[PATCH v2:libXt] Add test framework similar to xserver and use it to test XtAsprintf

Alan Coopersmith alan.coopersmith at oracle.com
Wed Mar 9 20:19:16 PST 2011


Only two simple test cases to start with:
 - compares the results of snprintf of a short string to a static buffer
	with the new buffer returned by XtAsprintf.
 - compare the results of using XtAsprintf to replicate a portion of a
	very long string with the original string.

Uses malloc debugging flags for various platforms to try to catch errors
with uninitialized memory (such as the recently fixed failure to terminate
the string).

Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
---

v2: Thanks to suggestions from many on #xorg-devel IRC, set malloc debugging
    environment variables for common platforms (only tested on Solaris though)

    As suggested by KiBi, add a test case long enough to force XtAsprintf to
    re-run snprintf after allocating a larger buffer than the builtin default.

    The configure.ac changes should eventually be replaced by new XORG_*
    macros once we define them.

 Makefile.am      |    2 +-
 configure.ac     |   33 ++++++++++++++++
 test/Alloc.c     |  112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/Makefile.am |   12 ++++++
 4 files changed, 158 insertions(+), 1 deletions(-)
 create mode 100644 test/Alloc.c
 create mode 100644 test/Makefile.am

diff --git a/Makefile.am b/Makefile.am
index e9e0316..8ef09ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@
 #  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 #  PERFORMANCE OF THIS SOFTWARE.
 
-SUBDIRS = util src include man specs
+SUBDIRS = util src include man specs test
 
 ACLOCAL_AMFLAGS = -I m4
 
diff --git a/configure.ac b/configure.ac
index 8945729..104dcf3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,38 @@ if test "x$XKB" = "xyes" ; then
 	AC_DEFINE(XKB, 1, [Define to 1 to use XKB for keysym resolution.])
 fi
 
+AC_ARG_ENABLE(unit-tests,    AS_HELP_STRING([--enable-unit-tests],
+                                  [Enable unit-tests (default: auto)]),
+                                [UNITTESTS=$enableval], [UNITTESTS=auto])
+if test "x$UNITTESTS" != xno ; then
+       PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.16],
+                         [HAVE_GLIB=yes], [HAVE_GLIB=no])
+fi
+if test "x$UNITTESTS" = xyes; then
+       if test "x$HAVE_GLIB" = xno; then
+           AC_MSG_ERROR([glib required to build unit tests])
+       fi
+elif test "x$UNITTESTS" = xauto; then
+       UNITTESTS="$HAVE_GLIB"
+fi
+
+AM_CONDITIONAL(UNITTESTS, [test "x$UNITTESTS" = xyes])
+
+# Memory checking support
+case $host_os in
+     solaris*)
+        AC_CHECK_LIB([umem], [umem_alloc],
+            [MALLOC_DEBUG_ENV='LD_PRELOAD=libumem.so UMEM_DEBUG=default'])
+        ;;
+     *bsd*|darwin*)
+        MALLOC_DEBUG_ENV='MallocPreScribble=1 MallocScribble=1'
+        ;;
+     *) # Assume glibc
+        MALLOC_DEBUG_ENV='MALLOC_PERTURB_=255'
+        ;;
+esac
+AC_SUBST([MALLOC_DEBUG_ENV])
+
 # Replaces XFileSearchPathDefault from Imake configs
 XFILESEARCHPATHDEFAULT='$(sysconfdir)/X11/%L/%T/%N%C%S:$(sysconfdir)/X11/%l/%T/%N%C%S:$(sysconfdir)/X11/%T/%N%C%S:$(sysconfdir)/X11/%L/%T/%N%S:$(sysconfdir)/X11/%l/%T/%N%S:$(sysconfdir)/X11/%T/%N%S:$(datadir)/X11/%L/%T/%N%C%S:$(datadir)/X11/%l/%T/%N%C%S:$(datadir)/X11/%T/%N%C%S:$(datadir)/X11/%L/%T/%N%S:$(datadir)/X11/%l/%T/%N%S:$(datadir)/X11/%T/%N%S:$(libdir)/X11/%L/%T/%N%C%S:$(libdir)/X11/%l/%T/%N%C%S:$(libdir)/X11/%T/%N%C%S:$(libdir)/X11/%L/%T/%N%S:$(libdir)/X11/%l/%T/%N%S:$(libdir)/X11/%T/%N%S'
 
@@ -144,5 +176,6 @@ AC_CONFIG_FILES([Makefile
 		include/Makefile
 		man/Makefile
 		specs/Makefile
+		test/Makefile
 		xt.pc])
 AC_OUTPUT
