summaryrefslogtreecommitdiff
path: root/include/test.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/test.h')
-rw-r--r--include/test.h525
1 files changed, 475 insertions, 50 deletions
diff --git a/include/test.h b/include/test.h
index 012ffc51..5261dbd9 100644
--- a/include/test.h
+++ b/include/test.h
@@ -8,7 +8,14 @@
#ifndef TEST_H_
#define TEST_H_
+#define _GNU_SOURCE
+
#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
#if defined(__aarch64__)
#include <aarch64/efibind.h>
@@ -36,17 +43,368 @@
#include <stdlib.h>
-#define ZeroMem(buf, sz) memset(buf, 0, sz)
-#define SetMem(buf, sz, value) memset(buf, value, sz)
-#define CopyMem(dest, src, len) memcpy(dest, src, len)
-#define CompareMem(dest, src, len) memcmp(dest, src, len)
+#include <assert.h>
+
+#include <efiui.h>
+#include <efilib.h>
+
+#include <efivar/efivar.h>
#include <assert.h>
-#define AllocateZeroPool(x) calloc(1, (x))
-#define AllocatePool(x) malloc(x)
-#define FreePool(x) free(x)
-#define ReallocatePool(old, oldsz, newsz) realloc(old, newsz)
+#include "list.h"
+
+INTN StrCmp(IN CONST CHAR16 *s1,
+ IN CONST CHAR16 *s2);
+INTN StrnCmp(IN CONST CHAR16 *s1,
+ IN CONST CHAR16 *s2,
+ IN UINTN len);
+VOID StrCpy(IN CHAR16 *Dest,
+ IN CONST CHAR16 *Src);
+VOID StrnCpy(IN CHAR16 *Dest,
+ IN CONST CHAR16 *Src,
+ IN UINTN Len);
+CHAR16 *StrDuplicate(IN CONST CHAR16 *Src);
+UINTN StrLen(IN CONST CHAR16 *s1);
+UINTN StrSize(IN CONST CHAR16 *s1);
+VOID StrCat(IN CHAR16 *Dest, IN CONST CHAR16 *Src);
+CHAR16 *DevicePathToStr(EFI_DEVICE_PATH *DevPath);
+
+extern EFI_SYSTEM_TABLE *ST;
+extern EFI_BOOT_SERVICES *BS;
+extern EFI_RUNTIME_SERVICES *RT;
+
+#define GUID_FMT "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+#define GUID_ARGS(guid) \
+ ((EFI_GUID)guid).Data1, ((EFI_GUID)guid).Data2, ((EFI_GUID)guid).Data3, \
+ ((EFI_GUID)guid).Data4[1], ((EFI_GUID)guid).Data4[0], \
+ ((EFI_GUID)guid).Data4[2], ((EFI_GUID)guid).Data4[3], \
+ ((EFI_GUID)guid).Data4[4], ((EFI_GUID)guid).Data4[5], \
+ ((EFI_GUID)guid).Data4[6], ((EFI_GUID)guid).Data4[7]
+
+static inline INT64
+guidcmp_helper(const EFI_GUID * const guid0, const EFI_GUID * const guid1)
+{
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): Comparing "GUID_FMT" to "GUID_FMT"\n",
+ __FILE__, __LINE__-1, __func__,
+ GUID_ARGS(*guid0), GUID_ARGS(*guid1));
+#endif
+
+ if (guid0->Data1 != guid1->Data1) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data1, (INT64)guid1->Data1,
+ (INT64)guid0->Data1 - (INT64)guid1->Data1);
+#endif
+ return (INT64)guid0->Data1 - (INT64)guid1->Data1;
+ }
+
+ if (guid0->Data2 != guid1->Data2) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data2, (INT64)guid1->Data2,
+ (INT64)guid0->Data2 - (INT64)guid1->Data2);
+#endif
+ return (INT64)guid0->Data2 - (INT64)guid1->Data2;
+ }
+
+ if (guid0->Data3 != guid1->Data3) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data3, (INT64)guid1->Data3,
+ (INT64)guid0->Data3 - (INT64)guid1->Data3);
+#endif
+ return (INT64)guid0->Data3 - (INT64)guid1->Data3;
+ }
+
+ /*
+ * This is out of order because that's also true in the string
+ * representation of it.
+ */
+ if (guid0->Data4[1] != guid1->Data4[1]) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data4[1], (INT64)guid1->Data4[1],
+ (INT64)guid0->Data4[1] - (INT64)guid1->Data4[1]);
+#endif
+ return (INT64)guid0->Data4[1] - (INT64)guid1->Data4[1];
+ }
+
+ if (guid0->Data4[0] != guid1->Data4[0]) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data4[0], (INT64)guid1->Data4[0],
+ (INT64)guid0->Data4[0] - (INT64)guid1->Data4[0]);
+#endif
+ return (INT64)guid0->Data4[0] - (INT64)guid1->Data4[0];
+ }
+
+ for (UINTN i = 2; i < 8; i++) {
+ if (guid0->Data4[i] != guid1->Data4[i]) {
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x%"PRIx64"-0x%"PRIx64"->0x%"PRIx64"\n",
+ __FILE__, __LINE__-1, __func__,
+ (INT64)guid0->Data4[i], (INT64)guid1->Data4[i],
+ (INT64)guid0->Data4[i] - (INT64)guid1->Data4[i]);
+#endif
+ return (INT64)guid0->Data4[i] - (INT64)guid1->Data4[i];
+ }
+ }
+
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s(): returning 0x0\n",
+ __FILE__, __LINE__-1, __func__);
+#endif
+ return 0;
+}
+
+static inline int
+guidcmp(const EFI_GUID * const guid0, const EFI_GUID * const guid1)
+{
+ INT64 cmp;
+ int ret;
+ EFI_GUID empty;
+ const EFI_GUID * const guida = guid0 ? guid0 : &empty;
+ const EFI_GUID * const guidb = guid1 ? guid1 : &empty;
+
+ SetMem(&empty, sizeof(EFI_GUID), 0);
+
+ cmp = guidcmp_helper(guida, guidb);
+ ret = cmp < 0 ? -1 : (cmp > 0 ? 1 : 0);
+#if (defined(SHIM_DEBUG) && SHIM_DEBUG != 0)
+ printf("%s:%d:%s():CompareGuid("GUID_FMT","GUID_FMT")->%lld (%d)\n",
+ __FILE__, __LINE__-1, __func__,
+ GUID_ARGS(*guida), GUID_ARGS(*guidb), cmp, ret);
+#endif
+ return ret;
+}
+
+#define CompareGuid(a, b) guidcmp(a, b)
+
+static inline char *
+efi_strerror(EFI_STATUS status)
+{
+ static char buf0[1024];
+ static char buf1[1024];
+ char *out;
+ static int n;
+
+ out = n++ % 2 ? buf0 : buf1;
+ if (n > 1)
+ n -= 2;
+ SetMem(out, 1024, 0);
+
+ switch (status) {
+ case EFI_SUCCESS:
+ strcpy(out, "EFI_SUCCESS");
+ break;
+ case EFI_LOAD_ERROR:
+ strcpy(out, "EFI_LOAD_ERROR");
+ break;
+ case EFI_INVALID_PARAMETER:
+ strcpy(out, "EFI_INVALID_PARAMETER");
+ break;
+ case EFI_UNSUPPORTED:
+ strcpy(out, "EFI_UNSUPPORTED");
+ break;
+ case EFI_BAD_BUFFER_SIZE:
+ strcpy(out, "EFI_BAD_BUFFER_SIZE");
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ strcpy(out, "EFI_BUFFER_TOO_SMALL");
+ break;
+ case EFI_NOT_READY:
+ strcpy(out, "EFI_NOT_READY");
+ break;
+ case EFI_DEVICE_ERROR:
+ strcpy(out, "EFI_DEVICE_ERROR");
+ break;
+ case EFI_WRITE_PROTECTED:
+ strcpy(out, "EFI_WRITE_PROTECTED");
+ break;
+ case EFI_OUT_OF_RESOURCES:
+ strcpy(out, "EFI_OUT_OF_RESOURCES");
+ break;
+ case EFI_VOLUME_CORRUPTED:
+ strcpy(out, "EFI_VOLUME_CORRUPTED");
+ break;
+ case EFI_VOLUME_FULL:
+ strcpy(out, "EFI_VOLUME_FULL");
+ break;
+ case EFI_NO_MEDIA:
+ strcpy(out, "EFI_NO_MEDIA");
+ break;
+ case EFI_MEDIA_CHANGED:
+ strcpy(out, "EFI_MEDIA_CHANGED");
+ break;
+ case EFI_NOT_FOUND:
+ strcpy(out, "EFI_NOT_FOUND");
+ break;
+ case EFI_ACCESS_DENIED:
+ strcpy(out, "EFI_ACCESS_DENIED");
+ break;
+ case EFI_NO_RESPONSE:
+ strcpy(out, "EFI_NO_RESPONSE");
+ break;
+ case EFI_NO_MAPPING:
+ strcpy(out, "EFI_NO_MAPPING");
+ break;
+ case EFI_TIMEOUT:
+ strcpy(out, "EFI_TIMEOUT");
+ break;
+ case EFI_NOT_STARTED:
+ strcpy(out, "EFI_NOT_STARTED");
+ break;
+ case EFI_ALREADY_STARTED:
+ strcpy(out, "EFI_ALREADY_STARTED");
+ break;
+ case EFI_ABORTED:
+ strcpy(out, "EFI_ABORTED");
+ break;
+ case EFI_ICMP_ERROR:
+ strcpy(out, "EFI_ICMP_ERROR");
+ break;
+ case EFI_TFTP_ERROR:
+ strcpy(out, "EFI_TFTP_ERROR");
+ break;
+ case EFI_PROTOCOL_ERROR:
+ strcpy(out, "EFI_PROTOCOL_ERROR");
+ break;
+ case EFI_INCOMPATIBLE_VERSION:
+ strcpy(out, "EFI_INCOMPATIBLE_VERSION");
+ break;
+ case EFI_SECURITY_VIOLATION:
+ strcpy(out, "EFI_SECURITY_VIOLATION");
+ break;
+ case EFI_CRC_ERROR:
+ strcpy(out, "EFI_CRC_ERROR");
+ break;
+ case EFI_END_OF_MEDIA:
+ strcpy(out, "EFI_END_OF_MEDIA");
+ break;
+ case EFI_END_OF_FILE:
+ strcpy(out, "EFI_END_OF_FILE");
+ break;
+ case EFI_INVALID_LANGUAGE:
+ strcpy(out, "EFI_INVALID_LANGUAGE");
+ break;
+ case EFI_COMPROMISED_DATA:
+ strcpy(out, "EFI_COMPROMISED_DATA");
+ break;
+ default:
+ sprintf(out, "0x%lx", status);
+ break;
+ }
+ return out;
+}
+
+static inline char *
+Str2str(CHAR16 *in)
+{
+ static char buf0[1024];
+ static char buf1[1024];
+ char *out;
+ static int n;
+
+ out = n++ % 2 ? buf0 : buf1;
+ if (n > 1)
+ n -= 2;
+ SetMem(out, 1024, 0);
+ for (UINTN i = 0; i < 1023 && in[i]; i++)
+ out[i] = in[i];
+ return out;
+}
+
+static inline char *
+format_var_attrs(UINT32 attr)
+{
+ static char buf0[1024];
+ static char buf1[1024];
+ static int n;
+ int pos = 0;
+ bool found = false;
+ char *buf, *bufp;
+
+ buf = n++ % 2 ? buf0 : buf1;
+ if (n > 1)
+ n -= 2;
+ SetMem(buf, sizeof(buf0), 0);
+ bufp = &buf[0];
+ for (UINT32 i = 0; i < 8; i++) {
+ switch((1ul << i) & attr) {
+ case EFI_VARIABLE_NON_VOLATILE:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "NV");
+ attr &= ~EFI_VARIABLE_NON_VOLATILE;
+ found = true;
+ break;
+ case EFI_VARIABLE_BOOTSERVICE_ACCESS:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "BS");
+ attr &= ~EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ found = true;
+ break;
+ case EFI_VARIABLE_RUNTIME_ACCESS:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "RT");
+ attr &= ~EFI_VARIABLE_RUNTIME_ACCESS;
+ found = true;
+ break;
+ case EFI_VARIABLE_HARDWARE_ERROR_RECORD:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "HER");
+ attr &= ~EFI_VARIABLE_HARDWARE_ERROR_RECORD;
+ found = true;
+ break;
+ case EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "AUTH");
+ attr &= ~EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
+ found = true;
+ break;
+ case EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "TIMEAUTH");
+ attr &= ~EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+ found = true;
+ break;
+ case EFI_VARIABLE_APPEND_WRITE:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "APPEND");
+ attr &= ~EFI_VARIABLE_APPEND_WRITE;
+ found = true;
+ break;
+ case EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS:
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ bufp = stpcpy(bufp, "ENHANCED_AUTH");
+ attr &= ~EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS;
+ found = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (attr) {
+ if (found)
+ bufp = stpcpy(bufp, "|");
+ snprintf(bufp, bufp - buf - 1, "0x%x", attr);
+ }
+ return &buf[0];
+}
extern int debug;
#ifdef dprint
@@ -54,6 +412,14 @@ extern int debug;
#define dprint(fmt, ...) {( if (debug) printf("%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__); })
#endif
+void EFIAPI mock_efi_void();
+EFI_STATUS EFIAPI mock_efi_success();
+EFI_STATUS EFIAPI mock_efi_unsupported();
+EFI_STATUS EFIAPI mock_efi_not_found();
+void init_efi_system_table(void);
+void reset_efi_system_table(void);
+void print_traceback(int skip);
+
#define eassert(cond, fmt, ...) \
({ \
if (!(cond)) { \
@@ -63,24 +429,24 @@ extern int debug;
assert(cond); \
})
-#define assert_true_as_expr(a, status, fmt, ...) \
- ({ \
- int rc_ = 0; \
- if (!(a)) { \
- printf("%s:%d:got %lld, expected nonzero " fmt, \
- __func__, __LINE__, (long long)(a), \
- ##__VA_ARGS__); \
- printf("%s:%d:Assertion `%s' failed.\n", __func__, \
- __LINE__, __stringify(!(a))); \
- rc_ = status; \
- } \
- rc_; \
+#define assert_true_as_expr(a, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = 0; \
+ if (!(a)) { \
+ printf("%s:%d:got %lld, expected nonzero " fmt, \
+ __func__, __LINE__, (long long)(uintptr_t)(a), \
+ ##__VA_ARGS__); \
+ printf("%s:%d:Assertion `%s' failed.\n", __func__, \
+ __LINE__, __stringify(!(a))); \
+ rc_ = status; \
+ } \
+ rc_; \
})
#define assert_nonzero_as_expr(a, ...) assert_true_as_expr(a, ##__VA_ARGS__)
#define assert_false_as_expr(a, status, fmt, ...) \
({ \
- int rc_ = 0; \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
if (a) { \
printf("%s:%d:got %lld, expected zero " fmt, __func__, \
__LINE__, (long long)(a), ##__VA_ARGS__); \
@@ -94,7 +460,7 @@ extern int debug;
#define assert_positive_as_expr(a, status, fmt, ...) \
({ \
- int rc_ = 0; \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
if ((a) <= 0) { \
printf("%s:%d:got %lld, expected > 0 " fmt, __func__, \
__LINE__, (long long)(a), ##__VA_ARGS__); \
@@ -107,7 +473,7 @@ extern int debug;
#define assert_negative_as_expr(a, status, fmt, ...) \
({ \
- int rc_ = 0; \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
if ((a) >= 0) { \
printf("%s:%d:got %lld, expected < 0 " fmt, __func__, \
__LINE__, (long long)(a), ##__VA_ARGS__); \
@@ -120,7 +486,7 @@ extern int debug;
#define assert_equal_as_expr(a, b, status, fmt, ...) \
({ \
- int rc_ = 0; \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
if (!((a) == (b))) { \
printf("%s:%d:" fmt, __func__, __LINE__, (a), (b), \
##__VA_ARGS__); \
@@ -131,9 +497,22 @@ extern int debug;
rc_; \
})
+#define assert_not_equal_as_expr(a, b, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
+ if (!((a) != (b))) { \
+ printf("%s:%d:" fmt, __func__, __LINE__, (a), (b), \
+ ##__VA_ARGS__); \
+ printf("%s:%d:Assertion `%s' failed.\n", __func__, \
+ __LINE__, __stringify(a != b)); \
+ rc_ = status; \
+ } \
+ rc_; \
+ })
+
#define assert_as_expr(cond, status, fmt, ...) \
({ \
- int rc_ = 0; \
+ __typeof__(status) rc_ = (__typeof__(status))0; \
if (!(cond)) { \
printf("%s:%d:" fmt, __func__, __LINE__, \
##__VA_ARGS__); \
@@ -144,51 +523,62 @@ extern int debug;
rc_; \
})
-#define assert_true_return(a, status, fmt, ...) \
- ({ \
- int rc_ = assert_true_as_expr(a, status, fmt, ##__VA_ARGS__); \
- if (rc_ != 0) \
- return rc_; \
+#define assert_true_return(a, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = \
+ assert_true_as_expr(a, status, fmt, ##__VA_ARGS__); \
+ if (rc_ != 0) \
+ return rc_; \
})
#define assert_nonzero_return(a, ...) assert_true_return(a, ##__VA_ARGS__)
-#define assert_false_return(a, status, fmt, ...) \
- ({ \
- int rc_ = assert_false_as_expr(a, status, fmt, ##__VA_ARGS__); \
- if (rc_ != 0) \
- return rc_; \
+#define assert_false_return(a, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = \
+ assert_false_as_expr(a, status, fmt, ##__VA_ARGS__); \
+ if (rc_ != 0) \
+ return rc_; \
})
#define assert_zero_return(a, ...) assert_false_return(a, ##__VA_ARGS__)
#define assert_positive_return(a, status, fmt, ...) \
({ \
- int rc_ = assert_positive_as_expr(a, status, fmt, \
- ##__VA_ARGS__); \
+ __typeof__(status) rc_ = assert_positive_as_expr( \
+ a, status, fmt, ##__VA_ARGS__); \
if (rc_ != 0) \
return rc_; \
})
#define assert_negative_return(a, status, fmt, ...) \
({ \
- int rc_ = assert_negative_as_expr(a, status, fmt, \
- ##__VA_ARGS__); \
+ __typeof__(status) rc_ = assert_negative_as_expr( \
+ a, status, fmt, ##__VA_ARGS__); \
if (rc_ != 0) \
return rc_; \
})
-#define assert_equal_return(a, b, status, fmt, ...) \
- ({ \
- int rc_ = assert_equal_as_expr(a, b, status, fmt, \
- ##__VA_ARGS__); \
- if (rc_ != 0) \
- return rc_; \
+#define assert_equal_return(a, b, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = assert_equal_as_expr( \
+ a, b, status, fmt, ##__VA_ARGS__); \
+ if (rc_ != 0) \
+ return rc_; \
})
-#define assert_return(cond, status, fmt, ...) \
- ({ \
- int rc_ = assert_as_expr(cond, status, fmt, ##__VA_ARGS__); \
- if (rc_ != 0) \
- return rc_; \
+#define assert_not_equal_return(a, b, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = assert_not_equal_as_expr( \
+ a, b, status, fmt, ##__VA_ARGS__); \
+ if (rc_ != 0) \
+ return rc_; \
+ })
+
+#define assert_return(cond, status, fmt, ...) \
+ ({ \
+ __typeof__(status) rc_ = \
+ assert_as_expr(cond, status, fmt, ##__VA_ARGS__); \
+ if (rc_ != 0) \
+ return rc_; \
})
#define assert_goto(cond, label, fmt, ...) \
@@ -213,6 +603,41 @@ extern int debug;
} \
})
+#define assert_not_equal_goto(a, b, label, fmt, ...) \
+ ({ \
+ if (!((a) != (b))) { \
+ printf("%s:%d:" fmt, __func__, __LINE__, (a), (b), \
+ ##__VA_ARGS__); \
+ printf("%s:%d:Assertion `%s' failed.\n", __func__, \
+ __LINE__, __stringify(a != b)); \
+ goto label; \
+ } \
+ })
+
+#define assert_true_goto(a, label, fmt, ...) \
+ ({ \
+ if (!(a)) { \
+ printf("%s:%d:" fmt, __func__, __LINE__, (a), \
+ ##__VA_ARGS__); \
+ printf("%s:%d:Assertion `%s' failed.\n", __func__, \
+ __LINE__, __stringify(!(a))); \
+ goto label; \
+ } \
+ })
+#define assert_nonzero_goto(a, ...) assert_true_goto(a, ##__VA_ARGS__)
+
+#define assert_false_goto(a, label, fmt, ...) \
+ ({ \
+ if (a) { \
+ printf("%s:%d:" fmt, __func__, __LINE__, (a), \
+ ##__VA_ARGS__); \
+ printf("%s:%d:Assertion `%s' failed.\n", __func__, \
+ __LINE__, __stringify(a)); \
+ goto label; \
+ } \
+ })
+#define assert_zero_goto(a, ...) assert_false_goto(a, ##__VA_ARGS__)
+
#define assert_negative_goto(a, label, fmt, ...) \
({ \
int rc_ = assert_negative_as_expr(a, -1, fmt, ##__VA_ARGS__); \