strerror: incl enum name

strerror is nice, but usually I don't care about the text, I care about
the uppercase enum

Bug: N/A
Test: ./tests/run-on-host.sh glibc (existing failures -> b/201305529)
Test: atest bionic-unit-tests-static
Test: atest malloc_debug_unit_tests

Change-Id: I407bd9f4dfa918fff66a0da7df8d7239f789c7b8
diff --git a/libc/bionic/strerror.cpp b/libc/bionic/strerror.cpp
index 0deb200..00f50b7 100644
--- a/libc/bionic/strerror.cpp
+++ b/libc/bionic/strerror.cpp
@@ -43,139 +43,141 @@
 
 #include "bionic/pthread_internal.h"
 
+#define ERRNO_STRING_MAP_ENTRY(errno, string) [errno] = string " (" #errno ")"
+
 static const char* __sys_error_strings[] = {
     [0] = "Success",
-    [EPERM] = "Operation not permitted",
-    [ENOENT] = "No such file or directory",
-    [ESRCH] = "No such process",
-    [EINTR] = "Interrupted system call",
-    [EIO] = "I/O error",
-    [ENXIO] = "No such device or address",
-    [E2BIG] = "Argument list too long",
-    [ENOEXEC] = "Exec format error",
-    [EBADF] = "Bad file descriptor",
-    [ECHILD] = "No child processes",
-    [EAGAIN] = "Try again",
-    [ENOMEM] = "Out of memory",
-    [EACCES] = "Permission denied",
-    [EFAULT] = "Bad address",
-    [ENOTBLK] = "Block device required",
-    [EBUSY] = "Device or resource busy",
-    [EEXIST] = "File exists",
-    [EXDEV] = "Cross-device link",
-    [ENODEV] = "No such device",
-    [ENOTDIR] = "Not a directory",
-    [EISDIR] = "Is a directory",
-    [EINVAL] = "Invalid argument",
-    [ENFILE] = "File table overflow",
-    [EMFILE] = "Too many open files",
-    [ENOTTY] = "Inappropriate ioctl for device",
-    [ETXTBSY] = "Text file busy",
-    [EFBIG] = "File too large",
-    [ENOSPC] = "No space left on device",
-    [ESPIPE] = "Illegal seek",
-    [EROFS] = "Read-only file system",
-    [EMLINK] = "Too many links",
-    [EPIPE] = "Broken pipe",
-    [EDOM] = "Math argument out of domain of func",
-    [ERANGE] = "Math result not representable",
-    [EDEADLK] = "Resource deadlock would occur",
-    [ENAMETOOLONG] = "File name too long",
-    [ENOLCK] = "No record locks available",
-    [ENOSYS] = "Function not implemented",
-    [ENOTEMPTY] = "Directory not empty",
-    [ELOOP] = "Too many symbolic links encountered",
-    [ENOMSG] = "No message of desired type",
-    [EIDRM] = "Identifier removed",
-    [ECHRNG] = "Channel number out of range",
-    [EL2NSYNC] = "Level 2 not synchronized",
-    [EL3HLT] = "Level 3 halted",
-    [EL3RST] = "Level 3 reset",
-    [ELNRNG] = "Link number out of range",
-    [EUNATCH] = "Protocol driver not attached",
-    [ENOCSI] = "No CSI structure available",
-    [EL2HLT] = "Level 2 halted",
-    [EBADE] = "Invalid exchange",
-    [EBADR] = "Invalid request descriptor",
-    [EXFULL] = "Exchange full",
-    [ENOANO] = "No anode",
-    [EBADRQC] = "Invalid request code",
-    [EBADSLT] = "Invalid slot",
-    [EBFONT] = "Bad font file format",
-    [ENOSTR] = "Device not a stream",
-    [ENODATA] = "No data available",
-    [ETIME] = "Timer expired",
-    [ENOSR] = "Out of streams resources",
-    [ENONET] = "Machine is not on the network",
-    [ENOPKG] = "Package not installed",
-    [EREMOTE] = "Object is remote",
-    [ENOLINK] = "Link has been severed",
-    [EADV] = "Advertise error",
-    [ESRMNT] = "Srmount error",
-    [ECOMM] = "Communication error on send",
-    [EPROTO] = "Protocol error",
-    [EMULTIHOP] = "Multihop attempted",
-    [EDOTDOT] = "RFS specific error",
-    [EBADMSG] = "Not a data message",
-    [EOVERFLOW] = "Value too large for defined data type",
-    [ENOTUNIQ] = "Name not unique on network",
-    [EBADFD] = "File descriptor in bad state",
-    [EREMCHG] = "Remote address changed",
-    [ELIBACC] = "Can not access a needed shared library",
-    [ELIBBAD] = "Accessing a corrupted shared library",
-    [ELIBSCN] = ".lib section in a.out corrupted",
-    [ELIBMAX] = "Attempting to link in too many shared libraries",
-    [ELIBEXEC] = "Cannot exec a shared library directly",
-    [EILSEQ] = "Illegal byte sequence",
-    [ERESTART] = "Interrupted system call should be restarted",
-    [ESTRPIPE] = "Streams pipe error",
-    [EUSERS] = "Too many users",
-    [ENOTSOCK] = "Socket operation on non-socket",
-    [EDESTADDRREQ] = "Destination address required",
-    [EMSGSIZE] = "Message too long",
-    [EPROTOTYPE] = "Protocol wrong type for socket",
-    [ENOPROTOOPT] = "Protocol not available",
-    [EPROTONOSUPPORT] = "Protocol not supported",
-    [ESOCKTNOSUPPORT] = "Socket type not supported",
-    [EOPNOTSUPP] = "Operation not supported on transport endpoint",
-    [EPFNOSUPPORT] = "Protocol family not supported",
-    [EAFNOSUPPORT] = "Address family not supported by protocol",
-    [EADDRINUSE] = "Address already in use",
-    [EADDRNOTAVAIL] = "Cannot assign requested address",
-    [ENETDOWN] = "Network is down",
-    [ENETUNREACH] = "Network is unreachable",
-    [ENETRESET] = "Network dropped connection because of reset",
-    [ECONNABORTED] = "Software caused connection abort",
-    [ECONNRESET] = "Connection reset by peer",
-    [ENOBUFS] = "No buffer space available",
-    [EISCONN] = "Transport endpoint is already connected",
-    [ENOTCONN] = "Transport endpoint is not connected",
-    [ESHUTDOWN] = "Cannot send after transport endpoint shutdown",
-    [ETOOMANYREFS] = "Too many references: cannot splice",
-    [ETIMEDOUT] = "Connection timed out",
-    [ECONNREFUSED] = "Connection refused",
-    [EHOSTDOWN] = "Host is down",
-    [EHOSTUNREACH] = "No route to host",
-    [EALREADY] = "Operation already in progress",
-    [EINPROGRESS] = "Operation now in progress",
-    [ESTALE] = "Stale NFS file handle",
-    [EUCLEAN] = "Structure needs cleaning",
-    [ENOTNAM] = "Not a XENIX named type file",
-    [ENAVAIL] = "No XENIX semaphores available",
-    [EISNAM] = "Is a named type file",
-    [EREMOTEIO] = "Remote I/O error",
-    [EDQUOT] = "Quota exceeded",
-    [ENOMEDIUM] = "No medium found",
-    [EMEDIUMTYPE] = "Wrong medium type",
-    [ECANCELED] = "Operation Canceled",
-    [ENOKEY] = "Required key not available",
-    [EKEYEXPIRED] = "Key has expired",
-    [EKEYREVOKED] = "Key has been revoked",
-    [EKEYREJECTED] = "Key was rejected by service",
-    [EOWNERDEAD] = "Owner died",
-    [ENOTRECOVERABLE] = "State not recoverable",
-    [ERFKILL] = "Operation not possible due to RF-kill",
-    [EHWPOISON] = "Memory page has hardware error",
+    ERRNO_STRING_MAP_ENTRY(EPERM, "Operation not permitted"),
+    ERRNO_STRING_MAP_ENTRY(ENOENT, "No such file or directory"),
+    ERRNO_STRING_MAP_ENTRY(ESRCH, "No such process"),
+    ERRNO_STRING_MAP_ENTRY(EINTR, "Interrupted system call"),
+    ERRNO_STRING_MAP_ENTRY(EIO, "I/O error"),
+    ERRNO_STRING_MAP_ENTRY(ENXIO, "No such device or address"),
+    ERRNO_STRING_MAP_ENTRY(E2BIG, "Argument list too long"),
+    ERRNO_STRING_MAP_ENTRY(ENOEXEC, "Exec format error"),
+    ERRNO_STRING_MAP_ENTRY(EBADF, "Bad file descriptor"),
+    ERRNO_STRING_MAP_ENTRY(ECHILD, "No child processes"),
+    ERRNO_STRING_MAP_ENTRY(EAGAIN, "Try again"),
+    ERRNO_STRING_MAP_ENTRY(ENOMEM, "Out of memory"),
+    ERRNO_STRING_MAP_ENTRY(EACCES, "Permission denied"),
+    ERRNO_STRING_MAP_ENTRY(EFAULT, "Bad address"),
+    ERRNO_STRING_MAP_ENTRY(ENOTBLK, "Block device required"),
+    ERRNO_STRING_MAP_ENTRY(EBUSY, "Device or resource busy"),
+    ERRNO_STRING_MAP_ENTRY(EEXIST, "File exists"),
+    ERRNO_STRING_MAP_ENTRY(EXDEV, "Cross-device link"),
+    ERRNO_STRING_MAP_ENTRY(ENODEV, "No such device"),
+    ERRNO_STRING_MAP_ENTRY(ENOTDIR, "Not a directory"),
+    ERRNO_STRING_MAP_ENTRY(EISDIR, "Is a directory"),
+    ERRNO_STRING_MAP_ENTRY(EINVAL, "Invalid argument"),
+    ERRNO_STRING_MAP_ENTRY(ENFILE, "File table overflow"),
+    ERRNO_STRING_MAP_ENTRY(EMFILE, "Too many open files"),
+    ERRNO_STRING_MAP_ENTRY(ENOTTY, "Inappropriate ioctl for device"),
+    ERRNO_STRING_MAP_ENTRY(ETXTBSY, "Text file busy"),
+    ERRNO_STRING_MAP_ENTRY(EFBIG, "File too large"),
+    ERRNO_STRING_MAP_ENTRY(ENOSPC, "No space left on device"),
+    ERRNO_STRING_MAP_ENTRY(ESPIPE, "Illegal seek"),
+    ERRNO_STRING_MAP_ENTRY(EROFS, "Read-only file system"),
+    ERRNO_STRING_MAP_ENTRY(EMLINK, "Too many links"),
+    ERRNO_STRING_MAP_ENTRY(EPIPE, "Broken pipe"),
+    ERRNO_STRING_MAP_ENTRY(EDOM, "Math argument out of domain of func"),
+    ERRNO_STRING_MAP_ENTRY(ERANGE, "Math result not representable"),
+    ERRNO_STRING_MAP_ENTRY(EDEADLK, "Resource deadlock would occur"),
+    ERRNO_STRING_MAP_ENTRY(ENAMETOOLONG, "File name too long"),
+    ERRNO_STRING_MAP_ENTRY(ENOLCK, "No record locks available"),
+    ERRNO_STRING_MAP_ENTRY(ENOSYS, "Function not implemented"),
+    ERRNO_STRING_MAP_ENTRY(ENOTEMPTY, "Directory not empty"),
+    ERRNO_STRING_MAP_ENTRY(ELOOP, "Too many symbolic links encountered"),
+    ERRNO_STRING_MAP_ENTRY(ENOMSG, "No message of desired type"),
+    ERRNO_STRING_MAP_ENTRY(EIDRM, "Identifier removed"),
+    ERRNO_STRING_MAP_ENTRY(ECHRNG, "Channel number out of range"),
+    ERRNO_STRING_MAP_ENTRY(EL2NSYNC, "Level 2 not synchronized"),
+    ERRNO_STRING_MAP_ENTRY(EL3HLT, "Level 3 halted"),
+    ERRNO_STRING_MAP_ENTRY(EL3RST, "Level 3 reset"),
+    ERRNO_STRING_MAP_ENTRY(ELNRNG, "Link number out of range"),
+    ERRNO_STRING_MAP_ENTRY(EUNATCH, "Protocol driver not attached"),
+    ERRNO_STRING_MAP_ENTRY(ENOCSI, "No CSI structure available"),
+    ERRNO_STRING_MAP_ENTRY(EL2HLT, "Level 2 halted"),
+    ERRNO_STRING_MAP_ENTRY(EBADE, "Invalid exchange"),
+    ERRNO_STRING_MAP_ENTRY(EBADR, "Invalid request descriptor"),
+    ERRNO_STRING_MAP_ENTRY(EXFULL, "Exchange full"),
+    ERRNO_STRING_MAP_ENTRY(ENOANO, "No anode"),
+    ERRNO_STRING_MAP_ENTRY(EBADRQC, "Invalid request code"),
+    ERRNO_STRING_MAP_ENTRY(EBADSLT, "Invalid slot"),
+    ERRNO_STRING_MAP_ENTRY(EBFONT, "Bad font file format"),
+    ERRNO_STRING_MAP_ENTRY(ENOSTR, "Device not a stream"),
+    ERRNO_STRING_MAP_ENTRY(ENODATA, "No data available"),
+    ERRNO_STRING_MAP_ENTRY(ETIME, "Timer expired"),
+    ERRNO_STRING_MAP_ENTRY(ENOSR, "Out of streams resources"),
+    ERRNO_STRING_MAP_ENTRY(ENONET, "Machine is not on the network"),
+    ERRNO_STRING_MAP_ENTRY(ENOPKG, "Package not installed"),
+    ERRNO_STRING_MAP_ENTRY(EREMOTE, "Object is remote"),
+    ERRNO_STRING_MAP_ENTRY(ENOLINK, "Link has been severed"),
+    ERRNO_STRING_MAP_ENTRY(EADV, "Advertise error"),
+    ERRNO_STRING_MAP_ENTRY(ESRMNT, "Srmount error"),
+    ERRNO_STRING_MAP_ENTRY(ECOMM, "Communication error on send"),
+    ERRNO_STRING_MAP_ENTRY(EPROTO, "Protocol error"),
+    ERRNO_STRING_MAP_ENTRY(EMULTIHOP, "Multihop attempted"),
+    ERRNO_STRING_MAP_ENTRY(EDOTDOT, "RFS specific error"),
+    ERRNO_STRING_MAP_ENTRY(EBADMSG, "Not a data message"),
+    ERRNO_STRING_MAP_ENTRY(EOVERFLOW, "Value too large for defined data type"),
+    ERRNO_STRING_MAP_ENTRY(ENOTUNIQ, "Name not unique on network"),
+    ERRNO_STRING_MAP_ENTRY(EBADFD, "File descriptor in bad state"),
+    ERRNO_STRING_MAP_ENTRY(EREMCHG, "Remote address changed"),
+    ERRNO_STRING_MAP_ENTRY(ELIBACC, "Can not access a needed shared library"),
+    ERRNO_STRING_MAP_ENTRY(ELIBBAD, "Accessing a corrupted shared library"),
+    ERRNO_STRING_MAP_ENTRY(ELIBSCN, ".lib section in a.out corrupted"),
+    ERRNO_STRING_MAP_ENTRY(ELIBMAX, "Attempting to link in too many shared libraries"),
+    ERRNO_STRING_MAP_ENTRY(ELIBEXEC, "Cannot exec a shared library directly"),
+    ERRNO_STRING_MAP_ENTRY(EILSEQ, "Illegal byte sequence"),
+    ERRNO_STRING_MAP_ENTRY(ERESTART, "Interrupted system call should be restarted"),
+    ERRNO_STRING_MAP_ENTRY(ESTRPIPE, "Streams pipe error"),
+    ERRNO_STRING_MAP_ENTRY(EUSERS, "Too many users"),
+    ERRNO_STRING_MAP_ENTRY(ENOTSOCK, "Socket operation on non-socket"),
+    ERRNO_STRING_MAP_ENTRY(EDESTADDRREQ, "Destination address required"),
+    ERRNO_STRING_MAP_ENTRY(EMSGSIZE, "Message too long"),
+    ERRNO_STRING_MAP_ENTRY(EPROTOTYPE, "Protocol wrong type for socket"),
+    ERRNO_STRING_MAP_ENTRY(ENOPROTOOPT, "Protocol not available"),
+    ERRNO_STRING_MAP_ENTRY(EPROTONOSUPPORT, "Protocol not supported"),
+    ERRNO_STRING_MAP_ENTRY(ESOCKTNOSUPPORT, "Socket type not supported"),
+    ERRNO_STRING_MAP_ENTRY(EOPNOTSUPP, "Operation not supported on transport endpoint"),
+    ERRNO_STRING_MAP_ENTRY(EPFNOSUPPORT, "Protocol family not supported"),
+    ERRNO_STRING_MAP_ENTRY(EAFNOSUPPORT, "Address family not supported by protocol"),
+    ERRNO_STRING_MAP_ENTRY(EADDRINUSE, "Address already in use"),
+    ERRNO_STRING_MAP_ENTRY(EADDRNOTAVAIL, "Cannot assign requested address"),
+    ERRNO_STRING_MAP_ENTRY(ENETDOWN, "Network is down"),
+    ERRNO_STRING_MAP_ENTRY(ENETUNREACH, "Network is unreachable"),
+    ERRNO_STRING_MAP_ENTRY(ENETRESET, "Network dropped connection because of reset"),
+    ERRNO_STRING_MAP_ENTRY(ECONNABORTED, "Software caused connection abort"),
+    ERRNO_STRING_MAP_ENTRY(ECONNRESET, "Connection reset by peer"),
+    ERRNO_STRING_MAP_ENTRY(ENOBUFS, "No buffer space available"),
+    ERRNO_STRING_MAP_ENTRY(EISCONN, "Transport endpoint is already connected"),
+    ERRNO_STRING_MAP_ENTRY(ENOTCONN, "Transport endpoint is not connected"),
+    ERRNO_STRING_MAP_ENTRY(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
+    ERRNO_STRING_MAP_ENTRY(ETOOMANYREFS, "Too many references: cannot splice"),
+    ERRNO_STRING_MAP_ENTRY(ETIMEDOUT, "Connection timed out"),
+    ERRNO_STRING_MAP_ENTRY(ECONNREFUSED, "Connection refused"),
+    ERRNO_STRING_MAP_ENTRY(EHOSTDOWN, "Host is down"),
+    ERRNO_STRING_MAP_ENTRY(EHOSTUNREACH, "No route to host"),
+    ERRNO_STRING_MAP_ENTRY(EALREADY, "Operation already in progress"),
+    ERRNO_STRING_MAP_ENTRY(EINPROGRESS, "Operation now in progress"),
+    ERRNO_STRING_MAP_ENTRY(ESTALE, "Stale NFS file handle"),
+    ERRNO_STRING_MAP_ENTRY(EUCLEAN, "Structure needs cleaning"),
+    ERRNO_STRING_MAP_ENTRY(ENOTNAM, "Not a XENIX named type file"),
+    ERRNO_STRING_MAP_ENTRY(ENAVAIL, "No XENIX semaphores available"),
+    ERRNO_STRING_MAP_ENTRY(EISNAM, "Is a named type file"),
+    ERRNO_STRING_MAP_ENTRY(EREMOTEIO, "Remote I/O error"),
+    ERRNO_STRING_MAP_ENTRY(EDQUOT, "Quota exceeded"),
+    ERRNO_STRING_MAP_ENTRY(ENOMEDIUM, "No medium found"),
+    ERRNO_STRING_MAP_ENTRY(EMEDIUMTYPE, "Wrong medium type"),
+    ERRNO_STRING_MAP_ENTRY(ECANCELED, "Operation Canceled"),
+    ERRNO_STRING_MAP_ENTRY(ENOKEY, "Required key not available"),
+    ERRNO_STRING_MAP_ENTRY(EKEYEXPIRED, "Key has expired"),
+    ERRNO_STRING_MAP_ENTRY(EKEYREVOKED, "Key has been revoked"),
+    ERRNO_STRING_MAP_ENTRY(EKEYREJECTED, "Key was rejected by service"),
+    ERRNO_STRING_MAP_ENTRY(EOWNERDEAD, "Owner died"),
+    ERRNO_STRING_MAP_ENTRY(ENOTRECOVERABLE, "State not recoverable"),
+    ERRNO_STRING_MAP_ENTRY(ERFKILL, "Operation not possible due to RF-kill"),
+    ERRNO_STRING_MAP_ENTRY(EHWPOISON, "Memory page has hardware error"),
 };
 
 static inline const char* __strerror_lookup(int error_number) {
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 42d1415..a2b111f 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -103,7 +103,7 @@
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   std::string log_msg(
       "6 malloc_debug malloc_testing: bad value for option 'backtrace': "
-      "Math result not representable\n");
+      "Math result not representable (ERANGE)\n");
   ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
 }
 
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 1298df7..76bed3f 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -2351,7 +2351,8 @@
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   std::string expected_log = android::base::StringPrintf(
-      "6 malloc_debug Cannot create record alloc file %s: Too many symbolic links encountered\n",
+      "6 malloc_debug Cannot create record alloc file %s: Too many symbolic links encountered "
+      "(ELOOP)\n",
       RECORD_ALLOCS_FILE);
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index e38dd60..cf8cb0a 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -2461,7 +2461,7 @@
   ASSERT_STREQ("<Unknown error -1>", buf);
   errno = EINVAL;
   snprintf(buf, sizeof(buf), "<%m>");
