[glib/wip/nielsdg/g_assert_cmpstrv: 1/2] gtestutils: Add g_assert_cmpstrv()




commit f98f2c5d0fa608d2300d3a6e60e55918d09efa27
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Nov 1 12:03:04 2020 +0100

    gtestutils: Add g_assert_cmpstrv()
    
    Add a test util function that helps asserting two string arrays are the
    same, and which adds some useful information if they're not.
    
    Fixes: #2015

 docs/reference/glib/glib-sections.txt |  1 +
 glib/gtestutils.c                     | 49 +++++++++++++++++++++++++++++
 glib/gtestutils.h                     | 55 ++++++++++++++++++++++++++++++++
 glib/tests/testing.c                  | 59 +++++++++++++++++++++++++++++++++++
 4 files changed, 164 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 02bb2ba50..68574040d 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -3547,6 +3547,7 @@ g_assert
 g_assert_not_reached
 
 g_assert_cmpstr
+g_assert_cmpstrv
 g_assert_cmpint
 g_assert_cmpuint
 g_assert_cmphex
diff --git a/glib/gtestutils.c b/glib/gtestutils.c
index 974785a44..1bc6aa2f3 100644
--- a/glib/gtestutils.c
+++ b/glib/gtestutils.c
@@ -576,6 +576,30 @@
  * Since: 2.16
  */
 
