1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28:07 +00:00

feat(tests): support UI testing for persistence tests

Added new global `emulator_core` fixture that supports UI recording.

[no changelog]
This commit is contained in:
grdddj 2023-03-30 12:31:09 +02:00 committed by Jiří Musil
parent 923b1c42b0
commit b6ce90dc73
4 changed files with 78 additions and 80 deletions

View File

@ -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

View File

@ -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

View File

@ -14,10 +14,6 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
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

View File

@ -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