about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--support/Makefile4
-rw-r--r--support/check.h15
-rw-r--r--support/support.h6
-rw-r--r--support/support_quote_blob.c71
-rw-r--r--support/support_quote_blob_main.c88
-rw-r--r--support/support_quote_blob_wide.c24
-rw-r--r--support/support_test_compare_string.c83
-rw-r--r--support/support_test_compare_string_main.c94
-rw-r--r--support/support_test_compare_string_wide.c28
-rw-r--r--support/tst-support_quote_blob_wide.c66
-rw-r--r--support/tst-test_compare_string_wide.c107
11 files changed, 448 insertions, 138 deletions
diff --git a/support/Makefile b/support/Makefile
index fd27c8451e..7f03950914 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -71,6 +71,7 @@ libsupport-routines = \
   support_openpty \
   support_paths \
   support_quote_blob \
+  support_quote_blob_wide \
   support_quote_string \
   support_record_failure \
   support_run_diff \
@@ -84,6 +85,7 @@ libsupport-routines = \
   support_test_compare_blob \
   support_test_compare_failure \
   support_test_compare_string \
+  support_test_compare_string_wide \
   support_test_main \
   support_test_verify_impl \
   support_wait_for_thread_exit \
@@ -270,11 +272,13 @@ tests = \
   tst-support-open-dev-null-range \
   tst-support-process_state \
   tst-support_quote_blob \
+  tst-support_quote_blob_wide \
   tst-support_quote_string \
   tst-support_record_failure \
   tst-test_compare \
   tst-test_compare_blob \
   tst-test_compare_string \
+  tst-test_compare_string_wide \
   tst-timespec \
   tst-xreadlink \
   tst-xsigstack \
diff --git a/support/check.h b/support/check.h
index 83662b2d10..9b1844352f 100644
--- a/support/check.h
+++ b/support/check.h
@@ -20,6 +20,7 @@
 #define SUPPORT_CHECK_H
 
 #include <sys/cdefs.h>
+#include <stddef.h>
 
 __BEGIN_DECLS
 
