From 8b12a77a3bcad1b191a06bcf0d9a38a5e5ea74a1 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Mon, 10 Feb 2025 20:05:24 +0200 Subject: [PATCH] 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] --- .github/actions/ui-report/action.yml | 2 +- .github/workflows/core.yml | 5 +++-- tests/conftest.py | 16 ++++------------ tests/emulators.py | 24 ++++++++++++++++++++++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/.github/actions/ui-report/action.yml b/.github/actions/ui-report/action.yml index 080cc5ab6b..646a1198ed 100644 --- a/.github/actions/ui-report/action.yml +++ b/.github/actions/ui-report/action.yml @@ -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 diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 2b9ea58130..b1c565f5fa 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -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 diff --git a/tests/conftest.py b/tests/conftest.py index 05e6622e1b..004a3b7b66 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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(), diff --git a/tests/emulators.py b/tests/emulators.py index 9a227c7b76..4f69d1eaff 100644 --- a/tests/emulators.py +++ b/tests/emulators.py @@ -14,6 +14,8 @@ # You should have received a copy of the License along with this library. # If not, see . +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()