Basics of test case framework
This commit is contained in:
parent
9dec5dd628
commit
97a46e8c1a
7 changed files with 162 additions and 0 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,3 +4,6 @@
|
||||||
[submodule "extras/mbedtls/mbedtls"]
|
[submodule "extras/mbedtls/mbedtls"]
|
||||||
path = extras/mbedtls/mbedtls
|
path = extras/mbedtls/mbedtls
|
||||||
url = https://github.com/ARMmbed/mbedtls.git
|
url = https://github.com/ARMmbed/mbedtls.git
|
||||||
|
[submodule "tests/unity"]
|
||||||
|
path = tests/unity
|
||||||
|
url = git@github.com:ThrowTheSwitch/Unity.git
|
||||||
|
|
13
tests/Makefile
Normal file
13
tests/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
PROGRAM=tests
|
||||||
|
|
||||||
|
EXTRA_LINKER_SCRIPTS = $(PROGRAM_DIR)ld/tests.ld
|
||||||
|
PROGRAM_SRC_DIR = $(PROGRAM_DIR) $(PROGRAM_DIR)cases
|
||||||
|
|
||||||
|
# append -u <basename_test_entry to the linker arguments for
|
||||||
|
# each source file in the 'cases' directory, so the test case
|
||||||
|
# entries get added to the compiled binary
|
||||||
|
TESTCASE_SRC_FILES = $(wildcard $(PROGRAM_DIR)cases/*.c)
|
||||||
|
TESTCASE_ENTRIES = $(sort $(patsubst %.c,%,$(TESTCASE_SRC_FILES)))
|
||||||
|
EXTRA_LDFLAGS = $(foreach entry,$(TESTCASE_ENTRIES),-u testcase_$(notdir $(entry)))
|
||||||
|
|
||||||
|
include ../common.mk
|
8
tests/cases/01_basic.c
Normal file
8
tests/cases/01_basic.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "testcase.h"
|
||||||
|
|
||||||
|
DEFINE_SOLO_TESTCASE(01_basic)
|
||||||
|
|
||||||
|
static bool a_01_basic()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
40
tests/include/testcase.h
Normal file
40
tests/include/testcase.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef _TESTCASE_H
|
||||||
|
#define _TESTCASE_H
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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
|
11
tests/ld/tests.ld
Normal file
11
tests/ld/tests.ld
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
|
86
tests/test_main.c
Normal file
86
tests/test_main.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#include "testcase.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <esp/uart.h>
|
||||||
|
|
||||||
|
/* 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();
|
||||||
|
}
|
1
tests/unity
Submodule
1
tests/unity
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7943c766b993c9a84e1f6661d2d2427f6f2df9d0
|
Loading…
Reference in a new issue