diff options
Diffstat (limited to '02-usart/test_harness')
-rw-r--r-- | 02-usart/test_harness/Makefile | 9 | ||||
-rw-r--r-- | 02-usart/test_harness/fake_env.c | 25 | ||||
-rw-r--r-- | 02-usart/test_harness/fake_env.h | 13 | ||||
-rw-r--r-- | 02-usart/test_harness/test_harness.c | 82 | ||||
-rw-r--r-- | 02-usart/test_harness/test_harness.h | 88 |
5 files changed, 217 insertions, 0 deletions
diff --git a/02-usart/test_harness/Makefile b/02-usart/test_harness/Makefile new file mode 100644 index 0000000..443292b --- /dev/null +++ b/02-usart/test_harness/Makefile @@ -0,0 +1,9 @@ +CC=gcc +CFLAGS=-g3 -ggdb -Wall + +test_harness.a: test_harness.c test_harness.h fake_env.o + gcc -o test_harness.o -c test_harness.c $(CFLAGS) + ar r test_harness.a test_harness.o fake_env.o + +fake_env.o: fake_env.c fake_env.h + gcc -o fake_env.o -c fake_env.c $(CFLAGS) diff --git a/02-usart/test_harness/fake_env.c b/02-usart/test_harness/fake_env.c new file mode 100644 index 0000000..45cb1e9 --- /dev/null +++ b/02-usart/test_harness/fake_env.c @@ -0,0 +1,25 @@ +#include "fake_env.h" + +#include <stdlib.h> +#include <assert.h> + +#define DEFINE_MEMORY_SEGMENT(name, start_addr, end_addr) \ + static void* fake_##name = NULL; \ + void* load_fake_##name##__ () \ + { \ + if (fake_##name == NULL) { \ + fake_##name = malloc((end_addr) - (start_addr)); \ + assert(fake_##name != NULL); \ + } \ + return fake_##name; \ + } + +/* Peripheral buses */ +DEFINE_MEMORY_SEGMENT(apb1, 0x40000000, 0x40010000) +DEFINE_MEMORY_SEGMENT(apb2, 0x40010000, 0x40020000) +DEFINE_MEMORY_SEGMENT(ahb1, 0x40020000, 0x40024400) +DEFINE_MEMORY_SEGMENT(ahb2, 0x48000000, 0x50060C00) + +/* SRAM */ +DEFINE_MEMORY_SEGMENT(sram1, 0x20000000, 0x2000C000) +DEFINE_MEMORY_SEGMENT(sram2, 0x2000C000, 0x20018000) diff --git a/02-usart/test_harness/fake_env.h b/02-usart/test_harness/fake_env.h new file mode 100644 index 0000000..12c09ff --- /dev/null +++ b/02-usart/test_harness/fake_env.h @@ -0,0 +1,13 @@ +#ifndef FAKE_ENV_H_ +#define FAKE_ENV_H_ + +/* Functions which wil lazily load fake chunks of memory + * corresponding to the*/ +void* load_fake_ahb1__(); +void* load_fake_ahb2__(); +void* load_fake_apb1__(); +void* load_fake_apb2__(); +void* load_fake_sram1__(); +void* load_fake_sram2__(); + +#endif /* FAKE_ENV_H_ */ diff --git a/02-usart/test_harness/test_harness.c b/02-usart/test_harness/test_harness.c new file mode 100644 index 0000000..9f7dd79 --- /dev/null +++ b/02-usart/test_harness/test_harness.c @@ -0,0 +1,82 @@ +#include "test_harness.h" + +#include <assert.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <stdlib.h> +#include <setjmp.h> + + +static jmp_buf jmpbuf; + +volatile test_t dummy + __attribute((__section__("tests"))) + __attribute((__used__)) = { + "dummy", + "dummy", + NULL +}; + +extern test_t __start_tests; +extern test_t __stop_tests; + +test_t* iter = &__start_tests; + +static int execute_test(test_t* test); + +int main() { + for( ; iter < &__stop_tests; ++ iter) { + if (iter->fn_ptr != NULL) { + execute_test(iter); + } + } +} + +void test_harness_abort(int ec) +{ + longjmp(jmpbuf, ec); + assert("Long jump failed.\n"); +} + +static int execute_test(test_t* test) +{ + char fullname[512]; + int status; + int ec; + pid_t pid; + const char* note = ""; + + snprintf( + fullname, sizeof(fullname), "%s::%s", iter->test_suite, iter->test_name); + + if (!(pid = fork())) { + // child + + if ((ec = setjmp(jmpbuf))) { + exit(ec); + } else { + test->fn_ptr(); + exit(0); + } + } else { + if (waitpid(pid, &status, 0) == -1) { + fprintf(stderr, "waitpid() failed\n"); + return 1; + } + + ec = WEXITSTATUS(status); + switch (ec) { + case 0: + printf("%s " GREEN "[PASS]" RESET "\n", fullname); + return 0; + case 11: + note = " (SIGSEGV)"; + break; + } + + printf("%s " RED "[FAIL] %d%s" RESET "\n", fullname, ec, note); + return ec; + } +} diff --git a/02-usart/test_harness/test_harness.h b/02-usart/test_harness/test_harness.h new file mode 100644 index 0000000..0a218f8 --- /dev/null +++ b/02-usart/test_harness/test_harness.h @@ -0,0 +1,88 @@ +#ifndef TEST_HARNESS_H_ +#define TEST_HARNESS_H_ + +#include <stdio.h> +#include <string.h> + +#define YELLOW "\x1b[00;33m" +#define GREEN "\x1b[01;32m" +#define RED "\x1b[01;31m" +#define RESET "\x1b[0m" + +typedef struct { + const char* test_suite; + const char* test_name; + int (*fn_ptr)(); + void* alignment; +} test_t; + +#define GENPR(fmt, v1, v2) \ + fprintf(stderr, fmt "\n", v1, v2) + +#define FORMAT_STRING(v1, v2) \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ + _Generic(v1, long: GENPR("%ld == %ld", v1, v2), \ + unsigned long: GENPR("%lu == %lu", v1, v2), \ + int: GENPR("%d == %d", v1, v2), \ + unsigned int: GENPR("%u == %u", v1, v2), \ + short: GENPR("%h == %h", v1, v2), \ + unsigned short: GENPR("%hu == %hu", v1, v2), \ + char: GENPR("%c == %c", v1, v2), \ + double: GENPR("%f == %f", v1, v2), \ + unsigned char: fprintf( \ + stderr, "%02x == %02x\n", (unsigned int) v1, (unsigned int) v2),\ + default: GENPR("%p == %p\n", v1, v2)); \ + _Pragma("GCC diagnostic pop") + +#define TRY_PRINT_TYPE(v1, v2, type, fmt) \ + else if (__builtin_types_compatible_p(typeof (v1), type)) { \ + fprintf(stderr, fmt " == " fmt "\n", v1, v2); \ + } + +#define TYPE_STR(t) #t + +#define ASSERT_TRUE(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, RED "ASSERT_TRUE FAILED!\n" RESET); \ + fprintf(stderr, " - " YELLOW "In expression ASSERT_TRUE(" #x ")\n"); \ + fprintf(stderr, RESET " - " YELLOW "At " __FILE__ ":%d\n" RESET, __LINE__); \ + test_harness_abort(1); \ + } \ + } while (0) + +#define ASSERT_EQ(x, y) \ + do { \ + if ((x) != (y)) { \ + fprintf(stderr, RED "ASSERT_EQ FAILED! " RESET "Not true that "); \ + FORMAT_STRING(x, y); \ + fprintf(stderr, " - " YELLOW "In expression ASSERT_EQ(" #x ", " #y ")\n"); \ + fprintf(stderr, RESET " - " YELLOW "At " __FILE__ ":%d\n" RESET, __LINE__); \ + test_harness_abort(1); \ + } \ + } while (0) + +#define ASSERT_EQ_STR(x, y) \ + do { \ + if (strcmp(x, y)) { \ + fprintf(stderr, \ + RED "ASSSERT_EQ_STR FAILED! " RESET "Not true that \"%s\" equals \"%s\"", \ + x, y); \ + fprintf(stderr, " - " YELLOW "In expression ASSERT_EQ_STR(" #x ", " #y ")\n"); \ + fprintf(stderr, RESET " - " YELLOW "At " __FILE__":%d\n" RESET, __LINE__); \ + test_harness_abort(1); \ + } \ + } while (0) + + +#define TEST(test_suite, test_name) \ + int test_suite ## _ ## test_name ## _fn (void); \ + volatile test_t test_suite ## _ ## test_name ## _testing_struct__ \ + __attribute((__section__("tests"))) __attribute((__used__)) = \ + {#test_suite, #test_name, test_suite ## _ ## test_name ## _fn}; \ + int test_suite ## _ ## test_name ## _fn (void) + +void test_harness_abort(int ec); + +#endif |