+static inline char *hexstring(uint8_t *data, size_t size)
+{
+ char *str;
+ switch (size) {
+ case sizeof(unsigned long long):
+ asprintf(&str, "%016llx", *(unsigned long long *)data);
+ break;
+ case sizeof(unsigned int):
+ asprintf(&str, "%08x", *(unsigned int*)data);
+ break;
+ case sizeof(uint16_t):
+ asprintf(&str, "%04x", *(uint16_t *)data);
+ break;
+ default:
+ str = (char *)malloc(size * 2 + 1);
+ for (size_t i = 0; i < size; i++) {
+ sprintf(str + i, "%02x", data[i]);
+ }
+ }
+ return str;
+}
+
+static inline void failnotequal(uint8_t *lhs, size_t lhsSize, uint8_t *rhs, size_t rhsSize, const char *lhsStr, const char *rhsStr, const char *file, unsigned line)
+{
+ fprintf(stderr, "BAD: failed assertion '%s != %s' (0x%s != 0x%s) at %s:%u\n", lhsStr, rhsStr, hexstring(lhs, lhsSize), hexstring(rhs, rhsSize), file, line);
+ exit(1);
+}
+
+#define testassertequal(lhs, rhs) do {\
+ __typeof__(lhs) __lhs = lhs; \
+ __typeof__(rhs) __rhs = rhs; \
+ if ((lhs) != (rhs)) failnotequal((uint8_t *)&__lhs, sizeof(__lhs), (uint8_t *)&__rhs, sizeof(__rhs), #lhs, #rhs, __FILE__, __LINE__); \
+} while(0)
+