From cdf1db1c4197f76cf2dd876e3c8a27c807acb7fd Mon Sep 17 00:00:00 2001 From: Mumtahin Farabi Date: Tue, 12 May 2026 00:23:26 -0400 Subject: feat(firmware): scaffold setup Signed-off-by: Mumtahin Farabi --- firmware/tests/CMakeLists.txt | 12 ++++++++ firmware/tests/kernel.c | 42 +++++++++++++++++++++++++ firmware/tests/prj.conf | 10 ++++++ firmware/tests/shell.c | 71 +++++++++++++++++++++++++++++++++++++++++++ firmware/tests/testcase.yaml | 19 ++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 firmware/tests/CMakeLists.txt create mode 100644 firmware/tests/kernel.c create mode 100644 firmware/tests/prj.conf create mode 100644 firmware/tests/shell.c create mode 100644 firmware/tests/testcase.yaml (limited to 'firmware/tests') diff --git a/firmware/tests/CMakeLists.txt b/firmware/tests/CMakeLists.txt new file mode 100644 index 0000000..474f3b1 --- /dev/null +++ b/firmware/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(tests) + +if(TEST_SUITE_KERNEL) + target_sources(app PRIVATE kernel.c) +endif() + +if(TEST_SUITE_SHELL) + target_sources(app PRIVATE shell.c) +endif() diff --git a/firmware/tests/kernel.c b/firmware/tests/kernel.c new file mode 100644 index 0000000..c9f84b6 --- /dev/null +++ b/firmware/tests/kernel.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 Apidae Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(kernel, LOG_LEVEL_INF); + +ZTEST_SUITE(kernel, NULL, NULL, NULL, NULL, NULL); + +ZTEST(kernel, test_uptime_advances) +{ + int64_t t0 = k_uptime_get(); + + k_sleep(K_MSEC(50)); + + int64_t t1 = k_uptime_get(); + + zassert_true(t1 > t0, + "uptime did not advance: t0=%lld t1=%lld", t0, t1); + zassert_true((t1 - t0) >= 40, + "delta %lld ms is implausibly short", (t1 - t0)); +} + +ZTEST(kernel, test_log_subsystem_alive) +{ + LOG_INF("kernel test ran at uptime=%lld ms", k_uptime_get()); +} + +ZTEST(kernel, test_constants_make_sense) +{ + zassert_true(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 0, + "SYS_CLOCK_HW_CYCLES_PER_SEC=%d", + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + zassert_true(CONFIG_SYS_CLOCK_TICKS_PER_SEC > 0, + "SYS_CLOCK_TICKS_PER_SEC=%d", + CONFIG_SYS_CLOCK_TICKS_PER_SEC); +} diff --git a/firmware/tests/prj.conf b/firmware/tests/prj.conf new file mode 100644 index 0000000..9d81903 --- /dev/null +++ b/firmware/tests/prj.conf @@ -0,0 +1,10 @@ +CONFIG_ZTEST=y +CONFIG_TEST=y +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_SHELL=y +CONFIG_SHELL_BACKEND_DUMMY=y +CONFIG_SHELL_BACKEND_SERIAL=n +CONFIG_KERNEL_SHELL=y diff --git a/firmware/tests/shell.c b/firmware/tests/shell.c new file mode 100644 index 0000000..5b52a53 --- /dev/null +++ b/firmware/tests/shell.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2026 Apidae Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static atomic_t hello_invocations = ATOMIC_INIT(0); + +static int cmd_hello(const struct shell *sh, size_t argc, char **argv) +{ + atomic_inc(&hello_invocations); + shell_print(sh, "hello from %s", argc > 1 ? argv[1] : "test"); + return 0; +} + +SHELL_CMD_REGISTER(hello, NULL, "test-only command — increments a counter", cmd_hello); + +ZTEST_SUITE(shell, NULL, NULL, NULL, NULL, NULL); + +ZTEST(shell, test_dummy_backend_is_ready) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + + zassert_not_null(sh, "dummy shell backend pointer is NULL"); +} + +ZTEST(shell, test_executes_builtin_help) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + int rc = shell_execute_cmd(sh, "help"); + + zassert_ok(rc, "shell_execute_cmd(\"help\") failed: %d", rc); +} + +ZTEST(shell, test_executes_kernel_uptime) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + int rc = shell_execute_cmd(sh, "kernel uptime"); + + zassert_ok(rc, "shell_execute_cmd(\"kernel uptime\") failed: %d", rc); +} + +ZTEST(shell, test_executes_custom_command_with_side_effect) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + atomic_val_t before = atomic_get(&hello_invocations); + + int rc = shell_execute_cmd(sh, "hello world"); + + zassert_ok(rc, "shell_execute_cmd(\"hello world\") failed: %d", rc); + + atomic_val_t after = atomic_get(&hello_invocations); + zassert_equal(after, before + 1, + "custom command did not run: before=%ld after=%ld", + (long)before, (long)after); +} + +ZTEST(shell, test_unknown_command_does_not_crash) +{ + const struct shell *sh = shell_backend_dummy_get_ptr(); + int rc = shell_execute_cmd(sh, "definitely_not_a_real_command_xyz"); + + zassert_not_equal(rc, 0, + "unknown command should return non-zero, got %d", rc); +} diff --git a/firmware/tests/testcase.yaml b/firmware/tests/testcase.yaml new file mode 100644 index 0000000..8ba79d0 --- /dev/null +++ b/firmware/tests/testcase.yaml @@ -0,0 +1,19 @@ +common: + harness: ztest + integration_platforms: + - walter/esp32s3/procpu + platform_allow: + - walter/esp32s3/procpu + timeout: 30 + tags: + - boot + +tests: + boot.kernel: + extra_args: TEST_SUITE_KERNEL=y + tags: + - kernel + boot.shell: + extra_args: TEST_SUITE_SHELL=y + tags: + - shell -- cgit v1.3