diff --git a/Makefile b/Makefile index 780303a..1a52d6c 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,24 @@ HFILES := $(shell find include -type f -name '*.h') CFILES := $(shell find src -type f -name '*.c') OFILES := $(CFILES:%.c=%.o) -.PHONY: clean +TESTFILES := $(shell find test -type f -name '*.c' -not -name runner.c) +TESTS := $(TESTFILES:%.c=%) + +.PHONY: clean test psxc: $(OFILES) $(CC) $(OFILES) -o $@ +test/%: test/%.c $(HFILES) $(OFILES) + $(CC) -Wno-unused-parameter $(CFLAGS) $(filter-out src/main.o, $(OFILES)) test/runner.c $< -o $@ + %.o: %.c $(HFILES) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OFILES) psxc + rm -f $(OFILES) $(TESTS) psxc + +test: $(TESTS) + @for TEST in $(TESTS); do \ + ./$$TEST; \ + done diff --git a/include/util.h b/include/util.h index 11061bb..a6f2a7b 100644 --- a/include/util.h +++ b/include/util.h @@ -1,6 +1,16 @@ #ifndef PSXC_UTIL_H_ #define PSXC_UTIL_H_ +#include +#include + +typedef struct { + size_t size; + uint8_t data[]; +} byte_arr_t; + void fatal(const char *fmt, ...); +byte_arr_t *read_file(const char *filepath); + #endif diff --git a/src/util.c b/src/util.c index 59c0b3e..ccffa03 100644 --- a/src/util.c +++ b/src/util.c @@ -13,3 +13,28 @@ void fatal(const char *fmt, ...) { exit(EXIT_FAILURE); } + +byte_arr_t *read_file(const char *filepath) { + FILE *fp = fopen(filepath, "rb"); + byte_arr_t *arr = NULL; + + fseek(fp, 0, SEEK_END); + const long size = ftell(fp); + if (size < 0) { + goto end; + } + + arr = malloc(sizeof *arr + size); + if (arr == NULL) { + goto end; + } + + arr->size = size; + + rewind(fp); + fread(arr->data, 1, size, fp); + +end: + fclose(fp); + return arr; +} diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..f903718 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,3 @@ +!runner.c +test_* +!test_*.c diff --git a/test/runner.c b/test/runner.c new file mode 100644 index 0000000..58df0c9 --- /dev/null +++ b/test/runner.c @@ -0,0 +1,13 @@ +#include "test.h" + +#include + +int main(int argc, char *argv[]) { + printf("%s:\n", argv[0]); + for (size_t i = 0; i < NUM_TEST_CASES; ++i) { + printf(" * %s: ", TEST_CASES[i].name); + TEST_CASES[i].test(); + printf("OK!\n"); + } + return 0; +} diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..86ea6ff --- /dev/null +++ b/test/test.h @@ -0,0 +1,15 @@ +#ifndef PSXC_TEST_H_ +#define PSXC_TEST_H_ + +#include + +typedef struct { + const char *name; + void (*test)(void); +} test_case_t; + +extern const test_case_t TEST_CASES[]; + +extern const size_t NUM_TEST_CASES; + +#endif diff --git a/test/test_util.c b/test/test_util.c new file mode 100644 index 0000000..d298dbd --- /dev/null +++ b/test/test_util.c @@ -0,0 +1,36 @@ +#include "test.h" +#include "util.h" + +#include +#include +#include +#include + +#define ARR_SIZE 50 + +void test_read_file(void) { + const char *filepath = tmpnam(NULL); + + uint8_t arr[ARR_SIZE] = {0}; + for (size_t i = 0; i < sizeof arr; ++i) { + arr[i] = rand() % 256; + } + + FILE *fp = fopen(filepath, "wb"); + assert(fp != NULL); + + fwrite(&arr[0], 1, ARR_SIZE, fp); + fclose(fp); + + byte_arr_t *barr = read_file(filepath); + assert(barr != NULL); + assert(barr->size == ARR_SIZE); + + assert(memcmp(&arr[0], barr->data, ARR_SIZE) == 0); +} + +const test_case_t TEST_CASES[] = { + {"can read simple file", test_read_file}, +}; + +const size_t NUM_TEST_CASES = sizeof TEST_CASES / sizeof TEST_CASES[0]; \ No newline at end of file