Skip to content

Commit

Permalink
app cleanup, new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tdejoigny-ledger committed Sep 20, 2024
1 parent fc6bf15 commit 1ad6574
Show file tree
Hide file tree
Showing 297 changed files with 900 additions and 494 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/build_and_functional_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ name: Build and run functional tests using ragger through reusable workflow

on:
workflow_dispatch:
inputs:
golden_run:
type: choice
required: true
default: 'Raise an error (default)'
description: CI behavior if the test snaphots are different than expected.
options:
- 'Raise an error (default)'
- 'Open a PR'
push:
branches:
- master
Expand All @@ -30,3 +39,4 @@ jobs:
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1
with:
download_app_binaries_artifact: "compiled_app_binaries"
regenerate_snapshots: ${{ inputs.golden_run == 'Open a PR' }}
2 changes: 1 addition & 1 deletion .github/workflows/codeql_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
name: Analyse
strategy:
matrix:
sdk: ["$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK", "$FLEX_SDK"]
sdk: ["$STAX_SDK", "$FLEX_SDK"]
#'cpp' covers C and C++
language: [ 'cpp' ]
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ doc/latex

# Virtual env for sideload (macOS and Windows)
ledger/

# Vscode
.vscode/
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ include $(BOLOS_SDK)/Makefile.defines
# Mandatory configuration #
########################################
# Application name
APPNAME = "NBGL_Tests"
APPNAME = "NBGL Tests"

