1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-21 13:58:08 +00:00

tests: add more granular silent language installation tests

This commit is contained in:
matejcik 2024-02-26 16:22:52 +01:00 committed by matejcik
parent 1909d1ebdb
commit 106793956c
2 changed files with 152 additions and 124 deletions

View File

@ -14,13 +14,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
from copy import deepcopy
from typing import Iterator
from typing import Any, Iterator
import pytest
from trezorlib import debuglink, device, exceptions, messages, models
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.debuglink import message_filters
from ..translations import LANGUAGES, build_and_sign_blob, get_lang_json, set_language
@ -145,39 +148,6 @@ def test_error_version_mismatch(client: Client):
_check_ping_screen_texts(client, get_ping_title("en"), get_ping_button("en"))
def test_error_invalid_header_version(client: Client):
assert client.features.language == "en-US"
# Invalid header version
# Version is not a valid semver with integers
with pytest.raises(ValueError), 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 == "en-US"
_check_ping_screen_texts(client, get_ping_title("en"), get_ping_button("en"))
def test_error_invalid_signature(client: Client):
assert client.features.language == "en-US"
# Invalid signature
# Changing the data in the signature section
with pytest.raises(
exceptions.TrezorFailure, match="Invalid translations data"
), client:
good_data = bytearray(build_and_sign_blob("cs", client.model))
bad_data = bytearray(good_data)
bad_data[128:256] = 128 * b"a"
device.change_language(
client,
language_data=bytes(bad_data),
)
assert client.features.language == "en-US"
_check_ping_screen_texts(client, get_ping_title("en"), get_ping_button("en"))
@pytest.mark.parametrize("lang", LANGUAGES)
def test_full_language_change(client: Client, lang: str):
assert client.features.language == "en-US"
@ -276,78 +246,96 @@ def test_reject_update(client: Client):
_check_ping_screen_texts(client, get_ping_title("en"), get_ping_button("en"))
def test_silent_update(client: Client):
assert client.features.language == "en-US"
lang = "cs"
def _maybe_confirm_set_language(
client: Client, lang: str, show_display: bool | None, is_displayed: bool
) -> None:
language_data = build_and_sign_blob(lang, client.model)
def input_flow_confirm(language: str):
if language == "cs":
title = "NASTAVENÍ JAZYKA"
text = "Změnit jazyk na cs-CZ?"
else:
title = "LANGUAGE SETTINGS"
text = "Change language to cs-CZ?"
CHUNK_SIZE = 1024
def input_flow():
yield
layout = client.debug.wait_layout()
assert layout.title() == title
assert layout.text_content() == text
client.debug.press_yes()
def chunks(data, size):
for i in range(0, len(data), size):
yield i, min(size, len(data) - i)
yield
layout = client.debug.wait_layout()
assert layout.text_content() == "Jazyk byl úspěšně změněn"
client.debug.press_yes()
expected_responses_silent: list[Any] = [
messages.TranslationDataRequest(data_offset=off, data_length=len)
for off, len in chunks(language_data, CHUNK_SIZE)
] + [message_filters.Success(), message_filters.Features()]
return input_flow
expected_responses_confirm = expected_responses_silent[:]
# confirmation after first TranslationDataRequest
expected_responses_confirm.insert(1, message_filters.ButtonRequest())
# success screen before Success / Features
expected_responses_confirm.insert(-2, message_filters.ButtonRequest())
def input_flow_silent():
yield
# It will never reach this - there is just loader on the screen
assert False
if is_displayed:
expected_responses = expected_responses_confirm
else:
expected_responses = expected_responses_silent
# Device is loaded with seed, language change is shown on the screen
with client:
client.watch_layout(True)
client.set_input_flow(input_flow_confirm("en"))
device.change_language(client, language_data)
client.set_expected_responses(expected_responses)
device.change_language(client, language_data, show_display=show_display)
assert client.features.language is not None
assert client.features.language[:2] == lang
device.wipe(client)
# explicitly handle the cases when expected_responses are correct for
# change_language but incorrect for selected is_displayed mode (otherwise the
# user would get an unhelpful generic expected_responses mismatch)
if is_displayed and client.actual_responses == expected_responses_silent:
raise AssertionError("Change should have been visible but was silent")
if not is_displayed and client.actual_responses == expected_responses_confirm:
raise AssertionError("Change should have been silent but was visible")
# if the expected_responses do not match either, the generic error message will
# be raised by the client context manager
@pytest.mark.parametrize(
"show_display, is_displayed",
[ # when device is not initialized, all combinations succeed.
(True, True),
(False, False),
(None, False), # default is False
],
)
@pytest.mark.setup_client(uninitialized=True)
def test_silent_first_install(client: Client, show_display: bool, is_displayed: bool):
assert not client.features.initialized
_maybe_confirm_set_language(client, "cs", show_display, is_displayed)
@pytest.mark.parametrize("show_display", (True, None))
def test_switch_from_english(client: Client, show_display: bool | None):
assert client.features.initialized
assert client.features.language == "en-US"
_maybe_confirm_set_language(client, "cs", show_display, True)
def test_switch_from_english_not_silent(client: Client):
assert client.features.initialized
assert client.features.language == "en-US"
with pytest.raises(
exceptions.TrezorFailure, match="Cannot change language without user prompt"
):
_maybe_confirm_set_language(client, "cs", False, False)
@pytest.mark.setup_client(uninitialized=True)
def test_switch_language(client: Client):
assert not client.features.initialized
assert client.features.language == "en-US"
# Device is empty, language is changed silently
with client:
client.watch_layout(True)
client.set_input_flow(input_flow_silent)
device.change_language(client, language_data)
assert client.features.language[:2] == lang
# switch to Czech silently
_maybe_confirm_set_language(client, "cs", False, False)
# Same language is set again, shown on screen
with client:
client.watch_layout(True)
client.set_input_flow(input_flow_confirm("cs"))
device.change_language(client, language_data)
assert client.features.language[:2] == lang
# switch to French silently
with pytest.raises(
exceptions.TrezorFailure, match="Cannot change language without user prompt"
):
_maybe_confirm_set_language(client, "fr", False, False)
device.wipe(client)
assert client.features.language == "en-US"
# switch to French with display, explicitly
_maybe_confirm_set_language(client, "fr", True, True)
debuglink.load_device(
client,
mnemonic=" ".join(["all"] * 12),
pin=None,
passphrase_protection=False,
label="test",
)
# Device is again loaded with seed, language change is shown on the screen
with client:
client.watch_layout(True)
client.set_input_flow(input_flow_confirm("en"))
device.change_language(client, language_data)
assert client.features.language[:2] == lang
_check_ping_screen_texts(client, get_ping_title(lang), get_ping_button(lang))
# switch back to Czech with display, implicitly
_maybe_confirm_set_language(client, "cs", None, True)

