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;
172 test_simple_group (void)
174 GSimpleActionGroup *group;
175 Activation a = { 0, };
176 GSimpleAction *simple;
181 simple = g_simple_action_new ("foo", NULL);
182 g_signal_connect (simple, "activate", G_CALLBACK (activate), &a);
183 g_assert (!a.did_run);
184 g_action_activate (G_ACTION (simple), NULL);
185 g_assert (a.did_run);
188 group = g_simple_action_group_new ();
189 g_simple_action_group_insert (group, G_ACTION (simple));
190 g_object_unref (simple);
192 g_assert (!a.did_run);
193 g_action_group_activate_action (G_ACTION_GROUP (group), "foo", NULL);
194 g_assert (a.did_run);
196 simple = g_simple_action_new_stateful ("bar", G_VARIANT_TYPE_STRING, g_variant_new_string ("hihi"));
197 g_simple_action_group_insert (group, G_ACTION (simple));
198 g_object_unref (simple);
200 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "foo"));
201 g_assert (g_action_group_has_action (G_ACTION_GROUP (group), "bar"));
202 g_assert (!g_action_group_has_action (G_ACTION_GROUP (group), "baz"));
203 actions = g_action_group_list_actions (G_ACTION_GROUP (group));
204 g_assert_cmpint (g_strv_length (actions), ==, 2);
205 g_assert (strv_set_equal (actions, "foo", "bar", NULL));
206 g_strfreev (actions);
207 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "foo"));
208 g_assert (g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
209 g_assert (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "foo") == NULL);
210 g_assert (g_variant_type_equal (g_action_group_get_action_parameter_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
211 g_assert (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "foo") == NULL);
212 g_assert (g_variant_type_equal (g_action_group_get_action_state_type (G_ACTION_GROUP (group), "bar"), G_VARIANT_TYPE_STRING));
213 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "foo") == NULL);
214 g_assert (g_action_group_get_action_state_hint (G_ACTION_GROUP (group), "bar") == NULL);
215 g_assert (g_action_group_get_action_state (G_ACTION_GROUP (group), "foo") == NULL);
216 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
217 g_assert (g_variant_type_equal (g_variant_get_type (state), G_VARIANT_TYPE_STRING));
218 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
219 g_variant_unref (state);
221 g_action_group_change_action_state (G_ACTION_GROUP (group), "bar", g_variant_new_string ("boo"));
222 state = g_action_group_get_action_state (G_ACTION_GROUP (group), "bar");
223 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "boo");
224 g_variant_unref (state);
226 action = g_simple_action_group_lookup (group, "bar");
227 g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
228 g_assert (!g_action_group_get_action_enabled (G_ACTION_GROUP (group), "bar"));
230 g_simple_action_group_remove (group, "bar");
231 action = g_simple_action_group_lookup (group, "foo");
232 g_assert_cmpstr (g_action_get_name (action), ==, "foo");
233 action = g_simple_action_group_lookup (group, "bar");
234 g_assert (action == NULL);
237 g_object_unref (group);
238 g_assert (!a.did_run);
244 GSimpleAction *action;
247 action = g_simple_action_new_stateful ("foo", NULL, g_variant_new_string ("hihi"));
248 g_assert (g_action_get_enabled (G_ACTION (action)));
249 g_assert (g_action_get_parameter_type (G_ACTION (action)) == NULL);
250 g_assert (g_action_get_state_hint (G_ACTION (action)) == NULL);
251 g_assert (g_variant_type_equal (g_action_get_state_type (G_ACTION (action)),
252 G_VARIANT_TYPE_STRING));
253 state = g_action_get_state (G_ACTION (action));
254 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hihi");
255 g_variant_unref (state);
257 if (g_test_undefined ())
259 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
260 "*assertion*g_variant_is_of_type*failed*");
261 g_simple_action_set_state (action, g_variant_new_int32 (123));
262 g_test_assert_expected_messages ();
265 g_simple_action_set_state (action, g_variant_new_string ("hello"));
266 state = g_action_get_state (G_ACTION (action));
267 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "hello");
268 g_variant_unref (state);
270 g_object_unref (action);
272 action = g_simple_action_new ("foo", NULL);
274 if (g_test_undefined ())
276 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
277 "*assertion*!= NULL*failed*");
278 g_simple_action_set_state (action, g_variant_new_int32 (123));
279 g_test_assert_expected_messages ();
282 g_object_unref (action);
285 static gboolean foo_activated = FALSE;
286 static gboolean bar_activated = FALSE;
289 activate_foo (GSimpleAction *simple,
293 g_assert (user_data == GINT_TO_POINTER (123));
294 g_assert (parameter == NULL);
295 foo_activated = TRUE;
299 activate_bar (GSimpleAction *simple,
303 g_assert (user_data == GINT_TO_POINTER (123));
304 g_assert_cmpstr (g_variant_get_string (parameter, NULL), ==, "param");
305 bar_activated = TRUE;
309 change_volume_state (GSimpleAction *action,
315 requested = g_variant_get_int32 (value);
317 /* Volume only goes from 0 to 10 */
318 if (0 <= requested && requested <= 10)
319 g_simple_action_set_state (action, value);
325 const GActionEntry entries[] = {
326 { "foo", activate_foo },
327 { "bar", activate_bar, "s" },
328 { "toggle", NULL, NULL, "false" },
329 { "volume", NULL, NULL, "0", change_volume_state }
331 GSimpleActionGroup *actions;
334 actions = g_simple_action_group_new ();
335 g_simple_action_group_add_entries (actions, entries,
336 G_N_ELEMENTS (entries),
337 GINT_TO_POINTER (123));
339 g_assert (!foo_activated);
340 g_action_group_activate_action (G_ACTION_GROUP (actions), "foo", NULL);
341 g_assert (foo_activated);
342 foo_activated = FALSE;
344 g_assert (!bar_activated);
345 g_action_group_activate_action (G_ACTION_GROUP (actions), "bar",
346 g_variant_new_string ("param"));
347 g_assert (bar_activated);
348 g_assert (!foo_activated);
350 if (g_test_undefined ())
352 const GActionEntry bad_type = {
353 "bad-type", NULL, "ss"
355 const GActionEntry bad_state = {
356 "bad-state", NULL, NULL, "flse"
359 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
360 "*not a valid GVariant type string*");
361 g_simple_action_group_add_entries (actions, &bad_type, 1, NULL);
362 g_test_assert_expected_messages ();
364 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
365 "*could not parse*");
366 g_simple_action_group_add_entries (actions, &bad_state, 1, NULL);
367 g_test_assert_expected_messages ();
370 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
371 g_assert_cmpint (g_variant_get_int32 (state), ==, 0);
372 g_variant_unref (state);
375 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
376 g_variant_new_int32 (7));
377 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
378 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
379 g_variant_unref (state);
381 /* should not change */
382 g_action_group_change_action_state (G_ACTION_GROUP (actions), "volume",
383 g_variant_new_int32 (11));
384 state = g_action_group_get_action_state (G_ACTION_GROUP (actions), "volume");
385 g_assert_cmpint (g_variant_get_int32 (state), ==, 7);
386 g_variant_unref (state);
388 g_object_unref (actions);
392 test_parse_detailed (void)
395 const gchar *detailed;
396 const gchar *expected_name;
397 const gchar *expected_target;
398 const gchar *expected_error;
400 { "abc", "abc", NULL, NULL },
401 { " abc", NULL, NULL, "invalid format" },
402 { " abc", NULL, NULL, "invalid format" },
403 { "abc:", NULL, NULL, "invalid format" },
404 { ":abc", NULL, NULL, "invalid format" },
405 { "abc(", NULL, NULL, "invalid format" },
406 { "abc)", NULL, NULL, "invalid format" },
407 { "(abc", NULL, NULL, "invalid format" },
408 { ")abc", NULL, NULL, "invalid format" },
409 { "abc::xyz", "abc", "'xyz'", NULL },
410 { "abc('xyz')", "abc", "'xyz'", NULL },
411 { "abc(42)", "abc", "42", NULL },
412 { "abc(int32 42)", "abc", "42", NULL },
413 { "abc(@i 42)", "abc", "42", NULL },
414 { "abc (42)", NULL, NULL, "invalid format" },
415 { "abc(42abc)", NULL, NULL, "invalid character in number" },
416 { "abc(42, 4)", "abc", "(42, 4)", "expected end of input" },
417 { "abc(42,)", "abc", "(42,)", "expected end of input" }
421 for (i = 0; i < G_N_ELEMENTS (testcases); i++)
423 GError *error = NULL;
428 success = g_action_parse_detailed_name (testcases[i].detailed, &name, &target, &error);
429 g_assert (success == (error == NULL));
430 if (success && testcases[i].expected_error)
431 g_error ("Unexpected success on '%s'. Expected error containing '%s'",
432 testcases[i].detailed, testcases[i].expected_error);
434 if (!success && !testcases[i].expected_error)
435 g_error ("Unexpected failure on '%s': %s", testcases[i].detailed, error->message);
439 if (!strstr (error->message, testcases[i].expected_error))
440 g_error ("Failure message '%s' for string '%s' did not contained expected substring '%s'",
441 error->message, testcases[i].detailed, testcases[i].expected_error);
443 g_error_free (error);
447 g_assert_cmpstr (name, ==, testcases[i].expected_name);
448 g_assert ((target == NULL) == (testcases[i].expected_target == NULL));
453 expected = g_variant_parse (NULL, testcases[i].expected_target, NULL, NULL, NULL);
456 g_assert (g_variant_equal (expected, target));
457 g_variant_unref (expected);
458 g_variant_unref (target);
465 GHashTable *activation_counts;
468 count_activation (const gchar *action)
472 if (activation_counts == NULL)
473 activation_counts = g_hash_table_new (g_str_hash, g_str_equal);
474 count = GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
476 g_hash_table_insert (activation_counts, (gpointer)action, GINT_TO_POINTER (count));
480 activation_count (const gchar *action)
482 if (activation_counts == NULL)
485 return GPOINTER_TO_INT (g_hash_table_lookup (activation_counts, action));
489 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
491 count_activation (g_action_get_name (G_ACTION (action)));
495 activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
497 GVariant *old_state, *new_state;
499 count_activation (g_action_get_name (G_ACTION (action)));
501 old_state = g_action_get_state (G_ACTION (action));
502 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
503 g_simple_action_set_state (action, new_state);
504 g_variant_unref (old_state);
508 activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
512 count_activation (g_action_get_name (G_ACTION (action)));
514 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
515 g_simple_action_set_state (action, new_state);
519 compare_action_groups (GActionGroup *a, GActionGroup *b)
526 gboolean aenabled, benabled;
527 const GVariantType *aparameter_type, *bparameter_type;
528 const GVariantType *astate_type, *bstate_type;
529 GVariant *astate_hint, *bstate_hint;
530 GVariant *astate, *bstate;
532 alist = g_action_group_list_actions (a);
533 blist = g_action_group_list_actions (b);
534 equal = strv_strv_cmp (alist, blist);
536 for (i = 0; equal && alist[i]; i++)
538 ares = g_action_group_query_action (a, alist[i], &aenabled, &aparameter_type, &astate_type, &astate_hint, &astate);
539 bres = g_action_group_query_action (b, alist[i], &benabled, &bparameter_type, &bstate_type, &bstate_hint, &bstate);
543 equal = equal && (aenabled == benabled);
544 equal = equal && ((!aparameter_type && !bparameter_type) || g_variant_type_equal (aparameter_type, bparameter_type));
545 equal = equal && ((!astate_type && !bstate_type) || g_variant_type_equal (astate_type, bstate_type));
546 equal = equal && ((!astate_hint && !bstate_hint) || g_variant_equal (astate_hint, bstate_hint));
547 equal = equal && ((!astate && !bstate) || g_variant_equal (astate, bstate));
550 g_variant_unref (astate_hint);
552 g_variant_unref (bstate_hint);
554 g_variant_unref (astate);
556 g_variant_unref (bstate);
569 stop_loop (gpointer data)
571 GMainLoop *loop = data;
573 g_main_loop_quit (loop);
575 return G_SOURCE_REMOVE;
578 static GActionEntry exported_entries[] = {
579 { "undo", activate_action, NULL, NULL, NULL },
580 { "redo", activate_action, NULL, NULL, NULL },
581 { "cut", activate_action, NULL, NULL, NULL },
582 { "copy", activate_action, NULL, NULL, NULL },
583 { "paste", activate_action, NULL, NULL, NULL },
584 { "bold", activate_toggle, NULL, "true", NULL },
585 { "lang", activate_radio, "s", "'latin'", NULL },
589 list_cb (GObject *source,
593 GDBusConnection *bus = G_DBUS_CONNECTION (source);
594 GMainLoop *loop = user_data;
595 GError *error = NULL;
599 v = g_dbus_connection_call_finish (bus, res, &error);
601 g_variant_get (v, "(^a&s)", &actions);
602 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
605 g_main_loop_quit (loop);
609 call_list (gpointer user_data)
611 GDBusConnection *bus;
613 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
614 g_dbus_connection_call (bus,
615 g_dbus_connection_get_unique_name (bus),
626 g_object_unref (bus);
628 return G_SOURCE_REMOVE;
632 describe_cb (GObject *source,
636 GDBusConnection *bus = G_DBUS_CONNECTION (source);
637 GMainLoop *loop = user_data;
638 GError *error = NULL;
644 v = g_dbus_connection_call_finish (bus, res, &error);
646 /* FIXME: there's an extra level of tuplelization in here */
647 g_variant_get (v, "((bgav))", &enabled, ¶m, &iter);
648 g_assert (enabled == TRUE);
649 g_assert_cmpstr (param, ==, "");
650 g_assert_cmpint (g_variant_iter_n_children (iter), ==, 0);
652 g_variant_iter_free (iter);
655 g_main_loop_quit (loop);
659 call_describe (gpointer user_data)
661 GDBusConnection *bus;
663 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
664 g_dbus_connection_call (bus,
665 g_dbus_connection_get_unique_name (bus),
669 g_variant_new ("(s)", "copy"),
676 g_object_unref (bus);
678 return G_SOURCE_REMOVE;
682 test_dbus_export (void)
684 GDBusConnection *bus;
685 GSimpleActionGroup *group;
686 GDBusActionGroup *proxy;
687 GSimpleAction *action;
689 GError *error = NULL;
694 loop = g_main_loop_new (NULL, FALSE);
697 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
699 group = g_simple_action_group_new ();
700 g_simple_action_group_add_entries (group,
702 G_N_ELEMENTS (exported_entries),
705 id = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &error);
706 g_assert_no_error (error);
708 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
710 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
711 g_assert_cmpint (g_strv_length (actions), ==, 0);
712 g_strfreev (actions);
714 g_timeout_add (100, stop_loop, loop);
715 g_main_loop_run (loop);
717 actions = g_action_group_list_actions (G_ACTION_GROUP (proxy));
718 g_assert_cmpint (g_strv_length (actions), ==, G_N_ELEMENTS (exported_entries));
719 g_strfreev (actions);
721 /* check that calling "List" works too */
722 g_idle_add (call_list, loop);
723 g_main_loop_run (loop);
725 /* check that calling "Describe" works */
726 g_idle_add (call_describe, loop);
727 g_main_loop_run (loop);
729 /* test that the initial transfer works */
730 g_assert (G_IS_DBUS_ACTION_GROUP (proxy));
731 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
733 /* test that various changes get propagated from group to proxy */
734 action = g_simple_action_new_stateful ("italic", NULL, g_variant_new_boolean (FALSE));
735 g_simple_action_group_insert (group, G_ACTION (action));
736 g_object_unref (action);
738 g_timeout_add (100, stop_loop, loop);
739 g_main_loop_run (loop);
741 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
743 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "cut"));
744 g_simple_action_set_enabled (action, FALSE);
746 g_timeout_add (100, stop_loop, loop);
747 g_main_loop_run (loop);
749 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
751 action = G_SIMPLE_ACTION (g_simple_action_group_lookup (group, "bold"));
752 g_simple_action_set_state (action, g_variant_new_boolean (FALSE));
754 g_timeout_add (100, stop_loop, loop);
755 g_main_loop_run (loop);
757 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
759 g_simple_action_group_remove (group, "italic");
761 g_timeout_add (100, stop_loop, loop);
762 g_main_loop_run (loop);
764 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
766 /* test that activations and state changes propagate the other way */
768 g_assert_cmpint (activation_count ("copy"), ==, 0);
769 g_action_group_activate_action (G_ACTION_GROUP (proxy), "copy", NULL);
771 g_timeout_add (100, stop_loop, loop);
772 g_main_loop_run (loop);
774 g_assert_cmpint (activation_count ("copy"), ==, 1);
775 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
777 g_assert_cmpint (activation_count ("bold"), ==, 0);
778 g_action_group_activate_action (G_ACTION_GROUP (proxy), "bold", NULL);
780 g_timeout_add (100, stop_loop, loop);
781 g_main_loop_run (loop);
783 g_assert_cmpint (activation_count ("bold"), ==, 1);
784 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
785 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
786 g_assert (g_variant_get_boolean (v));
789 g_action_group_change_action_state (G_ACTION_GROUP (proxy), "bold", g_variant_new_boolean (FALSE));
791 g_timeout_add (100, stop_loop, loop);
792 g_main_loop_run (loop);
794 g_assert_cmpint (activation_count ("bold"), ==, 1);
795 g_assert (compare_action_groups (G_ACTION_GROUP (group), G_ACTION_GROUP (proxy)));
796 v = g_action_group_get_action_state (G_ACTION_GROUP (group), "bold");
797 g_assert (!g_variant_get_boolean (v));
800 g_dbus_connection_unexport_action_group (bus, id);
802 g_object_unref (proxy);
803 g_object_unref (group);
804 g_main_loop_unref (loop);
805 g_object_unref (bus);
811 do_export (gpointer data)
813 GActionGroup *group = data;
816 GError *error = NULL;
818 GDBusConnection *bus;
822 ctx = g_main_context_new ();
824 g_main_context_push_thread_default (ctx);
826 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
827 path = g_strdup_printf("/%p", data);
829 for (i = 0; i < 100000; i++)
831 id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error);
832 g_assert_no_error (error);
834 action = g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group), "a");
835 g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
836 !g_action_get_enabled (action));
838 g_dbus_connection_unexport_action_group (bus, id);
840 while (g_main_context_iteration (ctx, FALSE));
844 g_object_unref (bus);
846 g_main_context_pop_thread_default (ctx);
848 g_main_context_unref (ctx);
854 test_dbus_threaded (void)
856 GSimpleActionGroup *group[10];
858 static GActionEntry entries[] = {
859 { "a", activate_action, NULL, NULL, NULL },
860 { "b", activate_action, NULL, NULL, NULL },
866 for (i = 0; i < 10; i++)
868 group[i] = g_simple_action_group_new ();
869 g_simple_action_group_add_entries (group[i], entries, G_N_ELEMENTS (entries), NULL);
870 export[i] = g_thread_new ("export", do_export, group[i]);
873 for (i = 0; i < 10; i++)
874 g_thread_join (export[i]);
876 for (i = 0; i < 10; i++)
877 g_object_unref (group[i]);
883 test_bug679509 (void)
885 GDBusConnection *bus;
886 GDBusActionGroup *proxy;
889 loop = g_main_loop_new (NULL, FALSE);
892 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
894 proxy = g_dbus_action_group_get (bus, g_dbus_connection_get_unique_name (bus), "/");
895 g_strfreev (g_action_group_list_actions (G_ACTION_GROUP (proxy)));
896 g_object_unref (proxy);
898 g_timeout_add (100, stop_loop, loop);
899 g_main_loop_run (loop);
901 g_main_loop_unref (loop);
902 g_object_unref (bus);
907 static gchar *state_change_log;
910 state_changed (GActionGroup *group,
911 const gchar *action_name,
917 g_assert (!state_change_log);
919 string = g_string_new (action_name);
920 g_string_append_c (string, ':');
921 g_variant_print_string (value, string, TRUE);
922 state_change_log = g_string_free (string, FALSE);
926 verify_changed (const gchar *log_entry)
928 g_assert_cmpstr (state_change_log, ==, log_entry);
929 g_clear_pointer (&state_change_log, g_free);
933 ensure_state (GSimpleActionGroup *group,
934 const gchar *action_name,
935 const gchar *expected)
940 value = g_action_group_get_action_state (G_ACTION_GROUP (group), action_name);
941 printed = g_variant_print (value, TRUE);
942 g_variant_unref (value);
944 g_assert_cmpstr (printed, ==, expected);
949 test_property_actions (void)
951 GSimpleActionGroup *group;
952 GPropertyAction *action;
953 GSocketClient *client;
956 group = g_simple_action_group_new ();
957 g_signal_connect (group, "action-state-changed", G_CALLBACK (state_changed), NULL);
959 client = g_socket_client_new ();
960 app = g_application_new ("org.gtk.test", 0);
963 action = g_property_action_new ("app-id", app, "application-id");
964 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
965 g_object_unref (action);
968 action = g_property_action_new ("keepalive", app, "inactivity-timeout");
969 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
970 g_object_unref (action);
973 action = g_property_action_new ("tls", client, "tls");
974 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
975 g_object_unref (action);
978 action = g_property_action_new ("type", client, "type");
979 g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
980 g_object_unref (action);
982 /* the objects should be held alive by the actions... */
983 g_object_unref (client);
984 g_object_unref (app);
986 ensure_state (group, "app-id", "'org.gtk.test'");
987 ensure_state (group, "keepalive", "uint32 0");
988 ensure_state (group, "tls", "false");
989 ensure_state (group, "type", "'stream'");
991 verify_changed (NULL);
993 /* some string tests... */
994 g_action_group_change_action_state (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test2"));
995 verify_changed ("app-id:'org.gtk.test2'");
996 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test2");
997 ensure_state (group, "app-id", "'org.gtk.test2'");
999 g_action_group_activate_action (G_ACTION_GROUP (group), "app-id", g_variant_new ("s", "org.gtk.test3"));
1000 verify_changed ("app-id:'org.gtk.test3'");
1001 g_assert_cmpstr (g_application_get_application_id (app), ==, "org.gtk.test3");
1002 ensure_state (group, "app-id", "'org.gtk.test3'");
1004 g_application_set_application_id (app, "org.gtk.test");
1005 verify_changed ("app-id:'org.gtk.test'");
1006 ensure_state (group, "app-id", "'org.gtk.test'");
1009 g_action_group_change_action_state (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 1234));
1010 verify_changed ("keepalive:uint32 1234");
1011 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 1234);
1012 ensure_state (group, "keepalive", "uint32 1234");
1014 g_action_group_activate_action (G_ACTION_GROUP (group), "keepalive", g_variant_new ("u", 5678));
1015 verify_changed ("keepalive:uint32 5678");
1016 g_assert_cmpuint (g_application_get_inactivity_timeout (app), ==, 5678);
1017 ensure_state (group, "keepalive", "uint32 5678");
1019 g_application_set_inactivity_timeout (app, 0);
1020 verify_changed ("keepalive:uint32 0");
1021 ensure_state (group, "keepalive", "uint32 0");
1024 g_action_group_change_action_state (G_ACTION_GROUP (group), "tls", g_variant_new ("b", TRUE));
1025 verify_changed ("tls:true");
1026 g_assert (g_socket_client_get_tls (client));
1027 ensure_state (group, "tls", "true");
1029 /* test toggle true->false */
1030 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1031 verify_changed ("tls:false");
1032 g_assert (!g_socket_client_get_tls (client));
1033 ensure_state (group, "tls", "false");
1035 /* and now back false->true */
1036 g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
1037 verify_changed ("tls:true");
1038 g_assert (g_socket_client_get_tls (client));
1039 ensure_state (group, "tls", "true");
1041 g_socket_client_set_tls (client, FALSE);
1042 verify_changed ("tls:false");
1043 ensure_state (group, "tls", "false");
1046 g_action_group_change_action_state (G_ACTION_GROUP (group), "type", g_variant_new ("s", "datagram"));
1047 verify_changed ("type:'datagram'");
1048 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_DATAGRAM);
1049 ensure_state (group, "type", "'datagram'");
1051 g_action_group_activate_action (G_ACTION_GROUP (group), "type", g_variant_new ("s", "stream"));
1052 verify_changed ("type:'stream'");
1053 g_assert_cmpint (g_socket_client_get_socket_type (client), ==, G_SOCKET_TYPE_STREAM);
1054 ensure_state (group, "type", "'stream'");
1056 g_socket_client_set_socket_type (client, G_SOCKET_TYPE_SEQPACKET);
1057 verify_changed ("type:'seqpacket'");
1058 ensure_state (group, "type", "'seqpacket'");
1060 /* Check some error cases... */
1061 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*non-existent*");
1062 action = g_property_action_new ("foo", app, "xyz");
1063 g_test_assert_expected_messages ();
1064 g_object_unref (action);
1066 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*writable*");
1067 action = g_property_action_new ("foo", app, "is-registered");
1068 g_test_assert_expected_messages ();
1069 g_object_unref (action);
1071 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL, "*type 'GSocketAddress'*");
1072 action = g_property_action_new ("foo", client, "local-address");
1073 g_test_assert_expected_messages ();
1074 g_object_unref (action);
1076 g_object_unref (group);
1080 main (int argc, char **argv)
1082 g_test_init (&argc, &argv, NULL);
1084 g_test_add_func ("/actions/basic", test_basic);
1085 g_test_add_func ("/actions/simplegroup", test_simple_group);
1086 g_test_add_func ("/actions/stateful", test_stateful);
1087 g_test_add_func ("/actions/entries", test_entries);
1088 g_test_add_func ("/actions/parse-detailed", test_parse_detailed);
1089 g_test_add_func ("/actions/dbus/export", test_dbus_export);
1090 g_test_add_func ("/actions/dbus/threaded", test_dbus_threaded);
1091 g_test_add_func ("/actions/property", test_property_actions);
1093 return g_test_run ();