aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <git@mosder.eu>2026-09-17 12:37:01 +0200
committerMosder <git@mosder.eu>2026-09-17 12:37:11 +0200
commitde163fe7ee64e63d36dd581db16c776831cbead0 (patch)
tree57f9861bd63a5479c8ee1d829a00d3b4ab053bba
parent33e2e9d8aff7ee16aa5c071df93d6f9c0a37e53f (diff)
feat: improved compatibility - removed possible duplicate names, exit tests now create a fork instead of relying on being able to overwrite exit function, made tester only output ASCII escape sequences for colour into a tty
-rw-r--r--Makefile8
-rw-r--r--compat/compat.h1
-rw-r--r--include/moslib/ds/hashmap.h15
-rw-r--r--include/moslib/safe.h7
-rw-r--r--src/ds/array.c2
-rw-r--r--src/ds/hashmap.c6
-rw-r--r--src/safe.c16
-rw-r--r--src/string.c4
-rw-r--r--src/tester.c56
-rw-r--r--tests/ds/hashmap_tests.c4
10 files changed, 77 insertions, 42 deletions
diff --git a/Makefile b/Makefile
index 0739c71..d47cade 100644
--- a/Makefile
+++ b/Makefile
@@ -22,14 +22,14 @@ TESTS_LDFLAGS=-L$(LIB_DIR) -Wl,-rpath,$(LIB_DIR) -lmoslib
TESTS_SRCS:=$(shell find tests compat | grep "\.c$$")
define probe_fun
- $(shell printf '#define $(1)\n#include <$(2)>\nint main(void){$(3);}' \
+ $(shell printf '#include "compat.h"\n#include <$(1)>\nint main(void){$(2);return 0;}' \
| $(CC) $(CFLAGS) -x c - -o /dev/null 2>/dev/null \
- || echo -DNO_$(shell echo $(3) | tr a-z A-Z))
+ || echo -DNO_$(shell echo $(2) | tr a-z A-Z))
endef
PROBED:= \
- $(call probe_fun,_GNU_SOURCE,string.h,memmem) \
- $(call probe_fun,_XOPEN_SOURCE 500,string.h,strdup)
+ $(call probe_fun,string.h,memmem) \
+ $(call probe_fun,string.h,strdup)
CFLAGS+=$(PROBED)
TESTS_CFLAGS+=$(PROBED)
diff --git a/compat/compat.h b/compat/compat.h
index b36b17f..3e46993 100644
--- a/compat/compat.h
+++ b/compat/compat.h
@@ -4,7 +4,6 @@
#ifndef MOSLIB_COMPAT_H
#define MOSLIB_COMPAT_H
-#define _XOPEN_SOURCE 500
#define _GNU_SOURCE
typedef void declaration;
diff --git a/include/moslib/ds/hashmap.h b/include/moslib/ds/hashmap.h
index 09a27e2..c2a88b9 100644
--- a/include/moslib/ds/hashmap.h
+++ b/include/moslib/ds/hashmap.h
@@ -27,7 +27,7 @@
//
// It accepts these optional arguments:
//
-// .key (enum {DEFAULT, STR, SS}) - use predefined hash and equals functions
+// .key (enum {HM_DEFAULT, HM_STR, HM_SS}) - use predefined hash and equals functions
// for C strings or StringSlice
// .hash (uint32_t (*)(const void *key)) - user defined hash function
// .eq (int (*)(const void *key1, cosnt void *key2)) - user defined equals function
@@ -39,10 +39,10 @@
// Examples:
//
// HM_DEF(str_int, char *, int);
-// str_int *hm1 = hm_new(.key = STR);
+// str_int *hm1 = hm_new(.key = HM_STR);
//
// HM_DEF(ss_float, StringSlice, float);
-// ss_float *hm2 = hm_new(.key = SS);
+// ss_float *hm2 = hm_new(.key = HM_SS);
//
// uint32_t hash_int(const void *key) {
// return (uint32_t)(*(int *)key);
@@ -143,6 +143,9 @@
#ifndef MOS_FORCE_PREFIXES
+#define HM_DEFAULT MOS_HM_DEFAULT
+#define HM_STR MOS_HM_STR
+#define HM_SS MOS_HM_SS
#define HM_DEF MOS_HM_DEF
#define hm_new mos_hm_new
#define hm_put mos_hm_put
@@ -159,7 +162,7 @@
#endif // MOS_FORCE_PREFIXES
typedef struct {
- enum { DEFAULT, STR, SS } key;
+ enum { MOS_HM_DEFAULT, MOS_HM_STR, MOS_HM_SS } key;
uint32_t (*hash)(const void *key);
int (*eq)(const void *key1, const void *key2);
} MosHmNewArgs;
@@ -176,8 +179,8 @@ typedef struct {
// Optional arguments:
// .key
// key specification enum
-// STR - C string hash and equals functions
-// SS - StringSlice hash and equals functions
+// HM_STR - C string hash and equals functions
+// HM_SS - StringSlice hash and equals functions
//
// .hash
// user defined hash function
diff --git a/include/moslib/safe.h b/include/moslib/safe.h
index 18ab5b0..c855cea 100644
--- a/include/moslib/safe.h
+++ b/include/moslib/safe.h
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdio.h>
+#include <unistd.h>
#ifndef MOSLIB_SAFE_H
#define MOSLIB_SAFE_H
@@ -17,6 +18,8 @@
#define safe_tmpfile mos_safe_tmpfile
#define safe_dup mos_safe_dup
#define safe_dup2 mos_safe_dup2
+#define safe_fork mos_safe_fork
+#define safe_pipe mos_safe_pipe
#endif // MOS_FORCE_PREFIXES
@@ -37,6 +40,8 @@ typedef struct {
#define mos_safe_tmpfile() mos_safe_tmpfile_fn(mos_err_info)
#define mos_safe_dup(fd) mos_safe_dup_fn(fd, mos_err_info)
#define mos_safe_dup2(fd, fd2) mos_safe_dup2_fn(fd, fd2, mos_err_info)
+#define mos_safe_fork() mos_safe_fork_fn(mos_err_info)
+#define mos_safe_pipe(fd) mos_safe_pipe_fn(fd, mos_err_info)
// Function prototypes for macros
extern void *mos_safe_malloc_fn(size_t size, MosSafeErrInfo info);
@@ -46,5 +51,7 @@ extern FILE *mos_safe_fopen_fn(const char *path, const char *mode, MosSafeErrInf
extern FILE *mos_safe_tmpfile_fn(MosSafeErrInfo info);
extern int mos_safe_dup_fn(int fd, MosSafeErrInfo info);
extern int mos_safe_dup2_fn(int fd, int fd2, MosSafeErrInfo info);
+extern pid_t mos_safe_fork_fn(MosSafeErrInfo info);
+extern int mos_safe_pipe_fn(int fd[2], MosSafeErrInfo info);
#endif // MOSLIB_SAFE_H
diff --git a/src/ds/array.c b/src/ds/array.c
index 21d8be5..3148944 100644
--- a/src/ds/array.c
+++ b/src/ds/array.c
@@ -158,7 +158,7 @@ size_t mos_arr_set_len_fn(void *p_arr, size_t len, size_t el_size, size_t init_c
size_t del = hdr->len > len ? hdr->len - len : 0;
if (len > hdr->len)
- memset((char *)arr + hdr->len, 0, (len - hdr->len) * el_size);
+ memset((char *)arr + hdr->len * el_size, 0, (len - hdr->len) * el_size);
hdr->len = len;
return del;
diff --git a/src/ds/hashmap.c b/src/ds/hashmap.c
index a983fc2..a08ce70 100644
--- a/src/ds/hashmap.c
+++ b/src/ds/hashmap.c
@@ -117,15 +117,15 @@ void *mos_hm_new_fn(MosHmNewArgs args) {
hdr->n_dead = 0;
switch (args.key) {
- case DEFAULT:
+ case MOS_HM_DEFAULT:
hdr->hash = NULL;
hdr->eq = NULL;
break;
- case STR:
+ case MOS_HM_STR:
hdr->hash = string_hash;
hdr->eq = string_eq;
break;
- case SS:
+ case MOS_HM_SS:
hdr->hash = slice_hash;
hdr->eq = slice_eq;
break;
diff --git a/src/safe.c b/src/safe.c
index 1b75bf2..fd7a1af 100644
--- a/src/safe.c
+++ b/src/safe.c
@@ -72,3 +72,19 @@ int mos_safe_dup2_fn(int fd, int fd2, MosSafeErrInfo info) {
ERR_MESS("failed to dup %d 2 %d", fd, fd2);
exit(EXIT_FAILURE);
}
+
+pid_t mos_safe_fork_fn(MosSafeErrInfo info) {
+ pid_t pid = fork();
+ if (pid != -1)
+ return pid;
+ ERR_MESS("failed to fork");
+ exit(EXIT_FAILURE);
+}
+
+int mos_safe_pipe_fn(int fd[2], MosSafeErrInfo info) {
+ int res = pipe(fd);
+ if (res != -1)
+ return res;
+ ERR_MESS("failed to pipe");
+ exit(EXIT_FAILURE);
+}
diff --git a/src/string.c b/src/string.c
index 6625d8f..606a80c 100644
--- a/src/string.c
+++ b/src/string.c
@@ -45,7 +45,7 @@ MosStringSlice mos_ss_trim(MosStringSlice ss) {
MosStringSlice mos_ss_trim_left(MosStringSlice ss) {
size_t i = 0;
- while (i < ss.len && isspace(ss.data[i])) {
+ while (i < ss.len && isspace((unsigned char)ss.data[i])) {
i++;
}
@@ -56,7 +56,7 @@ MosStringSlice mos_ss_trim_left(MosStringSlice ss) {
MosStringSlice mos_ss_trim_right(MosStringSlice ss) {
size_t i = ss.len;
- while (i-- > 0 && isspace(ss.data[i]))
+ while (i-- > 0 && isspace((unsigned char)ss.data[i]))
;
ss.len = i + 1;
diff --git a/src/tester.c b/src/tester.c
index 20bc340..e789871 100644
--- a/src/tester.c
+++ b/src/tester.c
@@ -1,7 +1,6 @@
#define MOS_FORCE_PREFIXES
#include "moslib/tester.h"
-#include <setjmp.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,7 +35,9 @@ static Outputs suppressed = {
.out_cap = 4,
};
-#define print_color(template, ...) printf("\033[%dm" template "\033[0m", __VA_ARGS__)
+#define print_color(color, ...) \
+ (isatty(STDOUT_FILENO) ? (printf("\033[%dm", color), printf(__VA_ARGS__), printf("\033[0m")) \
+ : printf(__VA_ARGS__))
#define nl printf("\n")
static void print_center(const char *text, int color, char padding_char) {
@@ -46,7 +47,7 @@ static void print_center(const char *text, int color, char padding_char) {
for (size_t i = 1; i < pre_char_count; i++)
printf("%c", padding_char);
- print_color(" %s ", color, text);
+ print_color(color, " %s ", text);
for (size_t i = 1; i < post_char_count; i++)
printf("%c", padding_char);
@@ -101,32 +102,41 @@ MosTestGroup *mos_add_test_group_fn(MosTester *tester, const char *group_name) {
void mos_test_assert(int expression, const char *fail_message) {
if (!expression) {
failed = 1;
- print_color("ASSERT FAILED: ", RED);
+ print_color(RED, "ASSERT FAILED: ");
printf("%s\n", fail_message);
}
}
-static jmp_buf jump_env;
-static int expected_code;
-static const char *fn_name;
-void exit(int code) {
- if (code != expected_code) {
- failed = 1;
- print_color("ASSERT FAILED: ", RED);
- printf("exit code was %d, expected %d (in function %s)\n", code, expected_code, fn_name);
- }
- longjmp(jump_env, 1);
-}
-
void mos_test_assert_exit_fn(MosTestFn function, int code, const char *name) {
- expected_code = code;
- fn_name = name;
- if (setjmp(jump_env) == 0) {
+ int fd[2];
+ mos_safe_pipe(fd);
+ pid_t pid = mos_safe_fork();
+ if (pid == 0) {
function();
+ uint8_t exited = 0;
+ write(fd[1], &exited, sizeof(uint8_t));
+ exit(1);
+ }
+
+ int status;
+ waitpid(pid, &status, 0);
+ int exit_code = status >> 8;
+
+ uint8_t exited = 1;
+ close(fd[1]);
+ read(fd[0], &exited, sizeof(uint8_t));
+ close(fd[0]);
+
+ if (!exited) {
failed = 1;
- print_color("ASSERT FAILED: ", RED);
+ print_color(RED, "ASSERT FAILED: ");
printf("exit was not called (in function %s)\n", name);
}
+ else if (exit_code != code) {
+ failed = 1;
+ print_color(RED, "ASSERT FAILED: ");
+ printf("exit code was %d, expected %d (in function %s)\n", exit_code, code, name);
+ }
}
void mos_test_assert_out_fn(
@@ -152,7 +162,7 @@ void mos_test_assert_out_fn(
if (strcmp(out, output)) {
failed = 1;
- print_color("ASSERT FAILED: ", RED);
+ print_color(RED, "ASSERT FAILED: ");
printf("function %s outputed to %s:\n", fn_name, stream_name);
printf(" %s (capped at %zu chars)\n", out, n + 1);
printf(" expected: %s\n", output);
@@ -223,11 +233,11 @@ int mos_run_tests(MosTester *tester) {
group->tests[j].test();
if (failed) {
tests_failed += 1;
- print_color("--- FAILED ---\n", RED);
+ print_color(RED, "--- FAILED ---\n");
}
else {
tests_passed += 1;
- print_color("--- PASSED ---\n", GREEN);
+ print_color(GREEN, "--- PASSED ---\n");
}
}
diff --git a/tests/ds/hashmap_tests.c b/tests/ds/hashmap_tests.c
index 822ee2a..72965b4 100644
--- a/tests/ds/hashmap_tests.c
+++ b/tests/ds/hashmap_tests.c
@@ -96,7 +96,7 @@ TEST(deleting) {
TEST(str_key) {
HM_DEF(E, char *, int);
- E *hm = hm_new(.key = STR);
+ E *hm = hm_new(.key = HM_STR);
char *str = "key";
char *str2 = strdup(str);
@@ -114,7 +114,7 @@ TEST(str_key) {
TEST(ss_key) {
HM_DEF(E, StringSlice, int);
- E *hm = hm_new(.key = SS);
+ E *hm = hm_new(.key = HM_SS);
char *str = "key";
char *str2 = strdup(str);