libXmu: Branch 'master' - 11 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 7 17:31:22 UTC 2023


 .gitlab-ci.yml        |    9 +
 configure.ac          |   12 ++
 test/CursorName.c     |  139 +++++++++++++++++++++++++++++
 test/EditResStream.c  |   48 ++++++----
 test/Lower.c          |  238 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test/Makefile.am      |   71 ++++++++++++++
 test/ReadBitmapData.c |  138 ++++++++++++++++++++++++++++
 test/StrToBS.c        |  164 ++++++++++++++++++++++++++++++++++
 test/StrToGrav.c      |  200 ++++++++++++++++++++++++++++++++++++++++++
 test/StrToJust.c      |  165 ++++++++++++++++++++++++++++++++++
 test/StrToLong.c      |  166 ++++++++++++++++++++++++++++++++++
 test/StrToOrnt.c      |  165 ++++++++++++++++++++++++++++++++++
 test/StrToShap.c      |  197 +++++++++++++++++++++++++++++++++++++++++
 test/bitmaps/plaid    |   11 ++
 test/bitmaps/star     |    8 +
 test/bitmaps/xlogo64  |   46 +++++++++
 test/reallocarray.c   |  228 +++++++++++++++++++++++++++++++++++++++++++++++
 test/tap-test         |    2 
 18 files changed, 1983 insertions(+), 24 deletions(-)

New commits:
commit 35eb34a9513467a88bf5e59f5cb44beb993753db
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Mar 27 13:34:27 2023 -0700

    test: Add simple test cases for functions in src/reallocarray.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/configure.ac b/configure.ac
index 48c761a..ce7ace2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,6 +48,10 @@ AC_REQUIRE_AUX_FILE([tap-driver.sh])
 XORG_ENABLE_UNIT_TESTS
 XORG_WITH_GLIB([2.46])
 XORG_MEMORY_CHECK_FLAGS
