From 55c858555e96f9ad8dc929a769d6b3251441ead7 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 14 Feb 2023 19:17:18 +0100 Subject: [PATCH] tests: add REQUIRE_MEMEQ() macro Actually prints out the offending memory regions. Very useful for debugging, to avoid having to attach a (gdb) instance and poke at memory regions every single time. --- src/tests/tests.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/tests/tests.h b/src/tests/tests.h index c58d8044..28be773f 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -105,6 +105,45 @@ static inline bool feq(float a, float b, float epsilon) } \ } while (0) +static inline void log_array(const uint8_t *a, const uint8_t *ref, size_t size) +{ + for (size_t n = 0; n < size; n++) { + const char *prefix = "", *suffix = ""; + char terminator = ' '; + if (a[n] != ref[n]) { + prefix = "\033[31;1m"; + suffix = "\033[0m"; + } + if (n+1 == size || n % 16 == 15) + terminator = '\n'; + fprintf(stderr, "%s%02"PRIx8"%s%c", prefix, a[n], suffix, terminator); + } +} + +static inline void require_memeq(const void *aptr, const void *bptr, size_t size, + const char *astr, const char *bstr, + const char *sizestr, const char *file, int line) +{ + const uint8_t *a = aptr, *b = bptr; + for (size_t i = 0; i < size; i++) { + if (a[i] == b[i]) + continue; + + fprintf(stderr, "=== FAILED: memcmp(%s, %s, %s) == 0 at %s:%d\n" + "at position %zu: 0x%02"PRIx8" != 0x%02"PRIx8"\n\n", + astr, bstr, sizestr, file, line, i, a[i], b[i]); + + const size_t logsize = PL_MIN(size, PL_MAX(i+2, 512)); + fprintf(stderr, "first %zu bytes of '%s':\n", logsize, astr); + log_array(a, b, logsize); + fprintf(stderr, "\nfirst %zu bytes of '%s':\n", logsize, bstr); + log_array(b, a, logsize); + exit(1); + } +} + +#define REQUIRE_MEMEQ(a, b, size) require_memeq(a, b, size, #a, #b, #size, __FILE__, __LINE__) + #define REQUIRE_HANDLE(shmem, type) \ switch (type) { \ case PL_HANDLE_FD: \