1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
/*
Confirm that no warnings/criticals get generated by including
multiple add/removes in a match w/o waiting on the mainloop to iterate.
Copyright 2013 Canonical Ltd.
Original sample code by Drew Bliss <drewb@valvesoftware.com>
Modified for automatic testing by Charles Kerr <charles.kerr@canonical.com>
*/
#include <stdlib.h> /* exit() */
#include <gtk/gtk.h>
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-gtk/menu.h>
#include <libdbusmenu-gtk/parser.h>
static GMainLoop * loop = NULL;
static GtkWidget * top_gtk = NULL;
static DbusmenuMenuitem * top_dbusmenu = NULL;
static DbusmenuServer * menuservice = NULL;
static void
rebuild_menu (void)
{
GList * l;
GList * children;
int i;
const int n = 10;
static int count = 0;
if (top_gtk == NULL)
{
top_gtk = gtk_menu_new ();
gtk_widget_show (top_gtk);
top_dbusmenu = dbusmenu_gtk_parse_menu_structure (top_gtk);
menuservice = dbusmenu_server_new ("/org/ayatana/NotificationItem/test/Menu");
dbusmenu_server_set_root (menuservice, top_dbusmenu);
}
// remove all the previous children
children = gtk_container_get_children (GTK_CONTAINER(top_gtk));
for (l=children; l!=NULL; l=l->next)
gtk_widget_destroy (GTK_WIDGET (l->data));
// add a handful of new children
for (i=0; i<n; ++i)
{
char buf[80];
GtkWidget * child;
g_snprintf (buf, sizeof(buf), "Test item %d", ++count);
child = gtk_menu_item_new_with_label (buf);
gtk_menu_shell_append (GTK_MENU_SHELL(top_gtk), child);
gtk_widget_show (child);
}
}
/*
* Periodically rebuild the menu.
*
* After we've looped a couple of times with only one rebuild,
* attempt to reproduce the bug Drew reported by rebuilding multiple
* times before returning control to the main loop.
*
* If we survive doing this a handful of times without encountering
* a g_warning or g_critical, pass the test.
*/
static gint
on_timer (gpointer unused G_GNUC_UNUSED)
{
static int iteration = 0;
++iteration;
if (iteration > 5)
{
g_main_loop_quit (loop);
return G_SOURCE_REMOVE;
}
if (iteration <= 2)
{
rebuild_menu ();
}
else
{
int i;
for (i=0; i<iteration; ++i)
rebuild_menu ();
}
return G_SOURCE_CONTINUE;
}
static void
warning_counter (const gchar * log_domain,
GLogLevelFlags log_level G_GNUC_UNUSED,
const gchar * message,
gpointer user_data G_GNUC_UNUSED)
{
g_message ("Failing the test due to warning: %s %s", log_domain, message);
exit (EXIT_FAILURE);
}
int
main (int argc, char ** argv)
{
g_log_set_handler ("LIBDBUSMENU-GLIB", G_LOG_LEVEL_WARNING|G_LOG_LEVEL_CRITICAL, warning_counter, NULL);
gtk_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
g_timeout_add (200, on_timer, NULL);
g_main_loop_run (loop);
return 0;
}
|