diff --git a/.gitmodules b/.gitmodules index 8dc737e..edac09f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "extras/mbedtls/mbedtls"] path = extras/mbedtls/mbedtls url = https://github.com/ARMmbed/mbedtls.git +[submodule "tests/unity"] + path = tests/unity + url = git@github.com:ThrowTheSwitch/Unity.git diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..0659600 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,13 @@ +PROGRAM=tests + +EXTRA_LINKER_SCRIPTS = $(PROGRAM_DIR)ld/tests.ld +PROGRAM_SRC_DIR = $(PROGRAM_DIR) $(PROGRAM_DIR)cases + +# append -u +#include +#include "esp/uart.h" + +/* Types of test, defined by hardware requirements */ +typedef enum { + SOLO, /* Test require "ESP A" only, no other connections */ + DUAL, /* Test requires "ESP A" and "ESP "B", basic interconnections between them */ + EYORE_TEST, /* Test requires an eyore-test board with onboard STM32F0 */ +} testcase_type_t; + +typedef bool (testcase_fn_t)(void); + +typedef struct { + char *name; + testcase_type_t type; + testcase_fn_t *a_fn; + testcase_fn_t *b_fn; +} testcase_t; + + +/* Register a test case using these macros. Use DEFINE_SOLO_TESTCASE for single-MCU tests, + and DEFINE_TESTCASE for all other test types. + */ +#define DEFINE_SOLO_TESTCASE(NAME) \ + static testcase_fn_t a_##NAME; \ + const __attribute__((section(".testcases.text"))) __attribute__((used)) \ + testcase_t testcase_##NAME = { .name = #NAME, .type = SOLO, .a_fn = a_##NAME }; + + +#define DEFINE_TESTCASE(NAME, TYPE) \ + static testcase_fn_t a_##NAME; \ + static testcase_fn_t b_##NAME; \ + const __attribute__((section(".testcases.text"))) __attribute__((used)) \ + testcase_t testcase_##NAME = { .name = #NAME, .type = TYPE, .a_fn = a_##NAME, .b_fn = b_##NAME }; + + +#endif diff --git a/tests/ld/tests.ld b/tests/ld/tests.ld new file mode 100644 index 0000000..2825c64 --- /dev/null +++ b/tests/ld/tests.ld @@ -0,0 +1,11 @@ +/* Extra linker script sections used only for test case registration */ +SECTIONS +{ + .irom0.text : ALIGN(4) + { + _testcases_start = ABSOLUTE(.); + *(.testcases.text) + _testcases_end = ABSOLUTE(.); + } > irom0_0_seg +} + diff --git a/tests/test_main.c b/tests/test_main.c new file mode 100644 index 0000000..2f75390 --- /dev/null +++ b/tests/test_main.c @@ -0,0 +1,86 @@ +#include "testcase.h" +#include +#include + +/* Linker sets up these pointers to the registered test cases */ +extern const testcase_t _testcases_start; +extern const testcase_t _testcases_end; + +/* Convert requirement enum to a string we can print */ +static const char *get_requirements_name(const testcase_type_t arg) { + switch(arg) { + case SOLO: + return "SOLO"; + case DUAL: + return "DUAL"; + case EYORE_TEST: + return "EYORE_TEST"; + default: + return "UNKNOWN"; + } +} + +void user_init(void) +{ + const testcase_t *cases_start = &_testcases_start; + const testcase_t *cases_end= &_testcases_end; + uart_set_baud(0, 115200); + printf("esp-open-rtos test runner.\n"); + printf("testcases_start %p testcases_end %p\n", cases_start, cases_end); + printf("%d test cases are defined:\n\n", cases_end-cases_start); + for(const testcase_t *icase=cases_start; icase != cases_end; icase++) { + printf("CASE %d = %s %s\n", icase-cases_start, icase->name, get_requirements_name(icase->type)); + } + + printf("Enter A or B then number of test case to run, ie A0.\n"); + int case_idx = -1; + char type; + do { + printf("> "); + uart_rxfifo_wait(0,1); + type = uart_getc(0); + if(type != 'a' && type != 'A' && type != 'b' && type != 'B') { + printf("Type must be A or B.\n"); + continue; + } + + char idx_buf[6]; + for(int c = 0; c < sizeof(idx_buf); c++) { + uart_rxfifo_wait(0,1); + idx_buf[c] = uart_getc(0); + if(idx_buf[c] == ' ') { /* Ignore spaces */ + c--; + continue; + } + if(idx_buf[c] == '\r' || idx_buf[c] == '\n') { + idx_buf[c] = 0; + case_idx = atoi(idx_buf); + break; + } + else if(idx_buf[c] < '0' || idx_buf[c] > '9') { + break; + } + } + + if(case_idx == -1) { + printf("Invalid case index"); + } + else if(case_idx < 0 || case_idx >= cases_end-cases_start) { + printf("Test case index out of range.\n"); + } + else if((type == 'b' || type =='B') && cases_start[case_idx].type == SOLO) { + printf("No ESP type B for 'SOLO' test cases.\n"); + } else { + break; + } + } while(1); + if(type =='a') + type = 'A'; + else if (type == 'b') + type = 'B'; + printf("Running test case %d as %c (%s %s)\n", case_idx, type, cases_start[case_idx].name, get_requirements_name(cases_start[case_idx].type)); + if(type=='A') + cases_start[case_idx].a_fn(); + else + cases_start[case_idx].b_fn(); +} diff --git a/tests/unity b/tests/unity new file mode 160000 index 0000000..7943c76 --- /dev/null +++ b/tests/unity @@ -0,0 +1 @@ +Subproject commit 7943c766b993c9a84e1f6661d2d2427f6f2df9d0