diff options
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | compat/compat.h | 1 | ||||
| -rw-r--r-- | include/moslib/ds/hashmap.h | 15 | ||||
| -rw-r--r-- | include/moslib/safe.h | 7 | ||||
| -rw-r--r-- | src/ds/array.c | 2 | ||||
| -rw-r--r-- | src/ds/hashmap.c | 6 | ||||
| -rw-r--r-- | src/safe.c | 16 | ||||
| -rw-r--r-- | src/string.c | 4 | ||||
| -rw-r--r-- | src/tester.c | 56 | ||||
| -rw-r--r-- | tests/ds/hashmap_tests.c | 4 |
10 files changed, 77 insertions, 42 deletions
@@ -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; @@ -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); |
