8000 qemu-arm: fully integrated test suite. · davidgiven/micropython@c1c32d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit c1c32d6

Browse files
Ilya Dmitrichenkopfalcon
authored andcommitted
qemu-arm: fully integrated test suite.
This is primarily intended to provide testing of Thumb-specific code within Travis CI as well as if anyone else want to run it locally. As discussed in purposes. This is currently agains an emulated Cortex-M3 core, however in the near future it can extended to support M0, M0+ as well M4 (work in progress exists in sushihangover/qemu). It's probably true that most of the code base can be covered running uPy natively on a POSIX system, however we do have the tiny bit of assembly code. There may exist bugs related to endianness and type aliases, let alone potential standard library or compiler bugs or even architecture-specific optimisations. This could also incorporate lwIP (or other TCP/IP stack) integration as well as SDIO+FATFS drivers. The solution to inline the test cases was chose due to simplicity. It could alternatively be implemented in a number of different way (see micropython#515), but this looked the simplest. Inclusion of tinytest was just to avoid writing boilerplate code for counting failed tests and other utility functions. Currently only a few functions are used, however this could be extended. Checking in the code instead of using submodule was a personal preference, but if people do want the pain of submodules, this can provided. This particular framework is also pretty good if one desires to run unit test on target. The approach with scripts being inlined is probably not quite suited for the size of memory an MCU has, but the tinytest itself should be good, if lower-level C code is to be unit tested.
1 parent be86596 commit c1c32d6

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

qemu-arm/Makefile

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,42 @@ endif
3333
## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/qemu/Makefile
3434
LDFLAGS= --specs=nano.specs --specs=rdimon.specs -Wl,--gc-sections -Wl,-Map=$(@:.elf=.map)
3535

36+
ifeq ($(RUN_TESTS), 1)
37+
SRC_C = \
38+
test_main.c \
39+
40+
else
3641
SRC_C = \
3742
main.c \
3843

44+
endif
45+
3946
SRC_S = \
4047

4148
OBJ =
4249
OBJ += $(PY_O)
4350
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
4451
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
4552

53+
ifeq ($(RUN_TESTS), 1)
54+
INC += -I../tools/tinytest/
55+
OBJ += $(BUILD)/tinytest.o
56+
endif
57+
4658
all: run
4759

4860
run: $(BUILD)/flash.elf
49-
5061
qemu-system-arm -cpu cortex-m3 -nographic -monitor null -serial null -semihosting -kernel $(BUILD)/flash.elf
5162

63+
.PHONY: $(BUILD)/genhdr/tests.h
64+
65+
$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h
66+
$(BUILD)/genhdr/tests.h:
67+
$(Q)echo "Generating $@";(cd ../tests; ../tools/tinytest-codegen.py) > $@
68+
69+
$(BUILD)/tinytest.o:
70+
$(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c ../tools/tinytest/tinytest.c
71+
5272
## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here.
5373
$(BUILD)/flash.elf: $(OBJ)
5474
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)

qemu-arm/test_main.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
5+
#include "mpconfig.h"
6+
#include "nlr.h"
7+
#include "misc.h"
8+
#include "qstr.h"
9+
#include "lexer.h"
10+
#include "parse.h"
11+
#include "obj.h"
12+
#include "parsehelper.h"
13+
#include "compile.h"
14+
#include "runtime0.h"
15+
#include "runtime.h"
16+
#include "repl.h"
17+
18+
#include "tinytest.h"
19+
#include "tinytest_macros.h"
20+
21+
inline void do_str(const char *src) {
22+
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
23+
if (lex == NULL) {
24+
tt_abort_msg("Lexer initialization error");
25+
}
26+
27+
mp_parse_error_kind_t parse_error_kind;
28+
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind);
29+
30+
if (pn == MP_PARSE_NODE_NULL) {
31+
mp_parse_show_exception(lex, parse_error_kind);
32+
mp_lexer_free(lex);
33+
tt_abort_msg("Parser error");
34+
}
35+
36+
// parse okay
37+
qstr source_name = mp_lexer_source_name(lex);
38+
mp_lexer_free(lex);
39+
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
40+
mp_parse_node_free(pn);
41+
42+
if (module_fun == mp_const_none) {
43+
tt_abort_msg("Computer error");
44+
}
45+
46+
nlr_buf_t nlr;
47+
if (nlr_push(&nlr) == 0) {
48+
mp_call_function_0(module_fun);
49+
nlr_pop();
50+
} else {
51+
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
52+
tt_abort_msg("Uncaught exception");
53+
}
54+
end:
55+
;
56+
}
57+
58+
#include "genhdr/tests.h"
59+
60+
int main() {
61+
const char a[] = {"sim"};
62+
qstr_init();
63+
mp_init();
64+
int r = tinytest_main(1, (const char **) a, groups);
65+
mp_deinit();
66+
printf( "status: %i\n", r);
67+
return r;
68+
}
69+
70+
void gc_collect(void) {
71+
}
72+
73+
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
74+
return NULL;
75+
}
76+
77+
mp_import_stat_t mp_import_stat(const char *path) {
78+
return MP_IMPORT_STAT_NO_EXIST;
79+
}
80+
81+
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
82+
return mp_const_none;
83+
}
84+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
85+
86+
void nlr_jump_fail(void *val) {
87+
}

0 commit comments

Comments
 (0)
0