From ea6bddbf8125e09d5d779d7203d402dbc093379d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 11 Dec 2017 20:04:27 +0200 Subject: [PATCH] ports/qemu-arm: Rework "test" target using upytesthelper. The way tinytest was used in qemu-arm test target is that it didn't test much. MicroPython tests are based on matching the test output against reference output, but qemu-arm's implementation didn't do that, it effectively tested just that there was no exception during test execution. "upytesthelper" wrapper was introduce to fix it, so switch test implementation to use it. This requires passing different CFLAGS when building the firmware, so split out test-related parts to Makefile.test. --- ports/qemu-arm/Makefile | 20 +------------------- ports/qemu-arm/Makefile.test | 24 ++++++++++++++++++++++++ ports/qemu-arm/README.md | 4 ++++ ports/qemu-arm/mpconfigport.h | 7 +++++++ ports/qemu-arm/test_main.c | 30 +----------------------------- 5 files changed, 37 insertions(+), 48 deletions(-) create mode 100644 ports/qemu-arm/Makefile.test diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index c0d257a3e..95f349beb 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -46,7 +46,7 @@ SRC_RUN_C = \ SRC_TEST_C = \ test_main.c \ -LIB_SRC_C = $(addprefix lib/,\ +LIB_SRC_C += $(addprefix lib/,\ libm/math.c \ libm/fmodf.c \ libm/nearbyintf.c \ @@ -91,27 +91,9 @@ all: run run: $(BUILD)/firmware.elf qemu-system-arm -machine integratorcp -cpu cortex-m3 -nographic -monitor null -serial null -semihosting -kernel $(BUILD)/firmware.elf -test: $(BUILD)/firmware-test.elf - qemu-system-arm -machine integratorcp -cpu cortex-m3 -nographic -monitor null -serial null -semihosting -kernel $(BUILD)/firmware-test.elf > $(BUILD)/console.out - $(Q)tail -n2 $(BUILD)/console.out - $(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0" - -.PHONY: $(BUILD)/genhdr/tests.h - -$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h -$(BUILD)/genhdr/tests.h: - $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ - -$(BUILD)/tinytest.o: - $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TINYTEST)/tinytest.c - ## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here. $(BUILD)/firmware.elf: $(OBJ_COMMON) $(OBJ_RUN) $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ -$(BUILD)/firmware-test.elf: $(OBJ_COMMON) $(OBJ_TEST) - $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) - $(Q)$(SIZE) $@ - include $(TOP)/py/mkrules.mk diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test new file mode 100644 index 000000000..a9aace6d0 --- /dev/null +++ b/ports/qemu-arm/Makefile.test @@ -0,0 +1,24 @@ +LIB_SRC_C = lib/upytesthelper/upytesthelper.c + +include Makefile + +CFLAGS += -DTEST + +.PHONY: $(BUILD)/genhdr/tests.h + +$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h +$(BUILD)/genhdr/tests.h: + (cd $(TOP)/tests; ./run-tests --write-exp) + $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ + +$(BUILD)/tinytest.o: + $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TINYTEST)/tinytest.c + +$(BUILD)/firmware-test.elf: $(OBJ_COMMON) $(OBJ_TEST) + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + $(Q)$(SIZE) $@ + +test: $(BUILD)/firmware-test.elf + qemu-system-arm -machine integratorcp -cpu cortex-m3 -nographic -monitor null -serial null -semihosting -kernel $(BUILD)/firmware-test.elf > $(BUILD)/console.out + $(Q)tail -n2 $(BUILD)/console.out + $(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0" diff --git a/ports/qemu-arm/README.md b/ports/qemu-arm/README.md index 0cf93c7d5..4f1e79b10 100644 --- a/ports/qemu-arm/README.md +++ b/ports/qemu-arm/README.md @@ -21,3 +21,7 @@ toolchain and not with CodeSourcery toolchain. You will need to modify The difference is that CodeSourcery needs `-T generic-m-hosted.ld` while ARM's version requires `--specs=nano.specs --specs=rdimon.specs` to be passed to the linker. + +To build and run image with builtin testsuite: + + make -f Makefile.test test diff --git a/ports/qemu-arm/mpconfigport.h b/ports/qemu-arm/mpconfigport.h index 51706b927..5d8619198 100644 --- a/ports/qemu-arm/mpconfigport.h +++ b/ports/qemu-arm/mpconfigport.h @@ -17,6 +17,7 @@ #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_WARNINGS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) @@ -69,3 +70,9 @@ extern const struct _mp_obj_module_t mp_module_uos; // We need to provide a declaration/definition of alloca() #include + +#ifdef TEST +#include "lib/upytesthelper/upytesthelper.h" +#undef MP_PLAT_PRINT_STRN +#define MP_PLAT_PRINT_STRN(str, len) upytest_output(str, len) +#endif diff --git a/ports/qemu-arm/test_main.c b/ports/qemu-arm/test_main.c index acac66e6a..926478ea1 100644 --- a/ports/qemu-arm/test_main.c +++ b/ports/qemu-arm/test_main.c @@ -17,41 +17,13 @@ #define HEAP_SIZE (128 * 1024) STATIC void *heap; -void do_str(const char *src); -inline void do_str(const char *src) { - gc_init(heap, (char*)heap + HEAP_SIZE); - mp_init(); - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); - qstr source_name = lex->source_name; - mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); - mp_call_function_0(module_fun); - nlr_pop(); - } else { - mp_obj_t exc = (mp_obj_t)nlr.ret_val; - if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { - // Assume that sys.exit() is called to skip the test. - // TODO: That can be always true, we should set up convention to - // use specific exit code as skip indicator. - tinytest_set_test_skipped_(); - goto end; - } - mp_obj_print_exception(&mp_plat_print, exc); - tt_abort_msg("Uncaught exception"); - } -end: - mp_deinit(); -} - #include "genhdr/tests.h" int main() { mp_stack_ctrl_init(); mp_stack_set_limit(10240); heap = malloc(HEAP_SIZE); + upytest_set_heap(heap, (char*)heap + HEAP_SIZE); int r = tinytest_main(0, NULL, groups); printf("status: %d\n", r); return r;