+/**
+ * g_assert_cmpstrv:
+ * @strv1: (nullable): a string array (may be %NULL)
+ * @strv2: (nullable): another string array (may be %NULL)
+ *
+ * Debugging macro to check if two %NULL-terminated string arrays (i.e. 2
+ * #GStrv) are equal. If they are not equal, an error message is logged and the
+ * application is either terminated or the testcase marked as failed.
+ * If both arrays are %NULL, the check passes. If one array is %NULL but the
+ * other is not, an error message is logged.
+ *
+ * The effect of `g_assert_cmpstrv (strv1, strv2)` is the same as
+ * `g_assert_true (g_strv_equal (strv1, strv2))` (if both arrays are not
+ * %NULL). The advantage of this macro is that it can produce a message that
+ * includes how @strv1 and @strv2 are different.
+ *
+ * |[<!-- language="C" -->
+ *   const char *expected[] = { "one", "two", "three", NULL };
+ *   g_assert_cmpstrv (mystrv, expected);
+ * ]|
+ *
+ * Since: 2.68
+ */
+
 /**
  * g_assert_cmpint:
  * @n1: an integer
@@ -3018,6 +3042,31 @@ g_assertion_message_cmpstr (const char     *domain,
   g_free (s);
 }
 
+void
+g_assertion_message_cmpstrv (const char         *domain,
+                             const char         *file,
+                             int                 line,
+                             const char         *func,
+                             const char         *expr,
+                             const char * const *arg1,
+                             const char * const *arg2,
+                             gsize               first_wrong_idx)
+{
+  const char *s1 = arg1[first_wrong_idx], *s2 = arg2[first_wrong_idx];
+  char *a1, *a2, *s, *t1 = NULL, *t2 = NULL;
+
+  a1 = arg1 ? g_strconcat ("\"", t1 = g_strescape (s1, NULL), "\"", NULL) : g_strdup ("NULL");
+  a2 = arg2 ? g_strconcat ("\"", t2 = g_strescape (s2, NULL), "\"", NULL) : g_strdup ("NULL");
+  g_free (t1);
+  g_free (t2);
+  s = g_strdup_printf ("assertion failed (%s): first differing element at index %" G_GSIZE_FORMAT ": %s does 
not equal %s",
+                       expr, first_wrong_idx, a1, a2);
+  g_free (a1);
+  g_free (a2);
+  g_assertion_message (domain, file, line, func, s);
+  g_free (s);
+}
+
 void
 g_assertion_message_error (const char     *domain,
                           const char     *file,
diff --git a/glib/gtestutils.h b/glib/gtestutils.h
index 10b65c164..c7a0c5969 100644
--- a/glib/gtestutils.h
+++ b/glib/gtestutils.h
@@ -111,6 +111,51 @@ typedef void (*GTestFixtureFunc) (gpointer      fixture,
       } \
   } \
   G_STMT_END
+#define g_assert_cmpstrv(strv1, strv2) \
+  G_STMT_START \
+  { \
+    const char * const *__strv1 = (const char * const *) (strv1); \
+    const char * const *__strv2 = (const char * const *) (strv2); \
+    if (!__strv1 || !__strv2) \
+      { \
+        if (__strv1) \
+          { \
+            g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+                                 "assertion failed (" #strv1 " == " #strv2 "): " #strv2 " is NULL, but " 
#strv1 " is not"); \
+          } \
+        else if (__strv2) \
+          { \
+            g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+                                 "assertion failed (" #strv1 " == " #strv2 "): " #strv1 " is NULL, but " 
#strv2 " is not"); \
+          } \
+      } \
+    else \
+      { \
+        guint __l1 = g_strv_length ((char **) __strv1); \
+        guint __l2 = g_strv_length ((char **) __strv2); \
+        if (__l1 != __l2) \
+          { \
+            char *__msg; \
+            __msg = g_strdup_printf ("assertion failed (" #strv1 " == " #strv2 "): length %u does not equal 
length %u", __l1, __l2); \
+            g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \
+            g_free (__msg); \
+          } \
+        else \
+          { \
+            guint __i; \
+            for (__i = 0; __i < __l1; __i++) \
+              { \
+                if (g_strcmp0 (__strv1[__i], __strv2[__i]) != 0) \
+                  { \
+                    g_assertion_message_cmpstrv (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+                                                 #strv1 " == " #strv2, \
+                                                 __strv1, __strv2, __i); \
+                  } \
+              } \
+          } \
+      } \
+  } \
+  G_STMT_END
 #define g_assert_no_errno(expr)         G_STMT_START { \
                                              int __ret, __errsv; \
                                              errno = 0; \
@@ -483,6 +528,16 @@ void    g_assertion_message_cmpstr      (const char     *domain,
                                          const char     *arg1,
                                          const char     *cmp,
                                          const char     *arg2) G_ANALYZER_NORETURN;
+
+GLIB_AVAILABLE_IN_2_68
+void    g_assertion_message_cmpstrv     (const char         *domain,
+                                         const char         *file,
+                                         int                 line,
+                                         const char         *func,
+                                         const char         *expr,
+                                         const char * const *arg1,
+                                         const char * const *arg2,
+                                         gsize               first_wrong_idx) G_ANALYZER_NORETURN;
 GLIB_AVAILABLE_IN_ALL
 void    g_assertion_message_cmpnum      (const char     *domain,
                                          const char     *file,
diff --git a/glib/tests/testing.c b/glib/tests/testing.c
index ed4c8d6f7..1e6a33742 100644
--- a/glib/tests/testing.c
+++ b/glib/tests/testing.c
@@ -66,6 +66,40 @@ test_assertions_bad_cmpvariant_values (void)
   exit (0);
 }
 
+static void
+test_assertions_bad_cmpstrv_null1 (void)
+{
+  const char *strv[] = { "one", "two", "three", NULL };
+  g_assert_cmpstrv (strv, NULL);
+  exit (0);
+}
+
+static void
+test_assertions_bad_cmpstrv_null2 (void)
+{
+  const char *strv[] = { "one", "two", "three", NULL };
+  g_assert_cmpstrv (NULL, strv);
+  exit (0);
+}
+
+static void
+test_assertions_bad_cmpstrv_length (void)
+{
+  const char *strv1[] = { "one", "two", "three", NULL };
+  const char *strv2[] = { "one", "two", NULL };
+  g_assert_cmpstrv (strv1, strv2);
+  exit (0);
+}
+
+static void
+test_assertions_bad_cmpstrv_values (void)
+{
+  const char *strv1[] = { "one", "two", "three", NULL };
+  const char *strv2[] = { "one", "too", "three", NULL };
+  g_assert_cmpstrv (strv1, strv2);
+  exit (0);
+}
+
 static void
 test_assertions_bad_cmpstr (void)
 {
@@ -132,6 +166,8 @@ test_assertions_bad_no_errno (void)
 static void
 test_assertions (void)
 {
+  const char *strv1[] = { "one", "two", "three", NULL };
+  const char *strv2[] = { "one", "two", "three", NULL };
   GVariant *v1, *v2;
   gchar *fuu;
 
@@ -160,6 +196,9 @@ test_assertions (void)
   g_assert_cmpmem ("foo", 0, NULL, 0);
   g_assert_no_errno (return_no_errno ());
 
+  g_assert_cmpstrv (NULL, NULL);
+  g_assert_cmpstrv (strv1, strv2);
+
   v1 = g_variant_new_parsed ("['hello', 'there']");
   v2 = g_variant_new_parsed ("['hello', 'there']");
 
@@ -181,6 +220,22 @@ test_assertions (void)
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*assertion failed*");
 
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpstrv_null1", 0, 0);
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*assertion failed*");
+
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpstrv_null2", 0, 0);
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*assertion failed*");
+
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpstrv_length", 0, 0);
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*assertion failed*");
+
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpstrv_values", 0, 0);
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*assertion failed*");
+
   g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpint", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*assertion failed*");
@@ -1303,6 +1358,10 @@ main (int   argc,
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpvariant_types", test_assertions_bad_cmpvariant_types);
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpvariant_values", 
test_assertions_bad_cmpvariant_values);
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpstr", test_assertions_bad_cmpstr);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpstrv_null1", test_assertions_bad_cmpstrv_null1);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpstrv_null2", test_assertions_bad_cmpstrv_null2);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpstrv_length", test_assertions_bad_cmpstrv_length);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpstrv_values", test_assertions_bad_cmpstrv_values);
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpint", test_assertions_bad_cmpint);
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpmem_len", test_assertions_bad_cmpmem_len);
   g_test_add_func ("/misc/assertions/subprocess/bad_cmpmem_data", test_assertions_bad_cmpmem_data);


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