aboutsummaryrefslogtreecommitdiff
path: root/02-usart/test_harness
diff options
context:
space:
mode:
Diffstat (limited to '02-usart/test_harness')
-rw-r--r--02-usart/test_harness/Makefile9
-rw-r--r--02-usart/test_harness/fake_env.c25
-rw-r--r--02-usart/test_harness/fake_env.h13
-rw-r--r--02-usart/test_harness/test_harness.c82
-rw-r--r--02-usart/test_harness/test_harness.h88
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