From 8b31c6fcf4c13970347e06d3333d0f0660785155 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 27 May 2019 14:23:04 +0200 Subject: [PATCH 1/3] core: increase stack size for unix port --- core/embed/unix/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index c14049d26..3de795cdf 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -461,7 +461,7 @@ MP_NOINLINE int main_(int argc, char **argv) { signal(SIGPIPE, SIG_IGN); #endif - mp_stack_set_limit(60000 * (BYTES_PER_WORD / 4)); + mp_stack_set_limit(600000 * (BYTES_PER_WORD / 4)); pre_process_options(argc, argv); From 62e9ff0ad24672a1960915ceb164d35749d8996f Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 27 May 2019 14:26:35 +0200 Subject: [PATCH 2/3] core: introduce coverage wrapper --- core/prof/prof.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 core/prof/prof.py diff --git a/core/prof/prof.py b/core/prof/prof.py new file mode 100644 index 000000000..fcb13017c --- /dev/null +++ b/core/prof/prof.py @@ -0,0 +1,70 @@ +import sys + +import uos +from uio import open + +sys.path.insert(0, uos.getenv("TREZOR_SRC")) +del uos + + +class Coverage: + def __init__(self): + self.__files = {} + + def line_tick(self, filename, lineno): + if not filename in self.__files: + self.__files[filename] = set() + self.__files[filename].add(lineno) + + def lines_execution(self): + lines_execution = {"lines": {}} + lines = lines_execution["lines"] + this_file = globals()["__file__"] + for filename in self.__files: + if not filename == this_file: + lines[filename] = list(self.__files[filename]) + + return lines_execution + + +class _Prof: + trace_count = 0 + display_flags = 0 + __coverage = Coverage() + + def trace_tick(self, frame, event, arg): + self.trace_count += 1 + + # if frame.f_code.co_filename.endswith('/loop.py'): + # print(event, frame.f_code.co_filename, frame.f_lineno) + + if event == "line": + self.__coverage.line_tick(frame.f_code.co_filename, frame.f_lineno) + + def coverage_data(self): + return self.__coverage.lines_execution() + + +def trace_handler(frame, event, arg): + __prof__.trace_tick(frame, event, arg) + return trace_handler + + +def atexit(): + print("\n------------------ script exited ------------------") + print("Total traces executed: ", __prof__.trace_count) + with open(".coverage", "w") as f: + # wtf so private much beautiful wow + f.write("!coverage.py: This is a private format, don't read it directly!") + # poormans json + f.write(str(__prof__.coverage_data()).replace("'", '"')) + + +sys.atexit(atexit) + +global __prof__ +if not "__prof__" in globals(): + __prof__ = _Prof() + +sys.settrace(trace_handler) +import main From 33b7e378c2d0af90c967238e6c6f2c5855ec6e00 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 27 May 2019 14:17:43 +0200 Subject: [PATCH 3/3] core/ci: add coverage target, introduce posttest stage --- .gitlab-ci.yml | 2 ++ ci/posttest.yml | 21 +++++++++++++++++++++ ci/test.yml | 24 ++++++++++++++++++++++++ core/Makefile | 7 +++++++ core/SConscript.unix | 2 ++ docs/tests/device-tests.md | 16 ++++++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 ci/posttest.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5619cfae4..df1b8ef4f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,6 +26,7 @@ stages: - prebuild - build - test + - posttest - deploy before_script: @@ -36,4 +37,5 @@ include: - ci/prebuild.yml - ci/build.yml - ci/test.yml + - ci/posttest.yml - ci/deploy.yml diff --git a/ci/posttest.yml b/ci/posttest.yml new file mode 100644 index 000000000..57990c11c --- /dev/null +++ b/ci/posttest.yml @@ -0,0 +1,21 @@ +image: registry.gitlab.com/satoshilabs/trezor/trezor-firmware/environment + +core unix coverage posttest: + stage: posttest + dependencies: + - core unix device test + - core unix monero test + - core unix u2f test + - core unix fido2 test + script: + - cd core + - pipenv run make res # we need to regenerate resources.py + - pipenv run make coverage + coverage: '/>\d+%/dev/null && \ + mv .coverage .coverage.empty && \ + coverage combine .coverage.* && \ + coverage html + grep pc_cov htmlcov/index.html diff --git a/core/SConscript.unix b/core/SConscript.unix index 13cd861d8..d2ed5ff20 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -265,6 +265,7 @@ SOURCE_MICROPYTHON = [ 'vendor/micropython/py/parsenum.c', 'vendor/micropython/py/parsenumbase.c', 'vendor/micropython/py/persistentcode.c', + 'vendor/micropython/py/profile.c', 'vendor/micropython/py/pystack.c', 'vendor/micropython/py/qstr.c', 'vendor/micropython/py/reader.c', @@ -295,6 +296,7 @@ SOURCE_UNIX = [ 'embed/unix/touch.c', 'embed/unix/usb.c', 'vendor/micropython/ports/unix/alloc.c', + 'vendor/micropython/ports/unix/file.c', 'vendor/micropython/ports/unix/gccollect.c', 'vendor/micropython/ports/unix/input.c', 'vendor/micropython/ports/unix/unix_mphal.c', diff --git a/docs/tests/device-tests.md b/docs/tests/device-tests.md index 42928b189..f47e98d3b 100644 --- a/docs/tests/device-tests.md +++ b/docs/tests/device-tests.md @@ -91,3 +91,19 @@ If you wan't to catch some memory errors use this. ```sh time ASAN_OPTIONS=verbosity=1:detect_invalid_pointer_pairs=1:strict_init_order=true:strict_string_checks=true TREZOR_PROFILE="" pipenv run make test_emu ``` + +### Coverage (Emulator only) + +Get the Python code coverage report. + +If you want to get HTML/console summary output you need to install the __coverage.py__ tool. + +```sh +pip3 install coverage +``` + +Run the tests with coverage output. + +```sh +make build_unix && make coverage +```