What changed, and why it matters
This commit only changes the test suite and supporting Python tooling. It renames a model set from TREZORS to ALL_MODELS, splits devices into legacy and core groups, and updates upgrade tests so they can run against individual Trezor models rather than just broad 'legacy' or 'core' categories. There is no change to the firmware that runs on the hardware wallet, no fix for a security bug, and no new attack path.
No security action required. Treat as normal test-maintenance commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is a refactoring of trezor-firmware’s testing infrastructure. Key changes: models.py replaces TREZORS with LEGACY_MODELS/CORE_MODELS/ALL_MODELS; conftest.py, github.py, and webusb.py consume the new constants; tests/emulators.py and tests/download_emulators.py now organize emulator binaries by model internal name and pass a model argument to EmulatorWrapper; tests/upgrade_tests/init.py parametrizes upgrade tests by (gen, tag, model). No runtime firmware code is modified, no cryptographic or protocol behavior changes, and no vulnerability is patched.
Changed components
tests/conftest.pytests/download_emulators.pytests/emulators.pytests/github.pytests/upgrade_tests/__init__.pytests/upgrade_tests/test_firmware_upgrades.pytests/upgrade_tests/test_passphrase_consistency.pypython/src/trezorlib/models.pypython/src/trezorlib/transport/webusb.pyInspect captured patch +146 / −74
diff --git a/python/src/trezorlib/models.py b/python/src/trezorlib/models.py
index 4f8c245b..48dfb05e 100644
--- a/python/src/trezorlib/models.py
+++ b/python/src/trezorlib/models.py
@@ -127,7 +127,9 @@ TREZOR_SAFE5 = T3T1
TREZOR_DISC1 = DISC1
TREZOR_DISC2 = DISC2
-TREZORS = frozenset({T1B1, T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
+LEGACY_MODELS = frozenset({T1B1})
+CORE_MODELS = frozenset({T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
+ALL_MODELS = LEGACY_MODELS | CORE_MODELS
def by_name(name: str | None) -> TrezorModel | None:
@@ -138,7 +140,7 @@ def by_name(name: str | None) -> TrezorModel | None:
"""
if name is None:
return T1B1
- for model in TREZORS:
+ for model in ALL_MODELS:
if model.name == name:
return model
return None
@@ -152,7 +154,7 @@ def by_internal_name(name: str | None) -> TrezorModel | None:
"""
if name is None:
return None
- for model in TREZORS:
+ for model in ALL_MODELS:
if model.internal_name == name:
return model
return None
diff --git a/python/src/trezorlib/transport/webusb.py b/python/src/trezorlib/transport/webusb.py
index c2679f26..0d60723b 100644
--- a/python/src/trezorlib/transport/webusb.py
+++ b/python/src/trezorlib/transport/webusb.py
@@ -23,7 +23,7 @@ import time
from typing import Iterable, List
from ..log import DUMP_PACKETS
-from ..models import TREZORS, TrezorModel
+from ..models import ALL_MODELS, TrezorModel
from . import UDEV_RULES_STR, DeviceIsBusy, Timeout, Transport, TransportException
LOG = logging.getLogger(__name__)
@@ -80,7 +80,7 @@ class WebUsbTransport(Transport):
atexit.register(cls.context.close)
if models is None:
- models = TREZORS
+ models = ALL_MODELS
usb_ids = [id for model in models for id in model.usb_ids]
devices: List["WebUsbTransport"] = []
for dev in cls.context.getDeviceIterator(skip_on_error=True):
diff --git a/tests/conftest.py b/tests/conftest.py
index 027bcf82..0fd9a8be 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -187,8 +187,8 @@ def _find_client(request: pytest.FixtureRequest, interact: bool) -> Client:
class ModelsFilter:
MODEL_SHORTCUTS = {
- "core": models.TREZORS - {models.T1B1},
- "legacy": {models.T1B1},
+ "core": models.CORE_MODELS,
+ "legacy": models.LEGACY_MODELS,
"t1": {models.T1B1},
"t2": {models.T2T1},
"tt": {models.T2T1},
@@ -201,7 +201,7 @@ class ModelsFilter:
def __init__(self, node: Node) -> None:
markers = node.iter_markers("models")
- self.models = set(models.TREZORS)
+ self.models = set(models.ALL_MODELS)
for marker in markers:
self._refine_by_marker(marker)
diff --git a/tests/download_emulators.py b/tests/download_emulators.py
index 43b23747..17b84eb9 100755
--- a/tests/download_emulators.py
+++ b/tests/download_emulators.py
@@ -7,10 +7,13 @@ from typing import TypeAlias
import click
import requests
-from emulators import ALL_MODELS, gen_from_model
+from emulators import gen_from_model
+
+from trezorlib.models import ALL_MODELS
EmulatorDict: TypeAlias = dict[str, list[str]]
+ALL_MODEL_NAMES = sorted(m.internal_name for m in ALL_MODELS)
OLDEST_AVAILABLE = {
"legacy": (1, 6, 2),
@@ -126,7 +129,7 @@ def get_emulators_for_model(model: str, firmwares: EmulatorDict) -> list[Emulato
def download_emulators_for_model(model: str) -> None:
- if model not in ALL_MODELS:
+ if model not in ALL_MODEL_NAMES:
raise ValueError(f"Unknown model: {model}")
all_releases = get_all_releases()
@@ -138,7 +141,7 @@ def download_emulators_for_model(model: str) -> None:
@click.command()
-@click.argument("model", type=click.Choice(ALL_MODELS, case_sensitive=True))
+@click.argument("model", type=click.Choice(ALL_MODEL_NAMES, case_sensitive=True))
def main(model: str) -> None:
"""
Download all available emulators for a given Trezor model.
diff --git a/tests/emulators.py b/tests/emulators.py
index 1ca74aa7..df90bcd1 100644
--- a/tests/emulators.py
+++ b/tests/emulators.py
@@ -13,14 +13,16 @@
#
# 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 __future__ import annotations
import os
import tempfile
from collections import defaultdict
from pathlib import Path
-from typing import Dict, List, Optional, Sequence, Tuple
+from typing import Sequence, Tuple
from trezorlib._internal.emulator import CoreEmulator, Emulator, LegacyEmulator
+from trezorlib.models import CORE_MODELS, LEGACY_MODELS, by_internal_name
ROOT = Path(__file__).resolve().parent.parent
BINDIR = ROOT / "tests" / "emulators"
@@ -37,6 +39,15 @@ ENV = {"SDL_VIDEODRIVER": "dummy"}
TROPIC_MODEL_CONFIGFILE = ROOT / "tests" / "tropic_model" / "config.yml"
+def gen_from_model(model_internal_name: str) -> str:
+ model = by_internal_name(model_internal_name)
+ if model in LEGACY_MODELS:
+ return "legacy"
+ if model in CORE_MODELS:
+ return "core"
+ raise ValueError(f"Unknown model: {model_internal_name}")
+
+
def check_version(tag: str, version_tuple: Tuple[int, int, int]) -> None:
if tag is not None and tag.startswith("v") and len(tag.split(".")) == 3:
version = ".".join(str(i) for i in version_tuple)
@@ -44,23 +55,19 @@ def check_version(tag: str, version_tuple: Tuple[int, int, int]) -> None:
raise RuntimeError(f"Version mismatch: tag {tag} reports version {version}")
-def filename_from_tag(gen: str, tag: str) -> Path:
- return BINDIR / f"trezor-emu-{gen}-{tag}"
+def get_emulator_path(gen: str, model: str, tag: str) -> Path:
+ return BINDIR / model / f"trezor-emu-{gen}-{model}-{tag}"
-def get_tags() -> Dict[str, List[str]]:
- files = list(BINDIR.iterdir())
- if not files:
- raise ValueError(
- "No files found. Use download_emulators.sh to download emulators."
- )
+def get_tags() -> dict[str, list[str]]:
+ files = [p for p in BINDIR.glob("*/trezor-emu-*") if p.is_file()]
result = defaultdict(list)
for f in sorted(files):
try:
- # example: "trezor-emu-core-v2.1.1" or "trezor-emu-core-v2.1.1-46ab42fw"
- _, _, gen, tag = f.name.split("-", maxsplit=3)
- result[gen].append(tag)
+ # example: "trezor-emu-core-T2T1-v2.0.8" or "trezor-emu-core-T2T1-v2.0.8-46ab42fw"
+ _, _, _, model, tag = f.name.split("-", maxsplit=4)
+ result[model].append(tag)
except ValueError:
pass
return result
@@ -90,19 +97,22 @@ def _get_port(worker_id: int) -> int:
class EmulatorWrapper:
+
def __init__(
self,
gen: str,
- tag: Optional[str] = None,
- storage: Optional[bytes] = None,
+ tag: str | None = None,
+ model: str | None = None,
+ storage: bytes | None = None,
worker_id: int = 0,
headless: bool = True,
auto_interact: bool = True,
main_args: Sequence[str] = ("-m", "main"),
launch_tropic_model: bool = False,
) -> None:
- if tag is not None:
- executable = filename_from_tag(gen, tag)
+
+ if tag is not None and model is not None:
+ executable = get_emulator_path(gen, model, tag)
else:
executable = LOCAL_BUILD_PATHS[gen]
diff --git a/tests/github.py b/tests/github.py
index 426c8629..02027672 100644
--- a/tests/github.py
+++ b/tests/github.py
@@ -21,7 +21,7 @@ HERE = Path(__file__).parent
LIST_RUNS_TEMPLATE = "https://api.github.com/repos/trezor/trezor-firmware/actions/workflows/{workflow}/runs?branch={branch}"
FIXTURES_TEMPLATE = "https://data.trezor.io/dev/firmware/ui_report/{run}/{job_instance}-fixtures.results.json"
-MODELS = [model.internal_name for model in models.TREZORS]
+MODELS = [model.internal_name for model in models.ALL_MODELS]
CORE_LANGUAGES = ["en", "cs", "de", "es", "fr", "it", "pt"]
CORE_JOBS = ["core_device_test", "core_click_test", "core_persistence_test"]
LEGACY_LANGUAGES = ["en"]
diff --git a/tests/upgrade_tests/__init__.py b/tests/upgrade_tests/__init__.py
index 6291ca71..d39a016b 100644
--- a/tests/upgrade_tests/__init__.py
+++ b/tests/upgrade_tests/__init__.py
@@ -20,7 +20,9 @@ from typing import List, Tuple
import pytest
from _pytest.mark.structures import MarkDecorator
-from ..emulators import ALL_TAGS, LOCAL_BUILD_PATHS
+from trezorlib.models import CORE_MODELS, LEGACY_MODELS, T1B1, T2T1, by_internal_name
+
+from ..emulators import ALL_TAGS, LOCAL_BUILD_PATHS, gen_from_model
SELECTED_GENS = [
gen.strip() for gen in os.environ.get("TREZOR_UPGRADE_TEST", "").split(",") if gen
@@ -67,48 +69,65 @@ def for_all(
Usage example:
>>> @for_all()
- >>> def test_runs_for_all_old_versions(gen, tag):
+ >>> def test_runs_for_all_old_versions(gen, tag, model):
>>> assert True
- Arguments can be "core" and "legacy", and you can specify core_minimum_version and
- legacy_minimum_version as triplets.
+ Arguments can be trezor models (e.g."T1B1" and "T2T1") or aliases "core" and "legacy",
+ and you can specify core_minimum_version and legacy_minimum_version as triplets.
The test function should have arguments `gen` ("core" or "legacy") and `tag`
(version tag usable in EmulatorWrapper call)
"""
+ models = []
+ gens = set()
+ for item in args:
+ if item == "core":
+ models.extend(CORE_MODELS)
+ gens.add("core")
+ elif item == "legacy":
+ models.extend(LEGACY_MODELS)
+ gens.add("legacy")
+ else:
+ models.append(by_internal_name(item))
+ gens.add(gen_from_model(item))
+
if not args:
- args = ("core", "legacy")
+ gens = ["core", "legacy"]
+ models = [T1B1, T2T1]
# If any gens were selected, use them. If none, select all.
- enabled_gens = SELECTED_GENS or args
+ enabled_gens = SELECTED_GENS or list(gens)
- all_params: list[tuple[str, str | None]] = []
- for gen in args:
- if gen == "legacy":
+ all_params: set[tuple[str, str | None, str | None]] = set()
+ for model in models:
+ if model in LEGACY_MODELS:
minimum_version = legacy_minimum_version
- elif gen == "core":
+ elif model in CORE_MODELS:
minimum_version = core_minimum_version
else:
raise ValueError
+ gen = gen_from_model(model.internal_name)
if gen not in enabled_gens:
continue
try:
- for tag in ALL_TAGS[gen]:
+ for tag in ALL_TAGS[model.internal_name]:
tag_version = version_from_tag(tag)
if tag_version is not None and tag_version < minimum_version:
continue
- all_params.append((gen, tag))
+ all_params.add((gen, tag, model.internal_name))
- # at end, add None tag, which is the current master
- all_params.append((gen, None))
+ # At the end, add (gen, None, None), which is the current master.
+ # The same (gen, None, None) can be added multiple times as there are
+ # more models than gens. That is why all_params is defined as a set.
+ all_params.add((gen, None, None))
except KeyError:
pass
if not all_params:
return pytest.mark.skip("no versions are applicable")
- return pytest.mark.parametrize("gen, tag", all_params)
+ return pytest.mark.parametrize("gen, tag, model", all_params)
def for_tags(*args: Tuple[str, List[str]]) -> "MarkDecorator":
diff --git a/tests/upgrade_tests/test_firmware_upgrades.py b/tests/upgrade_tests/test_firmware_upgrades.py
index ce55902b..64d7780c 100644
--- a/tests/upgrade_tests/test_firmware_upgrades.py
+++ b/tests/upgrade_tests/test_firmware_upgrades.py
@@ -13,10 +13,11 @@
#
# 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 __future__ import annotations
import dataclasses
import functools
-from typing import TYPE_CHECKING, List, Optional
+from typing import TYPE_CHECKING, List
import pytest
from shamir_mnemonic import shamir
@@ -59,7 +60,7 @@ def lower_models_minimum_version(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
- original_trezors = models.TREZORS.copy()
+ original_trezors = models.ALL_MODELS.copy()
original_t1b1 = models.T1B1
original_t2t1 = models.T2T1
@@ -67,7 +68,7 @@ def lower_models_minimum_version(func):
models.T2T1 = dataclasses.replace(models.T2T1, minimum_version=(2, 0, 0))
models.TREZOR_ONE = models.T1B1
models.TREZOR_T = models.T2T1
- models.TREZORS = {models.T1B1, models.T2T1}
+ models.ALL_MODELS = {models.T1B1, models.T2T1}
try:
result = func(*args, **kwargs)
@@ -76,7 +77,7 @@ def lower_models_minimum_version(func):
models.T2T1 = original_t2t1
models.TREZOR_ONE = models.T1B1
models.TREZOR_T = models.T2T1
- models.TREZORS = original_trezors
+ models.ALL_MODELS = original_trezors
return result
return wrapper
@@ -110,7 +111,11 @@ def _get_session(client: "Client", passphrase: str | object = "") -> "Session":
@for_all()
@lower_models_minimum_version
-def test_upgrade_load(gen: str, tag: str) -> None:
+def test_upgrade_load(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+) -> None:
def asserts(client: "Client"):
client.refresh_features()
assert not client.features.pin_protection
@@ -122,7 +127,7 @@ def test_upgrade_load(gen: str, tag: str) -> None:
== ADDRESS
)
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
debuglink.load_device_by_mnemonic(
emu.client.get_seedless_session(),
mnemonic=MNEMONIC,
@@ -141,7 +146,11 @@ def test_upgrade_load(gen: str, tag: str) -> None:
@for_all("legacy")
@lower_models_minimum_version
-def test_upgrade_load_pin(gen: str, tag: str) -> None:
+def test_upgrade_load_pin(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+) -> None:
PIN = "1234"
def asserts(client: "Client") -> None:
@@ -154,7 +163,7 @@ def test_upgrade_load_pin(gen: str, tag: str) -> None:
session = client.get_session()
assert btc.get_address(session, "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
debuglink.load_device_by_mnemonic(
emu.client.get_seedless_session(),
mnemonic=MNEMONIC,
@@ -195,7 +204,7 @@ def test_storage_upgrade_progressive(gen: str, tags: List[str]):
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tags[0]) as emu:
+ with EmulatorWrapper(gen, tags[0], model="T1B1") as emu:
debuglink.load_device_by_mnemonic(
emu.client.get_seedless_session(),
mnemonic=MNEMONIC,
@@ -208,7 +217,7 @@ def test_storage_upgrade_progressive(gen: str, tags: List[str]):
storage = emu.get_storage()
for tag in tags[1:]:
- with EmulatorWrapper(gen, tag, storage=storage) as emu:
+ with EmulatorWrapper(gen, tag, model="T1B1", storage=storage) as emu:
storage = emu.get_storage()
with EmulatorWrapper(gen, storage=storage) as emu:
@@ -218,7 +227,11 @@ def test_storage_upgrade_progressive(gen: str, tags: List[str]):
@for_all("legacy", legacy_minimum_version=(1, 9, 0))
@lower_models_minimum_version
-def test_upgrade_wipe_code(gen: str, tag: str):
+def test_upgrade_wipe_code(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
PIN = "1234"
WIPE_CODE = "4321"
@@ -230,7 +243,7 @@ def test_upgrade_wipe_code(gen: str, tag: str):
client.use_pin_sequence([PIN])
assert btc.get_address(client.get_session(), "Bitcoin", PATH) == ADDRESS
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
debuglink.load_device_by_mnemonic(
emu.client.get_seedless_session(),
mnemonic=MNEMONIC,
@@ -266,7 +279,11 @@ def test_upgrade_wipe_code(gen: str, tag: str):
@for_all("legacy")
@lower_models_minimum_version
-def test_upgrade_reset(gen: str, tag: str):
+def test_upgrade_reset(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
def asserts(client: "Client"):
assert not client.features.pin_protection
assert not client.features.passphrase_protection
@@ -276,7 +293,7 @@ def test_upgrade_reset(gen: str, tag: str):
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
device.setup(
emu.client.get_seedless_session(),
strength=STRENGTH,
@@ -299,7 +316,11 @@ def test_upgrade_reset(gen: str, tag: str):
@for_all()
@lower_models_minimum_version
-def test_upgrade_reset_skip_backup(gen: str, tag: str):
+def test_upgrade_reset_skip_backup(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
def asserts(client: "Client"):
assert not client.features.pin_protection
assert not client.features.passphrase_protection
@@ -309,7 +330,7 @@ def test_upgrade_reset_skip_backup(gen: str, tag: str):
assert not client.features.unfinished_backup
assert not client.features.no_backup
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
device.setup(
emu.client.get_seedless_session(),
strength=STRENGTH,
@@ -333,7 +354,11 @@ def test_upgrade_reset_skip_backup(gen: str, tag: str):
@for_all(legacy_minimum_version=(1, 7, 2))
@lower_models_minimum_version
-def test_upgrade_reset_no_backup(gen: str, tag: str):
+def test_upgrade_reset_no_backup(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
def asserts(client: "Client"):
assert not client.features.pin_protection
assert not client.features.passphrase_protection
@@ -343,7 +368,7 @@ def test_upgrade_reset_no_backup(gen: str, tag: str):
assert not client.features.unfinished_backup
assert client.features.no_backup
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
device.setup(
emu.client.get_seedless_session(),
strength=STRENGTH,
@@ -369,9 +394,13 @@ def test_upgrade_reset_no_backup(gen: str, tag: str):
# Although Shamir was introduced in 2.1.2 already, the debug instrumentation was not present until 2.1.9.
@for_all("core", core_minimum_version=(2, 1, 9))
@lower_models_minimum_version
-def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
+def test_upgrade_shamir_recovery(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
with (
- EmulatorWrapper(gen, tag) as emu,
+ EmulatorWrapper(gen, tag, model) as emu,
BackgroundDeviceHandler(emu.client) as device_handler,
):
assert emu.client.features.recovery_status == RecoveryStatus.Nothing
@@ -424,8 +453,12 @@ def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
@for_all("core", core_minimum_version=(2, 1, 9))
@lower_models_minimum_version
-def test_upgrade_shamir_backup(gen: str, tag: Optional[str]):
- with EmulatorWrapper(gen, tag) as emu:
+def test_upgrade_shamir_backup(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
+ with EmulatorWrapper(gen, tag, model) as emu:
session = emu.client.get_seedless_session()
# Generate a new encrypted master secret and record it.
device.setup(
@@ -496,9 +529,13 @@ def test_upgrade_shamir_backup(gen: str, tag: Optional[str]):
@for_all(legacy_minimum_version=(1, 8, 4), core_minimum_version=(2, 1, 9))
@lower_models_minimum_version
-def test_upgrade_u2f(gen: str, tag: str):
+def test_upgrade_u2f(
+ gen: str,
+ tag: str | None,
+ model: str | None,
+):
"""Check U2F counter stayed the same after an upgrade."""
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
debuglink.load_device_by_mnemonic(
emu.client.get_seedless_session(),
mnemonic=MNEMONIC,
@@ -528,7 +565,8 @@ def test_upgrade_u2f(gen: str, tag: str):
)
def test_cardano_address_does_not_change_by_upgrade(
gen: str,
- tag: Optional[str],
+ tag: str,
+ model: str,
backup_type: BackupType,
derivation_type: CardanoDerivationType,
):
@@ -547,7 +585,7 @@ def test_cardano_address_does_not_change_by_upgrade(
# SLIP-39 was not implemented for Cardano in v2.1.2
return
- with EmulatorWrapper(gen, tag) as emu:
+ with EmulatorWrapper(gen, tag, model) as emu:
device.setup(
emu.client.get_seedless_session(),
pin_protection=False,
@@ -571,8 +609,8 @@ def test_cardano_address_does_not_change_by_upgrade(
if __name__ == "__main__":
if not ALL_TAGS:
- print("No versions found. Remember to run download_emulators.sh")
- for k, v in ALL_TAGS.items():
- print(f"Found versions for {k}: {v}")
+ print("No emulators found. Remember to run download_emulators.sh")
+ for model, tag in ALL_TAGS.items():
+ print(f"Found versions for {model}: {tag}")
print()
print(f"Use `pytest {__file__}` to run tests")
diff --git a/tests/upgrade_tests/test_passphrase_consistency.py b/tests/upgrade_tests/test_passphrase_consistency.py
index c453cf93..14ae4094 100644
--- a/tests/upgrade_tests/test_passphrase_consistency.py
+++ b/tests/upgrade_tests/test_passphrase_consistency.py
@@ -46,8 +46,8 @@ mapping.DEFAULT_MAPPING.register(ApplySettingsCompat)
@pytest.fixture
-def emulator(gen: str, tag: str) -> Iterator[Emulator]:
- with EmulatorWrapper(gen, tag) as emu:
+def emulator(gen: str, tag: str, model: str) -> Iterator[Emulator]:
+ with EmulatorWrapper(gen, tag, model) as emu:
# set up a passphrase-protected device
device.setup(
emu.client.get_seedless_session(),
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.