/* An indicator to show information that is in messaging applications that the user is using. Copyright 2012 Canonical Ltd. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include extern "C" { #include "gactionmuxer.h" } static gboolean strv_contains (gchar **str_array, const gchar *str) { gchar **it; for (it = str_array; *it; it++) { if (!g_strcmp0 (*it, str)) return TRUE; } return FALSE; } TEST(GActionMuxerTest, Sanity) { GActionMuxer *muxer; #if G_ENCODE_VERSION(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init (); #endif g_test_expect_message ("Ayatana-Indicator-Messages", G_LOG_LEVEL_CRITICAL, "*G_IS_ACTION_MUXER*"); g_action_muxer_insert (NULL, NULL, NULL); g_test_assert_expected_messages (); g_test_expect_message ("Ayatana-Indicator-Messages", G_LOG_LEVEL_CRITICAL, "*G_IS_ACTION_MUXER*"); g_action_muxer_remove (NULL, NULL); g_test_assert_expected_messages (); muxer = g_action_muxer_new (); g_action_muxer_insert (muxer, NULL, NULL); g_action_muxer_remove (muxer, NULL); g_test_expect_message ("Ayatana-Indicator-Messages", G_LOG_LEVEL_CRITICAL, "*NULL*"); EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), NULL)); g_test_assert_expected_messages (); g_test_expect_message ("Ayatana-Indicator-Messages", G_LOG_LEVEL_CRITICAL, "*NULL*"); EXPECT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), NULL)); g_test_assert_expected_messages (); g_test_expect_message ("Ayatana-Indicator-Messages", G_LOG_LEVEL_CRITICAL, "*NULL*"); EXPECT_FALSE (g_action_group_query_action (G_ACTION_GROUP (muxer), NULL, NULL, NULL, NULL, NULL, NULL)); g_test_assert_expected_messages (); g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*NULL*"); g_action_group_activate_action (G_ACTION_GROUP (muxer), NULL, NULL); g_test_assert_expected_messages (); g_object_unref (muxer); } TEST(GActionMuxerTest, Empty) { GActionMuxer *muxer; gchar **actions; #if G_ENCODE_VERSION(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init (); #endif muxer = g_action_muxer_new (); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_EQ (0, g_strv_length (actions)); g_strfreev (actions); g_object_unref (muxer); } TEST(GActionMuxerTest, AddAndRemove) { const GActionEntry entries1[] = { { "one" }, { "two" }, { "three" } }; const GActionEntry entries2[] = { { "gb" }, { "es" }, { "fr" } }; const GActionEntry entries3[] = { { "foo" }, { "bar" } }; GSimpleActionGroup *group1; GSimpleActionGroup *group2; GSimpleActionGroup *group3; GActionMuxer *muxer; gchar **actions; #if G_ENCODE_VERSION(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init (); #endif group1 = g_simple_action_group_new (); g_action_map_add_action_entries (G_ACTION_MAP (group1), entries1, G_N_ELEMENTS (entries1), NULL); group2 = g_simple_action_group_new (); g_action_map_add_action_entries (G_ACTION_MAP (group2), entries2, G_N_ELEMENTS (entries2), NULL); group3 = g_simple_action_group_new (); g_action_map_add_action_entries (G_ACTION_MAP (group3), entries3, G_N_ELEMENTS (entries3), NULL); muxer = g_action_muxer_new (); g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group1)); g_action_muxer_insert (muxer, "second", G_ACTION_GROUP (group2)); g_action_muxer_insert (muxer, NULL, G_ACTION_GROUP (group3)); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.one")); EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "one")); EXPECT_EQ (8, g_strv_length (actions)); EXPECT_TRUE (strv_contains (actions, "first.one")); EXPECT_TRUE (strv_contains (actions, "first.two")); EXPECT_TRUE (strv_contains (actions, "first.three")); EXPECT_TRUE (strv_contains (actions, "second.gb")); EXPECT_TRUE (strv_contains (actions, "second.es")); EXPECT_TRUE (strv_contains (actions, "second.fr")); EXPECT_TRUE (strv_contains (actions, "foo")); EXPECT_TRUE (strv_contains (actions, "bar")); g_strfreev (actions); g_action_muxer_remove (muxer, NULL); EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "foo")); EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.one")); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_EQ (6, g_strv_length (actions)); EXPECT_FALSE (strv_contains (actions, "foo")); EXPECT_TRUE (strv_contains (actions, "first.one")); g_strfreev (actions); g_action_muxer_remove (muxer, "first"); EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.two")); EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "second.es")); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_EQ (3, g_strv_length (actions)); EXPECT_FALSE (strv_contains (actions, "first.two")); EXPECT_TRUE (strv_contains (actions, "second.es")); g_strfreev (actions); g_action_muxer_insert (muxer, "second", G_ACTION_GROUP (group2)); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_EQ (3, g_strv_length (actions)); g_strfreev (actions); g_action_muxer_insert (muxer, NULL, G_ACTION_GROUP (group3)); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); EXPECT_EQ (5, g_strv_length (actions)); g_strfreev (actions); g_object_unref (muxer); g_object_unref (group1); g_object_unref (group2); g_object_unref (group3); } static gboolean g_variant_equal0 (gconstpointer one, gconstpointer two) { if (one == NULL) return two == NULL; else return g_variant_equal (one, two); } TEST(GActionMuxerTest, ActionAttributes) { GSimpleActionGroup *group; GSimpleAction *action; GActionMuxer *muxer; gboolean enabled[2]; const GVariantType *param_type[2]; const GVariantType *state_type[2]; GVariant *state_hint[2]; GVariant *state[2]; #if G_ENCODE_VERSION(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init (); #endif group = g_simple_action_group_new (); action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); g_action_map_add_action (G_ACTION_MAP(group), G_ACTION (action)); muxer = g_action_muxer_new (); g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); /* test two of the convenience functions */ EXPECT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); g_simple_action_set_enabled (action, FALSE); EXPECT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); EXPECT_STREQ ((gchar *) g_action_group_get_action_parameter_type (G_ACTION_GROUP (muxer), "first.one"), (gchar *) G_VARIANT_TYPE_STRING); /* query_action */ g_action_group_query_action (G_ACTION_GROUP (group), "one", &enabled[0], ¶m_type[0], &state_type[0], &state_hint[0], &state[0]); g_action_group_query_action (G_ACTION_GROUP (muxer), "first.one", &enabled[1], ¶m_type[1], &state_type[1], &state_hint[1], &state[1]); EXPECT_EQ (enabled[0], enabled[1]); EXPECT_STREQ ((gchar *) param_type[0], (gchar *) param_type[1]); EXPECT_STREQ ((gchar *) state_type[0], (gchar *) state_type[1]); EXPECT_TRUE (g_variant_equal0 ((gconstpointer) state_hint[0], (gconstpointer) state_hint[1])); EXPECT_TRUE (g_variant_equal0 ((gconstpointer) state[0], (gconstpointer) state[1])); g_object_unref (action); g_object_unref (group); g_object_unref (muxer); } typedef struct { gboolean signal_ran; const gchar *name; } TestSignalClosure; static void action_added (GActionGroup *group, gchar *action_name, gpointer user_data) { TestSignalClosure *c = (TestSignalClosure *)user_data; EXPECT_STREQ (c->name, action_name); c->signal_ran = TRUE; } static void action_enabled_changed (GActionGroup *group, gchar *action_name, gboolean enabled, gpointer user_data) { TestSignalClosure *c = (TestSignalClosure *)user_data; EXPECT_EQ (enabled, FALSE); c->signal_ran = TRUE; } static void action_state_changed (GActionGroup *group, gchar *action_name, GVariant *value, gpointer user_data) { TestSignalClosure *c = (TestSignalClosure *)user_data; EXPECT_STREQ (g_variant_get_string (value, NULL), "off"); c->signal_ran = TRUE; } static void action_removed (GActionGroup *group, gchar *action_name, gpointer user_data) { TestSignalClosure *c = (TestSignalClosure *)user_data; EXPECT_STREQ (c->name, action_name); c->signal_ran = TRUE; } TEST(GActionMuxerTest, Signals) { GSimpleActionGroup *group; GSimpleAction *action; GActionMuxer *muxer; TestSignalClosure closure; group = g_simple_action_group_new (); action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); g_action_map_add_action (G_ACTION_MAP(group), G_ACTION (action)); g_object_unref (action); muxer = g_action_muxer_new (); g_signal_connect (muxer, "action-added", G_CALLBACK (action_added), (gpointer) &closure); g_signal_connect (muxer, "action-enabled-changed", G_CALLBACK (action_enabled_changed), (gpointer) &closure); g_signal_connect (muxer, "action-state-changed", G_CALLBACK (action_state_changed), (gpointer) &closure); g_signal_connect (muxer, "action-removed", G_CALLBACK (action_removed), (gpointer) &closure); /* add the group with "one" action and check whether the signal is emitted */ closure.signal_ran = FALSE; closure.name = "first.one"; g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); EXPECT_TRUE (closure.signal_ran); /* add a second action after the group was added to the muxer */ closure.signal_ran = FALSE; closure.name = "first.two"; action = g_simple_action_new_stateful ("two", G_VARIANT_TYPE_STRING, g_variant_new_string ("on")); g_action_map_add_action (G_ACTION_MAP(group), G_ACTION (action)); EXPECT_TRUE (closure.signal_ran); /* disable the action */ closure.signal_ran = FALSE; g_simple_action_set_enabled (action, FALSE); EXPECT_TRUE (closure.signal_ran); /* change its state */ closure.signal_ran = FALSE; g_simple_action_set_state (action, g_variant_new_string ("off")); EXPECT_TRUE (closure.signal_ran); g_object_unref (action); /* remove the first action */ closure.signal_ran = FALSE; closure.name = "first.one"; g_action_map_remove_action (G_ACTION_MAP(group), "one"); EXPECT_TRUE (closure.signal_ran); /* remove the whole group, should be notified about "first.two" */ closure.signal_ran = FALSE; closure.name = "first.two"; g_action_muxer_remove (muxer, "first"); EXPECT_TRUE (closure.signal_ran); g_object_unref (group); g_object_unref (muxer); } static void action_activated (GSimpleAction *simple, GVariant *parameter, gpointer user_data) { gboolean *signal_ran = (gboolean *)user_data; EXPECT_STREQ (g_variant_get_string (parameter, NULL), "value"); *signal_ran = TRUE; } static void action_change_state (GSimpleAction *simple, GVariant *value, gpointer user_data) { gboolean *signal_ran = (gboolean *)user_data; EXPECT_STREQ (g_variant_get_string (value, NULL), "off"); *signal_ran = TRUE; } TEST(GActionMuxerTest, ActivateAction) { GSimpleActionGroup *group; GSimpleAction *action; GActionMuxer *muxer; gboolean signal_ran; group = g_simple_action_group_new (); action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); g_action_map_add_action (G_ACTION_MAP(group), G_ACTION (action)); g_signal_connect (action, "activate", G_CALLBACK (action_activated), (gpointer) &signal_ran); g_object_unref (action); action = g_simple_action_new_stateful ("two", NULL, g_variant_new_string ("on")); g_action_map_add_action (G_ACTION_MAP(group), G_ACTION (action)); g_signal_connect (action, "change-state", G_CALLBACK (action_change_state), (gpointer) &signal_ran); g_object_unref (action); muxer = g_action_muxer_new (); g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); signal_ran = FALSE; g_action_group_activate_action (G_ACTION_GROUP (muxer), "first.one", g_variant_new_string ("value")); EXPECT_TRUE (signal_ran); signal_ran = FALSE; g_action_group_change_action_state (G_ACTION_GROUP (muxer), "first.two", g_variant_new_string ("off")); EXPECT_TRUE (signal_ran); g_object_unref (group); g_object_unref (muxer); }