Skip to content

Commit

Permalink
Merge pull request #746 from LedgerHQ/add-ux-sync-unit-tests
Browse files Browse the repository at this point in the history
Add UX Sync unit tests
  • Loading branch information
nroggeman-ledger authored Sep 17, 2024
2 parents 9a9e153 + a940eb3 commit 73b6dbb
Show file tree
Hide file tree
Showing 7 changed files with 501 additions and 2 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
cd ../lib_nbgl/
cmake -Bbuild -H. && make -C build && CTEST_OUTPUT_ON_FAILURE=1 make -C build test
STAX=1 cmake -Bbuild -H. && make -C build && CTEST_OUTPUT_ON_FAILURE=1 make -C build test
cd ../lib_ux_sync/
cmake -Bbuild -H. && make -C build && make -C build test
- name: Generate code coverage
run: |
Expand All @@ -42,6 +44,12 @@ jobs:
lcov --directory . -b "$(realpath build/)" --add-tracefile coverage.base --add-tracefile coverage.capture -o coverage.info && \
lcov --directory . -b "$(realpath build/)" --remove coverage.info '*/unit-tests/*' -o coverage.info && \
genhtml coverage.info -o coverage
cd ../lib_ux_sync/
lcov --directory . -b "$(realpath build/)" --capture --initial -o coverage.base && \
lcov --rc lcov_branch_coverage=1 --directory . -b "$(realpath build/)" --capture -o coverage.capture && \
lcov --directory . -b "$(realpath build/)" --add-tracefile coverage.base --add-tracefile coverage.capture -o coverage.info && \
lcov --directory . -b "$(realpath build/)" --remove coverage.info '*/unit-tests/*' -o coverage.info && \
genhtml coverage.info -o coverage
- uses: actions/upload-artifact@v3
Expand All @@ -53,7 +61,7 @@ jobs:
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./unit-tests/lib_standard_app/coverage.info,./unit-tests/lib_nbgl/coverage.info
files: ./unit-tests/lib_standard_app/coverage.info,./unit-tests/lib_nbgl/coverage.info,./unit-tests/lib_ux_sync/coverage.info
flags: unittests
name: codecov-app-boilerplate
fail_ci_if_error: true
Expand Down
3 changes: 3 additions & 0 deletions lib_ux_sync/include/ux_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ ux_sync_ret_t ux_sync_reviewStreamingStart(nbgl_operationType_t operationT

ux_sync_ret_t ux_sync_reviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList);

ux_sync_ret_t ux_sync_reviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList,
const char *finishTitle);

ux_sync_ret_t ux_sync_reviewStreamingFinish(const char *finishTitle);

ux_sync_ret_t ux_sync_genericReview(const nbgl_genericContents_t *contents, const char *rejectText);
Expand Down
30 changes: 29 additions & 1 deletion lib_ux_sync/src/ux_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

static ux_sync_ret_t g_ret;
static bool g_ended;
static const char *g_finish_title;

static void choice_callback(bool confirm)
{
Expand All @@ -17,6 +18,11 @@ static void choice_callback(bool confirm)
g_ended = true;
}

static void skip_callback(void)
{
nbgl_useCaseReviewStreamingFinish(g_finish_title, choice_callback);
}

static void quit_callback(void)
{
g_ret = UX_SYNC_RET_QUITTED;
Expand Down Expand Up @@ -308,9 +314,31 @@ ux_sync_ret_t ux_sync_reviewStreamingStart(nbgl_operationType_t operationT
*/
ux_sync_ret_t ux_sync_reviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList)

{
return ux_sync_reviewStreamingContinueExt(tagValueList, NULL);
}

/**
* @brief Continue drawing the flow of pages of a review.
* @note This should be called after a call to nbgl_useCaseReviewStreamingStart with @ref
* SKIPPABLE_OPERATION and can be followed by others calls to nbgl_useCaseReviewStreamingContinue
* and finally to nbgl_useCaseReviewStreamingFinish. If "Skip" is touched, a choice will be offered
* to go directly to last page, using the given finish title.
*
* @param tagValueList list of tag/value pairs
* @param finishTitle string used in the last review page if "skip" is used
*
* @return ret code:
* - UX_SYNC_RET_APPROVED
* - UX_SYNC_RET_REJECTED
*/
ux_sync_ret_t ux_sync_reviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList,
const char *finishTitle)

{
ux_sync_init();
nbgl_useCaseReviewStreamingContinue(tagValueList, choice_callback);
g_finish_title = finishTitle;
nbgl_useCaseReviewStreamingContinueExt(tagValueList, choice_callback, skip_callback);
return ux_sync_wait(false);
}

Expand Down
58 changes: 58 additions & 0 deletions unit-tests/lib_ux_sync/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
cmake_minimum_required(VERSION 3.10)

if(${CMAKE_VERSION} VERSION_LESS 3.10)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()

# project information
project(unit_tests
VERSION 0.1
DESCRIPTION "Unit tests for UX_SYNC"
LANGUAGES C)


# guard against bad build-type strings
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()

include(CTest)
ENABLE_TESTING()

# specify C standard
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
add_compile_definitions(SCREEN_SIZE_WALLET)
add_compile_definitions(USB_SEGMENT_SIZE=64)
add_compile_definitions(HAVE_NBGL)
add_compile_definitions(WITH_STDIO)

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall ${DEFINES} -g -O0 --coverage")

set(GCC_COVERAGE_LINK_FLAGS "--coverage -lgcov")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")

# guard against in-source builds
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
endif()

