WIP - reorganize tests

pull/3491/head
matejcik 4 months ago
parent 82cf2d9bc7
commit ba7afc3e28

@ -17,13 +17,14 @@
import json
import re
import time
import typing as t
from pathlib import Path
from typing import TYPE_CHECKING, Generator, Optional
from unittest import mock
import pytest
from trezorlib import btc, messages, tools
from trezorlib import btc, cosi, messages, tools
from trezorlib.messages import ButtonRequestType
if TYPE_CHECKING:
@ -33,6 +34,7 @@ if TYPE_CHECKING:
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.messages import ButtonRequest
PRIVATE_KEYS_DEV = [byte * 32 for byte in (b"\xdd", b"\xde", b"\xdf")]
BRGeneratorType = Generator[None, messages.ButtonRequest, None]
@ -291,3 +293,19 @@ def compact_size(n: int) -> bytes:
return bytes([254]) + n.to_bytes(4, "little")
else:
return bytes([255]) + n.to_bytes(8, "little")
def sign_with_privkeys(digest: bytes, privkeys: t.Sequence[bytes]) -> bytes:
"""Locally produce a CoSi signature."""
pubkeys = [cosi.pubkey_from_privkey(sk) for sk in privkeys]
nonces = [cosi.get_nonce(sk, digest, i) for i, sk in enumerate(privkeys)]
global_pk = cosi.combine_keys(pubkeys)
global_R = cosi.combine_keys(R for _, R in nonces)
sigs = [
cosi.sign_with_privkey(digest, sk, global_pk, r, global_R)
for sk, (r, _) in zip(privkeys, nonces)
]
return cosi.combine_sig(global_R, sigs)

@ -23,13 +23,18 @@ from typing import TYPE_CHECKING, Generator, Iterator
import pytest
import xdist
from trezorlib import debuglink, log, translations
from trezorlib import debuglink, log
from trezorlib._internal import translations
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.device import apply_settings, change_language
from trezorlib.device import apply_settings
from trezorlib.device import wipe as wipe_device
from trezorlib.transport import enumerate_devices, get_transport
from . import ui_tests
# register rewrites before importing from local package
# so that we see details of failed asserts from this module
pytest.register_assert_rewrite("tests.common")
from . import translations, ui_tests
from .device_handler import BackgroundDeviceHandler
from .emulators import EmulatorWrapper
@ -43,14 +48,6 @@ if TYPE_CHECKING:
HERE = Path(__file__).resolve().parent
CORE = HERE.parent / "core"
TRANSLATIONS = CORE / "embed" / "rust" / "src" / "ui" / "translations"
CS_JSON = TRANSLATIONS / "cs.json"
FR_JSON = TRANSLATIONS / "fr.json"
# So that we see details of failed asserts from this module
pytest.register_assert_rewrite("tests.common")
def _emulator_wrapper_main_args() -> list[str]:
@ -146,26 +143,8 @@ def _raw_client(request: pytest.FixtureRequest) -> Client:
# Not doing it for T1
if client.features.model != "1":
lang = request.session.config.getoption("lang") or "en"
_set_language(client, lang) # type: ignore
return client
def _set_language(client: Client, lang: str) -> Client:
model = client.features.model or ""
if lang == "en":
with client:
change_language(client, language_data=b"")
elif lang == "cs":
change_language(
client, language_data=translations.blob_from_file(CS_JSON, model)
)
elif lang == "fr":
change_language(
client, language_data=translations.blob_from_file(FR_JSON, model)
)
else:
raise RuntimeError(f"Unknown language: {lang}")
assert isinstance(lang, str)
translations.set_language(client, lang)
return client

