[gtk+] Improve tests for X error traps, fix two bugs



commit e32ab82069cb99b8a7e649b9d6e09dd2c66904ec
Author: Havoc Pennington <hp pobox com>
Date:   Sat Sep 18 23:03:31 2010 -0400

    Improve tests for X error traps, fix two bugs
    
    * don't lose track of previous X error handler
      if nested traps are pushed
    * free any remaining traps when display
      is finalized
    
    Test will fail unless bug 630032 is closed so
    gdk_display_close() works.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=630033

 gdk/x11/gdkdisplay-x11.c |   15 ++++++
 gdk/x11/gdkmain-x11.c    |   13 ++++-
 tests/testerrors.c       |  110 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 128 insertions(+), 10 deletions(-)
---
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index ea4e991..3b82590 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -1911,6 +1911,21 @@ gdk_display_x11_finalize (GObject *object)
 
   XCloseDisplay (display_x11->xdisplay);
 
+  /* error traps */
+  while (display_x11->error_traps != NULL)
+    {
+      GdkErrorTrap *trap = display_x11->error_traps->data;
+
+      display_x11->error_traps =
+        g_slist_delete_link (display_x11->error_traps,
+                             display_x11->error_traps);
+
+      if (trap->end_sequence == 0)
+        g_warning ("Display finalized with an unpopped error trap");
+
+      g_slice_free (GdkErrorTrap, trap);
+    }
+
   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
 }
 
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 996715c..ca20f97 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -62,7 +62,8 @@ struct _GdkPredicate
 };
 
 /* non-GDK previous error handler */
-static int (*_gdk_old_error_handler) (Display *, XErrorEvent *);
+typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
+static GdkXErrorHandler _gdk_old_error_handler;
 /* number of times we've pushed the GDK error handler */
 static int _gdk_error_handler_push_count = 0;
 
@@ -386,13 +387,19 @@ gdk_x_error (Display	 *xdisplay,
 void
 _gdk_x11_error_handler_push (void)
 {
-  _gdk_old_error_handler = XSetErrorHandler (gdk_x_error);
+  GdkXErrorHandler previous;
+
+  previous = XSetErrorHandler (gdk_x_error);
 
   if (_gdk_error_handler_push_count > 0)
     {
-      if (_gdk_old_error_handler != gdk_x_error)
+      if (previous != gdk_x_error)
         g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
     }
+  else
+    {
+      _gdk_old_error_handler = previous;
+    }
 
   _gdk_error_handler_push_count += 1;
 }
diff --git a/tests/testerrors.c b/tests/testerrors.c
index 63b98cc..b8d1a8a 100755
--- a/tests/testerrors.c
+++ b/tests/testerrors.c
@@ -23,25 +23,23 @@
 #include <gtk/gtk.h>
 #include "x11/gdkx.h"
 
-gint
-main (gint argc, gchar *argv[])
+static void
+test_error_trapping (GdkDisplay *gdk_display)
 {
   Display *d;
   int dummy;
   int error;
 
-  gtk_init (&argc, &argv);
-
-  d = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+  d = GDK_DISPLAY_XDISPLAY (gdk_display);
 
   /* verify that we can catch errors */
   gdk_error_trap_push ();
-  XListProperties (d, 0, &dummy);
+  XListProperties (d, 0, &dummy); /* round trip */
   error = gdk_error_trap_pop ();
   g_assert (error == BadWindow);
 
   gdk_error_trap_push ();
-  XSetCloseDownMode (d, 12345);
+  XSetCloseDownMode (d, 12345); /* not a round trip */
   XSetCloseDownMode (d, DestroyAll);
   error = gdk_error_trap_pop ();
   g_assert (error == BadValue);
@@ -58,6 +56,104 @@ main (gint argc, gchar *argv[])
 
   XSync (d, TRUE);
 
+  /* verify that we can catch with nested traps */
+  gdk_error_trap_push ();
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  error = gdk_error_trap_pop ();
+  g_assert (error == BadValue);
+  error = gdk_error_trap_pop ();
+  g_assert (error == BadValue);
+
+  /* try nested, without sync */
+  gdk_error_trap_push ();
+  gdk_error_trap_push ();
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_pop_ignored ();
+  gdk_error_trap_pop_ignored ();
+  gdk_error_trap_pop_ignored ();
+
+  XSync (d, TRUE);
+
+  /* try nested, without sync, with interleaved calls */
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_pop_ignored ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_pop_ignored ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_pop_ignored ();
+
+  XSync (d, TRUE);
+
+  /* don't want to get errors that weren't in our push range */
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  gdk_error_trap_push ();
+  XSync (d, TRUE); /* not an error */
+  error = gdk_error_trap_pop ();
+  g_assert (error == Success);
+  error = gdk_error_trap_pop ();
+  g_assert (error == BadValue);
+
+  /* non-roundtrip non-error request after error request, inside trap */
+  gdk_error_trap_push ();
+  XSetCloseDownMode (d, 12345);
+  XMapWindow (d, DefaultRootWindow (d));
+  error = gdk_error_trap_pop ();
+  g_assert (error == BadValue);
+
+  /* a non-roundtrip non-error request before error request, inside trap */
+  gdk_error_trap_push ();
+  XMapWindow (d, DefaultRootWindow (d));
+  XSetCloseDownMode (d, 12345);
+  error = gdk_error_trap_pop ();
+  g_assert (error == BadValue);
+
+  /* Not part of any test, just a double-check
+   * that all errors have arrived
+   */
+  XSync (d, TRUE);
+}
+
+gint
+main (gint argc, gchar *argv[])
+{
+  GdkDisplay *extra_display;
+
+  gtk_init (&argc, &argv);
+
+  test_error_trapping (gdk_display_get_default ());
+
+  extra_display = gdk_display_open (NULL);
+  test_error_trapping (extra_display);
+  gdk_display_close (extra_display);
+
+  test_error_trapping (gdk_display_get_default ());
+
+  /* open a display with a trap pushed and see if we
+   * get confused
+   */
+  gdk_error_trap_push ();
+  gdk_error_trap_push ();
+
+  extra_display = gdk_display_open (NULL);
+  test_error_trapping (extra_display);
+  gdk_display_close (extra_display);
+
+  gdk_error_trap_pop_ignored ();
+  gdk_error_trap_pop_ignored ();
+
+  test_error_trapping (gdk_display_get_default ());
+
+  /* reassure us that the tests ran. */
+  g_print("All errors properly trapped.\n");
+
   return 0;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]