diff --git a/tests/conftest.py b/tests/conftest.py index 7aeaba179..61dc6bb27 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,7 +18,7 @@ from __future__ import annotations import os from pathlib import Path -from typing import TYPE_CHECKING, Generator +from typing import TYPE_CHECKING, Generator, Iterator import pytest import xdist @@ -46,6 +46,28 @@ HERE = Path(__file__).resolve().parent pytest.register_assert_rewrite("tests.common") +def _emulator_wrapper_main_args() -> list[str]: + """Look at TREZOR_PROFILING env variable, so that we can generate coverage reports.""" + do_profiling = os.environ.get("TREZOR_PROFILING") == "1" + if do_profiling: + core_dir = HERE.parent / "core" + profiling_wrapper = core_dir / "prof" / "prof.py" + # So that the coverage reports have the correct paths + os.environ["TREZOR_SRC"] = str(core_dir / "src") + return [str(profiling_wrapper)] + else: + return ["-m", "main"] + + +@pytest.fixture +def core_emulator(request: pytest.FixtureRequest) -> Iterator[Emulator]: + """Fixture returning default core emulator with possibility of screen recording.""" + with EmulatorWrapper("core", main_args=_emulator_wrapper_main_args()) as emu: + # Modifying emu.client to add screen recording (when --ui=test is used) + with ui_tests.screen_recording(emu.client, request) as _: + yield emu + + @pytest.fixture(scope="session") def emulator(request: pytest.FixtureRequest) -> Generator["Emulator", None, None]: """Fixture for getting emulator connection in case tests should operate it on their own. @@ -88,23 +110,12 @@ def emulator(request: pytest.FixtureRequest) -> Generator["Emulator", None, None # 1. normal link, 2. debug link and 3. webauthn fake interface return 20000 + int(worker_id[2:]) * 3 - # So that we can generate coverage reports - profiling = os.environ.get("TREZOR_PROFILING") == "1" - if profiling: - core_dir = HERE.parent / "core" - profiling_wrapper = core_dir / "prof" / "prof.py" - main_args = [str(profiling_wrapper)] - # So that the coverage reports have the correct paths - os.environ["TREZOR_SRC"] = str(core_dir / "src") - else: - main_args = ["-m", "main"] - with EmulatorWrapper( model, port=_get_port(), headless=True, auto_interact=not interact, - main_args=main_args, + main_args=_emulator_wrapper_main_args(), ) as emu: yield emu diff --git a/tests/persistence_tests/test_safety_checks.py b/tests/persistence_tests/test_safety_checks.py index 9d8c0a54a..1cbf7d755 100644 --- a/tests/persistence_tests/test_safety_checks.py +++ b/tests/persistence_tests/test_safety_checks.py @@ -1,21 +1,13 @@ -from typing import Iterator - import pytest from trezorlib import debuglink, device from trezorlib.messages import SafetyCheckLevel from ..common import MNEMONIC12 -from ..emulators import Emulator, EmulatorWrapper +from ..emulators import Emulator from ..upgrade_tests import core_only -@pytest.fixture -def emulator() -> Iterator[Emulator]: - with EmulatorWrapper("core") as emu: - yield emu - - @core_only @pytest.mark.parametrize( "set_level,after_level", @@ -26,20 +18,20 @@ def emulator() -> Iterator[Emulator]: ], ) def test_safety_checks_level_after_reboot( - emulator: Emulator, set_level: SafetyCheckLevel, after_level: SafetyCheckLevel + core_emulator: Emulator, set_level: SafetyCheckLevel, after_level: SafetyCheckLevel ): - device.wipe(emulator.client) + device.wipe(core_emulator.client) debuglink.load_device( - emulator.client, + core_emulator.client, mnemonic=MNEMONIC12, pin="", passphrase_protection=False, label="SAFETYLEVEL", ) - device.apply_settings(emulator.client, safety_checks=set_level) - assert emulator.client.features.safety_checks == set_level + device.apply_settings(core_emulator.client, safety_checks=set_level) + assert core_emulator.client.features.safety_checks == set_level - emulator.restart() + core_emulator.restart() - assert emulator.client.features.safety_checks == after_level + assert core_emulator.client.features.safety_checks == after_level diff --git a/tests/persistence_tests/test_shamir_persistence.py b/tests/persistence_tests/test_shamir_persistence.py index 0944bc3a0..ac408e909 100644 --- a/tests/persistence_tests/test_shamir_persistence.py +++ b/tests/persistence_tests/test_shamir_persistence.py @@ -14,10 +14,6 @@ # You should have received a copy of the License along with this library. # If not, see . -from typing import Iterator - -import pytest - from trezorlib import device from trezorlib.debuglink import DebugLink @@ -25,24 +21,20 @@ from .. import buttons from ..click_tests import recovery from ..common import MNEMONIC_SLIP39_ADVANCED_20, MNEMONIC_SLIP39_BASIC_20_3of6 from ..device_handler import BackgroundDeviceHandler -from ..emulators import Emulator, EmulatorWrapper +from ..emulators import Emulator from ..upgrade_tests import core_only -@pytest.fixture -def emulator() -> Iterator[Emulator]: - with EmulatorWrapper("core") as emu: - yield emu - - -def _restart(device_handler: BackgroundDeviceHandler, emulator: Emulator): - device_handler.restart(emulator) +def _restart( + device_handler: BackgroundDeviceHandler, core_emulator: Emulator +) -> DebugLink: + device_handler.restart(core_emulator) return device_handler.debuglink() @core_only -def test_abort(emulator: Emulator): - device_handler = BackgroundDeviceHandler(emulator.client) +def test_abort(core_emulator: Emulator): + device_handler = BackgroundDeviceHandler(core_emulator.client) debug = device_handler.debuglink() features = device_handler.features() @@ -55,8 +47,7 @@ def test_abort(emulator: Emulator): layout = debug.click(buttons.OK, wait=True) assert "Select number of words" in layout.get_content() - device_handler.restart(emulator) - debug = device_handler.debuglink() + debug = _restart(device_handler, core_emulator) features = device_handler.features() assert features.recovery_mode is True @@ -75,8 +66,8 @@ def test_abort(emulator: Emulator): @core_only -def test_recovery_single_reset(emulator: Emulator): - device_handler = BackgroundDeviceHandler(emulator.client) +def test_recovery_single_reset(core_emulator: Emulator): + device_handler = BackgroundDeviceHandler(core_emulator.client) debug = device_handler.debuglink() features = device_handler.features() @@ -88,7 +79,7 @@ def test_recovery_single_reset(emulator: Emulator): recovery.select_number_of_words(debug) - debug = _restart(device_handler, emulator) + debug = _restart(device_handler, core_emulator) features = device_handler.features() assert features.recovery_mode is True @@ -103,7 +94,7 @@ def test_recovery_single_reset(emulator: Emulator): @core_only -def test_recovery_on_old_wallet(emulator: Emulator): +def test_recovery_on_old_wallet(core_emulator: Emulator): """Check that the recovery workflow started on a disconnected device can survive handling by the old Wallet. @@ -112,7 +103,7 @@ def test_recovery_on_old_wallet(emulator: Emulator): Initialize+GetFeatures). At minimum, these two messages must not interrupt the running recovery. """ - device_handler = BackgroundDeviceHandler(emulator.client) + device_handler = BackgroundDeviceHandler(core_emulator.client) debug = device_handler.debuglink() features = device_handler.features() @@ -124,7 +115,7 @@ def test_recovery_on_old_wallet(emulator: Emulator): recovery.confirm_recovery(debug) # restart to get into stand-alone recovery - debug = _restart(device_handler, emulator) + debug = _restart(device_handler, core_emulator) features = device_handler.features() assert features.recovery_mode is True @@ -171,7 +162,7 @@ def test_recovery_on_old_wallet(emulator: Emulator): @core_only -def test_recovery_multiple_resets(emulator: Emulator): +def test_recovery_multiple_resets(core_emulator: Emulator): def enter_shares_with_restarts(debug: DebugLink) -> None: shares = MNEMONIC_SLIP39_ADVANCED_20 layout = debug.read_layout() @@ -182,11 +173,11 @@ def test_recovery_multiple_resets(emulator: Emulator): layout = recovery.enter_share(debug, share) remaining -= 1 expected_text = "You have entered" - debug = _restart(device_handler, emulator) + debug = _restart(device_handler, core_emulator) assert "You have successfully recovered your wallet" in layout.get_content() - device_handler = BackgroundDeviceHandler(emulator.client) + device_handler = BackgroundDeviceHandler(core_emulator.client) debug = device_handler.debuglink() features = device_handler.features() @@ -201,7 +192,7 @@ def test_recovery_multiple_resets(emulator: Emulator): recovery.select_number_of_words(debug) # restart - debug = _restart(device_handler, emulator) + debug = _restart(device_handler, core_emulator) features = device_handler.features() assert features.recovery_mode is True diff --git a/tests/persistence_tests/test_wipe_code.py b/tests/persistence_tests/test_wipe_code.py index 709eff37b..62daa1bcc 100644 --- a/tests/persistence_tests/test_wipe_code.py +++ b/tests/persistence_tests/test_wipe_code.py @@ -2,7 +2,7 @@ from trezorlib import debuglink, device, messages from trezorlib.debuglink import TrezorClientDebugLink as Client from ..common import MNEMONIC12 -from ..emulators import EmulatorWrapper +from ..emulators import Emulator, EmulatorWrapper from ..upgrade_tests import core_only, legacy_only PIN = "1234" @@ -48,34 +48,38 @@ def setup_device_core(client: Client, pin: str, wipe_code: str) -> None: @core_only -def test_wipe_code_activate_core(): - with EmulatorWrapper("core") as emu: - # set up device - setup_device_core(emu.client, PIN, WIPE_CODE) +def test_wipe_code_activate_core(core_emulator: Emulator): + # set up device + setup_device_core(core_emulator.client, PIN, WIPE_CODE) - emu.client.init_device() - device_id = emu.client.features.device_id + core_emulator.client.init_device() + device_id = core_emulator.client.features.device_id - # Initiate Change pin process - ret = emu.client.call_raw(messages.ChangePin(remove=False)) - assert isinstance(ret, messages.ButtonRequest) - emu.client.debug.press_yes() - ret = emu.client.call_raw(messages.ButtonAck()) + # Initiate Change pin process + ret = core_emulator.client.call_raw(messages.ChangePin(remove=False)) + assert isinstance(ret, messages.ButtonRequest) + core_emulator.client.debug.press_yes() + ret = core_emulator.client.call_raw(messages.ButtonAck()) - # Enter the wipe code instead of the current PIN - assert ret == messages.ButtonRequest(code=messages.ButtonRequestType.PinEntry) - emu.client._raw_write(messages.ButtonAck()) - emu.client.debug.input(WIPE_CODE) + # Enter the wipe code instead of the current PIN + assert ret == messages.ButtonRequest(code=messages.ButtonRequestType.PinEntry) + core_emulator.client._raw_write(messages.ButtonAck()) + core_emulator.client.debug.input(WIPE_CODE) - # wait 30 seconds for emulator to shut down - # this will raise a TimeoutError if the emulator doesn't die. - emu.wait(30) + # preserving screenshots even after it dies and starts again + prev_screenshot_dir = core_emulator.client.debug.screenshot_recording_dir - emu.start() - assert emu.client.features.initialized is False - assert emu.client.features.pin_protection is False - assert emu.client.features.wipe_code_protection is False - assert emu.client.features.device_id != device_id + # wait 30 seconds for emulator to shut down + # this will raise a TimeoutError if the emulator doesn't die. + core_emulator.wait(30) + + core_emulator.start() + if prev_screenshot_dir: + core_emulator.client.debug.start_recording(prev_screenshot_dir, refresh_index=1) + assert core_emulator.client.features.initialized is False + assert core_emulator.client.features.pin_protection is False + assert core_emulator.client.features.wipe_code_protection is False + assert core_emulator.client.features.device_id != device_id @legacy_only