zephyr/test: Introduce finger capture unit tests
BUG=b:299924239
TEST=twister -v -i -T zephyr/test/fingerprint/task --toolchain host
TEST=twister -v -i -T zephyr/test/fingerprint/task --toolchain llvm
TEST=Run Gitlab CI locally
Change-Id: I807f8fb376c2cf6b32ca054ddc3a5ae60e539c11
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/5093883
Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Tested-by: Patryk Duda <patrykd@google.com>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Commit-Queue: Patryk Duda <patrykd@google.com>
diff --git a/zephyr/test/fingerprint/task/CMakeLists.txt b/zephyr/test/fingerprint/task/CMakeLists.txt
new file mode 100644
index 0000000..f588597
--- /dev/null
+++ b/zephyr/test/fingerprint/task/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+cmake_minimum_required(VERSION 3.13.1)
+find_package(Zephyr REQUIRED HINTS "${ZEPHYR_BASE}")
+project(fpsensor_task_test)
+
+target_sources(app PRIVATE src/mock_fingerprint_algorithm.c)
+target_sources_ifdef(CONFIG_LINK_TEST_SUITE_FINGERPRINT_CAPTURE app PRIVATE
+ src/fpsensor_capture.c)
diff --git a/zephyr/test/fingerprint/task/Kconfig b/zephyr/test/fingerprint/task/Kconfig
new file mode 100644
index 0000000..5d706c2
--- /dev/null
+++ b/zephyr/test/fingerprint/task/Kconfig
@@ -0,0 +1,11 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config LINK_TEST_SUITE_FINGERPRINT_CAPTURE
+ bool "Link fingerprint capture tests"
+ help
+ Link and execute fingerprint subsystem tests that focus
+ on finger capture.
+
+source "Kconfig.zephyr"
diff --git a/zephyr/test/fingerprint/task/boards/native_posix.overlay b/zephyr/test/fingerprint/task/boards/native_posix.overlay
new file mode 100644
index 0000000..33fd972
--- /dev/null
+++ b/zephyr/test/fingerprint/task/boards/native_posix.overlay
@@ -0,0 +1,70 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <board-overlays/native_posix.dts>
+#include <dt-bindings/gpio_defines.h>
+#include <cros/binman.dtsi>
+
+/ {
+ chosen {
+ cros-ec,flash-controller = &cros_flash;
+ cros-fp,fingerprint-sensor = &fpsensor_sim;
+ };
+
+ aliases {
+ gpio-wp = &ec_wp_l;
+ };
+
+ named-gpios {
+ compatible = "named-gpios";
+
+ ec_wp_l: write-protect {
+ gpios = <&gpio0 0 GPIO_INPUT>;
+ };
+
+ fp_sensor_sel: fp_sensor_sel {
+ gpios = <&gpio0 1 GPIO_INPUT>;
+ };
+
+ div_highside: div_highside {
+ gpios = <&gpio0 2 GPIO_OUTPUT_HIGH>;
+ };
+ };
+
+ cros_flash: cros-flash {
+ compatible = "cros-ec,flash-emul";
+ };
+
+ fpsensor_sim: fpsensor-sim {
+ compatible = "cros-ec,fingerprint-sensor-sim";
+ width = <160>;
+ height = <160>;
+ bits-per-pixel = <8>;
+ v4l2-pixel-format = "V4L2_PIX_FMT_GREY";
+ };
+};
+
+&gpio0 {
+ ngpios = <3>;
+};
+
+&flash0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Rollback region must have erase unit size. */
+ rollback0: partition@100000 {
+ label = "rollback0";
+ reg = <0x100000 DT_SIZE_K(4)>;
+ };
+
+ rollback1: partition@101000 {
+ label = "rollback1";
+ reg = <0x101000 DT_SIZE_K(4)>;
+ };
+ };
+};
diff --git a/zephyr/test/fingerprint/task/prj.conf b/zephyr/test/fingerprint/task/prj.conf
new file mode 100644
index 0000000..0a9f72e
--- /dev/null
+++ b/zephyr/test/fingerprint/task/prj.conf
@@ -0,0 +1,38 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+CONFIG_TEST=y
+CONFIG_ZTEST=y
+CONFIG_EMUL=y
+CONFIG_FLASH=y
+CONFIG_GPIO=y
+
+CONFIG_CPP=y
+CONFIG_STD_CPP17=y
+CONFIG_REQUIRES_FULL_LIBCPP=y
+
+CONFIG_CROS_EC=y
+CONFIG_PLATFORM_EC=y
+CONFIG_SHIMMED_TASKS=y
+
+CONFIG_COMMON_LIBC_MALLOC=y
+CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=2048
+CONFIG_BORINGSSL_CRYPTO=y
+
+CONFIG_PLATFORM_EC_RANDOM=y
+CONFIG_PLATFORM_EC_FINGERPRINT=y
+CONFIG_PLATFORM_EC_ROLLBACK=y
+CONFIG_PLATFORM_EC_ROLLBACK_SECRET_SIZE=32
+CONFIG_PLATFORM_EC_SHA256_SW=y
+CONFIG_PLATFORM_EC_SHA256_UNROLLED=y
+CONFIG_PLATFORM_EC_BACKLIGHT_LID=n
+CONFIG_PLATFORM_EC_CONSOLE_CMD_CHARGEN=n
+CONFIG_PLATFORM_EC_SWITCH=n
+CONFIG_PLATFORM_EC_FLASH_SIZE_BYTES=0x200000
+CONFIG_PLATFORM_EC_HOSTCMD=y
+
+CONFIG_FINGERPRINT_SUBSYSTEM=y
+CONFIG_FINGERPRINT_SENSOR=y
+
+CONFIG_FP_ALGORITHM_TEMPLATE_SIZE=32
diff --git a/zephyr/test/fingerprint/task/src/fpsensor_capture.c b/zephyr/test/fingerprint/task/src/fpsensor_capture.c
new file mode 100644
index 0000000..1f7d226
--- /dev/null
+++ b/zephyr/test/fingerprint/task/src/fpsensor_capture.c
@@ -0,0 +1,365 @@
+/* Copyright 2024 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/device.h>
+#include <zephyr/devicetree.h>
+#include <zephyr/drivers/emul.h>
+#include <zephyr/drivers/gpio.h>
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/fff.h>
+#include <zephyr/ztest.h>
+#include <zephyr/ztest_assert.h>
+
+#include <drivers/fingerprint.h>
+#include <drivers/fingerprint_sim.h>
+#include <ec_commands.h>
+#include <ec_tasks.h>
+#include <fpsensor/fpsensor_state.h>
+#include <host_command.h>
+
+DEFINE_FFF_GLOBALS;
+
+FAKE_VALUE_FUNC(int, mkbp_send_event, uint8_t);
+
+#define fp_sim DEVICE_DT_GET(DT_CHOSEN(cros_fp_fingerprint_sensor))
+#define IMAGE_SIZE \
+ FINGERPRINT_SENSOR_REAL_IMAGE_SIZE( \
+ DT_CHOSEN(cros_fp_fingerprint_sensor))
+static uint8_t image_buffer[IMAGE_SIZE];
+static uint8_t frame_buffer[IMAGE_SIZE];
+
+ZTEST_USER(fpsensor_capture, test_finger_capture_simple_image_detection_enabled)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Confirm that detect mode was enabled. */
+ fingerprint_get_state(fp_sim, &state);
+ zassert_true(state.detect_mode);
+
+ /* Disable finger capture. */
+ params.mode = 0;
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_false(response.mode & FP_MODE_CAPTURE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Confirm that detect mode was disabled. */
+ fingerprint_get_state(fp_sim, &state);
+ zassert_false(state.detect_mode);
+}
+
+ZTEST_USER(fpsensor_capture, test_finger_capture_simple_image_mode_is_correct)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor. */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Confirm that correct mode was passed to driver. */
+ fingerprint_get_state(fp_sim, &state);
+ zassert_equal(state.last_acquire_image_mode,
+ FINGERPRINT_CAPTURE_TYPE_SIMPLE_IMAGE);
+}
+
+ZTEST_USER(fpsensor_capture, test_finger_capture_finger_state_partial)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor (partially). */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PARTIAL;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Confirm that no scan was performed. */
+ fingerprint_get_state(fp_sim, &state);
+ zassert_equal(state.last_acquire_image_mode, -1);
+
+ /* Confirm that capture mode is still enabled. */
+ params.mode = FP_MODE_DONT_CHANGE;
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+}
+
+ZTEST_USER(fpsensor_capture, test_finger_capture_finger_state_none)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Confirm that no scan was performed. */
+ fingerprint_get_state(fp_sim, &state);
+ zassert_equal(state.last_acquire_image_mode, -1);
+
+ /* Confirm that capture mode is still enabled. */
+ params.mode = FP_MODE_DONT_CHANGE;
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+}
+
+ZTEST_USER(fpsensor_capture, test_finger_capture_simple_image_scan_too_fast)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor. */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
+ state.acquire_image_result = FINGERPRINT_SENSOR_SCAN_TOO_FAST;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Confirm that capture mode is still enabled. */
+ params.mode = FP_MODE_DONT_CHANGE;
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+}
+
+ZTEST_USER(fpsensor_capture,
+ test_finger_capture_simple_image_scan_success_mode_cleared)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor. */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Confirm that capture mode is not enabled. */
+ params.mode = FP_MODE_DONT_CHANGE;
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_false(response.mode & FP_MODE_CAPTURE);
+}
+
+ZTEST_USER(fpsensor_capture,
+ test_finger_capture_simple_image_scan_success_mkbp_event)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+ uint32_t fp_events;
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor. */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task to process event. */
+ k_msleep(1);
+
+ /* Confirm MKBP event was sent. */
+ zassert_equal(mkbp_send_event_fake.call_count, 1);
+ zassert_equal(mkbp_send_event_fake.arg0_val, EC_MKBP_EVENT_FINGERPRINT);
+
+ /* Confirm that FP_IMAGE_READY MKBP event is sent. */
+ fp_get_next_event((uint8_t *)&fp_events);
+ zassert_true(fp_events & EC_MKBP_FP_IMAGE_READY);
+}
+
+ZTEST_USER(fpsensor_capture,
+ test_finger_capture_simple_image_scan_success_get_frame)
+{
+ struct ec_params_fp_mode params = {
+ .mode = FP_MODE_CAPTURE |
+ (FP_CAPTURE_SIMPLE_IMAGE << FP_MODE_CAPTURE_TYPE_SHIFT),
+ };
+ struct ec_response_fp_mode response;
+ struct fingerprint_sensor_state state;
+ struct ec_params_fp_frame frame_request = {
+ .offset = FP_FRAME_INDEX_RAW_IMAGE << FP_FRAME_INDEX_SHIFT,
+ .size = IMAGE_SIZE,
+ };
+
+ /* Switch mode to capture. */
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_true(response.mode & FP_MODE_CAPTURE);
+ zassert_equal(FP_CAPTURE_TYPE(response.mode), FP_CAPTURE_SIMPLE_IMAGE);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ /* Put finger on the sensor. */
+ fingerprint_get_state(fp_sim, &state);
+ state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
+ fingerprint_set_state(fp_sim, &state);
+
+ /* Prepare image. */
+ memset(image_buffer, 1, IMAGE_SIZE);
+
+ /* Load image to simulator. */
+ fingerprint_load_image(fp_sim, image_buffer, IMAGE_SIZE);
+
+ /* Ping fpsensor task. */
+ fingerprint_run_callback(fp_sim);
+
+ /* Give opportunity for fpsensor task process event. */
+ k_msleep(1);
+
+ /* Get fingerprint raw image and compare buffers. */
+ zassert_ok(ec_cmd_fp_frame(NULL, &frame_request, frame_buffer));
+ zassert_mem_equal(frame_buffer, image_buffer, IMAGE_SIZE);
+}
+
+static void *fpsensor_setup(void)
+{
+ /* Start shimmed tasks. */
+ start_ec_tasks();
+ k_msleep(100);
+
+ return NULL;
+}
+
+static void fpsensor_before(void *f)
+{
+ struct fingerprint_sensor_state state = {
+ .bad_pixels = 0,
+ .maintenance_ran = false,
+ .detect_mode = false,
+ .low_power_mode = false,
+ .finger_state = FINGERPRINT_FINGER_STATE_NONE,
+ .init_result = 0,
+ .deinit_result = 0,
+ .config_result = 0,
+ .get_info_result = 0,
+ .acquire_image_result = FINGERPRINT_SENSOR_SCAN_GOOD,
+ .last_acquire_image_mode = -1,
+ };
+ struct ec_params_fp_mode params = {
+ .mode = 0,
+ };
+ struct ec_response_fp_mode response;
+
+ zassert_ok(ec_cmd_fp_mode(NULL, ¶ms, &response));
+ zassert_equal(response.mode, 0);
+
+ /* Give opportunity for fpsensor task to change mode. */
+ k_msleep(1);
+
+ fingerprint_set_state(fp_sim, &state);
+ RESET_FAKE(mkbp_send_event);
+}
+
+ZTEST_SUITE(fpsensor_capture, NULL, fpsensor_setup, fpsensor_before, NULL,
+ NULL);
diff --git a/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.c b/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.c
new file mode 100644
index 0000000..29925b0
--- /dev/null
+++ b/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.c
@@ -0,0 +1,36 @@
+/* Copyright 2024 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "mock_fingerprint_algorithm.h"
+
+#include <zephyr/fff.h>
+
+#include <fingerprint/fingerprint_alg.h>
+
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_init,
+ const struct fingerprint_algorithm *const);
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_exit,
+ const struct fingerprint_algorithm *const);
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_enroll_start,
+ const struct fingerprint_algorithm *const);
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_enroll_step,
+ const struct fingerprint_algorithm *const,
+ const uint8_t *const, int *);
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_enroll_finish,
+ const struct fingerprint_algorithm *const, void *);
+DEFINE_FAKE_VALUE_FUNC(int, mock_alg_match,
+ const struct fingerprint_algorithm *const, void *,
+ uint32_t, const uint8_t *const, int32_t *, uint32_t *);
+
+const struct fingerprint_algorithm_api mock_alg_api = {
+ .init = mock_alg_init,
+ .exit = mock_alg_exit,
+ .enroll_start = mock_alg_enroll_start,
+ .enroll_step = mock_alg_enroll_step,
+ .enroll_finish = mock_alg_enroll_finish,
+ .match = mock_alg_match,
+};
+
+FINGERPRINT_ALGORITHM_DEFINE(mock_algorithm, NULL, &mock_alg_api);
diff --git a/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.h b/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.h
new file mode 100644
index 0000000..0e76049
--- /dev/null
+++ b/zephyr/test/fingerprint/task/src/mock_fingerprint_algorithm.h
@@ -0,0 +1,23 @@
+/* Copyright 2024 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdint.h>
+
+#include <zephyr/fff.h>
+
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_init,
+ const struct fingerprint_algorithm *const);
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_exit,
+ const struct fingerprint_algorithm *const);
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_enroll_start,
+ const struct fingerprint_algorithm *const);
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_enroll_step,
+ const struct fingerprint_algorithm *const,
+ const uint8_t *const, int *);
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_enroll_finish,
+ const struct fingerprint_algorithm *const, void *);
+DECLARE_FAKE_VALUE_FUNC(int, mock_alg_match,
+ const struct fingerprint_algorithm *const, void *,
+ uint32_t, const uint8_t *const, int32_t *, uint32_t *);
diff --git a/zephyr/test/fingerprint/task/testcase.yaml b/zephyr/test/fingerprint/task/testcase.yaml
new file mode 100644
index 0000000..ed4a2df
--- /dev/null
+++ b/zephyr/test/fingerprint/task/testcase.yaml
@@ -0,0 +1,12 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+common:
+ platform_allow: native_posix
+tests:
+ fingerprint.task.capture:
+ extra_configs:
+ - CONFIG_LINK_TEST_SUITE_FINGERPRINT_CAPTURE=y
+ extra_conf_files:
+ - prj.conf