Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App cleanup and new tests #1

Merged
merged 3 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
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/
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@
"editor.formatOnSave": false,
"python.terminal.activateEnvironment": false,
"git.ignoreLimitWarning": true,
"ledgerDevTools.appSettings": {
"selectedDevice": "Nano S"
},
}
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
61 changes: 50 additions & 11 deletions src/apdu/dispatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
#include "ledger_assert.h"

#include "dispatcher.h"
#include "../constants.h"
#include "../globals.h"
#include "../types.h"
#include "../sw.h"
#include "../handler/get_version.h"
#include "../handler/get_app_name.h"
#include "../handler/nbgl_tests.h"
#include "constants.h"
#include "globals.h"
#include "types.h"
#include "sw.h"
#include "get_version.h"
#include "get_app_name.h"
#include "display.h"

int apdu_dispatcher(const command_t *cmd) {
LEDGER_ASSERT(cmd != NULL, "NULL cmd");
Expand All @@ -51,18 +51,57 @@ 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) {
tdejoigny-ledger marked this conversation as resolved.
Show resolved Hide resolved
return ui_display_long_address_review();
} else if (cmd->p1 == 2) {
return ui_display_long_address_review_with_tags();
}
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
7 changes: 5 additions & 2 deletions src/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#include "globals.h"
#include "io.h"
#include "sw.h"
#include "ui/menu.h"
#include "apdu/dispatcher.h"
#include "display.h"
#include "dispatcher.h"

const internal_storage_t N_storage_real;

Expand All @@ -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
Loading