View File

@ -3649,8 +3649,6 @@
"TR_cs_test_language.py::test_error_invalid_data_hash": "71a89aedd03ff90c662b0190e0d467442b9ba8f75b42737c50eaf4d69817c6fa",
"TR_cs_test_language.py::test_error_invalid_data_length": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_error_invalid_header_magic": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_error_invalid_header_version": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_error_invalid_signature": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_error_too_long": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_error_version_mismatch": "02e362fe1a3c830bd5cec9a2fde39ad32453800ccc4f3caf00f629813d9b2ce0",
"TR_cs_test_language.py::test_full_language_change[cs]": "99d0b7bb982c85a962e32412c4c6453c6aea8b82f5d73ea2c306e1e8a831dea5",
@ -3660,7 +3658,13 @@
"TR_cs_test_language.py::test_full_language_change[fr]": "18ef4870bf5ee29d49ece9e92910bf3772e5bebde6c642929126d22a84086557",
"TR_cs_test_language.py::test_language_is_removed_after_wipe": "3fed5c087d565830eae7c0647a4c1ef9350595f550062ae575a97f50cdd7d826",
"TR_cs_test_language.py::test_reject_update": "94873b672e55ac3a766fe78cce140e27fe5fbbe4a837bc0e64bb46592ec5d4e3",
"TR_cs_test_language.py::test_silent_update": "a84304d3e385ec4058f0a24befad2258bbc05a2d16f4b72575c261229f5ed362",
"TR_cs_test_language.py::test_silent_first_install[False-False]": "cfca3550117beb0f44e6fecb844dfbbf2a182dd440a117398ff04603b6d365f2",
"TR_cs_test_language.py::test_silent_first_install[None-False]": "cfca3550117beb0f44e6fecb844dfbbf2a182dd440a117398ff04603b6d365f2",
"TR_cs_test_language.py::test_silent_first_install[True-True]": "980f87f189c299eabdea79fd17ee666798786f0abf040e3528d15da9ef64421c",
"TR_cs_test_language.py::test_switch_from_english[None]": "6be222894012b260aa66a38cff70ecd78b9f31f933c2d108de2ac08291cb8127",
"TR_cs_test_language.py::test_switch_from_english[True]": "6be222894012b260aa66a38cff70ecd78b9f31f933c2d108de2ac08291cb8127",
"TR_cs_test_language.py::test_switch_from_english_not_silent": "0014957129d3c34df2b2174c8fd770563e5f79e79b5152b22883b39569c4550e",
"TR_cs_test_language.py::test_switch_language": "3178eba877e67bef8f27429929b9130dcf6b6f98fadb0a830b9d45f3c4c0ae4a",
"TR_cs_test_language.py::test_translations_renders_on_screen": "be601d81b272fa966d1392ddf48e8ed522fcb4916bdb9c712a3c1c06c9ae553a",
"TR_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "d2e9ddb474a242c5bee49b3647d1151c3b078976b386d9a6408ddca8138096f3",
"TR_cs_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "e54ce8daf0f240096612320da0c75a794bcc021bf17d23b0af1a7ed2036443b4",
@ -5012,8 +5016,6 @@
"TR_de_test_language.py::test_error_invalid_data_hash": "001546a6d7d6fd797f5d358a85afbb653ab3dba0ee15650b38981149460e33ad",
"TR_de_test_language.py::test_error_invalid_data_length": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_error_invalid_header_magic": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_error_invalid_header_version": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_error_invalid_signature": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_error_too_long": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_error_version_mismatch": "84138ca1475cc52d9eb63b38826db3e857741f4da5194bd58a9fb3632ef9d9d5",
"TR_de_test_language.py::test_full_language_change[cs]": "b9b49f071757548a9502db2efef0ee7686f130e2a4fa1c01954b13e8a2d4833c",
@ -5023,7 +5025,13 @@
"TR_de_test_language.py::test_full_language_change[fr]": "fda57886e4c371f3219a29dd54b01de43e96bbb94a6fcc7d6c9e1bd1e7e30ace",
"TR_de_test_language.py::test_language_is_removed_after_wipe": "f330e4d64e824ff1f20541ccedba6fbb80ccdf61a3a5197eed59789db8f3216e",
"TR_de_test_language.py::test_reject_update": "c030eaa1b84ee548a68f0e20ad74201cbbeea1f09095dfafe0465020f3215a7a",
"TR_de_test_language.py::test_silent_update": "ed24fddb1ba9593380a12bad0a4b2b58cb0119ea83e717e83703eee7fc2fcc95",
"TR_de_test_language.py::test_silent_first_install[False-False]": "84a63e9be7b085d0b8ce087df8d575342a90157a52811decea69ba2083be41c1",
"TR_de_test_language.py::test_silent_first_install[None-False]": "84a63e9be7b085d0b8ce087df8d575342a90157a52811decea69ba2083be41c1",
"TR_de_test_language.py::test_silent_first_install[True-True]": "6108380651fe9016680a8f8b786ad37dd85bafc79c04c565a3b585abeb9f1c09",
"TR_de_test_language.py::test_switch_from_english[None]": "14b2652fcf2fbe73394c4ddaf035fa1830ec426a5cdf00b97b2a990fa070733f",
"TR_de_test_language.py::test_switch_from_english[True]": "14b2652fcf2fbe73394c4ddaf035fa1830ec426a5cdf00b97b2a990fa070733f",
"TR_de_test_language.py::test_switch_from_english_not_silent": "734df403a42da192b49b0bfc990db9f4b84e118c0b678da7e159e6a0c2a86896",
"TR_de_test_language.py::test_switch_language": "31ed10ba59a29b3c4a61e848cbb1a89fc31f03f9ad723bf358bc9654eeb9053a",
"TR_de_test_language.py::test_translations_renders_on_screen": "fffccd195b57d14281cb540af6aab7b3a7f92a4c99fccf0e879613fdb97b5aed",
"TR_de_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "30b469a1fb9e03d651dd0e07f705e7e7f834adaf03d06972c3c464a095820650",
"TR_de_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "10695655e2026fae50529e65dd58f2b21ed52fb9ac8df0d074c98e63bb849624",
@ -6375,8 +6383,6 @@
"TR_en_test_language.py::test_error_invalid_data_hash": "0cb01b8002472dff316d6eb3ba901dffb762d88fdf61e5ef8642ca7772d3e71c",
"TR_en_test_language.py::test_error_invalid_data_length": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_error_invalid_header_magic": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_error_invalid_header_version": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_error_invalid_signature": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_error_too_long": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_error_version_mismatch": "4ffbed72e7ed7fbab85f830952200adf7758af81b658b56de4672344120456a6",
"TR_en_test_language.py::test_full_language_change[cs]": "ba3669f5c7043e8021d84589d5c173eb1d3f6b2402f1e31525ce832094ca1e20",
@ -6386,7 +6392,13 @@
"TR_en_test_language.py::test_full_language_change[fr]": "2f3a0e8541cc7b96dc983d4de2149e4e2b230b43e1971153ec6bc82e7dadafb8",
"TR_en_test_language.py::test_language_is_removed_after_wipe": "5363564a612486602f3e6c94cb5d18ef82c2253dfe51df4623d56b5bab920a2e",
"TR_en_test_language.py::test_reject_update": "949fb112e684d3fb8a204a8ce15a202ebe9613bd3a453408138b3e54bb42e99a",
"TR_en_test_language.py::test_silent_update": "d8bc60cdfdce974b5e7259b7910c4178ae2b29a9a185fefe730c131fafba750c",
"TR_en_test_language.py::test_silent_first_install[False-False]": "8c6d7a8d499e4ede3d42cb6ef67cbde9f7dd35d518bacaa538e900bf3944b250",
"TR_en_test_language.py::test_silent_first_install[None-False]": "8c6d7a8d499e4ede3d42cb6ef67cbde9f7dd35d518bacaa538e900bf3944b250",
"TR_en_test_language.py::test_silent_first_install[True-True]": "2cdc473638078db0ed9406d904c2198946de9c31093df69268a6de87545c8ab6",
"TR_en_test_language.py::test_switch_from_english[None]": "47bd3a1f3c7ac6c6fec5c9c22219c6c638375f4810043ca29312fd3755356655",
"TR_en_test_language.py::test_switch_from_english[True]": "47bd3a1f3c7ac6c6fec5c9c22219c6c638375f4810043ca29312fd3755356655",
"TR_en_test_language.py::test_switch_from_english_not_silent": "8c801bd0142e5c1ad4aad50b34c7debb1b8f17a2e0a87eb7f95531b9fd15e095",
"TR_en_test_language.py::test_switch_language": "d227f924d8b76642511d25f78c646be6232c71db4d40fe6916b4364a58e70c4a",
"TR_en_test_language.py::test_translations_renders_on_screen": "baf3b0e15c9ccced6ce4d4fb4d026d61cee7d7e557434aa6dbfbc78d1dd54420",
"TR_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "fc78876e183a82d8099263e5b3858620f65f7842f7d31f4679dddcb045f1dfb2",
"TR_en_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "57dc2b38db364a7ba43566c700ab27a3e98a08e64efc564db53b61aa6f4098aa",
@ -7738,8 +7750,6 @@
"TR_es_test_language.py::test_error_invalid_data_hash": "1e4a266ea51d55976cf4a1f8655e58629092b617c9d36e0603a5081961130564",
"TR_es_test_language.py::test_error_invalid_data_length": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_error_invalid_header_magic": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_error_invalid_header_version": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_error_invalid_signature": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_error_too_long": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_error_version_mismatch": "7fe6f34be4850fe62d0125548db36aa49493f7ef08781916025877445700ccae",
"TR_es_test_language.py::test_full_language_change[cs]": "5499d72b948c2b12fbf42cab072a8fea155a759a144930b7786104b32391e490",
@ -7749,7 +7759,13 @@
"TR_es_test_language.py::test_full_language_change[fr]": "0f7df785e611deec165dcce914efbabb497cba640795c8b90f396c223af7f3f0",
"TR_es_test_language.py::test_language_is_removed_after_wipe": "7a7d05f7feed0938e23ec6ac76133246f6dbd626969efe43b0122bb2801e4e93",
"TR_es_test_language.py::test_reject_update": "72b5cc4bb1d3a1024ef5348356565e711392fc379afee08a9d4275b7d627c213",
"TR_es_test_language.py::test_silent_update": "f1205df1c47f4b200af848b150c72b66dfcf7ebd20c2087a31341047a198a92d",
"TR_es_test_language.py::test_silent_first_install[False-False]": "fe722b1d027ca3b5af955c350722176de874b9d22446492a1b80d3f74d5bebfe",
"TR_es_test_language.py::test_silent_first_install[None-False]": "fe722b1d027ca3b5af955c350722176de874b9d22446492a1b80d3f74d5bebfe",
"TR_es_test_language.py::test_silent_first_install[True-True]": "0033ba8e0e156f7a2f80caafd1c899572717ee7da0785f2d2269ac418e2c45c5",
"TR_es_test_language.py::test_switch_from_english[None]": "81cc930de51884130ce9db2436a174f82b35f5f63355b1c0c3b1e78bc3a00ba8",
"TR_es_test_language.py::test_switch_from_english[True]": "81cc930de51884130ce9db2436a174f82b35f5f63355b1c0c3b1e78bc3a00ba8",
"TR_es_test_language.py::test_switch_from_english_not_silent": "a9b0e47be4dac0a6e99582439a6225527e8e365b7e74cca03892675853b1a152",
"TR_es_test_language.py::test_switch_language": "2993b2aecba562707e306426b9de9c041785f82d47ffbafdb5d558f6648b3265",
"TR_es_test_language.py::test_translations_renders_on_screen": "300210d6d6cb920795fcbaf5efabadfa10a06462a311bbf1428e6ac6b80a40de",
"TR_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "158963b7b966fe95b92d8a4be19971c5321847154c2e574de04e361750537569",
"TR_es_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "2e80ee5ab2d87d55f9c96460eda140a7074faa2d5237d23057de2b12cbbb61ec",
@ -9101,8 +9117,6 @@
"TR_fr_test_language.py::test_error_invalid_data_hash": "c3c594c2d963c7562250b5cae43e6933a6c67c8b7aa7063e58de94e56fdad446",
"TR_fr_test_language.py::test_error_invalid_data_length": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_error_invalid_header_magic": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_error_invalid_header_version": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_error_invalid_signature": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_error_too_long": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_error_version_mismatch": "cb1cd75e37f30dacba9ccd6d4a9d0ada0179a8ac056340ce16edb802d16fac8c",
"TR_fr_test_language.py::test_full_language_change[cs]": "7715e87e6a60006e6d6c61cde25ba2bc88540bd078f56d39ba1919e53e2dba99",
@ -9112,7 +9126,13 @@
"TR_fr_test_language.py::test_full_language_change[fr]": "7fae72778d7111b0d7746ce3fdfdae724415f651b2c3e195da55dc3cf6e24f8e",
"TR_fr_test_language.py::test_language_is_removed_after_wipe": "9c12ba731cef7dd8a2fbb421aa328af48ed383b9d4ea4edb6cfbe6bd7a594115",
"TR_fr_test_language.py::test_reject_update": "4c1d851a4f7ca6075e71d096a4b124b31f8ff280d609cc2495ded9750f057b51",
"TR_fr_test_language.py::test_silent_update": "cf65c68c90b206e2a97c9bf51d9e149b4197a7b050f3a6af4aa96a15254d980e",
"TR_fr_test_language.py::test_silent_first_install[False-False]": "79baf3cf0b204f265a80ce571552b1fb082aeb72cc37d515b6682365a6ebeae4",
"TR_fr_test_language.py::test_silent_first_install[None-False]": "79baf3cf0b204f265a80ce571552b1fb082aeb72cc37d515b6682365a6ebeae4",
"TR_fr_test_language.py::test_silent_first_install[True-True]": "41aa1b307824a1a11a0b6c5cf8651ff5c5e10cce93fd00523c9f4fa479a4c69b",
"TR_fr_test_language.py::test_switch_from_english[None]": "bb46ea113250150bd51ca80987a2ed75b33b6d35b26281a22411f158a4204bef",
"TR_fr_test_language.py::test_switch_from_english[True]": "bb46ea113250150bd51ca80987a2ed75b33b6d35b26281a22411f158a4204bef",
"TR_fr_test_language.py::test_switch_from_english_not_silent": "2d59eedb25da2468512d9576ef7d7f4528804d4fb8bb1921d4ee8d4d20d91196",
"TR_fr_test_language.py::test_switch_language": "c661df1f59509ae664e8731b444bcaf23b6068b49b28bf36b5733b6fba7fce25",
"TR_fr_test_language.py::test_translations_renders_on_screen": "8b10d800ab66299a70c2bc569138031b5d9bd7be519980e180b7853433037cae",
"TR_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_good": "61e42f4eef33a9f482a1593dc245186e26883d3b78e3d48af1651bfb5fe6e3d6",
"TR_fr_test_msg_applysettings.py::test_apply_homescreen_tr_toif_with_long_label": "184525975dc813659ec4b463cd09b71eefa7ddb250f01dd34b3c1a0010d203ed",
@ -10771,8 +10791,6 @@
"TT_cs_test_language.py::test_error_invalid_data_hash": "f839ad9340a0fbc2c26aeacd077a278c90b1544c62c185f403c4e791b00d232a",
"TT_cs_test_language.py::test_error_invalid_data_length": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_error_invalid_header_magic": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_error_invalid_header_version": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_error_invalid_signature": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_error_too_long": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_error_version_mismatch": "011d289134e070f0f1b21939ddd9dc8003ab02c8ff29db2db8b349eed7478b92",
"TT_cs_test_language.py::test_full_language_change[cs]": "b837b129f22886f15e2cf5183adc44561ba24de2848097fbbbfc6c44fd34728d",
@ -10782,7 +10800,13 @@
"TT_cs_test_language.py::test_full_language_change[fr]": "5b6297ad7b03664e18a95b8eb32ff4f0fd76f827da64559e09815fa506812440",
"TT_cs_test_language.py::test_language_is_removed_after_wipe": "a3ae02a5a95dbfa4ffde27c66ab3b5a766aa0e84e04c64504c19a3ae432d0e8b",
"TT_cs_test_language.py::test_reject_update": "baabea339f79af37b0184349a1d1e360cbbf111fc8fe8c7bf89f6ee8b6091cbb",
"TT_cs_test_language.py::test_silent_update": "9cca353e4b1a07d422b09bd1477705283fcfcc157f6c6a724a5c352df2216033",
"TT_cs_test_language.py::test_silent_first_install[False-False]": "b8494f22dfd7426af61780d585cedbdfbdd20c65721cc50e599e6f0c97aec1cb",
"TT_cs_test_language.py::test_silent_first_install[None-False]": "b8494f22dfd7426af61780d585cedbdfbdd20c65721cc50e599e6f0c97aec1cb",
"TT_cs_test_language.py::test_silent_first_install[True-True]": "6f6459ab5c1f6c307019b9d5aea2e4f5a09c1d970770f2b6cef2d6b0f5c6d9f4",
"TT_cs_test_language.py::test_switch_from_english[None]": "e9797de1f140ecdfcf8922b67e663ba7af1730d53ff38b4a1f33f484b38396f5",
"TT_cs_test_language.py::test_switch_from_english[True]": "e9797de1f140ecdfcf8922b67e663ba7af1730d53ff38b4a1f33f484b38396f5",
"TT_cs_test_language.py::test_switch_from_english_not_silent": "24633a26cdca3b628311460762d4a3bd6de6ac3d12475175dd24420fe8df40a3",
"TT_cs_test_language.py::test_switch_language": "9cd751812d02a2dce1dbe4d7b49f247286e490c25cc46a5e45e2140df1ada6e9",
"TT_cs_test_language.py::test_translations_renders_on_screen": "29e8127373ad1c7c383deaa04f8bdcaca8f245eefcc710b3b50ceb5d1f154b22",
"TT_cs_test_msg_applysettings.py::test_apply_homescreen_jpeg": "9fad96569555ce39a883e478c87d5c5f1f08a25458833834b27b4285d66ada47",
"TT_cs_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "b5a62384cb7191d76f1a33b653ae1491788dbc611f484742707c95602298af87",
@ -12214,8 +12238,6 @@
"TT_de_test_language.py::test_error_invalid_data_hash": "449c596f93b1a7833e9631c0d8fe1f3f09eb64f3bf6006cf0ed22f08d051e263",
"TT_de_test_language.py::test_error_invalid_data_length": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_error_invalid_header_magic": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_error_invalid_header_version": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_error_invalid_signature": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_error_too_long": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_error_version_mismatch": "aa98140621cbb05cbaaad67e2fbaeba12f6d5ece97cb5cef993b6a263cce38b2",
"TT_de_test_language.py::test_full_language_change[cs]": "14d372b0e5e896a15209b36c23196fa2b445124ff07eac3e8e550f79ef53fc52",
@ -12225,7 +12247,13 @@
"TT_de_test_language.py::test_full_language_change[fr]": "256177588435bf75d7bb339e835a6e79f8d10314f155784047b9d5a77a5c5e72",
"TT_de_test_language.py::test_language_is_removed_after_wipe": "5b9f5817ba4e243d41262887aa338bb674f700ce47e1b50bc564cfd665876799",
"TT_de_test_language.py::test_reject_update": "adef723d293c68592689b4fafbe87e6811656e6ea962484474594ce8f2407b4b",
"TT_de_test_language.py::test_silent_update": "eb921dc09253bc1019b737134880cb8b463b8ea8d2286c5a1acdad1d2fccec82",
"TT_de_test_language.py::test_silent_first_install[False-False]": "629c908f9d1d76b1248297c5a2eb9ee4933d54c53003329599312d6f292d4c7d",
"TT_de_test_language.py::test_silent_first_install[None-False]": "629c908f9d1d76b1248297c5a2eb9ee4933d54c53003329599312d6f292d4c7d",
"TT_de_test_language.py::test_silent_first_install[True-True]": "b5c51aa5234462c28aebbb1eb08d95da257557508b81b5e062ff05d893864b64",
"TT_de_test_language.py::test_switch_from_english[None]": "e058c2547a47e5592f0101ae076fd524dba3a5586ab6ba0f8ed679c1d6641535",
"TT_de_test_language.py::test_switch_from_english[True]": "e058c2547a47e5592f0101ae076fd524dba3a5586ab6ba0f8ed679c1d6641535",
"TT_de_test_language.py::test_switch_from_english_not_silent": "f3c1080628d56137fa597f86b6b11a6442ac36d30bc4630a1da1f9c662838b1f",
"TT_de_test_language.py::test_switch_language": "4987d445aa4db7d2b9728c44bed8123b2b080c432e36248083a32ba9f3198e57",
"TT_de_test_language.py::test_translations_renders_on_screen": "00ec765b78d1751da86f8e1a40b93670a57a7e57ce6c06a1d6f5631cbbedb2df",
"TT_de_test_msg_applysettings.py::test_apply_homescreen_jpeg": "1b11556c545da921ec13699de08ebbcfcd5482975a6cab5933af547c1c190e54",
"TT_de_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "eddbeacf3bd533bd744db1675b8c13814c7b212aa894e7a7adf5b93005af4d13",
@ -13657,8 +13685,6 @@
"TT_en_test_language.py::test_error_invalid_data_hash": "67782b952469c260afac92bac1efc2ba9c2f342319ae95fb5e91c843da2a6e46",
"TT_en_test_language.py::test_error_invalid_data_length": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_error_invalid_header_magic": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_error_invalid_header_version": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_error_invalid_signature": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_error_too_long": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_error_version_mismatch": "d702b0f90581cf17e0f77b4d318324a002deec42c2c5cb8860d51f6cb50f5739",
"TT_en_test_language.py::test_full_language_change[cs]": "1359095f8b87e599c6fd88c15dd257c09c4afb3095d4db671e1746dfc4017604",
@ -13668,7 +13694,13 @@
"TT_en_test_language.py::test_full_language_change[fr]": "a6b00695cb76f4fcc7197d37df49c3b1997da6ed23f2c21330d30e0f28dc910d",
"TT_en_test_language.py::test_language_is_removed_after_wipe": "20955fc2d8ae93c616be7041440c1e86a6a92e3235b352abdf0f17d95319d600",
"TT_en_test_language.py::test_reject_update": "78b8f16e00c5d653a7d5c0929d21ae8ae1c76798fe28f0eb6edee8e2ee8b0202",
"TT_en_test_language.py::test_silent_update": "adc7d11983056a7fc66669c23162c2f09e8d65bc3992f2037ce7092ed4af1410",
"TT_en_test_language.py::test_silent_first_install[False-False]": "bbd64861dce4334f1d4a49cdccf981c854b72fe6807adfa516d115337eb60a36",
"TT_en_test_language.py::test_silent_first_install[None-False]": "bbd64861dce4334f1d4a49cdccf981c854b72fe6807adfa516d115337eb60a36",
"TT_en_test_language.py::test_silent_first_install[True-True]": "731c195ff8462396a6d3b1acc9b41d9258d96ac5053e777b9f3906a5611ea4be",
"TT_en_test_language.py::test_switch_from_english[None]": "d4072a9dae776c7fec7eae5f2ef1d9e944d0927b368d9f1e0a1c3fe8f6e2919a",
"TT_en_test_language.py::test_switch_from_english[True]": "d4072a9dae776c7fec7eae5f2ef1d9e944d0927b368d9f1e0a1c3fe8f6e2919a",
"TT_en_test_language.py::test_switch_from_english_not_silent": "80a6e289138a604cf351a29511cf6f85e2243591317894703152787e1351a1a3",
"TT_en_test_language.py::test_switch_language": "ea97a14817a6343259ad69aa1fa0ef06509ab9052d896fe67db64a98ecc643c0",
"TT_en_test_language.py::test_translations_renders_on_screen": "5af6cd73525ef98f4151bf97d73bd92be0866bc99406f339a4aeab95e3a95048",
"TT_en_test_msg_applysettings.py::test_apply_homescreen_jpeg": "0e2a71ac60add6bebc03645b6f4f6f19abdba56f1e55e799479b116e5a66aef6",
"TT_en_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "4d7c67024ee17436071e5cf2f79c36453249c95314a732580623cb1f1cdbfdf3",
@ -15118,8 +15150,6 @@
"TT_es_test_language.py::test_error_invalid_data_hash": "1af05b4747855d9479d1d34bd3f1bc17cfe57f60a5c7bfdb4e93ceb331f13b2b",
"TT_es_test_language.py::test_error_invalid_data_length": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_error_invalid_header_magic": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_error_invalid_header_version": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_error_invalid_signature": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_error_too_long": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_error_version_mismatch": "cece2fdd44e917f03f20485e030d2ae3a614143360ce784cc7a3f43da9751f46",
"TT_es_test_language.py::test_full_language_change[cs]": "a786fa6053511bd1be10fd59016991fa079e8ee3c565d6533568d690541412e3",
@ -15129,7 +15159,13 @@
"TT_es_test_language.py::test_full_language_change[fr]": "a8d92d89b104b2fc3ee65e17d870366fd22fa910d2971d1c61319078a15244bc",
"TT_es_test_language.py::test_language_is_removed_after_wipe": "6a92f98a10478ddc916f0b8f6c56b13cae1f458a9ad86eb6c8f46a9033abcdec",
"TT_es_test_language.py::test_reject_update": "107634fbdacc72337abd7de1291904e6297bf5dd9551163780a1438b6d965949",
"TT_es_test_language.py::test_silent_update": "605a09f42c127ef4467b88b8173cc7f113e5d28b31c74512b331b74e074d689f",
"TT_es_test_language.py::test_silent_first_install[False-False]": "b307450f1f7e6118118b631c8354e9acb89f90f5755294ebb45b610ee8fc23c2",
"TT_es_test_language.py::test_silent_first_install[None-False]": "b307450f1f7e6118118b631c8354e9acb89f90f5755294ebb45b610ee8fc23c2",
"TT_es_test_language.py::test_silent_first_install[True-True]": "bc9bdd3d18dd96508b582f2857db7fc0a82a07a33da183c83175303bc5d0eee6",
"TT_es_test_language.py::test_switch_from_english[None]": "9dd9403584a75607f9f42ca859bf30b2ba1ac7d90ae923a52317d946cdbe6ee2",
"TT_es_test_language.py::test_switch_from_english[True]": "9dd9403584a75607f9f42ca859bf30b2ba1ac7d90ae923a52317d946cdbe6ee2",
"TT_es_test_language.py::test_switch_from_english_not_silent": "2798ba0027990ef7dfbadb74ec534fad4cb2698a62a6faf891f90b8cc3b874e2",
"TT_es_test_language.py::test_switch_language": "bebdee51e66ac9568e79a2c4b6f29306fea00cf9655c3a90c54611be1f239aa3",
"TT_es_test_language.py::test_translations_renders_on_screen": "2e945f0cd09141d24d86a2b9619581088a0ea5ec157379da4e7149459c65fc32",
"TT_es_test_msg_applysettings.py::test_apply_homescreen_jpeg": "86311915f84c811d5b011af80327112f650baa241bcb019ba58276fa27685e45",
"TT_es_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "a94fffcba3fdd453aa33c43a34d8522cd47bf215e4848bb887f4769dc5420665",
@ -16561,8 +16597,6 @@
"TT_fr_test_language.py::test_error_invalid_data_hash": "43d82fabe548153d7cbde335cd0e80ac0d444ba58628b0a4fef503817d2fb82b",
"TT_fr_test_language.py::test_error_invalid_data_length": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_error_invalid_header_magic": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_error_invalid_header_version": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_error_invalid_signature": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_error_too_long": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_error_version_mismatch": "cf1b79fdfa5643710dabe6a0dc9abc8ebf227f617e7bc2214bcffe465dc81670",
"TT_fr_test_language.py::test_full_language_change[cs]": "447d14f4f54f2b9e7f894514770d73a47958503a93983fb48b8f54f2c8e1fa8a",
@ -16572,7 +16606,13 @@
"TT_fr_test_language.py::test_full_language_change[fr]": "f59be182fa1ff0bfb9230b69a49dabfed30394618e2eaf11597c8a109a7bab95",
"TT_fr_test_language.py::test_language_is_removed_after_wipe": "a474ebb565e9e2fc01647fe2ae739519f25807562abe757ac55d20814b3458af",
"TT_fr_test_language.py::test_reject_update": "1ea4e3f645e5d788714b61525c0eee446a306f2844fec383460e45574f9a5de5",
"TT_fr_test_language.py::test_silent_update": "22785c108bee4ac76af3a923a9d35a316d9153fefb9221a855912eab24fd3d32",
"TT_fr_test_language.py::test_silent_first_install[False-False]": "d0046d29c419e87c0f3881d7c9308c9621dc111a6b5a914eb8bd63266a7d7b91",
"TT_fr_test_language.py::test_silent_first_install[None-False]": "d0046d29c419e87c0f3881d7c9308c9621dc111a6b5a914eb8bd63266a7d7b91",
"TT_fr_test_language.py::test_silent_first_install[True-True]": "9c67d06a18c5c1c8f7016c5280d9275a6eb7d3b5672e0da276c0a01b102e80cf",
"TT_fr_test_language.py::test_switch_from_english[None]": "9fcd8061d44e55942221e65c13f20c39b0e36619e236e7a7c2bbd3e43abab322",
"TT_fr_test_language.py::test_switch_from_english[True]": "9fcd8061d44e55942221e65c13f20c39b0e36619e236e7a7c2bbd3e43abab322",
"TT_fr_test_language.py::test_switch_from_english_not_silent": "44384285d55f517fd9644ea67051c07c34dad16b278eb4b2534091581756979e",
"TT_fr_test_language.py::test_switch_language": "b8fa1068af12657179987aa8d31c665dc53d2ab1304c67e4968bb63d7a9ff1cb",
"TT_fr_test_language.py::test_translations_renders_on_screen": "3704b37de0d90dfe0f9d2451b2920787d1d0da3c102d93e43f98e00a888811c5",
"TT_fr_test_msg_applysettings.py::test_apply_homescreen_jpeg": "7dd352a6c4e12d3cad9e6ef85541941c4c0cdd57d6b2a9b5d312d3ea055ac51c",
"TT_fr_test_msg_applysettings.py::test_apply_homescreen_jpeg_progressive": "a96ae889c91bb377c6932cd37e0ce914bd4d8ab551b553d5f6f5d2ab6e9f7e0f",