# Application version
APPVERSION_M = 1
Expand Down
217 changes: 4 additions & 213 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,216 +1,7 @@
[![Ensure compliance with Ledger guidelines](https://github.com/LedgerHQ/app-boilerplate/actions/workflows/guidelines_enforcer.yml/badge.svg)](https://github.com/LedgerHQ/app-boilerplate/actions/workflows/guidelines_enforcer.yml) [![Build and run functional tests using ragger through reusable workflow](https://github.com/LedgerHQ/app-boilerplate/actions/workflows/build_and_functional_tests.yml/badge.svg?branch=master)](https://github.com/LedgerHQ/app-boilerplate/actions/workflows/build_and_functional_tests.yml)
[![Ensure compliance with Ledger guidelines](https://github.com/LedgerHQ/app-nbgl-test/actions/workflows/guidelines_enforcer.yml/badge.svg)](https://github.com/LedgerHQ/app-nbgl-test/actions/workflows/guidelines_enforcer.yml) [![Build and run functional tests using ragger through reusable workflow](https://github.com/LedgerHQ/app-nbgl-test/actions/workflows/build_and_functional_tests.yml/badge.svg?branch=master)](https://github.com/LedgerHQ/app-nbgl-test/actions/workflows/build_and_functional_tests.yml)

# Ledger NBGL_Tests Application
# Ledger NBGL Tests Application

This is a boilerplate application which can be forked to start a new project for the Ledger Nano X/SP, Stax and Flex.
This application is designed to test various standard use cases of the NBGL graphical library. It provides a simple APDU interface which allows to trig the different use case flows. The application includes predefined parameters for each use case that demonstrate the capabilities of NBGL.

## Quick start guide

### With VSCode

You can quickly setup a convenient environment to build and test your application by using [Ledger's VSCode developer tools extension](https://marketplace.visualstudio.com/items?itemName=LedgerHQ.ledger-dev-tools) which leverages the [ledger-app-dev-tools](https://github.com/LedgerHQ/ledger-app-builder/pkgs/container/ledger-app-builder%2Fledger-app-dev-tools) docker image.

It will allow you, whether you are developing on macOS, Windows or Linux to quickly **build** your apps, **test** them on **Speculos** and **load** them on any supported device.

* Install and run [Docker](https://www.docker.com/products/docker-desktop/).
* Make sure you have an X11 server running :
* On Ubuntu Linux, it should be running by default.
* On macOS, install and launch [XQuartz](https://www.xquartz.org/) (make sure to go to XQuartz > Preferences > Security and check "Allow client connections").
* On Windows, install and launch [VcXsrv](https://sourceforge.net/projects/vcxsrv/) (make sure to configure it to disable access control).
* Install [VScode](https://code.visualstudio.com/download) and add [Ledger's extension](https://marketplace.visualstudio.com/items?itemName=LedgerHQ.ledger-dev-tools).
* Open a terminal and clone `app-boilerplate` with `git clone [email protected]:LedgerHQ/app-boilerplate.git`.
* Open the `app-boilerplate` folder with VSCode.
* Use Ledger extension's sidebar menu or open the tasks menu with `ctrl + shift + b` (`command + shift + b` on a Mac) to conveniently execute actions :
* Build the app for the device model of your choice with `Build`.
* Test your binary on [Speculos](https://github.com/LedgerHQ/speculos) with `Run with Speculos`.
* You can also run functional tests, load the app on a physical device, and more.

:information_source: The terminal tab of VSCode will show you what commands the extension runs behind the scene.

### With a terminal

The [ledger-app-dev-tools](https://github.com/LedgerHQ/ledger-app-builder/pkgs/container/ledger-app-builder%2Fledger-app-dev-tools) docker image contains all the required tools and libraries to **build**, **test** and **load** an application.

You can download it from the ghcr.io docker repository:

```shell
sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

You can then enter this development environment by executing the following command from the directory of the application `git` repository:

**Linux (Ubuntu)**

```shell
sudo docker run --rm -ti --user "$(id -u):$(id -g)" --privileged -v "/dev/bus/usb:/dev/bus/usb" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

**macOS**

```shell
sudo docker run --rm -ti --user "$(id -u):$(id -g)" --privileged -v "$(pwd -P):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

**Windows (with PowerShell)**

```shell
docker run --rm -ti --privileged -v "$(Get-Location):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

The application's code will be available from inside the docker container, you can proceed to the following compilation steps to build your app.

## Compilation and load

To easily setup a development environment for compilation and loading on a physical device, you can use the [VSCode integration](#with-vscode) whether you are on Linux, macOS or Windows.

If you prefer using a terminal to perform the steps manually, you can use the guide below.

### Compilation

Setup a compilation environment by following the [shell with docker approach](#with-a-terminal).

From inside the container, use the following command to build the app :

```shell
make DEBUG=1 # compile optionally with PRINTF
```

You can choose which device to compile and load for by setting the `BOLOS_SDK` environment variable to the following values :

* `BOLOS_SDK=$NANOX_SDK`
* `BOLOS_SDK=$NANOSP_SDK`
* `BOLOS_SDK=$STAX_SDK`

By default this variable is set to build/load for Nano S+.

### Loading on a physical device

This step will vary slightly depending on your platform.

:information_source: Your physical device must be connected, unlocked and the screen showing the dashboard (not inside an application).

**Linux (Ubuntu)**

First make sure you have the proper udev rules added on your host :

```shell
# Run these commands on your host, from the app's source folder.
sudo cp .vscode/20-ledger.ledgerblue.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
```

Then once you have [opened a terminal](#with-a-terminal) in the `app-builder` image and [built the app](#compilation-and-load) for the device you want, run the following command :

```shell
# Run this command from the app-builder container terminal.
make load # load the app on a Nano S+ by default
```

[Setting the BOLOS_SDK environment variable](#compilation-and-load) will allow you to load on whichever supported device you want.

**macOS / Windows (with PowerShell)**

:information_source: It is assumed you have [Python](https://www.python.org/downloads/) installed on your computer.

Run these commands on your host from the app's source folder once you have [built the app](#compilation-and-load) for the device you want :

```shell
# Install Python virtualenv
python3 -m pip install virtualenv
# Create the 'ledger' virtualenv
python3 -m virtualenv ledger
```

Enter the Python virtual environment

* macOS : `source ledger/bin/activate`
* Windows : `.\ledger\Scripts\Activate.ps1`

```shell
# Install Ledgerblue (tool to load the app)
python3 -m pip install ledgerblue
# Load the app.
python3 -m ledgerblue.runScript --scp --fileName bin/app.apdu --elfFile bin/app.elf
```

## Test

The boilerplate app comes with functional tests implemented with Ledger's [Ragger](https://github.com/LedgerHQ/ragger) test framework.

### macOS / Windows

To test your app on macOS or Windows, it is recommended to use [Ledger's VS Code extension](#with-vscode) to quickly setup a working test environment.

You can use the following sequence of tasks and commands (all accessible in the **extension sidebar menu**) :

* `Select build target`
* `Build app`

Then you can choose to execute the functional tests :

* Use `Run tests`.

Or simply run the app on the Speculos emulator :

* `Run with Speculos`.

### Linux (Ubuntu)

On Linux, you can use [Ledger's VS Code extension](#with-vscode) to run the tests. If you prefer not to, open a terminal and follow the steps below.

Install the tests requirements :

```shell
pip install -r tests/requirements.txt
```

Then you can :

Run the functional tests (here for nanos+ but available for any device once you have built the binaries) :

```shell
pytest tests/ --tb=short -v --device nanosp
```

Or run your app directly with Speculos

```shell
speculos --model nanosp build/nanos2/bin/app.elf
```

## Documentation

High level documentation such as [application specification](APP_SPECIFICATION.md), [APDU](doc/APDU.md) and [transaction serialization](doc/TRANSACTION.md) are included in developer documentation which can be generated with [doxygen](https://www.doxygen.nl)

```shell
doxygen .doxygen/Doxyfile
```

the process outputs HTML and LaTeX documentations in `doc/html` and `doc/latex` folders.

## Continuous Integration

The flow processed in [GitHub Actions](https://github.com/features/actions) is the following:

- Ledger guidelines enforcer which verifies that an app is compliant with Ledger guidelines. The successful completion of this reusable workflow is a mandatory step for an app to be available on the Ledger application store. More information on the guidelines can be found in the repository [ledger-app-workflow](https://github.com/LedgerHQ/ledger-app-workflows)
- Code formatting with [clang-format](http://clang.llvm.org/docs/ClangFormat.html)
- Compilation of the application for all Ledger hardware in [ledger-app-builder](https://github.com/LedgerHQ/ledger-app-builder)
- Unit tests of C functions with [cmocka](https://cmocka.org/) (see [unit-tests/](unit-tests/))
- End-to-end tests with [Speculos](https://github.com/LedgerHQ/speculos) emulator and [ragger](https://github.com/LedgerHQ/ragger) (see [tests/](tests/))
- Code coverage with [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html)/[lcov](http://ltp.sourceforge.net/coverage/lcov.php) and upload to [codecov.io](https://about.codecov.io)
- Documentation generation with [doxygen](https://www.doxygen.nl)

It outputs 3 artifacts:
- `compiled_app_binaries` within binary files of the build process for each device
- `code-coverage` within HTML details of code coverage
- `documentation` within HTML auto-generated documentation

## Are you developing an application for Ledger devices?

If so, This boilerplate will help you get started.

For a smooth and quick integration:

- See the developers’ documentation on the [Developer Portal](https://developers.ledger.com/), and
- [Go on Discord](https://developers.ledger.com/discord-pro/) to chat with developer support and the developer community.
It also ensures that there are no regression issues by using a set of tests.
Binary file modified glyphs/app_nbgl_tests_64px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/app_nbgl_tests_32px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified icons/app_nbgl_tests_40px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ledger_app.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[app]
build_directory = "./"
sdk = "C"
devices = ["nanox", "nanos+", "stax", "flex"]
devices = ["stax", "flex"]

[tests]
unit_directory = "./unit-tests/"
Expand Down
50 changes: 45 additions & 5 deletions src/apdu/dispatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "../sw.h"
#include "../handler/get_version.h"
#include "../handler/get_app_name.h"
#include "../handler/nbgl_tests.h"
#include "../menu.h"

int apdu_dispatcher(const command_t *cmd) {
LEDGER_ASSERT(cmd != NULL, "NULL cmd");
Expand All @@ -51,18 +51,58 @@ int apdu_dispatcher(const command_t *cmd) {
}

return handler_get_app_name();
case TEST_REVIEW1:
case TEST_SPINNER:
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return ui_display_spinner();
case TEST_USE_CASE_REVIEW:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return ui_display_review(false);
case TEST_USE_CASE_REVIEW_BLIND_SIGNING:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return ui_display_review(true);
case TEST_USE_CASE_ADDRESS_REVIEW:
if (cmd->p1 == 0) {
return ui_display_address_review();
} else if (cmd->p1 == 1) {
return ui_display_long_address_review();
} else if (cmd->p1 == 2) {
return ui_display_long_address_review_with_tags();
} else {
return io_send_sw(SW_WRONG_P1P2);
}
case TEST_USE_CASE_STREAMING_REVIEW:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return ui_display_streaming_review(false);

case TEST_USE_CASE_STREAMING_REVIEW_BLIND_SIGNING:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return ui_display_streaming_review(true);
case TEST_USE_CASE_STATIC_REVIEW:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return handler_test_transaction_review(cmd->p1, cmd->p2);
case TEST_REVIEW2:
return ui_display_static_review();
case TEST_USE_CASE_LIGHT_REVIEW:
// P1 & P2 may be used later as test/sub-test number
if (cmd->p1 != 0 || cmd->p2 != 0) {
return io_send_sw(SW_WRONG_P1P2);
}
return handler_test_address_review(cmd->p1, cmd->p2);
return ui_display_light_review();
default:
return io_send_sw(SW_INS_NOT_SUPPORTED);
}
Expand Down
3 changes: 3 additions & 0 deletions src/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ void app_main() {

ui_menu_main();

// initialize ticker event counter
G_ticker_counter = -1;

// Initialize the NVM data if required
if (N_storage.initialized != 0x01) {
internal_storage_t storage;
Expand Down
5 changes: 5 additions & 0 deletions src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ typedef struct internal_storage_t {

extern const internal_storage_t N_storage_real;
#define N_storage (*(volatile internal_storage_t *) PIC(&N_storage_real))

/**
* Global ticker events counter.
*/
extern int G_ticker_counter;
Loading

0 comments on commit 1ad6574

Please sign in to comment.