summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-08-20 20:54:43 +0000
committerpeter <peter@pmikkelsen.com>2026-08-20 20:54:43 +0000
commit86feda786f115cb4468957f00b8968b986ed7c54 (patch)
tree31228cf73674178764cd6376d483e76212181707
parentf5d445afa10ed7ba03b0ea9a5274f11904220700 (diff)
Get full coverage of aplwc-repl.
This required wrapping malloc so that it can fail under our control. FossilOrigin-Name: a27ccb5f02994393a518419bae15fd26ff0016c734d96350ae2137a1d3c0937c
-rw-r--r--CMakeLists.txt32
-rw-r--r--src/bin/aplwc_repl.h23
-rw-r--r--src/bin/main.c19
-rw-r--r--src/bin/util.c17
-rw-r--r--src/bin/wrappers.c40
-rw-r--r--src/include/aplwc.h2
-rw-r--r--src/include/aplwc_macros.h20
-rw-r--r--src/lib/aplwc_internal.h16
-rw-r--r--src/lib/main.c4
-rw-r--r--tests/aplwc_errstr.c4
-rw-r--r--tests/aplwc_new.c4
-rwxr-xr-xtools/checkcov6
12 files changed, 149 insertions, 38 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0e8af0..18aaeb1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,6 +54,8 @@ target_link_libraries(aplwc PRIVATE common)
add_executable(aplwc-repl
src/bin/main.c
+ src/bin/util.c
+ src/bin/wrappers.c
)
target_link_libraries(aplwc-repl PRIVATE common aplwc)
@@ -67,4 +69,34 @@ foreach(source ${TEST_SOURCES})
add_test(NAME "${name}" COMMAND "${test_bin}")
endforeach()
+add_test(NAME "aplwc-repl-tiny" COMMAND "aplwc-repl")
+set_tests_properties("aplwc-repl-tiny" PROPERTIES
+ ENVIRONMENT "APLWC_MEM=16"
+ WILL_FAIL TRUE
+)
+
+add_test(NAME "aplwc-repl-emptyvar" COMMAND "aplwc-repl")
+set_tests_properties("aplwc-repl-emptyvar" PROPERTIES
+ ENVIRONMENT "APLWC_MEM="
+)
+
+add_test(NAME "aplwc-repl-badvar" COMMAND "aplwc-repl")
+set_tests_properties("aplwc-repl-badvar" PROPERTIES
+ ENVIRONMENT "APLWC_MEM=1M"
+)
+
add_test(NAME "aplwc-repl" COMMAND "aplwc-repl")
+
+set(REQUIRED_MALLOCS 1)
+foreach(i RANGE 0 ${REQUIRED_MALLOCS})
+ set(name "aplwc-repl-${i}-${REQUIRED_MALLOCS}")
+ add_test(NAME "${name}" COMMAND "aplwc-repl")
+ set_tests_properties("${name}" PROPERTIES
+ ENVIRONMENT "APLWC_MALLOC_FAIL_AFTER=${i}"
+ )
+ if(NOT i EQUAL ${REQUIRED_MALLOCS} AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
+ set_tests_properties("${name}" PROPERTIES
+ WILL_FAIL TRUE
+ )
+ endif()
+endforeach()
diff --git a/src/bin/aplwc_repl.h b/src/bin/aplwc_repl.h
new file mode 100644
index 0000000..c189b77
--- /dev/null
+++ b/src/bin/aplwc_repl.h
@@ -0,0 +1,23 @@
+#ifndef APLWC_REPL_H
+#define APLWC_REPL_H
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <aplwc.h>
+#include <aplwc_macros.h>
+
+/* util.c */
+unsigned long getenv_ulong(const char *, unsigned long);
+
+/* wrappers.c */
+void *wrapped_malloc(size_t);
+void wrapped_free(void *);
+#define malloc(size) wrapped_malloc(size)
+#define free(ptr) wrapped_free(ptr)
+
+#endif /* APLWC_REPL_H */
diff --git a/src/bin/main.c b/src/bin/main.c
index 2538248..80b2ee0 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -1,6 +1,5 @@
#include <stdio.h>
-#include <stdlib.h>
-#include <aplwc.h>
+#include "aplwc_repl.h"
int
main(void)
@@ -8,24 +7,24 @@ main(void)
struct aplwc *aplwc;
uint8_t *data;
int ret;
+ size_t memsize;
- data = malloc(APLWC_MIN_MEM);
+ memsize = getenv_ulong("APLWC_MEM", APLWC_MIN_MEM);
+
+ data = malloc(memsize);
if(data == NULL){
fprintf(stderr, "Couldn't allocate memory\n");
return 1;
}
- ret = aplwc_new(&aplwc, data, APLWC_MIN_MEM);
+ ret = aplwc_new(&aplwc, data, memsize);
if(ret){
- fprintf(stderr, "Couldn't create new aplwc instance: %s\n", aplwc_errstr(aplwc));
+ fprintf(stderr, "Couldn't create new aplwc instance: %s\n", aplwc_errstr_rc(ret));
+ free(data);
return 1;
}
- ret = aplwc_destroy(aplwc);
- if(ret){
- fprintf(stderr, "Couldn't destroy the aplwc instance: %s\n", aplwc_errstr(aplwc));
- return 1;
- }
+ aplwc_destroy(aplwc);
free(data);
diff --git a/src/bin/util.c b/src/bin/util.c
new file mode 100644
index 0000000..c8218fd
--- /dev/null
+++ b/src/bin/util.c
@@ -0,0 +1,17 @@
+#include "aplwc_repl.h"
+
+unsigned long
+getenv_ulong(const char *name, unsigned long def)
+{
+ unsigned long ret, parsed;
+ char *env, *p;
+
+ ret = def;
+ env = getenv(name);
+ if((env != NULL) && (strlen(env) > 0)){
+ parsed = strtoul(env, &p, 10);
+ if((*p) == 0)
+ ret = parsed;
+ }
+ return ret;
+}
diff --git a/src/bin/wrappers.c b/src/bin/wrappers.c
new file mode 100644
index 0000000..18e179a
--- /dev/null
+++ b/src/bin/wrappers.c
@@ -0,0 +1,40 @@
+#include "aplwc_repl.h"
+
+static uint64_t malloc_count = 0;
+
+static uint64_t
+malloc_fail_after(void)
+{
+#if APLWC_BUILD_TYPE_RELEASE
+ return UINT64_MAX;
+#else
+ static int setup;
+ static uint64_t count, count_rec;
+
+ if(!setup){
+ setup = 1;
+ count = getenv_ulong("APLWC_MALLOC_FAIL_AFTER", ULONG_MAX);
+ count_rec = malloc_fail_after();
+ assert(ALWAYS(count == count_rec));
+ }
+
+ return count;
+#endif
+}
+
+#undef malloc
+void *
+wrapped_malloc(size_t size)
+{
+ if(malloc_count++ >= malloc_fail_after())
+ return NULL;
+ else
+ return malloc(size);
+}
+
+#undef free
+void
+wrapped_free(void *ptr)
+{
+ free(ptr);
+}
diff --git a/src/include/aplwc.h b/src/include/aplwc.h
index 9905411..d4d101c 100644
--- a/src/include/aplwc.h
+++ b/src/include/aplwc.h
@@ -14,7 +14,7 @@ enum aplwc_rc {
struct aplwc;
enum aplwc_rc aplwc_new(struct aplwc **, uint8_t *, size_t);
-enum aplwc_rc aplwc_destroy(struct aplwc *);
+void aplwc_destroy(struct aplwc *);
const char *aplwc_errstr_rc(enum aplwc_rc);
const char *aplwc_errstr(struct aplwc *);
diff --git a/src/include/aplwc_macros.h b/src/include/aplwc_macros.h
new file mode 100644
index 0000000..cf05803
--- /dev/null
+++ b/src/include/aplwc_macros.h
@@ -0,0 +1,20 @@
+#ifndef APLWC_MACROS_H
+#define APLWC_MACROS_H
+
+#define UNUSED_PARAMETER(arg) ((void)arg)
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+#if APLWC_BUILD_TYPE_DEBUG
+ #define ALWAYS(x) ((x) ? 1 : (assert(0), 0))
+ #define NEVER(x) ((x) ? (assert(0), 1) : 0)
+#elif APLWC_BUILD_TYPE_RELEASE
+ #define ALWAYS(x) (X)
+ #define NEVER(X) (X)
+#elif APLWC_BUILD_TYPE_COVERAGE
+ #define ALWAYS(x) (1)
+ #define NEVER(x) (0)
+#endif
+
+
+#endif /* APLWC_MACROS_H */
diff --git a/src/lib/aplwc_internal.h b/src/lib/aplwc_internal.h
index 97a89ba..52ecd2e 100644
--- a/src/lib/aplwc_internal.h
+++ b/src/lib/aplwc_internal.h
@@ -2,26 +2,12 @@
#define APLWC_INTERNAL_H
#include <aplwc.h>
-
-#define UNUSED_PARAMETER(arg) ((void)arg)
+#include <aplwc_macros.h>
#define RETURN_ERROR(aplwcp, rc, msg) do{ \
return ((aplwc)->last_error = (rc)); \
}while(0)
-#define NELEM(x) (sizeof(x)/sizeof(x[0]))
-
-#if APLWC_BUILD_TYPE_DEBUG
- #define ALWAYS(x) ((x) ? 1 : (assert(0), 0))
- #define NEVER(x) ((x) ? (assert(0), 1) : 0)
-#elif APLWC_BUILD_TYPE_RELEASE
- #define ALWAYS(x) (X)
- #define NEVER(X) (X)
-#elif APLWC_BUILD_TYPE_COVERAGE
- #define ALWAYS(x) (1)
- #define NEVER(x) (0)
-#endif
-
#include <assert.h>
#include <stdalign.h>
#include <stdbool.h>
diff --git a/src/lib/main.c b/src/lib/main.c
index d44d6de..f7cbe7d 100644
--- a/src/lib/main.c
+++ b/src/lib/main.c
@@ -15,13 +15,11 @@ aplwc_new(struct aplwc **p, uint8_t *data, size_t size)
return APLWC_OK;
}
-enum aplwc_rc
+void
aplwc_destroy(struct aplwc *p)
{
if(p)
memory_free_aplwc(&p->memory, p);
-
- return APLWC_OK;
}
const char *
diff --git a/tests/aplwc_errstr.c b/tests/aplwc_errstr.c
index 0a3b2ad..0efb777 100644
--- a/tests/aplwc_errstr.c
+++ b/tests/aplwc_errstr.c
@@ -26,9 +26,7 @@ main(void)
if(strcmp(err, "(unable to produce error string)") != 0)
return 1;
- ret = aplwc_destroy(aplwc);
- if(ret)
- return 1;
+ aplwc_destroy(aplwc);
ret = aplwc_new(&aplwc, data, 0);
if(ret == 0)
diff --git a/tests/aplwc_new.c b/tests/aplwc_new.c
index 1931c3c..55e742f 100644
--- a/tests/aplwc_new.c
+++ b/tests/aplwc_new.c
@@ -19,9 +19,7 @@ main(void)
if(j >= APLWC_MIN_MEM)
return 1;
}
- ret = aplwc_destroy(aplwc);
- if(ret)
- return 1;
+ aplwc_destroy(aplwc);
}
}
diff --git a/tools/checkcov b/tools/checkcov
index 32e30d7..3d9fedf 100755
--- a/tools/checkcov
+++ b/tools/checkcov
@@ -4,8 +4,8 @@ cd build/$1
case "$1" in
Coverage)
- rm -rf CMakeFiles/aplwc.dir/src/*
- rm -rf CMakeFiles/aplwc-repl.dir/src/*
+ rm -rf CMakeFiles/aplwc.dir/src/lib/*
+ rm -rf CMakeFiles/aplwc-repl.dir/src/bin/*
;;
*)
;;
@@ -22,7 +22,7 @@ case "$1" in
;;
esac
-gcov -tg CMakeFiles/aplwc.dir/src/*.gcno CMakeFiles/aplwc-repl.dir/src/*.gcno | awk '
+gcov -tg CMakeFiles/aplwc.dir/src/lib/*.gcno CMakeFiles/aplwc-repl.dir/src/bin/*.gcno | awk '
BEGIN {
FS=":"
}