diff options
| author | peter <peter@pmikkelsen.com> | 2026-09-05 07:22:31 +0000 |
|---|---|---|
| committer | peter <peter@pmikkelsen.com> | 2026-09-05 07:22:31 +0000 |
| commit | 58beb0bc9236234a697a3619c5023100a9574a59 (patch) | |
| tree | 09078526487e37b000fcfc5305e1967cece90050 | |
| parent | 91ddaf36c86658b852f31dbaa7c1e96a980315c4 (diff) | |
Full coverage of bin/main.c
FossilOrigin-Name: 91deb642cded69b6c480471147004489a6072ec7c6603286aa6c0ebfc75bf030
| -rw-r--r-- | CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/bin/aplwc_repl.h | 2 | ||||
| -rw-r--r-- | src/bin/main.c | 56 | ||||
| -rw-r--r-- | src/bin/util.c | 8 | ||||
| -rw-r--r-- | src/include/aplwc.h | 5 | ||||
| -rw-r--r-- | src/include/aplwc_macros.h | 2 | ||||
| -rw-r--r-- | src/lib/main.c | 13 | ||||
| -rw-r--r-- | src/lib/memory.c | 6 | ||||
| -rw-r--r-- | src/lib/syntax.c | 4 | ||||
| -rwxr-xr-x | tests/scripts/bad/2.sh | 2 | ||||
| -rwxr-xr-x | tests/scripts/bad/3.sh | 2 | ||||
| -rwxr-xr-x | tests/scripts/bad/4.aplwc | 1 | ||||
| -rwxr-xr-x | tests/scripts/bad/4.sh | 3 | ||||
| -rwxr-xr-x | tests/scripts/bad/5.sh | 3 | ||||
| -rwxr-xr-x | tests/scripts/bad/6.sh | 4 | ||||
| -rwxr-xr-x | tests/scripts/bad/7.sh | 4 | ||||
| -rwxr-xr-x | tests/scripts/memfail.sh | 16 | ||||
| -rwxr-xr-x | tests/scripts/simfail.sh | 16 |
18 files changed, 82 insertions, 73 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3466f60..3e2c034 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,8 +112,8 @@ foreach(script ${TEST_SCRIPTS_GOOD}) ENVIRONMENT "PATH=$<TARGET_FILE_DIR:aplwc-repl>" ) - add_test(NAME "memfail ${script}" COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts/memfail.sh" "${script}") - set_tests_properties("memfail ${script}" PROPERTIES + add_test(NAME "simfail ${script}" COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts/simfail.sh" "${script}") + set_tests_properties("simfail ${script}" PROPERTIES ENVIRONMENT "PATH=$<TARGET_FILE_DIR:aplwc-repl>" ) endforeach() @@ -133,8 +133,8 @@ foreach(script ${TEST_SCRIPTS_GOOD}) set_tests_properties("${script}" PROPERTIES ENVIRONMENT "PATH=$<TARGET_FILE_DIR:aplwc-repl>" ) - add_test(NAME "memfail ${script}" COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts/memfail.sh" "${script}") - set_tests_properties("memfail ${script}" PROPERTIES + add_test(NAME "simfail ${script}" COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/scripts/simfail.sh" "${script}") + set_tests_properties("simfail ${script}" PROPERTIES ENVIRONMENT "PATH=$<TARGET_FILE_DIR:aplwc-repl>" ) endforeach() diff --git a/src/bin/aplwc_repl.h b/src/bin/aplwc_repl.h index 4e594bc..6fb4415 100644 --- a/src/bin/aplwc_repl.h +++ b/src/bin/aplwc_repl.h @@ -31,6 +31,6 @@ #include <aplwc_macros.h> /* util.c */ -long getenv_long(const char *, long); +unsigned long getenv_ulong(const char *, unsigned long); #endif /* APLWC_REPL_H */ diff --git a/src/bin/main.c b/src/bin/main.c index 36dd424..d0328f0 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -23,32 +23,12 @@ #include <errno.h> #include "aplwc_repl.h" -static uint64_t alloc_count; -static long memdbg; - -static int -hook_alloc(void) -{ - alloc_count++; - if((memdbg >= 0) && (alloc_count > ((uint64_t)memdbg))) - return 0; - else - return 1; -} - -static void * -my_malloc(size_t size) -{ - if(!hook_alloc()) - return NULL; - return malloc(size); -} - static void * my_alloc(size_t size, size_t *actual) { size_t target = size; void *p; + int fail2; if(actual){ if(NEVER(target == 0)) @@ -65,10 +45,12 @@ my_alloc(size_t size, size_t *actual) } } - p = my_malloc(target); + fail2 = aplwc_simulate_failure(); + + p = FAILCASE(malloc(target), NULL); if((p == NULL) && (size < target)){ target = size; - p = my_malloc(target); + p = FAILCASE_X(malloc(target), NULL, fail2); } if(actual) @@ -95,6 +77,7 @@ main(int argc, char *argv[]) size_t input_size, src_size, i; int opt, xflag, input_file; long tmp; + unsigned long print_failsims; FILE *f; aplwc_clear_line(&line); @@ -106,12 +89,12 @@ main(int argc, char *argv[]) line_number = 0; aplwc = NULL; - memdbg = getenv_long("APLWC_ALLOC_FAIL_AFTER", -2); + aplwc_simulate_failure_at = getenv_ulong("APLWC_SIMULATE_FAILURE_AT", 0); + print_failsims = getenv_ulong("APLWC_SIMULATE_FAILURE_PRINT_COUNT", 0); memset(&fns, 0, sizeof(fns)); fns.alloc = my_alloc; fns.dealloc = my_dealloc; - fns.hook_alloc = hook_alloc; while((opt = getopt(argc, argv, "x")) != -1){ switch(opt){ @@ -147,24 +130,24 @@ usage: } if(input_file){ - if(fseek(f, 0, SEEK_END)){ + if(FAILCASE(fseek(f, 0, SEEK_END), -1)){ file_size: fprintf(stderr, "Failed to determine file size\n"); exit_code = 1; goto end; } - tmp = ftell(f); + tmp = FAILCASE(ftell(f), -1); if(tmp < 0) goto file_size; input_size = tmp; rewind(f); - input = malloc(input_size); + input = FAILCASE(malloc(input_size), NULL); if(input == NULL){ fprintf(stderr, "Failed to allocate space for file contents\n"); exit_code = 1; goto end; } - if(fread(input, 1, input_size, f) < input_size){ + if(FAILCASE(fread(input, 1, input_size, f), 0) < input_size){ fprintf(stderr, "Failed to read file contents\n"); exit_code = 1; goto end; @@ -215,12 +198,7 @@ file_size: aplwc_read(aplwc, input, &line); if(!aplwc_valid_line(&line)){ line_error: - ret = aplwc_last_error(aplwc); fprintf(stderr, "error on line %d: %s: %s\n", line_number, aplwc_errstr(aplwc), input); - if(input_file){ - exit_code = 1; - goto end; - } continue; } aplwc_eval(&line, &value); @@ -233,25 +211,25 @@ line_error: end: if(input) free(input); - if(aplwc_valid_line(&line)) + if(NEVER(aplwc_valid_line(&line))) aplwc_free_line(&line); - if(aplwc_valid_value(&value)) + if(NEVER(aplwc_valid_value(&value))) aplwc_free_value(&value); if(aplwc) aplwc_destroy(aplwc); - if(memdbg == -1){ + if(print_failsims){ f = fdopen(3, "w"); if(f == NULL){ fprintf(stderr, "Failed to open fd 3\n"); exit_code = 1; }else{ - fprintf(f, "%ld\n", alloc_count); + fprintf(f, "%ld\n", aplwc_simulate_failure_count); fclose(f); } } - if((exit_code != 0) && (memdbg >= 0) && (ret == APLWC_OUT_OF_MEMORY)) + if((exit_code != 0) && aplwc_simulate_failure_at && (aplwc_simulate_failure_count >= aplwc_simulate_failure_at)) exit_code = 0; return exit_code; diff --git a/src/bin/util.c b/src/bin/util.c index 40892b0..b887447 100644 --- a/src/bin/util.c +++ b/src/bin/util.c @@ -19,16 +19,16 @@ #include "aplwc_repl.h" -long -getenv_long(const char *name, long def) +unsigned long +getenv_ulong(const char *name, unsigned long def) { - long ret, parsed; + unsigned long ret, parsed; char *env, *p; ret = def; env = getenv(name); if((env != NULL) && (strlen(env) > 0)){ - parsed = strtol(env, &p, 10); + parsed = strtoul(env, &p, 10); if((*p) == 0) ret = parsed; } diff --git a/src/include/aplwc.h b/src/include/aplwc.h index 459a036..5a6cb79 100644 --- a/src/include/aplwc.h +++ b/src/include/aplwc.h @@ -47,9 +47,11 @@ typedef struct { struct aplwc_ref ref; } AplwcValue; struct aplwc_fns { void *(*alloc)(size_t, size_t *); void (*dealloc)(void *); - int (*hook_alloc)(void); }; +extern uint64_t aplwc_simulate_failure_at; +extern uint64_t aplwc_simulate_failure_count; + struct aplwc *aplwc_new(struct aplwc_fns, enum aplwc_rc *); void aplwc_destroy(struct aplwc *); void aplwc_clear_line(AplwcLine *); @@ -65,5 +67,6 @@ void aplwc_eval(AplwcLine *, AplwcValue *); void aplwc_free_value(AplwcValue *); const char *aplwc_value_string(AplwcValue *); enum aplwc_rc aplwc_load_module(struct aplwc *, const char *, const char *, int n); +int aplwc_simulate_failure(void); #endif /* APLWC_H */ diff --git a/src/include/aplwc_macros.h b/src/include/aplwc_macros.h index f68fea9..80ada28 100644 --- a/src/include/aplwc_macros.h +++ b/src/include/aplwc_macros.h @@ -38,5 +38,7 @@ #define DEBUG(x) ((void)0) #endif +#define FAILCASE(x, fail) (aplwc_simulate_failure() ? (fail) : (x)) +#define FAILCASE_X(x, fail, test) ((test) ? (fail) : (x)) #endif /* APLWC_MACROS_H */ diff --git a/src/lib/main.c b/src/lib/main.c index 161fdde..bba93d3 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -228,3 +228,16 @@ aplwc_valid_line(AplwcLine *l) { return valid_ref(&l->ref); } + +uint64_t aplwc_simulate_failure_at; +uint64_t aplwc_simulate_failure_count; + +int +aplwc_simulate_failure(void) +{ + aplwc_simulate_failure_count++; + if(aplwc_simulate_failure_at && (aplwc_simulate_failure_count >= aplwc_simulate_failure_at)) + return 1; + else + return 0; +} diff --git a/src/lib/memory.c b/src/lib/memory.c index 8dbb5f2..03f2056 100644 --- a/src/lib/memory.c +++ b/src/lib/memory.c @@ -379,13 +379,10 @@ alloc(struct aplwc *aplwc, size_t size, enum chunk_tag tag) if(pad) size += ALIGNMENT - pad; - if(aplwc->fns.hook_alloc && !aplwc->fns.hook_alloc()) - goto fail; - attempt = 0; retry: DEBUG(check_mem(aplwc)); - free = find_free(aplwc, size); + free = FAILCASE(find_free(aplwc, size), NULL); if(!free){ switch(attempt++){ case 0: @@ -399,7 +396,6 @@ retry: goto retry; /* fall-through */ default: -fail: aplwc->last_error = APLWC_OUT_OF_MEMORY; return NULL; } diff --git a/src/lib/syntax.c b/src/lib/syntax.c index 6e08d1b..23138ed 100644 --- a/src/lib/syntax.c +++ b/src/lib/syntax.c @@ -286,8 +286,10 @@ scan_string(struct aplwc *aplwc, struct string *text, int oneline) goto end; tokens = memory_alloc_token_list(aplwc, n); - if(tokens == NULL) + if(tokens == NULL){ + rc = aplwc->last_error; goto end; + } tokens->text = text; tokens->length = n; scan(text, tokens); diff --git a/tests/scripts/bad/2.sh b/tests/scripts/bad/2.sh index 03db180..73321be 100755 --- a/tests/scripts/bad/2.sh +++ b/tests/scripts/bad/2.sh @@ -1,3 +1,3 @@ #!/bin/sh -aplwc-repl -? +aplwc-repl -x -? diff --git a/tests/scripts/bad/3.sh b/tests/scripts/bad/3.sh index 55b2735..ff0e033 100755 --- a/tests/scripts/bad/3.sh +++ b/tests/scripts/bad/3.sh @@ -1,3 +1,3 @@ #!/bin/sh -aplwc-repl some-file-which-does-not-exist +aplwc-repl -x some-file-which-does-not-exist diff --git a/tests/scripts/bad/4.aplwc b/tests/scripts/bad/4.aplwc new file mode 100755 index 0000000..af9da70 --- /dev/null +++ b/tests/scripts/bad/4.aplwc @@ -0,0 +1 @@ +#!/usr/bin/env aplwc-repl
\ No newline at end of file diff --git a/tests/scripts/bad/4.sh b/tests/scripts/bad/4.sh new file mode 100755 index 0000000..0c48eaf --- /dev/null +++ b/tests/scripts/bad/4.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +aplwc-repl -x f1 f2 diff --git a/tests/scripts/bad/5.sh b/tests/scripts/bad/5.sh new file mode 100755 index 0000000..8411e21 --- /dev/null +++ b/tests/scripts/bad/5.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +aplwc-repl -x /dev/stdin diff --git a/tests/scripts/bad/6.sh b/tests/scripts/bad/6.sh new file mode 100755 index 0000000..2d9a94c --- /dev/null +++ b/tests/scripts/bad/6.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +export APLWC_SIMULATE_FAILURE_PRINT_COUNT=1 +aplwc-repl -x 3>&- diff --git a/tests/scripts/bad/7.sh b/tests/scripts/bad/7.sh new file mode 100755 index 0000000..189a5f0 --- /dev/null +++ b/tests/scripts/bad/7.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +export APLWC_SIMULATE_FAILURE_AT=100 +aplwc-repl -x /dev/stdin diff --git a/tests/scripts/memfail.sh b/tests/scripts/memfail.sh deleted file mode 100755 index c0076d1..0000000 --- a/tests/scripts/memfail.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -set -e - -export APLWC_ALLOC_FAIL_AFTER=-1 -N=$($1 3>&1 1>/dev/null 2>/dev/null) -n=0 - -while [ "$n" -le "$N" ] -do - echo $n out of $N - export APLWC_ALLOC_FAIL_AFTER=$n - $1 1>/dev/null 2>/dev/null - - n=$((n + 1)) -done diff --git a/tests/scripts/simfail.sh b/tests/scripts/simfail.sh new file mode 100755 index 0000000..fe64a25 --- /dev/null +++ b/tests/scripts/simfail.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +export APLWC_SIMULATE_FAILURE_PRINT_COUNT=1 +N=$($1 3>&1 1>/dev/null 2>/dev/null) +n=1 +export APLWC_SIMULATE_FAILURE_PRINT_COUNT=0 + +while [ "$n" -le "$N" ] +do + echo $n out of $N + export APLWC_SIMULATE_FAILURE_AT=$n + $1 #1>/dev/null 2>/dev/null + n=$((n + 1)) +done |