Fix config/dyn_array with tests.

pull/9/head
Joshua Potter 2023-11-23 07:40:17 -07:00
parent 81500d3087
commit 25b46b9b64
8 changed files with 107 additions and 33 deletions

View File

@ -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 all: build bear
@ -11,7 +11,7 @@ bear: include/*.h src/*.c
test: test/runner 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 clang -I include src/*.c test/*.c -o test/runner
.PHONY: test .PHONY: test

View File

@ -17,12 +17,12 @@ enum ConfigError {
INVALID_TARGET, INVALID_TARGET,
}; };
enum ConfigError load_config( enum ConfigError config_load(
const char *root_dir, const char *root_dir,
const char *target, 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 */ #endif /* _SPEC_CONFIG_H */

6
main.c
View File

@ -16,8 +16,8 @@ int main(int argc, char **argv) {
const char *root_dir = getenv(ENV_SPEC_ROOT_DIR); const char *root_dir = getenv(ENV_SPEC_ROOT_DIR);
struct Config config; struct Config *config = 0;
switch (load_config(root_dir, argv[1], &config)) { switch (config_load(root_dir, argv[1], &config)) {
case ENV_SPEC_ROOT_DIR_MISSING: case ENV_SPEC_ROOT_DIR_MISSING:
fprintf(stderr, "Must specify $SPEC_ROOT_DIR environment variable."); fprintf(stderr, "Must specify $SPEC_ROOT_DIR environment variable.");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -29,6 +29,6 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
free_config(&config); config_free(config);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -3,10 +3,10 @@
#include "config.h" #include "config.h"
enum ConfigError load_config( enum ConfigError config_load(
const char *root_dir, const char *root_dir,
const char *target, const char *target,
struct Config *config struct Config **config
) { ) {
if (root_dir == 0) { if (root_dir == 0) {
return ENV_SPEC_ROOT_DIR_MISSING; return ENV_SPEC_ROOT_DIR_MISSING;
@ -23,17 +23,17 @@ enum ConfigError load_config(
return INVALID_TARGET; return INVALID_TARGET;
} }
config = malloc(sizeof(struct Config)); *config = malloc(sizeof(struct Config));
config->root_dir = root_dir; (*config)->root_dir = root_dir;
char *copy_target = calloc(1, target_len + 1); char *copy_target = calloc(1, target_len + 1);
strcpy(copy_target, target); strcpy(copy_target, target);
config->target = copy_target; (*config)->target = copy_target;
return 0; return 0;
} }
void free_config(struct Config *config) { void config_free(struct Config *config) {
if (!config) { if (!config) {
return; return;
} }

View File

@ -4,9 +4,10 @@
struct DynArray *dyn_array_new(size_t capacity) { struct DynArray *dyn_array_new(size_t capacity) {
struct DynArray *a = malloc(sizeof(struct DynArray)); 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->size = 0;
a->_capacity = capacity; a->_capacity = new_capacity;
return a; return a;
} }
@ -18,16 +19,17 @@ size_t dyn_array_size(struct DynArray *a) {
void dyn_array_push(struct DynArray *a, void *item) { void dyn_array_push(struct DynArray *a, void *item) {
assert(a); assert(a);
if (a->size == a->_capacity) { if (a->size == a->_capacity) {
// We assume reallocation will work.
a->_capacity *= 2; 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->buf[a->size] = item;
a->size += 1;
} }
void dyn_array_free(struct DynArray *a) { void dyn_array_free(struct DynArray *a) {
assert(a); if (!a) {
return;
}
free(a->buf); free(a->buf);
free(a); free(a);
} }

View File

@ -1,10 +1,18 @@
#include "sput.h" #include "sput.h"
#include "test_config.h" #include "test_config.h"
#include "test_dyn_array.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
sput_start_testing(); 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(); sput_finish_testing();

View File

@ -4,24 +4,41 @@
#include "config.h" #include "config.h"
#include "sput.h" #include "sput.h"
static void test_load_config_root_dir_missing() { static void test_config_load_root_dir_invalid() {
struct Config config; struct Config *config = 0;
enum ConfigError retval = load_config(0, "target", &config);
enum ConfigError retval = 0;
retval = config_load(0, "target", &config);
sput_fail_unless(retval == ENV_SPEC_ROOT_DIR_MISSING, "root_dir == 0"); 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 == \"\""); sput_fail_unless(retval == ENV_SPEC_ROOT_DIR_EMPTY, "root_dir == \"\"");
} }
static void test_config_run() { static void test_config_load_target_invalid() {
sput_enter_suite("load_config()"); struct Config *config = 0;
sput_run_test(test_load_config_root_dir_missing); enum ConfigError retval = 0;
sput_run_test(test_load_config_root_dir_empty);
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 */ #endif /* _SPEC_TEST_CONFIG */

47
test/test_dyn_array.h Normal file
View File

@ -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 */