[testing] Clean up check.h array macros to only print what's relevant

Signed-off-by: Miguel Young de la Sota <mcyoung@google.com>
diff --git a/sw/device/lib/runtime/log.h b/sw/device/lib/runtime/log.h
index 6431fa6..e5b98df 100644
--- a/sw/device/lib/runtime/log.h
+++ b/sw/device/lib/runtime/log.h
@@ -135,8 +135,7 @@
 #define LOG_MAKE_FIELDS_(_severity, _format, ...)                         \
   {                                                                       \
     .severity = _severity, .file_name = "" __FILE__ "", .line = __LINE__, \
-    .nargs = OT_VA_ARGS_COUNT(_format, ##__VA_ARGS__),                    \
-    .format = "" _format "",                                              \
+    .nargs = OT_VA_ARGS_COUNT(_format, ##__VA_ARGS__), .format = _format, \
   }
 
 /**
diff --git a/sw/device/lib/testing/hmac_testutils.c b/sw/device/lib/testing/hmac_testutils.c
index 8a6187c..cac55a3 100644
--- a/sw/device/lib/testing/hmac_testutils.c
+++ b/sw/device/lib/testing/hmac_testutils.c
@@ -51,7 +51,7 @@
                                             const dif_hmac_digest_t *expected) {
   dif_hmac_digest_t digest;
   hmac_testutils_finish_polled(hmac, &digest);
-  CHECK_BUFFER_EQ(digest.digest, expected, ARRAYSIZE(digest.digest));
+  CHECK_BUFFER(digest.digest, expected->digest, ARRAYSIZE(digest.digest));
 }
 
 void hmac_testutils_push_message(const dif_hmac_t *hmac, const char *data,
diff --git a/sw/device/lib/testing/test_framework/check.h b/sw/device/lib/testing/test_framework/check.h
index 9c043cc..0094b5a 100644
--- a/sw/device/lib/testing/test_framework/check.h
+++ b/sw/device/lib/testing/test_framework/check.h
@@ -18,6 +18,10 @@
  * Runtime assertion macros with log.h integration.
  */
 
+#ifdef __cplusplus
+#error "This file is C-only; it is not a polyglot header!"
+#endif
+
 /**
  * Checks that the given condition is true. If the condition is false, this
  * function logs and then aborts.
@@ -47,47 +51,31 @@
     }                                                \
   } while (false)
 
-/**
- * Compare `num_items_` of `actual_` against `reference_` buffer.
- *
- * Prints differences between `actual_` and `reference_` before logging an
- * error. Note, the differences between the actual and expected buffer values
- * are logged via LOG_INFO _before_ the error is logged with LOG_ERROR, since by
- * default DV simulations are configured to terminate upon the first error.
- *
- * @param actual_ Buffer containing actual values.
- * @param reference_ Buffer containing expected values.
- * @param num_items_ Number of items to compare.
- * @param ... Arguments to a LOG_* macro, which are evaluated if the check.
- */
-#define CHECK_BUFFER_IMPL_(eq_, actual_, reference_, num_items_, ...)          \
-  do {                                                                         \
-    /* `sizeof(actual_[0])` is used to determine the size of each item in the  \
-     * buffer. */                                                              \
-    if ((memcmp((actual_), (reference_), num_items_ * sizeof((actual_)[0])) == \
-         0) != eq_) {                                                          \
-      for (size_t i = 0; i < num_items_; ++i) {                                \
-        LOG_INFO("[%d] actual = 0x%x; reference = 0x%x", i, (actual_)[i],      \
-                 (reference_)[i]);                                             \
-      }                                                                        \
-      if (OT_VA_ARGS_COUNT(_, ##__VA_ARGS__) == 0) {                           \
-        if (eq_) {                                                             \
-          LOG_ERROR("CHECK-BUFFER-fail: " #actual_                             \
-                    "does not match" #reference_);                             \
-        } else {                                                               \
-          LOG_ERROR("CHECK-BUFFER-fail: " #actual_ "match" #reference_);       \
-        }                                                                      \
-      } else {                                                                 \
-        LOG_ERROR("CHECK-BUFFER-fail: " __VA_ARGS__);                          \
-      }                                                                        \
-      /* Currently, this macro will call into                                  \
-          the test failure code, which logs                                    \
-          "FAIL" and aborts. In the future,                                    \
-          we will try to condition on whether                                  \
-          or not this is a test.*/                                             \
-      test_status_set(kTestStatusFailed);                                      \
-    }                                                                          \
-  } while (false)
+// Note that this is *not* a polyglot header, so we can use the C11-only
+// _Generic keyword safely.
+// See: https://en.cppreference.com/w/c/language/generic
+// clang-format off
+#define SHOW_MISMATCH_FMT_STR_(a) _Generic((a),                 \
+          bool: "CHECK-fail: [%d] got: 0x02%x; want: 0x02%x",   \
+        int8_t: "CHECK-fail: [%d] got: 0x02%x; want: 0x02%x",   \
+       uint8_t: "CHECK-fail: [%d] got: 0x02%x; want: 0x02%x",   \
+       int16_t: "CHECK-fail: [%d] got: 0x04%x; want: 0x04%x",   \
+      uint16_t: "CHECK-fail: [%d] got: 0x04%x; want: 0x04%x",   \
+       int32_t: "CHECK-fail: [%d] got: 0x08%x; want: 0x08%x",   \
+      uint32_t: "CHECK-fail: [%d] got: 0x08%x; want: 0x08%x",   \
+       int64_t: "CHECK-fail: [%d] got: 0x016%x; want: 0x016%x", \
+      uint64_t: "CHECK-fail: [%d] got: 0x016%x; want: 0x016%x")
+#define SHOW_MATCH_FMT_STR_(a) _Generic((a),            \
+          bool: "CHECK-fail: [%d] both equal: 0x02%x",  \
+        int8_t: "CHECK-fail: [%d] both equal: 0x02%x",  \
+       uint8_t: "CHECK-fail: [%d] both equal: 0x02%x",  \
+       int16_t: "CHECK-fail: [%d] both equal: 0x04%x",  \
+      uint16_t: "CHECK-fail: [%d] both equal: 0x04%x",  \
+       int32_t: "CHECK-fail: [%d] both equal: 0x08%x",  \
+      uint32_t: "CHECK-fail: [%d] both equal: 0x08%x",  \
+       int64_t: "CHECK-fail: [%d] both equal: 0x016%x", \
+      uint64_t: "CHECK-fail: [%d] both equal: 0x016%x")
+// clang-format on
 
 /**
  * Compare `num_items_` of `actual_` against `expected_` buffer.
@@ -102,24 +90,76 @@
  * @param num_items_ Number of items to compare.
  * @param ... Arguments to a LOG_* macro, which are evaluated if the check.
  */
-#define CHECK_BUFFER_EQ(actual_, expected_, num_items_, ...) \
-  CHECK_BUFFER_IMPL_(true, actual_, expected_, num_items_, __VA_ARGS__)
+#define CHECK_ARRAYS_EQ(actual_, expected_, num_items_, ...)                  \
+  do {                                                                        \
+    static_assert(sizeof(*(actual_)) == sizeof(*(expected_)),                 \
+                  "CHECK_ARRAYS requires arguments of equal size.");          \
+    bool fail = false;                                                        \
+    for (size_t i = 0; i < num_items_; ++i) {                                 \
+      if ((actual_)[i] != (expected_)[i]) {                                   \
+        if (!fail) {                                                          \
+          /* Print a failure message as soon as possible. */                  \
+          if (OT_VA_ARGS_COUNT(_, ##__VA_ARGS__) == 0) {                      \
+            LOG_ERROR("CHECK-fail: " #actual_ " does not match " #expected_); \
+          } else {                                                            \
+            LOG_ERROR("CHECK-fail: " __VA_ARGS__);                            \
+          }                                                                   \
+        }                                                                     \
+                                                                              \
+        LOG_ERROR(SHOW_MISMATCH_FMT_STR_((actual_)[i]), i, (actual_)[i],      \
+                  (expected_)[i]);                                            \
+        fail = true;                                                          \
+      }                                                                       \
+    }                                                                         \
+    if (fail) {                                                               \
+      /* Currently, this macro will call into                                 \
+          the test failure code, which logs                                   \
+          "FAIL" and aborts. In the future,                                   \
+          we will try to condition on whether                                 \
+          or not this is a test.*/                                            \
+      test_status_set(kTestStatusFailed);                                     \
+    }                                                                         \
+  } while (false)
 
 /**
- * Compare `num_items_` of `actual_` against `unexpected_` buffer.
+ * Compare `num_items_` of `actual_` against `not_expected_` buffer.
  *
- * Prints matches between `actual_` and `unexpected_` before logging an error.
+ * Prints matches between `actual_` and `not_expected_` before logging an error.
  * Note, the matches between the actual and not_expected buffer values are
  * logged via LOG_INFO _before_ the error is logged with LOG_ERROR, since by
  * default DV simulations are configured to terminate upon the first error.
  *
  * @param actual_ Buffer containing actual values.
- * @param unexpected_ Buffer containing not expected values.
+ * @param not_expected_ Buffer containing not expected values.
  * @param num_items_ Number of items to compare.
  * @param ... Arguments to a LOG_* macro, which are evaluated if the check.
  */
-#define CHECK_BUFFER_NEQ(actual_, unexpected_, num_items_, ...) \
-  CHECK_BUFFER_IMPL_(false, actual_, unexpected_, num_items_, __VA_ARGS__)
+#define CHECK_ARRAYS_NE(actual_, not_expected_, num_items_, ...)               \
+  do {                                                                         \
+    static_assert(sizeof(*(actual_)) == sizeof(*(not_expected_)),              \
+                  "CHECK_ARRAYS requires arguments of equal size.");           \
+    if (memcmp((actual_), (not_expected_), num_items_ * sizeof(*(actual_))) == \
+        0) {                                                                   \
+      if (OT_VA_ARGS_COUNT(_, ##__VA_ARGS__) == 0) {                           \
+        LOG_ERROR("CHECK-fail: " #actual_ " matches " #not_expected_);         \
+      } else {                                                                 \
+        LOG_ERROR("CHECK-fail: " __VA_ARGS__);                                 \
+      }                                                                        \
+      for (size_t i = 0; i < num_items_; ++i) {                                \
+        LOG_ERROR(SHOW_MATCH_FMT_STR_((actual_)[i]), i, (actual_)[i]);         \
+      }                                                                        \
+      /* Currently, this macro will call into                                  \
+          the test failure code, which logs                                    \
+          "FAIL" and aborts. In the future,                                    \
+          we will try to condition on whether                                  \
+          or not this is a test.*/                                             \
+      test_status_set(kTestStatusFailed);                                      \
+    }                                                                          \
+  } while (false)
+
+// Temporary shims to prevent merge-skew-breakage during renaming.
+#define CHECK_BUFFER_EQ CHECK_ARRAYS_EQ
+#define CHECK_BUFFER_NEQ CHECK_ARRAYS_NE
 
 /**
  * Checks that the given DIF call returns kDifOk. If the DIF call returns a
diff --git a/sw/device/tests/flash_ctrl_test.c b/sw/device/tests/flash_ctrl_test.c
index 5f042ab..75a81a3 100644
--- a/sw/device/tests/flash_ctrl_test.c
+++ b/sw/device/tests/flash_ctrl_test.c
@@ -14,16 +14,6 @@
 
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
 
-#define CHECK_ARRAYS_EQ(xs, ys, len) \
-  do {                               \
-    uint32_t *xs_ = (xs);            \
-    uint32_t *ys_ = (ys);            \
-    size_t len_ = (len);             \
-    for (int i = 0; i < len_; ++i) { \
-      CHECK(xs_[i] == ys_[i]);       \
-    }                                \
-  } while (false)
-
 #define CHECK_EQZ(x) CHECK((x) == 0)
 #define CHECK_NEZ(x) CHECK((x) != 0)