add_compile_definitions(TEST)

include_directories(.)
include_directories(../../target/stax/include)
include_directories(../../include)
include_directories(../../lib_nbgl/include)
include_directories(../../lib_nbgl/include/fonts)
include_directories(../../lib_ux_nbgl)
include_directories(../../lib_ux_sync/include)

add_executable(test_ux_sync test_ux_sync.c)

add_library(nbgl_stubs SHARED nbgl_stubs.c)
add_library(ux_sync SHARED ../../lib_ux_sync/src/ux_sync.c)

target_link_libraries(test_ux_sync PUBLIC cmocka gcov ux_sync nbgl_stubs)

add_test(test_ux_sync test_ux_sync)
36 changes: 36 additions & 0 deletions unit-tests/lib_ux_sync/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Unit tests

## Prerequisite

Be sure to have installed:

- CMake >= 3.10
- CMocka >= 1.1.5

and for code coverage generation:

- lcov >= 1.14

## Overview

In `unit-tests/lib_ux_sync` folder, compile with:

```
cmake -Bbuild -H. && make -C build
```

and run tests with:

```
CTEST_OUTPUT_ON_FAILURE=1 make -C build test
```

## Generate code coverage

Just execute in `unit-tests` folder

```
./gen_coverage.sh
```

it will output `coverage.total` and `coverage/` folder with HTML details (in `coverage/index.html`).
181 changes: 181 additions & 0 deletions unit-tests/lib_ux_sync/nbgl_stubs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <string.h>

#include <cmocka.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

#include "nbgl_use_case.h"
#include "ux_sync.h"

static nbgl_choiceCallback_t g_choiceCallback;
static nbgl_callback_t g_rejectCallback;

void *pic(void *addr)
{
return addr;
}

bool io_recv_and_process_event(void)
{
bool ret = (bool) mock_type(bool);
if (!ret && g_choiceCallback) {
g_choiceCallback(true);
}
return ret;
}

void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback)
{
check_expected(message);
check_expected(isSuccess);
g_rejectCallback = quitCallback;
}

void nbgl_useCaseReviewStatus(nbgl_reviewStatusType_t reviewStatusType,
nbgl_callback_t quitCallback)
{
check_expected(reviewStatusType);
g_rejectCallback = quitCallback;
}

void nbgl_useCaseGenericConfiguration(const char *title,
uint8_t initPage,
const nbgl_genericContents_t *contents,
nbgl_callback_t quitCallback)
{
check_expected(title);
check_expected(initPage);
check_expected(contents);
check_expected(quitCallback);
}

void nbgl_useCaseChoice(const nbgl_icon_details_t *icon,
const char *message,
const char *subMessage,
const char *confirmText,
const char *cancelText,
nbgl_choiceCallback_t callback)
{
check_expected(icon);
check_expected(message);
check_expected(subMessage);
check_expected(confirmText);
check_expected(cancelText);
g_choiceCallback = callback;
}

void nbgl_useCaseHomeAndSettings(const char *appName,
const nbgl_icon_details_t *appIcon,
const char *tagline,
const uint8_t initSettingPage,
const nbgl_genericContents_t *settingContents,
const nbgl_contentInfoList_t *infosList,
const nbgl_homeAction_t *action,
nbgl_callback_t quitCallback)
{
check_expected(appName);
check_expected(appIcon);
check_expected(tagline);
check_expected(initSettingPage);
check_expected(settingContents);
check_expected(infosList);
check_expected(action);
}

void nbgl_useCaseReview(nbgl_operationType_t operationType,
const nbgl_contentTagValueList_t *tagValueList,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
const char *finishTitle,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(operationType);
check_expected(tagValueList);
check_expected(icon);
check_expected(reviewTitle);
check_expected(reviewSubTitle);
check_expected(finishTitle);
g_choiceCallback = choiceCallback;
}

void nbgl_useCaseReviewLight(nbgl_operationType_t operationType,
const nbgl_contentTagValueList_t *tagValueList,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
const char *finishTitle,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(operationType);
check_expected(tagValueList);
check_expected(icon);
check_expected(reviewTitle);
check_expected(reviewSubTitle);
check_expected(finishTitle);
g_choiceCallback = choiceCallback;
}

void nbgl_useCaseGenericReview(const nbgl_genericContents_t *contents,
const char *rejectText,
nbgl_callback_t rejectCallback)
{
check_expected(contents);
check_expected(rejectText);
g_rejectCallback = rejectCallback;
}

void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(operationType);
check_expected(icon);
check_expected(reviewTitle);
check_expected(reviewSubTitle);
g_choiceCallback = choiceCallback;
}

void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList,
nbgl_choiceCallback_t choiceCallback,
nbgl_callback_t skipCallback)
{
check_expected(tagValueList);
g_choiceCallback = choiceCallback;
g_rejectCallback = skipCallback;
}

void nbgl_useCaseReviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(tagValueList);
g_choiceCallback = choiceCallback;
}

void nbgl_useCaseReviewStreamingFinish(const char *finishTitle,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(finishTitle);
g_choiceCallback = choiceCallback;
}

void nbgl_useCaseAddressReview(const char *address,
const nbgl_contentTagValueList_t *additionalTagValueList,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
nbgl_choiceCallback_t choiceCallback)
{
check_expected(address);
check_expected(additionalTagValueList);
check_expected(icon);
check_expected(reviewTitle);
check_expected(reviewSubTitle);
g_choiceCallback = choiceCallback;
}
Loading

0 comments on commit 73b6dbb

Please sign in to comment.