diff options
Diffstat (limited to 'libmisc/tests')
-rw-r--r-- | libmisc/tests/test_assert.c | 36 | ||||
-rw-r--r-- | libmisc/tests/test_assert_min.c | 17 | ||||
-rw-r--r-- | libmisc/tests/test_endian.c | 39 | ||||
-rw-r--r-- | libmisc/tests/test_log.c | 49 | ||||
-rw-r--r-- | libmisc/tests/test_macro.c | 54 | ||||
-rw-r--r-- | libmisc/tests/test_map.c | 60 | ||||
-rw-r--r-- | libmisc/tests/test_private.c | 10 | ||||
-rw-r--r-- | libmisc/tests/test_rand.c | 25 | ||||
-rw-r--r-- | libmisc/tests/test_vcall.c | 74 |
9 files changed, 220 insertions, 144 deletions
diff --git a/libmisc/tests/test_assert.c b/libmisc/tests/test_assert.c index 5b28561..15f9446 100644 --- a/libmisc/tests/test_assert.c +++ b/libmisc/tests/test_assert.c @@ -1,20 +1,21 @@ /* libmisc/tests/test_assert.c - Tests for <libmisc/assert.h> * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ #include <setjmp.h> +#include <stdarg.h> /* for va_list, va_start(), va_end() */ #include <stdbool.h> -#include <string.h> #include <stdlib.h> +#include <string.h> +#include <libmisc/macro.h> #include <libmisc/assert.h> +#include <libmisc/_intercept.h> #include "test.h" -#define UNUSED(name) - /* Intercept failures and logging *********************************************/ bool global_failed; @@ -29,17 +30,21 @@ jmp_buf global_env; setjmp(global_env) == 0; \ }) -[[noreturn]] void abort(void) { +void __lm_abort(void) { global_failed = true; longjmp(global_env, 1); } -#define __builtin_unreachable() test_assert(0) - -int vprintf(const char *format, va_list ap) { - return vasprintf(&global_log, format, ap); +int __lm_light_printf(const char *format, ...) { + va_list va; + va_start(va, format); + int ret = vasprintf(&global_log, format, va); + va_end(va); + return ret; } +#define __builtin_unreachable() test_assert(0) + /* Utilities ******************************************************************/ #define test_should_succeed(test) do { \ @@ -64,27 +69,26 @@ int vprintf(const char *format, va_list ap) { } \ } while (0) -#define _STR(x) #x -#define STR(x) _STR(x) - /* Actual tests ***************************************************************/ static_assert(sizeof(char) == 1); int main() { +#ifndef NDEBUG test_should_succeed(assert(true)); - test_should_fail(assert(false), "error: ASSERT: "__FILE__":"STR(__LINE__)":main(): assertion \"false\" failed\n"); + 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__":"STR(__LINE__)":main(): assertion \"false\" failed: foo\n"); + 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__":"STR(__LINE__)":main(): assertion \"false\" failed\n"); + 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__":"STR(__LINE__)":main(): assertion \"notreached\" failed: xxx\n"); + test_should_fail(assert_notreached("xxx"), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"notreached\" failed: xxx\n"); if (global_log) { free(global_log); global_log = NULL; } +#endif return 0; } diff --git a/libmisc/tests/test_assert_min.c b/libmisc/tests/test_assert_min.c new file mode 100644 index 0000000..9c0394b --- /dev/null +++ b/libmisc/tests/test_assert_min.c @@ -0,0 +1,17 @@ +/* libmisc/tests/test_assert_min.c - Tests for minimal <libmisc/assert.h> + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +/* Don't include *anything* else. */ +#include <libmisc/assert.h> + +static_assert(1 == 1); + +int main() { + assert_msg(1, "foo"); + assert(1); + return 0; + assert_notreached("ret"); +} diff --git a/libmisc/tests/test_endian.c b/libmisc/tests/test_endian.c index d0b547c..dcb3cc2 100644 --- a/libmisc/tests/test_endian.c +++ b/libmisc/tests/test_endian.c @@ -1,6 +1,6 @@ /* libmisc/tests/test_endian.c - Tests for <libmisc/endian.h> * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -11,22 +11,31 @@ #include "test.h" int main() { - uint8_t act[12] = {0}; - uint16be_encode(&act[0], UINT16_C(0x1234)); - uint32be_encode(&act[2], UINT32_C(0x56789ABC)); - uint16le_encode(&act[6], UINT16_C(0x1234)); - uint32le_encode(&act[8], UINT32_C(0x56789ABC)); + uint8_t act[(2+4+8)*2] = {0}; + size_t pos = 0; + pos += uint16be_encode(&act[pos], UINT16_C(0x1234)); + pos += uint32be_encode(&act[pos], UINT32_C(0x56789ABC)); + pos += uint64be_encode(&act[pos], UINT64_C(0xAC589A93278CB30A)); + pos += uint16le_encode(&act[pos], UINT16_C(0x1234)); + pos += uint32le_encode(&act[pos], UINT32_C(0x56789ABC)); + pos += uint64le_encode(&act[pos], UINT64_C(0xAC589A93278CB30A)); - uint8_t exp[12] = { 0x12, 0x34, - 0x56, 0x78, 0x9A, 0xBC, - 0x34, 0x12, - 0xBC, 0x9A, 0x78, 0x56 }; - test_assert(memcmp(act, exp, 12) == 0); + test_assert(pos == sizeof(act)); + uint8_t exp[(2+4+8)*2] = { 0x12, 0x34, + 0x56, 0x78, 0x9A, 0xBC, + 0xAC, 0x58, 0x9A, 0x93, 0x27, 0x8C, 0xB3, 0x0A, + 0x34, 0x12, + 0xBC, 0x9A, 0x78, 0x56, + 0x0A, 0xB3, 0x8C, 0x27, 0x93, 0x9A, 0x58, 0xAC}; + test_assert(memcmp(act, exp, sizeof(act)) == 0); - test_assert(uint16be_decode(&act[0]) == UINT16_C(0x1234)); - test_assert(uint32be_decode(&act[2]) == UINT32_C(0x56789ABC)); - test_assert(uint16le_decode(&act[6]) == UINT16_C(0x1234)); - test_assert(uint32le_decode(&act[8]) == UINT32_C(0x56789ABC)); + pos = 0; + test_assert(uint16be_decode(&act[pos]) == UINT16_C(0x1234)); pos += 2; + test_assert(uint32be_decode(&act[pos]) == UINT32_C(0x56789ABC)); pos += 4; + test_assert(uint64be_decode(&act[pos]) == UINT64_C(0xAC589A93278CB30A)); pos += 8; + test_assert(uint16le_decode(&act[pos]) == UINT16_C(0x1234)); pos += 2; + test_assert(uint32le_decode(&act[pos]) == UINT32_C(0x56789ABC)); pos += 4; + test_assert(uint64le_decode(&act[pos]) == UINT64_C(0xAC589A93278CB30A)); pos += 8; return 0; } diff --git a/libmisc/tests/test_log.c b/libmisc/tests/test_log.c index 286738d..49a76ca 100644 --- a/libmisc/tests/test_log.c +++ b/libmisc/tests/test_log.c @@ -13,36 +13,43 @@ #define LOG_NAME FROBNICATE #include <libmisc/log.h> +#include <libmisc/_intercept.h> + #include "test.h" /* Intercept output ***********************************************************/ static char *log_output = NULL; -int vprintf(const char *format, va_list ap) { - return vasprintf(&log_output, format, ap); +int __lm_printf(const char *format, ...) { + va_list va; + va_start(va, format); + int ret = vasprintf(&log_output, format, va); + va_end(va); + return ret; } /* Actual tests ***************************************************************/ -#define should_print(_exp, cmd) do { \ - char *exp = _exp; \ - test_assert(!log_output); \ - cmd; \ - if (!exp) \ - test_assert(!log_output); \ - else \ - if (!(log_output != NULL && \ - strcmp(log_output, exp) == 0)) { \ - printf("exp = \"%s\"\n" \ - "act = \"%s\"\n", \ - exp, log_output); \ - test_assert(0); \ - } \ - if (log_output) { \ - free(log_output); \ - log_output = NULL; \ - } \ +#define should_print(_exp, cmd) do { \ + char *exp = _exp; \ + test_assert(!log_output); \ + cmd; \ + if (!exp) \ + test_assert(!log_output); \ + else { \ + test_assert(log_output); \ + if (strcmp(log_output, exp)) { \ + printf("exp = \"%s\"\n" \ + "act = \"%s\"\n", \ + exp, log_output); \ + test_assert(0); \ + } \ + } \ + if (log_output) { \ + free(log_output); \ + log_output = NULL; \ + } \ } while (0) int main() { @@ -50,6 +57,7 @@ int main() { errorf("val=%d", 42)); should_print("info : FROBNICATE: val=0\n", infof("val=%d", 0)); +#ifndef NDEBUG #define CONFIG_FROBNICATE_DEBUG 1 should_print("debug: FROBNICATE: val=-2\n", debugf("val=%d", -2)); @@ -57,5 +65,6 @@ int main() { #define CONFIG_FROBNICATE_DEBUG 0 should_print(NULL, debugf("val=%d", -2)); +#endif return 0; } diff --git a/libmisc/tests/test_macro.c b/libmisc/tests/test_macro.c new file mode 100644 index 0000000..1320eb3 --- /dev/null +++ b/libmisc/tests/test_macro.c @@ -0,0 +1,54 @@ +/* libmisc/tests/test_macro.c - Tests for <libmisc/macro.h> + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/macro.h> + +#include "test.h" + +int main() { + printf("== LM_NEXT_POWER_OF_2 =====================================\n"); + /* valid down to 0. */ + test_assert(LM_NEXT_POWER_OF_2(0) == 1); + test_assert(LM_NEXT_POWER_OF_2(1) == 2); + test_assert(LM_NEXT_POWER_OF_2(2) == 4); + test_assert(LM_NEXT_POWER_OF_2(3) == 4); + test_assert(LM_NEXT_POWER_OF_2(4) == 8); + test_assert(LM_NEXT_POWER_OF_2(5) == 8); + test_assert(LM_NEXT_POWER_OF_2(6) == 8); + test_assert(LM_NEXT_POWER_OF_2(7) == 8); + test_assert(LM_NEXT_POWER_OF_2(8) == 16); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(16) == 32); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(0x7000000000000000) == 0x8000000000000000); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(0x8000000000000000-1) == 0x8000000000000000); + /* Valid up to 0x8000000000000000-1 = (1<<63)-1 */ + + printf("== LM_FLOORLOG2 ===========================================\n"); + /* valid down to 1. */ + test_assert(LM_FLOORLOG2(1) == 0); + test_assert(LM_FLOORLOG2(2) == 1); + test_assert(LM_FLOORLOG2(3) == 1); + test_assert(LM_FLOORLOG2(4) == 2); + test_assert(LM_FLOORLOG2(5) == 2); + test_assert(LM_FLOORLOG2(6) == 2); + test_assert(LM_FLOORLOG2(7) == 2); + test_assert(LM_FLOORLOG2(8) == 3); + /* ... */ + test_assert(LM_FLOORLOG2(16) == 4); + /* ... */ + test_assert(LM_FLOORLOG2(0x80000000) == 31); + /* ... */ + test_assert(LM_FLOORLOG2(0xFFFFFFFF) == 31); + test_assert(LM_FLOORLOG2(0x100000000) == 32); + /* ... */ + test_assert(LM_FLOORLOG2(0x8000000000000000) == 63); + /* ... */ + test_assert(LM_FLOORLOG2(0xFFFFFFFFFFFFFFFF) == 63); + + return 0; +} diff --git a/libmisc/tests/test_map.c b/libmisc/tests/test_map.c new file mode 100644 index 0000000..855dace --- /dev/null +++ b/libmisc/tests/test_map.c @@ -0,0 +1,60 @@ +/* libmisc/tests/test_map.c - Tests for <libmisc/map.h> + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/map.h> + +#include "test.h" + +MAP_DECLARE(intmap, int, int); + +int main() { + struct intmap m = {}; + test_assert(map_len(&m) == 0); + + int *v = map_store(&m, 3, 8); + test_assert(v && *v == 8); + test_assert(map_len(&m) == 1); + + v = map_load(&m, 3); + test_assert(v); + test_assert(*v == 8); + + v = NULL; + + test_assert(map_del(&m, 3)); + test_assert(map_len(&m) == 0); + test_assert(!map_del(&m, 3)); + + map_store(&m, 1, 11); + map_store(&m, 2, 12); + map_store(&m, 3, 13); + test_assert(map_len(&m) == 3); + bool seen_1 = false, seen_2 = false, seen_3 = false; + MAP_FOREACH(&m, ik, iv) { + switch (ik) { + case 1: seen_1 = true; break; + case 2: seen_2 = true; break; + case 3: seen_3 = true; break; + } + switch (ik) { + case 1: case 2: case 3: + map_store(&m, ik+20, (*iv)+20); + test_assert(map_del(&m, ik)); + test_assert(!map_del(&m, ik)); + test_assert(map_load(&m, ik) == NULL); + break; + } + } + test_assert(map_len(&m) == 3); + test_assert(seen_1); v = map_load(&m, 21); test_assert(v && *v == 31); v = map_load(&m, 1); test_assert(!v); + test_assert(seen_2); v = map_load(&m, 22); test_assert(v && *v == 32); v = map_load(&m, 2); test_assert(!v); + test_assert(seen_3); v = map_load(&m, 23); test_assert(v && *v == 33); v = map_load(&m, 3); test_assert(!v); + + map_free(&m); + test_assert(map_len(&m) == 0); + + return 0; +} diff --git a/libmisc/tests/test_private.c b/libmisc/tests/test_private.c index 7aaf1ee..024dddb 100644 --- a/libmisc/tests/test_private.c +++ b/libmisc/tests/test_private.c @@ -1,6 +1,6 @@ /* libmisc/tests/test_private.c - Tests for <libmisc/private.h> * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -8,18 +8,18 @@ struct a { int foo; - BEGIN_PRIVATE(A) + BEGIN_PRIVATE(A); int bar; - END_PRIVATE(A) + END_PRIVATE(A); }; #define IMPLEMENTATION_FOR_B YES struct b { int foo; - BEGIN_PRIVATE(B) + BEGIN_PRIVATE(B); int bar; - END_PRIVATE(B) + END_PRIVATE(B); }; int main() { diff --git a/libmisc/tests/test_rand.c b/libmisc/tests/test_rand.c index fff1b27..8076155 100644 --- a/libmisc/tests/test_rand.c +++ b/libmisc/tests/test_rand.c @@ -8,26 +8,18 @@ #include <setjmp.h> #include <libmisc/rand.h> +#include <libmisc/_intercept.h> #include "test.h" /* Intercept failures *********************************************************/ +#ifndef NDEBUG jmp_buf *__catch; -void __assert_msg_fail(const char *expr, - const char *file, unsigned int line, const char *func, - const char *msg) { - static bool in_fail = false; +void __lm_abort(void) { if (__catch) longjmp(*__catch, 1); - if (!in_fail) { - in_fail = true; - printf("error: %s:%u:%s(): assertion \"%s\" failed%s%s\n", - file, line, func, - expr, - msg ? ": " : "", msg); - } abort(); } @@ -43,6 +35,7 @@ void __assert_msg_fail(const char *expr, __catch = old_catch; \ } \ } while (0); +#endif /* Actual tests ***************************************************************/ @@ -51,20 +44,24 @@ void __assert_msg_fail(const char *expr, static void test_n(uint64_t cnt) { if (cnt == 0 || cnt > UINT64_C(1)<<63) { +#ifndef NDEBUG should_abort(rand_uint63n(cnt)); +#else + return; +#endif } else { double sum = 0; bool seen[MAX_SEE_ALL] = {0}; for (int i = 0; i < ROUNDS; i++) { uint64_t val = rand_uint63n(cnt); - sum += ((double)val)/(cnt-1); + sum += val; test_assert(val < cnt); if (cnt < MAX_SEE_ALL) seen[val] = true; } if (cnt > 1) { - test_assert(sum/ROUNDS > 0.45); - test_assert(sum/ROUNDS < 0.55); + test_assert(sum/ROUNDS > 0.45*(cnt-1)); + test_assert(sum/ROUNDS < 0.55*(cnt-1)); } if (cnt < MAX_SEE_ALL) { for (uint64_t i = 0; i < cnt; i++) diff --git a/libmisc/tests/test_vcall.c b/libmisc/tests/test_vcall.c deleted file mode 100644 index f36fc4b..0000000 --- a/libmisc/tests/test_vcall.c +++ /dev/null @@ -1,74 +0,0 @@ -/* libmisc/tests/test_vcall.c - Tests for <libmisc/vcall.h> - * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include <libmisc/assert.h> -#include <libmisc/vcall.h> - -#include "test.h" - -/******************************************************************************/ - -struct frobber_vtable; - -typedef struct { - struct frobber_vtable *vtable; -} implements_frobber; - -struct frobber_vtable { - int (*frob)(implements_frobber *); - int (*frob1)(implements_frobber *, int); - void (*frob0)(implements_frobber *); -}; - -/******************************************************************************/ - -struct myclass { - int a; - implements_frobber; -}; -static_assert(offsetof(struct myclass, implements_frobber) != 0); - -static int myclass_frob(implements_frobber *_self) { - struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self); - test_assert(self); - test_assert((void*)self != (void*)_self); - return self->a; -} - -static int myclass_frob1(implements_frobber *_self, int arg) { - struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self); - test_assert(self); - test_assert((void*)self != (void*)_self); - return arg; -} - -static void myclass_frob0(implements_frobber *_self) { - struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self); - test_assert(self); - test_assert((void*)self != (void*)_self); -} - -struct frobber_vtable myclass_vtable = { - .frob = myclass_frob, - .frob1 = myclass_frob1, - .frob0 = myclass_frob0, -}; - -/******************************************************************************/ - -#define MAGIC1 909837 -#define MAGIC2 657441 - -int main() { - struct myclass obj = { - .implements_frobber = { .vtable = &myclass_vtable }, - .a = MAGIC1, - }; - test_assert(VCALL(&obj, frob) == MAGIC1); - test_assert(VCALL(&obj, frob1, MAGIC2) == MAGIC2); - VCALL(&obj, frob0); - return 0; -} |