[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)