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
);
305 test_default_activate (void)
307 GSimpleAction
*action
;
310 /* Test changing state via activation with parameter */
311 action
= g_simple_action_new_stateful ("foo", G_VARIANT_TYPE_STRING
, g_variant_new_string ("hihi"));
312 g_action_activate (G_ACTION (action
), g_variant_new_string ("bye"));
313 state
= g_action_get_state (G_ACTION (action
));
314 g_assert_cmpstr (g_variant_get_string (state
, NULL
), ==, "bye");
315 g_variant_unref (state
);
316 g_object_unref (action
);
318 /* Test toggling a boolean action via activation with no parameter */
319 action
= g_simple_action_new_stateful ("foo", NULL
, g_variant_new_boolean (FALSE
));
320 g_action_activate (G_ACTION (action
), NULL
);
321 state
= g_action_get_state (G_ACTION (action
));
322 g_assert (g_variant_get_boolean (state
));
323 g_variant_unref (state
);
325 g_action_activate (G_ACTION (action
), NULL
);
326 state
= g_action_get_state (G_ACTION (action
));
327 g_assert (!g_variant_get_boolean (state
));
328 g_variant_unref (state
);
329 g_object_unref (action
);
332 static gboolean foo_activated
= FALSE
;
333 static gboolean bar_activated
= FALSE
;
336 activate_foo (GSimpleAction
*simple
,
340 g_assert (user_data
== GINT_TO_POINTER (123));
341 g_assert (parameter
== NULL
);
342 foo_activated
= TRUE
;
346 activate_bar (GSimpleAction
*simple
,
350 g_assert (user_data
== GINT_TO_POINTER (123));
351 g_assert_cmpstr (g_variant_get_string (parameter
, NULL
), ==, "param");
352 bar_activated
= TRUE
;
356 change_volume_state (GSimpleAction
*action
,
362 requested
= g_variant_get_int32 (value
);
364 /* Volume only goes from 0 to 10 */
365 if (0 <= requested
&& requested
<= 10)
366 g_simple_action_set_state (action
, value
);
369 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
374 const GActionEntry entries
[] = {
375 { "foo", activate_foo
},
376 { "bar", activate_bar
, "s" },
377 { "toggle", NULL
, NULL
, "false" },
378 { "volume", NULL
, NULL
, "0", change_volume_state
}
380 GSimpleActionGroup
*actions
;
383 actions
= g_simple_action_group_new ();
384 g_simple_action_group_add_entries (actions
, entries
,
385 G_N_ELEMENTS (entries
),
386 GINT_TO_POINTER (123));
388 g_assert (!foo_activated
);
389 g_action_group_activate_action (G_ACTION_GROUP (actions
), "foo", NULL
);
390 g_assert (foo_activated
);
391 foo_activated
= FALSE
;
393 g_assert (!bar_activated
);
394 g_action_group_activate_action (G_ACTION_GROUP (actions
), "bar",
395 g_variant_new_string ("param"));
396 g_assert (bar_activated
);
397 g_assert (!foo_activated
);
399 if (g_test_undefined ())
401 const GActionEntry bad_type
= {
402 "bad-type", NULL
, "ss"
404 const GActionEntry bad_state
= {
405 "bad-state", NULL
, NULL
, "flse"
408 g_test_expect_message (G_LOG_DOMAIN
, G_LOG_LEVEL_CRITICAL
,
409 "*not a valid GVariant type string*");
410 g_simple_action_group_add_entries (actions
, &bad_type
, 1, NULL
);
411 g_test_assert_expected_messages ();
413 g_test_expect_message (G_LOG_DOMAIN
, G_LOG_LEVEL_CRITICAL
,
414 "*could not parse*");
415 g_simple_action_group_add_entries (actions
, &bad_state
, 1, NULL
);
416 g_test_assert_expected_messages ();
419 state
= g_action_group_get_action_state (G_ACTION_GROUP (actions
), "volume");
420 g_assert_cmpint (g_variant_get_int32 (state
), ==, 0);
421 g_variant_unref (state
);
424 g_action_group_change_action_state (G_ACTION_GROUP (actions
), "volume",
425 g_variant_new_int32 (7));
426 state
= g_action_group_get_action_state (G_ACTION_GROUP (actions
), "volume");
427 g_assert_cmpint (g_variant_get_int32 (state
), ==, 7);
428 g_variant_unref (state
);
430 /* should not change */
431 g_action_group_change_action_state (G_ACTION_GROUP (actions
), "volume",
432 g_variant_new_int32 (11));
433 state
= g_action_group_get_action_state (G_ACTION_GROUP (actions
), "volume");
434 g_assert_cmpint (g_variant_get_int32 (state
), ==, 7);
435 g_variant_unref (state
);
437 g_object_unref (actions
);
440 G_GNUC_END_IGNORE_DEPRECATIONS
443 test_parse_detailed (void)
446 const gchar
*detailed
;
447 const gchar
*expected_name
;
448 const gchar
*expected_target
;
449 const gchar
*expected_error
;
450 const gchar
*detailed_roundtrip
;
452 { "abc", "abc", NULL
, NULL
, "abc" },
453 { " abc", NULL
, NULL
, "invalid format", NULL
},
454 { " abc", NULL
, NULL
, "invalid format", NULL
},
455 { "abc:", NULL
, NULL
, "invalid format", NULL
},
456 { ":abc", NULL
, NULL
, "invalid format", NULL
},
457 { "abc(", NULL
, NULL
, "invalid format", NULL
},
458 { "abc)", NULL
, NULL
, "invalid format", NULL
},
459 { "(abc", NULL
, NULL
, "invalid format", NULL
},
460 { ")abc", NULL
, NULL
, "invalid format", NULL
},
461 { "abc::xyz", "abc", "'xyz'", NULL
, "abc::xyz" },
462 { "abc('xyz')", "abc", "'xyz'", NULL
, "abc::xyz" },
463 { "abc(42)", "abc", "42", NULL
, "abc(42)" },
464 { "abc(int32 42)", "abc", "42", NULL
, "abc(42)" },
465 { "abc(@i 42)", "abc", "42", NULL
, "abc(42)" },
466 { "abc (42)", NULL
, NULL
, "invalid format", NULL
},
467 { "abc(42abc)", NULL
, NULL
, "invalid character in number", NULL
},
468 { "abc(42, 4)", "abc", "(42, 4)", "expected end of input", NULL
},
469 { "abc(42,)", "abc", "(42,)", "expected end of input", NULL
}
473 for (i
= 0; i
< G_N_ELEMENTS (testcases
); i
++)
475 GError
*error
= NULL
;
480 success
= g_action_parse_detailed_name (testcases
[i
].detailed
, &name
, &target
, &error
);
481 g_assert (success
== (error
== NULL
));
482 if (success
&& testcases
[i
].expected_error
)
483 g_error ("Unexpected success on '%s'. Expected error containing '%s'",
484 testcases
[i
].detailed
, testcases
[i
].expected_error
);
486 if (!success
&& !testcases
[i
].expected_error
)
487 g_error ("Unexpected failure on '%s': %s", testcases
[i
].detailed
, error
->message
);
491 if (!strstr (error
->message
, testcases
[i
].expected_error
))
492 g_error ("Failure message '%s' for string '%s' did not contained expected substring '%s'",
493 error
->message
, testcases
[i
].detailed
, testcases
[i
].expected_error
);
495 g_error_free (error
);
499 g_assert_cmpstr (name
, ==, testcases
[i
].expected_name
);
500 g_assert ((target
== NULL
) == (testcases
[i
].expected_target
== NULL
));
506 detailed
= g_action_print_detailed_name (name
, target
);
507 g_assert_cmpstr (detailed
, ==, testcases
[i
].detailed_roundtrip
);
515 expected
= g_variant_parse (NULL
, testcases
[i
].expected_target
, NULL
, NULL
, NULL
);
518 g_assert (g_variant_equal (expected
, target
));
519 g_variant_unref (expected
);
520 g_variant_unref (target
);
527 GHashTable
*activation_counts
;
530 count_activation (const gchar
*action
)
534 if (activation_counts
== NULL
)
535 activation_counts
= g_hash_table_new (g_str_hash
, g_str_equal
);
536 count
= GPOINTER_TO_INT (g_hash_table_lookup (activation_counts
, action
));
538 g_hash_table_insert (activation_counts
, (gpointer
)action
, GINT_TO_POINTER (count
));
542 activation_count (const gchar
*action
)
544 if (activation_counts
== NULL
)
547 return GPOINTER_TO_INT (g_hash_table_lookup (activation_counts
, action
));
551 activate_action (GSimpleAction
*action
, GVariant
*parameter
, gpointer user_data
)
553 count_activation (g_action_get_name (G_ACTION (action
)));
557 activate_toggle (GSimpleAction
*action
, GVariant
*parameter
, gpointer user_data
)
559 GVariant
*old_state
, *new_state
;
561 count_activation (g_action_get_name (G_ACTION (action
)));
563 old_state
= g_action_get_state (G_ACTION (action
));
564 new_state
= g_variant_new_boolean (!g_variant_get_boolean (old_state
));
565 g_simple_action_set_state (action
, new_state
);
566 g_variant_unref (old_state
);
570 activate_radio (GSimpleAction
*action
, GVariant
*parameter
, gpointer user_data
)
574 count_activation (g_action_get_name (G_ACTION (action
)));
576 new_state
= g_variant_new_string (g_variant_get_string (parameter
, NULL
));
577 g_simple_action_set_state (action
, new_state
);
581 compare_action_groups (GActionGroup
*a
, GActionGroup
*b
)
588 gboolean aenabled
, benabled
;
589 const GVariantType
*aparameter_type
, *bparameter_type
;
590 const GVariantType
*astate_type
, *bstate_type
;
591 GVariant
*astate_hint
, *bstate_hint
;
592 GVariant
*astate
, *bstate
;
594 alist
= g_action_group_list_actions (a
);
595 blist
= g_action_group_list_actions (b
);
596 equal
= strv_strv_cmp (alist
, blist
);
598 for (i
= 0; equal
&& alist
[i
]; i
++)
600 ares
= g_action_group_query_action (a
, alist
[i
], &aenabled
, &aparameter_type
, &astate_type
, &astate_hint
, &astate
);
601 bres
= g_action_group_query_action (b
, alist
[i
], &benabled
, &bparameter_type
, &bstate_type
, &bstate_hint
, &bstate
);
605 equal
= equal
&& (aenabled
== benabled
);
606 equal
= equal
&& ((!aparameter_type
&& !bparameter_type
) || g_variant_type_equal (aparameter_type
, bparameter_type
));
607 equal
= equal
&& ((!astate_type
&& !bstate_type
) || g_variant_type_equal (astate_type
, bstate_type
));
608 equal
= equal
&& ((!astate_hint
&& !bstate_hint
) || g_variant_equal (astate_hint
, bstate_hint
));
609 equal
= equal
&& ((!astate
&& !bstate
) || g_variant_equal (astate
, bstate
));
612 g_variant_unref (astate_hint
);
614 g_variant_unref (bstate_hint
);
616 g_variant_unref (astate
);
618 g_variant_unref (bstate
);
631 stop_loop (gpointer data
)
633 GMainLoop
*loop
= data
;
635 g_main_loop_quit (loop
);
637 return G_SOURCE_REMOVE
;
640 static GActionEntry exported_entries
[] = {
641 { "undo", activate_action
, NULL
, NULL
, NULL
},
642 { "redo", activate_action
, NULL
, NULL
, NULL
},
643 { "cut", activate_action
, NULL
, NULL
, NULL
},
644 { "copy", activate_action
, NULL
, NULL
, NULL
},
645 { "paste", activate_action
, NULL
, NULL
, NULL
},
646 { "bold", activate_toggle
, NULL
, "true", NULL
},
647 { "lang", activate_radio
, "s", "'latin'", NULL
},
651 list_cb (GObject
*source
,
655 GDBusConnection
*bus
= G_DBUS_CONNECTION (source
);
656 GMainLoop
*loop
= user_data
;
657 GError
*error
= NULL
;
661 v
= g_dbus_connection_call_finish (bus
, res
, &error
);
663 g_variant_get (v
, "(^a&s)", &actions
);
664 g_assert_cmpint (g_strv_length (actions
), ==, G_N_ELEMENTS (exported_entries
));
667 g_main_loop_quit (loop
);
671 call_list (gpointer user_data
)
673 GDBusConnection
*bus
;
675 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
676 g_dbus_connection_call (bus
,
677 g_dbus_connection_get_unique_name (bus
),
688 g_object_unref (bus
);
690 return G_SOURCE_REMOVE
;
694 describe_cb (GObject
*source
,
698 GDBusConnection
*bus
= G_DBUS_CONNECTION (source
);
699 GMainLoop
*loop
= user_data
;
700 GError
*error
= NULL
;
706 v
= g_dbus_connection_call_finish (bus
, res
, &error
);
708 /* FIXME: there's an extra level of tuplelization in here */
709 g_variant_get (v
, "((bgav))", &enabled
, ¶m
, &iter
);
710 g_assert (enabled
== TRUE
);
711 g_assert_cmpstr (param
, ==, "");
712 g_assert_cmpint (g_variant_iter_n_children (iter
), ==, 0);
714 g_variant_iter_free (iter
);
717 g_main_loop_quit (loop
);
721 call_describe (gpointer user_data
)
723 GDBusConnection
*bus
;
725 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
726 g_dbus_connection_call (bus
,
727 g_dbus_connection_get_unique_name (bus
),
731 g_variant_new ("(s)", "copy"),
738 g_object_unref (bus
);
740 return G_SOURCE_REMOVE
;
743 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
746 test_dbus_export (void)
748 GDBusConnection
*bus
;
749 GSimpleActionGroup
*group
;
750 GDBusActionGroup
*proxy
;
751 GSimpleAction
*action
;
753 GError
*error
= NULL
;
758 loop
= g_main_loop_new (NULL
, FALSE
);
761 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
763 group
= g_simple_action_group_new ();
764 g_simple_action_group_add_entries (group
,
766 G_N_ELEMENTS (exported_entries
),
769 id
= g_dbus_connection_export_action_group (bus
, "/", G_ACTION_GROUP (group
), &error
);
770 g_assert_no_error (error
);
772 proxy
= g_dbus_action_group_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
774 actions
= g_action_group_list_actions (G_ACTION_GROUP (proxy
));
775 g_assert_cmpint (g_strv_length (actions
), ==, 0);
776 g_strfreev (actions
);
778 g_timeout_add (100, stop_loop
, loop
);
779 g_main_loop_run (loop
);
781 actions
= g_action_group_list_actions (G_ACTION_GROUP (proxy
));
782 g_assert_cmpint (g_strv_length (actions
), ==, G_N_ELEMENTS (exported_entries
));
783 g_strfreev (actions
);
785 /* check that calling "List" works too */
786 g_idle_add (call_list
, loop
);
787 g_main_loop_run (loop
);
789 /* check that calling "Describe" works */
790 g_idle_add (call_describe
, loop
);
791 g_main_loop_run (loop
);
793 /* test that the initial transfer works */
794 g_assert (G_IS_DBUS_ACTION_GROUP (proxy
));
795 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
797 /* test that various changes get propagated from group to proxy */
798 action
= g_simple_action_new_stateful ("italic", NULL
, g_variant_new_boolean (FALSE
));
799 g_simple_action_group_insert (group
, G_ACTION (action
));
800 g_object_unref (action
);
802 g_timeout_add (100, stop_loop
, loop
);
803 g_main_loop_run (loop
);
805 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
807 action
= G_SIMPLE_ACTION (g_simple_action_group_lookup (group
, "cut"));
808 g_simple_action_set_enabled (action
, FALSE
);
810 g_timeout_add (100, stop_loop
, loop
);
811 g_main_loop_run (loop
);
813 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
815 action
= G_SIMPLE_ACTION (g_simple_action_group_lookup (group
, "bold"));
816 g_simple_action_set_state (action
, g_variant_new_boolean (FALSE
));
818 g_timeout_add (100, stop_loop
, loop
);
819 g_main_loop_run (loop
);
821 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
823 g_simple_action_group_remove (group
, "italic");
825 g_timeout_add (100, stop_loop
, loop
);
826 g_main_loop_run (loop
);
828 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
830 /* test that activations and state changes propagate the other way */
832 g_assert_cmpint (activation_count ("copy"), ==, 0);
833 g_action_group_activate_action (G_ACTION_GROUP (proxy
), "copy", NULL
);
835 g_timeout_add (100, stop_loop
, loop
);
836 g_main_loop_run (loop
);
838 g_assert_cmpint (activation_count ("copy"), ==, 1);
839 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
841 g_assert_cmpint (activation_count ("bold"), ==, 0);
842 g_action_group_activate_action (G_ACTION_GROUP (proxy
), "bold", NULL
);
844 g_timeout_add (100, stop_loop
, loop
);
845 g_main_loop_run (loop
);
847 g_assert_cmpint (activation_count ("bold"), ==, 1);
848 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
849 v
= g_action_group_get_action_state (G_ACTION_GROUP (group
), "bold");
850 g_assert (g_variant_get_boolean (v
));
853 g_action_group_change_action_state (G_ACTION_GROUP (proxy
), "bold", g_variant_new_boolean (FALSE
));
855 g_timeout_add (100, stop_loop
, loop
);
856 g_main_loop_run (loop
);
858 g_assert_cmpint (activation_count ("bold"), ==, 1);
859 g_assert (compare_action_groups (G_ACTION_GROUP (group
), G_ACTION_GROUP (proxy
)));
860 v
= g_action_group_get_action_state (G_ACTION_GROUP (group
), "bold");
861 g_assert (!g_variant_get_boolean (v
));
864 g_dbus_connection_unexport_action_group (bus
, id
);
866 g_object_unref (proxy
);
867 g_object_unref (group
);
868 g_main_loop_unref (loop
);
869 g_object_unref (bus
);
875 do_export (gpointer data
)
877 GActionGroup
*group
= data
;
880 GError
*error
= NULL
;
882 GDBusConnection
*bus
;
886 ctx
= g_main_context_new ();
888 g_main_context_push_thread_default (ctx
);
890 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
891 path
= g_strdup_printf("/%p", data
);
893 for (i
= 0; i
< 100000; i
++)
895 id
= g_dbus_connection_export_action_group (bus
, path
, G_ACTION_GROUP (group
), &error
);
896 g_assert_no_error (error
);
898 action
= g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group
), "a");
899 g_simple_action_set_enabled (G_SIMPLE_ACTION (action
),
900 !g_action_get_enabled (action
));
902 g_dbus_connection_unexport_action_group (bus
, id
);
904 while (g_main_context_iteration (ctx
, FALSE
));
908 g_object_unref (bus
);
910 g_main_context_pop_thread_default (ctx
);
912 g_main_context_unref (ctx
);
918 test_dbus_threaded (void)
920 GSimpleActionGroup
*group
[10];
922 static GActionEntry entries
[] = {
923 { "a", activate_action
, NULL
, NULL
, NULL
},
924 { "b", activate_action
, NULL
, NULL
, NULL
},
930 for (i
= 0; i
< 10; i
++)
932 group
[i
] = g_simple_action_group_new ();
933 g_simple_action_group_add_entries (group
[i
], entries
, G_N_ELEMENTS (entries
), NULL
);
934 export
[i
] = g_thread_new ("export", do_export
, group
[i
]);
937 for (i
= 0; i
< 10; i
++)
938 g_thread_join (export
[i
]);
940 for (i
= 0; i
< 10; i
++)
941 g_object_unref (group
[i
]);
946 G_GNUC_END_IGNORE_DEPRECATIONS
949 test_bug679509 (void)
951 GDBusConnection
*bus
;
952 GDBusActionGroup
*proxy
;
955 loop
= g_main_loop_new (NULL
, FALSE
);
958 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
960 proxy
= g_dbus_action_group_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
961 g_strfreev (g_action_group_list_actions (G_ACTION_GROUP (proxy
)));
962 g_object_unref (proxy
);
964 g_timeout_add (100, stop_loop
, loop
);
965 g_main_loop_run (loop
);
967 g_main_loop_unref (loop
);
968 g_object_unref (bus
);
973 static gchar
*state_change_log
;
976 state_changed (GActionGroup
*group
,
977 const gchar
*action_name
,
983 g_assert (!state_change_log
);
985 string
= g_string_new (action_name
);
986 g_string_append_c (string
, ':');
987 g_variant_print_string (value
, string
, TRUE
);
988 state_change_log
= g_string_free (string
, FALSE
);
992 verify_changed (const gchar
*log_entry
)
994 g_assert_cmpstr (state_change_log
, ==, log_entry
);
995 g_clear_pointer (&state_change_log
, g_free
);
999 ensure_state (GSimpleActionGroup
*group
,
1000 const gchar
*action_name
,
1001 const gchar
*expected
)
1006 value
= g_action_group_get_action_state (G_ACTION_GROUP (group
), action_name
);
1007 printed
= g_variant_print (value
, TRUE
);
1008 g_variant_unref (value
);
1010 g_assert_cmpstr (printed
, ==, expected
);
1015 test_property_actions (void)
1017 GSimpleActionGroup
*group
;
1018 GPropertyAction
*action
;
1019 GSocketClient
*client
;
1022 GVariantType
*ptype
, *stype
;
1026 group
= g_simple_action_group_new ();
1027 g_signal_connect (group
, "action-state-changed", G_CALLBACK (state_changed
), NULL
);
1029 client
= g_socket_client_new ();
1030 app
= g_application_new ("org.gtk.test", 0);
1033 action
= g_property_action_new ("app-id", app
, "application-id");
1034 g_action_map_add_action (G_ACTION_MAP (group
), G_ACTION (action
));
1035 g_object_unref (action
);
1038 action
= g_property_action_new ("keepalive", app
, "inactivity-timeout");
1039 g_object_get (action
, "name", &name
, "parameter-type", &ptype
, "enabled", &enabled
, "state-type", &stype
, "state", &state
, NULL
);
1040 g_assert_cmpstr (name
, ==, "keepalive");
1043 g_variant_unref (state
);
1045 g_action_map_add_action (G_ACTION_MAP (group
), G_ACTION (action
));
1046 g_object_unref (action
);
1049 action
= g_property_action_new ("tls", client
, "tls");
1050 g_action_map_add_action (G_ACTION_MAP (group
), G_ACTION (action
));
1051 g_object_unref (action
);
1054 action
= g_object_new (G_TYPE_PROPERTY_ACTION
,
1055 "name", "disable-proxy",
1057 "property-name", "enable-proxy",
1058 "invert-boolean", TRUE
,
1060 g_action_map_add_action (G_ACTION_MAP (group
), G_ACTION (action
));
1061 g_object_unref (action
);
1064 action
= g_property_action_new ("type", client
, "type");
1065 g_action_map_add_action (G_ACTION_MAP (group
), G_ACTION (action
));
1066 g_object_unref (action
);
1068 /* the objects should be held alive by the actions... */
1069 g_object_unref (client
);
1070 g_object_unref (app
);
1072 ensure_state (group
, "app-id", "'org.gtk.test'");
1073 ensure_state (group
, "keepalive", "uint32 0");
1074 ensure_state (group
, "tls", "false");
1075 ensure_state (group
, "disable-proxy", "false");
1076 ensure_state (group
, "type", "'stream'");
1078 verify_changed (NULL
);
1080 /* some string tests... */
1081 g_action_group_change_action_state (G_ACTION_GROUP (group
), "app-id", g_variant_new ("s", "org.gtk.test2"));
1082 verify_changed ("app-id:'org.gtk.test2'");
1083 g_assert_cmpstr (g_application_get_application_id (app
), ==, "org.gtk.test2");
1084 ensure_state (group
, "app-id", "'org.gtk.test2'");
1086 g_action_group_activate_action (G_ACTION_GROUP (group
), "app-id", g_variant_new ("s", "org.gtk.test3"));
1087 verify_changed ("app-id:'org.gtk.test3'");
1088 g_assert_cmpstr (g_application_get_application_id (app
), ==, "org.gtk.test3");
1089 ensure_state (group
, "app-id", "'org.gtk.test3'");
1091 g_application_set_application_id (app
, "org.gtk.test");
1092 verify_changed ("app-id:'org.gtk.test'");
1093 ensure_state (group
, "app-id", "'org.gtk.test'");
1096 g_action_group_change_action_state (G_ACTION_GROUP (group
), "keepalive", g_variant_new ("u", 1234));
1097 verify_changed ("keepalive:uint32 1234");
1098 g_assert_cmpuint (g_application_get_inactivity_timeout (app
), ==, 1234);
1099 ensure_state (group
, "keepalive", "uint32 1234");
1101 g_action_group_activate_action (G_ACTION_GROUP (group
), "keepalive", g_variant_new ("u", 5678));
1102 verify_changed ("keepalive:uint32 5678");
1103 g_assert_cmpuint (g_application_get_inactivity_timeout (app
), ==, 5678);
1104 ensure_state (group
, "keepalive", "uint32 5678");
1106 g_application_set_inactivity_timeout (app
, 0);
1107 verify_changed ("keepalive:uint32 0");
1108 ensure_state (group
, "keepalive", "uint32 0");
1111 g_action_group_change_action_state (G_ACTION_GROUP (group
), "tls", g_variant_new ("b", TRUE
));
1112 verify_changed ("tls:true");
1113 g_assert (g_socket_client_get_tls (client
));
1114 ensure_state (group
, "tls", "true");
1116 g_action_group_change_action_state (G_ACTION_GROUP (group
), "disable-proxy", g_variant_new ("b", TRUE
));
1117 verify_changed ("disable-proxy:true");
1118 ensure_state (group
, "disable-proxy", "true");
1119 g_assert (!g_socket_client_get_enable_proxy (client
));
1121 /* test toggle true->false */
1122 g_action_group_activate_action (G_ACTION_GROUP (group
), "tls", NULL
);
1123 verify_changed ("tls:false");
1124 g_assert (!g_socket_client_get_tls (client
));
1125 ensure_state (group
, "tls", "false");
1127 /* and now back false->true */
1128 g_action_group_activate_action (G_ACTION_GROUP (group
), "tls", NULL
);
1129 verify_changed ("tls:true");
1130 g_assert (g_socket_client_get_tls (client
));
1131 ensure_state (group
, "tls", "true");
1133 g_socket_client_set_tls (client
, FALSE
);
1134 verify_changed ("tls:false");
1135 ensure_state (group
, "tls", "false");
1137 /* now do the same for the inverted action */
1138 g_action_group_activate_action (G_ACTION_GROUP (group
), "disable-proxy", NULL
);
1139 verify_changed ("disable-proxy:false");
1140 g_assert (g_socket_client_get_enable_proxy (client
));
1141 ensure_state (group
, "disable-proxy", "false");
1143 g_action_group_activate_action (G_ACTION_GROUP (group
), "disable-proxy", NULL
);
1144 verify_changed ("disable-proxy:true");
1145 g_assert (!g_socket_client_get_enable_proxy (client
));
1146 ensure_state (group
, "disable-proxy", "true");
1148 g_socket_client_set_enable_proxy (client
, TRUE
);
1149 verify_changed ("disable-proxy:false");
1150 ensure_state (group
, "disable-proxy", "false");
1153 g_action_group_change_action_state (G_ACTION_GROUP (group
), "type", g_variant_new ("s", "datagram"));
1154 verify_changed ("type:'datagram'");
1155 g_assert_cmpint (g_socket_client_get_socket_type (client
), ==, G_SOCKET_TYPE_DATAGRAM
);
1156 ensure_state (group
, "type", "'datagram'");
1158 g_action_group_activate_action (G_ACTION_GROUP (group
), "type", g_variant_new ("s", "stream"));
1159 verify_changed ("type:'stream'");
1160 g_assert_cmpint (g_socket_client_get_socket_type (client
), ==, G_SOCKET_TYPE_STREAM
);
1161 ensure_state (group
, "type", "'stream'");
1163 g_socket_client_set_socket_type (client
, G_SOCKET_TYPE_SEQPACKET
);
1164 verify_changed ("type:'seqpacket'");
1165 ensure_state (group
, "type", "'seqpacket'");
1167 /* Check some error cases... */
1168 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL
, "*non-existent*");
1169 action
= g_property_action_new ("foo", app
, "xyz");
1170 g_test_assert_expected_messages ();
1171 g_object_unref (action
);
1173 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL
, "*writable*");
1174 action
= g_property_action_new ("foo", app
, "is-registered");
1175 g_test_assert_expected_messages ();
1176 g_object_unref (action
);
1178 g_test_expect_message ("GLib-GIO", G_LOG_LEVEL_CRITICAL
, "*type 'GSocketAddress'*");
1179 action
= g_property_action_new ("foo", client
, "local-address");
1180 g_test_assert_expected_messages ();
1181 g_object_unref (action
);
1183 g_object_unref (group
);
1187 main (int argc
, char **argv
)
1189 g_test_init (&argc
, &argv
, NULL
);
1191 g_test_add_func ("/actions/basic", test_basic
);
1192 g_test_add_func ("/actions/name", test_name
);
1193 g_test_add_func ("/actions/simplegroup", test_simple_group
);
1194 g_test_add_func ("/actions/stateful", test_stateful
);
1195 g_test_add_func ("/actions/default-activate", test_default_activate
);
1196 g_test_add_func ("/actions/entries", test_entries
);
1197 g_test_add_func ("/actions/parse-detailed", test_parse_detailed
);
1198 g_test_add_func ("/actions/dbus/export", test_dbus_export
);
1199 g_test_add_func ("/actions/dbus/threaded", test_dbus_threaded
);
1200 g_test_add_func ("/actions/dbus/bug679509", test_bug679509
);
1201 g_test_add_func ("/actions/property", test_property_actions
);
1203 return g_test_run ();