diff options
Diffstat (limited to 'libmisc/tests/test_assert.c')
-rw-r--r-- | libmisc/tests/test_assert.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/libmisc/tests/test_assert.c b/libmisc/tests/test_assert.c new file mode 100644 index 0000000..84b4d36 --- /dev/null +++ b/libmisc/tests/test_assert.c @@ -0,0 +1,104 @@ +/* libmisc/tests/test_assert.c - Tests for <libmisc/assert.h> + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <setjmp.h> +#include <stdlib.h> +#include <string.h> + +#include <libmisc/_intercept.h> +#include <libmisc/assert.h> +#include <libmisc/fmt.h> +#include <libmisc/macro.h> + +#include "test.h" + +/* Intercept failures and logging *********************************************/ + +static bool global_failed; +static struct fmt_buf global_log; +static jmp_buf global_env; + +#define with_intercept() ({ \ + global_failed = false; \ + global_log_clear(); \ + setjmp(global_env) == 0; \ + }) + +void __lm_abort(void) { + global_failed = true; + longjmp(global_env, 1); +} + +void __lm_putchar(unsigned char c) { + if (global_log.len+1 >= global_log.cap) { + global_log.cap += 16; + global_log.dat = realloc(global_log.dat, global_log.cap); + memset(global_log.dat + global_log.len, 0, global_log.cap - global_log.len); + } + ((uint8_t *)global_log.dat)[global_log.len++] = (uint8_t)c; +} + +static void global_log_clear(void) { + if (global_log.dat) + memset(global_log.dat, 0, global_log.cap); + global_log.len = 0; +} + +#define __builtin_unreachable() test_assert(0) + +/* Utilities ******************************************************************/ + +#define test_should_succeed(test) do { \ + if (with_intercept()) { \ + test; \ + } \ + test_assert(global_failed == false); \ + test_assert(global_log.len == 0); \ + } while (0) + +#define test_should_fail(test, exp_log) do { \ + if (with_intercept()) { \ + test; \ + } \ + test_assert(global_failed == true); \ + if (!(global_log.len != 0 && \ + strcmp(global_log.dat, exp_log) == 0)) { \ + printf("exp = \"%s\"\n" \ + "act = \"%s\"\n", \ + exp_log, (char *)global_log.dat); \ + test_assert(0); \ + } \ + } while (0) + +/* Actual tests ***************************************************************/ + +static_assert(sizeof(char) == 1); + +int main() { + unsigned char x = 4; + static_assert(0 <= x); + static_assert(x < 256); + +#ifndef NDEBUG + test_should_succeed(assert(true)); + test_should_fail(assert(false), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed\n"); + + test_should_succeed(assert_msg(true, "foo")); + test_should_fail(assert_msg(false, "foo"), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed: foo\n"); + test_should_succeed(assert_msg(true, NULL)); + test_should_fail(assert_msg(false, NULL), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed\n"); + + test_should_fail(assert_notreached("xxx"), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"notreached\" failed: xxx\n"); +#endif + + if (global_log.dat) { + global_log_clear(); + free(global_log.dat); + global_log.dat = NULL; + global_log.cap = 0; + } + return 0; +} |