From c151fdeefd7ff8428110a5b3ead69ef54fb61018 Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 14 Jan 2020 11:30:41 +0100 Subject: [PATCH 01/17] python: add wait-for-emulator command --- python/CHANGELOG.md | 7 +++++++ python/src/trezorlib/cli/trezorctl.py | 24 ++++++++++++++++++++++++ python/src/trezorlib/transport/udp.py | 19 ++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/python/CHANGELOG.md b/python/CHANGELOG.md index 0110aeb85..4ba30f8a0 100644 --- a/python/CHANGELOG.md +++ b/python/CHANGELOG.md @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). _At the moment, the project does **not** adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). That is expected to change with version 1.0._ +## [0.11.7] - Unreleased + +### Added + +- built-in functionality of UdpTransport to wait until an emulator comes up, and the + related command `trezorctl wait-for-emulator` + ## [0.11.6] - 2019-12-30 [0.11.6]: https://github.com/trezor/trezor-firmware/compare/python/v0.11.5...python/v0.11.6 diff --git a/python/src/trezorlib/cli/trezorctl.py b/python/src/trezorlib/cli/trezorctl.py index 2db84a42c..596db11d8 100755 --- a/python/src/trezorlib/cli/trezorctl.py +++ b/python/src/trezorlib/cli/trezorctl.py @@ -19,12 +19,14 @@ import json import os import sys +import time import click from .. import coins, log, messages, protobuf, ui from ..client import TrezorClient from ..transport import enumerate_devices, get_transport +from ..transport.udp import UdpTransport from . import ( binance, btc, @@ -250,6 +252,28 @@ def usb_reset(): WebUsbTransport.enumerate(usb_reset=True) +@cli.command() +@click.option("-t", "--timeout", type=float, default=10, help="Timeout in seconds") +@click.pass_context +def wait_for_emulator(ctx, timeout): + """Wait until Trezor Emulator comes up. + + Tries to connect to emulator and returns when it succeeds. + """ + path = ctx.parent.params.get("path") + if path: + if not path.startswith("udp:"): + raise click.ClickException("You must use UDP path, not {}".format(path)) + path = path.replace("udp:", "") + + start = time.monotonic() + UdpTransport(path).wait_until_ready(timeout) + end = time.monotonic() + + if ctx.parent.params.get("verbose"): + click.echo("Waited for {:.3f} seconds".format(end - start)) + + # # Basic coin functions # diff --git a/python/src/trezorlib/transport/udp.py b/python/src/trezorlib/transport/udp.py index 6a04c2421..7a79079ed 100644 --- a/python/src/trezorlib/transport/udp.py +++ b/python/src/trezorlib/transport/udp.py @@ -15,6 +15,7 @@ # If not, see . import socket +import time from typing import Iterable, Optional, cast from . import TransportException @@ -60,7 +61,7 @@ class UdpTransport(ProtocolBasedTransport): return d else: raise TransportException( - "No Trezor device found at address {}".format(path) + "No Trezor device found at address {}".format(d.get_path()) ) finally: d.close() @@ -84,6 +85,22 @@ class UdpTransport(ProtocolBasedTransport): path = path.replace("{}:".format(cls.PATH_PREFIX), "") return cls._try_path(path) + def wait_until_ready(self, timeout: float = 10) -> None: + try: + self.open() + self.socket.settimeout(0) + start = time.monotonic() + while True: + if self._ping(): + break + elapsed = time.monotonic() - start + if elapsed >= timeout: + raise TransportException("Timed out waiting for connection.") + + time.sleep(0.05) + finally: + self.close() + def open(self) -> None: self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.socket.connect(self.device) From 05131c328d734bc1a45f8964d1815204f0101c06 Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 14 Jan 2020 11:56:58 +0100 Subject: [PATCH 02/17] python: trezorctl should not print empty line if result is None --- python/src/trezorlib/cli/trezorctl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/trezorlib/cli/trezorctl.py b/python/src/trezorlib/cli/trezorctl.py index 596db11d8..95878fd9d 100755 --- a/python/src/trezorlib/cli/trezorctl.py +++ b/python/src/trezorlib/cli/trezorctl.py @@ -182,7 +182,7 @@ def print_result(res, path, verbose, is_json): click.echo("%s: %s" % (k, v)) elif isinstance(res, protobuf.MessageType): click.echo(protobuf.format_message(res)) - else: + elif res is not None: click.echo(res) From 27c4c2dd506849f549bffb594f31cbaf592bf1b4 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 17 Jan 2020 15:41:50 +0100 Subject: [PATCH 03/17] core: do not let frozen emulator import live files --- core/embed/unix/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index 3de795cdf..1ceef024d 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -692,6 +692,9 @@ MP_NOINLINE int main_(int argc, char **argv) { return ret & 0xff; } +#ifdef TREZOR_EMULATOR_FROZEN +uint mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } +#else uint mp_import_stat(const char *path) { struct stat st; if (stat(path, &st) == 0) { @@ -703,6 +706,7 @@ uint mp_import_stat(const char *path) { } return MP_IMPORT_STAT_NO_EXIST; } +#endif void nlr_jump_fail(void *val) { printf("FATAL: uncaught NLR %p\n", val); From 8dce2cf98c3eedb28fcadd34db4419c77185fa53 Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 15 Jan 2020 16:53:50 +0100 Subject: [PATCH 04/17] core: introduce emulator runner (fixes #466) --- core/emu.py | 268 +++++++++++++++++++++ core/trezor.sdcard.gz | Bin 0 -> 65333 bytes python/src/trezorlib/_internal/emulator.py | 237 ++++++++++++++++++ 3 files changed, 505 insertions(+) create mode 100755 core/emu.py create mode 100644 core/trezor.sdcard.gz create mode 100644 python/src/trezorlib/_internal/emulator.py diff --git a/core/emu.py b/core/emu.py new file mode 100755 index 000000000..a227bf374 --- /dev/null +++ b/core/emu.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python3 +import gzip +import os +import platform +import signal +import subprocess +import sys +import tempfile +import time +from pathlib import Path + +import click + +import trezorlib.debuglink +import trezorlib.device +from trezorlib._internal.emulator import CoreEmulator + +try: + import inotify.adapters +except ImportError: + inotify = None + + +HERE = Path(__file__).parent.resolve() +MICROPYTHON = HERE / "build" / "unix" / "micropython" +SRC_DIR = HERE / "src" +SD_CARD_GZ = HERE / "trezor.sdcard.gz" + +PROFILING_WRAPPER = HERE / "prof" / "prof.py" + +PROFILE_BASE = Path.home() / ".trezoremu" + + +def run_command_with_emulator(emulator, command): + with emulator: + # first start the subprocess + process = subprocess.Popen(command) + # After the subprocess is started, ignore SIGINT in parent + # (so that we don't need to handle KeyboardInterrupts) + signal.signal(signal.SIGINT, signal.SIG_IGN) + # SIGINTs will be sent to all children by the OS, so we should be able to safely + # wait for their exit. + return process.wait() + + +def run_emulator(emulator): + with emulator: + signal.signal(signal.SIGINT, signal.SIG_IGN) + return emulator.wait() + + +def watch_emulator(emulator): + watch = inotify.adapters.InotifyTree(str(SRC_DIR)) + try: + for _, type_names, _, _ in watch.event_gen(yield_nones=False): + if "IN_CLOSE_WRITE" in type_names: + click.echo("Restarting...") + emulator.restart() + except KeyboardInterrupt: + emulator.stop() + return 0 + + +def run_debugger(emulator): + os.chdir(emulator.workdir) + env = emulator.make_env() + if platform.system() == "Darwin": + env["PATH"] = "/usr/bin" + os.execvpe( + "lldb", + ["lldb", "-f", emulator.executable, "--"] + emulator.make_args(), + env, + ) + else: + os.execvpe( + "gdb", ["gdb", "--args", emulator.executable] + emulator.make_args(), env + ) + + +@click.command(context_settings=dict(ignore_unknown_options=True)) +# fmt: off +@click.option("-a", "--disable-animation", is_flag=True, default=os.environ.get("TREZOR_DISABLE_ANIMATION") == "1", help="Disable animation") +@click.option("-c", "--command", "run_command", is_flag=True, help="Run command while emulator is running") +@click.option("-d", "--production", is_flag=True, default=os.environ.get("PYOPT") == "1", help="Production mode (debuglink disabled)") +@click.option("-D", "--debugger", is_flag=True, help="Run emulator in debugger (gdb/lldb)") +@click.option("--executable", type=click.Path(exists=True, dir_okay=False), default=os.environ.get("MICROPYTHON"), help="Alternate emulator executable") +@click.option("-g", "--profiling", is_flag=True, default=os.environ.get("TREZOR_PROFILING"), help="Run with profiler wrapper") +@click.option("-h", "--headless", is_flag=True, help="Headless mode (no display)") +@click.option("--heap-size", metavar="SIZE", default="20M", help="Configure heap size") +@click.option("--main", help="Path to python main file") +@click.option("--mnemonic", "mnemonics", multiple=True, help="Initialize device with given mnemonic. Specify multiple times for Shamir shares.") +@click.option("--log-memory", is_flag=True, default=os.environ.get("TREZOR_LOG_MEMORY") == "1", help="Print memory usage after workflows") +@click.option("-o", "--output", type=click.File("w"), default="-", help="Redirect emulator output to file") +@click.option("-p", "--profile", metavar="NAME", help="Profile name or path") +@click.option("-P", "--port", metavar="PORT", type=int, default=int(os.environ.get("TREZOR_UDP_PORT", 0)) or None, help="UDP port number") +@click.option("-q", "--quiet", is_flag=True, help="Silence emulator output") +@click.option("-s", "--slip0014", is_flag=True, help="Initialize device with SLIP-14 seed (all all all...)") +@click.option("-t", "--temporary-profile", is_flag=True, help="Create an empty temporary profile") +@click.option("-w", "--watch", is_flag=True, help="Restart emulator if sources change") +@click.option("-X", "--extra-arg", "extra_args", multiple=True, help="Extra argument to pass to micropython") +# fmt: on +@click.argument("command", nargs=-1, type=click.UNPROCESSED) +def cli( + disable_animation, + run_command, + production, + debugger, + executable, + profiling, + headless, + heap_size, + main, + mnemonics, + log_memory, + profile, + port, + output, + quiet, + slip0014, + temporary_profile, + watch, + extra_args, + command, +): + """Run the trezor-core emulator. + + If -c is specified, extra arguments are treated as a command that is executed with + the running emulator. This command can access the following environment variables: + + \b + TREZOR_PROFILE_DIR - path to storage directory + TREZOR_PATH - trezorlib connection string + TREZOR_UDP_PORT - UDP port on which the emulator listens + TREZOR_FIDO2_UDP_PORT - UDP port for FIDO2 + + By default, emulator output goes to stdout. If silenced with -q, it is redirected + to $TREZOR_PROFILE_DIR/trezor.log. You can also specify a custom path with -o. + """ + if executable: + executable = Path(executable) + else: + executable = MICROPYTHON + + if command and not run_command: + raise click.ClickException("Extra arguments found. Did you mean to use -c?") + + if watch and (command or debugger or frozen): + raise click.ClickException("Cannot use -w together with -c or -D or -F") + + if watch and inotify is None: + raise click.ClickException("inotify module is missing, install with pip") + + if main and profiling: + raise click.ClickException("Cannot use --main and -g together") + + if slip0014 and mnemonics: + raise click.ClickException("Cannot use -s and --mnemonic together") + + if slip0014: + mnemonics = [" ".join(["all"] * 12)] + + if mnemonics and debugger: + raise click.ClickException("Cannot load mnemonics when running in debugger") + + if mnemonics and production: + raise click.ClickException("Cannot load mnemonics in production mode") + + if profiling: + main_args = [str(PROFILING_WRAPPER)] + elif main: + main_args = [main] + else: + main_args = ["-m", "main"] + + if profile and temporary_profile: + raise click.ClickException("Cannot use -p and -t together") + + tempdir = None + if profile: + if "/" in profile: + profile_dir = Path(profile) + else: + profile_dir = PROFILE_BASE / profile + + elif temporary_profile: + tempdir = tempfile.TemporaryDirectory(prefix="trezor-emulator-") + profile_dir = Path(tempdir.name) + # unpack empty SD card for faster start-up + with gzip.open(SD_CARD_GZ, "rb") as gz: + (profile_dir / "trezor.sdcard").write_bytes(gz.read()) + + elif "TREZOR_PROFILE_DIR" in os.environ: + profile_dir = Path(os.environ["TREZOR_PROFILE_DIR"]) + + else: + profile_dir = Path("/var/tmp") + + if quiet: + output = None + + emulator = CoreEmulator( + executable, + profile_dir, + logfile=output, + port=port, + headless=headless, + debug=not production, + extra_args=extra_args, + main_args=main_args, + heap_size=heap_size, + disable_animation=disable_animation, + workdir=SRC_DIR, + ) + + emulator_env = dict( + TREZOR_PATH=f"udp:127.0.0.1:{emulator.port}", + TREZOR_PROFILE_DIR=str(profile_dir.resolve()), + TREZOR_UDP_PORT=str(emulator.port), + TREZOR_FIDO2_UDP_PORT=str(emulator.port + 2), + ) + os.environ.update(emulator_env) + for k, v in emulator_env.items(): + click.echo(f"{k}={v}") + + if log_memory: + os.environ["TREZOR_LOG_MEMORY"] = "1" + + if debugger: + run_debugger(emulator) + raise RuntimeError("run_debugger should not return") + + click.echo("Waiting for emulator to come up... ", err=True) + start = time.monotonic() + emulator.start() + end = time.monotonic() + click.echo(f"Emulator ready after {end - start:.3f} seconds", err=True) + + if mnemonics: + if slip0014: + label = "SLIP-0014" + elif profile: + label = profile_dir.name + else: + label = "Emulator" + + trezorlib.device.wipe(emulator.client) + trezorlib.debuglink.load_device( + emulator.client, + mnemonics, + pin=None, + passphrase_protection=False, + label=label, + ) + + if run_command: + ret = run_command_with_emulator(emulator, command) + elif watch: + ret = watch_emulator(emulator) + else: + ret = run_emulator(emulator) + + if tempdir is not None: + tempdir.cleanup() + sys.exit(ret) + + +if __name__ == "__main__": + cli() diff --git a/core/trezor.sdcard.gz b/core/trezor.sdcard.gz new file mode 100644 index 0000000000000000000000000000000000000000..e9c6efc52f0949b9d8faefacfd1004ad875d1cbf GIT binary patch literal 65333 zcmeI&OGp$@6b9f?hZGCbN+B{I8zF=uC^SNFRNRD6q69(qP$9CiOh`0QFgLX-gEmFm za8W{8P*6<|N(ovNSw=9?1A0KEp;$Uox^dUKsqZWY&%?&T#wCcx=>4N45lLa$v9koS)KhEuN`?c)H zm3=Rs%#?qx&ia}5t*RoYDtp`gOE*XFbe!*fbExxaUNq}S#1fA1c@I+c^W z@@UokliU9$5INuUzeSdp009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0Rn%aK%}Rn zIDKxfv9A5WT0?*U0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5)eyFlhdq;#$e z@Gv%*Q4{ZJ>`#CI0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5)uKJQ6Nm@Nb3 z#YQSO^B_Qg009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjZ#USQYawBT$PpnH19 zics9A5r6;z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBo5Eh$c)?E(bGy7mWg z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RnL^kU0@4o$CTTj16Yg#C;qA z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+0D;k-^2FIPKq$6j. + +import os +import subprocess +import time +from pathlib import Path + +from trezorlib.debuglink import TrezorClientDebugLink +from trezorlib.transport.udp import UdpTransport + + +def _rm_f(path): + try: + path.unlink() + except FileNotFoundError: + pass + + +class Emulator: + STORAGE_FILENAME = None + + def __init__( + self, + executable, + profile_dir, + *, + logfile=None, + storage=None, + headless=False, + debug=True, + extra_args=() + ): + self.executable = Path(executable).resolve() + if not executable.exists(): + raise ValueError( + "emulator executable not found: {}".format(self.executable) + ) + + self.profile_dir = Path(profile_dir).resolve() + if not self.profile_dir.exists(): + self.profile_dir.mkdir(parents=True) + elif not self.profile_dir.is_dir(): + raise ValueError("profile_dir is not a directory") + + self.workdir = self.profile_dir + + self.storage = self.profile_dir / self.STORAGE_FILENAME + if storage: + self.storage.write_bytes(storage) + + if logfile: + self.logfile = logfile + else: + self.logfile = self.profile_dir / "trezor.log" + + self.client = None + self.process = None + + self.port = 21324 + self.headless = headless + self.debug = debug + self.extra_args = list(extra_args) + + def make_args(self): + return [] + + def make_env(self): + return os.environ.copy() + + def _get_transport(self): + return UdpTransport("127.0.0.1:{}".format(self.port)) + + def wait_until_ready(self, timeout=30): + transport = self._get_transport() + transport.open() + start = time.monotonic() + try: + while True: + if transport._ping(): + break + if self.process.poll() is not None: + raise RuntimeError("Emulator proces died") + + elapsed = time.monotonic() - start + if elapsed >= timeout: + raise RuntimeError("Can't connect to emulator") + + time.sleep(0.1) + finally: + transport.close() + + def wait(self, timeout=None): + ret = self.process.wait(timeout=None) + self.stop() + return ret + + def launch_process(self): + args = self.make_args() + env = self.make_env() + + if hasattr(self.logfile, "write"): + output = self.logfile + else: + output = open(self.logfile, "w") + + return subprocess.Popen( + [self.executable] + args + self.extra_args, + cwd=self.workdir, + stdout=output, + stderr=subprocess.STDOUT, + env=env, + ) + + def start(self): + if self.process: + if self.process.poll() is not None: + # process has died, stop and start again + self.stop() + else: + # process is running, no need to start again + return + + self.process = self.launch_process() + self.wait_until_ready() + + (self.profile_dir / "trezor.pid").write_text(str(self.process.pid) + "\n") + (self.profile_dir / "trezor.port").write_text(str(self.port) + "\n") + + transport = self._get_transport() + self.client = TrezorClientDebugLink(transport, auto_interact=self.debug) + + self.client.open() + + def stop(self): + if self.client: + self.client.close() + self.client = None + + if self.process: + self.process.terminate() + try: + self.process.wait(1) + except subprocess.TimeoutExpired: + self.process.kill() + + _rm_f(self.profile_dir / "trezor.pid") + _rm_f(self.profile_dir / "trezor.port") + self.process = None + + def restart(self): + self.stop() + self.start() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def get_storage(self): + return self.storage.read_bytes() + + +class CoreEmulator(Emulator): + STORAGE_FILENAME = "trezor.flash" + + def __init__( + self, + *args, + port=None, + main_args=("-m", "main"), + workdir=None, + sdcard=None, + disable_animation=True, + heap_size="20M", + **kwargs + ): + super().__init__(*args, **kwargs) + if workdir is not None: + self.workdir = Path(workdir).resolve() + + self.sdcard = self.profile_dir / "trezor.sdcard" + if sdcard is not None: + self.sdcard.write_bytes(sdcard) + + if port: + self.port = port + self.disable_animation = disable_animation + self.main_args = list(main_args) + self.heap_size = heap_size + + def make_env(self): + env = super().make_env() + env.update( + TREZOR_PROFILE_DIR=str(self.profile_dir), + TREZOR_PROFILE=str(self.profile_dir), + TREZOR_UDP_PORT=str(self.port), + ) + if self.headless: + env["SDL_VIDEODRIVER"] = "dummy" + if self.disable_animation: + env["TREZOR_DISABLE_FADE"] = "1" + env["TREZOR_DISABLE_ANIMATION"] = "1" + + return env + + def make_args(self): + pyopt = "-O0" if self.debug else "-O1" + return ( + [pyopt, "-X", "heapsize={}".format(self.heap_size)] + + self.main_args + + self.extra_args + ) + + +class LegacyEmulator(Emulator): + STORAGE_FILENAME = "emulator.img" + + def make_env(self): + env = super().make_env() + if self.headless: + env["SDL_VIDEODRIVER"] = "dummy" + return env From 2294fb0453fd609d6f67a5682bb88b310a5a7c4c Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 15 Jan 2020 16:54:13 +0100 Subject: [PATCH 05/17] core: drop unused env variables (TREZOR_TEST, TREZOR_SAVE_SCREEN) --- core/src/apps/debug/__init__.py | 2 +- core/src/trezor/utils.py | 4 ---- docs/core/emulator/index.md | 8 -------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/core/src/apps/debug/__init__.py b/core/src/apps/debug/__init__.py index 6366f7742..4f1004f98 100644 --- a/core/src/apps/debug/__init__.py +++ b/core/src/apps/debug/__init__.py @@ -38,7 +38,7 @@ if __debug__: current_content = None # type: Optional[List[str]] def screenshot() -> bool: - if utils.SAVE_SCREEN or save_screen: + if save_screen: ui.display.save(save_screen_directory + "/refresh-") return True return False diff --git a/core/src/trezor/utils.py b/core/src/trezor/utils.py index ea66aa240..403c38769 100644 --- a/core/src/trezor/utils.py +++ b/core/src/trezor/utils.py @@ -20,13 +20,9 @@ if __debug__: if EMULATOR: import uos - TEST = int(uos.getenv("TREZOR_TEST") or "0") DISABLE_ANIMATION = int(uos.getenv("TREZOR_DISABLE_ANIMATION") or "0") - SAVE_SCREEN = int(uos.getenv("TREZOR_SAVE_SCREEN") or "0") LOG_MEMORY = int(uos.getenv("TREZOR_LOG_MEMORY") or "0") else: - TEST = 0 - SAVE_SCREEN = 0 LOG_MEMORY = 0 if False: diff --git a/docs/core/emulator/index.md b/docs/core/emulator/index.md index 1eae65af3..773d3ca5e 100644 --- a/docs/core/emulator/index.md +++ b/docs/core/emulator/index.md @@ -74,10 +74,6 @@ Press `p` on your keyboard to capture emulator's screen. You will find a png scr ### Environment Variables -#### Auto print screen - -If ``` TREZOR_SAVE_SCREEN=1 ``` is set, the emulator makes print screen on every screen change. - #### Memory statistics If ```TREZOR_LOG_MEMORY=1``` is set, the emulator prints memory usage information after each workflow task is finished. @@ -85,7 +81,3 @@ If ```TREZOR_LOG_MEMORY=1``` is set, the emulator prints memory usage informatio #### Disable animations ```TREZOR_DISABLE_ANIMATION=1``` disables fading and other animations, which speeds up the UI workflows significantly (useful for tests). This is also requirement for UI integration tests. - -#### Tests - -```TREZOR_TEST``` informs whether device tests are to be run. Currently unused. From ec192e9406e7fbba2d927f99281454bc9c5adabf Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 13:57:14 +0100 Subject: [PATCH 06/17] core: use better emulator test wrappers (fixes #468) --- core/Makefile | 25 +++++++++---- core/tests/run_tests_device_emu.sh | 37 ------------------- core/tests/run_tests_device_emu_fido2.sh | 40 --------------------- core/tests/run_tests_device_emu_u2f.sh | 46 ------------------------ 4 files changed, 18 insertions(+), 130 deletions(-) delete mode 100755 core/tests/run_tests_device_emu.sh delete mode 100755 core/tests/run_tests_device_emu_fido2.sh delete mode 100755 core/tests/run_tests_device_emu_u2f.sh diff --git a/core/Makefile b/core/Makefile index 7c1ca0e8c..cb386a024 100644 --- a/core/Makefile +++ b/core/Makefile @@ -38,6 +38,15 @@ FIRMWARE_MAXSIZE = 1703936 GITREV=$(shell git describe --always --dirty | tr '-' '_') CFLAGS += -DGITREV=$(GITREV) +EMU = $(CURDIR)/emu.py +EMU_TEST_ARGS = --disable-animation --headless --quiet --temporary-profile +EMU_TEST = $(EMU) $(EMU_TEST_ARGS) -c + +TESTPATH = $(CURDIR)/../tests +JUNIT_XML ?= $(TESTPATH)/junit.xml +PYTEST = pytest --junitxml=$(JUNIT_XML) +TREZOR_FIDO2_UDP_PORT = 21326 + ## help commands: help: ## show this help @@ -57,7 +66,7 @@ run: ## run unix port cd src ; ../$(UNIX_BUILD_DIR)/micropython emu: ## run emulator - ./emu.sh + $(EMU) ## test commands: @@ -65,25 +74,27 @@ test: ## run unit tests cd tests ; ./run_tests.sh $(TESTOPTS) test_emu: ## run selected device tests from python-trezor - cd tests ; ./run_tests_device_emu.sh $(TESTOPTS) + $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests $(TESTOPTS) test_emu_monero: ## run selected monero device tests from monero-agent cd tests ; ./run_tests_device_emu_monero.sh $(TESTOPTS) test_emu_u2f: ## run selected u2f device tests from u2f-tests-hid - cd tests ; ./run_tests_device_emu_u2f.sh $(TESTOPTS) + $(EMU_TEST) --slip0014 $(TESTPATH)/fido_tests/u2f-tests-hid/HIDTest $(TREZOR_FIDO2_UDP_PORT) $(TESTOPTS) + $(EMU_TEST) --slip0014 $(TESTPATH)/fido_tests/u2f-tests-hid/U2FTest $(TREZOR_FIDO2_UDP_PORT) $(TESTOPTS) test_emu_fido2: ## run fido2 device tests - cd tests ; ./run_tests_device_emu_fido2.sh $(TESTOPTS) + cd $(TESTPATH)/fido_tests/fido2 ; \ + $(EMU_TEST) $(PYTEST) --sim tests/standard/ --vendor trezor $(TESTOPTS) test_emu_click: ## run click tests - cd tests ; ./run_tests_click_emu.sh $(TESTOPTS) + $(EMU_TEST) $(PYTEST) $(TESTPATH)/click_tests $(TESTOPTS) test_emu_ui: ## run ui integration tests - cd tests ; ./run_tests_device_emu.sh --ui=test -m "not skip_ui" $(TESTOPTS) + $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=test -m "not skip_ui" $(TESTOPTS) test_emu_ui_record: ## record and hash screens for ui integration tests - cd tests ; ./run_tests_device_emu.sh --ui=record -m "not skip_ui" $(TESTOPTS) + $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=record -m "not skip_ui" $(TESTOPTS) pylint: ## run pylint on application sources and tests pylint -E $(shell find src tests -name *.py) diff --git a/core/tests/run_tests_device_emu.sh b/core/tests/run_tests_device_emu.sh deleted file mode 100755 index b823bbc43..000000000 --- a/core/tests/run_tests_device_emu.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -: "${RUN_TEST_EMU:=1}" - -CORE_DIR="$(SHELL_SESSION_FILE='' && cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" -MICROPYTHON="${MICROPYTHON:-$CORE_DIR/build/unix/micropython}" -TREZOR_SRC="${CORE_DIR}/src" - -PYOPT="${PYOPT:-0}" -upy_pid="" - -# run emulator if RUN_TEST_EMU -if [[ $RUN_TEST_EMU > 0 ]]; then - source ../trezor_cmd.sh - - # remove flash and sdcard files before run to prevent inconsistent states - mv "${TREZOR_PROFILE_DIR}/trezor.flash" "${TREZOR_PROFILE_DIR}/trezor.flash.bkp" 2>/dev/null - mv "${TREZOR_PROFILE_DIR}/trezor.sdcard" "${TREZOR_PROFILE_DIR}/trezor.sdcard.bkp" 2>/dev/null - - cd "${TREZOR_SRC}" - echo "Starting emulator: $MICROPYTHON $ARGS ${MAIN}" - - TREZOR_TEST=1 \ - TREZOR_DISABLE_ANIMATION=1 \ - $MICROPYTHON $ARGS "${MAIN}" &> "${TREZOR_LOGFILE}" & - upy_pid=$! - cd - - sleep 30 -fi - -# run tests -error=0 -if ! pytest --junitxml=../../tests/junit.xml ../../tests/device_tests "$@"; then - error=1 -fi -kill $upy_pid -exit $error diff --git a/core/tests/run_tests_device_emu_fido2.sh b/core/tests/run_tests_device_emu_fido2.sh deleted file mode 100755 index bcbedbdd9..000000000 --- a/core/tests/run_tests_device_emu_fido2.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -: "${RUN_TEST_EMU:=1}" - -CORE_DIR="$(SHELL_SESSION_FILE='' && cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" -MICROPYTHON="${MICROPYTHON:-$CORE_DIR/build/unix/micropython}" -TREZOR_SRC="${CORE_DIR}/src" - -DISABLE_ANIMATION=1 -PYOPT="${PYOPT:-0}" -upy_pid="" - -# run emulator if RUN_TEST_EMU -if [[ $RUN_TEST_EMU > 0 ]]; then - source ../trezor_cmd.sh - - # remove flash and sdcard files before run to prevent inconsistent states - mv "${TREZOR_PROFILE_DIR}/trezor.flash" "${TREZOR_PROFILE_DIR}/trezor.flash.bkp" 2>/dev/null - mv "${TREZOR_PROFILE_DIR}/trezor.sdcard" "${TREZOR_PROFILE_DIR}/trezor.sdcard.bkp" 2>/dev/null - - cd "${TREZOR_SRC}" - echo "Starting emulator: $MICROPYTHON $ARGS ${MAIN}" - - TREZOR_TEST=1 \ - TREZOR_DISABLE_ANIMATION=$DISABLE_ANIMATION \ - $MICROPYTHON $ARGS "${MAIN}" &> "${TREZOR_LOGFILE}" & - upy_pid=$! - cd - - sleep 30 -fi - -cd ../../tests/fido_tests/fido2 -# run tests -error=0 -export TREZOR_FIDO2_UDP_PORT=21326 -if ! pytest --junitxml=../../tests/junit.xml --sim tests/standard/ --vendor trezor "$@"; then - error=1 -fi -kill $upy_pid -exit $error diff --git a/core/tests/run_tests_device_emu_u2f.sh b/core/tests/run_tests_device_emu_u2f.sh deleted file mode 100755 index 93c58fadb..000000000 --- a/core/tests/run_tests_device_emu_u2f.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash - -: "${RUN_TEST_EMU:=1}" - -CORE_DIR="$(SHELL_SESSION_FILE='' && cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" -MICROPYTHON="${MICROPYTHON:-$CORE_DIR/build/unix/micropython}" -TREZOR_SRC="${CORE_DIR}/src" - -DISABLE_ANIMATION=1 -PYOPT="${PYOPT:-0}" -upy_pid="" - -# run emulator if RUN_TEST_EMU -if [[ $RUN_TEST_EMU > 0 ]]; then - source ../trezor_cmd.sh - - # remove flash and sdcard files before run to prevent inconsistent states - mv "${TREZOR_PROFILE_DIR}/trezor.flash" "${TREZOR_PROFILE_DIR}/trezor.flash.bkp" 2>/dev/null - mv "${TREZOR_PROFILE_DIR}/trezor.sdcard" "${TREZOR_PROFILE_DIR}/trezor.sdcard.bkp" 2>/dev/null - - cd "${TREZOR_SRC}" - echo "Starting emulator: $MICROPYTHON $ARGS ${MAIN}" - - TREZOR_TEST=1 \ - TREZOR_DISABLE_ANIMATION=$DISABLE_ANIMATION \ - $MICROPYTHON $ARGS "${MAIN}" &> "${TREZOR_LOGFILE}" & - upy_pid=$! - cd - - sleep 30 -fi - -# run tests -error=0 -TREZOR_FIDO2_UDP_PORT=21326 -# missuse loaddevice test to initialize the device -if ! pytest ../../tests/device_tests -k "test_msg_loaddevice" "$@"; then - error=1 -fi -if ! ../../tests/fido_tests/u2f-tests-hid/HIDTest "${TREZOR_FIDO2_UDP_PORT}" "$@"; then - error=1 -fi -if ! ../../tests/fido_tests/u2f-tests-hid/U2FTest "${TREZOR_FIDO2_UDP_PORT}" "$@"; then - error=1 -fi -kill $upy_pid -exit $error From 22c8b2569b29765c51c17c8520bbb8d0855ccaab Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 15:45:26 +0100 Subject: [PATCH 07/17] core: simplify monero test use of emulator --- core/tests/run_tests_device_emu_monero.sh | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/core/tests/run_tests_device_emu_monero.sh b/core/tests/run_tests_device_emu_monero.sh index ea2140e43..93999b424 100755 --- a/core/tests/run_tests_device_emu_monero.sh +++ b/core/tests/run_tests_device_emu_monero.sh @@ -5,30 +5,14 @@ : "${RUN_TEST_EMU:=1}" CORE_DIR="$(SHELL_SESSION_FILE='' && cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" -MICROPYTHON="${MICROPYTHON:-$CORE_DIR/build/unix/micropython}" -TREZOR_SRC="${CORE_DIR}/src" -DISABLE_ANIMATION=1 -PYOPT="${PYOPT:-0}" upy_pid="" # run emulator if RUN_TEST_EMU if [[ $RUN_TEST_EMU > 0 ]]; then - source ../trezor_cmd.sh - - # remove flash and sdcard files before run to prevent inconsistent states - mv "${TREZOR_PROFILE_DIR}/trezor.flash" "${TREZOR_PROFILE_DIR}/trezor.flash.bkp" 2>/dev/null - mv "${TREZOR_PROFILE_DIR}/trezor.sdcard" "${TREZOR_PROFILE_DIR}/trezor.sdcard.bkp" 2>/dev/null - - cd "${TREZOR_SRC}" - echo "Starting emulator: $MICROPYTHON $ARGS ${MAIN}" - - TREZOR_TEST=1 \ - TREZOR_DISABLE_ANIMATION=$DISABLE_ANIMATION \ - $MICROPYTHON $ARGS "${MAIN}" &> "${TREZOR_LOGFILE}" & + ../emu.py --disable-animation --temporary-profile --quiet --headless & upy_pid=$! - cd - - sleep 30 + trezorctl -v wait-for-emulator fi DOCKER_ID="" @@ -36,7 +20,7 @@ DOCKER_ID="" # Test termination trap terminate_test() { if [[ $# > 0 ]]; then error=$1; fi - if [ -n "$upy_pid" ]; then kill $upy_pid 2> /dev/null; fi + if [ -n "$upy_pid" ]; then kill -- -$upy_pid 2> /dev/null; fi if [ -n "$DOCKER_ID" ]; then docker kill $DOCKER_ID 2>/dev/null >/dev/null; fi exit $error } From 85f2e18828c104864a18a673a0be3470b034f757 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 14:35:27 +0100 Subject: [PATCH 08/17] core: convert emu.sh to a simple dependency-less compat wrapper --- core/emu.sh | 41 +++++------------------- core/trezor_cmd.sh | 78 ---------------------------------------------- 2 files changed, 8 insertions(+), 111 deletions(-) delete mode 100644 core/trezor_cmd.sh diff --git a/core/emu.sh b/core/emu.sh index 4481de249..970d689a1 100755 --- a/core/emu.sh +++ b/core/emu.sh @@ -1,35 +1,10 @@ -#!/usr/bin/env bash +#!/bin/sh +PYOPT="${PYOPT:-1}" -MICROPYTHON="${MICROPYTHON:-${PWD}/build/unix/micropython}" -TREZOR_SRC=$(cd "${PWD}/src/"; pwd) -BROWSER="${BROWSER:-chromium}" +if [ -n "$1" ]; then + echo "This is just a compatibility wrapper. Use emu.py if you want features." + exit 1 +fi -source ./trezor_cmd.sh - -cd "${TREZOR_SRC}" - -case "$1" in - "-d") - shift - OPERATING_SYSTEM=$(uname) - if [ "$OPERATING_SYSTEM" = "Darwin" ]; then - PATH=/usr/bin /usr/bin/lldb -f $MICROPYTHON -- $ARGS $* $MAIN - else - gdb --args $MICROPYTHON $ARGS $* $MAIN - fi - ;; - "-r") - shift - while true; do - $MICROPYTHON $ARGS $* $MAIN & - UPY_PID=$! - find -name '*.py' | inotifywait -q -e close_write --fromfile - - echo Restarting ... - kill $UPY_PID - done - ;; - *) - echo "Starting emulator: $MICROPYTHON $ARGS $* $MAIN" - $MICROPYTHON $ARGS $* $MAIN 2>&1 | tee "${TREZOR_LOGFILE}" - exit ${PIPESTATUS[0]} -esac +cd src +../build/unix/micropython -O$PYOPT -X heapsize=20M -m main diff --git a/core/trezor_cmd.sh b/core/trezor_cmd.sh deleted file mode 100644 index cb96072f1..000000000 --- a/core/trezor_cmd.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash - -# expected inputs: -# TREZOR_SRC -- directory containing python code for uMP - -if [[ ! "${TREZOR_SRC}" ]]; then echo "expecting TREZOR_SRC"; exit 0; fi - -# optional inputs: -# TREZOR_PROFILE -- profile name (directory) in ~/.trezoremu or full path -# TREZOR_PROFILING -- wrap the uMP/python in the profiler script - -# outputs: -## uMP -# PYOPT -# HEAPSIZE -# ARGS -- uMP arguments -# MAIN -- uMP file to execute -## Trezor core -# TREZOR_PROFILE_DIR -# TREZOR_PROFILE_NAME -# TREZOR_UDP_PORT -## this script -# TREZOR_SRC -# TREZOR_LOGFILE -## python-trezor -# TREZOR_PATH -- connect string - - -# defaults -PYOPT="${PYOPT:-1}" -HEAPSIZE="${HEAPSIZE:-20M}" - -TREZOR_PROFILE="${TREZOR_PROFILE:-/var/tmp}" -TREZOR_PROFILE_DIR="${TREZOR_PROFILE}" -TREZOR_PROFILE_NAME="${TREZOR_PROFILE}" - -# for profile names create profile directory if not existent -if ! [[ "$TREZOR_PROFILE" == "/"* ]]; then - TREZOR_PROFILE_DIR="${HOME}/.trezoremu/${TREZOR_PROFILE}" - if ! [[ -d "${TREZOR_PROFILE_DIR}" ]]; then - mkdir -p "${TREZOR_PROFILE_DIR}" - PORT=$(( ( RANDOM % 1000 ) + 1 + 21324 )) - echo "# autogenerated config" > "${TREZOR_PROFILE_DIR}/emu.config" - echo "TREZOR_UDP_PORT=\"\${TREZOR_UDP_PORT:-${PORT}}\"" >> "${TREZOR_PROFILE_DIR}/emu.config" - fi -fi - -# load profile config -if [[ -f "${TREZOR_PROFILE_DIR}/emu.config" ]]; then - source "${TREZOR_PROFILE_DIR}/emu.config" -fi - -# for profiling wrap -if [[ "$TREZOR_PROFILING" -gt 0 ]]; then - MAIN="${TREZOR_SRC}/../prof/prof.py" -else - MAIN="${TREZOR_SRC}/main.py" -fi - -TREZOR_LOGFILE="${TREZOR_PROFILE_DIR}/trezor.log" -TREZOR_UDP_PORT="${TREZOR_UDP_PORT:-21324}" -TREZOR_PATH="${TREZOR_PATH:-udp:127.0.0.1:${TREZOR_UDP_PORT}}" - -echo "Trezor^emu profile name: ${TREZOR_PROFILE_NAME}" -echo "Trezor^emu profile directory: ${TREZOR_PROFILE_DIR}" -echo "Trezor^emu log file: ${TREZOR_LOGFILE}" -echo "Trezor^emu UDP port: ${TREZOR_UDP_PORT}" -echo "Trezor^emu path: ${TREZOR_PATH}" -echo "Trezor^emu src: ${TREZOR_SRC}" - -export TREZOR_PROFILE_NAME="${TREZOR_PROFILE_NAME}" -export TREZOR_PROFILE_DIR="${TREZOR_PROFILE_DIR}" -export TREZOR_LOGFILE="${TREZOR_LOGFILE}" -export TREZOR_UDP_PORT="${TREZOR_UDP_PORT}" -export TREZOR_PATH="${TREZOR_PATH}" -export TREZOR_SRC="${TREZOR_SRC}" - -ARGS="-O${PYOPT} -X heapsize=${HEAPSIZE}" From d28caf990e73bf5a71b21faafa859609e413407e Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 15:14:08 +0100 Subject: [PATCH 09/17] docs: update emulator documentation --- docs/core/build/emulator.md | 2 +- docs/core/emulator/index.md | 89 ++++++++++++++++++++++++++----------- docs/tests/device-tests.md | 5 +-- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/docs/core/build/emulator.md b/docs/core/build/emulator.md index 3ff68a0cc..1488b986b 100644 --- a/docs/core/build/emulator.md +++ b/docs/core/build/emulator.md @@ -59,7 +59,7 @@ pipenv run make build_unix Now you can start the emulator: ```sh -./emu.sh +./emu.py ``` The emulator has a number of interesting features all documented in the [Emulator](../emulator/index.md) section. diff --git a/docs/core/emulator/index.md b/docs/core/emulator/index.md index 773d3ca5e..b709d9e3c 100644 --- a/docs/core/emulator/index.md +++ b/docs/core/emulator/index.md @@ -11,73 +11,112 @@ Emulator significantly speeds up development and has several features to help yo ## How to run 1. [build](../build/emulator.md) the emulator -2. run `emu.sh` +2. run `emu.py` inside the pipenv environment: + - either enter `pipenv shell` first, and then use `./emu.py` + - or always use `pipenv run ./emu.py` 3. to use [bridge](https://github.com/trezor/trezord-go) with the emulator support, start it with `trezord -e 21324` Now you can use the emulator the same way as you use the device, for example you can visit our Wallet (https://wallet.trezor.io), use our Python CLI tool (`trezorctl`) etc. Simply click to emulate screen touches. ## Features -### Debug mode +Run `./emu.py --help` to see all supported command line options and shortcuts. The +sections below only list long option names and most notable features. -To allow debug link (to run tests), see exceptions and log output, run emulator with `PYOPT=0 ./emu.sh`. To properly distinguish the debug mode from production there is a tiny red square in the top right corner. The debug mode is obviously disabled on production firmwares. +### Debug and production mode + +By default the emulator runs in debug mode. Debuglink is available (on port 21325 by +default), exceptions and log output goes to console. To indicate debug mode, there is a +red square in the upper right corner of Trezor screen. ![emulator](emulator-debug.png) +To enable production mode, run `./emu.py --production`, or set environment variable `PYOPT=1`. + ### Initialize with mnemonic words -If the debug mode is enabled, you can load the device with any recovery seed directly from the console. This feature is otherwise disabled. To enter seed use `trezorctl`: +In debug mode, the emulator can be pre-configured with a mnemonic phrase. + +To use a specific mnemonic phrase: ```sh -trezorctl -m "your mnemonic words" +./emu.py --mnemonic "such deposit very security much theme..." ``` -or to use the "all all all" seed defined in [SLIP-14](https://github.com/satoshilabs/slips/blob/master/slip-0014.md): +When using Shamir shares, repeat the `--mnemonic` option: ```sh -trezorctl -s +./emu.py --mnemonic "your first share" --mnemonic "your second share" ... ``` -Shamir Backup is also supported: +To use the "all all all" seed defined in [SLIP-14](https://github.com/satoshilabs/slips/blob/master/slip-0014.md): ```sh -trezorctl -m "share 1 words" -m "share 2 words" +./emu.py --slip0014 ``` ### Storage and Profiles -Internal Trezor's storage is emulated and stored in the `/var/tmp/trezor.flash` file on default. Deleting this file is similar to calling _wipe device_. You can also find `/var/tmp/trezor.sdcard` for SD card and `/var/tmp/trezor.log`, which contains the communication log, the same as is in the emulator's stdout. +Internal Trezor's storage is emulated and stored in the `/var/tmp/trezor.flash` file on +default. Deleting this file is similar to calling _wipe device_. You can also find +`/var/tmp/trezor.sdcard` for SD card and `/var/tmp/trezor.log`, which contains the +communication log, the same as is in the emulator's stdout. -To run emulator with different files set the environment variable **TREZOR_PROFILE** like so: +You can specify a different location for the storage and log files via the `-p` / +`--profile` option: ```sh -TREZOR_PROFILE=foobar ./emu.sh +./emu.py -p foobar ``` -This will create a profile directory in your home ``` ~/.trezoremu/foobar``` containing emulator run files. Alternatively you can set a full path like so: +This will create a profile directory in your home `~/.trezoremu/foobar` containing +emulator run files. Alternatively you can set a full path like so: ```sh -TREZOR_PROFILE=/var/tmp/foobar ./emu.sh +./emu.py -p /var/tmp/foobar ``` -### Run in gdb +You can also set a full profile path to `TREZOR_PROFILE_DIR` environment variable. -Running `emu.sh` with `-d` runs emulator inside gdb/lldb. +Specifying `-t` / `--temporary-profile` will start the emulator in a clean temporary +profile that will be erased when the emulator stops. This is useful, e.g., for tests. -### Watch for file changes +### Running subcommands with the emulator -Running `emu.sh` with `-r` watches for file changes and reloads the emulator if any occur. Note that this does not do rebuild, i.e. this works for MicroPython code (which is interpreted) but if you make C changes, you need to rebuild your self. +In scripts, it is often necessary to start the emulator, run a commmand while it is +available, and then stop it. The following command runs the device test suite using the +emulator: -### Print screen +```sh +./emu.py --command pytest ../tests/device_tests +``` + +### Profiling support -Press `p` on your keyboard to capture emulator's screen. You will find a png screenshot in the `src` directory. +Run `./emu.py --profiling`, or set environment variable `TREZOR_PROFILING=1`, to run the +emulator with a profiling wrapper that generates statistics of executed lines. -### Environment Variables +### Memory statistics -#### Memory statistics +Run `./emu.py --log-memory`, or set environment variable `TREZOR_LOG_MEMORY=1`, to dump +memory usage information after each workflow task is finished. + +### Run in gdb + +Running `./emu.py --debugger` runs emulator inside gdb/lldb. + +### Watch for file changes + +Running `./emu.py --watch` watches for file changes and reloads the emulator if any +occur. Note that this does not do rebuild, i.e. this works for MicroPython code (which +is interpreted) but if you make C changes, you need to rebuild yourself. + +### Print screen -If ```TREZOR_LOG_MEMORY=1``` is set, the emulator prints memory usage information after each workflow task is finished. +Press `p` on your keyboard to capture emulator's screen. You will find a png screenshot +in the `src` directory. -#### Disable animations +### Disable animation -```TREZOR_DISABLE_ANIMATION=1``` disables fading and other animations, which speeds up the UI workflows significantly (useful for tests). This is also requirement for UI integration tests. +Run `./emu.py --disable-animation`, or set environment variable +`TREZOR_DISABLE_ANIMATION=1` to disable all animations. diff --git a/docs/tests/device-tests.md b/docs/tests/device-tests.md index f47e98d3b..c996d6169 100644 --- a/docs/tests/device-tests.md +++ b/docs/tests/device-tests.md @@ -25,10 +25,9 @@ environment: pipenv shell ``` -If you want to test against the emulator, run it in a separate terminal from the `core` -subdirectory: +If you want to test against the emulator, run it in a separate terminal: ```sh -PYOPT=0 ./emu.sh +./core/emu.py ``` Now you can run the test suite with `pytest` from the root directory: From 32b269ad432d19ffd5f5a26b0a33cdf48b19c031 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 15:42:41 +0100 Subject: [PATCH 10/17] ci: fix path for core-bitcoinonly test --- ci/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test.yml b/ci/test.yml index 107c80c42..38dc30d84 100644 --- a/ci/test.yml +++ b/ci/test.yml @@ -92,7 +92,7 @@ core unix btconly device test: dependencies: - core unix frozen btconly build variables: - MICROPYTHON: "../build/unix/micropython-bitcoinonly" + MICROPYTHON: "build/unix/micropython-bitcoinonly" TREZOR_PYTEST_SKIP_ALTCOINS: 1 script: - cd core From 6cf48bf48596f2752ef2aa78a49e86cadc207523 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 16 Jan 2020 17:17:41 +0100 Subject: [PATCH 11/17] ci: use explicit trezor.log location --- ci/test.yml | 21 +++++++-------------- core/Makefile | 6 ++++-- core/tests/run_tests_device_emu_monero.sh | 6 +++++- docs/core/emulator/index.md | 9 +++++++-- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/ci/test.yml b/ci/test.yml index 38dc30d84..cd26accaa 100644 --- a/ci/test.yml +++ b/ci/test.yml @@ -46,16 +46,15 @@ core unix device ui test: script: - cd core - pipenv run make test_emu_ui - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} - cd ../ci - pipenv run python prepare_ui_artifacts.py artifacts: name: core-unix-device-ui-test paths: - - trezor.log - ci/ui_test_records/ - tests/ui_tests/reports/ - tests/junit.xml + - tests/trezor.log when: always expire_in: 1 week reports: @@ -71,14 +70,13 @@ core unix device test: script: - cd core - pipenv run make test_emu - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} - sync - sleep 1 - mv ./src/.coverage .coverage.test_emu artifacts: name: core-unix-device-test paths: - - trezor.log + - tests/trezor.log - tests/junit.xml - core/.coverage.* expire_in: 1 week @@ -97,11 +95,10 @@ core unix btconly device test: script: - cd core - pipenv run make test_emu - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} artifacts: name: core-unix-btconly-device-test paths: - - trezor.log + - tests/trezor.log - tests/junit.xml expire_in: 1 week when: always @@ -118,14 +115,13 @@ core unix monero test: script: - cd core - pipenv run make test_emu_monero - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} - sync - sleep 1 - mv ./src/.coverage .coverage.test_emu_monero artifacts: name: core-unix-monero-test paths: - - trezor.log + - tests/trezor.log - core/.coverage.* expire_in: 1 week when: always @@ -141,14 +137,13 @@ core unix u2f test: - make -C tests/fido_tests/u2f-tests-hid - cd core - pipenv run make test_emu_u2f - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} - sync - sleep 1 - mv ./src/.coverage .coverage.test_emu_u2f artifacts: name: core-unix-u2f-test paths: - - trezor.log + - tests/trezor.log - core/.coverage.* expire_in: 1 week when: always @@ -163,14 +158,13 @@ core unix fido2 test: script: - cd core - pipenv run make test_emu_fido2 - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} - sync - sleep 1 - mv ./src/.coverage .coverage.test_emu_fido2 artifacts: name: core-unix-fido2-test paths: - - trezor.log + - tests/trezor.log - tests/junit.xml - core/.coverage.* expire_in: 1 week @@ -186,11 +180,10 @@ core unix click test: script: - cd core - pipenv run make test_emu_click - - cp /var/tmp/trezor.log ${CI_PROJECT_DIR} artifacts: name: core-unix-click-test paths: - - trezor.log + - tests/trezor.log - tests/junit.xml reports: junit: tests/junit.xml diff --git a/core/Makefile b/core/Makefile index cb386a024..84b9cf7d6 100644 --- a/core/Makefile +++ b/core/Makefile @@ -38,11 +38,13 @@ FIRMWARE_MAXSIZE = 1703936 GITREV=$(shell git describe --always --dirty | tr '-' '_') CFLAGS += -DGITREV=$(GITREV) +TESTPATH = $(CURDIR)/../tests + EMU = $(CURDIR)/emu.py -EMU_TEST_ARGS = --disable-animation --headless --quiet --temporary-profile +EMU_LOG_FILE ?= $(TESTPATH)/trezor.log +EMU_TEST_ARGS = --disable-animation --headless --output=$(EMU_LOG_FILE) --temporary-profile EMU_TEST = $(EMU) $(EMU_TEST_ARGS) -c -TESTPATH = $(CURDIR)/../tests JUNIT_XML ?= $(TESTPATH)/junit.xml PYTEST = pytest --junitxml=$(JUNIT_XML) TREZOR_FIDO2_UDP_PORT = 21326 diff --git a/core/tests/run_tests_device_emu_monero.sh b/core/tests/run_tests_device_emu_monero.sh index 93999b424..fd22890f7 100755 --- a/core/tests/run_tests_device_emu_monero.sh +++ b/core/tests/run_tests_device_emu_monero.sh @@ -10,7 +10,11 @@ upy_pid="" # run emulator if RUN_TEST_EMU if [[ $RUN_TEST_EMU > 0 ]]; then - ../emu.py --disable-animation --temporary-profile --quiet --headless & + ../emu.py \ + --disable-animation \ + --temporary-profile \ + --headless \ + --output=../../tests/trezor.log & upy_pid=$! trezorctl -v wait-for-emulator fi diff --git a/docs/core/emulator/index.md b/docs/core/emulator/index.md index b709d9e3c..236fc9f8a 100644 --- a/docs/core/emulator/index.md +++ b/docs/core/emulator/index.md @@ -59,8 +59,7 @@ To use the "all all all" seed defined in [SLIP-14](https://github.com/satoshilab Internal Trezor's storage is emulated and stored in the `/var/tmp/trezor.flash` file on default. Deleting this file is similar to calling _wipe device_. You can also find -`/var/tmp/trezor.sdcard` for SD card and `/var/tmp/trezor.log`, which contains the -communication log, the same as is in the emulator's stdout. +`/var/tmp/trezor.sdcard` for SD card. You can specify a different location for the storage and log files via the `-p` / `--profile` option: @@ -81,6 +80,12 @@ You can also set a full profile path to `TREZOR_PROFILE_DIR` environment variabl Specifying `-t` / `--temporary-profile` will start the emulator in a clean temporary profile that will be erased when the emulator stops. This is useful, e.g., for tests. +### Logging + +By default, emulator output goes to stdout. When silenced with `--quiet`, it is +redirected to `${TREZOR_PROFILE_DIR}/trezor.log`. You can specify an alternate output +file with `--output`. + ### Running subcommands with the emulator In scripts, it is often necessary to start the emulator, run a commmand while it is From e2f71a1acc98850e241520a53f18fa8bbf0405f1 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 17 Jan 2020 15:46:59 +0100 Subject: [PATCH 12/17] ci: use frozen debug builds for emulator tests --- ci/build.yml | 9 ++++++++- ci/test.yml | 14 +++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ci/build.yml b/ci/build.yml index d6ff06f30..3652961fa 100644 --- a/ci/build.yml +++ b/ci/build.yml @@ -93,6 +93,12 @@ core unix regular build: script: - cd core - pipenv run make build_unix + artifacts: + name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA" + paths: + - core/build/unix/micropython + - core/src/trezor/res/resources.py + expire_in: 1 week core unix frozen regular build: stage: build @@ -107,10 +113,11 @@ core unix frozen regular build: - core/src/trezor/res/resources.py expire_in: 1 week -core unix frozen btconly build: +core unix frozen btconly debug build: stage: build <<: *only_changes_core variables: + PYOPT: "0" BITCOIN_ONLY: "1" script: - cd core diff --git a/ci/test.yml b/ci/test.yml index cd26accaa..64e7ce0b7 100644 --- a/ci/test.yml +++ b/ci/test.yml @@ -33,7 +33,7 @@ core unix unit test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix regular build script: - cd core - pipenv run make test @@ -42,7 +42,7 @@ core unix device ui test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix frozen debug build script: - cd core - pipenv run make test_emu_ui @@ -64,7 +64,7 @@ core unix device test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix frozen debug build variables: TREZOR_PROFILING: 1 script: @@ -88,7 +88,7 @@ core unix btconly device test: stage: test <<: *only_changes_core dependencies: - - core unix frozen btconly build + - core unix frozen btconly debug build variables: MICROPYTHON: "build/unix/micropython-bitcoinonly" TREZOR_PYTEST_SKIP_ALTCOINS: 1 @@ -109,7 +109,7 @@ core unix monero test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix frozen debug build variables: TREZOR_PROFILING: 1 script: @@ -130,7 +130,7 @@ core unix u2f test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix frozen debug build variables: TREZOR_PROFILING: 1 script: @@ -152,7 +152,7 @@ core unix fido2 test: stage: test <<: *only_changes_core dependencies: - - core unix frozen regular build + - core unix frozen debug build variables: TREZOR_PROFILING: 1 script: From e2fd2c35ffbda92f5ff3804a709264c9fa1b4a12 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 17 Jan 2020 16:21:12 +0100 Subject: [PATCH 13/17] core: modify profiling wrapper to work with frozen builds --- core/prof/prof.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/prof/prof.py b/core/prof/prof.py index fcb13017c..6839fe000 100644 --- a/core/prof/prof.py +++ b/core/prof/prof.py @@ -1,10 +1,10 @@ import sys -import uos from uio import open -sys.path.insert(0, uos.getenv("TREZOR_SRC")) -del uos +# We need to insert "" to sys.path so that the frozen build can import main from the +# frozen modules, and regular build can import it from current directory. +sys.path.insert(0, "") class Coverage: From 34332cc294b7d4dda417825d189ed1c25c1d5737 Mon Sep 17 00:00:00 2001 From: matejcik Date: Fri, 17 Jan 2020 16:46:42 +0100 Subject: [PATCH 14/17] ci: do not store resources for frozen builds --- ci/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci/build.yml b/ci/build.yml index 3652961fa..52fca1292 100644 --- a/ci/build.yml +++ b/ci/build.yml @@ -110,7 +110,6 @@ core unix frozen regular build: name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA" paths: - core/build/unix/micropython - - core/src/trezor/res/resources.py expire_in: 1 week core unix frozen btconly debug build: @@ -127,7 +126,6 @@ core unix frozen btconly debug build: name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA" paths: - core/build/unix/micropython-bitcoinonly - - core/src/trezor/res/resources.py expire_in: 1 week core unix frozen debug build: From a3d309eca28e8f96018c9b4d9b0e5f27e1dfec84 Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 21 Jan 2020 14:25:54 +0100 Subject: [PATCH 15/17] core/prof: make sure coverage data is generated with absolute paths --- core/emu.py | 1 + core/prof/prof.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/emu.py b/core/emu.py index a227bf374..95432b8be 100755 --- a/core/emu.py +++ b/core/emu.py @@ -217,6 +217,7 @@ def cli( TREZOR_PROFILE_DIR=str(profile_dir.resolve()), TREZOR_UDP_PORT=str(emulator.port), TREZOR_FIDO2_UDP_PORT=str(emulator.port + 2), + TREZOR_SRC=str(SRC_DIR), ) os.environ.update(emulator_env) for k, v in emulator_env.items(): diff --git a/core/prof/prof.py b/core/prof/prof.py index 6839fe000..75703ed05 100644 --- a/core/prof/prof.py +++ b/core/prof/prof.py @@ -1,11 +1,14 @@ import sys from uio import open +from uos import getenv # We need to insert "" to sys.path so that the frozen build can import main from the # frozen modules, and regular build can import it from current directory. sys.path.insert(0, "") +PATH_PREFIX = (getenv("TREZOR_SRC") or ".") + "/" + class Coverage: def __init__(self): @@ -22,7 +25,7 @@ class Coverage: this_file = globals()["__file__"] for filename in self.__files: if not filename == this_file: - lines[filename] = list(self.__files[filename]) + lines[PATH_PREFIX + filename] = list(self.__files[filename]) return lines_execution From 0496e49507e6afc4ceba030374d5cc6ff38c167e Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 21 Jan 2020 15:24:54 +0100 Subject: [PATCH 16/17] core/tests: fix monero runner script --- core/tests/run_tests_device_emu_monero.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/tests/run_tests_device_emu_monero.sh b/core/tests/run_tests_device_emu_monero.sh index fd22890f7..2071fe1eb 100755 --- a/core/tests/run_tests_device_emu_monero.sh +++ b/core/tests/run_tests_device_emu_monero.sh @@ -10,13 +10,17 @@ upy_pid="" # run emulator if RUN_TEST_EMU if [[ $RUN_TEST_EMU > 0 ]]; then + t=$(mktemp) ../emu.py \ --disable-animation \ --temporary-profile \ --headless \ - --output=../../tests/trezor.log & - upy_pid=$! - trezorctl -v wait-for-emulator + --output=../../tests/trezor.log \ + > $t & + trezorctl wait-for-emulator + source $t + upy_pid=$(cat $TREZOR_PROFILE_DIR/trezor.pid) + rm $t fi DOCKER_ID="" @@ -24,7 +28,7 @@ DOCKER_ID="" # Test termination trap terminate_test() { if [[ $# > 0 ]]; then error=$1; fi - if [ -n "$upy_pid" ]; then kill -- -$upy_pid 2> /dev/null; fi + if [ -n "$upy_pid" ]; then kill $upy_pid 2> /dev/null; fi if [ -n "$DOCKER_ID" ]; then docker kill $DOCKER_ID 2>/dev/null >/dev/null; fi exit $error } From 25910acdd19ef786ade682b6117f79c1b32e3a78 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 23 Jan 2020 18:41:25 +0100 Subject: [PATCH 17/17] tests: make use of new emulator code in emulator tests --- tests/emulators.py | 159 +++++------------- .../test_shamir_persistence.py | 5 +- tests/upgrade_tests/__init__.py | 15 +- tests/upgrade_tests/test_firmware_upgrades.py | 12 +- 4 files changed, 52 insertions(+), 139 deletions(-) diff --git a/tests/emulators.py b/tests/emulators.py index 71ee6cf73..c1df8cb12 100644 --- a/tests/emulators.py +++ b/tests/emulators.py @@ -15,23 +15,22 @@ # If not, see . import gzip -import os -import subprocess import tempfile -import time from collections import defaultdict +from pathlib import Path -from trezorlib.debuglink import TrezorClientDebugLink -from trezorlib.transport.udp import UdpTransport +from trezorlib._internal.emulator import CoreEmulator, LegacyEmulator + +ROOT = Path(__file__).parent.parent.resolve() +BINDIR = ROOT / "tests" / "emulators" -ROOT = os.path.abspath(os.path.dirname(__file__) + "/..") -BINDIR = ROOT + "/tests/emulators" LOCAL_BUILD_PATHS = { - "core": ROOT + "/core/build/unix/micropython", - "legacy": ROOT + "/legacy/firmware/trezor.elf", + "core": ROOT / "core" / "build" / "unix" / "micropython", + "legacy": ROOT / "legacy" / "firmware" / "trezor.elf", } -SD_CARD_GZ = ROOT + "/tests/trezor.sdcard.gz" +CORE_SRC_DIR = ROOT / "core" / "src" +SD_CARD_GZ = ROOT / "core" / "trezor.sdcard.gz" ENV = {"SDL_VIDEODRIVER": "dummy"} @@ -44,11 +43,11 @@ def check_version(tag, version_tuple): def filename_from_tag(gen, tag): - return f"{BINDIR}/trezor-emu-{gen}-{tag}" + return BINDIR / f"trezor-emu-{gen}-{tag}" def get_tags(): - files = os.listdir(BINDIR) + files = list(BINDIR.iterdir()) if not files: raise ValueError( "No files found. Use download_emulators.sh to download emulators." @@ -58,7 +57,7 @@ def get_tags(): for f in sorted(files): try: # example: "trezor-emu-core-v2.1.1" - _, _, gen, tag = f.split("-", maxsplit=3) + _, _, gen, tag = f.name.split("-", maxsplit=3) result[gen].append(tag) except ValueError: pass @@ -69,116 +68,40 @@ ALL_TAGS = get_tags() class EmulatorWrapper: - def __init__(self, gen, tag=None, executable=None, storage=None): - self.gen = gen - self.tag = tag - - if executable is not None: - self.executable = executable - elif tag is not None: - self.executable = filename_from_tag(gen, tag) - else: - self.executable = LOCAL_BUILD_PATHS[gen] - - if not os.path.exists(self.executable): - raise ValueError(f"emulator executable not found: {self.executable}") - - self.workdir = tempfile.TemporaryDirectory() - if storage: - open(self._storage_file(), "wb").write(storage) - - with gzip.open(SD_CARD_GZ, "rb") as gz: - with open(self.workdir.name + "/trezor.sdcard", "wb") as sd: - sd.write(gz.read()) - - self.client = None - - def _get_params_core(self): - env = ENV.copy() - args = [self.executable, "-m", "main"] - # for firmware 2.1.2 and newer - env["TREZOR_PROFILE_DIR"] = self.workdir.name - # for firmware 2.1.1 and older - env["TREZOR_PROFILE"] = self.workdir.name - - if self.executable == LOCAL_BUILD_PATHS["core"]: - cwd = ROOT + "/core/src" + def __init__(self, gen, tag=None, storage=None): + if tag is not None: + executable = filename_from_tag(gen, tag) else: - cwd = self.workdir.name + executable = LOCAL_BUILD_PATHS[gen] - return env, args, cwd + if not executable.exists(): + raise ValueError(f"emulator executable not found: {executable}") - def _get_params_legacy(self): - env = ENV.copy() - args = [self.executable] - cwd = self.workdir.name - return env, args, cwd - - def _get_params(self): - if self.gen == "core": - return self._get_params_core() - elif self.gen == "legacy": - return self._get_params_legacy() + self.profile_dir = tempfile.TemporaryDirectory() + if executable == LOCAL_BUILD_PATHS["core"]: + workdir = CORE_SRC_DIR else: - raise ValueError("Unknown gen") - - def start(self): - env, args, cwd = self._get_params() - self.process = subprocess.Popen( - args, cwd=cwd, env=env, stdout=open(os.devnull, "w") - ) - - # wait until emulator is listening - transport = UdpTransport("127.0.0.1:21324") - transport.open() - for _ in range(300): - if transport._ping(): - break - if self.process.poll() is not None: - self._cleanup() - raise RuntimeError("Emulator proces died") - time.sleep(0.1) - else: - # could not connect after 300 attempts * 0.1s = 30s of waiting - self._cleanup() - raise RuntimeError("Can't connect to emulator") - transport.close() - - self.client = TrezorClientDebugLink(transport) - self.client.open() - check_version(self.tag, self.client.version) - - def stop(self): - if self.client: - self.client.close() - self.process.terminate() - try: - self.process.wait(1) - except subprocess.TimeoutExpired: - self.process.kill() - - def restart(self): - self.stop() - self.start() + workdir = None + + if gen == "legacy": + self.emulator = LegacyEmulator( + executable, self.profile_dir.name, storage=storage, headless=True, + ) + elif gen == "core": + with gzip.open(SD_CARD_GZ, "rb") as gz: + self.emulator = CoreEmulator( + executable, + self.profile_dir.name, + storage=storage, + workdir=workdir, + sdcard=gz.read(), + headless=True, + ) def __enter__(self): - self.start() - return self + self.emulator.start() + return self.emulator def __exit__(self, exc_type, exc_value, traceback): - self._cleanup() - - def _cleanup(self): - self.stop() - self.workdir.cleanup() - - def _storage_file(self): - if self.gen == "legacy": - return self.workdir.name + "/emulator.img" - elif self.gen == "core": - return self.workdir.name + "/trezor.flash" - else: - raise ValueError("Unknown gen") - - def storage(self): - return open(self._storage_file(), "rb").read() + self.emulator.stop() + self.profile_dir.cleanup() diff --git a/tests/persistence_tests/test_shamir_persistence.py b/tests/persistence_tests/test_shamir_persistence.py index 33a6f8e4d..7118ebc7c 100644 --- a/tests/persistence_tests/test_shamir_persistence.py +++ b/tests/persistence_tests/test_shamir_persistence.py @@ -28,12 +28,11 @@ from ..upgrade_tests import core_only @pytest.fixture def emulator(): - emu = EmulatorWrapper("core") - with emu: + with EmulatorWrapper("core") as emu: yield emu -def _restart(device_handler: BackgroundDeviceHandler, emulator: EmulatorWrapper): +def _restart(device_handler, emulator): device_handler.restart(emulator) return device_handler.debuglink() diff --git a/tests/upgrade_tests/__init__.py b/tests/upgrade_tests/__init__.py index efeb28409..781b5720a 100644 --- a/tests/upgrade_tests/__init__.py +++ b/tests/upgrade_tests/__init__.py @@ -2,7 +2,7 @@ import os import pytest -from ..emulators import EmulatorWrapper +from ..emulators import LOCAL_BUILD_PATHS SELECTED_GENS = [ gen.strip() for gen in os.environ.get("TREZOR_UPGRADE_TEST", "").split(",") if gen @@ -15,17 +15,8 @@ if SELECTED_GENS: else: # if no selection was provided, select those for which we have emulators - try: - EmulatorWrapper("legacy") - LEGACY_ENABLED = True - except Exception: - LEGACY_ENABLED = False - - try: - EmulatorWrapper("core") - CORE_ENABLED = True - except Exception: - CORE_ENABLED = False + LEGACY_ENABLED = LOCAL_BUILD_PATHS["legacy"].exists() + CORE_ENABLED = LOCAL_BUILD_PATHS["core"].exists() legacy_only = pytest.mark.skipif( diff --git a/tests/upgrade_tests/test_firmware_upgrades.py b/tests/upgrade_tests/test_firmware_upgrades.py index ff7ede598..bfd1f9457 100644 --- a/tests/upgrade_tests/test_firmware_upgrades.py +++ b/tests/upgrade_tests/test_firmware_upgrades.py @@ -96,7 +96,7 @@ def test_upgrade_load(gen, from_tag, to_tag): ) device_id = emu.client.features.device_id asserts(from_tag, emu.client) - storage = emu.storage() + storage = emu.get_storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id @@ -128,7 +128,7 @@ def test_upgrade_reset(gen, from_tag, to_tag): device_id = emu.client.features.device_id asserts(from_tag, emu.client) address = btc.get_address(emu.client, "Bitcoin", PATH) - storage = emu.storage() + storage = emu.get_storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id @@ -162,7 +162,7 @@ def test_upgrade_reset_skip_backup(gen, from_tag, to_tag): device_id = emu.client.features.device_id asserts(from_tag, emu.client) address = btc.get_address(emu.client, "Bitcoin", PATH) - storage = emu.storage() + storage = emu.get_storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id @@ -196,7 +196,7 @@ def test_upgrade_reset_no_backup(gen, from_tag, to_tag): device_id = emu.client.features.device_id asserts(from_tag, emu.client) address = btc.get_address(emu.client, "Bitcoin", PATH) - storage = emu.storage() + storage = emu.get_storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id @@ -222,7 +222,7 @@ def test_upgrade_shamir_recovery(gen, from_tag, to_tag): assert "2 more shares" in layout.text device_id = emu.client.features.device_id - storage = emu.storage() + storage = emu.get_storage() device_handler.check_finalize() with EmulatorWrapper(gen, to_tag, storage=storage) as emu, BackgroundDeviceHandler( @@ -258,7 +258,7 @@ def test_upgrade_u2f(gen, from_tag, to_tag): counter = fido.get_next_counter(emu.client) assert counter == 11 - storage = emu.storage() + storage = emu.get_storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: counter = fido.get_next_counter(emu.client)