test: Moved mocking specific things to unit tests
What changed, and why it matters
This commit is a pure internal test-code refactor. It moves CMocka-specific mock functions out of a shared hardware-mocks library and into the unit-test directory so that the simulator no longer depends on the CMocka testing framework. No production firmware code is changed, and nothing in the commit affects the security of the shipped BitBox02 device.
No security action required. Treat as normal maintenance; standard code-review approval is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change reorganizes the build and test mocks: CMocka-dependent mocks (gestures, screen stack, memory wrappers, qtouch) are relocated from test/hardware-mocks to test/unit-test/framework, CMake finds CMocka only inside the unit-test subtree, and the simulator build drops CMockA linkage. A small production source file (src/da14531/da14531_protocol.c) simply loses its TESTING-time mock_dap.h include. A CMake typo fix (DRIVER-SOURCES -> QTOUCH-SOURCES) is also present. There are no runtime behavior changes to firmware.
Changed components
test/hardware-mockstest/unit-test/frameworkCMake build configurationsrc/da14531/da14531_protocol.c (test-only include removal)Inspect captured patch +552 / −517
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8d6c131..297c34e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -350,14 +350,6 @@ if (PROTOC STREQUAL "PROTOC-NOTFOUND")
message(FATAL_ERROR "Could not find 'protoc'.")
endif()
-# We use FindPkgConfig instead of FindPackage because it finds libraries in
-# both linux and macos
-find_package(PkgConfig REQUIRED)
-
-# Unit testing uses CMocka (rust unit testing is in `src`, which is why we load
-# it already here.)
-pkg_check_modules(CMOCKA REQUIRED cmocka)
-
#-----------------------------------------------------------------------------
# Build
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a2676e5..523babc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -136,7 +136,7 @@ set(DRIVER-SOURCES ${DRIVER-SOURCES} PARENT_SCOPE)
set(QTOUCH-SOURCES
${CMAKE_SOURCE_DIR}/src/qtouch/qtouch.c
)
-set(QTOUCH-SOURCES ${DRIVER-SOURCES} PARENT_SCOPE)
+set(QTOUCH-SOURCES ${QTOUCH-SOURCES} PARENT_SCOPE)
# The additional files required for the plus platform
set(PLATFORM-BITBOX02-PLUS-SOURCES
@@ -277,7 +277,7 @@ add_custom_target(rust-cbindgen
# Test rust crates that contain business logic. Avoid testing crates that depend on hardware.
if(NOT CMAKE_CROSSCOMPILING)
- set(RUSTFLAGS_TESTS ${RUSTFLAGS} -L${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} ${CMOCKA_LDFLAGS} -lbitbox_merged -lwallycore -lsecp256k1 -lfatfs -lhardware-mocks)
+ set(RUSTFLAGS_TESTS ${RUSTFLAGS} -L${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} -lbitbox_merged -lwallycore -lsecp256k1 -lfatfs -lhardware-mocks)
# Since we build with all features we need to use a separate build directory.
# Otherwise we invalidate the result from the normal compilation that uses a
diff --git a/src/da14531/da14531_protocol.c b/src/da14531/da14531_protocol.c
index d0efdc2..e68343a 100644
--- a/src/da14531/da14531_protocol.c
+++ b/src/da14531/da14531_protocol.c
@@ -23,8 +23,6 @@
#include <utils_assert.h>
#ifndef TESTING
#include "dap.h"
-#else
-#include "mock_dap.h"
#endif
#include <hardfault.h>
diff --git a/test/hardware-mocks/CMakeLists.txt b/test/hardware-mocks/CMakeLists.txt
index fe0dfa2..e007dd8 100644
--- a/test/hardware-mocks/CMakeLists.txt
+++ b/test/hardware-mocks/CMakeLists.txt
@@ -24,9 +24,7 @@ set(HARDWARE-MOCKS-SOURCES
src/mock_spi_mem.c
src/mock_component.c
src/mock_delay.c
- src/mock_gestures.c
src/mock_qtouch.c
- src/mock_screen_stack.c
)
add_library(hardware-mocks
@@ -56,12 +54,11 @@ target_include_directories(
PRIVATE
${INCLUDES}
${CMAKE_BINARY_DIR}/src
- ${CMOCKA_INCLUDE_DIRS}
$<TARGET_PROPERTY:fatfs,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:wallycore,INTERFACE_INCLUDE_DIRECTORIES>
)
-target_link_libraries(hardware-mocks PUBLIC wallycore ${CMOCKA_LDFLAGS})
+target_link_libraries(hardware-mocks PUBLIC wallycore)
if(SANITIZE_ADDRESS)
target_compile_options(hardware-mocks PUBLIC "-fsanitize=address")
diff --git a/test/hardware-mocks/README.md b/test/hardware-mocks/README.md
index 7682ded..aa0a51a 100644
--- a/test/hardware-mocks/README.md
+++ b/test/hardware-mocks/README.md
@@ -1,6 +1,4 @@
-# Hardware mocks and fakes
+# Hardware fakes
-This library is used for c unit tests and the c simulator.
-
-Some of the files depend on cmocka to provide mocks. Some of the files are only
-fakes.
+All files in this directory fake hardware functionailty. Used in unit tests and
+simulators
diff --git a/test/hardware-mocks/include/mock_dap.h b/test/hardware-mocks/include/mock_dap.h
deleted file mode 100644
index bcab573..0000000
--- a/test/hardware-mocks/include/mock_dap.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2025 Shift Crypto AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef MOCK_DAP_H
-#define MOCK_DAP_H
-#include <stdbool.h>
-#include <stdint.h>
-
-void dap_init(void);
-void dap_connect(void);
-void dap_disconnect(void);
-uint32_t dap_read_word(uint32_t addr);
-uint16_t dap_read_hword(uint32_t addr);
-void dap_write_word(uint32_t addr, uint32_t data);
-void dap_write_hword(uint32_t addr, uint16_t data);
-void dap_reset_link(void);
-uint32_t dap_read_idcode(void);
-bool dap_target_prepare(int32_t timeout);
-
-// Target operations
-void dap_target_select(void);
-void dap_target_deselect(void);
-void dap_target_erase(void);
-void dap_target_lock(void);
-void dap_target_erase_row(uint32_t addr);
-#endif
diff --git a/test/hardware-mocks/include/mock_gestures.h b/test/hardware-mocks/include/mock_gestures.h
deleted file mode 100644
index 76c7364..0000000
--- a/test/hardware-mocks/include/mock_gestures.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2019 Shift Cryptosecurity AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _MOCK_GESTURES_H_
-#define _MOCK_GESTURES_H_
-
-#include <screen.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <touch/gestures.h>
-
-/**
- * Mocks the sensors for sliding and tap or hold detection.
- * The flag 'expect_slide_detection' indicates whether the caller expects that the mocked gesture
- * detection returns after detecting a slide gesture. This flag needs to be set to false if the
- * caller requires mocking of the sensor node signal and sensor node reference driver functions.
- * @param[in] screen_position The position at which the touch slider was touched (between 0 and
- * 255).
- */
-void mock_gestures_touch(slider_location_t location, uint8_t screen_position);
-
-/**
- * Mocks the sensors for slider release detection.
- */
-void mock_gestures_touch_release(void);
-
-/**
- * Initializes the touch detection by resetting the detection history.
- */
-void mock_gestures_touch_init(void);
-
-#endif
diff --git a/test/hardware-mocks/include/mock_screen_stack.h b/test/hardware-mocks/include/mock_screen_stack.h
deleted file mode 100644
index ab91907..0000000
--- a/test/hardware-mocks/include/mock_screen_stack.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2019 Shift Cryptosecurity AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _TEST_SCREEN_STACK_H
-#define _TEST_SCREEN_STACK_H
-
-void mock_screen_stack_assert_clean(void);
-#endif
diff --git a/test/hardware-mocks/include/mock_uart.h b/test/hardware-mocks/include/mock_uart.h
deleted file mode 100644
index 2913ecf..0000000
--- a/test/hardware-mocks/include/mock_uart.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2025 Shift Crypto AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
diff --git a/test/hardware-mocks/include/test_random.h b/test/hardware-mocks/include/test_random.h
deleted file mode 100644
index e32bd87..0000000
--- a/test/hardware-mocks/include/test_random.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2019 Shift Cryptosecurity AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _TEST_RANDOM_H
-#define _TEST_RANDOM_H
-
-int __wrap_rand(void);
-int __wrap_rust_sha256(const unsigned char* data, size_t len, unsigned char* out);
-
-#endif
diff --git a/test/hardware-mocks/src/mock_gestures.c b/test/hardware-mocks/src/mock_gestures.c
deleted file mode 100644
index 47c25e5..0000000
--- a/test/hardware-mocks/src/mock_gestures.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2019 Shift Cryptosecurity AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <cmocka.h>
-
-#include "mock_gestures.h"
-#include "mock_qtouch.h"
-#include <util.h>
-
-#define MEASUREMENT_PERIOD 125
-
-static bool gestures_history_reset = false;
-
-/********************************** POSITIONING **********************************/
-
-/**
- * Converts the screen position into the slider position.
- */
-// TODO: clean up eventually. This is copied form gestures.c
-static uint16_t _screen_to_slider_position(uint8_t screen_position)
-{
- uint16_t slider_position = ((float)screen_position / (float)SCREEN_WIDTH) * MAX_SLIDER_POS;
- return slider_position;
-}
-
-/**
- * Mocks the sensors for sliding and tap or hold detection.
- * The flag 'expect_slide_detection' indicates whether the caller expects that the mocked gesture
- * detection returns after detecting a slide gesture. This flag needs to be set to false if the
- * caller requires mocking of the sensor node signal and sensor node reference driver functions.
- * @param[in] pos The position at which the touch slider was touched (between 0 and 255).
- */
-void mock_gestures_touch(slider_location_t location, uint8_t screen_position)
-{
- for (int j = 0; j < MEASUREMENT_PERIOD; j++) {
- for (int i = 0; i < TOUCH_NUM_SLIDERS; i++) {
- if (i == location) {
- will_return(qtouch_is_scroller_active, 129);
- uint8_t measured_position = _screen_to_slider_position(screen_position);
- if (location == bottom_slider) {
- measured_position = MAX_SLIDER_POS - measured_position;
- }
- will_return(qtouch_get_scroller_position, measured_position);
- } else {
- will_return(qtouch_is_scroller_active, 0);
- }
- }
- gestures_detect(gestures_history_reset, true);
- gestures_history_reset = false;
- }
-}
-
-/**
- * Mocks the sensors for slider release detection.
- */
-void mock_gestures_touch_release(void)
-{
- for (int i = 0; i < TOUCH_NUM_SLIDERS; i++) {
- will_return(qtouch_is_scroller_active, 0);
- }
- gestures_detect(gestures_history_reset, true);
- gestures_history_reset = false;
-}
-
-/**
- * Initializes the touch detection by resetting the detection history.
- */
-void mock_gestures_touch_init(void)
-{
- gestures_history_reset = true;
-}
diff --git a/test/hardware-mocks/src/mock_memory.c b/test/hardware-mocks/src/mock_memory.c
index 559c6f9..d3051b3 100644
--- a/test/hardware-mocks/src/mock_memory.c
+++ b/test/hardware-mocks/src/mock_memory.c
@@ -12,12 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <cmocka.h>
-
#include <flags.h>
#include <memory/memory.h>
#include <mock_memory.h>
@@ -74,51 +68,6 @@ void memory_read_shared_bootdata_mock(uint8_t* chunk_out)
memcpy(chunk_out, _memory_shared_data, (size_t)FLASH_SHARED_DATA_LEN);
}
-bool __wrap_memory_is_initialized(void)
-{
- return mock();
-}
-
-bool __wrap_memory_is_seeded(void)
-{
- return mock();
-}
-
-static uint8_t _encrypted_seed_and_hmac[96];
-static uint8_t _encrypted_seed_and_hmac_len;
-
-bool __wrap_memory_set_encrypted_seed_and_hmac(uint8_t* encrypted_seed_and_hmac, uint8_t len)
-{
- memcpy(_encrypted_seed_and_hmac, encrypted_seed_and_hmac, len);
- _encrypted_seed_and_hmac_len = len;
- return true;
-}
-
-bool __wrap_memory_get_encrypted_seed_and_hmac(
- uint8_t* encrypted_seed_and_hmac_out,
- uint8_t* len_out)
-{
- *len_out = _encrypted_seed_and_hmac_len;
- memcpy(encrypted_seed_and_hmac_out, _encrypted_seed_and_hmac, *len_out);
- return true;
-}
-
-void __wrap_memory_get_device_name(char* name_out)
-{
- snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", (const char*)mock());
-}
-
-bool __wrap_memory_set_device_name(const char* name)
-{
- return mock();
-}
-
-bool __wrap_memory_set_mnemonic_passphrase_enabled(bool enabled)
-{
- check_expected(enabled);
- return mock();
-}
-
static uint8_t _salt_root[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
diff --git a/test/hardware-mocks/src/mock_qtouch.c b/test/hardware-mocks/src/mock_qtouch.c
index 58772d9..e980b09 100644
--- a/test/hardware-mocks/src/mock_qtouch.c
+++ b/test/hardware-mocks/src/mock_qtouch.c
@@ -12,26 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <cmocka.h>
+// The real qtouch.h depends on hardware specific headers and cannot be used
+#include <mock_qtouch.h>
-#include "mock_qtouch.h"
+#include <stdbool.h>
volatile bool measurement_done_touch = true;
-uint8_t qtouch_is_scroller_active(uint16_t sensor_node)
-{
- return (uint8_t)mock();
-}
-
-uint16_t qtouch_get_scroller_position(uint16_t sensor_node)
-{
- return (uint16_t)mock();
-}
-
void qtouch_process(void) {}
void qtouch_force_calibrate(void) {}
diff --git a/test/hardware-mocks/src/mock_screen_stack.c b/test/hardware-mocks/src/mock_screen_stack.c
deleted file mode 100644
index 31ff935..0000000
--- a/test/hardware-mocks/src/mock_screen_stack.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2019 Shift Cryptosecurity AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <cmocka.h>
-
-#include <ui/screen_stack.h>
-
-static int _stack_counter = 0;
-void __wrap_ui_screen_stack_push(component_t* component)
-{
- _stack_counter++;
- check_expected(component);
-}
-
-void __wrap_ui_screen_stack_pop(void)
-{
- _stack_counter--;
- assert_true(_stack_counter >= 0);
-}
-
-void mock_screen_stack_assert_clean(void)
-{
- assert_int_equal(_stack_counter, 0);
-}
diff --git a/test/hardware-mocks/src/mock_securechip.c b/test/hardware-mocks/src/mock_securechip.c
index 9dc9ed3..90ec17c 100644
--- a/test/hardware-mocks/src/mock_securechip.c
+++ b/test/hardware-mocks/src/mock_securechip.c
@@ -12,12 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <cmocka.h>
-
#include <rust/rust.h>
#include <salt.h>
#include <securechip/securechip.h>
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
index d9f877b..3e0678a 100644
--- a/test/unit-test/CMakeLists.txt
+++ b/test/unit-test/CMakeLists.txt
@@ -19,6 +19,10 @@
# both linux and macos
find_package(PkgConfig REQUIRED)
+# Unit testing uses CMocka (rust unit testing is in `src`, which is why we load
+# it already here.)
+pkg_check_modules(CMOCKA REQUIRED cmocka)
+
# u2f tests with hardware uses hidapi-hidraw
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
pkg_check_modules(HIDAPI REQUIRED hidapi)
@@ -32,6 +36,10 @@ endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations -Wno-implicit-function-declaration -Wno-bad-function-cast")
set(DBB-FILTERED-SOURCES
+ framework/src/mock_gestures.c
+ framework/src/mock_screen_stack.c
+ framework/src/mock_memory.c
+ framework/src/mock_qtouch.c
${DBB-FIRMWARE-SOURCES}
${DBB-FIRMWARE-UI-SOURCES}
${FIRMWARE-U2F-SOURCES}
@@ -98,12 +106,14 @@ target_include_directories(
$<TARGET_PROPERTY:wallycore,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:secp256k1,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:fatfs,INTERFACE_INCLUDE_DIRECTORIES>
+ ${CMOCKA_INCLUDE_DIRS}
)
target_include_directories(
bitbox_objects
PUBLIC
${INCLUDES}
${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/framework/include
${CMAKE_BINARY_DIR}/src
)
@@ -123,6 +133,7 @@ target_include_directories(
PUBLIC
${INCLUDES}
${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/framework/include
${CMAKE_BINARY_DIR}/src
)
@@ -149,6 +160,7 @@ target_compile_definitions(bitbox PUBLIC TESTING _UNIT_TEST_)
target_link_libraries(bitbox
PUBLIC
secp256k1
+ ${CMOCKA_LDFLAGS}
PRIVATE
wallycore
fatfs
@@ -266,7 +278,7 @@ foreach(TEST_NAME ${U2F_TESTS})
set(EXE test_${TEST_NAME})
# This tests link to our code
- add_executable(${EXE} test_${TEST_NAME}.c framework/mock_hidapi.c)
+ add_executable(${EXE} test_${TEST_NAME}.c framework/src/mock_hidapi.c)
target_link_libraries(${EXE} PRIVATE
$<$<BOOL:${SANITIZE_ADDRESS}>:asan>
$<$<BOOL:${SANITIZE_UNDEFINED}>:-fsanitize=undefined>
diff --git a/test/unit-test/framework/include/mock_gestures.h b/test/unit-test/framework/include/mock_gestures.h
new file mode 100644
index 0000000..76c7364
--- /dev/null
+++ b/test/unit-test/framework/include/mock_gestures.h
@@ -0,0 +1,44 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _MOCK_GESTURES_H_
+#define _MOCK_GESTURES_H_
+
+#include <screen.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <touch/gestures.h>
+
+/**
+ * Mocks the sensors for sliding and tap or hold detection.
+ * The flag 'expect_slide_detection' indicates whether the caller expects that the mocked gesture
+ * detection returns after detecting a slide gesture. This flag needs to be set to false if the
+ * caller requires mocking of the sensor node signal and sensor node reference driver functions.
+ * @param[in] screen_position The position at which the touch slider was touched (between 0 and
+ * 255).
+ */
+void mock_gestures_touch(slider_location_t location, uint8_t screen_position);
+
+/**
+ * Mocks the sensors for slider release detection.
+ */
+void mock_gestures_touch_release(void);
+
+/**
+ * Initializes the touch detection by resetting the detection history.
+ */
+void mock_gestures_touch_init(void);
+
+#endif
diff --git a/test/unit-test/framework/include/mock_memory.h b/test/unit-test/framework/include/mock_memory.h
new file mode 100644
index 0000000..b050aad
--- /dev/null
+++ b/test/unit-test/framework/include/mock_memory.h
@@ -0,0 +1,32 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _MOCK_MEMORY_H_
+#define _MOCK_MEMORY_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <flags.h>
+
+void mock_memory_factoryreset(void);
+bool memory_write_to_address_mock(uint32_t base, uint32_t addr, const uint8_t* chunk);
+bool memory_write_chunk_mock(uint32_t chunk_num, const uint8_t* chunk);
+void memory_read_chunk_mock(uint32_t chunk_num, uint8_t* chunk_out);
+// Size: `FLASH_SHARED_DATA_LEN`.
+void memory_read_shared_bootdata_mock(uint8_t* chunk_out);
+void mock_memory_set_salt_root(const uint8_t* salt_root);
+void memory_bootloader_hash_mock(uint8_t* hash_out);
+void memory_set_bootloader_hash_mock(const uint8_t* mock_hash);
+#endif
diff --git a/test/unit-test/framework/include/mock_qtouch.h b/test/unit-test/framework/include/mock_qtouch.h
new file mode 100644
index 0000000..11271da
--- /dev/null
+++ b/test/unit-test/framework/include/mock_qtouch.h
@@ -0,0 +1,26 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _QTOUCH_H_
+#define _QTOUCH_H_
+
+#include <stdint.h>
+
+void __wrap_qtouch_process(void);
+
+uint8_t __wrap_qtouch_get_scroller_is_active(uint16_t sensor_node);
+
+uint16_t __wrap_qtouch_get_scroller_position(uint16_t sensor_node);
+
+#endif
diff --git a/test/unit-test/framework/include/mock_screen_stack.h b/test/unit-test/framework/include/mock_screen_stack.h
new file mode 100644
index 0000000..ab91907
--- /dev/null
+++ b/test/unit-test/framework/include/mock_screen_stack.h
@@ -0,0 +1,19 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _TEST_SCREEN_STACK_H
+#define _TEST_SCREEN_STACK_H
+
+void mock_screen_stack_assert_clean(void);
+#endif
diff --git a/test/unit-test/framework/mock_hidapi.c b/test/unit-test/framework/mock_hidapi.c
deleted file mode 100644
index 4841235..0000000
--- a/test/unit-test/framework/mock_hidapi.c
+++ /dev/null
@@ -1,164 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <util.h>
-
-// POSIX
-#include <pthread.h>
-
-#include <hidapi.h>
-
-#include "queue.h"
-#include "u2f.h"
-#include "u2f/u2f_packet.h"
-#include "usb/usb_processing.h"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
-
-#define BUFSIZE 0x40LU
-
-static uint8_t _buf[BUFSIZE];
-static size_t _buf_len;
-static bool _expect_more;
-
-static bool _have_data;
-static pthread_t thread;
-static bool timer_thread_stop;
-static pthread_mutex_t mutex;
-
-static void _delay(uint32_t msec)
-{
- struct timespec rem;
- struct timespec ts = {
- .tv_sec = 0,
- .tv_nsec = msec * 1000000,
- };
- nanosleep(&ts, &rem);
-}
-
-void* timer_task(void* args)
-{
- (void)args;
- for (;;) {
- // printf("tick\n");
- u2f_packet_timeout_tick();
- uint32_t timeout_cid;
- while (u2f_packet_timeout_get(&timeout_cid)) {
- u2f_packet_timeout(timeout_cid);
- }
- _delay(90);
- pthread_mutex_lock(&mutex);
- if (timer_thread_stop) {
- pthread_mutex_unlock(&mutex);
- return 0;
- }
- pthread_mutex_unlock(&mutex);
- }
- return 0;
-}
-
-int hid_exit(void)
-{
- return 0;
-}
-
-int hid_init(void)
-{
- return 0;
-}
-
-void hid_close(hid_device* dev)
-{
- pthread_mutex_lock(&mutex);
- timer_thread_stop = true;
- pthread_mutex_unlock(&mutex);
- void* retval;
- int res = pthread_join(thread, &retval);
- if (res != 0) {
- printf("Failed to join thread\n");
- }
-}
-
-hid_device* hid_open_path(const char* path)
-{
- static char sham[] = "sham";
- usb_processing_init();
- u2f_device_setup();
- timer_thread_stop = false;
- int res = pthread_create(&thread, NULL, &timer_task, NULL);
- if (res != 0) {
- printf("failed to create thread\n");
- }
- pthread_mutex_init(&mutex, NULL);
- return (hid_device*)&sham;
-}
-
-int hid_write(hid_device* dev, const unsigned char* data, size_t length)
-{
- if (length > BUFSIZE + 1) {
- printf("Internal test error: %lu > %lu\n", length - 1, BUFSIZE);
- return 0;
- }
- memcpy(_buf, data + 1, length - 1);
- _buf_len = length - 1;
- _expect_more = u2f_packet_process((const USB_FRAME*)_buf);
- if (!_expect_more) {
- // printf("Got complete packet\n");
- _have_data = true;
- }
- _delay(2);
- return length;
-}
-
-int hid_read_timeout(hid_device* dev, unsigned char* data, size_t length, int milliseconds)
-{
- if (_expect_more || !_have_data) {
- if (_expect_more) {
- // printf("Internal error: expected more before read\n");
- }
- if (!_have_data) {
- // printf("No data yet\n");
- }
- _delay(600);
- usb_processing_process(usb_processing_u2f());
- }
- usb_processing_process(usb_processing_u2f());
- uint8_t* p = queue_pull(queue_u2f_queue());
- // printf("Queue: %p\n", p);
- if (p != NULL) {
- memcpy(data, p, MIN(length, BUFSIZE));
- } else {
- // printf("No data in queue\n");
- _delay(600);
- return -127;
- }
- if (queue_peek(queue_u2f_queue()) == NULL) {
- if (usb_processing_locked(usb_processing_u2f())) {
- usb_processing_unlock();
- }
- _have_data = false;
- }
- _expect_more = false;
- _delay(2);
- return length;
-}
-
-struct hid_device_info* hid_enumerate(unsigned short vendor_id, unsigned short product_id)
-{
- static struct hid_device_info dev = {
- .path = "sham",
- .vendor_id = 0x03eb,
- .product_id = 0x2403,
- .manufacturer_string = L"mock",
- .product_string = L"mock",
- .next = NULL,
- };
- return &dev;
-}
-
-void hid_free_enumeration(struct hid_device_info* devs) {}
-
-#pragma GCC diagnostic pop
diff --git a/test/unit-test/framework/src/mock_gestures.c b/test/unit-test/framework/src/mock_gestures.c
new file mode 100644
index 0000000..47c25e5
--- /dev/null
+++ b/test/unit-test/framework/src/mock_gestures.c
@@ -0,0 +1,86 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <cmocka.h>
+
+#include "mock_gestures.h"
+#include "mock_qtouch.h"
+#include <util.h>
+
+#define MEASUREMENT_PERIOD 125
+
+static bool gestures_history_reset = false;
+
+/********************************** POSITIONING **********************************/
+
+/**
+ * Converts the screen position into the slider position.
+ */
+// TODO: clean up eventually. This is copied form gestures.c
+static uint16_t _screen_to_slider_position(uint8_t screen_position)
+{
+ uint16_t slider_position = ((float)screen_position / (float)SCREEN_WIDTH) * MAX_SLIDER_POS;
+ return slider_position;
+}
+
+/**
+ * Mocks the sensors for sliding and tap or hold detection.
+ * The flag 'expect_slide_detection' indicates whether the caller expects that the mocked gesture
+ * detection returns after detecting a slide gesture. This flag needs to be set to false if the
+ * caller requires mocking of the sensor node signal and sensor node reference driver functions.
+ * @param[in] pos The position at which the touch slider was touched (between 0 and 255).
+ */
+void mock_gestures_touch(slider_location_t location, uint8_t screen_position)
+{
+ for (int j = 0; j < MEASUREMENT_PERIOD; j++) {
+ for (int i = 0; i < TOUCH_NUM_SLIDERS; i++) {
+ if (i == location) {
+ will_return(qtouch_is_scroller_active, 129);
+ uint8_t measured_position = _screen_to_slider_position(screen_position);
+ if (location == bottom_slider) {
+ measured_position = MAX_SLIDER_POS - measured_position;
+ }
+ will_return(qtouch_get_scroller_position, measured_position);
+ } else {
+ will_return(qtouch_is_scroller_active, 0);
+ }
+ }
+ gestures_detect(gestures_history_reset, true);
+ gestures_history_reset = false;
+ }
+}
+
+/**
+ * Mocks the sensors for slider release detection.
+ */
+void mock_gestures_touch_release(void)
+{
+ for (int i = 0; i < TOUCH_NUM_SLIDERS; i++) {
+ will_return(qtouch_is_scroller_active, 0);
+ }
+ gestures_detect(gestures_history_reset, true);
+ gestures_history_reset = false;
+}
+
+/**
+ * Initializes the touch detection by resetting the detection history.
+ */
+void mock_gestures_touch_init(void)
+{
+ gestures_history_reset = true;
+}
diff --git a/test/unit-test/framework/src/mock_hidapi.c b/test/unit-test/framework/src/mock_hidapi.c
new file mode 100644
index 0000000..4841235
--- /dev/null
+++ b/test/unit-test/framework/src/mock_hidapi.c
@@ -0,0 +1,164 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <util.h>
+
+// POSIX
+#include <pthread.h>
+
+#include <hidapi.h>
+
+#include "queue.h"
+#include "u2f.h"
+#include "u2f/u2f_packet.h"
+#include "usb/usb_processing.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
+
+#define BUFSIZE 0x40LU
+
+static uint8_t _buf[BUFSIZE];
+static size_t _buf_len;
+static bool _expect_more;
+
+static bool _have_data;
+static pthread_t thread;
+static bool timer_thread_stop;
+static pthread_mutex_t mutex;
+
+static void _delay(uint32_t msec)
+{
+ struct timespec rem;
+ struct timespec ts = {
+ .tv_sec = 0,
+ .tv_nsec = msec * 1000000,
+ };
+ nanosleep(&ts, &rem);
+}
+
+void* timer_task(void* args)
+{
+ (void)args;
+ for (;;) {
+ // printf("tick\n");
+ u2f_packet_timeout_tick();
+ uint32_t timeout_cid;
+ while (u2f_packet_timeout_get(&timeout_cid)) {
+ u2f_packet_timeout(timeout_cid);
+ }
+ _delay(90);
+ pthread_mutex_lock(&mutex);
+ if (timer_thread_stop) {
+ pthread_mutex_unlock(&mutex);
+ return 0;
+ }
+ pthread_mutex_unlock(&mutex);
+ }
+ return 0;
+}
+
+int hid_exit(void)
+{
+ return 0;
+}
+
+int hid_init(void)
+{
+ return 0;
+}
+
+void hid_close(hid_device* dev)
+{
+ pthread_mutex_lock(&mutex);
+ timer_thread_stop = true;
+ pthread_mutex_unlock(&mutex);
+ void* retval;
+ int res = pthread_join(thread, &retval);
+ if (res != 0) {
+ printf("Failed to join thread\n");
+ }
+}
+
+hid_device* hid_open_path(const char* path)
+{
+ static char sham[] = "sham";
+ usb_processing_init();
+ u2f_device_setup();
+ timer_thread_stop = false;
+ int res = pthread_create(&thread, NULL, &timer_task, NULL);
+ if (res != 0) {
+ printf("failed to create thread\n");
+ }
+ pthread_mutex_init(&mutex, NULL);
+ return (hid_device*)&sham;
+}
+
+int hid_write(hid_device* dev, const unsigned char* data, size_t length)
+{
+ if (length > BUFSIZE + 1) {
+ printf("Internal test error: %lu > %lu\n", length - 1, BUFSIZE);
+ return 0;
+ }
+ memcpy(_buf, data + 1, length - 1);
+ _buf_len = length - 1;
+ _expect_more = u2f_packet_process((const USB_FRAME*)_buf);
+ if (!_expect_more) {
+ // printf("Got complete packet\n");
+ _have_data = true;
+ }
+ _delay(2);
+ return length;
+}
+
+int hid_read_timeout(hid_device* dev, unsigned char* data, size_t length, int milliseconds)
+{
+ if (_expect_more || !_have_data) {
+ if (_expect_more) {
+ // printf("Internal error: expected more before read\n");
+ }
+ if (!_have_data) {
+ // printf("No data yet\n");
+ }
+ _delay(600);
+ usb_processing_process(usb_processing_u2f());
+ }
+ usb_processing_process(usb_processing_u2f());
+ uint8_t* p = queue_pull(queue_u2f_queue());
+ // printf("Queue: %p\n", p);
+ if (p != NULL) {
+ memcpy(data, p, MIN(length, BUFSIZE));
+ } else {
+ // printf("No data in queue\n");
+ _delay(600);
+ return -127;
+ }
+ if (queue_peek(queue_u2f_queue()) == NULL) {
+ if (usb_processing_locked(usb_processing_u2f())) {
+ usb_processing_unlock();
+ }
+ _have_data = false;
+ }
+ _expect_more = false;
+ _delay(2);
+ return length;
+}
+
+struct hid_device_info* hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ static struct hid_device_info dev = {
+ .path = "sham",
+ .vendor_id = 0x03eb,
+ .product_id = 0x2403,
+ .manufacturer_string = L"mock",
+ .product_string = L"mock",
+ .next = NULL,
+ };
+ return &dev;
+}
+
+void hid_free_enumeration(struct hid_device_info* devs) {}
+
+#pragma GCC diagnostic pop
diff --git a/test/unit-test/framework/src/mock_memory.c b/test/unit-test/framework/src/mock_memory.c
new file mode 100644
index 0000000..649dede
--- /dev/null
+++ b/test/unit-test/framework/src/mock_memory.c
@@ -0,0 +1,70 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <cmocka.h>
+
+#include <flags.h>
+#include <memory/memory.h>
+#include <mock_memory.h>
+#include <stdio.h>
+#include <string.h>
+
+bool __wrap_memory_is_initialized(void)
+{
+ return mock();
+}
+
+bool __wrap_memory_is_seeded(void)
+{
+ return mock();
+}
+
+static uint8_t _encrypted_seed_and_hmac[96];
+static uint8_t _encrypted_seed_and_hmac_len;
+
+bool __wrap_memory_set_encrypted_seed_and_hmac(uint8_t* encrypted_seed_and_hmac, uint8_t len)
+{
+ memcpy(_encrypted_seed_and_hmac, encrypted_seed_and_hmac, len);
+ _encrypted_seed_and_hmac_len = len;
+ return true;
+}
+
+bool __wrap_memory_get_encrypted_seed_and_hmac(
+ uint8_t* encrypted_seed_and_hmac_out,
+ uint8_t* len_out)
+{
+ *len_out = _encrypted_seed_and_hmac_len;
+ memcpy(encrypted_seed_and_hmac_out, _encrypted_seed_and_hmac, *len_out);
+ return true;
+}
+
+void __wrap_memory_get_device_name(char* name_out)
+{
+ snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", (const char*)mock());
+}
+
+bool __wrap_memory_set_device_name(const char* name)
+{
+ return mock();
+}
+
+bool __wrap_memory_set_mnemonic_passphrase_enabled(bool enabled)
+{
+ check_expected(enabled);
+ return mock();
+}
diff --git a/test/unit-test/framework/src/mock_qtouch.c b/test/unit-test/framework/src/mock_qtouch.c
new file mode 100644
index 0000000..00a2afe
--- /dev/null
+++ b/test/unit-test/framework/src/mock_qtouch.c
@@ -0,0 +1,30 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <cmocka.h>
+
+#include "mock_qtouch.h"
+
+uint8_t qtouch_is_scroller_active(uint16_t sensor_node)
+{
+ return (uint8_t)mock();
+}
+
+uint16_t qtouch_get_scroller_position(uint16_t sensor_node)
+{
+ return (uint16_t)mock();
+}
diff --git a/test/unit-test/framework/src/mock_screen_stack.c b/test/unit-test/framework/src/mock_screen_stack.c
new file mode 100644
index 0000000..31ff935
--- /dev/null
+++ b/test/unit-test/framework/src/mock_screen_stack.c
@@ -0,0 +1,38 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <cmocka.h>
+
+#include <ui/screen_stack.h>
+
+static int _stack_counter = 0;
+void __wrap_ui_screen_stack_push(component_t* component)
+{
+ _stack_counter++;
+ check_expected(component);
+}
+
+void __wrap_ui_screen_stack_pop(void)
+{
+ _stack_counter--;
+ assert_true(_stack_counter >= 0);
+}
+
+void mock_screen_stack_assert_clean(void)
+{
+ assert_int_equal(_stack_counter, 0);
+}
diff --git a/test/unit-test/test_random.h b/test/unit-test/test_random.h
new file mode 100644
index 0000000..e32bd87
--- /dev/null
+++ b/test/unit-test/test_random.h
@@ -0,0 +1,21 @@
+// Copyright 2019 Shift Cryptosecurity AG
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _TEST_RANDOM_H
+#define _TEST_RANDOM_H
+
+int __wrap_rand(void);
+int __wrap_rust_sha256(const unsigned char* data, size_t len, unsigned char* out);
+
+#endif
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.