From 25b46b9b646f8bb4c80b715cabbff749a93efeeb Mon Sep 17 00:00:00 2001 From: Joshua Potter Date: Thu, 23 Nov 2023 07:40:17 -0700 Subject: [PATCH] Fix config/dyn_array with tests. --- Makefile | 4 ++-- include/config.h | 6 +++--- main.c | 6 +++--- src/config.c | 12 +++++------ src/dyn_array.c | 14 +++++++------ test/runner.c | 10 ++++++++- test/test_config.h | 41 ++++++++++++++++++++++++++----------- test/test_dyn_array.h | 47 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 107 insertions(+), 33 deletions(-) create mode 100644 test/test_dyn_array.h diff --git a/Makefile b/Makefile index 65ed709..a6136c0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -BUILD=clang -g -I include src/*.c main.c -o spec +BUILD=clang -Og -g -I include src/*.c main.c -o spec all: build bear @@ -11,7 +11,7 @@ bear: include/*.h src/*.c test: test/runner $^ -test/runner: include/*.h src/*.c test/*.c +test/runner: include/*.h src/*.c test/*.h test/*.c clang -I include src/*.c test/*.c -o test/runner .PHONY: test diff --git a/include/config.h b/include/config.h index fe4e563..6c03777 100644 --- a/include/config.h +++ b/include/config.h @@ -17,12 +17,12 @@ enum ConfigError { INVALID_TARGET, }; -enum ConfigError load_config( +enum ConfigError config_load( const char *root_dir, const char *target, - struct Config *config + struct Config **config ); -void free_config(struct Config *config); +void config_free(struct Config *config); #endif /* _SPEC_CONFIG_H */ diff --git a/main.c b/main.c index 9468e84..fc53e15 100644 --- a/main.c +++ b/main.c @@ -16,8 +16,8 @@ int main(int argc, char **argv) { const char *root_dir = getenv(ENV_SPEC_ROOT_DIR); - struct Config config; - switch (load_config(root_dir, argv[1], &config)) { + struct Config *config = 0; + switch (config_load(root_dir, argv[1], &config)) { case ENV_SPEC_ROOT_DIR_MISSING: fprintf(stderr, "Must specify $SPEC_ROOT_DIR environment variable."); exit(EXIT_FAILURE); @@ -29,6 +29,6 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - free_config(&config); + config_free(config); return EXIT_SUCCESS; } diff --git a/src/config.c b/src/config.c index 2ec9ce8..be4c4bc 100644 --- a/src/config.c +++ b/src/config.c @@ -3,10 +3,10 @@ #include "config.h" -enum ConfigError load_config( +enum ConfigError config_load( const char *root_dir, const char *target, - struct Config *config + struct Config **config ) { if (root_dir == 0) { return ENV_SPEC_ROOT_DIR_MISSING; @@ -23,17 +23,17 @@ enum ConfigError load_config( return INVALID_TARGET; } - config = malloc(sizeof(struct Config)); - config->root_dir = root_dir; + *config = malloc(sizeof(struct Config)); + (*config)->root_dir = root_dir; char *copy_target = calloc(1, target_len + 1); strcpy(copy_target, target); - config->target = copy_target; + (*config)->target = copy_target; return 0; } -void free_config(struct Config *config) { +void config_free(struct Config *config) { if (!config) { return; } diff --git a/src/dyn_array.c b/src/dyn_array.c index 6dd50cb..5c1f45a 100644 --- a/src/dyn_array.c +++ b/src/dyn_array.c @@ -4,9 +4,10 @@ struct DynArray *dyn_array_new(size_t capacity) { struct DynArray *a = malloc(sizeof(struct DynArray)); - a->buf = calloc(capacity, sizeof(void *)); + size_t new_capacity = capacity ? capacity : 1; + a->buf = calloc(new_capacity, sizeof(void *)); a->size = 0; - a->_capacity = capacity; + a->_capacity = new_capacity; return a; } @@ -18,16 +19,17 @@ size_t dyn_array_size(struct DynArray *a) { void dyn_array_push(struct DynArray *a, void *item) { assert(a); if (a->size == a->_capacity) { - // We assume reallocation will work. a->_capacity *= 2; - a = realloc(a, sizeof(void *) * a->_capacity); + a->buf = realloc(a->buf, sizeof(void *) * a->_capacity); } - a->size += 1; a->buf[a->size] = item; + a->size += 1; } void dyn_array_free(struct DynArray *a) { - assert(a); + if (!a) { + return; + } free(a->buf); free(a); } diff --git a/test/runner.c b/test/runner.c index a4a7645..0f6b296 100644 --- a/test/runner.c +++ b/test/runner.c @@ -1,10 +1,18 @@ #include "sput.h" #include "test_config.h" +#include "test_dyn_array.h" int main(int argc, char *argv[]) { sput_start_testing(); - test_config_run(); + sput_enter_suite("config"); + sput_run_test(test_config_load_root_dir_invalid); + sput_run_test(test_config_load_target_invalid); + sput_run_test(test_config_load_success); + + sput_enter_suite("dyn_array"); + sput_run_test(test_dyn_array_empty); + sput_run_test(test_dyn_array_nonzero_capacity); sput_finish_testing(); diff --git a/test/test_config.h b/test/test_config.h index 1efdb18..2e8436f 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -4,24 +4,41 @@ #include "config.h" #include "sput.h" -static void test_load_config_root_dir_missing() { - struct Config config; - enum ConfigError retval = load_config(0, "target", &config); +static void test_config_load_root_dir_invalid() { + struct Config *config = 0; + enum ConfigError retval = 0; + + retval = config_load(0, "target", &config); sput_fail_unless(retval == ENV_SPEC_ROOT_DIR_MISSING, "root_dir == 0"); -} - -static void test_load_config_root_dir_empty() { - struct Config config; - enum ConfigError retval = load_config("", "target", &config); + retval = config_load("", "target", &config); sput_fail_unless(retval == ENV_SPEC_ROOT_DIR_EMPTY, "root_dir == \"\""); } -static void test_config_run() { - sput_enter_suite("load_config()"); - sput_run_test(test_load_config_root_dir_missing); - sput_run_test(test_load_config_root_dir_empty); +static void test_config_load_target_invalid() { + struct Config *config = 0; + enum ConfigError retval = 0; + + retval = config_load("/usr/local/share/specs", 0, &config); + sput_fail_unless(retval == INVALID_TARGET, "target == 0"); + + retval = config_load("/usr/local/share/specs", "", &config); + sput_fail_unless(retval == INVALID_TARGET, "target == \"\""); +} + +static void test_config_load_success() { + struct Config *config = 0; + enum ConfigError retval = + config_load("/usr/local/share/specs", "target", &config); + + sput_fail_unless(retval == 0, "config_load() success"); + sput_fail_unless(strcmp(config->root_dir, "/usr/local/share/specs") == 0, + "config_load() root_dir"); + sput_fail_unless(strcmp(config->target, "target") == 0, + "config_load(0 target"); + + config_free(config); } #endif /* _SPEC_TEST_CONFIG */ diff --git a/test/test_dyn_array.h b/test/test_dyn_array.h new file mode 100644 index 0000000..d6d15b1 --- /dev/null +++ b/test/test_dyn_array.h @@ -0,0 +1,47 @@ +#ifndef _SPEC_TEST_DYN_ARRAY +#define _SPEC_TEST_DYN_ARRAY + +#include "dyn_array.h" +#include "sput.h" + +static void test_dyn_array_empty() { + struct DynArray *a = dyn_array_new(0); + sput_fail_unless(a->size == 0, "a->size == 0"); + sput_fail_unless(a->_capacity == 1, "a->_capacity == 1"); + + int x; + dyn_array_push(a, &x); + sput_fail_unless(a->size == 1, "a->size == 1"); + sput_fail_unless(a->_capacity == 1, "a->_capacity == 1"); + + int y; + dyn_array_push(a, &y); + sput_fail_unless(a->size == 2, "a->size == 2"); + sput_fail_unless(a->_capacity == 2, "a->_capacity == 2"); + + dyn_array_free(a); +} + +static void test_dyn_array_nonzero_capacity() { + struct DynArray *a = dyn_array_new(3); + sput_fail_unless(a->size == 0, "a->size == 0"); + sput_fail_unless(a->_capacity == 3, "a->_capacity == 3"); + + int x; + int y; + int z; + dyn_array_push(a, &x); + dyn_array_push(a, &y); + dyn_array_push(a, &z); + sput_fail_unless(a->size == 3, "a->size == 3"); + sput_fail_unless(a->_capacity == 3, "a->_capacity == 3"); + + int w; + dyn_array_push(a, &w); + sput_fail_unless(a->size == 4, "a->size == 4"); + sput_fail_unless(a->_capacity == 6, "a->_capacity == 6"); + + dyn_array_free(a); +} + +#endif /* _SPEC_TEST_DYN_ARRAY */