@ -4,25 +4,9 @@ import io
import typing as t
from hashlib import sha256
from trezorlib import cosi, definitions, messages, protobuf
from trezorlib import definitions, messages, protobuf
PRIVATE_KEYS_DEV = [byte * 32 for byte in (b"\xdd", b"\xde", b"\xdf")]
def sign_with_privkeys(digest: bytes, privkeys: t.Sequence[bytes]) -> bytes:
"""Locally produce a CoSi signature."""
pubkeys = [cosi.pubkey_from_privkey(sk) for sk in privkeys]
nonces = [cosi.get_nonce(sk, digest, i) for i, sk in enumerate(privkeys)]
global_pk = cosi.combine_keys(pubkeys)
global_R = cosi.combine_keys(R for _, R in nonces)
sigs = [
cosi.sign_with_privkey(digest, sk, global_pk, r, global_R)
for sk, (r, _) in zip(privkeys, nonces)
]
return cosi.combine_sig(global_R, sigs)
from ...common import sign_with_privkeys, PRIVATE_KEYS_DEV
def make_network(

@ -14,85 +14,41 @@
# 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>.
import json
from contextlib import contextmanager
from copy import deepcopy
from pathlib import Path
from typing import Any, Dict, Generator
from typing import Iterator
import pytest
from trezorlib import debuglink, device, exceptions, messages, translations
from trezorlib import debuglink, device, exceptions, messages, models
from trezorlib._internal import translations
from trezorlib.debuglink import TrezorClientDebugLink as Client
pytestmark = pytest.mark.skip_t1
HERE = Path(__file__).parent.resolve()
CORE = HERE.parent.parent / "core"
TRANSLATIONS = CORE / "embed" / "rust" / "src" / "ui" / "translations"
FONTS = TRANSLATIONS / "fonts"
ORDER_FILE = TRANSLATIONS / "order.json"
from ..translations import (
LANGUAGES,
get_lang_json,
set_language,
build_and_sign_blob,
)
EN_JSON = TRANSLATIONS / "en.json"
CS_JSON = TRANSLATIONS / "cs.json"
FR_JSON = TRANSLATIONS / "fr.json"
MAX_DATA_LENGTH = {"T": 48 * 1024, "Safe 3": 32 * 1024}
pytestmark = pytest.mark.skip_t1
def _read_confirm_word(file: Path) -> str:
content = json.loads(file.read_text())
return content["translations"]["words"]["confirm"]
MAX_DATA_LENGTH = {models.T2T1: 48 * 1024, models.T2B1: 32 * 1024}
ENGLISH_CONFIRM = _read_confirm_word(EN_JSON)
CZECH_CONFIRM = _read_confirm_word(CS_JSON)
FRENCH_CONFIRM = _read_confirm_word(FR_JSON)
def get_confirm(lang: str) -> str:
content = get_lang_json(lang)
return content["translations"]["words__confirm"]
@contextmanager
def _set_english_return_back(client: Client) -> Generator[Client, None, None]:
@pytest.fixture
def client(client: Client) -> Iterator[Client]:
lang_before = client.features.language or ""
try:
_set_default_english(client)
set_language(client, "en")
yield client
finally:
if lang_before.startswith("en"):
_set_default_english(client)
elif lang_before == "cs":
_set_full_czech(client)
elif lang_before == "fr":
_set_full_french(client)
else:
raise RuntimeError(f"Unknown language: {lang_before}")
def _set_full_czech(client: Client):
device.change_language(
client,
language_data=translations.blob_from_file(CS_JSON, client.features.model or ""),
)
def _set_full_french(client: Client):
device.change_language(
client,
language_data=translations.blob_from_file(FR_JSON, client.features.model or ""),
)
def _set_default_english(client: Client):
with client:
device.change_language(client, language_data=b"")
def _get_data_from_dict(data: Dict[str, Any], client: Client) -> bytes:
return translations.blob_from_dict(
data,
font_dir=FONTS,
order_json_file=ORDER_FILE,
model=client.features.model or "",
)
set_language(client, lang_before[:2])
def _check_ping_screen_texts(client: Client, title: str, right_button: str) -> None:
@ -115,210 +71,186 @@ def _check_ping_screen_texts(client: Client, title: str, right_button: str) -> N
def test_change_language_errors(client: Client):
with _set_english_return_back(client) as client:
assert client.features.language == "en-US"
# Translations too short
# Sending less data than the header length
with pytest.raises(
exceptions.TrezorFailure, match="Translations too short"
), client:
bad_data = (translations.HEADER_LEN - 1) * b"a"
device.change_language(client, language_data=bad_data)
assert client.features.language == "en-US"
# Translations too long
# Sending more than allowed by the flash capacity
max_length = MAX_DATA_LENGTH[client.features.model]
with pytest.raises(
exceptions.TrezorFailure, match="Translations too long"
), client:
bad_data = (max_length + 1) * b"a"
device.change_language(client, language_data=bad_data)
assert client.features.language == "en-US"
# Invalid header data length
# Sending more data than advertised in the header
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header data length"
), client:
good_data = translations.blob_from_file(
CS_JSON, client.features.model or ""
)
bad_data = good_data + b"abcd"
device.change_language(client, language_data=bad_data)
assert client.features.language == "en-US"
# Invalid header magic
# Does not match the expected magic
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header magic"
), client:
good_data = translations.blob_from_file(
CS_JSON, client.features.model or ""
)
bad_data = 4 * b"a" + good_data[4:]
device.change_language(client, language_data=bad_data)
assert client.features.language == "en-US"
# Invalid header data
# Putting non-zero bytes where zero is expected
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header data"
), client:
good_data = translations.blob_from_file(
CS_JSON, client.features.model or ""
)
pre_sig_pos = translations.HEADER_LEN - translations.SIG_LEN
bad_data = good_data[: pre_sig_pos - 4] + 4 * b"a" + good_data[pre_sig_pos:]
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "en-US"
# Invalid data hash
# Changing the data after their hash has been calculated
with pytest.raises(exceptions.TrezorFailure, match="Invalid data hash"), client:
good_data = translations.blob_from_file(
CS_JSON, client.features.model or ""
)
bad_data = good_data[:-8] + 8 * b"a"
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "en-US"
# Invalid translations version
# Change the version to one not matching the current device
with pytest.raises(
exceptions.TrezorFailure, match="Invalid translations version"
), client:
with open(CS_JSON, "r") as f:
data = json.load(f)
data["header"]["version"] = "3.5.4"
device.change_language(
client,
language_data=_get_data_from_dict(data, client),
)
assert client.features.language == "en-US"
# Invalid header version
# Version is not a valid semver with integers
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header version"
), client:
with open(CS_JSON, "r") as f:
data = json.load(f)
data["header"]["version"] = "ABC.XYZ.DEF"
device.change_language(
client,
language_data=_get_data_from_dict(data, client),
)
assert client.features.language == "en-US"
# Invalid translations signature
# Modifying the signature part of the header
with pytest.raises(
exceptions.TrezorFailure, match="Invalid translations signature"
), client:
good_data = translations.blob_from_file(
CS_JSON, client.features.model or ""
)
bad_data = (
good_data[: translations.HEADER_LEN - 8]
+ 8 * b"a"
+ good_data[translations.HEADER_LEN :]
)
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "en-US"
_check_ping_screen_texts(client, ENGLISH_CONFIRM, ENGLISH_CONFIRM)
def test_full_language_change(client: Client):
with _set_english_return_back(client) as client:
assert client.features.language == "en-US"
# Setting cs language
_set_full_czech(client)
assert client.features.language == "cs"
_check_ping_screen_texts(client, CZECH_CONFIRM, CZECH_CONFIRM)
# Setting fr language
_set_full_french(client)
assert client.features.language == "fr"
_check_ping_screen_texts(client, FRENCH_CONFIRM, FRENCH_CONFIRM)
# Setting the default language via empty data
_set_default_english(client)
assert client.features.language == "en-US"
_check_ping_screen_texts(client, ENGLISH_CONFIRM, ENGLISH_CONFIRM)
assert client.features.language == "enUS"
# Translations too short
# Sending less data than the header length
with pytest.raises(
exceptions.TrezorFailure, match="Translations too short"
), client:
bad_data = (translations.HEADER_LEN - 1) * b"a"
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
# Translations too long
# Sending more than allowed by the flash capacity
max_length = MAX_DATA_LENGTH[client.model]
with pytest.raises(exceptions.TrezorFailure, match="Translations too long"), client:
bad_data = (max_length + 1) * b"a"
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
# Invalid header data length
# Sending more data than advertised in the header
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header data length"
), client:
good_data = build_and_sign_blob("cs", client.model)
bad_data = good_data + b"abcd"
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
# Invalid header magic
# Does not match the expected magic
with pytest.raises(exceptions.TrezorFailure, match="Invalid header magic"), client:
good_data = build_and_sign_blob("cs", client.model)
bad_data = 4 * b"a" + good_data[4:]
device.change_language(client, language_data=bad_data)
assert client.features.language == "enUS"
# Invalid header data
# Putting non-zero bytes where zero is expected
with pytest.raises(exceptions.TrezorFailure, match="Invalid header data"), client:
good_data = build_and_sign_blob("cs", client.model)
pre_sig_pos = translations.HEADER_LEN - translations.SIG_LEN
bad_data = good_data[: pre_sig_pos - 4] + 4 * b"a" + good_data[pre_sig_pos:]
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "enUS"
# Invalid data hash
# Changing the data after their hash has been calculated
with pytest.raises(exceptions.TrezorFailure, match="Invalid data hash"), client:
good_data = build_and_sign_blob("cs", client.model)
bad_data = good_data[:-8] + 8 * b"a"
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "enUS"
# Invalid translations version
# Change the version to one not matching the current device
with pytest.raises(
exceptions.TrezorFailure, match="Invalid translations version"
), client:
data = get_lang_json("cs")
data["header"]["version"] = "3.5.4"
device.change_language(
client,
language_data=build_and_sign_blob(data, client.model),
)
assert client.features.language == "enUS"
# Invalid header version
# Version is not a valid semver with integers
with pytest.raises(
exceptions.TrezorFailure, match="Invalid header version"
), client:
data = get_lang_json("cs")
data["header"]["version"] = "ABC.XYZ.DEF"
device.change_language(
client,
language_data=build_and_sign_blob(data, client.model),
)
assert client.features.language == "enUS"
# Invalid translations signature
# Modifying the signature part of the header
with pytest.raises(
exceptions.TrezorFailure, match="Invalid translations signature"
), client:
good_data = translations.blob_from_file(
get_lang_json("cs"), client.features.model or ""
)
bad_data = (
good_data[: translations.HEADER_LEN - 8]
+ 8 * b"a"
+ good_data[translations.HEADER_LEN :]
)
device.change_language(
client,
language_data=bad_data,
)
assert client.features.language == "enUS"
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
@pytest.mark.parametrize("lang", LANGUAGES)
def test_full_language_change(client: Client, lang: str):
assert client.features.language == "enUS"
# Setting selected language
set_language(client, lang)
assert client.features.language[:2] == lang
_check_ping_screen_texts(client, get_confirm(lang), get_confirm(lang))
# Setting the default language via empty data
set_language(client, "en")
assert client.features.language == "enUS"
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
def test_language_stays_after_wipe(client: Client):
with _set_english_return_back(client) as client:
assert client.features.language == "en-US"
assert client.features.language == "enUS"
_check_ping_screen_texts(client, ENGLISH_CONFIRM, ENGLISH_CONFIRM)
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
# Setting cs language
_set_full_czech(client)
assert client.features.language == "cs"
# Setting cs language
set_language(client, "cs")
assert client.features.language == "csCZ"
_check_ping_screen_texts(client, CZECH_CONFIRM, CZECH_CONFIRM)
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
# Wipe device
device.wipe(client)
assert client.features.language == "cs"
# Wipe device
device.wipe(client)
assert client.features.language == "csCZ"
# Load it again
debuglink.load_device(
client,
mnemonic=" ".join(["all"] * 12),
pin=None,
passphrase_protection=False,
label="test",
)
assert client.features.language == "cs"
# Load it again
debuglink.load_device(
client,
mnemonic=" ".join(["all"] * 12),
pin=None,
passphrase_protection=False,
label="test",
)
assert client.features.language == "csCZ"
_check_ping_screen_texts(client, CZECH_CONFIRM, CZECH_CONFIRM)
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
def test_translations_renders_on_screen(client: Client):
with open(CS_JSON, "r") as f:
czech_data = json.load(f)
czech_data = get_lang_json("cs")
# Setting some values of words__confirm key and checking that in ping screen title
with _set_english_return_back(client) as client:
assert client.features.language == "en-US"
assert client.features.language == "enUS"
# Normal english
_check_ping_screen_texts(client, ENGLISH_CONFIRM, ENGLISH_CONFIRM)
# Normal english
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("en"))
# Normal czech
_set_full_czech(client)
assert client.features.language == "cs"
_check_ping_screen_texts(client, CZECH_CONFIRM, CZECH_CONFIRM)
# Normal czech
set_language(client, "cs")
assert client.features.language == "csCZ"
_check_ping_screen_texts(client, get_confirm("cs"), get_confirm("cs"))
# Modified czech - changed value
czech_data_copy = deepcopy(czech_data)
new_czech_confirm = "ABCD"
czech_data_copy["translations"]["words"]["confirm"] = new_czech_confirm
device.change_language(
client,
language_data=_get_data_from_dict(czech_data_copy, client),
)
_check_ping_screen_texts(client, new_czech_confirm, CZECH_CONFIRM)
# Modified czech - changed value
czech_data_copy = deepcopy(czech_data)
new_czech_confirm = "ABCD"
czech_data_copy["translations"]["words__confirm"] = new_czech_confirm
device.change_language(
client,
language_data=build_and_sign_blob(czech_data_copy, client.model),
)
_check_ping_screen_texts(client, new_czech_confirm, get_confirm("cs"))
# Modified czech - key deleted completely, english is shown
czech_data_copy = deepcopy(czech_data)
del czech_data_copy["translations"]["words"]["confirm"]
device.change_language(
client, language_data=_get_data_from_dict(czech_data_copy, client)
)
_check_ping_screen_texts(client, ENGLISH_CONFIRM, CZECH_CONFIRM)
# Modified czech - key deleted completely, english is shown
czech_data_copy = deepcopy(czech_data)
del czech_data_copy["translations"]["words__confirm"]
device.change_language(
client,
language_data=build_and_sign_blob(czech_data_copy, client.model),
)
_check_ping_screen_texts(client, get_confirm("en"), get_confirm("cs"))

