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);
107 strv_has_string (gchar **haystack,
112 for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
114 if (g_strcmp0 (haystack[n], needle) == 0)
121 strv_strv_cmp (gchar **a, gchar **b)
125 for (n = 0; a[n] != NULL; n++)
127 if (!strv_has_string (b, a[n]))
131 for (n = 0; b[n] != NULL; n++)
133 if (!strv_has_string (a, b[n]))
141 strv_set_equal (gchar **strv, ...)
150 va_start (list, strv);
153 str = va_arg (list, const gchar *);
156 if (!strv_has_string (strv, str))
166 res = g_strv_length ((gchar**)strv) == count;
171 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
174 test_simple_group (void)
176 GSimpleActionGroup *group;
177 Activation a = { 0, };
178 GSimpleAction *simple;
183 simple = g_simple_action_new ("foo", NULL);
184 g_signal_connect (simple, "activate", G_CALLBACK (activate), &a);
185 g_assert (!a.did_run);
186 g_action_activate (G_ACTION (simple), NULL);
187 g_assert (a.did_run);
190 group = g_simple_action_group_new ();
191 g_simple_action_group_insert (group, G_ACTION (simple));
192 g_object_unref (simple);
194 g_assert (!a.did_run);
195 g_action_group_activate_action (G_ACTION_GROUP (group), "foo", NULL);
196 g_assert (a.did_run);
198 simple = g_simple_action_new_stateful ("bar", G_VARIANT_TYPE_STRING, g_variant_new_string ("hihi"));
199 g_simple_action_group_insert (group, G_ACTION (simple));
200 g_object_unref (simple);
202 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "foo"));
203 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "bar"));
204 g_assert (!g_action_group_has_action (G_ACTION_GROUP (group), "baz"));
205 actions = g_action_group_list_actions (G_ACTION_GROUP (group));
206 g_assert_cmpint (g_strv_length (actions), ==, 2);
207 g_assert (strv_set_equal (actions, "foo", "bar", NULL));
208 g_strfreev (actions);
209 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "foo"));
210 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
211 g_assert (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "foo") == NULL);
212 g_assert (g_variant_type_equal (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
213 g_assert (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "foo") == NULL);
214 g_assert (g_variant_type_equal (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
215 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "foo") == NULL);
216 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "bar") == NULL);
217 g_assert (g_action_group_get_action_state (G_ACTION_GROUP (group), "foo") == NULL);
218 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
219 g_assert (g_variant_type_equal (g_variant_get_type (state), G_VARIANT_TYPE_STRING));
220 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
221 g_variant_unref (state);
223 g_action_group_change_action_state (G_ACTION_GROUP (group), "bar", g_variant_new_string ("boo"));
224 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
225 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "boo");
226 g_variant_unref (state);
228 action = g_simple_action_group_lookup (group, "bar");
229 g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
230 g_assert (!g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
232 g_simple_action_group_remove (group, "bar");
233 action = g_simple_action_group_lookup (group, "foo");
234 g_assert_cmpstr (g_action_get_name (action), ==, "foo");
235 action = g_simple_action_group_lookup (group, "bar");
236 g_assert (action == NULL);
239 g_object_unref (group);
240 g_assert (!a.did_run);
243 G_GNUC_END_IGNORE_DEPRECATIONS
248 GSimpleAction *action;
251 action = g_simple_action_new_stateful ("foo", NULL, g_variant_new_string ("hihi"));
252 g_assert (g_action_get_enabled (G_ACTION (action)));
253 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
254 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
255 g_assert (g_variant_type_equal (g_action_get_state_type (G_ACTION (action)),
256 G_VARIANT_TYPE_STRING));
257 state = g_action_get_state (G_ACTION (action));
258 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
259 g_variant_unref (state);
261 if (g_test_undefined ())
263 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
264 "*assertion*g_variant_is_of_type*failed*");
265 g_simple_action_set_state (action, g_variant_new_int32 (123));
266 g_test_assert_expected_messages ();
269 g_simple_action_set_state (action, g_variant_new_string ("hello"));
270 state = g_action_get_state (G_ACTION (action));
271 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hello");
272 g_variant_unref (state);
274 g_object_unref (action);
276 action = g_simple_action_new ("foo", NULL);
278 if (g_test_undefined ())
280 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
281 "*assertion*!= NULL*failed*");
282 g_simple_action_set_state (action, g_variant_new_int32 (123));
283 g_test_assert_expected_messages ();
286 g_object_unref (action);
289 static gboolean foo_activated = FALSE;
290 static gboolean bar_activated = FALSE;
293 activate_foo (GSimpleAction *simple,
297 g_assert (user_data == GINT_TO_POINTER (123));
298 g_assert (parameter == NULL);
299 foo_activated = TRUE;
303 activate_bar (GSimpleAction *simple,
307 g_assert (user_data == GINT_TO_POINTER (123));
308 g_assert_cmpstr (g_variant_get_string (parameter, NULL), ==, "param");
309 bar_activated = TRUE;
313 change_volume_state (GSimpleAction *action,
319 requested = g_variant_get_int32 (value);
321 /* Volume only goes from 0 to 10 */
322 if (0 <= requested && requested <= 10)
323 g_simple_action_set_state (action, value);
326 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
331 const GActionEntry entries[] = {
332 { "foo", activate_foo },
333 { "bar", activate_bar, "s" },
334 { "toggle", NULL, NULL, "false" },
335 { "volume", NULL, NULL, "0", change_volume_state }
337 GSimpleActionGroup *actions;
340 actions = g_simple_action_group_new ();
341 g_simple_action_group_add_entries (actions, entries,
342 G_N_ELEMENTS (entries),
343 GINT_TO_POINTER (123));
345 g_assert (!foo_activated);
346 g_action_group_activate_action (G_ACTION_GROUP (actions), "foo", NULL);
347 g_assert (foo_activated);
348 foo_activated = FALSE;
350 g_assert (!bar_activated);
351 g_action_group_activate_action (G_ACTION_GROUP (actions), "bar",
352 g_variant_new_string ("param"));
353 g_assert (bar_activated);
354 g_assert (!foo_activated);
356 if (g_test_undefined ())
358 const GActionEntry bad_type = {
359 "bad-type", NULL, "ss"
361 const GActionEntry bad_state = {
362 "bad-state", NULL, NULL, "flse"
365 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
366 "*not a valid GVariant type string*");
367 g_simple_action_group_add_entries (actions, &bad_type, 1, NULL);
368 g_test_assert_expected_messages ();
370 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
371 "*could not parse*");
372 g_simple_action_group_add_entries (actions, &bad_state, 1, NULL);
373 g_test_assert_expected_messages ();
376 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
377 g_assert_cmpint (g_variant_get_int32 (state), ==, 0);
378 g_variant_unref (state);
381 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
382 g_variant_new_int32 (7));
383 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
384 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
385 g_variant_unref (state);
387 /* should not change */
388 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
389 g_variant_new_int32 (11));
390 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
391 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
392 g_variant_unref (state);
394 g_object_unref (actions);
397 G_GNUC_END_IGNORE_DEPRECATIONS
400 test_parse_detailed (void)
403 const gchar *detailed;
404 const gchar *expected_name;
405 const gchar *expected_target;
406 const gchar *expected_error;
408 { "abc", "abc", NULL, NULL },
409 { " abc", NULL, NULL, "invalid format" },
410 { " abc", NULL, NULL, "invalid format" },
411 { "abc:", NULL, NULL, "invalid format" },
412 { ":abc", NULL, NULL, "invalid format" },
413 { "abc(", NULL, NULL, "invalid format" },
414 { "abc)", NULL, NULL, "invalid format" },
415 { "(abc", NULL, NULL, "invalid format" },
416 { ")abc", NULL, NULL, "invalid format" },
417 { "abc::xyz", "abc", "'xyz'", NULL },
418 { "abc('xyz')", "abc", "'xyz'", NULL },
419 { "abc(42)", "abc", "42", NULL },
420 { "abc(int32 42)", "abc", "42", NULL },
421 { "abc(@i 42)", "abc", "42", NULL },
422 { "abc (42)", NULL, NULL, "invalid format" },
423 { "abc(42abc)", NULL, NULL, "invalid character in number" },
424 { "abc(42, 4)", "abc", "(42, 4)", "expected end of input" },
425 { "abc(42,)", "abc", "(42,)", "expected end of input" }
429 for (i = 0; i < G_N_ELEMENTS (testcases); i++)
431 GError *error = NULL;
436 success = g_action_parse_detailed_name (testcases[i].detailed, &name, &target, &error);
437 g_assert (success == (error == NULL));
438 if (success && testcases[i].expected_error)
439 g_error ("Unexpected success on '%s'. Expected error containing '%s'",
440 testcases[i].detailed, testcases[i].expected_error);
442 if (!success && !testcases[i].expected_error)
443 g_error ("Unexpected failure on '%s': %s", testcases[i].detailed, error->message);
447 if (!strstr (error->message, testcases[i].expected_error))
448 g_error ("Failure message '%s' for string '%s' did not contained expected substring '%s'",
449 error->message, testcases[i].detailed, testcases[i].expected_error);
451 g_error_free (error);
455 g_assert_cmpstr (name, ==, testcases[i].expected_name);
456 g_assert ((target == NULL) == (testcases[i].expected_target == NULL));
461 expected = g_variant_parse (NULL, testcases[i].expected_target, NULL, NULL, NULL);
464 g_assert (g_variant_equal (expected, target));
465 g_variant_unref (expected);
466 g_variant_unref (target);
473 GHashTable *activation_counts;
476 count_activation (const gchar *action)
480 if (activation_counts == NULL)
481 activation_counts = g_hash_table_new (g_str_hash, g_str_equal);
482 count = GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
484 g_hash_table_insert (activation_counts, (gpointer)action, GINT_TO_POINTER (count));
488 activation_count (const gchar *action)
490 if (activation_counts == NULL)
493 return GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
497 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
499 count_activation (g_action_get_name (G_ACTION (action)));
503 activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
505 GVariant *old_state, *new_state;
507 count_activation (g_action_get_name (G_ACTION (action)));
509 old_state = g_action_get_state (G_ACTION (action));
510 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
511 g_simple_action_set_state (action, new_state);
512 g_variant_unref (old_state);
516 activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
520 count_activation (g_action_get_name (G_ACTION (action)));
522 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
523 g_simple_action_set_state (action, new_state);
527 compare_action_groups (GActionGroup *a, GActionGroup *b)
534 gboolean aenabled, benabled;
535 const GVariantType *aparameter_type, *bparameter_type;
536 const GVariantType *astate_type, *bstate_type;
537 GVariant *astate_hint, *bstate_hint;
538 GVariant *astate, *bstate;
540 alist = g_action_group_list_actions (a);
541 blist = g_action_group_list_actions (b);
542 equal = strv_strv_cmp (alist, blist);
544 for (i = 0; equal && alist[i]; i++)
546 ares = g_action_group_query_action (a, alist[i], &aenabled, &aparameter_type, &astate_type, &astate_hint, &astate);
547 bres = g_action_group_query_action (b, alist[i], &benabled, &bparameter_type, &bstate_type, &bstate_hint, &bstate);
551 equal = equal && (aenabled == benabled);
552 equal = equal && ((!aparameter_type && !bparameter_type) || g_variant_type_equal (aparameter_type, bparameter_type));
553 equal = equal && ((!astate_type && !bstate_type) || g_variant_type_equal (astate_type, bstate_type));
554 equal = equal && ((!astate_hint && !bstate_hint) || g_variant_equal (astate_hint, bstate_hint));
555 equal = equal && ((!astate && !bstate) || g_variant_equal (astate, bstate));
558 g_variant_unref (astate_hint);
560 g_variant_unref (bstate_hint);
562 g_variant_unref (astate);
564 g_variant_unref (bstate);
577 stop_loop (gpointer data)
579 GMainLoop *loop = data;
581 g_main_loop_quit (loop);
583 return G_SOURCE_REMOVE;
586 static GActionEntry exported_entries[] = {
587 { "undo", activate_action, NULL, NULL, NULL },
588 { "redo", activate_action, NULL, NULL, NULL },
589 { "cut", activate_action, NULL, NULL, NULL },
590 { "copy", activate_action, NULL, NULL, NULL },
591 { "paste", activate_action, NULL, NULL, NULL },
592 { "bold", activate_toggle, NULL, "true", NULL },
593 { "lang", activate_radio, "s", "'latin'", NULL },
597 list_cb (GObject *source,
601 GDBusConnection *bus = G_DBUS_CONNECTION (source);
602 GMainLoop *loop = user_data;
603 GError *error = NULL;
607 v = g_dbus_connection_call_finish (bus, res, &error);
609 g_variant_get (v, "(^a&s)", &actions);
610 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
613 g_main_loop_quit (loop);
617 call_list (gpointer user_data)
619 GDBusConnection *bus;
621 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
622 g_dbus_connection_call (bus,
623 g_dbus_connection_get_unique_name (bus),
634 g_object_unref (bus);
636 return G_SOURCE_REMOVE;
640 describe_cb (GObject *source,
644 GDBusConnection *bus = G_DBUS_CONNECTION (source);
645 GMainLoop *loop = user_data;
646 GError *error = NULL;
652 v = g_dbus_connection_call_finish (bus, res, &error);
654 /* FIXME: there's an extra level of tuplelization in here */
655 g_variant_get (v, "((bgav))", &enabled, ¶m, &iter);
656 g_assert (enabled == TRUE);
657 g_assert_cmpstr (param, ==, "");
658 g_assert_cmpint (g_variant_iter_n_children (iter), ==, 0);
660 g_variant_iter_free (iter);
663 g_main_loop_quit (loop);
667 call_describe (gpointer user_data)
669 GDBusConnection *bus;
671 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
672 g_dbus_connection_call (bus,
673 g_dbus_connection_get_unique_name (bus),
677 g_variant_new ("(s)", "copy"),
684 g_object_unref (bus);
686 return G_SOURCE_REMOVE;
689 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
692 test_dbus_export (void)
694 GDBusConnection *bus;
695 GSimpleActionGroup *group;
696 GDBusActionGroup *proxy;
697 GSimpleAction *action;
699 GError *error = NULL;
704 loop = g_main_loop_new (NULL, FALSE);
707 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
709 group = g_simple_action_group_new ();
710 g_simple_action_group_add_entries (group,
712 G_N_ELEMENTS (exported_entries),
715 id = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &error);
716 g_assert_no_error (error);
718 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
720 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
721 g_assert_cmpint (g_strv_length (actions), ==, 0);
722 g_strfreev (actions);
724 g_timeout_add (100, stop_loop, loop);
725 g_main_loop_run (loop);
727 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
728 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
729 g_strfreev (actions);
731 /* check that calling "List" works too */
732 g_idle_add (call_list, loop);
733 g_main_loop_run (loop);
735 /* check that calling "Describe" works */
736 g_idle_add (call_describe, loop);
737 g_main_loop_run (loop);
739 /* test that the initial transfer works */
740 g_assert (G_IS_DBUS_ACTION_GROUP (proxy));
741 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
743 /* test that various changes get propagated from group to proxy */
744 action = g_simple_action_new_stateful ("italic", NULL, g_variant_new_boolean (FALSE));
745 g_simple_action_group_insert (group, G_ACTION (action));
746 g_object_unref (action);
748 g_timeout_add (100, stop_loop, loop);
749 g_main_loop_run (loop);
751 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
753 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "cut"));
754 g_simple_action_set_enabled (action, FALSE);
756 g_timeout_add (100, stop_loop, loop);
757 g_main_loop_run (loop);
759 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
761 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "bold"));
762 g_simple_action_set_state (action, g_variant_new_boolean (FALSE));
764 g_timeout_add (100, stop_loop, loop);
765 g_main_loop_run (loop);
767 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
769 g_simple_action_group_remove (group, "italic");
771 g_timeout_add (100, stop_loop, loop);
772 g_main_loop_run (loop);
774 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
776 /* test that activations and state changes propagate the other way */
778 g_assert_cmpint (activation_count ("copy"), ==, 0);
779 g_action_group_activate_action (G_ACTION_GROUP (proxy), "copy", NULL);
781 g_timeout_add (100, stop_loop, loop);
782 g_main_loop_run (loop);
784 g_assert_cmpint (activation_count ("copy"), ==, 1);
785 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
787 g_assert_cmpint (activation_count ("bold"), ==, 0);
788 g_action_group_activate_action (G_ACTION_GROUP (proxy), "bold", NULL);
790 g_timeout_add (100, stop_loop, loop);
791 g_main_loop_run (loop);
793 g_assert_cmpint (activation_count ("bold"), ==, 1);
794 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
795 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
796 g_assert (g_variant_get_boolean (v));
799 g_action_group_change_action_state (G_ACTION_GROUP (proxy), "bold", g_variant_new_boolean (FALSE));
801 g_timeout_add (100, stop_loop, loop);
802 g_main_loop_run (loop);
804 g_assert_cmpint (activation_count ("bold"), ==, 1);
805 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
806 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
807 g_assert (!g_variant_get_boolean (v));
810 g_dbus_connection_unexport_action_group (bus, id);
812 g_object_unref (proxy);
813 g_object_unref (group);
814 g_main_loop_unref (loop);
815 g_object_unref (bus);
821 do_export (gpointer data)
823 GActionGroup *group = data;
826 GError *error = NULL;
828 GDBusConnection *bus;
832 ctx = g_main_context_new ();
834 g_main_context_push_thread_default (ctx);
836 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
837 path = g_strdup_printf("/%p", data);
839 for (i = 0; i < 100000; i++)
841 id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error);
842 g_assert_no_error (error);
844 action = g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group), "a");
845 g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
846 !g_action_get_enabled (action));
848 g_dbus_connection_unexport_action_group (bus, id);
850 while (g_main_context_iteration (ctx, FALSE));
854 g_object_unref (bus);
856 g_main_context_pop_thread_default (ctx);
858 g_main_context_unref (ctx);
864 test_dbus_threaded (void)
866 GSimpleActionGroup *group[10];
868 static GActionEntry entries[] = {
869 { "a", activate_action, NULL, NULL, NULL },
870 { "b", activate_action, NULL, NULL, NULL },
876 for (i = 0; i < 10; i++)
878 group[i] = g_simple_action_group_new ();
879 g_simple_action_group_add_entries (group[i], entries, G_N_ELEMENTS (entries), NULL);
880 export[i] = g_thread_new ("export", do_export, group[i]);
883 for (i = 0; i < 10; i++)
884 g_thread_join (export[i]);
886 for (i = 0; i < 10; i++)
887 g_object_unref (group[i]);
892 G_GNUC_END_IGNORE_DEPRECATIONS
895 test_bug679509 (void)
897 GDBusConnection *bus;
898 GDBusActionGroup *proxy;
901 loop = g_main_loop_new (NULL, FALSE);
904 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
906 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
907 g_strfreev (g_action_group_list_actions (G_ACTION_GROUP (proxy)));
908 g_object_unref (proxy);
910 g_timeout_add (100, stop_loop, loop);
911 g_main_loop_run (loop);
913 g_main_loop_unref (loop);
914 g_object_unref (bus);
919 static gchar *state_change_log;
922 state_changed (GActionGroup *group,
923 const gchar *action_name,
929 g_assert (!state_change_log);
931 string = g_string_new (action_name);
932 g_string_append_c (string, ':');
933 g_variant_print_string (value, string, TRUE);
934 state_change_log = g_string_free (string, FALSE);
938 verify_changed (const gchar *log_entry)
940 g_assert_cmpstr (state_change_log, ==, log_entry);
941 g_clear_pointer (&state_change_log, g_free);
945 ensure_state (GSimpleActionGroup *group,
946 const gchar *action_name,
947 const gchar *expected)
952 value = g_action_group_get_action_state (G_ACTION_GROUP (group), action_name);
953 printed = g_variant_print (value, TRUE);
954 g_variant_unref (value);
956 g_assert_cmpstr (printed, ==, expected);
961 test_property_actions (void)
963 GSimpleActionGroup *group;
964 GPropertyAction *action;
965 GSocketClient *client;
968 group = g_simple_action_group_new ();
969 g_signal_connect (group, "action-state-changed", G_CALLBACK (state_changed), NULL);
971 client = g_socket_client_new ();
972 app = g_application_new ("org.gtk.test", 0);
975 action = g_property_action_new ("app-id", app, "application-id");
976 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
977 g_object_unref (action);
980 action = g_property_action_new ("keepalive", app, "inactivity-timeout");
981 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
982 g_object_unref (action);
985 action = g_property_action_new ("tls", client, "tls");
986 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
987 g_object_unref (action);
990 action = g_property_action_new ("type", client, "type");
991 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
992 g_object_unref (action);
994 /* the objects should be held alive by the actions... */
995 g_object_unref (client);
996 g_object_unref (app);
998 ensure_state (group, "app-id", "'org.gtk.test'");
999 ensure_state (group, "keepalive", "uint32 0");
1000 ensure_state (group, "tls", "false");
1001 ensure_state (group, "type", "'stream'");
1003 verify_changed (NULL);
1005 /* some string tests... */
1006 g_action_group_change_action_state (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test2"));
1007 verify_changed ("app-id:'org.gtk.test2'");
1008 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test2");
1009 ensure_state (group, "app-id", "'org.gtk.test2'");
1011 g_action_group_activate_action (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test3"));
1012 verify_changed ("app-id:'org.gtk.test3'");
1013 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test3");
1014 ensure_state (group, "app-id", "'org.gtk.test3'");
1016 g_application_set_application_id (app, "org.gtk.test");
1017 verify_changed ("app-id:'org.gtk.test'");
1018 ensure_state (group, "app-id", "'org.gtk.test'");
1021 g_action_group_change_action_state (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 1234));
1022 verify_changed ("keepalive:uint32 1234");
1023 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 1234);
1024 ensure_state (group, "keepalive", "uint32 1234");
1026 g_action_group_activate_action (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 5678));
1027 verify_changed ("keepalive:uint32 5678");
1028 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 5678);
1029 ensure_state (group, "keepalive", "uint32 5678");
1031 g_application_set_inactivity_timeout (app, 0);
1032 verify_changed ("keepalive:uint32 0");
1033 ensure_state (group, "keepalive", "uint32 0");
1036 g_action_group_change_action_state (G_ACTION_GROUP (group), "tls", g_variant_new ("b", TRUE));
1037 verify_changed ("tls:true");
1038 g_assert (g_socket_client_get_tls (client));
1039 ensure_state (group, "tls", "true");
1041 /* test toggle true->false */
1042 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1043 verify_changed ("tls:false");
1044 g_assert (!g_socket_client_get_tls (client));
1045 ensure_state (group, "tls", "false");
1047 /* and now back false->true */
1048 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1049 verify_changed ("tls:true");
1050 g_assert (g_socket_client_get_tls (client));
1051 ensure_state (group, "tls", "true");
1053 g_socket_client_set_tls (client, FALSE);
1054 verify_changed ("tls:false");
1055 ensure_state (group, "tls", "false");
1058 g_action_group_change_action_state (G_ACTION_GROUP (group), "type", g_variant_new ("s", "datagram"));
1059 verify_changed ("type:'datagram'");
1060 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_DATAGRAM);
1061 ensure_state (group, "type", "'datagram'");
1063 g_action_group_activate_action (G_ACTION_GROUP (group), "type", g_variant_new ("s", "stream"));
1064 verify_changed ("type:'stream'");
1065 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_STREAM);
1066 ensure_state (group, "type", "'stream'");
1068 g_socket_client_set_socket_type (client, G_SOCKET_TYPE_SEQPACKET);
1069 verify_changed ("type:'seqpacket'");
1070 ensure_state (group, "type", "'seqpacket'");
1072 /* Check some error cases... */
1073 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*non-existent*");
1074 action = g_property_action_new ("foo", app, "xyz");
1075 g_test_assert_expected_messages ();
1076 g_object_unref (action);
1078 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*writable*");
1079 action = g_property_action_new ("foo", app, "is-registered");
1080 g_test_assert_expected_messages ();
1081 g_object_unref (action);
1083 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*type 'GSocketAddress'*");
1084 action = g_property_action_new ("foo", client, "local-address");
1085 g_test_assert_expected_messages ();
1086 g_object_unref (action);
1088 g_object_unref (group);
1092 main (int argc, char **argv)
1094 g_test_init (&argc, &argv, NULL);
1096 g_test_add_func ("/actions/basic", test_basic);
1097 g_test_add_func ("/actions/simplegroup", test_simple_group);
1098 g_test_add_func ("/actions/stateful", test_stateful);
1099 g_test_add_func ("/actions/entries", test_entries);
1100 g_test_add_func ("/actions/parse-detailed", test_parse_detailed);
1101 g_test_add_func ("/actions/dbus/export", test_dbus_export);
1102 g_test_add_func ("/actions/dbus/threaded", test_dbus_threaded);
1103 g_test_add_func ("/actions/dbus/bug679509", test_bug679509);
1104 g_test_add_func ("/actions/property", test_property_actions);
1106 return g_test_run ();