summaryrefslogtreecommitdiff
path: root/firmware/tests
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/tests')
-rw-r--r--firmware/tests/CMakeLists.txt12
-rw-r--r--firmware/tests/kernel.c42
-rw-r--r--firmware/tests/prj.conf10
-rw-r--r--firmware/tests/shell.c71
-rw-r--r--firmware/tests/testcase.yaml19
5 files changed, 154 insertions, 0 deletions
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 <zephyr/kernel.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/ztest.h>
+
+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 <zephyr/kernel.h>
+#include <zephyr/shell/shell.h>
+#include <zephyr/shell/shell_dummy.h>
+#include <zephyr/sys/atomic.h>
+#include <zephyr/ztest.h>
+
+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