@ -1,32 +1,84 @@
import json
import typing as t
from hashlib import sha256
from pathlib import Path
from typing import Any, Iterable
from trezorlib import device, models
from trezorlib._internal import translations
from trezorlib.debuglink import TrezorClientDebugLink as Client
from . import common
HERE = Path(__file__).resolve().parent
ROOT = HERE.parent
TRANSLATIONS = ROOT / "core" / "embed" / "rust" / "src" / "ui" / "translations"
TRANSLATIONS = ROOT / "core" / "translations"
FONTS_DIR = TRANSLATIONS / "fonts"
ORDER_FILE = TRANSLATIONS / "order.json"
LANGUAGES = [file.stem for file in TRANSLATIONS.glob("??.json")]
def build_and_sign_blob(
lang_or_def: translations.JsonDef | Path | str, model: models.TrezorModel
) -> bytes:
order = translations.order_from_json(json.loads(ORDER_FILE.read_text()))
if isinstance(lang_or_def, str):
lang_or_def = get_lang_json(lang_or_def)
if isinstance(lang_or_def, Path):
lang_or_def = t.cast(translations.JsonDef, json.loads(lang_or_def.read_text()))
# generate raw blob
blob = translations.blob_from_defs(lang_or_def, order, model, FONTS_DIR)
# build 0-item Merkle proof
digest = sha256(b"\x00" + blob.header_bytes).digest()
signature = common.sign_with_privkeys(digest, common.PRIVATE_KEYS_DEV)
blob.proof = translations.Proof(
merkle_proof=[],
sigmask=0b111,
signature=signature,
)
return blob.build()
LANGUAGES = ["cs", "en", "fr"]
def set_language(client: Client, lang: str):
if lang.startswith("en"):
language_data = b""
else:
language_data = build_and_sign_blob(lang, client.model)
with client:
device.change_language(client, language_data)
def _get_all_language_data() -> list[dict[str, dict[str, str]]]:
def get_lang_json(lang: str) -> translations.JsonDef:
assert lang in LANGUAGES
return json.loads((TRANSLATIONS / f"{lang}.json").read_text())
def _get_all_language_data() -> list[dict[str, str]]:
return [_get_language_data(language) for language in LANGUAGES]
def _get_language_data(language: str) -> dict[str, dict[str, str]]:
file = TRANSLATIONS / f"{language}.json"
return json.loads(file.read_text())["translations"]
def _get_language_data(lang: str) -> dict[str, str]:
defs = get_lang_json(lang)
# TODO: remove this before merge
translations = {
k: v.replace(" (TODO)", "") for k, v in defs["translations"].items()
}
return translations
all_language_data = _get_all_language_data()
def _resolve_path_to_texts(path: str, template: Iterable[Any] = ()) -> list[str]:
def _resolve_path_to_texts(
path: str, template: t.Iterable[t.Any] = (), lower: bool = True
) -> list[str]:
texts: list[str] = []
lookups = path.split(".")
for language_data in all_language_data:
data: dict[str, Any] | str = language_data
data: dict[str, t.Any] | str = language_data
for lookup in lookups:
assert isinstance(data, dict), f"{lookup} is not a dict"
data = data[lookup]
@ -34,27 +86,39 @@ def _resolve_path_to_texts(path: str, template: Iterable[Any] = ()) -> list[str]
if template:
data = data.format(*template)
texts.append(data)
if lower:
texts = [t.lower() for t in texts]
return texts
def assert_equals(text: str, path: str, template: Iterable[Any] = ()) -> None:
def assert_equals(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None:
# TODO: we can directly pass in the current device language
texts = _resolve_path_to_texts(path, template)
assert text in texts, f"{text} not found in {texts}"
assert text.lower() in texts, f"{text} not found in {texts}"
def assert_equals_multiple(
text: str, paths: list[str], template: t.Iterable[t.Any] = ()
) -> None:
texts: list[str] = []
for path in paths:
texts += _resolve_path_to_texts(path, template)
assert text.lower() in texts, f"{text} not found in {texts}"
def assert_in(text: str, path: str, template: Iterable[Any] = ()) -> None:
def assert_in(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None:
texts = _resolve_path_to_texts(path, template)
for t in texts:
if t in text:
if t in text.lower():
return
assert False, f"{text} not found in {texts}"
def assert_startswith(text: str, path: str, template: Iterable[Any] = ()) -> None:
def assert_startswith(text: str, path: str, template: t.Iterable[t.Any] = ()) -> None:
texts = _resolve_path_to_texts(path, template)
for t in texts:
if text.startswith(t):
if text.lower().startswith(t):
return
assert False, f"{text} not found in {texts}"
@ -64,10 +128,13 @@ def assert_template(text: str, template_path: str) -> None:
for t in templates:
# Checking at least the first part
first_part = t.split("{")[0]
if text.startswith(first_part):
if text.lower().startswith(first_part):
return
assert False, f"{text} not found in {templates}"
def translate(path: str, template: Iterable[Any] = ()) -> list[str]:
return _resolve_path_to_texts(path, template)
def translate(
path: str, template: t.Iterable[t.Any] = (), lower: bool = False
) -> list[str]:
# Do not converting to lowercase, we want the exact value
return _resolve_path_to_texts(path, template, lower=lower)

@ -17,6 +17,7 @@ import pytest
from PIL import Image
from typing_extensions import Self
from trezorlib import models
from trezorlib.debuglink import TrezorClientDebugLink as Client
UI_TESTS_DIR = Path(__file__).resolve().parent
@ -36,10 +37,7 @@ FixturesType = t.NewType("FixturesType", "dict[str, dict[str, dict[str, str]]]")
FIXTURES: FixturesType = FixturesType({})
ENGLISH_LANGUAGE_TREZOR = "en-US"
ENGLISH_LANGUAGE = "en"
FOREIGN_LANGUAGES = ["cs", "fr"]
SUPPORTED_LANGUAGES = FOREIGN_LANGUAGES + [ENGLISH_LANGUAGE]
def get_current_fixtures() -> FixturesType:
@ -236,17 +234,18 @@ class TestCase:
@classmethod
def build(cls, client: Client, request: pytest.FixtureRequest) -> Self:
model = client.features.model
# FIXME
if model == "Safe 3":
model = "R"
if client.model is models.T2B1:
model_name = "R"
else:
model_name = client.model.name
name, group = _get_test_name_and_group(request.node.nodeid)
language = client.features.language or ""
if language == ENGLISH_LANGUAGE_TREZOR:
if client.features.language:
language = client.features.language[:2]
else:
language = ENGLISH_LANGUAGE
assert language in SUPPORTED_LANGUAGES
return cls(
model=f"T{model}",
model=f"T{model_name}",
name=name,
group=group,
language=language,
@ -254,8 +253,9 @@ class TestCase:
@staticmethod
def get_language_from_fixture_name(fixture_name: str) -> str:
# FIXME
lang = fixture_name.split("_")[1]
if lang in FOREIGN_LANGUAGES:
if len(lang) == 2:
return lang
# English (currently) is implicit there
return ENGLISH_LANGUAGE

Loading…
Cancel
Save