summaryrefslogtreecommitdiff
path: root/libmisc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'libmisc/tests')
-rw-r--r--libmisc/tests/test_assert.c36
-rw-r--r--libmisc/tests/test_assert_min.c17
-rw-r--r--libmisc/tests/test_endian.c39
-rw-r--r--libmisc/tests/test_log.c49
-rw-r--r--libmisc/tests/test_macro.c54
-rw-r--r--libmisc/tests/test_map.c60
-rw-r--r--libmisc/tests/test_private.c10
-rw-r--r--libmisc/tests/test_rand.c25
-rw-r--r--libmisc/tests/test_vcall.c74
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;
-}