Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- run: sudo apt-get install -y pycodestyle
- run: pycodestyle --statistics --exclude translations ports/stm32/boards/Passport
- run: pycodestyle --statistics ports/stm32/boards/Passport

is-foundation-header-up-to-date:
name: Is foundation.h header file up to date?
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/simulator-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: © 2026 Foundation Devices, Inc. <hello@foundation.xyz>
# SPDX-License-Identifier: GPL-3.0-or-later

name: Simulator tests
on: [push, pull_request]

jobs:
simulator-tests-pass:
name: Simulator tests pass?
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31
- run: sudo apt-get install -y xvfb
- run: xvfb-run -a nix develop .#build -c just test
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ sim screen="mono" ext="":
# Run unit tests.
test:
just simulator/build color
cd ports/stm32/boards/Passport/modules/tests; python3 -m pytest . --simulatordir=$(pwd)/simulator
cd ports/stm32/boards/Passport/modules/tests && python3 -m pytest . --simulatordir={{justfile_directory()}}/simulator

# Lint the codebase.
lint: (run-in-docker "just ports/stm32/lint") (run-in-docker "just extmod/foundation-rust/lint")
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,15 @@
openssl
pkg-config
python3
python3Packages.autopep8
python3Packages.imageio
python3Packages.opencv4
python3Packages.pip
python3Packages.pillow
python3Packages.pytest
python3Packages.pysdl2
python3Packages.virtualenv
python3Packages.autopep8
SDL2
reuse
rust-cbindgen
xterm
Expand All @@ -145,7 +151,6 @@
fontmiscmisc
minicom
openocd
SDL2
]);


Expand Down
2 changes: 1 addition & 1 deletion ports/stm32/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ init-openocd:

# Lint only the python code of the project
lint-py:
pycodestyle --exclude trezor-firmware,unused_modules,graphics.py,translations --statistics boards/Passport
pycodestyle --exclude trezor-firmware,unused_modules,graphics.py --statistics boards/Passport

# Lint only the C code of the project
lint-c:
Expand Down
6 changes: 0 additions & 6 deletions ports/stm32/boards/Passport/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,6 @@
'tasks/verify_backup_task.py',
'tasks/verify_firmware_signature_task.py'))

# Translations
freeze('$(MPY_DIR)/ports/stm32/boards/Passport/modules',
('translations/__init__.py',
'translations/en.py',
'translations/tags.py'))