@@ -171,11 +172,25 @@ void support_test_compare_blob (const void *left,
   (support_test_compare_string (left, right, __FILE__, __LINE__, \
                                 #left, #right))
 
+/* Compare the wide strings LEFT and RIGHT and report a test failure
+   if they are different.  Also report failure if one of the arguments
+   is a null pointer and the other is not.  The strings should be
+   reasonably short because on mismatch, both are printed.  */
+#define TEST_COMPARE_STRING_WIDE(left, right)                         \
+  (support_test_compare_string_wide (left, right, __FILE__, __LINE__, \
+				     #left, #right))
+
 void support_test_compare_string (const char *left, const char *right,
                                   const char *file, int line,
                                   const char *left_expr,
                                   const char *right_expr);
 
+void support_test_compare_string_wide (const wchar_t *left,
+				       const wchar_t *right,
+				       const char *file, int line,
+				       const char *left_expr,
+				       const char *right_expr);
+
 /* Internal function called by the test driver.  */
 int support_report_failure (int status)
   __attribute__ ((weak, warn_unused_result));
diff --git a/support/support.h b/support/support.h
index 837a806531..0ee454da6d 100644
--- a/support/support.h
+++ b/support/support.h
@@ -73,6 +73,12 @@ void support_write_file_string (const char *path, const char *contents);
    the result).  */
 char *support_quote_blob (const void *blob, size_t length);
 
+/* Quote the contents of the wide character array starting at BLOB, of
+   LENGTH wide characters, in such a way that the result string can be
+   included in a C wide string literal (in single/double quotes,
+   without putting the quotes into the result).  */
+char *support_quote_blob_wide (const void *blob, size_t length);
+
 /* Quote the contents of the string, in such a way that the result
    string can be included in a C literal (in single/double quotes,
    without putting the quotes into the result).  */
diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c
index b5e70125f1..611980c9a2 100644
--- a/support/support_quote_blob.c
+++ b/support/support_quote_blob.c
@@ -1,4 +1,4 @@
-/* Quote a blob so that it can be used in C literals.
+/* Quote a narrow string blob so that it can be used in C literals.
    Copyright (C) 2018-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,68 +16,9 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <support/support.h>
-#include <support/xmemstream.h>
+#define CHAR unsigned char
+#define L_(C) C
+#define SUPPORT_QUOTE_BLOB support_quote_blob
+#define WIDE 0
 
-char *
-support_quote_blob (const void *blob, size_t length)
-{
-  struct xmemstream out;
-  xopen_memstream (&out);
-
-  const unsigned char *p = blob;
-  for (size_t i = 0; i < length; ++i)
-    {
-      unsigned char ch = p[i];
-
-      /* Use C backslash escapes for those control characters for
-         which they are defined.  */
-      switch (ch)
-        {
-          case '\a':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('a', out.out);
-            break;
-          case '\b':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('b', out.out);
-            break;
-          case '\f':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('f', out.out);
-            break;
-          case '\n':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('n', out.out);
-            break;
-          case '\r':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('r', out.out);
-            break;
-          case '\t':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('t', out.out);
-            break;
-          case '\v':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked ('v', out.out);
-            break;
-          case '\\':
-          case '\'':
-          case '\"':
-            putc_unlocked ('\\', out.out);
-            putc_unlocked (ch, out.out);
-            break;
-        default:
-          if (ch < ' ' || ch > '~')
-            /* Use octal sequences because they are fixed width,
-               unlike hexadecimal sequences.  */
-            fprintf (out.out, "\\%03o", ch);
-          else
-            putc_unlocked (ch, out.out);
-        }
-    }
-
-  xfclose_memstream (&out);
-  return out.buffer;
-}
+#include "support_quote_blob_main.c"
diff --git a/support/support_quote_blob_main.c b/support/support_quote_blob_main.c
new file mode 100644
index 0000000000..19ccfad593
--- /dev/null
+++ b/support/support_quote_blob_main.c
@@ -0,0 +1,88 @@
+/* Quote a blob so that it can be used in C literals.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+SUPPORT_QUOTE_BLOB (const void *blob, size_t length)
+{
+  struct xmemstream out;
+  xopen_memstream (&out);
+
+  const CHAR *p = blob;
+  for (size_t i = 0; i < length; ++i)
+    {
+      CHAR ch = p[i];
+
+      /* Use C backslash escapes for those control characters for
+	 which they are defined.  */
+      switch (ch)
+	{
+	case L_('\a'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('a', out.out);
+	  break;
+	case L_('\b'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('b', out.out);
+	  break;
+	case L_('\f'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('f', out.out);
+	  break;
+	case L_('\n'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('n', out.out);
+	  break;
+	case L_('\r'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('r', out.out);
+	  break;
+	case L_('\t'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('t', out.out);
+	  break;
+	case L_('\v'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked ('v', out.out);
+	  break;
+	case L_('\\'):
+	case L_('\''):
+	case L_('\"'):
+	  putc_unlocked ('\\', out.out);
+	  putc_unlocked (ch, out.out);
+	  break;
+	default:
+	  if (ch < L_(' ') || ch > L_('~'))
+	    /* For narrow characters, use octal sequences because they
+	       are fixed width, unlike hexadecimal sequences.  For
+	       wide characters, use N2785 delimited escape
+	       sequences.  */
+	    if (WIDE)
+	      fprintf (out.out, "\\x{%x}", (unsigned int) ch);
+	    else
+	      fprintf (out.out, "\\%03o", (unsigned int) ch);
+	  else
+	    putc_unlocked (ch, out.out);
+	}
+    }
+
+  xfclose_memstream (&out);
+  return out.buffer;
+}
diff --git a/support/support_quote_blob_wide.c b/support/support_quote_blob_wide.c
new file mode 100644
index 0000000000..c451ed889c
--- /dev/null
+++ b/support/support_quote_blob_wide.c
@@ -0,0 +1,24 @@
+/* Quote a wide string blob so that it can be used in C literals.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define CHAR wchar_t
+#define L_(C) L ## C
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
+#define WIDE 1
+
+#include "support_quote_blob_main.c"
diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c
index cbeaf7b1ee..12bafe43d4 100644
--- a/support/support_test_compare_string.c
+++ b/support/support_test_compare_string.c
@@ -16,76 +16,13 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <support/check.h>
-#include <support/support.h>
-#include <support/xmemstream.h>
-
-static void
-report_length (const char *what, const char *str, size_t length)
-{
-  if (str == NULL)
-    printf ("  %s string: NULL\n", what);
-  else
-    printf ("  %s string: %zu bytes\n", what, length);
-}
-
-static void
-report_string (const char *what, const unsigned char *blob,
-               size_t length, const char *expr)
-{
-  if (length > 0)
-    {
-      printf ("  %s (evaluated from %s):\n", what, expr);
-      char *quoted = support_quote_blob (blob, length);
-      printf ("      \"%s\"\n", quoted);
-      free (quoted);
-
-      fputs ("     ", stdout);
-      for (size_t i = 0; i < length; ++i)
-        printf (" %02X", blob[i]);
-      putc ('\n', stdout);
-    }
-}
-
-static size_t
-string_length_or_zero (const char *str)
-{
-  if (str == NULL)
-    return 0;
-  else
-    return strlen (str);
-}
-
-void
-support_test_compare_string (const char *left, const char *right,
-                             const char *file, int line,
-                             const char *left_expr, const char *right_expr)
-{
-  /* Two null pointers are accepted.  */
-  if (left == NULL && right == NULL)
-    return;
-
-  size_t left_length = string_length_or_zero (left);
-  size_t right_length = string_length_or_zero (right);
-
-  if (left_length != right_length || left == NULL || right == NULL
-      || memcmp (left, right, left_length) != 0)
-    {
-      support_record_failure ();
-      printf ("%s:%d: error: string comparison failed\n", file, line);
-      if (left_length == right_length && right != NULL && left != NULL)
-        printf ("  string length: %zu bytes\n", left_length);
-      else
-        {
-          report_length ("left", left, left_length);
-          report_length ("right", right, right_length);
-        }
-      report_string ("left", (const unsigned char *) left,
-                     left_length, left_expr);
-      report_string ("right", (const unsigned char *) right,
-                     right_length, right_expr);
-    }
-}
+#define CHAR char
+#define UCHAR unsigned char
+#define LPREFIX ""
+#define STRLEN strlen
+#define MEMCMP memcmp
+#define SUPPORT_QUOTE_BLOB support_quote_blob
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string
+#define WIDE 0
+
+#include "support_test_compare_string_main.c"
diff --git a/support/support_test_compare_string_main.c b/support/support_test_compare_string_main.c
new file mode 100644
index 0000000000..0edc0ca97d
--- /dev/null
+++ b/support/support_test_compare_string_main.c
@@ -0,0 +1,94 @@
+/* Check two strings for equality.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+static void
+report_length (const char *what, const CHAR *str, size_t length)
+{
+  if (str == NULL)
+    printf ("  %s string: NULL\n", what);
+  else
+    printf ("  %s string: %zu %s\n", what, length,
+	    WIDE ? "wide characters" : "bytes");
+}
+
+static void
+report_string (const char *what, const UCHAR *blob,
+               size_t length, const char *expr)
+{
+  if (length > 0)
+    {
+      printf ("  %s (evaluated from %s):\n", what, expr);
+      char *quoted = SUPPORT_QUOTE_BLOB (blob, length);
+      printf ("      %s\"%s\"\n", LPREFIX, quoted);
+      free (quoted);
+
+      fputs ("     ", stdout);
+      for (size_t i = 0; i < length; ++i)
+        printf (" %02X", (unsigned int) blob[i]);
+      putc ('\n', stdout);
+    }
+}
+
+static size_t
+string_length_or_zero (const CHAR *str)
+{
+  if (str == NULL)
+    return 0;
+  else
+    return STRLEN (str);
+}
+
+void
+SUPPORT_TEST_COMPARE_STRING (const CHAR *left, const CHAR *right,
+                             const char *file, int line,
+                             const char *left_expr, const char *right_expr)
+{
+  /* Two null pointers are accepted.  */
+  if (left == NULL && right == NULL)
+    return;
+
+  size_t left_length = string_length_or_zero (left);
+  size_t right_length = string_length_or_zero (right);
+
+  if (left_length != right_length || left == NULL || right == NULL
+      || MEMCMP (left, right, left_length) != 0)
+    {
+      support_record_failure ();
+      printf ("%s:%d: error: string comparison failed\n", file, line);
+      if (left_length == right_length && right != NULL && left != NULL)
+        printf ("  string length: %zu %s\n", left_length,
+		WIDE ? "wide characters" : "bytes");
+      else
+        {
+          report_length ("left", left, left_length);
+          report_length ("right", right, right_length);
+        }
+      report_string ("left", (const UCHAR *) left,
+                     left_length, left_expr);
+      report_string ("right", (const UCHAR *) right,
+                     right_length, right_expr);
+    }
+}
diff --git a/support/support_test_compare_string_wide.c b/support/support_test_compare_string_wide.c
new file mode 100644
index 0000000000..88b560b142
--- /dev/null
+++ b/support/support_test_compare_string_wide.c
@@ -0,0 +1,28 @@
+/* Check two wide strings for equality.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define CHAR wchar_t
+#define UCHAR wchar_t
+#define LPREFIX "L"
+#define STRLEN wcslen
+#define MEMCMP wmemcmp
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string_wide
+#define WIDE 1
+
+#include "support_test_compare_string_main.c"
diff --git a/support/tst-support_quote_blob_wide.c b/support/tst-support_quote_blob_wide.c
new file mode 100644
index 0000000000..ea71a1f7f8
--- /dev/null
+++ b/support/tst-support_quote_blob_wide.c
@@ -0,0 +1,66 @@
+/* Test the support_quote_blob_wide function.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  /* Check handling of the empty blob, both with and without trailing
+     NUL byte.  */
+  char *p = support_quote_blob_wide (L"", 0);
+  TEST_COMPARE (strlen (p), 0);
+  free (p);
+  p = support_quote_blob_wide (L"X", 0);
+  TEST_COMPARE (strlen (p), 0);
+  free (p);
+
+  /* Check escaping of backslash-escaped characters, and lack of
+     escaping for other shell meta-characters.  */
+  p = support_quote_blob_wide (L"$()*?`@[]{}~\'\"X", 14);
+  TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0);
+  free (p);
+
+  /* Check lack of escaping for letters and digits.  */
+#define LETTERS_AND_DIGTS                       \
+  "abcdefghijklmnopqrstuvwxyz"                  \
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                  \
+  "0123456789"
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define WLETTERS_AND_DIGTS CONCAT (L, LETTERS_AND_DIGTS)
+  p = support_quote_blob_wide (WLETTERS_AND_DIGTS "@", 2 * 26 + 10);
+  TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0);
+  free (p);
+
+  /* Check escaping of control characters and other non-printable
+     characters.  */
+  p = support_quote_blob_wide (L"\r\n\t\a\b\f\v\1\177\200\377"
+			       "\x123\x76543210\xfedcba98\0@", 17);
+  TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\x{1}"
+                        "\\x{7f}\\x{80}\\x{ff}\\x{123}\\x{76543210}"
+			"\\x{fedcba98}\\x{0}@\\x{0}"), 0);
+  free (p);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/support/tst-test_compare_string_wide.c b/support/tst-test_compare_string_wide.c
new file mode 100644
index 0000000000..548f7dcdc6
--- /dev/null
+++ b/support/tst-test_compare_string_wide.c
@@ -0,0 +1,107 @@
+/* Basic test for the TEST_COMPARE_STRING_WIDE macro.
+   Copyright (C) 2018-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <support/check.h>
+#include <support/capture_subprocess.h>
+
+static void
+subprocess (void *closure)
+{
+  /* These tests should fail.  They were chosen to cover differences
+     in length (with the same contents), single-bit mismatches, and
+     mismatching null pointers.  */
+  TEST_COMPARE_STRING_WIDE (L"", NULL);             /* Line 29.  */
+  TEST_COMPARE_STRING_WIDE (L"X", L"");              /* Line 30.  */
+  TEST_COMPARE_STRING_WIDE (NULL, L"X");            /* Line 31.  */
+  TEST_COMPARE_STRING_WIDE (L"abcd", L"abcD");       /* Line 32.  */
+  TEST_COMPARE_STRING_WIDE (L"abcd", NULL);         /* Line 33.  */
+  TEST_COMPARE_STRING_WIDE (NULL, L"abcd");         /* Line 34.  */
+}
+
+/* Same contents, different addresses.  */
+wchar_t buffer_abc_1[] = L"abc";
+wchar_t buffer_abc_2[] = L"abc";
+
+static int
+do_test (void)
+{
+  /* This should succeed.  Even if the pointers and array contents are
+     different, zero-length inputs are not different.  */
+  TEST_COMPARE_STRING_WIDE (NULL, NULL);
+  TEST_COMPARE_STRING_WIDE (L"", L"");
+  TEST_COMPARE_STRING_WIDE (buffer_abc_1, buffer_abc_2);
+  TEST_COMPARE_STRING_WIDE (buffer_abc_1, L"abc");
+
+  struct support_capture_subprocess proc = support_capture_subprocess
+    (&subprocess, NULL);
+
+  /* Discard the reported error.  */
+  support_record_failure_reset ();
+
+  puts ("info: *** subprocess output starts ***");
+  fputs (proc.out.buffer, stdout);
+  puts ("info: *** subprocess output ends ***");
+
+  TEST_VERIFY
+    (strcmp (proc.out.buffer,
+"tst-test_compare_string_wide.c:29: error: string comparison failed\n"
+"  left string: 0 wide characters\n"
+"  right string: NULL\n"
+"tst-test_compare_string_wide.c:30: error: string comparison failed\n"
+"  left string: 1 wide characters\n"
+"  right string: 0 wide characters\n"
+"  left (evaluated from L\"X\"):\n"
+"      L\"X\"\n"
+"      58\n"
+"tst-test_compare_string_wide.c:31: error: string comparison failed\n"
+"  left string: NULL\n"
+"  right string: 1 wide characters\n"
+"  right (evaluated from L\"X\"):\n"
+"      L\"X\"\n"
+"      58\n"
+"tst-test_compare_string_wide.c:32: error: string comparison failed\n"
+"  string length: 4 wide characters\n"
+"  left (evaluated from L\"abcd\"):\n"
+"      L\"abcd\"\n"
+"      61 62 63 64\n"
+"  right (evaluated from L\"abcD\"):\n"
+"      L\"abcD\"\n"
+"      61 62 63 44\n"
+"tst-test_compare_string_wide.c:33: error: string comparison failed\n"
+"  left string: 4 wide characters\n"
+"  right string: NULL\n"
+"  left (evaluated from L\"abcd\"):\n"
+"      L\"abcd\"\n"
+"      61 62 63 64\n"
+"tst-test_compare_string_wide.c:34: error: string comparison failed\n"
+"  left string: NULL\n"
+"  right string: 4 wide characters\n"
+"  right (evaluated from L\"abcd\"):\n"
+"      L\"abcd\"\n"
+"      61 62 63 64\n"
+             ) == 0);
+
+  /* Check that there is no output on standard error.  */
+  support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING_WIDE",
+                                    0, sc_allow_stdout);
+
+  return 0;
+}
+
+#include <support/test-driver.c>