diff --git a/test/Alloc.c b/test/Alloc.c
new file mode 100644
index 0000000..8a70b5f
--- /dev/null
+++ b/test/Alloc.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Intrinsic.h>
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+static const char *program_name;
+
+/* Just a long string of characters to pull from */
+const char test_chars[] =
+    "|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel|"
+    "|010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si |"
+    "|020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb|"
+    "|030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us |"
+    "|040 sp |041  ! |042  \" |043  # |044  $ |045  % |046  & |047  ' |"
+    "|050  ( |051  ) |052  * |053  + |054  , |055  - |056  . |057  / |"
+    "|060  0 |061  1 |062  2 |063  3 |064  4 |065  5 |066  6 |067  7 |"
+    "|070  8 |071  9 |072  : |073  ; |074  < |075  = |076  > |077  ? |"
+    "|100  @ |101  A |102  B |103  C |104  D |105  E |106  F |107  G |"
+    "|110  H |111  I |112  J |113  K |114  L |115  M |116  N |117  O |"
+    "|120  P |121  Q |122  R |123  S |124  T |125  U |126  V |127  W |"
+    "|130  X |131  Y |132  Z |133  [ |134  \\ |135  ] |136  ^ |137  _ |"
+    "|140  ` |141  a |142  b |143  c |144  d |145  e |146  f |147  g |"
+    "|150  h |151  i |152  j |153  k |154  l |155  m |156  n |157  o |"
+    "|160  p |161  q |162  r |163  s |164  t |165  u |166  v |167  w |"
+    "|170  x |171  y |172  z |173  { |174  | |175  } |176  ~ |177 del|"
+    "| 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel|"
+    "| 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si |"
+    "| 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb|"
+    "| 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us |"
+    "| 20 sp | 21  ! | 22  \" | 23  # | 24  $ | 25  % | 26  & | 27  ' |"
+    "| 28  ( | 29  ) | 2a  * | 2b  + | 2c  , | 2d  - | 2e  . | 2f  / |"
+    "| 30  0 | 31  1 | 32  2 | 33  3 | 34  4 | 35  5 | 36  6 | 37  7 |"
+    "| 38  8 | 39  9 | 3a  : | 3b  ; | 3c  < | 3d  = | 3e  > | 3f  ? |"
+    "| 40  @ | 41  A | 42  B | 43  C | 44  D | 45  E | 46  F | 47  G |"
+    "| 48  H | 49  I | 4a  J | 4b  K | 4c  L | 4d  M | 4e  N | 4f  O |"
+    "| 50  P | 51  Q | 52  R | 53  S | 54  T | 55  U | 56  V | 57  W |"
+    "| 58  X | 59  Y | 5a  Z | 5b  [ | 5c  \\ | 5d  ] | 5e  ^ | 5f  _ |"
+    "| 60  ` | 61  a | 62  b | 63  c | 64  d | 65  e | 66  f | 67  g |"
+    "| 68  h | 69  i | 6a  j | 6b  k | 6c  l | 6d  m | 6e  n | 6f  o |"
+    "| 70  p | 71  q | 72  r | 73  s | 74  t | 75  u | 76  v | 77  w |"
+    "| 78  x | 79  y | 7a  z | 7b  { | 7c  | | 7d  } | 7e  ~ | 7f del|";
+
+
+/* Test a simple short string & int */
+static void test_XtAsprintf_short(void)
+{
+    char snbuf[1024];
+    char *asbuf;
+    gint32 r = g_test_rand_int();
+    int snlen, aslen;
+
+    snlen = snprintf(snbuf, sizeof(snbuf), "%s: %d\n", program_name, r);
+    aslen = XtAsprintf(&asbuf, "%s: %d\n", program_name, r);
+
+    g_assert(asbuf != NULL);
+    g_assert(snlen == aslen);
+    g_assert(strcmp(snbuf, asbuf) == 0);
+    g_assert(asbuf[aslen] == '\0');
+}
+
+/* Test a string long enough to be past the 256 character limit that
+   makes XtAsprintf re-run snprintf after allocating memory */
+static void test_XtAsprintf_long(void)
+{
+    char *asbuf;
+    int aslen;
+    gint r1 = g_test_rand_int_range(0, 256);
+    gint r2 = g_test_rand_int_range(1024, sizeof(test_chars) - r1);
+
+    aslen = XtAsprintf(&asbuf, "%.*s", r2, test_chars + r1);
+
+    g_assert(asbuf != NULL);
+    g_assert(aslen = r2);
+    g_assert(strncmp(asbuf, test_chars + r1, r2) == 0);
+    g_assert(asbuf[aslen] == '\0');
+}
+
+int main(int argc, char** argv)
+{
+    program_name = argv[0];
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
+
+    g_test_add_func("/Alloc/XtAsprintf/short", test_XtAsprintf_short);
+    g_test_add_func("/Alloc/XtAsprintf/long", test_XtAsprintf_long);
+
+    return g_test_run();
+}
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..6ea3888
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,12 @@
+if UNITTESTS
+check_PROGRAMS = Alloc
+
+TESTS=$(check_PROGRAMS)
+
+AM_CFLAGS = $(CWARNFLAGS) $(XT_CFLAGS) $(GLIB_CFLAGS)
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include
+LDADD= $(top_builddir)/src/libXt.la $(GLIB_LIBS)
+
+TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
+
+endif
-- 
1.7.3.2



More information about the xorg-devel mailing list