# UI
freeze('$(MPY_DIR)/ports/stm32/boards/Passport/modules',
('ui/__init__.py',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pages import PINEntryPage, ErrorPage, SuccessPage
from tasks import change_pin_task
from utils import spinner_task
from translations import t, T
import microns
from common import settings
from serializations import sha256
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from pages import ErrorPage, SuccessPage, QuestionPage, ErrorPage
from tasks import delete_account_task
from utils import spinner_task
from translations import t, T


class DeleteAccountFlow(Flow):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# delete_multisig_flow.py - Delete the specified multisig config

from flows import Flow
from translations import t, T


class DeleteMultisigFlow(Flow):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from pages import SuccessPage, QuestionPage, LongQuestionPage
from tasks import erase_passport_task
from utils import spinner_task
from translations import t, T
import microns
import passport

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from pages import ErrorPage, SuccessPage, TextInputPage, ErrorPage
from tasks import save_new_account_task
from utils import get_account_by_name, get_account_by_number, get_accounts_by_xfp, spinner_task
from translations import t, T
from wallets.utils import get_next_account_num
from common import settings

Expand Down
1 change: 0 additions & 1 deletion ports/stm32/boards/Passport/modules/flows/new_seed_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pages import ErrorPage, QuestionPage, SuccessPage, YesNoChooserPage
from tasks import new_seed_task, save_seed_task
from utils import has_secrets, spinner_task
from translations import t, T
import lvgl as lv
import microns

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from pages import ErrorPage, SuccessPage, TextInputPage, ErrorPage
from tasks import rename_account_task
from utils import get_account_by_name, spinner_task
from translations import t, T


class RenameAccountFlow(Flow):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

from flows import Flow
import microns
from translations import t, T


class RenameMultisigFlow(Flow):
Expand Down
1 change: 0 additions & 1 deletion ports/stm32/boards/Passport/modules/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import gc
from utils import mem_info
# from translations import T, t, set_active_language

mem_info(label='Start main.py:')

Expand Down
83 changes: 68 additions & 15 deletions ports/stm32/boards/Passport/modules/tests/fixtures/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,102 @@

import pytest
import os
import signal
import subprocess
import time


class SimulatorSocket:
UNIX_SOCKET_PATH = b'/tmp/passport-simulator.sock'
TEST_SPI_FLASH_PATH = 'work/test_spi_flash.bin'

def __init__(self, simulator_dir):
self.simulator_dir = simulator_dir
self.pipe = None
self._open(simulator_dir)
self._connect()
self.process = None
self.socket_path = None
try:
self._open(simulator_dir)
self._connect()
except BaseException:
self.close()
raise

def _open(self, simulator_dir):
import subprocess

self._remove_server_socket()
self._remove_test_spi_flash(simulator_dir)
simulator_cmd = simulator_dir + '/simulator.py'
self.process = subprocess.Popen([simulator_cmd, 'color', '--unit-test'], cwd=simulator_dir,
preexec_fn=os.setsid)

def _remove_server_socket(self):
try:
os.unlink(self.UNIX_SOCKET_PATH)
except FileNotFoundError:
pass

def _remove_test_spi_flash(self, simulator_dir):
try:
os.unlink(simulator_dir + '/' + self.TEST_SPI_FLASH_PATH)
except FileNotFoundError:
pass

def _connect(self):
import socket
import tempfile

self.pipe = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
deadline = time.monotonic() + 10
while True:
try:
self.pipe.connect(self.UNIX_SOCKET_PATH)
break
except Exception:
continue
except OSError:
if self.process.poll() is not None:
raise RuntimeError(
'Simulator exited before opening its socket '
f'(exit code {self.process.returncode})'
)
if time.monotonic() >= deadline:
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
raise TimeoutError('Simulator did not open its socket within 10 seconds')
time.sleep(0.01)

while True:
try:
addr = ''
with tempfile.NamedTemporaryFile(suffix='.sock', prefix='passport-client.',
dir='/tmp', delete=True) as tmpfile:
addr = tmpfile.name
self.pipe.bind(addr)
self.socket_path = addr
break
except OSError:
continue
except OSError as error:
if time.monotonic() >= deadline:
raise TimeoutError('Could not bind the simulator client socket within 10 seconds') from error
time.sleep(0.01)

# Close the connection and kill the simulator process.
def close(self):
import signal

self.pipe.close()
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
if self.pipe is not None:
self.pipe.close()
self.pipe = None
if self.socket_path is not None:
try:
os.unlink(self.socket_path)
except FileNotFoundError:
pass
self.socket_path = None
if self.process is not None:
if self.process.poll() is None:
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
try:
self.process.wait(timeout=5)
except subprocess.TimeoutExpired:
os.killpg(os.getpgid(self.process.pid), signal.SIGKILL)
self.process.wait()
self.process = None
self._remove_server_socket()
self._remove_test_spi_flash(self.simulator_dir)

# Run `exec()` in the Unix MP simulator.
def exec(self, object):
Expand Down Expand Up @@ -80,7 +130,11 @@ def execute_command(self, cmd, text):
# Get a connection to the simulator.
@pytest.fixture
def simulator(simulatordir):
return SimulatorSocket(simulatordir)
connection = SimulatorSocket(simulatordir)
try:
yield connection
finally:
connection.close()


# Execute a file in the simulator using the Unix Micro-Python built-in `exec()` function.
Expand All @@ -89,7 +143,6 @@ def exec_file(simulator):
def doit(filename):
from pathlib import Path
cmd, return_value = simulator.exec(Path(filename).read_text())
simulator.close()
if cmd == 'excp':
pytest.fail('Remote test failed with exception:\n{}'.format(return_value.decode('utf-8', 'strict')))
elif cmd == 'resp':
Expand Down
51 changes: 0 additions & 51 deletions ports/stm32/boards/Passport/modules/tests/test_translations.py

This file was deleted.

4 changes: 0 additions & 4 deletions ports/stm32/boards/Passport/modules/tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ def test_seedqr_codec(test):
assert test('seedqr_codec.py') == b'OK'


def test_settings(test):
assert test('settings.py') == b'OK'


def test_ui(test):
assert test('ui.py') == b'OK'

Expand Down
4 changes: 2 additions & 2 deletions ports/stm32/boards/Passport/modules/tests/unit/foundation.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def should_fail(f):


should_fail(lambda: foundation.qr.init())
should_fail(lambda: foundation.qr.init(None, None, None))
foundation.qr.init(HOR_RES, VER_RES, bytearray(HOR_RES * VER_RES))
should_fail(lambda: foundation.qr.init(None, None))
foundation.qr.init(HOR_RES, VER_RES)

should_fail(lambda: foundation.convert_rgb565_to_grayscale())
should_fail(lambda: foundation.convert_rgb565_to_grayscale(None, None, None, None))
Expand Down
Loading