5 /* This utility struct is used by both the RandomMenu and MirrorMenu
6 * class implementations below.
9 GHashTable
*attributes
;
14 test_item_new (GHashTable
*attributes
,
19 item
= g_slice_new (TestItem
);
20 item
->attributes
= g_hash_table_ref (attributes
);
21 item
->links
= g_hash_table_ref (links
);
27 test_item_free (gpointer data
)
29 TestItem
*item
= data
;
31 g_hash_table_unref (item
->attributes
);
32 g_hash_table_unref (item
->links
);
34 g_slice_free (TestItem
, item
);
42 GMenuModel parent_instance
;
48 typedef GMenuModelClass RandomMenuClass
;
50 static GType
random_menu_get_type (void);
51 G_DEFINE_TYPE (RandomMenu
, random_menu
, G_TYPE_MENU_MODEL
);
54 random_menu_is_mutable (GMenuModel
*model
)
60 random_menu_get_n_items (GMenuModel
*model
)
62 RandomMenu
*menu
= (RandomMenu
*) model
;
64 return g_sequence_get_length (menu
->items
);
68 random_menu_get_item_attributes (GMenuModel
*model
,
72 RandomMenu
*menu
= (RandomMenu
*) model
;
75 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
76 *table
= g_hash_table_ref (item
->attributes
);
80 random_menu_get_item_links (GMenuModel
*model
,
84 RandomMenu
*menu
= (RandomMenu
*) model
;
87 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
88 *table
= g_hash_table_ref (item
->links
);
92 random_menu_finalize (GObject
*object
)
94 RandomMenu
*menu
= (RandomMenu
*) object
;
96 g_sequence_free (menu
->items
);
98 G_OBJECT_CLASS (random_menu_parent_class
)
103 random_menu_init (RandomMenu
*menu
)
108 random_menu_class_init (GMenuModelClass
*class)
110 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
112 class->is_mutable
= random_menu_is_mutable
;
113 class->get_n_items
= random_menu_get_n_items
;
114 class->get_item_attributes
= random_menu_get_item_attributes
;
115 class->get_item_links
= random_menu_get_item_links
;
117 object_class
->finalize
= random_menu_finalize
;
120 static RandomMenu
* random_menu_new (GRand
*rand
, gint order
);
123 random_menu_change (RandomMenu
*menu
,
126 gint position
, removes
, adds
;
127 GSequenceIter
*point
;
131 n_items
= g_sequence_get_length (menu
->items
);
135 position
= g_rand_int_range (rand
, 0, n_items
+ 1);
136 removes
= g_rand_int_range (rand
, 0, n_items
- position
+ 1);
137 adds
= g_rand_int_range (rand
, 0, MAX_ITEMS
- (n_items
- removes
) + 1);
139 while (removes
== 0 && adds
== 0);
141 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removes
);
145 GSequenceIter
*start
;
147 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
148 g_sequence_remove_range (start
, point
);
151 for (i
= 0; i
< adds
; i
++)
155 GHashTable
*attributes
;
157 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
158 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
160 if (menu
->order
> 0 && g_rand_boolean (rand
))
163 const gchar
*subtype
;
165 child
= random_menu_new (rand
, menu
->order
- 1);
167 if (g_rand_boolean (rand
))
169 subtype
= G_MENU_LINK_SECTION
;
170 /* label some section headers */
171 if (g_rand_boolean (rand
))
178 /* label all submenus */
179 subtype
= G_MENU_LINK_SUBMENU
;
183 g_hash_table_insert (links
, g_strdup (subtype
), child
);
186 /* label all terminals */
190 g_hash_table_insert (attributes
, g_strdup ("label"), g_variant_ref_sink (g_variant_new_string (label
)));
192 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
193 g_hash_table_unref (links
);
194 g_hash_table_unref (attributes
);
197 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removes
, adds
);
201 random_menu_new (GRand
*rand
,
206 menu
= g_object_new (random_menu_get_type (), NULL
);
207 menu
->items
= g_sequence_new (test_item_free
);
210 random_menu_change (menu
, rand
);
215 /* MirrorMenu {{{1 */
217 GMenuModel parent_instance
;
219 GMenuModel
*clone_of
;
224 typedef GMenuModelClass MirrorMenuClass
;
226 static GType
mirror_menu_get_type (void);
227 G_DEFINE_TYPE (MirrorMenu
, mirror_menu
, G_TYPE_MENU_MODEL
);
230 mirror_menu_is_mutable (GMenuModel
*model
)
232 MirrorMenu
*menu
= (MirrorMenu
*) model
;
234 return menu
->handler_id
!= 0;
238 mirror_menu_get_n_items (GMenuModel
*model
)
240 MirrorMenu
*menu
= (MirrorMenu
*) model
;
242 return g_sequence_get_length (menu
->items
);
246 mirror_menu_get_item_attributes (GMenuModel
*model
,
250 MirrorMenu
*menu
= (MirrorMenu
*) model
;
253 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
254 *table
= g_hash_table_ref (item
->attributes
);
258 mirror_menu_get_item_links (GMenuModel
*model
,
262 MirrorMenu
*menu
= (MirrorMenu
*) model
;
265 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
266 *table
= g_hash_table_ref (item
->links
);
270 mirror_menu_finalize (GObject
*object
)
272 MirrorMenu
*menu
= (MirrorMenu
*) object
;
274 if (menu
->handler_id
)
275 g_signal_handler_disconnect (menu
->clone_of
, menu
->handler_id
);
277 g_sequence_free (menu
->items
);
278 g_object_unref (menu
->clone_of
);
280 G_OBJECT_CLASS (mirror_menu_parent_class
)
285 mirror_menu_init (MirrorMenu
*menu
)
290 mirror_menu_class_init (GMenuModelClass
*class)
292 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
294 class->is_mutable
= mirror_menu_is_mutable
;
295 class->get_n_items
= mirror_menu_get_n_items
;
296 class->get_item_attributes
= mirror_menu_get_item_attributes
;
297 class->get_item_links
= mirror_menu_get_item_links
;
299 object_class
->finalize
= mirror_menu_finalize
;
302 static MirrorMenu
* mirror_menu_new (GMenuModel
*clone_of
);
305 mirror_menu_changed (GMenuModel
*model
,
311 MirrorMenu
*menu
= user_data
;
312 GSequenceIter
*point
;
315 g_assert (model
== menu
->clone_of
);
317 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removed
);
321 GSequenceIter
*start
;
323 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
324 g_sequence_remove_range (start
, point
);
327 for (i
= position
; i
< position
+ added
; i
++)
329 GMenuAttributeIter
*attr_iter
;
330 GMenuLinkIter
*link_iter
;
332 GHashTable
*attributes
;
337 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
338 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
340 attr_iter
= g_menu_model_iterate_item_attributes (model
, i
);
341 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &value
))
343 g_hash_table_insert (attributes
, g_strdup (name
), value
);
345 g_object_unref (attr_iter
);
347 link_iter
= g_menu_model_iterate_item_links (model
, i
);
348 while (g_menu_link_iter_get_next (link_iter
, &name
, &child
))
350 g_hash_table_insert (links
, g_strdup (name
), mirror_menu_new (child
));
351 g_object_unref (child
);
353 g_object_unref (link_iter
);
355 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
356 g_hash_table_unref (attributes
);
357 g_hash_table_unref (links
);
360 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removed
, added
);
364 mirror_menu_new (GMenuModel
*clone_of
)
368 menu
= g_object_new (mirror_menu_get_type (), NULL
);
369 menu
->items
= g_sequence_new (test_item_free
);
370 menu
->clone_of
= g_object_ref (clone_of
);
372 if (g_menu_model_is_mutable (clone_of
))
373 menu
->handler_id
= g_signal_connect (clone_of
, "items-changed", G_CALLBACK (mirror_menu_changed
), menu
);
374 mirror_menu_changed (clone_of
, 0, 0, g_menu_model_get_n_items (clone_of
), menu
);
379 /* check_menus_equal(), assert_menus_equal() {{{1 */
381 check_menus_equal (GMenuModel
*a
,
384 gboolean equal
= TRUE
;
388 a_n
= g_menu_model_get_n_items (a
);
389 b_n
= g_menu_model_get_n_items (b
);
394 for (i
= 0; i
< a_n
; i
++)
396 GMenuAttributeIter
*attr_iter
;
397 GVariant
*a_value
, *b_value
;
398 GMenuLinkIter
*link_iter
;
399 GMenuModel
*a_menu
, *b_menu
;
402 attr_iter
= g_menu_model_iterate_item_attributes (a
, i
);
403 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &a_value
))
405 b_value
= g_menu_model_get_item_attribute_value (b
, i
, name
, NULL
);
406 equal
&= b_value
&& g_variant_equal (a_value
, b_value
);
408 g_variant_unref (b_value
);
409 g_variant_unref (a_value
);
411 g_object_unref (attr_iter
);
413 attr_iter
= g_menu_model_iterate_item_attributes (b
, i
);
414 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &b_value
))
416 a_value
= g_menu_model_get_item_attribute_value (a
, i
, name
, NULL
);
417 equal
&= a_value
&& g_variant_equal (a_value
, b_value
);
419 g_variant_unref (a_value
);
420 g_variant_unref (b_value
);
422 g_object_unref (attr_iter
);
424 link_iter
= g_menu_model_iterate_item_links (a
, i
);
425 while (g_menu_link_iter_get_next (link_iter
, &name
, &a_menu
))
427 b_menu
= g_menu_model_get_item_link (b
, i
, name
);
428 equal
&= b_menu
&& check_menus_equal (a_menu
, b_menu
);
430 g_object_unref (b_menu
);
431 g_object_unref (a_menu
);
433 g_object_unref (link_iter
);
435 link_iter
= g_menu_model_iterate_item_links (b
, i
);
436 while (g_menu_link_iter_get_next (link_iter
, &name
, &b_menu
))
438 a_menu
= g_menu_model_get_item_link (a
, i
, name
);
439 equal
&= a_menu
&& check_menus_equal (a_menu
, b_menu
);
441 g_object_unref (a_menu
);
442 g_object_unref (b_menu
);
444 g_object_unref (link_iter
);
451 assert_menus_equal (GMenuModel
*a
,
454 if (!check_menus_equal (a
, b
))
458 string
= g_string_new ("\n <a>\n");
459 g_menu_markup_print_string (string
, G_MENU_MODEL (a
), 4, 2);
460 g_string_append (string
, " </a>\n\n-------------\n <b>\n");
461 g_menu_markup_print_string (string
, G_MENU_MODEL (b
), 4, 2);
462 g_string_append (string
, " </b>\n");
463 g_error ("%s", string
->str
);
467 /* Test cases {{{1 */
471 GRand
*randa
, *randb
;
475 seed
= g_test_rand_int ();
477 randa
= g_rand_new_with_seed (seed
);
478 randb
= g_rand_new_with_seed (seed
);
480 for (i
= 0; i
< 500; i
++)
484 a
= random_menu_new (randa
, TOP_ORDER
);
485 b
= random_menu_new (randb
, TOP_ORDER
);
486 assert_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
));
493 for (i
= 0; i
< 500;)
497 a
= random_menu_new (randa
, TOP_ORDER
);
498 b
= random_menu_new (randb
, TOP_ORDER
);
499 if (check_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
)))
501 /* by chance, they may really be equal. double check. */
504 as
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (a
), 4, 2);
505 bs
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (b
), 4, 2);
506 g_assert_cmpstr (as
->str
, ==, bs
->str
);
507 g_string_free (bs
, TRUE
);
508 g_string_free (as
, TRUE
);
510 /* we're here because randa and randb just generated equal
511 * menus. they may do it again, so throw away randb and make
515 randb
= g_rand_new_with_seed (g_rand_int (randa
));
518 /* make sure we get enough unequals (ie: no GRand failure) */
537 rand
= g_rand_new_with_seed (g_test_rand_int ());
538 random
= random_menu_new (rand
, TOP_ORDER
);
539 mirror
= mirror_menu_new (G_MENU_MODEL (random
));
541 for (i
= 0; i
< 500; i
++)
543 assert_menus_equal (G_MENU_MODEL (random
), G_MENU_MODEL (mirror
));
544 random_menu_change (random
, rand
);
547 g_object_unref (mirror
);
548 g_object_unref (random
);
553 struct roundtrip_state
556 MirrorMenu
*proxy_mirror
;
557 GDBusMenuModel
*proxy
;
565 roundtrip_step (gpointer data
)
567 struct roundtrip_state
*state
= data
;
569 if (check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
)) &&
570 check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy_mirror
)))
575 if (state
->success
< 100)
576 random_menu_change (state
->random
, state
->rand
);
578 g_main_loop_quit (state
->loop
);
580 else if (state
->count
== 100)
582 assert_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
));
583 g_assert_not_reached ();
588 return G_SOURCE_CONTINUE
;
592 test_dbus_roundtrip (void)
594 struct roundtrip_state state
;
595 GDBusConnection
*bus
;
599 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
601 state
.rand
= g_rand_new_with_seed (g_test_rand_int ());
603 state
.random
= random_menu_new (state
.rand
, 2);
604 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (state
.random
), NULL
);
605 state
.proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
606 state
.proxy_mirror
= mirror_menu_new (G_MENU_MODEL (state
.proxy
));
610 id
= g_timeout_add (10, roundtrip_step
, &state
);
612 state
.loop
= g_main_loop_new (NULL
, FALSE
);
613 g_main_loop_run (state
.loop
);
615 g_main_loop_unref (state
.loop
);
616 g_source_remove (id
);
617 g_object_unref (state
.proxy
);
618 g_dbus_connection_unexport_menu_model (bus
, export_id
);
619 g_object_unref (state
.random
);
620 g_object_unref (state
.proxy_mirror
);
621 g_rand_free (state
.rand
);
622 g_object_unref (bus
);
625 static gint items_changed_count
;
628 items_changed (GMenuModel
*model
,
634 items_changed_count
++;
638 stop_loop (gpointer data
)
640 GMainLoop
*loop
= data
;
642 g_main_loop_quit (loop
);
644 return G_SOURCE_REMOVE
;
648 test_dbus_subscriptions (void)
650 GDBusConnection
*bus
;
652 GDBusMenuModel
*proxy
;
654 GError
*error
= NULL
;
657 loop
= g_main_loop_new (NULL
, FALSE
);
659 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
661 menu
= g_menu_new ();
663 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (menu
), &error
);
664 g_assert_no_error (error
);
666 proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
667 items_changed_count
= 0;
668 g_signal_connect (proxy
, "items-changed",
669 G_CALLBACK (items_changed
), NULL
);
671 g_menu_append (menu
, "item1", NULL
);
672 g_menu_append (menu
, "item2", NULL
);
673 g_menu_append (menu
, "item3", NULL
);
675 g_assert_cmpint (items_changed_count
, ==, 0);
677 g_timeout_add (100, stop_loop
, loop
);
678 g_main_loop_run (loop
);
680 g_menu_model_get_n_items (G_MENU_MODEL (proxy
));
682 g_timeout_add (100, stop_loop
, loop
);
683 g_main_loop_run (loop
);
685 g_assert_cmpint (items_changed_count
, ==, 1);
686 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 3);
688 g_timeout_add (100, stop_loop
, loop
);
689 g_main_loop_run (loop
);
691 g_menu_append (menu
, "item4", NULL
);
692 g_menu_append (menu
, "item5", NULL
);
693 g_menu_append (menu
, "item6", NULL
);
694 g_menu_remove (menu
, 0);
695 g_menu_remove (menu
, 0);
697 g_timeout_add (200, stop_loop
, loop
);
698 g_main_loop_run (loop
);
700 g_assert_cmpint (items_changed_count
, ==, 6);
702 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 4);
703 g_object_unref (proxy
);
705 g_timeout_add (100, stop_loop
, loop
);
706 g_main_loop_run (loop
);
708 g_menu_remove (menu
, 0);
709 g_menu_remove (menu
, 0);
711 g_timeout_add (100, stop_loop
, loop
);
712 g_main_loop_run (loop
);
714 g_assert_cmpint (items_changed_count
, ==, 6);
716 g_dbus_connection_unexport_menu_model (bus
, export_id
);
717 g_object_unref (menu
);
719 g_main_loop_unref (loop
);
723 do_modify (gpointer data
)
725 RandomMenu
*menu
= data
;
729 rand
= g_rand_new_with_seed (g_test_rand_int ());
731 for (i
= 0; i
< 10000; i
++)
733 random_menu_change (menu
, rand
);
740 do_export (gpointer data
)
742 GMenuModel
*menu
= data
;
744 GDBusConnection
*bus
;
746 GError
*error
= NULL
;
749 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
750 path
= g_strdup_printf ("/%p", data
);
752 for (i
= 0; i
< 10000; i
++)
754 id
= g_dbus_connection_export_menu_model (bus
, path
, menu
, &error
);
755 g_assert_no_error (error
);
756 g_dbus_connection_unexport_menu_model (bus
, id
);
757 while (g_main_context_iteration (NULL
, FALSE
));
762 g_object_unref (bus
);
768 test_dbus_threaded (void)
770 RandomMenu
*menu
[10];
775 for (i
= 0; i
< 10; i
++)
777 menu
[i
] = random_menu_new (g_rand_new_with_seed (g_test_rand_int ()), 2);
778 call
[i
] = g_thread_new ("call", do_modify
, menu
[i
]);
779 export
[i
] = g_thread_new ("export", do_export
, menu
[i
]);
782 for (i
= 0; i
< 10; i
++)
784 g_thread_join (call
[i
]);
785 g_thread_join (export
[i
]);
788 for (i
= 0; i
< 10; i
++)
789 g_object_unref (menu
[i
]);
798 start_element (GMarkupParseContext
*context
,
799 const gchar
*element_name
,
800 const gchar
**attribute_names
,
801 const gchar
**attribute_values
,
805 ParserData
*data
= user_data
;
807 if (g_strcmp0 (element_name
, "menu") == 0)
808 g_menu_markup_parser_start_menu (context
, "domain", data
->objects
);
812 end_element (GMarkupParseContext
*context
,
813 const gchar
*element_name
,
817 ParserData
*data
= user_data
;
819 if (g_strcmp0 (element_name
, "menu") == 0)
820 data
->menu
= g_menu_markup_parser_end_menu (context
);
824 parse_menu_string (const gchar
*string
, GHashTable
*objects
, GError
**error
)
826 const GMarkupParser parser
= {
827 start_element
, end_element
, NULL
, NULL
, NULL
829 GMarkupParseContext
*context
;
833 data
.objects
= objects
;
835 context
= g_markup_parse_context_new (&parser
, 0, &data
, NULL
);
836 g_markup_parse_context_parse (context
, string
, -1, error
);
837 g_markup_parse_context_free (context
);
839 return (GMenuModel
*)data
.menu
;
843 menu_to_string (GMenuModel
*menu
)
847 s
= g_string_new ("<menu>\n");
848 g_menu_markup_print_string (s
, menu
, 2, 2);
849 g_string_append (s
, "</menu>\n");
851 return g_string_free (s
, FALSE
);
854 const gchar menu_data
[] =
855 "<menu id='edit-menu'>\n"
857 " <item action='undo'>\n"
858 " <attribute name='label' translatable='yes' context='Stock label'>'_Undo'</attribute>\n"
860 " <item label='Redo' action='redo'/>\n"
862 " <section></section>\n"
863 " <section label='Copy & Paste'>\n"
864 " <item label='Cut' action='cut'/>\n"
865 " <item label='Copy' action='copy'/>\n"
866 " <item label='Paste' action='paste'/>\n"
868 " <item><link name='section' id='blargh'>\n"
869 " <item label='Bold' action='bold'/>\n"
870 " <submenu label='Language'>\n"
871 " <item label='Latin' action='lang' target='latin'/>\n"
872 " <item label='Greek' action='lang' target='greek'/>\n"
873 " <item label='Urdu' action='lang' target='urdu'/>\n"
875 " <item name='test unusual attributes'>\n"
876 " <attribute name='action' type='s'>'quite-some-action'</attribute>\n"
877 " <attribute name='target' type='i'>36</attribute>\n"
878 " <attribute name='chocolate-thunda' type='as'>['a','b']</attribute>\n"
879 " <attribute name='thing1' type='g'>'s(uu)'</attribute>\n"
880 " <attribute name='icon' type='s'>'small blue thing'</attribute>\n"
886 test_markup_roundtrip (void)
888 GError
*error
= NULL
;
894 a
= parse_menu_string (menu_data
, NULL
, &error
);
895 g_assert_no_error (error
);
896 g_assert (G_IS_MENU_MODEL (a
));
898 /* normalized representation */
899 s
= menu_to_string (a
);
901 b
= parse_menu_string (s
, NULL
, &error
);
902 g_assert_no_error (error
);
903 g_assert (G_IS_MENU_MODEL (b
));
905 assert_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
));
907 s2
= menu_to_string (b
);
909 g_assert_cmpstr (s
, ==, s2
);
918 test_markup_objects (void)
922 GError
*error
= NULL
;
924 objects
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, g_object_unref
);
925 a
= parse_menu_string (menu_data
, objects
, &error
);
926 g_assert_no_error (error
);
927 g_assert (G_IS_MENU_MODEL (a
));
928 g_assert_cmpint (g_hash_table_size (objects
), ==, 1);
929 b
= g_hash_table_lookup (objects
, "blargh");
930 g_assert (G_IS_MENU_MODEL (b
));
932 g_hash_table_unref (objects
);
935 const gchar menu_data2
[] =
938 " <item label='Redo' action='redo'/>"
940 " <section></section>\n"
941 " <section label='Copy & Paste'>"
942 " <item label='Cut' action='cut'/>"
944 " <section id='section1'>"
945 " <item label='Bold' action='bold'/>"
946 " <submenu label='Language' id='submenu1'>"
947 " <section id='section2'>"
948 " <item label='Urdu' action='lang' target='urdu'/>"
954 test_markup_ids (void)
958 GError
*error
= NULL
;
960 objects
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, g_object_unref
);
961 a
= parse_menu_string (menu_data2
, objects
, &error
);
962 g_assert_no_error (error
);
963 g_assert (G_IS_MENU_MODEL (a
));
964 g_assert_cmpint (g_hash_table_size (objects
), ==, 3);
965 b
= g_hash_table_lookup (objects
, "section1");
966 g_assert (G_IS_MENU_MODEL (b
));
967 b
= g_hash_table_lookup (objects
, "section2");
968 g_assert (G_IS_MENU_MODEL (b
));
969 b
= g_hash_table_lookup (objects
, "submenu1");
970 g_assert (G_IS_MENU_MODEL (b
));
972 g_hash_table_unref (objects
);
976 test_attributes (void)
982 menu
= g_menu_new ();
984 item
= g_menu_item_new ("test", NULL
);
985 g_menu_item_set_attribute_value (item
, "boolean", g_variant_new_boolean (FALSE
));
986 g_menu_item_set_attribute_value (item
, "string", g_variant_new_string ("bla"));
987 g_menu_item_set_attribute_value (item
, "double", g_variant_new_double (1.5));
988 v
= g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
989 g_menu_item_set_attribute_value (item
, "complex", v
);
990 g_menu_item_set_attribute_value (item
, "test-123", g_variant_new_string ("test-123"));
992 g_menu_append_item (menu
, item
);
994 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 1);
996 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "boolean", NULL
);
997 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_BOOLEAN
));
1000 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "string", NULL
);
1001 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
1002 g_variant_unref (v
);
1004 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "double", NULL
);
1005 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_DOUBLE
));
1006 g_variant_unref (v
);
1008 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "complex", NULL
);
1009 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE("a(si)")));
1010 g_variant_unref (v
);
1012 g_object_unref (menu
);
1023 m
= G_MENU_MODEL (g_menu_new ());
1024 g_menu_append (G_MENU (m
), "test", NULL
);
1026 menu
= g_menu_new ();
1028 item
= g_menu_item_new ("test1", NULL
);
1029 g_menu_item_set_link (item
, "section", m
);
1030 g_menu_append_item (menu
, item
);
1032 item
= g_menu_item_new ("test2", NULL
);
1033 g_menu_item_set_link (item
, "submenu", m
);
1034 g_menu_append_item (menu
, item
);
1036 item
= g_menu_item_new ("test3", NULL
);
1037 g_menu_item_set_link (item
, "wallet", m
);
1038 g_menu_append_item (menu
, item
);
1040 item
= g_menu_item_new ("test4", NULL
);
1041 g_menu_item_set_link (item
, "purse", m
);
1042 g_menu_item_set_link (item
, "purse", NULL
);
1043 g_menu_append_item (menu
, item
);
1045 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 4);
1047 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 0, "section");
1051 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 1, "submenu");
1055 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 2, "wallet");
1059 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 3, "purse");
1060 g_assert (x
== NULL
);
1063 g_object_unref (menu
);
1071 menu
= g_menu_new ();
1072 g_menu_append (menu
, "test", "test");
1074 g_assert (g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1075 g_menu_freeze (menu
);
1076 g_assert (!g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1078 g_object_unref (menu
);
1084 /* trying to use most of the GMenu api for constructing the
1085 * same menu two different ways
1093 item
= g_menu_item_new ("test1", "action1::target1");
1094 g_menu_prepend_item (a
, item
);
1095 g_object_unref (item
);
1098 g_menu_prepend (m
, "test2a", "action2");
1099 g_menu_append (m
, "test2c", NULL
);
1100 g_menu_insert (m
, 1, "test2b", NULL
);
1102 item
= g_menu_item_new_submenu ("test2", G_MENU_MODEL (m
));
1103 g_menu_append_item (a
, item
);
1104 g_object_unref (item
);
1110 g_menu_append (m2
, "x", NULL
);
1111 g_menu_prepend_section (m
, "test3a", G_MENU_MODEL (m2
));
1112 g_object_unref (m2
);
1114 item
= g_menu_item_new_section ("test3", G_MENU_MODEL (m
));
1115 g_menu_insert_item (a
, -1, item
);
1116 g_object_unref (item
);
1121 " <item target='target1' action='action1' label='test1'/>"
1122 " <item label='test2'>"
1123 " <link name='submenu'>"
1124 " <item action='action2' label='test2a'/>"
1125 " <item label='test2b'/>"
1126 " <item label='test2c'/>"
1129 " <item label='test3'>"
1130 " <link name='section'>"
1131 " <item label='test3a'>"
1132 " <link name='section'>"
1133 " <item label='x'/>"
1140 b
= parse_menu_string (s
, NULL
, NULL
);
1142 assert_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
));
1149 main (int argc
, char **argv
)
1151 g_test_init (&argc
, &argv
, NULL
);
1155 g_test_add_func ("/gmenu/equality", test_equality
);
1156 g_test_add_func ("/gmenu/random", test_random
);
1157 g_test_add_func ("/gmenu/dbus/roundtrip", test_dbus_roundtrip
);
1158 g_test_add_func ("/gmenu/dbus/subscriptions", test_dbus_subscriptions
);
1159 g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded
);
1160 g_test_add_func ("/gmenu/markup/roundtrip", test_markup_roundtrip
);
1161 g_test_add_func ("/gmenu/markup/objects", test_markup_objects
);
1162 g_test_add_func ("/gmenu/markup/ids", test_markup_ids
);
1163 g_test_add_func ("/gmenu/attributes", test_attributes
);
1164 g_test_add_func ("/gmenu/links", test_links
);
1165 g_test_add_func ("/gmenu/mutable", test_mutable
);
1166 g_test_add_func ("/gmenu/misc", test_misc
);
1168 return g_test_run ();
1170 /* vim:set foldmethod=marker: */