wifi: Add support for autoscan request
[framework/connectivity/connman.git] / unit / test-session.c
index 388073f..38ed2bf 100644 (file)
 
 #include "test-connman.h"
 
-static connman_bool_t is_connman_running(DBusConnection *connection)
+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)
 {
-       DBusError error;
-       connman_bool_t running;
-
-       dbus_error_init(&error);
-
-       running = dbus_bus_name_has_owner(connection, CONNMAN_SERVICE, &error);
-
-       if (dbus_error_is_set(&error) == TRUE) {
-               fprintf(stderr, "%s\n", error.message);
-               dbus_error_free(&error);
+       return GPOINTER_TO_UINT(session->fix->user_data);
+}
 
-               return FALSE;
-       }
+static void set_session_state(struct test_session *session,
+                               enum test_session_state state)
+{
+       session->fix->user_data = GUINT_TO_POINTER(state);
+}
 
-       return running;
+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)
@@ -62,7 +67,6 @@ static gboolean test_session_create_no_notify(gpointer data)
 
        dbus_message_unref(msg);
 
-       g_assert(is_connman_running(fix->session->connection) == TRUE);
        util_idle_call(fix, util_quit_loop, util_session_destroy);
 
        return FALSE;
@@ -78,7 +82,6 @@ static gboolean test_session_destroy_no_notify(gpointer data)
        msg = manager_destroy_session(fix->session->connection, "/foo");
        g_assert(msg == NULL);
 
-       g_assert(is_connman_running(fix->session->connection) == TRUE);
        util_idle_call(fix, util_quit_loop, util_session_destroy);
 
        return FALSE;
@@ -88,7 +91,6 @@ static void test_session_create_notify(struct test_session *session)
 {
        LOG("session %p", session);
 
-       g_assert(is_connman_running(session->connection) == TRUE);
        util_idle_call(session->fix, util_quit_loop, util_session_destroy);
 }
 
@@ -132,7 +134,6 @@ static gboolean test_session_create_destroy(gpointer data)
        util_session_init(fix->session);
        util_session_cleanup(fix->session);
 
-       g_assert(is_connman_running(session->connection) == TRUE);
        util_idle_call(fix, util_quit_loop, util_session_destroy);
 
        return FALSE;
@@ -160,7 +161,6 @@ static gboolean test_session_create_already_exists(gpointer data)
 
        util_session_cleanup(session0);
 
-       g_assert(is_connman_running(session0->connection) == TRUE);
        util_idle_call(fix, util_quit_loop, util_session_destroy);
 
        return FALSE;
@@ -172,8 +172,6 @@ static void test_session_create_many_notify(struct test_session *session)
 
        LOG("session %p", session);
 
-       g_assert(is_connman_running(session->connection) == TRUE);
-
        nr = GPOINTER_TO_UINT(session->fix->user_data);
        nr--;
        session->fix->user_data = GUINT_TO_POINTER(nr);
@@ -218,20 +216,17 @@ static void set_session_mode(struct test_fix *fix,
        g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
 
        dbus_message_unref(msg);
-
-       util_idle_call(fix, util_quit_loop, NULL);
 }
 
 static void test_session_connect_notify(struct test_session *session)
 {
-       LOG("session %p online %d", session, session->info->online);
+       LOG("session %p state %d", session, session->info->state);
 
-       if (session->info->online != TRUE)
+       if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
                return;
 
        util_session_cleanup(session);
 
-       g_assert(is_connman_running(session->connection) == TRUE);
        util_idle_call(session->fix, util_quit_loop, util_session_destroy);
 }
 
@@ -257,12 +252,278 @@ static gboolean test_session_connect(gpointer data)
        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;
 }
 
@@ -277,15 +538,21 @@ static gboolean disable_session_mode(gpointer data)
 
 static void setup_cb(struct test_fix *fix, gconstpointer data)
 {
-       util_setup(fix, 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);
@@ -310,6 +577,12 @@ int main(int argc, char *argv[])
 
        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();
 }