Skip to content

Commit

Permalink
Speculos tests (#4)
Browse files Browse the repository at this point in the history
* Speculos tests

* Update for CI

---------

Co-authored-by: sabledeesse <[email protected]>
  • Loading branch information
pashinov and sabledeesse authored Oct 11, 2023
1 parent 1cc6e67 commit 3115b1a
Show file tree
Hide file tree
Showing 134 changed files with 1,448 additions and 53 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/build-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Compilation

on:
push:
branches:
- master
pull_request:
branches:
- master
- develop
workflow_dispatch:

jobs:
nano_release_build:
name: Build release application for NanoS, X and S+
strategy:
matrix:
sdk: ["$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK"]
runs-on: ubuntu-latest
container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest

steps:
- name: Clone
uses: actions/checkout@v3

- name: Build Everscale
run: |
make -j BOLOS_SDK=${{ matrix.sdk }}
- name: Build Venom
run: |
make clean
make -j BOLOS_SDK=${{ matrix.sdk }} CHAIN=venom
97 changes: 97 additions & 0 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master
- develop
workflow_dispatch:

jobs:
scan-build:
name: Clang Static Analyzer
runs-on: ubuntu-latest
container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest

steps:
- uses: actions/checkout@v3

- name: Build with Clang Static Analyzer
run: |
make clean
scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default
- uses: actions/upload-artifact@v3
if: failure()
with:
name: scan-build
path: scan-build


# =====================================================
# SPECULOS TESTS
# =====================================================


building_for_e2e_speculos_tests:
name: Building binaries for E2E Speculos tests
runs-on: ubuntu-latest
container:
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest

steps:
- uses: actions/checkout@v3

- name: Build testing binaries
run: |
mkdir tests/speculos/elfs
make clean && make -j DEBUG=1 BOLOS_SDK=$NANOS_SDK && mv bin/app.elf tests/speculos/elfs/nanos.elf
make clean && make -j DEBUG=1 BOLOS_SDK=$NANOX_SDK && mv bin/app.elf tests/speculos/elfs/nanox.elf
make clean && make -j DEBUG=1 BOLOS_SDK=$NANOSP_SDK && mv bin/app.elf tests/speculos/elfs/nanosp.elf
- name: Upload app binaries
uses: actions/upload-artifact@v3
with:
name: e2e_speculos_elfs
path: ./tests/speculos/elfs


jobs-e2e-speculos-tests:
name: Speculos tests
strategy:
fail-fast: false
matrix:
model: ["nanos", "nanox", "nanosp"]

needs: [building_for_e2e_speculos_tests]
runs-on: ubuntu-latest

steps:
- name: Clone
uses: actions/checkout@v3

- name: Create tmp folder for artifacts
run: mkdir tests/speculos/elfs

- name: Download app binaries
uses: actions/download-artifact@v3
with:
path: tmp/

- name: Gather elfs
run: cp `find tmp/e2e_speculos_elfs/ -name "*.elf"` tests/speculos/elfs/

- name: Install dependencies
run: |
cd tests/speculos
sudo apt-get update && sudo apt-get install -y qemu-user-static
pip install -r requirements.txt
- name: Run speculos tests
run: |
cd tests/speculos
pytest --model ${{ matrix.model }} --path ./elfs/${{ matrix.model }}.elf --display headless
53 changes: 0 additions & 53 deletions .github/workflows/ci.yml

This file was deleted.

Empty file added tests/python/apps/__init__.py
Empty file.
40 changes: 40 additions & 0 deletions tests/speculos/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pathlib import Path
import pytest

from speculos.client import SpeculosClient

from ledger_client.ledger_cmd import LedgerCommand


SCRIPT_DIR = Path(__file__).absolute().parent
API_URL = "http://127.0.0.1:5000"
#http://10.66.66.8:5000


def pytest_addoption(parser):
# nanos, nanox, nanosp
parser.addoption("--model", action="store", default="nanos")
# qt: default, requires a X server
# headless: nothing is displayed
parser.addoption("--display", action="store", default="qt")

path: str = SCRIPT_DIR.parent.parent / "bin" / "app.elf"
parser.addoption("--path", action="store", default=path)

@pytest.fixture()
def client(pytestconfig):
file_path = pytestconfig.getoption("path")
model = pytestconfig.getoption("model")

args = ['--log-level', 'speculos:DEBUG','--model', model, '--display', pytestconfig.getoption("display")]
with SpeculosClient(app=str(file_path), args=args) as client:
yield client


@pytest.fixture()
def cmd(client, pytestconfig):
yield LedgerCommand(
client=client,
debug=True,
model=pytestconfig.getoption("model"),
)
Empty file.
35 changes: 35 additions & 0 deletions tests/speculos/ledger_client/exception/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from .device_exception import DeviceException
from .errors import (UnknownDeviceError,
DenyError,
WrongP1P2Error,
WrongDataLengthError,
InsNotSupportedError,
ClaNotSupportedError,
WrongResponseLengthError,
DisplayBip32PathFailError,
DisplayAddressFailError,
DisplayAmountFailError,
WrongTxLengthError,
TxParsingFailError,
TxHashFail,
BadStateError,
SignatureFailError)

__all__ = [
"DeviceException",
"DenyError",
"UnknownDeviceError",
"WrongP1P2Error",
"WrongDataLengthError",
"InsNotSupportedError",
"ClaNotSupportedError",
"WrongResponseLengthError",
"DisplayBip32PathFailError",
"DisplayAddressFailError",
"DisplayAmountFailError",
"WrongTxLengthError",
"TxParsingFailError",
"TxHashFail",
"BadStateError",
"SignatureFailError"
]
38 changes: 38 additions & 0 deletions tests/speculos/ledger_client/exception/device_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import enum
from typing import Dict, Any, Union

from .errors import *


class DeviceException(Exception): # pylint: disable=too-few-public-methods
exc: Dict[int, Any] = {
0x6985: DenyError,
0x6A86: WrongP1P2Error,
0x6A87: WrongDataLengthError,
0x6D00: InsNotSupportedError,
0x6E00: ClaNotSupportedError,
0xB000: WrongResponseLengthError,
0xB001: DisplayBip32PathFailError,
0xB002: DisplayAddressFailError,
0xB003: DisplayAmountFailError,
0xB004: WrongTxLengthError,
0xB005: TxParsingFailError,
0xB006: TxHashFail,
0xB007: BadStateError,
0xB008: SignatureFailError
}

def __new__(cls,
error_code: int,
ins: Union[int, enum.IntEnum, None] = None,
message: str = ""
) -> Any:
error_message: str = (f"Error in {ins!r} command"
if ins else "Error in command")

if error_code in DeviceException.exc:
return DeviceException.exc[error_code](hex(error_code),
error_message,
message)

return UnknownDeviceError(hex(error_code), error_message, message)
58 changes: 58 additions & 0 deletions tests/speculos/ledger_client/exception/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
class UnknownDeviceError(Exception):
pass


class DenyError(Exception):
pass


class WrongP1P2Error(Exception):
pass


class WrongDataLengthError(Exception):
pass


class InsNotSupportedError(Exception):
pass


class ClaNotSupportedError(Exception):
pass


class WrongResponseLengthError(Exception):
pass


class DisplayBip32PathFailError(Exception):
pass


class DisplayAddressFailError(Exception):
pass


class DisplayAmountFailError(Exception):
pass


class WrongTxLengthError(Exception):
pass


class TxParsingFailError(Exception):
pass


class TxHashFail(Exception):
pass


class BadStateError(Exception):
pass


class SignatureFailError(Exception):
pass
Loading

0 comments on commit 3115b1a

Please sign in to comment.