3 #include "gdbus-sessionbus.h"
5 /* Markup printing {{{1 */
7 /* This used to be part of GLib, but it was removed before the stable
8 * release because it wasn't generally useful. We want it here, though.
11 indent_string (GString
*string
,
15 g_string_append_c (string
, ' ');
19 g_menu_markup_print_string (GString
*string
,
24 gboolean need_nl
= FALSE
;
27 if G_UNLIKELY (string
== NULL
)
28 string
= g_string_new (NULL
);
30 n
= g_menu_model_get_n_items (model
);
32 for (i
= 0; i
< n
; i
++)
34 GMenuAttributeIter
*attr_iter
;
35 GMenuLinkIter
*link_iter
;
39 attr_iter
= g_menu_model_iterate_item_attributes (model
, i
);
40 link_iter
= g_menu_model_iterate_item_links (model
, i
);
41 contents
= g_string_new (NULL
);
42 attrs
= g_string_new (NULL
);
44 while (g_menu_attribute_iter_next (attr_iter
))
46 const char *name
= g_menu_attribute_iter_get_name (attr_iter
);
47 GVariant
*value
= g_menu_attribute_iter_get_value (attr_iter
);
49 if (g_variant_is_of_type (value
, G_VARIANT_TYPE_STRING
))
52 str
= g_markup_printf_escaped (" %s='%s'", name
, g_variant_get_string (value
, NULL
));
53 g_string_append (attrs
, str
);
63 printed
= g_variant_print (value
, TRUE
);
64 type
= g_variant_type_peek_string (g_variant_get_type (value
));
65 str
= g_markup_printf_escaped ("<attribute name='%s' type='%s'>%s</attribute>\n", name
, type
, printed
);
66 indent_string (contents
, indent
+ tabstop
);
67 g_string_append (contents
, str
);
72 g_variant_unref (value
);
74 g_object_unref (attr_iter
);
76 while (g_menu_link_iter_next (link_iter
))
78 const gchar
*name
= g_menu_link_iter_get_name (link_iter
);
79 GMenuModel
*menu
= g_menu_link_iter_get_value (link_iter
);
83 g_string_append_c (contents
, '\n');
85 str
= g_markup_printf_escaped ("<link name='%s'>\n", name
);
86 indent_string (contents
, indent
+ tabstop
);
87 g_string_append (contents
, str
);
90 g_menu_markup_print_string (contents
, menu
, indent
+ 2 * tabstop
, tabstop
);
92 indent_string (contents
, indent
+ tabstop
);
93 g_string_append (contents
, "</link>\n");
94 g_object_unref (menu
);
96 g_object_unref (link_iter
);
100 indent_string (string
, indent
);
101 g_string_append_printf (string
, "<item%s>\n", attrs
->str
);
102 g_string_append (string
, contents
->str
);
103 indent_string (string
, indent
);
104 g_string_append (string
, "</item>\n");
111 g_string_append_c (string
, '\n');
113 indent_string (string
, indent
);
114 g_string_append_printf (string
, "<item%s/>\n", attrs
->str
);
118 g_string_free (contents
, TRUE
);
119 g_string_free (attrs
, TRUE
);
127 /* This utility struct is used by both the RandomMenu and MirrorMenu
128 * class implementations below.
131 GHashTable
*attributes
;
136 test_item_new (GHashTable
*attributes
,
141 item
= g_slice_new (TestItem
);
142 item
->attributes
= g_hash_table_ref (attributes
);
143 item
->links
= g_hash_table_ref (links
);
149 test_item_free (gpointer data
)
151 TestItem
*item
= data
;
153 g_hash_table_unref (item
->attributes
);
154 g_hash_table_unref (item
->links
);
156 g_slice_free (TestItem
, item
);
159 /* RandomMenu {{{1 */
164 GMenuModel parent_instance
;
170 typedef GMenuModelClass RandomMenuClass
;
172 static GType
random_menu_get_type (void);
173 G_DEFINE_TYPE (RandomMenu
, random_menu
, G_TYPE_MENU_MODEL
);
176 random_menu_is_mutable (GMenuModel
*model
)
182 random_menu_get_n_items (GMenuModel
*model
)
184 RandomMenu
*menu
= (RandomMenu
*) model
;
186 return g_sequence_get_length (menu
->items
);
190 random_menu_get_item_attributes (GMenuModel
*model
,
194 RandomMenu
*menu
= (RandomMenu
*) model
;
197 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
198 *table
= g_hash_table_ref (item
->attributes
);
202 random_menu_get_item_links (GMenuModel
*model
,
206 RandomMenu
*menu
= (RandomMenu
*) model
;
209 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
210 *table
= g_hash_table_ref (item
->links
);
214 random_menu_finalize (GObject
*object
)
216 RandomMenu
*menu
= (RandomMenu
*) object
;
218 g_sequence_free (menu
->items
);
220 G_OBJECT_CLASS (random_menu_parent_class
)
225 random_menu_init (RandomMenu
*menu
)
230 random_menu_class_init (GMenuModelClass
*class)
232 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
234 class->is_mutable
= random_menu_is_mutable
;
235 class->get_n_items
= random_menu_get_n_items
;
236 class->get_item_attributes
= random_menu_get_item_attributes
;
237 class->get_item_links
= random_menu_get_item_links
;
239 object_class
->finalize
= random_menu_finalize
;
242 static RandomMenu
* random_menu_new (GRand
*rand
, gint order
);
245 random_menu_change (RandomMenu
*menu
,
248 gint position
, removes
, adds
;
249 GSequenceIter
*point
;
253 n_items
= g_sequence_get_length (menu
->items
);
257 position
= g_rand_int_range (rand
, 0, n_items
+ 1);
258 removes
= g_rand_int_range (rand
, 0, n_items
- position
+ 1);
259 adds
= g_rand_int_range (rand
, 0, MAX_ITEMS
- (n_items
- removes
) + 1);
261 while (removes
== 0 && adds
== 0);
263 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removes
);
267 GSequenceIter
*start
;
269 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
270 g_sequence_remove_range (start
, point
);
273 for (i
= 0; i
< adds
; i
++)
277 GHashTable
*attributes
;
279 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
280 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
282 if (menu
->order
> 0 && g_rand_boolean (rand
))
285 const gchar
*subtype
;
287 child
= random_menu_new (rand
, menu
->order
- 1);
289 if (g_rand_boolean (rand
))
291 subtype
= G_MENU_LINK_SECTION
;
292 /* label some section headers */
293 if (g_rand_boolean (rand
))
300 /* label all submenus */
301 subtype
= G_MENU_LINK_SUBMENU
;
305 g_hash_table_insert (links
, g_strdup (subtype
), child
);
308 /* label all terminals */
312 g_hash_table_insert (attributes
, g_strdup ("label"), g_variant_ref_sink (g_variant_new_string (label
)));
314 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
315 g_hash_table_unref (links
);
316 g_hash_table_unref (attributes
);
319 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removes
, adds
);
323 random_menu_new (GRand
*rand
,
328 menu
= g_object_new (random_menu_get_type (), NULL
);
329 menu
->items
= g_sequence_new (test_item_free
);
332 random_menu_change (menu
, rand
);
337 /* MirrorMenu {{{1 */
339 GMenuModel parent_instance
;
341 GMenuModel
*clone_of
;
346 typedef GMenuModelClass MirrorMenuClass
;
348 static GType
mirror_menu_get_type (void);
349 G_DEFINE_TYPE (MirrorMenu
, mirror_menu
, G_TYPE_MENU_MODEL
);
352 mirror_menu_is_mutable (GMenuModel
*model
)
354 MirrorMenu
*menu
= (MirrorMenu
*) model
;
356 return menu
->handler_id
!= 0;
360 mirror_menu_get_n_items (GMenuModel
*model
)
362 MirrorMenu
*menu
= (MirrorMenu
*) model
;
364 return g_sequence_get_length (menu
->items
);
368 mirror_menu_get_item_attributes (GMenuModel
*model
,
372 MirrorMenu
*menu
= (MirrorMenu
*) model
;
375 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
376 *table
= g_hash_table_ref (item
->attributes
);
380 mirror_menu_get_item_links (GMenuModel
*model
,
384 MirrorMenu
*menu
= (MirrorMenu
*) model
;
387 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
388 *table
= g_hash_table_ref (item
->links
);
392 mirror_menu_finalize (GObject
*object
)
394 MirrorMenu
*menu
= (MirrorMenu
*) object
;
396 if (menu
->handler_id
)
397 g_signal_handler_disconnect (menu
->clone_of
, menu
->handler_id
);
399 g_sequence_free (menu
->items
);
400 g_object_unref (menu
->clone_of
);
402 G_OBJECT_CLASS (mirror_menu_parent_class
)
407 mirror_menu_init (MirrorMenu
*menu
)
412 mirror_menu_class_init (GMenuModelClass
*class)
414 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
416 class->is_mutable
= mirror_menu_is_mutable
;
417 class->get_n_items
= mirror_menu_get_n_items
;
418 class->get_item_attributes
= mirror_menu_get_item_attributes
;
419 class->get_item_links
= mirror_menu_get_item_links
;
421 object_class
->finalize
= mirror_menu_finalize
;
424 static MirrorMenu
* mirror_menu_new (GMenuModel
*clone_of
);
427 mirror_menu_changed (GMenuModel
*model
,
433 MirrorMenu
*menu
= user_data
;
434 GSequenceIter
*point
;
437 g_assert (model
== menu
->clone_of
);
439 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removed
);
443 GSequenceIter
*start
;
445 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
446 g_sequence_remove_range (start
, point
);
449 for (i
= position
; i
< position
+ added
; i
++)
451 GMenuAttributeIter
*attr_iter
;
452 GMenuLinkIter
*link_iter
;
454 GHashTable
*attributes
;
459 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
460 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
462 attr_iter
= g_menu_model_iterate_item_attributes (model
, i
);
463 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &value
))
465 g_hash_table_insert (attributes
, g_strdup (name
), value
);
467 g_object_unref (attr_iter
);
469 link_iter
= g_menu_model_iterate_item_links (model
, i
);
470 while (g_menu_link_iter_get_next (link_iter
, &name
, &child
))
472 g_hash_table_insert (links
, g_strdup (name
), mirror_menu_new (child
));
473 g_object_unref (child
);
475 g_object_unref (link_iter
);
477 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
478 g_hash_table_unref (attributes
);
479 g_hash_table_unref (links
);
482 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removed
, added
);
486 mirror_menu_new (GMenuModel
*clone_of
)
490 menu
= g_object_new (mirror_menu_get_type (), NULL
);
491 menu
->items
= g_sequence_new (test_item_free
);
492 menu
->clone_of
= g_object_ref (clone_of
);
494 if (g_menu_model_is_mutable (clone_of
))
495 menu
->handler_id
= g_signal_connect (clone_of
, "items-changed", G_CALLBACK (mirror_menu_changed
), menu
);
496 mirror_menu_changed (clone_of
, 0, 0, g_menu_model_get_n_items (clone_of
), menu
);
501 /* check_menus_equal(), assert_menus_equal() {{{1 */
503 check_menus_equal (GMenuModel
*a
,
506 gboolean equal
= TRUE
;
510 a_n
= g_menu_model_get_n_items (a
);
511 b_n
= g_menu_model_get_n_items (b
);
516 for (i
= 0; i
< a_n
; i
++)
518 GMenuAttributeIter
*attr_iter
;
519 GVariant
*a_value
, *b_value
;
520 GMenuLinkIter
*link_iter
;
521 GMenuModel
*a_menu
, *b_menu
;
524 attr_iter
= g_menu_model_iterate_item_attributes (a
, i
);
525 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &a_value
))
527 b_value
= g_menu_model_get_item_attribute_value (b
, i
, name
, NULL
);
528 equal
&= b_value
&& g_variant_equal (a_value
, b_value
);
530 g_variant_unref (b_value
);
531 g_variant_unref (a_value
);
533 g_object_unref (attr_iter
);
535 attr_iter
= g_menu_model_iterate_item_attributes (b
, i
);
536 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &b_value
))
538 a_value
= g_menu_model_get_item_attribute_value (a
, i
, name
, NULL
);
539 equal
&= a_value
&& g_variant_equal (a_value
, b_value
);
541 g_variant_unref (a_value
);
542 g_variant_unref (b_value
);
544 g_object_unref (attr_iter
);
546 link_iter
= g_menu_model_iterate_item_links (a
, i
);
547 while (g_menu_link_iter_get_next (link_iter
, &name
, &a_menu
))
549 b_menu
= g_menu_model_get_item_link (b
, i
, name
);
550 equal
&= b_menu
&& check_menus_equal (a_menu
, b_menu
);
552 g_object_unref (b_menu
);
553 g_object_unref (a_menu
);
555 g_object_unref (link_iter
);
557 link_iter
= g_menu_model_iterate_item_links (b
, i
);
558 while (g_menu_link_iter_get_next (link_iter
, &name
, &b_menu
))
560 a_menu
= g_menu_model_get_item_link (a
, i
, name
);
561 equal
&= a_menu
&& check_menus_equal (a_menu
, b_menu
);
563 g_object_unref (a_menu
);
564 g_object_unref (b_menu
);
566 g_object_unref (link_iter
);
573 assert_menus_equal (GMenuModel
*a
,
576 if (!check_menus_equal (a
, b
))
580 string
= g_string_new ("\n <a>\n");
581 g_menu_markup_print_string (string
, G_MENU_MODEL (a
), 4, 2);
582 g_string_append (string
, " </a>\n\n-------------\n <b>\n");
583 g_menu_markup_print_string (string
, G_MENU_MODEL (b
), 4, 2);
584 g_string_append (string
, " </b>\n");
585 g_error ("%s", string
->str
);
590 assert_menuitem_equal (GMenuItem
*item
,
594 GMenuAttributeIter
*attr_iter
;
595 GMenuLinkIter
*link_iter
;
598 GMenuModel
*linked_model
;
600 /* NOTE we can't yet test whether item has attributes or links that
601 * are not in the model, because there's no iterator API for menu
604 attr_iter
= g_menu_model_iterate_item_attributes (model
, index
);
605 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &value
))
607 GVariant
*item_value
;
609 item_value
= g_menu_item_get_attribute_value (item
, name
, g_variant_get_type (value
));
610 g_assert (item_value
&& g_variant_equal (item_value
, value
));
612 g_variant_unref (item_value
);
613 g_variant_unref (value
);
616 link_iter
= g_menu_model_iterate_item_links (model
, index
);
617 while (g_menu_link_iter_get_next (link_iter
, &name
, &linked_model
))
619 GMenuModel
*item_linked_model
;
621 item_linked_model
= g_menu_item_get_link (item
, name
);
622 g_assert (linked_model
== item_linked_model
);
624 g_object_unref (item_linked_model
);
625 g_object_unref (linked_model
);
628 g_object_unref (attr_iter
);
629 g_object_unref (link_iter
);
632 /* Test cases {{{1 */
636 GRand
*randa
, *randb
;
640 seed
= g_test_rand_int ();
642 randa
= g_rand_new_with_seed (seed
);
643 randb
= g_rand_new_with_seed (seed
);
645 for (i
= 0; i
< 500; i
++)
649 a
= random_menu_new (randa
, TOP_ORDER
);
650 b
= random_menu_new (randb
, TOP_ORDER
);
651 assert_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
));
658 for (i
= 0; i
< 500;)
662 a
= random_menu_new (randa
, TOP_ORDER
);
663 b
= random_menu_new (randb
, TOP_ORDER
);
664 if (check_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
)))
666 /* by chance, they may really be equal. double check. */
669 as
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (a
), 4, 2);
670 bs
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (b
), 4, 2);
671 g_assert_cmpstr (as
->str
, ==, bs
->str
);
672 g_string_free (bs
, TRUE
);
673 g_string_free (as
, TRUE
);
675 /* we're here because randa and randb just generated equal
676 * menus. they may do it again, so throw away randb and make
680 randb
= g_rand_new_with_seed (g_rand_int (randa
));
683 /* make sure we get enough unequals (ie: no GRand failure) */
702 rand
= g_rand_new_with_seed (g_test_rand_int ());
703 random
= random_menu_new (rand
, TOP_ORDER
);
704 mirror
= mirror_menu_new (G_MENU_MODEL (random
));
706 for (i
= 0; i
< 500; i
++)
708 assert_menus_equal (G_MENU_MODEL (random
), G_MENU_MODEL (mirror
));
709 random_menu_change (random
, rand
);
712 g_object_unref (mirror
);
713 g_object_unref (random
);
718 struct roundtrip_state
721 MirrorMenu
*proxy_mirror
;
722 GDBusMenuModel
*proxy
;
730 roundtrip_step (gpointer data
)
732 struct roundtrip_state
*state
= data
;
734 if (check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
)) &&
735 check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy_mirror
)))
740 if (state
->success
< 100)
741 random_menu_change (state
->random
, state
->rand
);
743 g_main_loop_quit (state
->loop
);
745 else if (state
->count
== 100)
747 assert_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
));
748 g_assert_not_reached ();
753 return G_SOURCE_CONTINUE
;
757 test_dbus_roundtrip (void)
759 struct roundtrip_state state
;
760 GDBusConnection
*bus
;
764 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
766 state
.rand
= g_rand_new_with_seed (g_test_rand_int ());
768 state
.random
= random_menu_new (state
.rand
, 2);
769 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (state
.random
), NULL
);
770 state
.proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
771 state
.proxy_mirror
= mirror_menu_new (G_MENU_MODEL (state
.proxy
));
775 id
= g_timeout_add (10, roundtrip_step
, &state
);
777 state
.loop
= g_main_loop_new (NULL
, FALSE
);
778 g_main_loop_run (state
.loop
);
780 g_main_loop_unref (state
.loop
);
781 g_source_remove (id
);
782 g_object_unref (state
.proxy
);
783 g_dbus_connection_unexport_menu_model (bus
, export_id
);
784 g_object_unref (state
.random
);
785 g_object_unref (state
.proxy_mirror
);
786 g_rand_free (state
.rand
);
787 g_object_unref (bus
);
790 static gint items_changed_count
;
793 items_changed (GMenuModel
*model
,
799 items_changed_count
++;
803 stop_loop (gpointer data
)
805 GMainLoop
*loop
= data
;
807 g_main_loop_quit (loop
);
809 return G_SOURCE_REMOVE
;
813 test_dbus_subscriptions (void)
815 GDBusConnection
*bus
;
817 GDBusMenuModel
*proxy
;
819 GError
*error
= NULL
;
822 loop
= g_main_loop_new (NULL
, FALSE
);
824 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
826 menu
= g_menu_new ();
828 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (menu
), &error
);
829 g_assert_no_error (error
);
831 proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
832 items_changed_count
= 0;
833 g_signal_connect (proxy
, "items-changed",
834 G_CALLBACK (items_changed
), NULL
);
836 g_menu_append (menu
, "item1", NULL
);
837 g_menu_append (menu
, "item2", NULL
);
838 g_menu_append (menu
, "item3", NULL
);
840 g_assert_cmpint (items_changed_count
, ==, 0);
842 g_timeout_add (100, stop_loop
, loop
);
843 g_main_loop_run (loop
);
845 g_menu_model_get_n_items (G_MENU_MODEL (proxy
));
847 g_timeout_add (100, stop_loop
, loop
);
848 g_main_loop_run (loop
);
850 g_assert_cmpint (items_changed_count
, ==, 1);
851 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 3);
853 g_timeout_add (100, stop_loop
, loop
);
854 g_main_loop_run (loop
);
856 g_menu_append (menu
, "item4", NULL
);
857 g_menu_append (menu
, "item5", NULL
);
858 g_menu_append (menu
, "item6", NULL
);
859 g_menu_remove (menu
, 0);
860 g_menu_remove (menu
, 0);
862 g_timeout_add (200, stop_loop
, loop
);
863 g_main_loop_run (loop
);
865 g_assert_cmpint (items_changed_count
, ==, 6);
867 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 4);
868 g_object_unref (proxy
);
870 g_timeout_add (100, stop_loop
, loop
);
871 g_main_loop_run (loop
);
873 g_menu_remove (menu
, 0);
874 g_menu_remove (menu
, 0);
876 g_timeout_add (100, stop_loop
, loop
);
877 g_main_loop_run (loop
);
879 g_assert_cmpint (items_changed_count
, ==, 6);
881 g_dbus_connection_unexport_menu_model (bus
, export_id
);
882 g_object_unref (menu
);
884 g_main_loop_unref (loop
);
885 g_object_unref (bus
);
889 do_modify (gpointer data
)
891 RandomMenu
*menu
= data
;
895 rand
= g_rand_new_with_seed (g_test_rand_int ());
897 for (i
= 0; i
< 10000; i
++)
899 random_menu_change (menu
, rand
);
906 do_export (gpointer data
)
908 GMenuModel
*menu
= data
;
910 GDBusConnection
*bus
;
912 GError
*error
= NULL
;
915 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
916 path
= g_strdup_printf ("/%p", data
);
918 for (i
= 0; i
< 10000; i
++)
920 id
= g_dbus_connection_export_menu_model (bus
, path
, menu
, &error
);
921 g_assert_no_error (error
);
922 g_dbus_connection_unexport_menu_model (bus
, id
);
923 while (g_main_context_iteration (NULL
, FALSE
));
928 g_object_unref (bus
);
934 test_dbus_threaded (void)
936 RandomMenu
*menu
[10];
941 for (i
= 0; i
< 10; i
++)
943 menu
[i
] = random_menu_new (g_rand_new_with_seed (g_test_rand_int ()), 2);
944 call
[i
] = g_thread_new ("call", do_modify
, menu
[i
]);
945 export
[i
] = g_thread_new ("export", do_export
, menu
[i
]);
948 for (i
= 0; i
< 10; i
++)
950 g_thread_join (call
[i
]);
951 g_thread_join (export
[i
]);
954 for (i
= 0; i
< 10; i
++)
955 g_object_unref (menu
[i
]);
959 test_attributes (void)
965 menu
= g_menu_new ();
967 item
= g_menu_item_new ("test", NULL
);
968 g_menu_item_set_attribute_value (item
, "boolean", g_variant_new_boolean (FALSE
));
969 g_menu_item_set_attribute_value (item
, "string", g_variant_new_string ("bla"));
971 g_menu_item_set_attribute (item
, "double", "d", 1.5);
972 v
= g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
973 g_menu_item_set_attribute_value (item
, "complex", v
);
974 g_menu_item_set_attribute_value (item
, "test-123", g_variant_new_string ("test-123"));
976 g_menu_append_item (menu
, item
);
978 g_menu_item_set_attribute (item
, "double", "d", G_PI
);
980 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 1);
982 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "boolean", NULL
);
983 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_BOOLEAN
));
986 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "string", NULL
);
987 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
990 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "double", NULL
);
991 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_DOUBLE
));
994 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "complex", NULL
);
995 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE("a(si)")));
998 g_menu_remove_all (menu
);
1000 g_object_unref (menu
);
1001 g_object_unref (item
);
1005 test_attribute_iter (void)
1011 GMenuAttributeIter
*iter
;
1014 menu
= g_menu_new ();
1016 item
= g_menu_item_new ("test", NULL
);
1017 g_menu_item_set_attribute_value (item
, "boolean", g_variant_new_boolean (FALSE
));
1018 g_menu_item_set_attribute_value (item
, "string", g_variant_new_string ("bla"));
1020 g_menu_item_set_attribute (item
, "double", "d", 1.5);
1021 v
= g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
1022 g_menu_item_set_attribute_value (item
, "complex", v
);
1023 g_menu_item_set_attribute_value (item
, "test-123", g_variant_new_string ("test-123"));
1025 g_menu_append_item (menu
, item
);
1027 g_menu_item_set_attribute (item
, "double", "d", G_PI
);
1029 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 1);
1031 found
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
)g_variant_unref
);
1033 iter
= g_menu_model_iterate_item_attributes (G_MENU_MODEL (menu
), 0);
1034 while (g_menu_attribute_iter_get_next (iter
, &name
, &v
))
1035 g_hash_table_insert (found
, g_strdup (name
), v
);
1037 g_assert_cmpint (g_hash_table_size (found
), ==, 6);
1039 v
= g_hash_table_lookup (found
, "label");
1040 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
1042 v
= g_hash_table_lookup (found
, "boolean");
1043 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_BOOLEAN
));
1045 v
= g_hash_table_lookup (found
, "string");
1046 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
1048 v
= g_hash_table_lookup (found
, "double");
1049 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_DOUBLE
));
1051 v
= g_hash_table_lookup (found
, "complex");
1052 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE("a(si)")));
1054 v
= g_hash_table_lookup (found
, "test-123");
1055 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
1057 g_hash_table_unref (found
);
1059 g_menu_remove_all (menu
);
1061 g_object_unref (menu
);
1062 g_object_unref (item
);
1073 m
= G_MENU_MODEL (g_menu_new ());
1074 g_menu_append (G_MENU (m
), "test", NULL
);
1076 menu
= g_menu_new ();
1078 item
= g_menu_item_new ("test2", NULL
);
1079 g_menu_item_set_link (item
, "submenu", m
);
1080 g_menu_prepend_item (menu
, item
);
1082 item
= g_menu_item_new ("test1", NULL
);
1083 g_menu_item_set_link (item
, "section", m
);
1084 g_menu_insert_item (menu
, 0, item
);
1086 item
= g_menu_item_new ("test3", NULL
);
1087 g_menu_item_set_link (item
, "wallet", m
);
1088 g_menu_insert_item (menu
, 1000, item
);
1090 item
= g_menu_item_new ("test4", NULL
);
1091 g_menu_item_set_link (item
, "purse", m
);
1092 g_menu_item_set_link (item
, "purse", NULL
);
1093 g_menu_append_item (menu
, item
);
1095 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 4);
1097 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 0, "section");
1101 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 1, "submenu");
1105 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 2, "wallet");
1109 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 3, "purse");
1110 g_assert (x
== NULL
);
1113 g_object_unref (menu
);
1121 menu
= g_menu_new ();
1122 g_menu_append (menu
, "test", "test");
1124 g_assert (g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1125 g_menu_freeze (menu
);
1126 g_assert (!g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1128 g_object_unref (menu
);
1132 test_convenience (void)
1140 sub
= g_menu_new ();
1142 g_menu_prepend (m1
, "label1", "do::something");
1143 g_menu_insert (m2
, 0, "label1", "do::something");
1145 g_menu_append (m1
, "label2", "do::somethingelse");
1146 g_menu_insert (m2
, -1, "label2", "do::somethingelse");
1148 g_menu_insert_section (m1
, 10, "label3", G_MENU_MODEL (sub
));
1149 item
= g_menu_item_new_section ("label3", G_MENU_MODEL (sub
));
1150 g_menu_insert_item (m2
, 10, item
);
1151 g_object_unref (item
);
1153 g_menu_prepend_section (m1
, "label4", G_MENU_MODEL (sub
));
1154 g_menu_insert_section (m2
, 0, "label4", G_MENU_MODEL (sub
));
1156 g_menu_append_section (m1
, "label5", G_MENU_MODEL (sub
));
1157 g_menu_insert_section (m2
, -1, "label5", G_MENU_MODEL (sub
));
1159 g_menu_insert_submenu (m1
, 5, "label6", G_MENU_MODEL (sub
));
1160 item
= g_menu_item_new_submenu ("label6", G_MENU_MODEL (sub
));
1161 g_menu_insert_item (m2
, 5, item
);
1162 g_object_unref (item
);
1164 g_menu_prepend_submenu (m1
, "label7", G_MENU_MODEL (sub
));
1165 g_menu_insert_submenu (m2
, 0, "label7", G_MENU_MODEL (sub
));
1167 g_menu_append_submenu (m1
, "label8", G_MENU_MODEL (sub
));
1168 g_menu_insert_submenu (m2
, -1, "label8", G_MENU_MODEL (sub
));
1170 assert_menus_equal (G_MENU_MODEL (m1
), G_MENU_MODEL (m2
));
1172 g_object_unref (m1
);
1173 g_object_unref (m2
);
1177 test_menuitem (void)
1186 menu
= g_menu_new ();
1187 submenu
= g_menu_new ();
1189 item
= g_menu_item_new ("label", "action");
1190 g_menu_item_set_attribute (item
, "attribute", "b", TRUE
);
1191 g_menu_item_set_link (item
, G_MENU_LINK_SUBMENU
, G_MENU_MODEL (submenu
));
1192 g_menu_append_item (menu
, item
);
1194 icon
= g_themed_icon_new ("bla");
1195 g_menu_item_set_icon (item
, icon
);
1196 g_object_unref (icon
);
1198 g_assert (g_menu_item_get_attribute (item
, "attribute", "b", &b
));
1201 g_menu_item_set_action_and_target (item
, "action", "(bs)", TRUE
, "string");
1202 g_assert (g_menu_item_get_attribute (item
, "target", "(bs)", &b
, &s
));
1204 g_assert_cmpstr (s
, ==, "string");
1207 g_object_unref (item
);
1209 item
= g_menu_item_new_from_model (G_MENU_MODEL (menu
), 0);
1210 assert_menuitem_equal (item
, G_MENU_MODEL (menu
), 0);
1211 g_object_unref (item
);
1213 g_object_unref (menu
);
1214 g_object_unref (submenu
);
1219 main (int argc
, char **argv
)
1223 g_test_init (&argc
, &argv
, NULL
);
1227 g_test_add_func ("/gmenu/equality", test_equality
);
1228 g_test_add_func ("/gmenu/random", test_random
);
1229 g_test_add_func ("/gmenu/dbus/roundtrip", test_dbus_roundtrip
);
1230 g_test_add_func ("/gmenu/dbus/subscriptions", test_dbus_subscriptions
);
1231 g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded
);
1232 g_test_add_func ("/gmenu/attributes", test_attributes
);
1233 g_test_add_func ("/gmenu/attributes/iterate", test_attribute_iter
);
1234 g_test_add_func ("/gmenu/links", test_links
);
1235 g_test_add_func ("/gmenu/mutable", test_mutable
);
1236 g_test_add_func ("/gmenu/convenience", test_convenience
);
1237 g_test_add_func ("/gmenu/menuitem", test_menuitem
);
1239 ret
= g_test_run ();
1241 session_bus_down ();
1245 /* vim:set foldmethod=marker: */