5 #include "gdbus-sessionbus.h"
14 activate (GAction *action,
18 Activation *activation = user_data;
21 activation->params = g_variant_ref (parameter);
23 activation->params = NULL;
24 activation->did_run = TRUE;
30 Activation a = { 0, };
31 GSimpleAction *action;
33 GVariantType *parameter_type;
35 GVariantType *state_type;
38 action = g_simple_action_new ("foo", NULL);
39 g_assert (g_action_get_enabled (G_ACTION (action)));
40 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
41 g_assert (g_action_get_state_type (G_ACTION (action)) == NULL);
42 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
43 g_assert (g_action_get_state (G_ACTION (action)) == NULL);
46 "parameter-type", ¶meter_type,
48 "state-type", &state_type,
51 g_assert_cmpstr (name, ==, "foo");
52 g_assert (parameter_type == NULL);
54 g_assert (state_type == NULL);
55 g_assert (state == NULL);
58 g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
59 g_assert (!a.did_run);
60 g_action_activate (G_ACTION (action), NULL);
64 g_simple_action_set_enabled (action, FALSE);
65 g_action_activate (G_ACTION (action), NULL);
66 g_assert (!a.did_run);
68 if (g_test_undefined ())
70 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
71 "*assertion*g_variant_is_of_type*failed*");
72 g_action_activate (G_ACTION (action), g_variant_new_string ("xxx"));
73 g_test_assert_expected_messages ();
76 g_object_unref (action);
77 g_assert (!a.did_run);
79 action = g_simple_action_new ("foo", G_VARIANT_TYPE_STRING);
80 g_assert (g_action_get_enabled (G_ACTION (action)));
81 g_assert (g_variant_type_equal (g_action_get_parameter_type (G_ACTION (action)), G_VARIANT_TYPE_STRING));
82 g_assert (g_action_get_state_type (G_ACTION (action)) == NULL);
83 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
84 g_assert (g_action_get_state (G_ACTION (action)) == NULL);
86 g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
87 g_assert (!a.did_run);
88 g_action_activate (G_ACTION (action), g_variant_new_string ("Hello world"));
90 g_assert_cmpstr (g_variant_get_string (a.params, NULL), ==, "Hello world");
91 g_variant_unref (a.params);
94 if (g_test_undefined ())
96 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
97 "*assertion*!= NULL*failed*");
98 g_action_activate (G_ACTION (action), NULL);
99 g_test_assert_expected_messages ();
102 g_object_unref (action);
103 g_assert (!a.did_run);
109 g_assert (!g_action_name_is_valid (""));
110 g_assert (!g_action_name_is_valid ("("));
111 g_assert (!g_action_name_is_valid ("%abc"));
112 g_assert (!g_action_name_is_valid ("$x1"));
113 g_assert (g_action_name_is_valid ("abc.def"));
114 g_assert (g_action_name_is_valid ("ABC-DEF"));
118 strv_has_string (gchar **haystack,
123 for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
125 if (g_strcmp0 (haystack[n], needle) == 0)
132 strv_strv_cmp (gchar **a, gchar **b)
136 for (n = 0; a[n] != NULL; n++)
138 if (!strv_has_string (b, a[n]))
142 for (n = 0; b[n] != NULL; n++)
144 if (!strv_has_string (a, b[n]))
152 strv_set_equal (gchar **strv, ...)
161 va_start (list, strv);
164 str = va_arg (list, const gchar *);
167 if (!strv_has_string (strv, str))
177 res = g_strv_length ((gchar**)strv) == count;
182 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
185 test_simple_group (void)
187 GSimpleActionGroup *group;
188 Activation a = { 0, };
189 GSimpleAction *simple;
194 simple = g_simple_action_new ("foo", NULL);
195 g_signal_connect (simple, "activate", G_CALLBACK (activate), &a);
196 g_assert (!a.did_run);
197 g_action_activate (G_ACTION (simple), NULL);
198 g_assert (a.did_run);
201 group = g_simple_action_group_new ();
202 g_simple_action_group_insert (group, G_ACTION (simple));
203 g_object_unref (simple);
205 g_assert (!a.did_run);
206 g_action_group_activate_action (G_ACTION_GROUP (group), "foo", NULL);
207 g_assert (a.did_run);
209 simple = g_simple_action_new_stateful ("bar", G_VARIANT_TYPE_STRING, g_variant_new_string ("hihi"));
210 g_simple_action_group_insert (group, G_ACTION (simple));
211 g_object_unref (simple);
213 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "foo"));
214 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "bar"));
215 g_assert (!g_action_group_has_action (G_ACTION_GROUP (group), "baz"));
216 actions = g_action_group_list_actions (G_ACTION_GROUP (group));
217 g_assert_cmpint (g_strv_length (actions), ==, 2);
218 g_assert (strv_set_equal (actions, "foo", "bar", NULL));
219 g_strfreev (actions);
220 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "foo"));
221 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
222 g_assert (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "foo") == NULL);
223 g_assert (g_variant_type_equal (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
224 g_assert (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "foo") == NULL);
225 g_assert (g_variant_type_equal (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
226 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "foo") == NULL);
227 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "bar") == NULL);
228 g_assert (g_action_group_get_action_state (G_ACTION_GROUP (group), "foo") == NULL);
229 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
230 g_assert (g_variant_type_equal (g_variant_get_type (state), G_VARIANT_TYPE_STRING));
231 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
232 g_variant_unref (state);
234 g_action_group_change_action_state (G_ACTION_GROUP (group), "bar", g_variant_new_string ("boo"));
235 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
236 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "boo");
237 g_variant_unref (state);
239 action = g_simple_action_group_lookup (group, "bar");
240 g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
241 g_assert (!g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
243 g_simple_action_group_remove (group, "bar");
244 action = g_simple_action_group_lookup (group, "foo");
245 g_assert_cmpstr (g_action_get_name (action), ==, "foo");
246 action = g_simple_action_group_lookup (group, "bar");
247 g_assert (action == NULL);
249 simple = g_simple_action_new ("foo", NULL);
250 g_simple_action_group_insert (group, G_ACTION (simple));
251 g_object_unref (simple);
254 g_object_unref (group);
255 g_assert (!a.did_run);
258 G_GNUC_END_IGNORE_DEPRECATIONS
263 GSimpleAction *action;
266 action = g_simple_action_new_stateful ("foo", NULL, g_variant_new_string ("hihi"));
267 g_assert (g_action_get_enabled (G_ACTION (action)));
268 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
269 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
270 g_assert (g_variant_type_equal (g_action_get_state_type (G_ACTION (action)),
271 G_VARIANT_TYPE_STRING));
272 state = g_action_get_state (G_ACTION (action));
273 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
274 g_variant_unref (state);
276 if (g_test_undefined ())
278 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
279 "*assertion*g_variant_is_of_type*failed*");
280 g_simple_action_set_state (action, g_variant_new_int32 (123));
281 g_test_assert_expected_messages ();
284 g_simple_action_set_state (action, g_variant_new_string ("hello"));
285 state = g_action_get_state (G_ACTION (action));
286 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hello");
287 g_variant_unref (state);
289 g_object_unref (action);
291 action = g_simple_action_new ("foo", NULL);
293 if (g_test_undefined ())
295 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
296 "*assertion*!= NULL*failed*");
297 g_simple_action_set_state (action, g_variant_new_int32 (123));
298 g_test_assert_expected_messages ();
301 g_object_unref (action);
304 static gboolean foo_activated = FALSE;
305 static gboolean bar_activated = FALSE;
308 activate_foo (GSimpleAction *simple,
312 g_assert (user_data == GINT_TO_POINTER (123));
313 g_assert (parameter == NULL);
314 foo_activated = TRUE;
318 activate_bar (GSimpleAction *simple,
322 g_assert (user_data == GINT_TO_POINTER (123));
323 g_assert_cmpstr (g_variant_get_string (parameter, NULL), ==, "param");
324 bar_activated = TRUE;
328 change_volume_state (GSimpleAction *action,
334 requested = g_variant_get_int32 (value);
336 /* Volume only goes from 0 to 10 */
337 if (0 <= requested && requested <= 10)
338 g_simple_action_set_state (action, value);
341 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
346 const GActionEntry entries[] = {
347 { "foo", activate_foo },
348 { "bar", activate_bar, "s" },
349 { "toggle", NULL, NULL, "false" },
350 { "volume", NULL, NULL, "0", change_volume_state }
352 GSimpleActionGroup *actions;
355 actions = g_simple_action_group_new ();
356 g_simple_action_group_add_entries (actions, entries,
357 G_N_ELEMENTS (entries),
358 GINT_TO_POINTER (123));
360 g_assert (!foo_activated);
361 g_action_group_activate_action (G_ACTION_GROUP (actions), "foo", NULL);
362 g_assert (foo_activated);
363 foo_activated = FALSE;
365 g_assert (!bar_activated);
366 g_action_group_activate_action (G_ACTION_GROUP (actions), "bar",
367 g_variant_new_string ("param"));
368 g_assert (bar_activated);
369 g_assert (!foo_activated);
371 if (g_test_undefined ())
373 const GActionEntry bad_type = {
374 "bad-type", NULL, "ss"
376 const GActionEntry bad_state = {
377 "bad-state", NULL, NULL, "flse"
380 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
381 "*not a valid GVariant type string*");
382 g_simple_action_group_add_entries (actions, &bad_type, 1, NULL);
383 g_test_assert_expected_messages ();
385 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
386 "*could not parse*");
387 g_simple_action_group_add_entries (actions, &bad_state, 1, NULL);
388 g_test_assert_expected_messages ();
391 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
392 g_assert_cmpint (g_variant_get_int32 (state), ==, 0);
393 g_variant_unref (state);
396 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
397 g_variant_new_int32 (7));
398 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
399 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
400 g_variant_unref (state);
402 /* should not change */
403 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
404 g_variant_new_int32 (11));
405 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
406 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
407 g_variant_unref (state);
409 g_object_unref (actions);
412 G_GNUC_END_IGNORE_DEPRECATIONS
415 test_parse_detailed (void)
418 const gchar *detailed;
419 const gchar *expected_name;
420 const gchar *expected_target;
421 const gchar *expected_error;
422 const gchar *detailed_roundtrip;
424 { "abc", "abc", NULL, NULL, "abc" },
425 { " abc", NULL, NULL, "invalid format", NULL },
426 { " abc", NULL, NULL, "invalid format", NULL },
427 { "abc:", NULL, NULL, "invalid format", NULL },
428 { ":abc", NULL, NULL, "invalid format", NULL },
429 { "abc(", NULL, NULL, "invalid format", NULL },
430 { "abc)", NULL, NULL, "invalid format", NULL },
431 { "(abc", NULL, NULL, "invalid format", NULL },
432 { ")abc", NULL, NULL, "invalid format", NULL },
433 { "abc::xyz", "abc", "'xyz'", NULL, "abc::xyz" },
434 { "abc('xyz')", "abc", "'xyz'", NULL, "abc::xyz" },
435 { "abc(42)", "abc", "42", NULL, "abc(42)" },
436 { "abc(int32 42)", "abc", "42", NULL, "abc(42)" },
437 { "abc(@i 42)", "abc", "42", NULL, "abc(42)" },
438 { "abc (42)", NULL, NULL, "invalid format", NULL },
439 { "abc(42abc)", NULL, NULL, "invalid character in number", NULL },
440 { "abc(42, 4)", "abc", "(42, 4)", "expected end of input", NULL },
441 { "abc(42,)", "abc", "(42,)", "expected end of input", NULL }
445 for (i = 0; i < G_N_ELEMENTS (testcases); i++)
447 GError *error = NULL;
452 success = g_action_parse_detailed_name (testcases[i].detailed, &name, &target, &error);
453 g_assert (success == (error == NULL));
454 if (success && testcases[i].expected_error)
455 g_error ("Unexpected success on '%s'. Expected error containing '%s'",
456 testcases[i].detailed, testcases[i].expected_error);
458 if (!success && !testcases[i].expected_error)
459 g_error ("Unexpected failure on '%s': %s", testcases[i].detailed, error->message);
463 if (!strstr (error->message, testcases[i].expected_error))
464 g_error ("Failure message '%s' for string '%s' did not contained expected substring '%s'",
465 error->message, testcases[i].detailed, testcases[i].expected_error);
467 g_error_free (error);
471 g_assert_cmpstr (name, ==, testcases[i].expected_name);
472 g_assert ((target == NULL) == (testcases[i].expected_target == NULL));
478 detailed = g_action_print_detailed_name (name, target);
479 g_assert_cmpstr (detailed, ==, testcases[i].detailed_roundtrip);
487 expected = g_variant_parse (NULL, testcases[i].expected_target, NULL, NULL, NULL);
490 g_assert (g_variant_equal (expected, target));
491 g_variant_unref (expected);
492 g_variant_unref (target);
499 GHashTable *activation_counts;
502 count_activation (const gchar *action)
506 if (activation_counts == NULL)
507 activation_counts = g_hash_table_new (g_str_hash, g_str_equal);
508 count = GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
510 g_hash_table_insert (activation_counts, (gpointer)action, GINT_TO_POINTER (count));
514 activation_count (const gchar *action)
516 if (activation_counts == NULL)
519 return GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
523 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
525 count_activation (g_action_get_name (G_ACTION (action)));
529 activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
531 GVariant *old_state, *new_state;
533 count_activation (g_action_get_name (G_ACTION (action)));
535 old_state = g_action_get_state (G_ACTION (action));
536 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
537 g_simple_action_set_state (action, new_state);
538 g_variant_unref (old_state);
542 activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
546 count_activation (g_action_get_name (G_ACTION (action)));
548 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
549 g_simple_action_set_state (action, new_state);
553 compare_action_groups (GActionGroup *a, GActionGroup *b)
560 gboolean aenabled, benabled;
561 const GVariantType *aparameter_type, *bparameter_type;
562 const GVariantType *astate_type, *bstate_type;
563 GVariant *astate_hint, *bstate_hint;
564 GVariant *astate, *bstate;
566 alist = g_action_group_list_actions (a);
567 blist = g_action_group_list_actions (b);
568 equal = strv_strv_cmp (alist, blist);
570 for (i = 0; equal && alist[i]; i++)
572 ares = g_action_group_query_action (a, alist[i], &aenabled, &aparameter_type, &astate_type, &astate_hint, &astate);
573 bres = g_action_group_query_action (b, alist[i], &benabled, &bparameter_type, &bstate_type, &bstate_hint, &bstate);
577 equal = equal && (aenabled == benabled);
578 equal = equal && ((!aparameter_type && !bparameter_type) || g_variant_type_equal (aparameter_type, bparameter_type));
579 equal = equal && ((!astate_type && !bstate_type) || g_variant_type_equal (astate_type, bstate_type));
580 equal = equal && ((!astate_hint && !bstate_hint) || g_variant_equal (astate_hint, bstate_hint));
581 equal = equal && ((!astate && !bstate) || g_variant_equal (astate, bstate));
584 g_variant_unref (astate_hint);
586 g_variant_unref (bstate_hint);
588 g_variant_unref (astate);
590 g_variant_unref (bstate);
603 stop_loop (gpointer data)
605 GMainLoop *loop = data;
607 g_main_loop_quit (loop);
609 return G_SOURCE_REMOVE;
612 static GActionEntry exported_entries[] = {
613 { "undo", activate_action, NULL, NULL, NULL },
614 { "redo", activate_action, NULL, NULL, NULL },
615 { "cut", activate_action, NULL, NULL, NULL },
616 { "copy", activate_action, NULL, NULL, NULL },
617 { "paste", activate_action, NULL, NULL, NULL },
618 { "bold", activate_toggle, NULL, "true", NULL },
619 { "lang", activate_radio, "s", "'latin'", NULL },
623 list_cb (GObject *source,
627 GDBusConnection *bus = G_DBUS_CONNECTION (source);
628 GMainLoop *loop = user_data;
629 GError *error = NULL;
633 v = g_dbus_connection_call_finish (bus, res, &error);
635 g_variant_get (v, "(^a&s)", &actions);
636 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
639 g_main_loop_quit (loop);
643 call_list (gpointer user_data)
645 GDBusConnection *bus;
647 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
648 g_dbus_connection_call (bus,
649 g_dbus_connection_get_unique_name (bus),
660 g_object_unref (bus);
662 return G_SOURCE_REMOVE;
666 describe_cb (GObject *source,
670 GDBusConnection *bus = G_DBUS_CONNECTION (source);
671 GMainLoop *loop = user_data;
672 GError *error = NULL;
678 v = g_dbus_connection_call_finish (bus, res, &error);
680 /* FIXME: there's an extra level of tuplelization in here */
681 g_variant_get (v, "((bgav))", &enabled, ¶m, &iter);
682 g_assert (enabled == TRUE);
683 g_assert_cmpstr (param, ==, "");
684 g_assert_cmpint (g_variant_iter_n_children (iter), ==, 0);
686 g_variant_iter_free (iter);
689 g_main_loop_quit (loop);
693 call_describe (gpointer user_data)
695 GDBusConnection *bus;
697 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
698 g_dbus_connection_call (bus,
699 g_dbus_connection_get_unique_name (bus),
703 g_variant_new ("(s)", "copy"),
710 g_object_unref (bus);
712 return G_SOURCE_REMOVE;
715 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
718 test_dbus_export (void)
720 GDBusConnection *bus;
721 GSimpleActionGroup *group;
722 GDBusActionGroup *proxy;
723 GSimpleAction *action;
725 GError *error = NULL;
730 loop = g_main_loop_new (NULL, FALSE);
733 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
735 group = g_simple_action_group_new ();
736 g_simple_action_group_add_entries (group,
738 G_N_ELEMENTS (exported_entries),
741 id = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &error);
742 g_assert_no_error (error);
744 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
746 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
747 g_assert_cmpint (g_strv_length (actions), ==, 0);
748 g_strfreev (actions);
750 g_timeout_add (100, stop_loop, loop);
751 g_main_loop_run (loop);
753 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
754 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
755 g_strfreev (actions);
757 /* check that calling "List" works too */
758 g_idle_add (call_list, loop);
759 g_main_loop_run (loop);
761 /* check that calling "Describe" works */
762 g_idle_add (call_describe, loop);
763 g_main_loop_run (loop);
765 /* test that the initial transfer works */
766 g_assert (G_IS_DBUS_ACTION_GROUP (proxy));
767 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
769 /* test that various changes get propagated from group to proxy */
770 action = g_simple_action_new_stateful ("italic", NULL, g_variant_new_boolean (FALSE));
771 g_simple_action_group_insert (group, G_ACTION (action));
772 g_object_unref (action);
774 g_timeout_add (100, stop_loop, loop);
775 g_main_loop_run (loop);
777 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
779 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "cut"));
780 g_simple_action_set_enabled (action, FALSE);
782 g_timeout_add (100, stop_loop, loop);
783 g_main_loop_run (loop);
785 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
787 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "bold"));
788 g_simple_action_set_state (action, g_variant_new_boolean (FALSE));
790 g_timeout_add (100, stop_loop, loop);
791 g_main_loop_run (loop);
793 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
795 g_simple_action_group_remove (group, "italic");
797 g_timeout_add (100, stop_loop, loop);
798 g_main_loop_run (loop);
800 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
802 /* test that activations and state changes propagate the other way */
804 g_assert_cmpint (activation_count ("copy"), ==, 0);
805 g_action_group_activate_action (G_ACTION_GROUP (proxy), "copy", NULL);
807 g_timeout_add (100, stop_loop, loop);
808 g_main_loop_run (loop);
810 g_assert_cmpint (activation_count ("copy"), ==, 1);
811 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
813 g_assert_cmpint (activation_count ("bold"), ==, 0);
814 g_action_group_activate_action (G_ACTION_GROUP (proxy), "bold", NULL);
816 g_timeout_add (100, stop_loop, loop);
817 g_main_loop_run (loop);
819 g_assert_cmpint (activation_count ("bold"), ==, 1);
820 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
821 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
822 g_assert (g_variant_get_boolean (v));
825 g_action_group_change_action_state (G_ACTION_GROUP (proxy), "bold", g_variant_new_boolean (FALSE));
827 g_timeout_add (100, stop_loop, loop);
828 g_main_loop_run (loop);
830 g_assert_cmpint (activation_count ("bold"), ==, 1);
831 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
832 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
833 g_assert (!g_variant_get_boolean (v));
836 g_dbus_connection_unexport_action_group (bus, id);
838 g_object_unref (proxy);
839 g_object_unref (group);
840 g_main_loop_unref (loop);
841 g_object_unref (bus);
847 do_export (gpointer data)
849 GActionGroup *group = data;
852 GError *error = NULL;
854 GDBusConnection *bus;
858 ctx = g_main_context_new ();
860 g_main_context_push_thread_default (ctx);
862 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
863 path = g_strdup_printf("/%p", data);
865 for (i = 0; i < 100000; i++)
867 id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error);
868 g_assert_no_error (error);
870 action = g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group), "a");
871 g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
872 !g_action_get_enabled (action));
874 g_dbus_connection_unexport_action_group (bus, id);
876 while (g_main_context_iteration (ctx, FALSE));
880 g_object_unref (bus);
882 g_main_context_pop_thread_default (ctx);
884 g_main_context_unref (ctx);
890 test_dbus_threaded (void)
892 GSimpleActionGroup *group[10];
894 static GActionEntry entries[] = {
895 { "a", activate_action, NULL, NULL, NULL },
896 { "b", activate_action, NULL, NULL, NULL },
902 for (i = 0; i < 10; i++)
904 group[i] = g_simple_action_group_new ();
905 g_simple_action_group_add_entries (group[i], entries, G_N_ELEMENTS (entries), NULL);
906 export[i] = g_thread_new ("export", do_export, group[i]);
909 for (i = 0; i < 10; i++)
910 g_thread_join (export[i]);
912 for (i = 0; i < 10; i++)
913 g_object_unref (group[i]);
918 G_GNUC_END_IGNORE_DEPRECATIONS
921 test_bug679509 (void)
923 GDBusConnection *bus;
924 GDBusActionGroup *proxy;
927 loop = g_main_loop_new (NULL, FALSE);
930 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
932 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
933 g_strfreev (g_action_group_list_actions (G_ACTION_GROUP (proxy)));
934 g_object_unref (proxy);
936 g_timeout_add (100, stop_loop, loop);
937 g_main_loop_run (loop);
939 g_main_loop_unref (loop);
940 g_object_unref (bus);
945 static gchar *state_change_log;
948 state_changed (GActionGroup *group,
949 const gchar *action_name,
955 g_assert (!state_change_log);
957 string = g_string_new (action_name);
958 g_string_append_c (string, ':');
959 g_variant_print_string (value, string, TRUE);
960 state_change_log = g_string_free (string, FALSE);
964 verify_changed (const gchar *log_entry)
966 g_assert_cmpstr (state_change_log, ==, log_entry);
967 g_clear_pointer (&state_change_log, g_free);
971 ensure_state (GSimpleActionGroup *group,
972 const gchar *action_name,
973 const gchar *expected)
978 value = g_action_group_get_action_state (G_ACTION_GROUP (group), action_name);
979 printed = g_variant_print (value, TRUE);
980 g_variant_unref (value);
982 g_assert_cmpstr (printed, ==, expected);
987 test_property_actions (void)
989 GSimpleActionGroup *group;
990 GPropertyAction *action;
991 GSocketClient *client;
994 group = g_simple_action_group_new ();
995 g_signal_connect (group, "action-state-changed", G_CALLBACK (state_changed), NULL);
997 client = g_socket_client_new ();
998 app = g_application_new ("org.gtk.test", 0);
1001 action = g_property_action_new ("app-id", app, "application-id");
1002 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
1003 g_object_unref (action);
1006 action = g_property_action_new ("keepalive", app, "inactivity-timeout");
1007 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
1008 g_object_unref (action);
1011 action = g_property_action_new ("tls", client, "tls");
1012 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
1013 g_object_unref (action);
1016 action = g_property_action_new ("type", client, "type");
1017 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
1018 g_object_unref (action);
1020 /* the objects should be held alive by the actions... */
1021 g_object_unref (client);
1022 g_object_unref (app);
1024 ensure_state (group, "app-id", "'org.gtk.test'");
1025 ensure_state (group, "keepalive", "uint32 0");
1026 ensure_state (group, "tls", "false");
1027 ensure_state (group, "type", "'stream'");
1029 verify_changed (NULL);
1031 /* some string tests... */
1032 g_action_group_change_action_state (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test2"));
1033 verify_changed ("app-id:'org.gtk.test2'");
1034 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test2");
1035 ensure_state (group, "app-id", "'org.gtk.test2'");
1037 g_action_group_activate_action (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test3"));
1038 verify_changed ("app-id:'org.gtk.test3'");
1039 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test3");
1040 ensure_state (group, "app-id", "'org.gtk.test3'");
1042 g_application_set_application_id (app, "org.gtk.test");
1043 verify_changed ("app-id:'org.gtk.test'");
1044 ensure_state (group, "app-id", "'org.gtk.test'");
1047 g_action_group_change_action_state (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 1234));
1048 verify_changed ("keepalive:uint32 1234");
1049 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 1234);
1050 ensure_state (group, "keepalive", "uint32 1234");
1052 g_action_group_activate_action (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 5678));
1053 verify_changed ("keepalive:uint32 5678");
1054 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 5678);
1055 ensure_state (group, "keepalive", "uint32 5678");
1057 g_application_set_inactivity_timeout (app, 0);
1058 verify_changed ("keepalive:uint32 0");
1059 ensure_state (group, "keepalive", "uint32 0");
1062 g_action_group_change_action_state (G_ACTION_GROUP (group), "tls", g_variant_new ("b", TRUE));
1063 verify_changed ("tls:true");
1064 g_assert (g_socket_client_get_tls (client));
1065 ensure_state (group, "tls", "true");
1067 /* test toggle true->false */
1068 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1069 verify_changed ("tls:false");
1070 g_assert (!g_socket_client_get_tls (client));
1071 ensure_state (group, "tls", "false");
1073 /* and now back false->true */
1074 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1075 verify_changed ("tls:true");
1076 g_assert (g_socket_client_get_tls (client));
1077 ensure_state (group, "tls", "true");
1079 g_socket_client_set_tls (client, FALSE);
1080 verify_changed ("tls:false");
1081 ensure_state (group, "tls", "false");
1084 g_action_group_change_action_state (G_ACTION_GROUP (group), "type", g_variant_new ("s", "datagram"));
1085 verify_changed ("type:'datagram'");
1086 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_DATAGRAM);
1087 ensure_state (group, "type", "'datagram'");
1089 g_action_group_activate_action (G_ACTION_GROUP (group), "type", g_variant_new ("s", "stream"));
1090 verify_changed ("type:'stream'");
1091 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_STREAM);
1092 ensure_state (group, "type", "'stream'");
1094 g_socket_client_set_socket_type (client, G_SOCKET_TYPE_SEQPACKET);
1095 verify_changed ("type:'seqpacket'");
1096 ensure_state (group, "type", "'seqpacket'");
1098 /* Check some error cases... */
1099 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*non-existent*");
1100 action = g_property_action_new ("foo", app, "xyz");
1101 g_test_assert_expected_messages ();
1102 g_object_unref (action);
1104 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*writable*");
1105 action = g_property_action_new ("foo", app, "is-registered");
1106 g_test_assert_expected_messages ();
1107 g_object_unref (action);
1109 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*type 'GSocketAddress'*");
1110 action = g_property_action_new ("foo", client, "local-address");
1111 g_test_assert_expected_messages ();
1112 g_object_unref (action);
1114 g_object_unref (group);
1118 main (int argc, char **argv)
1120 g_test_init (&argc, &argv, NULL);
1122 g_test_add_func ("/actions/basic", test_basic);
1123 g_test_add_func ("/actions/name", test_name);
1124 g_test_add_func ("/actions/simplegroup", test_simple_group);
1125 g_test_add_func ("/actions/stateful", test_stateful);
1126 g_test_add_func ("/actions/entries", test_entries);
1127 g_test_add_func ("/actions/parse-detailed", test_parse_detailed);
1128 g_test_add_func ("/actions/dbus/export", test_dbus_export);
1129 g_test_add_func ("/actions/dbus/threaded", test_dbus_threaded);
1130 g_test_add_func ("/actions/dbus/bug679509", test_bug679509);
1131 g_test_add_func ("/actions/property", test_property_actions);
1133 return g_test_run ();