dhcp: warn on invalid netmask
[framework/connectivity/connman.git] / unit / test-session.c
index aaed275..38ed2bf 100644 (file)
 #include <config.h>
 #endif
 
+#include <stdio.h>
+
 #include "gdbus/gdbus.h"
 
 #include "test-connman.h"
 
-static gboolean test_empty(gpointer data)
+enum test_session_state {
+       TEST_SESSION_STATE_0 = 0,
+       TEST_SESSION_STATE_1 = 1,
+       TEST_SESSION_STATE_2 = 2,
+       TEST_SESSION_STATE_3 = 3,
+};
+
+static enum test_session_state get_session_state(struct test_session *session)
+{
+       return GPOINTER_TO_UINT(session->fix->user_data);
+}
+
+static void set_session_state(struct test_session *session,
+                               enum test_session_state state)
+{
+       session->fix->user_data = GUINT_TO_POINTER(state);
+}
+
+static struct test_session *get_session(struct test_session *session,
+                                       unsigned int index)
+{
+       return &session->fix->session[index];
+}
+
+static gboolean test_session_create_no_notify(gpointer data)
 {
        struct test_fix *fix = data;
+       DBusMessage *msg;
 
-       util_idle_call(fix, util_quit_loop, NULL);
+       util_session_create(fix, 1);
+
+       msg = manager_create_session(fix->session->connection,
+                                       fix->session->info, "/foo");
+       g_assert(msg != NULL);
+       g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
+
+       dbus_message_unref(msg);
+
+       util_idle_call(fix, util_quit_loop, util_session_destroy);
+
+       return FALSE;
+}
+
+static gboolean test_session_destroy_no_notify(gpointer data)
+{
+       struct test_fix *fix = data;
+       DBusMessage *msg;
+
+       util_session_create(fix, 1);
+
+       msg = manager_destroy_session(fix->session->connection, "/foo");
+       g_assert(msg == NULL);
+
+       util_idle_call(fix, util_quit_loop, util_session_destroy);
+
+       return FALSE;
+}
+
+static void test_session_create_notify(struct test_session *session)
+{
+       LOG("session %p", session);
+
+       util_idle_call(session->fix, util_quit_loop, util_session_destroy);
+}
+
+static gboolean test_session_create(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+       DBusMessage *msg;
+       int err;
+
+       util_session_create(fix, 1);
+       session = fix->session;
+
+       session->notify_path = "/foo";
+       session->notify = test_session_create_notify;
+
+       err = session_notify_register(session, session->notify_path);
+       g_assert(err == 0);
+
+       msg = manager_create_session(session->connection,
+                                       session->info,
+                                       session->notify_path);
+       g_assert(msg != NULL);
+       g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
+
+       dbus_message_unref(msg);
+
+       return FALSE;
+}
+
+static gboolean test_session_create_destroy(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+
+       util_session_create(fix, 1);
+       session = fix->session;
+
+       session->notify_path = g_strdup("/foo");
+
+       util_session_init(fix->session);
+       util_session_cleanup(fix->session);
+
+       util_idle_call(fix, util_quit_loop, util_session_destroy);
+
+       return FALSE;
+}
+
+static gboolean test_session_create_already_exists(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session0, *session1;
+       DBusMessage *msg;
+
+       util_session_create(fix, 2);
+       session0 = &fix->session[0];
+       session1 = &fix->session[1];
+
+       session0->notify_path = g_strdup("/foo");
+       session1->notify_path = session0->notify_path;
+
+       util_session_init(session0);
+
+       msg = manager_create_session(session1->connection,
+                                       session1->info,
+                                       session1->notify_path);
+       g_assert(msg == NULL);
+
+       util_session_cleanup(session0);
+
+       util_idle_call(fix, util_quit_loop, util_session_destroy);
+
+       return FALSE;
+}
+
+static void test_session_create_many_notify(struct test_session *session)
+{
+       unsigned int nr;
+
+       LOG("session %p", session);
+
+       nr = GPOINTER_TO_UINT(session->fix->user_data);
+       nr--;
+       session->fix->user_data = GUINT_TO_POINTER(nr);
+
+       if (nr > 0)
+               return;
+
+       util_idle_call(session->fix, util_quit_loop, util_session_destroy);
+}
+
+static gboolean test_session_create_many(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+       unsigned int i, max;
+
+       max = 100;
+
+       fix->user_data = GUINT_TO_POINTER(max);
+
+       util_session_create(fix, max);
+
+       for (i = 0; i < max; i++) {
+               session = &fix->session[i];
+
+               session->notify_path = g_strdup_printf("/foo/%d", i);
+               session->notify = test_session_create_many_notify;
+
+               util_session_init(session);
+       }
+
+       return FALSE;
+}
+
+static void set_session_mode(struct test_fix *fix,
+                                       connman_bool_t enable)
+{
+       DBusMessage *msg;
+
+       msg = manager_set_session_mode(fix->main_connection, enable);
+       g_assert(msg != NULL);
+       g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
+
+       dbus_message_unref(msg);
+}
+
+static void test_session_connect_notify(struct test_session *session)
+{
+       LOG("session %p state %d", session, session->info->state);
+
+       if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
+               return;
+
+       util_session_cleanup(session);
+
+       util_idle_call(session->fix, util_quit_loop, util_session_destroy);
+}
+
+static gboolean test_session_connect(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+       DBusMessage *msg;
+
+       util_session_create(fix, 1);
+       session = fix->session;
+
+       session->notify_path = g_strdup("/foo");
+       session->notify =  test_session_connect_notify;
+       util_session_init(session);
+
+       msg = session_connect(session->connection, session);
+       g_assert(msg != NULL);
+       g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
+
+       dbus_message_unref(msg);
+
+       return FALSE;
+}
+
+static void test_session_disconnect_notify(struct test_session *session)
+{
+       LOG("session %p state %d", session, session->info->state);
+
+       if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
+               return;
+
+       util_session_cleanup(session);
+
+       util_idle_call(session->fix, util_quit_loop, util_session_destroy);
+}
+
+static gboolean test_session_disconnect(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+       DBusMessage *msg;
+
+       util_session_create(fix, 1);
+       session = fix->session;
+
+       session->notify_path = g_strdup("/foo");
+       session->notify =  test_session_disconnect_notify;
+       util_session_init(session);
+
+       msg = session_disconnect(session->connection, session);
+       g_assert(msg != NULL);
+       dbus_message_unref(msg);
+
+       return FALSE;
+}
+
+static void test_session_connect_disconnect_notify(struct test_session *session)
+{
+       enum test_session_state state = get_session_state(session);
+       enum test_session_state next_state = state;
+       DBusMessage *msg;
+
+       LOG("state %d session %p %s state %d", state, session,
+               session->notify_path, session->info->state);
+
+       switch (state) {
+       case TEST_SESSION_STATE_0:
+               if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
+                       next_state = TEST_SESSION_STATE_1;
+               break;
+       case TEST_SESSION_STATE_1:
+               if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
+                       next_state = TEST_SESSION_STATE_2;
+               break;
+       case TEST_SESSION_STATE_2:
+               if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
+                       next_state = TEST_SESSION_STATE_3;
+       default:
+               break;
+       }
+
+       if (state == next_state)
+               return;
+
+       set_session_state(session, next_state);
+
+       LOG("next_state %d", next_state);
+
+       switch (next_state) {
+       case TEST_SESSION_STATE_1:
+               msg = session_connect(session->connection, session);
+               g_assert(msg != NULL);
+               dbus_message_unref(msg);
+               return;
+       case TEST_SESSION_STATE_2:
+               msg = session_disconnect(session->connection, session);
+               g_assert(msg != NULL);
+               dbus_message_unref(msg);
+               return;
+       case TEST_SESSION_STATE_3:
+               util_session_cleanup(session);
+               util_idle_call(session->fix, util_quit_loop,
+                               util_session_destroy);
+               return;
+       default:
+               return;
+       }
+}
+
+static gboolean test_session_connect_disconnect(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session;
+
+       /*
+        * +-------------------+
+        * |       START       |
+        * +-------------------+
+        *   |
+        *   | connect foo
+        *   v
+        * +-------------------+
+        * |   FOO-CONNECTED   |
+        * +-------------------+
+        *  |
+        *  | disconnect foo
+        *  v
+        * +-------------------+
+        * |        END        |
+        * +-------------------+
+        */
+
+       util_session_create(fix, 1);
+       session = fix->session;
+
+       session->notify_path = g_strdup("/foo");
+       session->notify =  test_session_connect_disconnect_notify;
+
+       util_session_init(session);
+
+       set_session_state(session, TEST_SESSION_STATE_0);
+
+       return FALSE;
+}
+
+static void test_session_connect_free_ride_notify(struct test_session *session)
+{
+       struct test_session *session0 = get_session(session, 0);
+       struct test_session *session1 = get_session(session, 1);
+       enum test_session_state state = get_session_state(session);
+       enum test_session_state next_state = state;
+       DBusMessage *msg;
+
+       LOG("state %d session %p %s state %d", state, session,
+               session->notify_path, session->info->state);
+
+       switch (state) {
+       case TEST_SESSION_STATE_0:
+               if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
+                               && session1->info->state ==
+                                       CONNMAN_SESSION_STATE_DISCONNECTED) {
+                       next_state = TEST_SESSION_STATE_1;
+               }
+
+               break;
+       case TEST_SESSION_STATE_1:
+               if (session0->info->state >= CONNMAN_SESSION_STATE_CONNECTED &&
+                               session1->info->state >=
+                                       CONNMAN_SESSION_STATE_CONNECTED) {
+                       next_state = TEST_SESSION_STATE_2;
+               }
+
+               break;
+       case TEST_SESSION_STATE_2:
+               if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
+                               && session1->info->state ==
+                                       CONNMAN_SESSION_STATE_DISCONNECTED) {
+                       next_state = TEST_SESSION_STATE_3;
+               }
+
+               break;
+       case TEST_SESSION_STATE_3:
+
+               return;
+       }
+
+       if (state == next_state)
+               return;
+
+       set_session_state(session, next_state);
+
+       LOG("next_state %d", next_state);
+
+       switch (next_state) {
+       case TEST_SESSION_STATE_0:
+
+               return;
+       case TEST_SESSION_STATE_1:
+               msg = session_connect(session0->connection, session0);
+               g_assert(msg != NULL);
+               dbus_message_unref(msg);
+
+               return;
+
+       case TEST_SESSION_STATE_2:
+               msg = session_disconnect(session0->connection, session0);
+               g_assert(msg != NULL);
+               dbus_message_unref(msg);
+
+               return;
+       case TEST_SESSION_STATE_3:
+               util_session_cleanup(session0);
+               util_session_cleanup(session1);
+
+               util_idle_call(session0->fix, util_quit_loop,
+                               util_session_destroy);
+
+               return;
+       }
+}
+
+static gboolean test_session_connect_free_ride(gpointer data)
+{
+       struct test_fix *fix = data;
+       struct test_session *session0, *session1;
+
+       /*
+        * +-------------------+
+        * |       START       |
+        * +-------------------+
+        *   |
+        *   | connect foo
+        *   v
+        * +-------------------+
+        * |   FOO-CONNECTED   |
+        * +-------------------+
+        *   |
+        *   | free-ride bar
+        *   v
+        * +-------------------+
+        * | FOO-BAR-CONNECTED |
+        * +-------------------+
+        *  |
+        *  | disconnect foo
+        *  v
+        * +-------------------+
+        * |        END        |
+        * +-------------------+
+        */
+
+       util_session_create(fix, 2);
+       session0 = &fix->session[0];
+       session1 = &fix->session[1];
+
+       session0->notify_path = g_strdup("/foo");
+       session1->notify_path = g_strdup("/bar");
+       session0->notify = test_session_connect_free_ride_notify;
+       session1->notify = test_session_connect_free_ride_notify;
+
+       util_session_init(session0);
+       util_session_init(session1);
+
+       set_session_state(session0, TEST_SESSION_STATE_0);
+
+       return FALSE;
+}
+
+static connman_bool_t is_online(struct test_fix *fix)
+{
+       if (g_strcmp0(fix->manager.state, "online") == 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static gboolean enable_session_mode(gpointer data)
+{
+       struct test_fix *fix = data;
+
+       set_session_mode(fix, TRUE);
+
+       if (is_online(fix) == FALSE)
+               util_idle_call(fix, util_quit_loop, NULL);
+
+       return FALSE;
+}
+
+static gboolean manager_state_changed(gpointer data)
+{
+       struct test_fix *fix = data;
+
+       if (is_online(fix) == FALSE) {
+               fix->manager_changed = NULL;
+               util_idle_call(fix, util_quit_loop, NULL);
+       }
+
+       return FALSE;
+}
+
+static gboolean disable_session_mode(gpointer data)
+{
+       struct test_fix *fix = data;
+
+       set_session_mode(fix, FALSE);
 
        return FALSE;
 }
 
 static void setup_cb(struct test_fix *fix, gconstpointer data)
 {
+       fix->manager_changed = manager_state_changed;
+
        util_setup(fix, data);
+       util_call(fix, enable_session_mode, NULL);
+
+       g_main_loop_run(fix->main_loop);
+
+       fix->manager_changed = NULL;
 }
 
 static void teardown_cb(struct test_fix *fix, gconstpointer data)
 {
+       util_call(fix, disable_session_mode, NULL);
+       util_idle_call(fix, util_quit_loop, NULL);
+
+       g_main_loop_run(fix->main_loop);
+
        util_teardown(fix, data);
 }
 
@@ -50,8 +562,27 @@ int main(int argc, char *argv[])
 {
        g_test_init(&argc, &argv, NULL);
 
-       util_test_add("/empty",
-               test_empty, setup_cb, teardown_cb);
+       util_test_add("/manager/session create no notify",
+               test_session_create_no_notify, setup_cb, teardown_cb);
+       util_test_add("/manager/session destroy no notify",
+               test_session_destroy_no_notify, setup_cb, teardown_cb);
+       util_test_add("/manager/session create",
+               test_session_create, setup_cb, teardown_cb);
+       util_test_add("/manager/session create destroy",
+               test_session_create_destroy, setup_cb, teardown_cb);
+       util_test_add("/manager/session create already exists",
+               test_session_create_already_exists, setup_cb, teardown_cb);
+       util_test_add("/manager/session create many",
+               test_session_create_many, setup_cb, teardown_cb);
+
+       util_test_add("/session/connect",
+               test_session_connect, setup_cb, teardown_cb);
+       util_test_add("/session/disconnect",
+               test_session_disconnect, setup_cb, teardown_cb);
+       util_test_add("/session/connect disconnect",
+               test_session_connect_disconnect, setup_cb, teardown_cb);
+       util_test_add("/session/connect free-ride",
+               test_session_connect_free_ride, setup_cb, teardown_cb);
 
        return g_test_run();
 }