1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-12 15:42:40 +00:00

ci(core): collect debug logs also from multicore tests

Otherwise, tailing and uploading when running `make test_emu_ui_multicore` fail:
https://github.com/trezor/trezor-firmware/actions/runs/13049022289/job/36405211984?pr=4558

[no changelog]
This commit is contained in:
Roman Zeyde 2025-02-10 20:05:24 +02:00 committed by Roman Zeyde
parent 75ffe1d6bd
commit 8b12a77a3b
4 changed files with 30 additions and 17 deletions

View File

@ -26,7 +26,7 @@ runs:
nix-shell --run "poetry run python ci/prepare_ui_artifacts.py || true"
mv tests/ui_tests/reports/test/* $OUTDIR || true
mv tests/ui_tests/fixtures.*.json $OUTDIR || true
mv tests/trezor.log $OUTDIR || true
mv tests/trezor*.log $OUTDIR || true
diff -u tests/ui_tests/fixtures.json tests/ui_tests/fixtures.suggestion.json || true
tar -cf screens_$MODELJOB.tar tests/ui_tests/screens || true

View File

@ -264,6 +264,7 @@ jobs:
TREZOR_PROFILING: ${{ matrix.asan == 'noasan' && '1' || '0' }}
TREZOR_MODEL: ${{ matrix.model }}
TREZOR_PYTEST_SKIP_ALTCOINS: ${{ matrix.coins == 'btconly' && '1' || '0' }}
TREZOR_PYTEST_LOGS_DIR: ${{ github.workspace }}/tests/
ADDRESS_SANITIZER: ${{ matrix.asan == 'asan' && '1' || '0' }}
PYTEST_TIMEOUT: ${{ matrix.asan == 'asan' && 600 || 400 }}
ACTIONS_DO_UI_TEST: ${{ matrix.coins == 'universal' && matrix.asan == 'noasan' }}
@ -279,12 +280,12 @@ jobs:
- run: chmod +x core/build/unix/trezor-emu-core*
- uses: ./.github/actions/environment
- run: nix-shell --run "poetry run make -C core ${{ env.ACTIONS_DO_UI_TEST == 'true' && 'test_emu_ui_multicore' || 'test_emu' }}"
- run: tail -n50 tests/trezor.log || true
- run: tail -v -n50 tests/trezor*.log || true
if: failure()
- uses: actions/upload-artifact@v4
with:
name: core-test-device-${{ matrix.model }}-${{ matrix.coins }}-${{ matrix.lang }}-${{ matrix.asan }}
path: tests/trezor.log
path: tests/trezor*.log
retention-days: 7
if: always()
- uses: ./.github/actions/ui-report

View File

@ -111,21 +111,13 @@ def emulator(request: pytest.FixtureRequest) -> t.Generator["Emulator", None, No
"Legacy emulator is not supported until it can be run on arbitrary ports."
)
def _get_port() -> int:
"""Get a unique port for this worker process on which it can run.
Guarantees to be unique because each worker has a different name.
gw0=>20000, gw1=>20003, gw2=>20006, etc.
"""
worker_id = xdist.get_xdist_worker_id(request)
assert worker_id.startswith("gw")
# One emulator instance occupies 3 consecutive ports:
# 1. normal link, 2. debug link and 3. webauthn fake interface
return 20000 + int(worker_id[2:]) * 3
worker_id = xdist.get_xdist_worker_id(request)
assert worker_id.startswith("gw")
worker_id = int(worker_id[2:])
with EmulatorWrapper(
model,
port=_get_port(),
worker_id=worker_id,
headless=True,
auto_interact=not interact,
main_args=_emulator_wrapper_main_args(),

View File

@ -14,6 +14,8 @@
# 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 os
import shutil
import tempfile
from collections import defaultdict
from pathlib import Path
@ -66,13 +68,24 @@ def get_tags() -> Dict[str, List[str]]:
ALL_TAGS = get_tags()
def _get_port(worker_id: int) -> int:
"""Get a unique port for this worker process on which it can run.
Guarantees to be unique because each worker has a unique ID.
#0=>20000, #1=>20003, #2=>20006, etc.
"""
# One emulator instance occupies 3 consecutive ports:
# 1. normal link, 2. debug link and 3. webauthn fake interface
return 20000 + worker_id * 3
class EmulatorWrapper:
def __init__(
self,
gen: str,
tag: Optional[str] = None,
storage: Optional[bytes] = None,
port: Optional[int] = None,
worker_id: int = 0,
headless: bool = True,
auto_interact: bool = True,
main_args: Sequence[str] = ("-m", "main"),
@ -91,6 +104,7 @@ class EmulatorWrapper:
else:
workdir = None
self.worker_id = worker_id
if gen == "legacy":
self.emulator = LegacyEmulator(
executable,
@ -105,7 +119,7 @@ class EmulatorWrapper:
self.profile_dir.name,
storage=storage,
workdir=workdir,
port=port,
port=_get_port(worker_id),
headless=headless,
auto_interact=auto_interact,
main_args=main_args,
@ -121,4 +135,10 @@ class EmulatorWrapper:
def __exit__(self, exc_type, exc_value, traceback) -> None:
self.emulator.stop()
logs_dir = os.environ.get("TREZOR_PYTEST_LOGS_DIR")
if logs_dir is not None:
src = Path(self.profile_dir.name) / "trezor.log"
dst = Path(logs_dir) / f"trezor-{self.worker_id}.log"
shutil.move(src, dst)
self.profile_dir.cleanup()