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

Add UX Sync unit tests #746

Merged
merged 1 commit into from
Sep 17, 2024
Merged
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
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
Loading