+if test "x$enable_unit_tests" != "xno" ; then
+       AC_CHECK_FUNCS([malloc_usable_size])
+       AC_CHECK_HEADERS([malloc.h])
+fi
 
 AC_CONFIG_FILES([Makefile
 		doc/Makefile
diff --git a/test/Makefile.am b/test/Makefile.am
index 807276a..f15fc0e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,6 +35,7 @@ check_PROGRAMS = \
         EditResStream \
         Lower \
         ReadBitmapData \
+        reallocarray \
         StrToBS \
         StrToGrav \
         StrToJust \
@@ -63,6 +64,9 @@ Lower_LDADD = $(XMUU_TEST_LIBS)
 ReadBitmapData_SOURCES = ReadBitmapData.c
 ReadBitmapData_LDADD = $(XMU_TEST_LIBS)
 
+reallocarray_SOURCES = reallocarray.c
+reallocarray_LDADD = $(GLIB_LIBS)
+
 StrToBS_SOURCES = StrToBS.c
 StrToBS_LDADD = $(XMU_TEST_LIBS)
 
diff --git a/test/reallocarray.c b/test/reallocarray.c
new file mode 100644
index 0000000..878d05e
--- /dev/null
+++ b/test/reallocarray.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/Xfuncproto.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <sys/resource.h>
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
+
+/* Tell gcc not to warn that we're asking for impossible sizes in some tests */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
+
+/*
+ * To ensure we're testing our Xmureallocarray and not any system-provided
+ * reallocarray, we directly include code being tested, since it won't be
+ * built into libXmu on platforms with a system-provided function.
+ */
+#include "../src/reallocarray.c"
+
+
+#ifndef g_assert_no_errno /* defined in glib 2.66 & later*/
+#define g_assert_no_errno(expr) g_assert_cmpint((expr), >=, 0)
+#endif
+
+/*
+ * Check that allocations point to properly aligned memory.
+ * For libXmu, we consider that to be aligned to an 8-byte (64-bit) boundary.
+ */
+#define EXPECTED_ALIGNMENT 8
+
+#define CHECK_ALIGNMENT(ptr) \
+    g_assert_cmpint(((uintptr_t)ptr) % EXPECTED_ALIGNMENT, ==, 0)
+
+/* Check that allocations point to expected amounts of memory, as best we can. */
+#ifdef HAVE_MALLOC_USABLE_SIZE
+# define CHECK_SIZE(ptr, size) do {		\
+    size_t ps = malloc_usable_size(ptr);	\
+    g_assert_cmpint(ps, >=, (size));		\
+} while (0)
+#else
+# define CHECK_SIZE(ptr, size) *(((char *)ptr) + ((size) - 1)) = 0
+#endif
+
+/* Limit we set for memory allocation to be able to test failure cases */
+#define ALLOC_LIMIT (INT_MAX / 4)
+
+/* Square root of SIZE_MAX+1 */
+#define SQRT_SIZE_MAX ((size_t)1 << (sizeof (size_t) * 4))
+
+
+/* Make sure Xmureallocarray() works for a non-zero amount of memory */
+static void test_Xmureallocarray_normal(void)
+{
+    void *p, *p2;
+    char *p3;
+
+    errno = 0;
+
+    /* Make sure reallocarray with a NULL pointer acts as malloc */
+    p = Xmureallocarray(NULL, 8, 14);
+    g_assert_nonnull(p);
+    CHECK_ALIGNMENT(p);
+    CHECK_SIZE(p, 8 * 14);
+
+    /* make sure we can write to all the allocated memory */
+    memset(p, 'A', 8 * 14);
+
+    /* create another block after the first */
+    p2 = Xmureallocarray(NULL, 1, 73);
+    g_assert_nonnull(p2);
+    CHECK_ALIGNMENT(p2);
+    CHECK_SIZE(p2, 73);
+
+    /* now resize the first */
+    p3 = Xmureallocarray(p, 73, 14);
+    g_assert_nonnull(p3);
+    CHECK_ALIGNMENT(p3);
+    CHECK_SIZE(p3, 73 * 14);
+    /* verify previous values are still present */
+    for (int i = 0; i < (8 * 14); i++) {
+        g_assert_cmpint(p3[i], ==, 'A');
+    }
+
+    free(p3);
+    free(p2);
+    g_assert_cmpint(errno, ==, 0);
+}
+
+/* Make sure Xmureallocarray(0) returns a valid pointer as expected */
+static void test_Xmureallocarray_zero(void)
+{
+    void *p, *p2;
+
+    errno = 0;
+
+    p = Xmureallocarray(NULL, 0, 0);
+    g_assert_nonnull(p);
+
+    p2 = Xmureallocarray(p, 0, 0);
+#ifdef MALLOC_0_RETURNS_NULL
+    g_assert_null(p);
+#else
+    g_assert_nonnull(p);
+#endif
+
+    free(p2);
+    g_assert_cmpint(errno, ==, 0);
+}
+
+/* Make sure sizes larger than the limit we set in main() fail */
+static void test_Xmureallocarray_oversize(void)
+{
+    void *p, *p2;
+
+    /* Pick a number of elements between 1 & 16K */
+    guint32 num = g_test_rand_int_range(1, (16 * 1024));
+    /* Pick a size between 1 & 16K */
+    guint32 size = g_test_rand_int_range(1, (16 * 1024));
+
+    p = Xmureallocarray(NULL, num, size);
+    g_assert_nonnull(p);
+    CHECK_ALIGNMENT(p);
+    CHECK_SIZE(p, num * size);
+
+    p2 = Xmureallocarray(p, 2, ALLOC_LIMIT);
+    g_assert_null(p2);
+    g_assert_cmpint(errno, ==, ENOMEM);
+
+    errno = 0;
+    free(p);
+    g_assert_cmpint(errno, ==, 0);
+}
+
+/* Make sure Xmureallocarray catches integer overflow if possible, by requesting
+ * sizes that are so large that they cause overflows when either adding the
+ * reallocarray data block overhead or aligning.
+ */
+static void test_Xmureallocarray_overflow(void)
+{
+    void *p, *p2;
+
+    /* Pick a number of elements between 1 & 16K */
+    guint32 num = g_test_rand_int_range(1, (16 * 1024));
+    /* Pick a size between 1 & 16K */
+    guint32 size = g_test_rand_int_range(1, (16 * 1024));
+
+    p = Xmureallocarray(NULL, num, size);
+    g_assert_nonnull(p);
+    CHECK_ALIGNMENT(p);
+    CHECK_SIZE(p, num * size);
+
+    p2 = Xmureallocarray(p, 1, SIZE_MAX);
+    g_assert_null(p2);
+    g_assert_cmpint(errno, ==, ENOMEM);
+
+    /* SQRT_SIZE_MAX * SQRT_SIZE_MAX == 0 due to overflow */
+    p2 = Xmureallocarray(p, SQRT_SIZE_MAX, SQRT_SIZE_MAX);
+    g_assert_null(p2);
+    g_assert_cmpint(errno, ==, ENOMEM);
+
+    /* Overflows to a small positive number */
+    p2 = Xmureallocarray(p, SQRT_SIZE_MAX + 1, SQRT_SIZE_MAX);
+    g_assert_null(p2);
+    g_assert_cmpint(errno, ==, ENOMEM);
+
+    errno = 0;
+    free(p);
+    g_assert_cmpint(errno, ==, 0);
+}
+#pragma GCC diagnostic pop
+
+int main(int argc, char** argv)
+{
+    struct rlimit lim;
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    /* Set a memory limit so we can test allocations over that size fail */
+    g_assert_no_errno(getrlimit(RLIMIT_AS, &lim));
+    if (lim.rlim_cur > ALLOC_LIMIT) {
+        lim.rlim_cur = ALLOC_LIMIT;
+        g_assert_no_errno(setrlimit(RLIMIT_AS, &lim));
+    }
+
+    g_test_add_func("/reallocarray/Xmureallocarray/normal",
+                    test_Xmureallocarray_normal);
+    g_test_add_func("/reallocarray/Xmureallocarray/zero",
+                    test_Xmureallocarray_zero);
+    g_test_add_func("/reallocarray/Xmureallocarray/oversize",
+                    test_Xmureallocarray_oversize);
+    g_test_add_func("/reallocarray/Xmureallocarray/overflow",
+                    test_Xmureallocarray_overflow);
+
+    return g_test_run();
+}
commit d729c59e46a939f5179e711dec9a53ef1e9cd1b4
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Mar 27 09:06:08 2023 -0700

    test: Add simple test cases for functions in src/StrToShap.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 5fc2310..807276a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -39,7 +39,8 @@ check_PROGRAMS = \
         StrToGrav \
         StrToJust \
         StrToLong \
-        StrToOrnt
+        StrToOrnt \
+        StrToShap
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -77,6 +78,9 @@ StrToLong_LDADD = $(XMU_TEST_LIBS)
 StrToOrnt_SOURCES = StrToOrnt.c
 StrToOrnt_LDADD = $(XMU_TEST_LIBS)
 
+StrToShap_SOURCES = StrToShap.c
+StrToShap_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToShap.c b/test/StrToShap.c
new file mode 100644
index 0000000..c73d5eb
--- /dev/null
+++ b/test/StrToShap.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToShap.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/CharSet.h>
+#include <X11/ThreadsI.h>
+#include <glib.h>
+#include <setjmp.h>
+
+struct TestData {
+    const char *name;
+    int value;
+};
+
+static const struct TestData data[] = {
+        { XtERectangle,         XmuShapeRectangle },
+        { XtEOval,              XmuShapeOval },
+        { XtEEllipse,           XmuShapeEllipse },
+        { XtERoundedRectangle,  XmuShapeRoundedRectangle },
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+/* Environment saved by setjmp() */
+static jmp_buf jmp_env;
+
+static void _X_NORETURN
+xt_error_handler(String message)
+{
+    g_test_message("Caught error: %s", message ? message : "<NULL>");
+    warning_count++;
+
+    UNLOCK_PROCESS;
+
+    /* Avoid exit() in XtErrorMsg() */
+    longjmp(jmp_env, 1);
+}
+
+
+static void
+test_XmuCvtStringToShapeStyle(void)
+{
+    XrmValue from, to;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[32];
+
+    g_test_message("test_XmuCvtStringToShapeStyle starting");
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToShapeStyle(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtStringToShapeStyle(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+
+
+        XmuNCopyISOLatin1Uppered(namebuf, data[i].name, sizeof(namebuf));
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtStringToShapeStyle(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+    }
+
+    /* No warning is currently issued for unused args */
+#if 0
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToShapeStyle with extra args");
+    XmuCvtStringToShapeStyle(NULL, &args, &nargs, &from, &to, NULL);
+    g_assert_cmpint(warning_count, >, 0);
+#endif
+
+    /* Verify warning issued for unknown string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToShapeStyle(%s)", from.addr);
+    if (setjmp(jmp_env) == 0) {
+        ret = XmuCvtStringToShapeStyle(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+    } else {
+        /* We jumped here from error handler as expected. */
+    }
+    g_assert_cmpint(warning_count, >, 0);
+    g_test_message("test_XmuCvtStringToShapeStyle completed");
+}
+
+static void
+test_XmuCvtShapeStyleToString(void)
+{
+    XrmValue from, to;
+    int value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[32];
+
+    g_test_message("test_XmuCvtShapeStyleToString starting");
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("ShapeStyleToString(%d)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(int *);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtShapeStyleToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 4;
+        ret = XmuCvtShapeStyleToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtShapeStyleToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+    }
+
+    /* Verify warning and return of False for invalid value */
+    warning_count = 0;
+    value = 1984;
+    from.addr = (XPointer) &value;
+    g_test_message("ShapeStyleToString(%d)", value);
+    ret = XmuCvtShapeStyleToString(NULL, NULL, &nargs, &from, &to, NULL);
+    g_assert_cmpint(ret, ==, False);
+    g_assert_cmpint(warning_count, >, 0);
+    g_test_message("test_XmuCvtShapeStyleToString completed");
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+    XtSetErrorHandler(xt_error_handler);
+
+    g_test_add_func("/StrToShap/XmuCvtStringToShapeStyle",
+                    test_XmuCvtStringToShapeStyle);
+    g_test_add_func("/StrToShap/XmuCvtShapeStyleToString",
+                    test_XmuCvtShapeStyleToString);
+
+
+    return g_test_run();
+}
commit 73764fa6f672a2aa540cae72155ba4ebfa1bcf4f
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Mar 27 08:47:44 2023 -0700

    test: Add simple test cases for functions in src/StrToOrnt.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 3fc5f26..5fc2310 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -38,7 +38,8 @@ check_PROGRAMS = \
         StrToBS \
         StrToGrav \
         StrToJust \
-        StrToLong
+        StrToLong \
+        StrToOrnt
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -73,6 +74,9 @@ StrToJust_LDADD = $(XMU_TEST_LIBS)
 StrToLong_SOURCES = StrToLong.c
 StrToLong_LDADD = $(XMU_TEST_LIBS)
 
+StrToOrnt_SOURCES = StrToOrnt.c
+StrToOrnt_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToOrnt.c b/test/StrToOrnt.c
new file mode 100644
index 0000000..43e9d98
--- /dev/null
+++ b/test/StrToOrnt.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToOrnt.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/CharSet.h>
+#include <X11/StringDefs.h>
+#include <glib.h>
+
+struct TestData {
+    const char *name;
+    XtOrientation value;
+};
+
+static const struct TestData data[] = {
+        { XtEvertical,          XtorientVertical },
+        { XtEhorizontal,        XtorientHorizontal }
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+
+
+static void
+test_XmuCvtStringToOrientation(void)
+{
+    XrmValue from, to;
+    Cardinal nargs = 0;
+
+    char namebuf[16];
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToOrientation(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToOrientation(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(XtOrientation *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+
+
+        XmuNCopyISOLatin1Uppered(namebuf, data[i].name, sizeof(namebuf));
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToOrientation(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(XtOrientation *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+    }
+
+    /* No warning is currently issued for unused args */
+#if 0
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToOrientation with extra args");
+    XmuCvtStringToOrientation(&args, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+#endif
+
+    /* Verify warning issued for unknown string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToOrientation(%s)", from.addr);
+    XmuCvtStringToOrientation(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+static void
+test_XmuCvtOrientationToString(void)
+{
+    XrmValue from, to;
+    XtOrientation value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[16];
+
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("OrientationToString(%d)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(XtOrientation);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtOrientationToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 4;
+        ret = XmuCvtOrientationToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtOrientationToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+    }
+
+    /* Verify warning and return of False for invalid value */
+    warning_count = 0;
+    value = 1984;
+    from.addr = (XPointer) &value;
+    g_test_message("OrientationToString(%d)", value);
+    ret = XmuCvtOrientationToString(NULL, NULL, &nargs, &from, &to, NULL);
+    g_assert_cmpint(ret, ==, False);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+
+    g_test_add_func("/StrToOrnt/XmuCvtStringToOrientation",
+                    test_XmuCvtStringToOrientation);
+    g_test_add_func("/StrToOrnt/XmuCvtOrientationToString",
+                    test_XmuCvtOrientationToString);
+
+
+    return g_test_run();
+}
commit a5db0a3c95fbcc0ac3bf1711f9b28e5b76dcb49c
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Mar 27 08:30:18 2023 -0700

    test: Add simple test cases for functions in src/StrToLong.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 8091faf..3fc5f26 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -37,7 +37,8 @@ check_PROGRAMS = \
         ReadBitmapData \
         StrToBS \
         StrToGrav \
-        StrToJust
+        StrToJust \
+        StrToLong
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -69,6 +70,9 @@ StrToGrav_LDADD = $(XMU_TEST_LIBS)
 StrToJust_SOURCES = StrToJust.c
 StrToJust_LDADD = $(XMU_TEST_LIBS)
 
+StrToLong_SOURCES = StrToLong.c
+StrToLong_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToLong.c b/test/StrToLong.c
new file mode 100644
index 0000000..bac9db3
--- /dev/null
+++ b/test/StrToLong.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToLong.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmd.h>
+#include <glib.h>
+
+struct TestData {
+    const char *name;
+    long value;
+};
+
+static const struct TestData data[] = {
+    { "0", 0 },
+    { "12345678", 12345678 },
+    { "2147483647", 2147483647 },
+    { "-2147483647", -2147483647 },
+#ifdef LONG64
+    { "9223372036854775807", 9223372036854775807L },
+    { "-9223372036854775807", -9223372036854775807L }
+#endif
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+
+
+static void
+test_XmuCvtStringToLong(void)
+{
+    XrmValue from, to, args;
+    Cardinal nargs = 0;
+
+    char namebuf[32];
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToLong(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToLong(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(long *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(long));
+    }
+
+    /* Verify warning is issued for unused args */
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToLong with extra args");
+    XmuCvtStringToLong(&args, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+
+    /* Verify warning issued for non-numeric string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToLong(%s)", from.addr);
+    XmuCvtStringToLong(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+
+    /* Verify warning issued for empty string */
+    warning_count = 0;
+    from.addr = (char *) "";
+    nargs = 0;
+    g_test_message("StringToLong(%s)", from.addr);
+    XmuCvtStringToLong(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+static void
+test_XmuCvtLongToString(void)
+{
+    XrmValue from, to, args;
+    long value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[32];
+
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("LongToString(%ld)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(long *);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtLongToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 1;
+        ret = XmuCvtLongToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtLongToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+    }
+
+    /* Verify warning is issued for unused args */
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("LongToString with extra args");
+    XmuCvtLongToString(NULL, &args, &nargs, &from, &to, NULL);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+
+    g_test_add_func("/StrToLong/XmuCvtStringToLong",
+                    test_XmuCvtStringToLong);
+    g_test_add_func("/StrToLong/XmuCvtLongToString",
+                    test_XmuCvtLongToString);
+
+
+    return g_test_run();
+}
commit 4335c55ea6848665969c17a8bf19bdf39be3758b
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 17:58:47 2023 -0700

    test: Add simple test cases for functions in src/StrToJust.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 05940e5..8091faf 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -36,7 +36,8 @@ check_PROGRAMS = \
         Lower \
         ReadBitmapData \
         StrToBS \
-        StrToGrav
+        StrToGrav \
+        StrToJust
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -65,6 +66,9 @@ StrToBS_LDADD = $(XMU_TEST_LIBS)
 StrToGrav_SOURCES = StrToGrav.c
 StrToGrav_LDADD = $(XMU_TEST_LIBS)
 
+StrToJust_SOURCES = StrToJust.c
+StrToJust_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToJust.c b/test/StrToJust.c
new file mode 100644
index 0000000..cf2386e
--- /dev/null
+++ b/test/StrToJust.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToJust.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/CharSet.h>
+#include <glib.h>
+
+struct TestData {
+    const char *name;
+    int value;
+};
+
+static const struct TestData data[] = {
+        { XtEleft,	XtJustifyLeft },
+        { XtEcenter, 	XtJustifyCenter },
+        { XtEright, 	XtJustifyRight },
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+
+
+static void
+test_XmuCvtStringToJustify(void)
+{
+    XrmValue from, to;
+    Cardinal nargs = 0;
+
+    char namebuf[16];
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToJustify(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToJustify(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+
+
+        XmuNCopyISOLatin1Uppered(namebuf, data[i].name, sizeof(namebuf));
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToJustify(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+    }
+
+    /* No warning is currently issued for unused args */
+#if 0
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToJustify with extra args");
+    XmuCvtStringToJustify(&args, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+#endif
+
+    /* Verify warning issued for unknown string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToJustify(%s)", from.addr);
+    XmuCvtStringToJustify(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+static void
+test_XmuCvtJustifyToString(void)
+{
+    XrmValue from, to;
+    int value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[16];
+
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("JustifyToString(%d)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(int *);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtJustifyToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 4;
+        ret = XmuCvtJustifyToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtJustifyToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+    }
+
+    /* Verify warning and return of False for invalid value */
+    warning_count = 0;
+    value = 1984;
+    from.addr = (XPointer) &value;
+    g_test_message("JustifyToString(%d)", value);
+    ret = XmuCvtJustifyToString(NULL, NULL, &nargs, &from, &to, NULL);
+    g_assert_cmpint(ret, ==, False);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+
+    g_test_add_func("/StrToJust/XmuCvtStringToJustify",
+                    test_XmuCvtStringToJustify);
+    g_test_add_func("/StrToJust/XmuCvtJustifyToString",
+                    test_XmuCvtJustifyToString);
+
+
+    return g_test_run();
+}
commit 18c9c8968c91224df16cb06cd798a4ba6893b632
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 17:28:48 2023 -0700

    test: Add simple test cases for functions in src/StrToGrav.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 2daa571..05940e5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,7 +35,8 @@ check_PROGRAMS = \
         EditResStream \
         Lower \
         ReadBitmapData \
-        StrToBS
+        StrToBS \
+        StrToGrav
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -61,6 +62,9 @@ ReadBitmapData_LDADD = $(XMU_TEST_LIBS)
 StrToBS_SOURCES = StrToBS.c
 StrToBS_LDADD = $(XMU_TEST_LIBS)
 
+StrToGrav_SOURCES = StrToGrav.c
+StrToGrav_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToGrav.c b/test/StrToGrav.c
new file mode 100644
index 0000000..0adb504
--- /dev/null
+++ b/test/StrToGrav.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToGrav.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/CharSet.h>
+#include <glib.h>
+#include <setjmp.h>
+
+struct TestData {
+    const char *name;
+    int value;
+    Bool dupvalue; /* value maps to a different string already */
+};
+
+static const struct TestData data[] = {
+    { XtEForget,        ForgetGravity,          False },
+    { XtENorthWest,     NorthWestGravity,       False },
+    { XtENorth,         NorthGravity,           False },
+    { XtENorthEast,     NorthEastGravity,       False },
+    { XtEWest,          WestGravity,            False },
+    { XtECenter,        CenterGravity,          False },
+    { XtEEast,          EastGravity,            False },
+    { XtESouthWest,     SouthWestGravity,       False },
+    { XtESouth,         SouthGravity,           False },
+    { XtESouthEast,     SouthEastGravity,       False },
+    { XtEStatic,        StaticGravity,          False },
+    { XtEUnmap,         UnmapGravity,           True },
+    { XtEleft,          WestGravity,            True },
+    { XtEtop,           NorthGravity,           True },
+    { XtEright,         EastGravity,            True },
+    { XtEbottom,        SouthGravity,           True }
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+/* Environment saved by setjmp() */
+static jmp_buf jmp_env;
+
+static void _X_NORETURN
+xt_error_handler(String message)
+{
+    g_test_message("Caught error: %s", message ? message : "<NULL>");
+    warning_count++;
+
+    /* Avoid exit() in XtErrorMsg() */
+    longjmp(jmp_env, 1);
+}
+
+
+static void
+test_XmuCvtStringToGravity(void)
+{
+    XrmValue from, to, args;
+    Cardinal nargs = 0;
+
+    char namebuf[16];
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToGravity(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToGravity(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+
+
+        XmuNCopyISOLatin1Uppered(namebuf, data[i].name, sizeof(namebuf));
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToGravity(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+    }
+
+    /* Verify warning issued for unused args */
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToGravity with extra args");
+    XmuCvtStringToGravity(&args, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+
+    /* Verify warning issued for unknown string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToGravity(%s)", from.addr);
+    XmuCvtStringToGravity(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+static void
+test_XmuCvtGravityToString(void)
+{
+    XrmValue from, to;
+    int value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[16];
+
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        if (data[i].dupvalue == True) {
+            /* skip values that map to different names */
+            continue;
+        }
+
+        g_test_message("GravityToString(%d)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(int *);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtGravityToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        /* Unlike StrtoBS, this always returns string length in to.size */
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 4;
+        ret = XmuCvtGravityToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtGravityToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+    }
+
+    /* Verify warning and return of False for invalid value */
+    warning_count = 0;
+    value = 1984;
+    from.addr = (XPointer) &value;
+    g_test_message("GravityToString(%d)", value);
+    if (setjmp(jmp_env) == 0) {
+        ret = XmuCvtGravityToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+    } else {
+        /* We jumped here from error handler as expected. */
+    }
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+    XtSetErrorHandler(xt_error_handler);
+
+    g_test_add_func("/StrToGrav/XmuCvtStringToGravity",
+                    test_XmuCvtStringToGravity);
+    g_test_add_func("/StrToGrav/XmuCvtGravityToString",
+                    test_XmuCvtGravityToString);
+
+    return g_test_run();
+}
commit 3078ccc44c25a1e96c7cd48961092931f583525e
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 16:54:34 2023 -0700

    test: Add simple test cases for functions in src/StrToBS.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index b4d9172..2daa571 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,12 @@ AM_CFLAGS = $(CWARNFLAGS) $(XMU_CFLAGS) $(GLIB_CFLAGS)
 XMU_TEST_LIBS  = ${top_builddir}/src/libXmu.la $(XMU_LIBS) $(GLIB_LIBS)
 XMUU_TEST_LIBS = ${top_builddir}/src/libXmuu.la $(XMUU_LIBS) $(GLIB_LIBS)
 
-check_PROGRAMS = CursorName EditResStream Lower ReadBitmapData
+check_PROGRAMS = \
+        CursorName \
+        EditResStream \
+        Lower \
+        ReadBitmapData \
+        StrToBS
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -53,6 +58,9 @@ Lower_LDADD = $(XMUU_TEST_LIBS)
 ReadBitmapData_SOURCES = ReadBitmapData.c
 ReadBitmapData_LDADD = $(XMU_TEST_LIBS)
 
+StrToBS_SOURCES = StrToBS.c
+StrToBS_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
diff --git a/test/StrToBS.c b/test/StrToBS.c
new file mode 100644
index 0000000..d2e0a43
--- /dev/null
+++ b/test/StrToBS.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/StrToBS.c */
+#include "config.h"
+#include <X11/Xmu/Converters.h>
+#include <X11/Xmu/CharSet.h>
+#include <glib.h>
+
+struct TestData {
+    const char *name;
+    int value;
+};
+
+static const struct TestData data[] = {
+    { XtEnotUseful, NotUseful },
+    { XtEwhenMapped, WhenMapped },
+    { XtEalways, Always },
+    { XtEdefault, Always + WhenMapped + NotUseful}
+};
+#define DATA_ENTRIES (sizeof(data) / sizeof(data[0]))
+
+static int warning_count;
+
+static void
+xt_warning_handler(String message)
+{
+    g_test_message("Caught warning: %s", message ? message : "<NULL>");
+    warning_count++;
+}
+
+
+
+static void
+test_XmuCvtStringToBackingStore(void)
+{
+    XrmValue from, to, args;
+    Cardinal nargs = 0;
+
+    char namebuf[16];
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("StringToBackingStore(%s)", data[i].name);
+
+        strncpy(namebuf, data[i].name, sizeof(namebuf) - 1);
+        namebuf[sizeof(namebuf) - 1] = 0;
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToBackingStore(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+
+
+        XmuNCopyISOLatin1Uppered(namebuf, data[i].name, sizeof(namebuf));
+        from.addr = namebuf;
+        from.size = sizeof(char *);
+        XmuCvtStringToBackingStore(NULL, &nargs, &from, &to);
+        g_assert_cmpint(*(int *)to.addr, ==, data[i].value);
+        g_assert_cmpint(to.size, ==, sizeof(int));
+    }
+
+    /* Verify warning issued for unused args */
+    warning_count = 0;
+    nargs = 1;
+    g_test_message("StringToBackingStore with extra args");
+    XmuCvtStringToBackingStore(&args, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+
+    /* Verify warning issued for unknown string */
+    warning_count = 0;
+    from.addr = (char *) "DoesNotExist";
+    nargs = 0;
+    g_test_message("StringToBackingStore(%s)", from.addr);
+    XmuCvtStringToBackingStore(NULL, &nargs, &from, &to);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+static void
+test_XmuCvtBackingStoreToString(void)
+{
+    XrmValue from, to;
+    int value;
+    Cardinal nargs = 0;
+    Boolean ret;
+    char namebuf[16];
+
+
+    for (unsigned int i = 0; i < DATA_ENTRIES; i++) {
+        g_test_message("BackingStoreToString(%d)", data[i].value);
+
+        value = data[i].value;
+        from.addr = (XPointer) &value;
+        from.size = sizeof(int *);
+
+        /* First test without providing a buffer to copy the string into */
+        to.addr = NULL;
+        to.size = 0;
+        ret = XmuCvtBackingStoreToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+
+        /* Then test with a buffer that's too small to copy the string into */
+        to.addr = namebuf;
+        to.size = 4;
+        ret = XmuCvtBackingStoreToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, False);
+        g_assert_cmpint(to.size, ==, strlen(data[i].name) + 1);
+
+        /* Then test with a buffer that's big enough to copy the string into */
+        to.addr = namebuf;
+        to.size = sizeof(namebuf);
+        ret = XmuCvtBackingStoreToString(NULL, NULL, &nargs, &from, &to, NULL);
+        g_assert_cmpint(ret, ==, True);
+        g_assert_cmpstr(to.addr, ==, data[i].name);
+        g_assert_cmpint(to.size, ==, sizeof(char *));
+    }
+
+    /* Verify warning and return of False for invalid value */
+    warning_count = 0;
+    value = 1984;
+    from.addr = (XPointer) &value;
+    g_test_message("BackingStoreToString(%d)", value);
+    ret = XmuCvtBackingStoreToString(NULL, NULL, &nargs, &from, &to, NULL);
+    g_assert_cmpint(ret, ==, False);
+    g_assert_cmpint(warning_count, >, 0);
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    XtSetWarningHandler(xt_warning_handler);
+
+    g_test_add_func("/StrToBS/XmuCvtStringToBackingStore",
+                    test_XmuCvtStringToBackingStore);
+    g_test_add_func("/StrToBS/XmuCvtBackingStoreToString",
+                    test_XmuCvtBackingStoreToString);
+
+
+    return g_test_run();
+}
commit f7ad1689cbdf8b026b57844d584fdd7b5df3700b
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 15:35:12 2023 -0700

    test: Add simple test cases for functions in src/Lower.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Lower.c b/test/Lower.c
new file mode 100644
index 0000000..2ad9ded
--- /dev/null
+++ b/test/Lower.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for functions in src/Lower.c */
+#include "config.h"
+#include <X11/Xmu/CharSet.h>
+#include <X11/Xmu/SysUtil.h>
+#define  XK_LATIN1
+#include <X11/keysymdef.h>
+#include <glib.h>
+#include <string.h>
+
+static const char upper[] = {
+    XK_space, XK_exclam, XK_quotedbl, XK_numbersign, XK_dollar, XK_percent,
+    XK_ampersand, XK_apostrophe, XK_quoteright, XK_parenleft, XK_parenright,
+    XK_asterisk, XK_plus, XK_comma, XK_minus, XK_period, XK_slash,
+    XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9,
+    XK_colon, XK_semicolon, XK_less, XK_equal, XK_greater, XK_question, XK_at,
+    XK_A, XK_B, XK_C, XK_D, XK_E, XK_F, XK_G, XK_H, XK_I, XK_J, XK_K, XK_L, XK_M,
+    XK_N, XK_O, XK_P, XK_Q, XK_R, XK_S, XK_T, XK_U, XK_V, XK_W, XK_X, XK_Y, XK_Z,
+    XK_bracketleft, XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore,
+    XK_grave, XK_quoteleft, XK_braceleft, XK_bar, XK_braceright, XK_asciitilde,
+    XK_exclamdown, XK_cent, XK_sterling, XK_currency, XK_yen, XK_brokenbar,
+    XK_section, XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
+    XK_notsign, XK_hyphen, XK_registered, XK_macron, XK_degree, XK_plusminus,
+    XK_twosuperior, XK_threesuperior, XK_acute, XK_mu, XK_paragraph,
+    XK_periodcentered, XK_cedilla, XK_onesuperior, XK_masculine,
+    XK_guillemotright, XK_onequarter, XK_onehalf, XK_threequarters,
+    XK_questiondown, XK_multiply, XK_division,
+    XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, XK_Adiaeresis, XK_Aring,
+    XK_AE, XK_Ccedilla, XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
+    XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, XK_ETH, XK_Ntilde,
+    XK_Ograve, XK_Oacute, XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_Oslash,
+    XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, XK_Udiaeresis, XK_Yacute,
+    XK_THORN, XK_ydiaeresis, '\0'
+};
+
+static const char lower[] = {
+    XK_space, XK_exclam, XK_quotedbl, XK_numbersign, XK_dollar, XK_percent,
+    XK_ampersand, XK_apostrophe, XK_quoteright, XK_parenleft, XK_parenright,
+    XK_asterisk, XK_plus, XK_comma, XK_minus, XK_period, XK_slash,
+    XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9,
+    XK_colon, XK_semicolon, XK_less, XK_equal, XK_greater, XK_question, XK_at,
+    XK_a, XK_b, XK_c, XK_d, XK_e, XK_f, XK_g, XK_h, XK_i, XK_j, XK_k, XK_l, XK_m,
+    XK_n, XK_o, XK_p, XK_q, XK_r, XK_s, XK_t, XK_u, XK_v, XK_w, XK_x, XK_y, XK_z,
+    XK_bracketleft, XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore,
+    XK_grave, XK_quoteleft, XK_braceleft, XK_bar, XK_braceright, XK_asciitilde,
+    XK_exclamdown, XK_cent, XK_sterling, XK_currency, XK_yen, XK_brokenbar,
+    XK_section, XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
+    XK_notsign, XK_hyphen, XK_registered, XK_macron, XK_degree, XK_plusminus,
+    XK_twosuperior, XK_threesuperior, XK_acute, XK_mu, XK_paragraph,
+    XK_periodcentered, XK_cedilla, XK_onesuperior, XK_masculine,
+    XK_guillemotright, XK_onequarter, XK_onehalf, XK_threequarters,
+    XK_questiondown, XK_multiply, XK_division,
+    XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, XK_adiaeresis, XK_aring,
+    XK_ae, XK_ccedilla, XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
+    XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, XK_eth, XK_ntilde,
+    XK_ograve, XK_oacute, XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_oslash,
+    XK_ooblique, XK_ugrave, XK_uacute, XK_ucircumflex, XK_udiaeresis, XK_yacute,
+    XK_thorn, XK_ydiaeresis, '\0'
+};
+
+static const char mixed[] = {
+    XK_space, XK_exclam, XK_quotedbl, XK_numbersign, XK_dollar, XK_percent,
+    XK_ampersand, XK_apostrophe, XK_quoteright, XK_parenleft, XK_parenright,
+    XK_asterisk, XK_plus, XK_comma, XK_minus, XK_period, XK_slash,
+    XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9,
+    XK_colon, XK_semicolon, XK_less, XK_equal, XK_greater, XK_question, XK_at,
+    XK_a, XK_b, XK_c, XK_d, XK_e, XK_f, XK_g, XK_h, XK_i, XK_j, XK_k, XK_l, XK_m,
+    XK_N, XK_O, XK_P, XK_Q, XK_R, XK_S, XK_T, XK_U, XK_V, XK_W, XK_X, XK_Y, XK_Z,
+    XK_bracketleft, XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore,
+    XK_grave, XK_quoteleft, XK_braceleft, XK_bar, XK_braceright, XK_asciitilde,
+    XK_exclamdown, XK_cent, XK_sterling, XK_currency, XK_yen, XK_brokenbar,
+    XK_section, XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
+    XK_notsign, XK_hyphen, XK_registered, XK_macron, XK_degree, XK_plusminus,
+    XK_twosuperior, XK_threesuperior, XK_acute, XK_mu, XK_paragraph,
+    XK_periodcentered, XK_cedilla, XK_onesuperior, XK_masculine,
+    XK_guillemotright, XK_onequarter, XK_onehalf, XK_threequarters,
+    XK_questiondown, XK_multiply, XK_division,
+    XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, XK_adiaeresis, XK_aring,
+    XK_AE, XK_Ccedilla, XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
+    XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, XK_eth, XK_ntilde,
+    XK_Ograve, XK_Oacute, XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_Oslash,
+    XK_ooblique, XK_ugrave, XK_uacute, XK_ucircumflex, XK_udiaeresis, XK_yacute,
+    XK_THORN, XK_ydiaeresis, '\0'
+};
+
+#define DATA_LEN sizeof(upper)
+
+static void
+test_XmuCopyISOLatin1Lowered(void)
+{
+    char buf[DATA_LEN];
+
+    XmuCopyISOLatin1Lowered(buf, upper);
+    g_assert_cmpstr(buf, ==, lower);
+
+    XmuCopyISOLatin1Lowered(buf, lower);
+    g_assert_cmpstr(buf, ==, lower);
+
+    XmuCopyISOLatin1Lowered(buf, mixed);
+    g_assert_cmpstr(buf, ==, lower);
+}
+
+static void
+test_XmuCopyISOLatin1Uppered(void)
+{
+    char buf[DATA_LEN];
+
+    XmuCopyISOLatin1Uppered(buf, upper);
+    g_assert_cmpstr(buf, ==, upper);
+
+    XmuCopyISOLatin1Uppered(buf, lower);
+    g_assert_cmpstr(buf, ==, upper);
+
+    XmuCopyISOLatin1Uppered(buf, mixed);
+    g_assert_cmpstr(buf, ==, upper);
+}
+
+static void
+test_XmuNCopyISOLatin1Lowered(void)
+{
+    char buf[DATA_LEN];
+
+    XmuNCopyISOLatin1Lowered(buf, upper, DATA_LEN);
+    g_assert_cmpstr(buf, ==, lower);
+
+    XmuNCopyISOLatin1Lowered(buf, lower, DATA_LEN);
+    g_assert_cmpstr(buf, ==, lower);
+
+    XmuNCopyISOLatin1Lowered(buf, mixed, DATA_LEN);
+    g_assert_cmpstr(buf, ==, lower);
+}
+
+static void
+test_XmuNCopyISOLatin1Uppered(void)
+{
+    char buf[DATA_LEN];
+
+    XmuNCopyISOLatin1Uppered(buf, upper, DATA_LEN);
+    g_assert_cmpstr(buf, ==, upper);
+
+    XmuNCopyISOLatin1Uppered(buf, lower, DATA_LEN);
+    g_assert_cmpstr(buf, ==, upper);
+
+    XmuNCopyISOLatin1Uppered(buf, mixed, DATA_LEN);
+    g_assert_cmpstr(buf, ==, upper);
+}
+
+static void
+test_XmuCompareISOLatin1(void)
+{
+    int cmp;
+
+    cmp = XmuCompareISOLatin1(upper, lower);
+    g_assert_cmpint(cmp, ==, 0);
+
+    cmp = XmuCompareISOLatin1(upper, mixed);
+    g_assert_cmpint(cmp, ==, 0);
+
+    cmp = XmuCompareISOLatin1(lower, mixed);
+    g_assert_cmpint(cmp, ==, 0);
+
+    cmp = XmuCompareISOLatin1(upper + 1, lower);
+    g_assert_cmpint(cmp, >, 0);
+
+    cmp = XmuCompareISOLatin1(mixed, lower + 1);
+    g_assert_cmpint(cmp, <, 0);
+}
+
+static void
+test_XmuSnprintf(void)
+{
+    char buf[DATA_LEN];
+    int ret;
+
+    g_assert_cmpint(DATA_LEN, >, 40);
+    ret = XmuSnprintf(buf, 40, "%s", upper);
+    g_assert_cmpint(ret, ==, sizeof(upper) - 1);
+    g_assert_cmpint(buf[39], ==, 0);
+    g_assert_cmpmem(buf, 39, upper, 39);
+
+    ret = XmuSnprintf(buf, sizeof(buf), "%s", upper);
+    g_assert_cmpint(ret, ==, sizeof(upper) - 1);
+    g_assert_cmpstr(buf, ==, upper);
+
+    ret = XmuSnprintf(buf, sizeof(buf), "%d", 12345678);
+    g_assert_cmpint(ret, ==, 8);
+    g_assert_cmpstr(buf, ==, "12345678");
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    g_assert_cmpuint(sizeof(upper), ==, sizeof(lower));
+    g_assert_cmpuint(sizeof(upper), ==, sizeof(mixed));
+
+    g_test_add_func("/Lower/XmuCopyISOLatin1Lowered",
+                    test_XmuCopyISOLatin1Lowered);
+    g_test_add_func("/Lower/XmuCopyISOLatin1Uppered",
+                    test_XmuCopyISOLatin1Uppered);
+
+    g_test_add_func("/Lower/XmuNCopyISOLatin1Lowered",
+                    test_XmuNCopyISOLatin1Lowered);
+    g_test_add_func("/Lower/XmuNCopyISOLatin1Uppered",
+                    test_XmuNCopyISOLatin1Uppered);
+
+    g_test_add_func("/Lower/XmuCompareISOLatin1",
+                    test_XmuCompareISOLatin1);
+    g_test_add_func("/Lower/XmuSnprintf",
+                    test_XmuSnprintf);
+
+
+    return g_test_run();
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index 75b95cb..b4d9172 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(XMU_CFLAGS) $(GLIB_CFLAGS)
 XMU_TEST_LIBS  = ${top_builddir}/src/libXmu.la $(XMU_LIBS) $(GLIB_LIBS)
 XMUU_TEST_LIBS = ${top_builddir}/src/libXmuu.la $(XMUU_LIBS) $(GLIB_LIBS)
 
-check_PROGRAMS = CursorName EditResStream ReadBitmapData
+check_PROGRAMS = CursorName EditResStream Lower ReadBitmapData
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -47,6 +47,9 @@ CursorName_LDADD = $(XMUU_TEST_LIBS)
 EditResStream_SOURCES = EditResStream.c
 EditResStream_LDADD = $(XMU_TEST_LIBS)
 
+Lower_SOURCES = Lower.c
+Lower_LDADD = $(XMUU_TEST_LIBS)
+
 ReadBitmapData_SOURCES = ReadBitmapData.c
 ReadBitmapData_LDADD = $(XMU_TEST_LIBS)
 
commit b6f70b5167557c8aa845feb53209d5b6ce58ce09
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 12:25:48 2023 -0700

    test: Add simple test cases for functions in src/CursorName.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/CursorName.c b/test/CursorName.c
new file mode 100644
index 0000000..a3f8aae
--- /dev/null
+++ b/test/CursorName.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for XmuCursorNameToIndex() in src/CursorName.c */
+#include "config.h"
+#include <X11/Xmu/CurUtil.h>
+#include <X11/Xmu/CharSet.h>
+#include <glib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SKIP_WHITESPACE(p)  while (isspace(*p)) p++
+
+/* Looks up each entry from <X11/cursorfont.h> to verify value returned */
+static void
+test_CursorNameToIndex_goodnames(void)
+{
+    FILE *cursorfont;
+    char line[256];
+    int cursorschecked = 0;
+    int cursorsexpected = 0;
+
+    cursorfont = fopen("/usr/include/X11/cursorfont.h", "r");
+    if (cursorfont == NULL) {
+        g_test_skip("Could not open /usr/include/X11/cursorfont.h");
+        return;
+    }
+
+    while (fgets(line, sizeof(line), cursorfont) != NULL) {
+        char *p = line;
+
+        /* skip lines that don't start with "#define" */
+        if (strncmp(p, "#define", 7) != 0)
+            continue;
+        else
+            p += 7;
+
+        /* skip over whitespace after #define */
+        SKIP_WHITESPACE(p);
+
+        /* skip #define _X11_CURSORFONT_H_ */
+        if (strncmp(p, "XC_", 3) != 0)
+            continue;
+        else
+            p += 3;
+
+        if (strncmp(p, "num_glyphs", 10) == 0) {
+            /* Use #define XC_num_glyphs to record the number we expect */
+            g_assert_cmpint(cursorsexpected, ==, 0);
+            p += strlen("num_glyphs");
+            SKIP_WHITESPACE(p);
+            cursorsexpected = (int) strtol(p, NULL, 0) / 2;
+            g_test_message("cursors expected = %d", cursorsexpected);
+            continue;
+        }
+        else {
+            /* Should be a cursor name then */
+            char *name = p;
+            int expected_id, returned_id;
+            char upper_name[32];
+
+            while (!isspace(*p))
+                p++;
+            *p++ = '\0';
+            SKIP_WHITESPACE(p);
+            expected_id = (int) strtol(p, NULL, 0);
+
+            g_test_message("%s = %d", name, expected_id);
+
+            returned_id = XmuCursorNameToIndex(name);
+            g_assert_cmpint(returned_id, ==, expected_id);
+
+            XmuNCopyISOLatin1Uppered(upper_name, name, sizeof(upper_name));
+            returned_id = XmuCursorNameToIndex(upper_name);
+            g_assert_cmpint(returned_id, ==, expected_id);
+
+            cursorschecked++;
+        }
+    }
+
+    fclose(cursorfont);
+
+    g_assert_cmpint(cursorschecked, ==, cursorsexpected);
+}
+
+static void
+test_CursorNameToIndex_badnames(void)
+{
+    const char *badnames[] = {
+        "does-not-exist",
+        "starts-with-a-good-name", /* starts with "star" */
+        "num_glyphs",
+        ""
+    };
+#define NUM_BAD_NAMES (sizeof(badnames) / sizeof(badnames[0]))
+
+    for (unsigned int i = 0; i < NUM_BAD_NAMES; i++) {
+        int returned_id = XmuCursorNameToIndex(badnames[i]);
+        g_test_message("%s", badnames[i]);
+        g_assert_cmpint(returned_id, ==, -1);
+    }
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    g_test_add_func("/CursorName/XmuCursorNameToIndex/good-names",
+                    test_CursorNameToIndex_goodnames);
+
+    g_test_add_func("/CursorName/XmuCursorNameToIndex/bad-names",
+                    test_CursorNameToIndex_badnames);
+
+    return g_test_run();
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index 5af50d1..75b95cb 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(XMU_CFLAGS) $(GLIB_CFLAGS)
 XMU_TEST_LIBS  = ${top_builddir}/src/libXmu.la $(XMU_LIBS) $(GLIB_LIBS)
 XMUU_TEST_LIBS = ${top_builddir}/src/libXmuu.la $(XMUU_LIBS) $(GLIB_LIBS)
 
-check_PROGRAMS = EditResStream ReadBitmapData
+check_PROGRAMS = CursorName EditResStream ReadBitmapData
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -41,6 +41,9 @@ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
                   $(top_srcdir)/tap-driver.sh
 LOG_COMPILER = $(srcdir)/tap-test
 
+CursorName_SOURCES = CursorName.c
+CursorName_LDADD = $(XMUU_TEST_LIBS)
+
 EditResStream_SOURCES = EditResStream.c
 EditResStream_LDADD = $(XMU_TEST_LIBS)
 
commit b08c297a37c2b061de783b1954bb908796fe91b0
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 11:33:06 2023 -0700

    test: Add simple test cases for functions in src/RdBitF.c
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 6a1dbbf..5af50d1 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(XMU_CFLAGS) $(GLIB_CFLAGS)
 XMU_TEST_LIBS  = ${top_builddir}/src/libXmu.la $(XMU_LIBS) $(GLIB_LIBS)
 XMUU_TEST_LIBS = ${top_builddir}/src/libXmuu.la $(XMUU_LIBS) $(GLIB_LIBS)
 
-check_PROGRAMS = EditResStream
+check_PROGRAMS = EditResStream ReadBitmapData
 TESTS = $(check_PROGRAMS)
 
 TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
@@ -44,8 +44,14 @@ LOG_COMPILER = $(srcdir)/tap-test
 EditResStream_SOURCES = EditResStream.c
 EditResStream_LDADD = $(XMU_TEST_LIBS)
 
+ReadBitmapData_SOURCES = ReadBitmapData.c
+ReadBitmapData_LDADD = $(XMU_TEST_LIBS)
+
 endif HAVE_GLIB
 endif ENABLE_UNIT_TESTS
 
 EXTRA_DIST = \
+        bitmaps/plaid \
+        bitmaps/star \
+        bitmaps/xlogo64 \
         tap-test
diff --git a/test/ReadBitmapData.c b/test/ReadBitmapData.c
new file mode 100644
index 0000000..b9cdcd1
--- /dev/null
+++ b/test/ReadBitmapData.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+
+/* Test code for XmuReadBitmapData functions in src/RdBitF.c */
+#include "config.h"
+#include <X11/Xmu/Drawing.h>
+#include <glib.h>
+#include <string.h>
+
+struct BitmapData {
+    unsigned int        width;
+    unsigned int        height;
+    unsigned char *     datap;
+    int                 xhot;
+    int                 yhot;
+};
+
+#include "bitmaps/plaid"
+
+static const struct BitmapData plaid_expected = {
+    plaid_width, plaid_height, (unsigned char *) plaid_bits,
+    plaid_x_hot, plaid_y_hot
+};
+
+#include "bitmaps/star"
+
+static const struct BitmapData star_expected = {
+    star_width, star_height, (unsigned char *) star_bits,
+    star_x_hot, star_y_hot
+};
+
+#include "bitmaps/xlogo64"
+#define xlogo64_x_hot -1
+#define xlogo64_y_hot -1
+
+static const struct BitmapData xlogo64_expected = {
+    xlogo64_width, xlogo64_height, xlogo64_bits,
+    xlogo64_x_hot, xlogo64_y_hot
+};
+
+struct TestData {
+    const char *filename;
+    const struct BitmapData *data;
+};
+
+static struct TestData testdata[] = {
+    { "plaid",		&plaid_expected },
+    { "star", 		&star_expected },
+    { "xlogo64", 	&xlogo64_expected },
+};
+
+#define testcount (sizeof(testdata) / sizeof(testdata[0]))
+
+static void
+CompareBitmapData(const struct BitmapData *readin,
+                  const struct BitmapData *expected)
+{
+    size_t bytes_per_line;
+    size_t total_bytes;
+
+    g_assert_cmpuint(readin->width, ==, expected->width);
+    g_assert_cmpuint(readin->height, ==, expected->height);
+    g_assert_cmpint(readin->xhot, ==, expected->xhot);
+    g_assert_cmpint(readin->yhot, ==, expected->yhot);
+
+    bytes_per_line = (readin->width + 7) / 8;
+    total_bytes = bytes_per_line * readin->height;
+    g_assert_cmpmem(readin->datap, total_bytes, expected->datap, total_bytes);
+}
+
+
+static void
+test_ReadBitmapData(void)
+{
+    for (unsigned int i = 0; i < testcount; i++) {
+        const gchar *filename;
+        FILE *fp;
+        int status;
+        struct BitmapData readin;
+
+        filename = g_test_get_filename(G_TEST_DIST, "bitmaps",
+                                       testdata[i].filename, NULL);
+
+        g_test_message("Testing XmuReadBitmapDataFromFile(\"%s\")", filename);
+
+        status = XmuReadBitmapDataFromFile(filename,
+                                           &readin.width, &readin.height,
+                                           &readin.datap,
+                                           &readin.xhot, &readin.yhot);
+        g_assert_cmpint(status, ==, Success);
+        CompareBitmapData(&readin, testdata[i].data);
+
+
+        g_test_message("Testing XmuReadBitmapData on \"%s\"", filename);
+        fp = fopen(filename, "r");
+        g_assert_nonnull(fp);
+
+        status = XmuReadBitmapData(fp,
+                                   &readin.width, &readin.height,
+                                   &readin.datap,
+                                   &readin.xhot, &readin.yhot);
+        g_assert_cmpint(status, ==, Success);
+        CompareBitmapData(&readin, testdata[i].data);
+        fclose(fp);
+    }
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    g_test_add_func("/RdBitF/ReadBitmapData",
+                    test_ReadBitmapData);
+
+    return g_test_run();
+}
diff --git a/test/bitmaps/plaid b/test/bitmaps/plaid
new file mode 100644
index 0000000..578e464
--- /dev/null
+++ b/test/bitmaps/plaid
@@ -0,0 +1,11 @@
+#define plaid_width 22
+#define plaid_height 22
+#define plaid_x_hot -1
+#define plaid_y_hot -1
+static char plaid_bits[] = {
+   0x75, 0xfd, 0x3f, 0xaa, 0xfa, 0x3e, 0x75, 0xfd, 0x3f, 0xaa, 0xfa, 0x3e,
+   0x75, 0xfd, 0x3f, 0xff, 0x57, 0x15, 0x75, 0xfd, 0x3f, 0xaa, 0xfa, 0x3e,
+   0x75, 0xfd, 0x3f, 0xaa, 0xfa, 0x3e, 0x75, 0xfd, 0x3f, 0x20, 0xa8, 0x2b,
+   0x20, 0x50, 0x15, 0x20, 0xa8, 0x2b, 0x20, 0x50, 0x15, 0x20, 0xa8, 0x2b,
+   0xff, 0xff, 0x3f, 0x20, 0xa8, 0x2b, 0x20, 0x50, 0x15, 0x20, 0xa8, 0x2b,
+   0x20, 0x50, 0x15, 0x20, 0xa8, 0x2b};
diff --git a/test/bitmaps/star b/test/bitmaps/star
new file mode 100644
index 0000000..c98f1a4
--- /dev/null
+++ b/test/bitmaps/star
@@ -0,0 +1,8 @@
+#define star_width 16
+#define star_height 16
+#define star_x_hot 7
+#define star_y_hot 7
+static char star_bits[] = {
+   0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x88, 0x08, 0x90, 0x04, 0xa0, 0x02,
+   0x40, 0x01, 0x3e, 0x3e, 0x40, 0x01, 0xa0, 0x02, 0x90, 0x04, 0x88, 0x08,
+   0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/test/bitmaps/xlogo64 b/test/bitmaps/xlogo64
new file mode 100644
index 0000000..ad3b0db
--- /dev/null
+++ b/test/bitmaps/xlogo64
@@ -0,0 +1,46 @@
+#define xlogo64_width 64
+#define xlogo64_height 64
+static unsigned char xlogo64_bits[] = {
+   0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xfe, 0xff, 0x01, 0x00,
+   0x00, 0x00, 0x00, 0xf8, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x7c,
+   0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00,
+   0x00, 0x00, 0x00, 0x1f, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x0f,
+   0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0xff, 0x3f, 0x00,
+   0x00, 0x00, 0xc0, 0x07, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0x03,
+   0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xff, 0xff, 0x00,
+   0x00, 0x00, 0xf8, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0xf8, 0x00,
+   0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xfc, 0xff, 0x03,
+   0x00, 0x00, 0x3e, 0x00, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x1f, 0x00,
+   0x00, 0xf0, 0xff, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x0f,
+   0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0xc0, 0x07, 0x00,
+   0x00, 0xc0, 0xff, 0x3f, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x80, 0xff, 0x7f,
+   0x00, 0xf0, 0x01, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0xf8, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0xff, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+   0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x3e, 0x00, 0x00,
+   0x00, 0x00, 0xfc, 0xff, 0x03, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+   0x87, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xcf, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0xe0, 0xff, 0xcf, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+   0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xf3, 0x01, 0x00, 0x00,
+   0x00, 0x00, 0x80, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+   0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x7e, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+   0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xff, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0x80, 0xcf, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe7,
+   0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe7, 0xff, 0x1f, 0x00, 0x00,
+   0x00, 0x00, 0xe0, 0xc3, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc1,
+   0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xff, 0x7f, 0x00, 0x00,
+   0x00, 0x00, 0x7c, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
+   0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xfe, 0xff, 0x01, 0x00,
+   0x00, 0x00, 0x1f, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x80, 0x0f, 0x00,
+   0xf8, 0xff, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf0, 0xff, 0x0f, 0x00,
+   0x00, 0xe0, 0x03, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0x03, 0x00,
+   0xe0, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xc0, 0xff, 0x3f, 0x00,
+   0x00, 0xf8, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x80, 0xff, 0x7f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
+   0x00, 0x3e, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x1f, 0x00, 0x00,
+   0x00, 0xfc, 0xff, 0x03, 0x80, 0x0f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03,
+   0xc0, 0x07, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x07, 0xe0, 0x03, 0x00, 0x00,
+   0x00, 0xf0, 0xff, 0x0f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f,
+   0xf0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0xf8, 0x00, 0x00, 0x00,
+   0x00, 0xc0, 0xff, 0x3f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f,
+   0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};
commit f3d7d1f96fba76c275df990b97d4c0995a70ee4b
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Mar 26 10:03:05 2023 -0700

    test: Convert test code to use glib test helpers
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ef25a82..4d2f615 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -32,8 +32,8 @@ variables:
   # The tag should be updated each time the list of packages is updated.
   # Changing a tag forces the associated image to be rebuilt.
   # Note: the tag has no meaning, we use a date format purely for readability
-  FDO_DISTRIBUTION_TAG:  '2023-02-16.0'
-  FDO_DISTRIBUTION_PACKAGES: 'git gcc pkgconf autoconf automake libtool make xutils-dev x11proto-dev libx11-dev libxext-dev libxt-dev xmlto xorg-sgml-doctools w3m xsltproc fop xz-utils'
+  FDO_DISTRIBUTION_TAG:  '2023-03-27.0'
+  FDO_DISTRIBUTION_PACKAGES: 'git gcc pkgconf autoconf automake libtool make xutils-dev x11proto-dev libx11-dev libxext-dev libxt-dev xmlto xorg-sgml-doctools w3m xsltproc fop xz-utils libglib2.0-dev'
 
 
 #
@@ -98,3 +98,8 @@ build:
     - make check
     - make distcheck
     - popd > /dev/null
+  artifacts:
+    when: always
+    reports:
+    paths:
+      - _builddir/test/*.log
diff --git a/configure.ac b/configure.ac
index f02fade..48c761a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Initialize Autoconf
 AC_PREREQ([2.70])
 AC_INIT([libXmu], [1.1.4],
-	[https://gitlab.freedesktop.org/xorg/lib/libxmu/-/issues], [libXmu])
+	[https://gitlab.freedesktop.org/xorg/lib/libxmu/-/issues/], [libXmu])
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIRS([m4])
@@ -43,6 +43,12 @@ XORG_LINT_LIBRARY([Xmu])
 LINTLIBUU=`echo $LINTLIB | sed s/Xmu/Xmuu/`
 AC_SUBST(LINTLIBUU)
 
+# --enable-unit-tests
+AC_REQUIRE_AUX_FILE([tap-driver.sh])
+XORG_ENABLE_UNIT_TESTS
+XORG_WITH_GLIB([2.46])
+XORG_MEMORY_CHECK_FLAGS
+
 AC_CONFIG_FILES([Makefile
 		doc/Makefile
 		include/Makefile
diff --git a/test/EditResStream.c b/test/EditResStream.c
index 4f35a37..b8a3ff3 100644
--- a/test/EditResStream.c
+++ b/test/EditResStream.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Oracle and/or its affiliates.
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -22,14 +22,16 @@
  */
 
 /* Test code for ProtocolStream Get/Put functions in src/EditResCom.c */
+#include "config.h"
 #include <X11/Xmu/EditresP.h>
-#include <assert.h>
+#include <glib.h>
 
 static const char *test_string = "\tIt was a dark and stormy night...\n";
 
 #define FillBuffer(d, v) memset(d, v, sizeof(d))
 
-int main(void)
+static void
+test_EditResStream(void)
 {
     ProtocolStream ps = { 0, 0, NULL, NULL, NULL };
     unsigned char c;
@@ -60,40 +62,50 @@ int main(void)
     ps.current = ps.top;
 
     res = _XEditResGet8(&ps, &c);
-    assert(res == True);
-    assert(c == 8);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpint(c, ==, 8);
 
     res = _XEditResGet16(&ps, &s);
-    assert(res == True);
-    assert(s == 16);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpint(s, ==, 16);
 
     res = _XEditResGet16(&ps, &s);
-    assert(res == True);
-    assert(s == 0xface);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpint(s, ==, 0xface);
 
     /* set the full value so we can make sure that in 64-bit mode we
        write to the full long value, not just 32-bits of it. */
     memset(&l, 0x0f, sizeof(l));
     res = _XEditResGet32(&ps, &l);
-    assert(res == True);
-    assert(l == 32);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpint(l, ==, 32);
 
     memset(&l, 0x0f, sizeof(l));
     res = _XEditResGet32(&ps, &l);
-    assert(res == True);
-    assert(l == 0xbabeface);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpint(l, ==, 0xbabeface);
 
     res = _XEditResGetString8(&ps, &str);
-    assert(res == True);
-    assert(strcmp(str, test_string) == 0);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpstr(str, ==, test_string);
     XtFree(str);
     str = NULL;
 
     res = _XEditResGetWidgetInfo(&ps, &out);
-    assert(res == True);
-    assert(memcmp(ids, out.ids, sizeof(ids)) == 0);
+    g_assert_cmpint(res, ==, True);
+    g_assert_cmpmem(ids, sizeof(ids), out.ids, out.num_widgets * sizeof(long));
     XtFree((char *) out.ids);
     out.ids = NULL;
+}
+
+int
+main(int argc, char** argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_bug_base(PACKAGE_BUGREPORT);
+
+    g_test_add_func("/EditResCom/ProtocolStream",
+                    test_EditResStream);
 
-    return 0;
+    return g_test_run();
 }
diff --git a/test/Makefile.am b/test/Makefile.am
index 955c0a6..6a1dbbf 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2022, Oracle and/or its affiliates.
+# Copyright (c) 2022, 2023, Oracle and/or its affiliates.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
@@ -21,10 +21,31 @@
 # DEALINGS IN THE SOFTWARE.
 #
 
+if ENABLE_UNIT_TESTS
+if HAVE_GLIB
+
 AM_CPPFLAGS = -D_CONST_X_STRING -I${top_srcdir}/include
+AM_CFLAGS = $(CWARNFLAGS) $(XMU_CFLAGS) $(GLIB_CFLAGS)
+
+XMU_TEST_LIBS  = ${top_builddir}/src/libXmu.la $(XMU_LIBS) $(GLIB_LIBS)
+XMUU_TEST_LIBS = ${top_builddir}/src/libXmuu.la $(XMUU_LIBS) $(GLIB_LIBS)
 
 check_PROGRAMS = EditResStream
 TESTS = $(check_PROGRAMS)
 
+TESTS_ENVIRONMENT = $(MALLOC_DEBUG_ENV)
+TESTS_ENVIRONMENT += G_TEST_SRCDIR="$(abs_srcdir)"
+TESTS_ENVIRONMENT += G_TEST_BUILDDIR="$(abs_builddir)"
+
+LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
+                  $(top_srcdir)/tap-driver.sh
+LOG_COMPILER = $(srcdir)/tap-test
+
 EditResStream_SOURCES = EditResStream.c
-EditResStream_LDADD = ${top_builddir}/src/libXmu.la $(XMU_LIBS)
+EditResStream_LDADD = $(XMU_TEST_LIBS)
+
+endif HAVE_GLIB
+endif ENABLE_UNIT_TESTS
+
+EXTRA_DIST = \
+        tap-test
diff --git a/test/tap-test b/test/tap-test
new file mode 100755
index 0000000..99a6d97
--- /dev/null
+++ b/test/tap-test
@@ -0,0 +1,2 @@
+#! /bin/sh
+"$1" -k --tap


More information about the xorg-commit mailing list