/*
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_action_muxer_insert (NULL, NULL, NULL);
g_action_muxer_remove (NULL, NULL);
muxer = g_action_muxer_new ();
g_action_muxer_insert (muxer, NULL, NULL);
g_action_muxer_remove (muxer, NULL);
EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), NULL));
EXPECT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), NULL));
EXPECT_FALSE (g_action_group_query_action (G_ACTION_GROUP (muxer), NULL, NULL, NULL, NULL, NULL, NULL));
g_action_group_activate_action (G_ACTION_GROUP (muxer), NULL, NULL);
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);
}