-  ASSERT_STREQ("<Invalid argument>", buf);
+  ASSERT_MATCH(buf, "<Invalid argument.*>");
 }
 
 TEST(STDIO_TEST, printf_m_does_not_clobber_strerror) {
@@ -2484,7 +2484,7 @@
   ASSERT_EQ(std::wstring(L"<Unknown error -1>"), buf);
   errno = EINVAL;
   swprintf(buf, sizeof(buf), L"<%m>");
-  ASSERT_EQ(std::wstring(L"<Invalid argument>"), buf);
+  ASSERT_MATCH(buf, L"Invalid argument.*>");
 }
 
 TEST(STDIO_TEST, wprintf_m_does_not_clobber_strerror) {
@@ -2558,9 +2558,9 @@
 
 TEST(STDIO_TEST, perror) {
   ExecTestHelper eth;
-  eth.Run([&]() { errno = EINVAL; perror("a b c"); exit(0); }, 0, "a b c: Invalid argument\n");
-  eth.Run([&]() { errno = EINVAL; perror(nullptr); exit(0); }, 0, "Invalid argument\n");
-  eth.Run([&]() { errno = EINVAL; perror(""); exit(0); }, 0, "Invalid argument\n");
+  eth.Run([&]() { errno = EINVAL; perror("a b c"); exit(0); }, 0, "a b c: Invalid argument.*\n");
+  eth.Run([&]() { errno = EINVAL; perror(nullptr); exit(0); }, 0, "Invalid argument.*\n");
+  eth.Run([&]() { errno = EINVAL; perror(""); exit(0); }, 0, "Invalid argument.*\n");
 }
 
 TEST(STDIO_TEST, puts) {
diff --git a/tests/string_posix_strerror_r_test.cpp b/tests/string_posix_strerror_r_test.cpp
index e4becaa..808f963 100644
--- a/tests/string_posix_strerror_r_test.cpp
+++ b/tests/string_posix_strerror_r_test.cpp
@@ -15,6 +15,8 @@
  */
 
 #include <errno.h>
+
+#include <android-base/test_utils.h>
 #include <gtest/gtest.h>
 
 // Defined in string_posix_strerror_r_wrapper.cpp as a wrapper around the posix
@@ -33,7 +35,7 @@
   ASSERT_STREQ("Success", buf);
 #endif
   ASSERT_EQ(0, posix_strerror_r(1, buf, sizeof(buf)));
-  ASSERT_STREQ("Operation not permitted", buf);
+  ASSERT_MATCH(buf, "Operation not permitted.*");
 
 #if defined(__BIONIC__) || defined(ANDROID_HOST_MUSL)
   // Invalid.
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 8d3fb68..1b0082f 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -28,6 +28,8 @@
 #include <algorithm>
 #include <vector>
 
+#include <android-base/test_utils.h>
+
 #include "buffer_tests.h"
 
 #if defined(NOFORTIFY)
@@ -58,7 +60,7 @@
 TEST(STRING_TEST, strerror) {
   // Valid.
   ASSERT_STREQ("Success", strerror(0));
-  ASSERT_STREQ("Operation not permitted", strerror(1));
+  ASSERT_MATCH(strerror(1), "Operation not permitted.*");
 
   // Invalid.
   ASSERT_STREQ("Unknown error -1", strerror(-1));
@@ -106,9 +108,9 @@
 #if defined(__BIONIC__)
   ASSERT_STREQ("Success", buf);
 #endif
-  ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf)));
+  ASSERT_MATCH(strerror_r(1, buf, sizeof(buf)), "Operation not permitted.*");
 #if defined(__BIONIC__)
-  ASSERT_STREQ("Operation not permitted", buf);
+  ASSERT_MATCH(buf, "Operation not permitted.*");
 #endif
 
   // Invalid.
diff --git a/tests/utils.h b/tests/utils.h
index 284140a..90fb1d0 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -44,6 +44,7 @@
 #include <android-base/macros.h>
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
 
 #if defined(__LP64__)
 #define PATH_TO_SYSTEM_LIB "/system/lib64/"
@@ -259,9 +260,7 @@
     std::string error_msg("Test output:\n" + output_);
     AssertChildExited(pid, expected_exit_status, &error_msg);
     if (expected_output_regex != nullptr) {
-      if (!std::regex_search(output_, std::regex(expected_output_regex))) {
-        FAIL() << "regex " << expected_output_regex << " didn't match " << output_;
-      }
+      ASSERT_MATCH(output_, expected_output_regex);
     }
   }