11 activate (GAction *action,
15 Activation *activation = user_data;
18 activation->params = g_variant_ref (parameter);
20 activation->params = NULL;
21 activation->did_run = TRUE;
27 Activation a = { 0, };
28 GSimpleAction *action;
30 GVariantType *parameter_type;
32 GVariantType *state_type;
35 action = g_simple_action_new ("foo", NULL);
36 g_assert (g_action_get_enabled (G_ACTION (action)));
37 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
38 g_assert (g_action_get_state_type (G_ACTION (action)) == NULL);
39 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
40 g_assert (g_action_get_state (G_ACTION (action)) == NULL);
43 "parameter-type", ¶meter_type,
45 "state-type", &state_type,
48 g_assert_cmpstr (name, ==, "foo");
49 g_assert (parameter_type == NULL);
51 g_assert (state_type == NULL);
52 g_assert (state == NULL);
55 g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
56 g_assert (!a.did_run);
57 g_action_activate (G_ACTION (action), NULL);
61 g_simple_action_set_enabled (action, FALSE);
62 g_action_activate (G_ACTION (action), NULL);
63 g_assert (!a.did_run);
65 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
67 g_action_activate (G_ACTION (action), g_variant_new_string ("xxx"));
70 g_test_trap_assert_failed ();
72 g_object_unref (action);
73 g_assert (!a.did_run);
75 action = g_simple_action_new ("foo", G_VARIANT_TYPE_STRING);
76 g_assert (g_action_get_enabled (G_ACTION (action)));
77 g_assert (g_variant_type_equal (g_action_get_parameter_type (G_ACTION (action)), G_VARIANT_TYPE_STRING));
78 g_assert (g_action_get_state_type (G_ACTION (action)) == NULL);
79 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
80 g_assert (g_action_get_state (G_ACTION (action)) == NULL);
82 g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
83 g_assert (!a.did_run);
84 g_action_activate (G_ACTION (action), g_variant_new_string ("Hello world"));
86 g_assert_cmpstr (g_variant_get_string (a.params, NULL), ==, "Hello world");
87 g_variant_unref (a.params);
90 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
92 g_action_activate (G_ACTION (action), NULL);
96 g_test_trap_assert_failed ();
98 g_object_unref (action);
99 g_assert (!a.did_run);
103 strv_has_string (gchar **haystack,
108 for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
110 if (g_strcmp0 (haystack[n], needle) == 0)
117 strv_strv_cmp (gchar **a, gchar **b)
121 for (n = 0; a[n] != NULL; n++)
123 if (!strv_has_string (b, a[n]))
127 for (n = 0; b[n] != NULL; n++)
129 if (!strv_has_string (a, b[n]))
137 strv_set_equal (gchar **strv, ...)
146 va_start (list, strv);
149 str = va_arg (list, const gchar *);
152 if (!strv_has_string (strv, str))
162 res = g_strv_length ((gchar**)strv) == count;
168 test_simple_group (void)
170 GSimpleActionGroup *group;
171 Activation a = { 0, };
172 GSimpleAction *simple;
177 simple = g_simple_action_new ("foo", NULL);
178 g_signal_connect (simple, "activate", G_CALLBACK (activate), &a);
179 g_assert (!a.did_run);
180 g_action_activate (G_ACTION (simple), NULL);
181 g_assert (a.did_run);
184 group = g_simple_action_group_new ();
185 g_simple_action_group_insert (group, G_ACTION (simple));
186 g_object_unref (simple);
188 g_assert (!a.did_run);
189 g_action_group_activate_action (G_ACTION_GROUP (group), "foo", NULL);
190 g_assert (a.did_run);
192 simple = g_simple_action_new_stateful ("bar", G_VARIANT_TYPE_STRING, g_variant_new_string ("hihi"));
193 g_simple_action_group_insert (group, G_ACTION (simple));
194 g_object_unref (simple);
196 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "foo"));
197 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "bar"));
198 g_assert (!g_action_group_has_action (G_ACTION_GROUP (group), "baz"));
199 actions = g_action_group_list_actions (G_ACTION_GROUP (group));
200 g_assert_cmpint (g_strv_length (actions), ==, 2);
201 g_assert (strv_set_equal (actions, "foo", "bar", NULL));
202 g_strfreev (actions);
203 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "foo"));
204 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
205 g_assert (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "foo") == NULL);
206 g_assert (g_variant_type_equal (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
207 g_assert (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "foo") == NULL);
208 g_assert (g_variant_type_equal (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
209 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "foo") == NULL);
210 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "bar") == NULL);
211 g_assert (g_action_group_get_action_state (G_ACTION_GROUP (group), "foo") == NULL);
212 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
213 g_assert (g_variant_type_equal (g_variant_get_type (state), G_VARIANT_TYPE_STRING));
214 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
215 g_variant_unref (state);
217 g_action_group_change_action_state (G_ACTION_GROUP (group), "bar", g_variant_new_string ("boo"));
218 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
219 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "boo");
220 g_variant_unref (state);
222 action = g_simple_action_group_lookup (group, "bar");
223 g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
224 g_assert (!g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
226 g_simple_action_group_remove (group, "bar");
227 action = g_simple_action_group_lookup (group, "foo");
228 g_assert_cmpstr (g_action_get_name (action), ==, "foo");
229 action = g_simple_action_group_lookup (group, "bar");
230 g_assert (action == NULL);
233 g_object_unref (group);
234 g_assert (!a.did_run);
240 GSimpleAction *action;
243 action = g_simple_action_new_stateful ("foo", NULL, g_variant_new_string ("hihi"));
244 g_assert (g_action_get_enabled (G_ACTION (action)));
245 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
246 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
247 g_assert (g_variant_type_equal (g_action_get_state_type (G_ACTION (action)),
248 G_VARIANT_TYPE_STRING));
249 state = g_action_get_state (G_ACTION (action));
250 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
251 g_variant_unref (state);
253 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
255 g_simple_action_set_state (action, g_variant_new_int32 (123));
258 g_test_trap_assert_failed ();
260 g_simple_action_set_state (action, g_variant_new_string ("hello"));
261 state = g_action_get_state (G_ACTION (action));
262 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hello");
263 g_variant_unref (state);
265 g_object_unref (action);
267 action = g_simple_action_new ("foo", NULL);
268 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
270 g_simple_action_set_state (action, g_variant_new_int32 (123));
273 g_test_trap_assert_failed ();
274 g_object_unref (action);
277 static gboolean foo_activated = FALSE;
278 static gboolean bar_activated = FALSE;
281 activate_foo (GSimpleAction *simple,
285 g_assert (user_data == GINT_TO_POINTER (123));
286 g_assert (parameter == NULL);
287 foo_activated = TRUE;
291 activate_bar (GSimpleAction *simple,
295 g_assert (user_data == GINT_TO_POINTER (123));
296 g_assert_cmpstr (g_variant_get_string (parameter, NULL), ==, "param");
297 bar_activated = TRUE;
301 change_volume_state (GSimpleAction *action,
307 requested = g_variant_get_int32 (value);
309 /* Volume only goes from 0 to 10 */
310 if (0 <= requested && requested <= 10)
311 g_simple_action_set_state (action, value);
317 const GActionEntry entries[] = {
318 { "foo", activate_foo },
319 { "bar", activate_bar, "s" },
320 { "toggle", NULL, NULL, "false" },
321 { "volume", NULL, NULL, "0", change_volume_state }
323 GSimpleActionGroup *actions;
326 actions = g_simple_action_group_new ();
327 g_simple_action_group_add_entries (actions, entries,
328 G_N_ELEMENTS (entries),
329 GINT_TO_POINTER (123));
331 g_assert (!foo_activated);
332 g_action_group_activate_action (G_ACTION_GROUP (actions), "foo", NULL);
333 g_assert (foo_activated);
334 foo_activated = FALSE;
336 g_assert (!bar_activated);
337 g_action_group_activate_action (G_ACTION_GROUP (actions), "bar",
338 g_variant_new_string ("param"));
339 g_assert (bar_activated);
340 g_assert (!foo_activated);
342 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
344 const GActionEntry bad_type = {
345 "bad-type", NULL, "ss"
348 g_simple_action_group_add_entries (actions, &bad_type, 1, NULL);
351 g_test_trap_assert_failed ();
353 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
355 const GActionEntry bad_state = {
356 "bad-state", NULL, NULL, "flse"
359 g_simple_action_group_add_entries (actions, &bad_state, 1, NULL);
362 g_test_trap_assert_failed ();
364 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
365 g_assert_cmpint (g_variant_get_int32 (state), ==, 0);
366 g_variant_unref (state);
369 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
370 g_variant_new_int32 (7));
371 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
372 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
373 g_variant_unref (state);
375 /* should not change */
376 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
377 g_variant_new_int32 (11));
378 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
379 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
380 g_variant_unref (state);
382 g_object_unref (actions);
386 GHashTable *activation_counts;
389 count_activation (const gchar *action)
393 if (activation_counts == NULL)
394 activation_counts = g_hash_table_new (g_str_hash, g_str_equal);
395 count = GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
397 g_hash_table_insert (activation_counts, (gpointer)action, GINT_TO_POINTER (count));
401 activation_count (const gchar *action)
403 if (activation_counts == NULL)
406 return GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
410 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
412 count_activation (g_action_get_name (G_ACTION (action)));
416 activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
418 GVariant *old_state, *new_state;
420 count_activation (g_action_get_name (G_ACTION (action)));
422 old_state = g_action_get_state (G_ACTION (action));
423 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
424 g_simple_action_set_state (action, new_state);
425 g_variant_unref (old_state);
429 activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
433 count_activation (g_action_get_name (G_ACTION (action)));
435 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
436 g_simple_action_set_state (action, new_state);
440 compare_action_groups (GActionGroup *a, GActionGroup *b)
447 gboolean aenabled, benabled;
448 const GVariantType *aparameter_type, *bparameter_type;
449 const GVariantType *astate_type, *bstate_type;
450 GVariant *astate_hint, *bstate_hint;
451 GVariant *astate, *bstate;
453 alist = g_action_group_list_actions (a);
454 blist = g_action_group_list_actions (b);
455 equal = strv_strv_cmp (alist, blist);
457 for (i = 0; equal && alist[i]; i++)
459 ares = g_action_group_query_action (a, alist[i], &aenabled, &aparameter_type, &astate_type, &astate_hint, &astate);
460 bres = g_action_group_query_action (b, alist[i], &benabled, &bparameter_type, &bstate_type, &bstate_hint, &bstate);
464 equal = equal && (aenabled == benabled);
465 equal = equal && ((!aparameter_type && !bparameter_type) || g_variant_type_equal (aparameter_type, bparameter_type));
466 equal = equal && ((!astate_type && !bstate_type) || g_variant_type_equal (astate_type, bstate_type));
467 equal = equal && ((!astate_hint && !bstate_hint) || g_variant_equal (astate_hint, bstate_hint));
468 equal = equal && ((!astate && !bstate) || g_variant_equal (astate, bstate));
471 g_variant_unref (astate_hint);
473 g_variant_unref (bstate_hint);
475 g_variant_unref (astate);
477 g_variant_unref (bstate);
490 stop_loop (gpointer data)
492 GMainLoop *loop = data;
494 g_main_loop_quit (loop);
496 return G_SOURCE_REMOVE;
499 GDBusActionGroup *proxy;
502 got_proxy (GObject *source,
506 GError *error = NULL;
508 proxy = g_dbus_action_group_new_finish (res, &error);
509 g_assert_no_error (error);
513 test_dbus_export (void)
515 GDBusConnection *bus;
516 GSimpleActionGroup *group;
517 GSimpleAction *action;
519 static GActionEntry entries[] = {
520 { "undo", activate_action, NULL, NULL, NULL },
521 { "redo", activate_action, NULL, NULL, NULL },
522 { "cut", activate_action, NULL, NULL, NULL },
523 { "copy", activate_action, NULL, NULL, NULL },
524 { "paste", activate_action, NULL, NULL, NULL },
525 { "bold", activate_toggle, NULL, "true", NULL },
526 { "lang", activate_radio, "s", "'latin'", NULL },
528 GError *error = NULL;
532 loop = g_main_loop_new (NULL, FALSE);
534 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
536 group = g_simple_action_group_new ();
537 g_simple_action_group_add_entries (group, entries, G_N_ELEMENTS (entries), NULL);
539 id = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &error);
540 g_assert_no_error (error);
542 g_dbus_action_group_new (bus, g_dbus_connection_get_unique_name (bus), "/", 0, NULL, got_proxy, NULL);
543 g_assert_no_error (error);
545 g_timeout_add (100, stop_loop, loop);
546 g_main_loop_run (loop);
548 /* test that the initial transfer works */
549 g_assert (G_IS_DBUS_ACTION_GROUP (proxy));
550 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
552 /* test that various changes get propagated from group to proxy */
553 action = g_simple_action_new_stateful ("italic", NULL, g_variant_new_boolean (FALSE));
554 g_simple_action_group_insert (group, G_ACTION (action));
555 g_object_unref (action);
557 g_timeout_add (100, stop_loop, loop);
558 g_main_loop_run (loop);
560 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
562 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "cut"));
563 g_simple_action_set_enabled (action, FALSE);
565 g_timeout_add (100, stop_loop, loop);
566 g_main_loop_run (loop);
568 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
570 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "bold"));
571 g_simple_action_set_state (action, g_variant_new_boolean (FALSE));
573 g_timeout_add (100, stop_loop, loop);
574 g_main_loop_run (loop);
576 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
578 g_simple_action_group_remove (group, "italic");
580 g_timeout_add (100, stop_loop, loop);
581 g_main_loop_run (loop);
583 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
585 /* test that activations and state changes propagate the other way */
587 g_assert_cmpint (activation_count ("copy"), ==, 0);
588 g_action_group_activate_action (G_ACTION_GROUP (proxy), "copy", NULL);
590 g_timeout_add (100, stop_loop, loop);
591 g_main_loop_run (loop);
593 g_assert_cmpint (activation_count ("copy"), ==, 1);
594 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
596 g_assert_cmpint (activation_count ("bold"), ==, 0);
597 g_action_group_activate_action (G_ACTION_GROUP (proxy), "bold", NULL);
599 g_timeout_add (100, stop_loop, loop);
600 g_main_loop_run (loop);
602 g_assert_cmpint (activation_count ("bold"), ==, 1);
603 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
604 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
605 g_assert (g_variant_get_boolean (v));
608 g_action_group_change_action_state (G_ACTION_GROUP (proxy), "bold", g_variant_new_boolean (FALSE));
610 g_timeout_add (100, stop_loop, loop);
611 g_main_loop_run (loop);
613 g_assert_cmpint (activation_count ("bold"), ==, 1);
614 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
615 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
616 g_assert (!g_variant_get_boolean (v));
619 g_dbus_connection_unexport_action_group (bus, id);
621 g_object_unref (proxy);
622 g_object_unref (group);
623 g_main_loop_unref (loop);
624 g_object_unref (bus);
628 main (int argc, char **argv)
631 g_test_init (&argc, &argv, NULL);
633 g_test_add_func ("/actions/basic", test_basic);
634 g_test_add_func ("/actions/simplegroup", test_simple_group);
635 g_test_add_func ("/actions/stateful", test_stateful);
636 g_test_add_func ("/actions/entries", test_entries);
637 g_test_add_func ("/actions/dbus/export", test_dbus_export);
639 return g_test_run ();