From 9a2faa85642dcbd7f7b9060c25a9c9aedb3b3669 Mon Sep 17 00:00:00 2001 From: hanzhijian Date: Wed, 15 Jul 2026 13:54:13 +0800 Subject: [PATCH 1/5] testing/drivers: add watchdog notifier tests Add cmocka coverage for notifier priority ordering, duplicate registration, repeated timeout delivery, unregister behavior, action propagation, and NULL callback data. Signed-off-by: hanzhijian Assisted-by: OpenAI Codex --- .../drivers/drivertest/drivertest_watchdog.c | 141 +++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/testing/drivers/drivertest/drivertest_watchdog.c b/testing/drivers/drivertest/drivertest_watchdog.c index 72f5abe0e2e..ef82fa8faa8 100644 --- a/testing/drivers/drivertest/drivertest_watchdog.c +++ b/testing/drivers/drivertest/drivertest_watchdog.c @@ -45,6 +45,7 @@ #include #include +#include #include /**************************************************************************** @@ -291,6 +292,141 @@ static int capture_callback(int irq, FAR void *context, FAR void *arg) return OK; } +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER + +struct watchdog_notifier_test_nb_s +{ + struct notifier_block nb; + int id; +}; + +struct watchdog_notifier_test_ctx_s +{ + unsigned int calls; + unsigned long action[8]; + FAR void *data[8]; + int id[8]; +}; + +static FAR struct watchdog_notifier_test_ctx_s *g_notifier_test_ctx; + +static int watchdog_notifier_test_callback(FAR struct notifier_block *nb, + unsigned long action, + FAR void *data) +{ + FAR struct watchdog_notifier_test_nb_s *test_nb; + unsigned int index; + + test_nb = (FAR struct watchdog_notifier_test_nb_s *) + ((FAR char *)nb - offsetof(struct watchdog_notifier_test_nb_s, + nb)); + index = g_notifier_test_ctx->calls; + if (index < 8) + { + g_notifier_test_ctx->action[index] = action; + g_notifier_test_ctx->data[index] = data; + g_notifier_test_ctx->id[index] = test_nb->id; + } + + g_notifier_test_ctx->calls++; + return OK; +} + +static unsigned long watchdog_notifier_test_expected_action(void) +{ +#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_ONESHOT) + return WATCHDOG_KEEPALIVE_BY_ONESHOT; +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) + return WATCHDOG_KEEPALIVE_BY_TIMER; +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) + return WATCHDOG_KEEPALIVE_BY_WDOG; +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) + return WATCHDOG_KEEPALIVE_BY_WORKER; +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) + return WATCHDOG_KEEPALIVE_BY_CAPTURE; +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) + return WATCHDOG_KEEPALIVE_BY_IDLE; +#else +# error "An automonitor source must be selected" +#endif +} + +static void drivertest_watchdog_notifier(FAR void **state) +{ + struct watchdog_notifier_test_ctx_s context = + { + 0 + }; + + struct watchdog_notifier_test_nb_s low = + { + .nb = + { + .notifier_call = watchdog_notifier_test_callback, + .priority = 10 + }, + .id = 1 + }; + + struct watchdog_notifier_test_nb_s high = + { + .nb = + { + .notifier_call = watchdog_notifier_test_callback, + .priority = 20 + }, + .id = 2 + }; + + unsigned long expected_action; + + UNUSED(state); + expected_action = watchdog_notifier_test_expected_action(); + g_notifier_test_ctx = &context; + + /* Registration is priority ordered, and duplicate registration of the + * same notifier must not result in a duplicate callback. + */ + + watchdog_notifier_chain_register(&low.nb); + watchdog_notifier_chain_register(&low.nb); + watchdog_notifier_chain_register(&high.nb); + + watchdog_automonitor_timeout(); + + assert_int_equal(context.calls, 2); + assert_int_equal(context.id[0], high.id); + assert_int_equal(context.id[1], low.id); + assert_int_equal(context.action[0], expected_action); + assert_int_equal(context.action[1], expected_action); + assert_null(context.data[0]); + assert_null(context.data[1]); + + /* Every timeout notification is delivered to all currently registered + * callbacks. + */ + + watchdog_automonitor_timeout(); + assert_int_equal(context.calls, 4); + assert_int_equal(context.id[2], high.id); + assert_int_equal(context.id[3], low.id); + + /* Unregistering one callback removes only that callback. */ + + watchdog_notifier_chain_unregister(&high.nb); + watchdog_automonitor_timeout(); + assert_int_equal(context.calls, 5); + assert_int_equal(context.id[4], low.id); + + watchdog_notifier_chain_unregister(&low.nb); + watchdog_automonitor_timeout(); + assert_int_equal(context.calls, 5); + + g_notifier_test_ctx = NULL; +} + +#endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ + /**************************************************************************** * Name: drivertest_watchdog_feeding * @@ -549,7 +685,10 @@ int main(int argc, FAR char *argv[]) cmocka_unit_test_prestate(drivertest_watchdog_interrupts, &wdg_state), cmocka_unit_test_prestate(drivertest_watchdog_loop, &wdg_state), #if !defined(CONFIG_ARCH_ARMV7A) || !defined(CONFIG_ARCH_HAVE_TRUSTZONE) - cmocka_unit_test_prestate(drivertest_watchdog_api, &wdg_state) + cmocka_unit_test_prestate(drivertest_watchdog_api, &wdg_state), +#endif +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER + cmocka_unit_test_prestate(drivertest_watchdog_notifier, &wdg_state) #endif }; From 8fa68e95c21b05ec410e5cf0bc0ad512cb787a0b Mon Sep 17 00:00:00 2001 From: hanzhijian Date: Wed, 15 Jul 2026 13:54:07 +0800 Subject: [PATCH 2/5] testing/drivers: add watchdog notifier cmocka coverage Add a focused watchdog-only cmocka registration and exercise notifier ordering, duplicate registration, repeated timeout delivery, unregister behavior, NULL data, and concurrent register/timeout/unregister activity. Signed-off-by: hanzhijian Assisted-by: OpenAI Codex --- testing/drivers/drivertest/CMakeLists.txt | 17 +- testing/drivers/drivertest/Kconfig | 8 + testing/drivers/drivertest/Makefile | 7 + .../drivers/drivertest/drivertest_watchdog.c | 177 ++++++++++++++---- 4 files changed, 170 insertions(+), 39 deletions(-) diff --git a/testing/drivers/drivertest/CMakeLists.txt b/testing/drivers/drivertest/CMakeLists.txt index 2492842304b..c176b5be593 100644 --- a/testing/drivers/drivertest/CMakeLists.txt +++ b/testing/drivers/drivertest/CMakeLists.txt @@ -21,6 +21,22 @@ # ############################################################################## if(CONFIG_TESTING_DRIVER_TEST) + if(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) + nuttx_add_application( + NAME + cmocka_driver_watchdog + PRIORITY + ${CONFIG_TESTING_DRIVER_TEST_PRIORITY} + STACKSIZE + ${CONFIG_TESTING_DRIVER_TEST_STACKSIZE} + MODULE + ${CONFIG_TESTING_DRIVER_TEST} + DEPENDS + cmocka + SRCS + drivertest_watchdog.c) + endif() +else() if(CONFIG_TESTING_DRIVER_TEST_SIMPLE) nuttx_add_application( NAME @@ -452,5 +468,4 @@ if(CONFIG_TESTING_DRIVER_TEST) SRCS drivertest_pm_runtime.c) endif() - endif() diff --git a/testing/drivers/drivertest/Kconfig b/testing/drivers/drivertest/Kconfig index c0975e9b889..24fcbe525b0 100644 --- a/testing/drivers/drivertest/Kconfig +++ b/testing/drivers/drivertest/Kconfig @@ -24,6 +24,14 @@ config TESTING_DRIVER_TEST_SIMPLE bool "Enable cmocka driver simple test" default n +config TESTING_DRIVER_TEST_WATCHDOG_ONLY + bool "Build only the watchdog notifier cmocka test" + default n + depends on WATCHDOG + ---help--- + Build only cmocka_driver_watchdog. This is useful for a minimal + simulator validation configuration without unrelated driver tests. + config TESTING_ONESHOT_TEST bool "Enable cmocka oneshot test" default n diff --git a/testing/drivers/drivertest/Makefile b/testing/drivers/drivertest/Makefile index 470c9151297..003d3d52af5 100644 --- a/testing/drivers/drivertest/Makefile +++ b/testing/drivers/drivertest/Makefile @@ -26,6 +26,11 @@ PRIORITY = $(CONFIG_TESTING_DRIVER_TEST_PRIORITY) STACKSIZE = $(CONFIG_TESTING_DRIVER_TEST_STACKSIZE) MODULE = $(CONFIG_TESTING_DRIVER_TEST) +ifeq ($(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY),y) +MAINSRC += drivertest_watchdog.c +PROGNAME += cmocka_driver_watchdog +else + ifneq ($(CONFIG_TESTING_DRIVER_TEST_SIMPLE),) MAINSRC += drivertest_simple.c PROGNAME += cmocka_driver_simple @@ -158,4 +163,6 @@ MAINSRC += drivertest_pm_runtime.c PROGNAME += cmocka_driver_pm_runtime endif +endif + include $(APPDIR)/Application.mk diff --git a/testing/drivers/drivertest/drivertest_watchdog.c b/testing/drivers/drivertest/drivertest_watchdog.c index ef82fa8faa8..e229ff8ae78 100644 --- a/testing/drivers/drivertest/drivertest_watchdog.c +++ b/testing/drivers/drivertest/drivertest_watchdog.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,12 @@ #define WDG_DEFAULT_TIMEOUT 2000 #define WDG_DEFAULT_TESTCASE 0 #define WDG_DEFAULT_DEVIATION 20 +#ifndef BOARDIOC_RESETCAUSE_SYS_CHIPPOR +# define BOARDIOC_RESETCAUSE_SYS_CHIPPOR 0 +#endif +#ifndef BOARDIOC_RESETCAUSE_SYS_RWDT +# define BOARDIOC_RESETCAUSE_SYS_RWDT 0 +#endif #if defined(CONFIG_ARCH_ARMV7A) && defined(CONFIG_ARCH_HAVE_TRUSTZONE) #define WDG_COUNT_TESTCASE 3 #else @@ -89,6 +96,12 @@ struct wdg_state_s uint32_t deviation; int test_case; bool test_getstatus; +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER + unsigned int notifier_calls; + unsigned long notifier_action[8]; + FAR void *notifier_data[8]; + int notifier_id[8]; +#endif }; static sem_t g_semaphore; @@ -297,18 +310,10 @@ static int capture_callback(int irq, FAR void *context, FAR void *arg) struct watchdog_notifier_test_nb_s { struct notifier_block nb; - int id; -}; - -struct watchdog_notifier_test_ctx_s -{ - unsigned int calls; - unsigned long action[8]; - FAR void *data[8]; - int id[8]; + int id; }; -static FAR struct watchdog_notifier_test_ctx_s *g_notifier_test_ctx; +static FAR struct wdg_state_s *g_notifier_test_state; static int watchdog_notifier_test_callback(FAR struct notifier_block *nb, unsigned long action, @@ -317,18 +322,16 @@ static int watchdog_notifier_test_callback(FAR struct notifier_block *nb, FAR struct watchdog_notifier_test_nb_s *test_nb; unsigned int index; - test_nb = (FAR struct watchdog_notifier_test_nb_s *) - ((FAR char *)nb - offsetof(struct watchdog_notifier_test_nb_s, - nb)); - index = g_notifier_test_ctx->calls; + test_nb = container_of(nb, struct watchdog_notifier_test_nb_s, nb); + index = g_notifier_test_state->notifier_calls; if (index < 8) { - g_notifier_test_ctx->action[index] = action; - g_notifier_test_ctx->data[index] = data; - g_notifier_test_ctx->id[index] = test_nb->id; + g_notifier_test_state->notifier_action[index] = action; + g_notifier_test_state->notifier_data[index] = data; + g_notifier_test_state->notifier_id[index] = test_nb->id; } - g_notifier_test_ctx->calls++; + g_notifier_test_state->notifier_calls++; return OK; } @@ -353,10 +356,7 @@ static unsigned long watchdog_notifier_test_expected_action(void) static void drivertest_watchdog_notifier(FAR void **state) { - struct watchdog_notifier_test_ctx_s context = - { - 0 - }; + FAR struct wdg_state_s *wdg_state = *state; struct watchdog_notifier_test_nb_s low = { @@ -382,7 +382,8 @@ static void drivertest_watchdog_notifier(FAR void **state) UNUSED(state); expected_action = watchdog_notifier_test_expected_action(); - g_notifier_test_ctx = &context; + wdg_state->notifier_calls = 0; + g_notifier_test_state = wdg_state; /* Registration is priority ordered, and duplicate registration of the * same notifier must not result in a duplicate callback. @@ -394,35 +395,116 @@ static void drivertest_watchdog_notifier(FAR void **state) watchdog_automonitor_timeout(); - assert_int_equal(context.calls, 2); - assert_int_equal(context.id[0], high.id); - assert_int_equal(context.id[1], low.id); - assert_int_equal(context.action[0], expected_action); - assert_int_equal(context.action[1], expected_action); - assert_null(context.data[0]); - assert_null(context.data[1]); + assert_int_equal(wdg_state->notifier_calls, 2); + assert_int_equal(wdg_state->notifier_id[0], high.id); + assert_int_equal(wdg_state->notifier_id[1], low.id); + assert_int_equal(wdg_state->notifier_action[0], expected_action); + assert_int_equal(wdg_state->notifier_action[1], expected_action); + assert_null(wdg_state->notifier_data[0]); + assert_null(wdg_state->notifier_data[1]); /* Every timeout notification is delivered to all currently registered * callbacks. */ watchdog_automonitor_timeout(); - assert_int_equal(context.calls, 4); - assert_int_equal(context.id[2], high.id); - assert_int_equal(context.id[3], low.id); + assert_int_equal(wdg_state->notifier_calls, 4); + assert_int_equal(wdg_state->notifier_id[2], high.id); + assert_int_equal(wdg_state->notifier_id[3], low.id); /* Unregistering one callback removes only that callback. */ watchdog_notifier_chain_unregister(&high.nb); watchdog_automonitor_timeout(); - assert_int_equal(context.calls, 5); - assert_int_equal(context.id[4], low.id); + assert_int_equal(wdg_state->notifier_calls, 5); + assert_int_equal(wdg_state->notifier_id[4], low.id); watchdog_notifier_chain_unregister(&low.nb); watchdog_automonitor_timeout(); - assert_int_equal(context.calls, 5); + assert_int_equal(wdg_state->notifier_calls, 5); + + g_notifier_test_state = NULL; +} + +struct watchdog_notifier_race_s +{ + struct watchdog_notifier_test_nb_s nb; + volatile bool stop; +}; + +static volatile unsigned int g_notifier_race_callbacks; + +static int watchdog_notifier_race_callback(FAR struct notifier_block *nb, + unsigned long action, + FAR void *data) +{ + UNUSED(nb); + UNUSED(action); + UNUSED(data); + g_notifier_race_callbacks++; + return OK; +} + +static FAR void *watchdog_notifier_race_worker(FAR void *arg) +{ + FAR struct watchdog_notifier_race_s *race = arg; + unsigned int count; + + for (count = 0; count < 2000 && !race->stop; count++) + { + watchdog_notifier_chain_register(&race->nb.nb); + watchdog_automonitor_timeout(); + watchdog_notifier_chain_unregister(&race->nb.nb); + } - g_notifier_test_ctx = NULL; + return NULL; +} + +static void drivertest_watchdog_notifier_race(FAR void **state) +{ + struct watchdog_notifier_race_s race = + { + .nb = + { + .nb = + { + .notifier_call = watchdog_notifier_race_callback, + .priority = 10 + }, + .id = 3 + } + }; + + pthread_t thread; + unsigned int count; + int ret; + + UNUSED(state); + g_notifier_race_callbacks = 0; + watchdog_notifier_chain_register(&race.nb.nb); + ret = pthread_create(&thread, NULL, watchdog_notifier_race_worker, &race); + assert_int_equal(ret, 0); + usleep(1000); + + /* Interleave timeout delivery with registration and unregistration from + * another task. The test is successful if the notifier chain remains + * usable and no callback observes a non-NULL payload. + */ + + for (count = 0; count < 2000; count++) + { + watchdog_automonitor_timeout(); + if ((count & 0x3f) == 0) + { + usleep(1000); + } + } + + race.stop = true; + ret = pthread_join(thread, NULL); + assert_int_equal(ret, 0); + watchdog_notifier_chain_unregister(&race.nb.nb); + assert_true(g_notifier_race_callbacks > 0); } #endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ @@ -441,7 +523,9 @@ static void drivertest_watchdog_feeding(FAR void **state) int ret; uint32_t start_ms; FAR struct wdg_state_s *wdg_state; +#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; +#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -452,8 +536,10 @@ static void drivertest_watchdog_feeding(FAR void **state) return; } +#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_CHIPPOR); +#endif dev_fd = wdg_init(wdg_state); @@ -497,7 +583,9 @@ static void drivertest_watchdog_feeding(FAR void **state) static void drivertest_watchdog_interrupts(FAR void **state) { FAR struct wdg_state_s *wdg_state; +#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; +#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -506,8 +594,10 @@ static void drivertest_watchdog_interrupts(FAR void **state) return; } +#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); +#endif wdg_init(wdg_state); @@ -542,7 +632,9 @@ static void drivertest_watchdog_loop(FAR void **state) int ret; static struct wdog_s wdog; FAR struct wdg_state_s *wdg_state; +#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; +#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -551,8 +643,10 @@ static void drivertest_watchdog_loop(FAR void **state) return; } +#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); +#endif wdg_init(wdg_state); @@ -581,15 +675,19 @@ static void drivertest_watchdog_api(FAR void **state) uint32_t start_ms; FAR struct wdg_state_s *wdg_state; struct watchdog_status_s status; +#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; +#endif struct watchdog_capture_s watchdog_capture; wdg_state = (FAR struct wdg_state_s *)*state; assert_int_equal(wdg_state->test_case, 3); +#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); +#endif dev_fd = wdg_init(wdg_state); @@ -681,14 +779,17 @@ int main(int argc, FAR char *argv[]) const struct CMUnitTest tests[] = { +#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY cmocka_unit_test_prestate(drivertest_watchdog_feeding, &wdg_state), cmocka_unit_test_prestate(drivertest_watchdog_interrupts, &wdg_state), cmocka_unit_test_prestate(drivertest_watchdog_loop, &wdg_state), #if !defined(CONFIG_ARCH_ARMV7A) || !defined(CONFIG_ARCH_HAVE_TRUSTZONE) cmocka_unit_test_prestate(drivertest_watchdog_api, &wdg_state), #endif +#endif #ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER - cmocka_unit_test_prestate(drivertest_watchdog_notifier, &wdg_state) + cmocka_unit_test_prestate(drivertest_watchdog_notifier, &wdg_state), + cmocka_unit_test_prestate(drivertest_watchdog_notifier_race, &wdg_state) #endif }; From 764e0a045f51dac8a71439c01d1e9d5bbf991762 Mon Sep 17 00:00:00 2001 From: hanzhijian Date: Wed, 15 Jul 2026 14:11:19 +0800 Subject: [PATCH 3/5] testing/drivers: fix watchdog-only build Include the container_of declaration and exclude unused hardware-only helpers when the watchdog notifier test is built alone. Signed-off-by: hanzhijian Assisted-by: OpenAI Codex --- testing/drivers/drivertest/drivertest_watchdog.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/testing/drivers/drivertest/drivertest_watchdog.c b/testing/drivers/drivertest/drivertest_watchdog.c index e229ff8ae78..2a1924ac30d 100644 --- a/testing/drivers/drivertest/drivertest_watchdog.c +++ b/testing/drivers/drivertest/drivertest_watchdog.c @@ -47,6 +47,7 @@ #include #include +#include #include /**************************************************************************** @@ -104,7 +105,9 @@ struct wdg_state_s #endif }; +#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY static sem_t g_semaphore; +#endif /**************************************************************************** * Private Data @@ -114,6 +117,8 @@ static sem_t g_semaphore; * Private Functions ****************************************************************************/ +#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY + /**************************************************************************** * Name: get_timestamp ****************************************************************************/ @@ -177,6 +182,8 @@ static int wdg_init(FAR struct wdg_state_s *state) return dev_fd; } +#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ + /**************************************************************************** * Name: show_usage ****************************************************************************/ @@ -295,6 +302,8 @@ static void parse_commandline(FAR struct wdg_state_s *wdg_state, int argc, } } +#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY + /**************************************************************************** * Name: capture_callback ****************************************************************************/ @@ -305,6 +314,8 @@ static int capture_callback(int irq, FAR void *context, FAR void *arg) return OK; } +#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ + #ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER struct watchdog_notifier_test_nb_s @@ -509,6 +520,8 @@ static void drivertest_watchdog_notifier_race(FAR void **state) #endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ +#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY + /**************************************************************************** * Name: drivertest_watchdog_feeding * @@ -754,6 +767,8 @@ static void drivertest_watchdog_api(FAR void **state) assert_return_code(ret, OK); } +#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ + /**************************************************************************** * Public Functions ****************************************************************************/ From b4167a1a574a4b01ec0f3e665dc625290ffc2240 Mon Sep 17 00:00:00 2001 From: hanzhijian Date: Wed, 15 Jul 2026 15:04:04 +0800 Subject: [PATCH 4/5] testing/drivers: fix watchdog-only CMake condition Keep the existing drivertest applications under the main test option and register only the watchdog notifier application for the watchdog-only mode. This prevents unrelated cmocka applications from being added to simulator configurations that do not enable the driver test option. Signed-off-by: hanzhijian Assisted-by: OpenAI Codex --- testing/drivers/drivertest/CMakeLists.txt | 35 ++++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/testing/drivers/drivertest/CMakeLists.txt b/testing/drivers/drivertest/CMakeLists.txt index c176b5be593..d72dce649f9 100644 --- a/testing/drivers/drivertest/CMakeLists.txt +++ b/testing/drivers/drivertest/CMakeLists.txt @@ -20,23 +20,23 @@ # # ############################################################################## -if(CONFIG_TESTING_DRIVER_TEST) - if(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) - nuttx_add_application( - NAME - cmocka_driver_watchdog - PRIORITY - ${CONFIG_TESTING_DRIVER_TEST_PRIORITY} - STACKSIZE - ${CONFIG_TESTING_DRIVER_TEST_STACKSIZE} - MODULE - ${CONFIG_TESTING_DRIVER_TEST} - DEPENDS - cmocka - SRCS - drivertest_watchdog.c) - endif() -else() +if(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) + nuttx_add_application( + NAME + cmocka_driver_watchdog + PRIORITY + ${CONFIG_TESTING_DRIVER_TEST_PRIORITY} + STACKSIZE + ${CONFIG_TESTING_DRIVER_TEST_STACKSIZE} + MODULE + ${CONFIG_TESTING_DRIVER_TEST} + DEPENDS + cmocka + SRCS + drivertest_watchdog.c) +endif() + +if(CONFIG_TESTING_DRIVER_TEST AND NOT CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) if(CONFIG_TESTING_DRIVER_TEST_SIMPLE) nuttx_add_application( NAME @@ -468,4 +468,5 @@ else() SRCS drivertest_pm_runtime.c) endif() + endif() From f26a62d7cec28cb425e2670695f6a0b0911a276c Mon Sep 17 00:00:00 2001 From: hanzhijian Date: Thu, 16 Jul 2026 19:03:33 +0800 Subject: [PATCH 5/5] testing/drivers: gate watchdog tests by capability Remove the special watchdog-only selection and register the watchdog cmocka application when reset-cause or timeout-notifier support is available. Compile the hardware watchdog cases only when reset-cause support is enabled, while allowing notifier-only simulator coverage. Remove the invalid reset-cause fallback macros so the real enum values are preserved. Assisted-by: OpenAI Codex Signed-off-by: hanzhijian --- testing/drivers/drivertest/CMakeLists.txt | 21 ++-------- testing/drivers/drivertest/Kconfig | 8 ---- testing/drivers/drivertest/Makefile | 9 +---- .../drivers/drivertest/drivertest_watchdog.c | 38 ++++--------------- 4 files changed, 12 insertions(+), 64 deletions(-) diff --git a/testing/drivers/drivertest/CMakeLists.txt b/testing/drivers/drivertest/CMakeLists.txt index d72dce649f9..ccf43d4ea8d 100644 --- a/testing/drivers/drivertest/CMakeLists.txt +++ b/testing/drivers/drivertest/CMakeLists.txt @@ -20,23 +20,7 @@ # # ############################################################################## -if(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) - nuttx_add_application( - NAME - cmocka_driver_watchdog - PRIORITY - ${CONFIG_TESTING_DRIVER_TEST_PRIORITY} - STACKSIZE - ${CONFIG_TESTING_DRIVER_TEST_STACKSIZE} - MODULE - ${CONFIG_TESTING_DRIVER_TEST} - DEPENDS - cmocka - SRCS - drivertest_watchdog.c) -endif() - -if(CONFIG_TESTING_DRIVER_TEST AND NOT CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) +if(CONFIG_TESTING_DRIVER_TEST) if(CONFIG_TESTING_DRIVER_TEST_SIMPLE) nuttx_add_application( NAME @@ -135,7 +119,8 @@ if(CONFIG_TESTING_DRIVER_TEST AND NOT CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY) drivertest_posix_timer.c) endif() - if(CONFIG_WATCHDOG AND CONFIG_BOARDCTL_RESET_CAUSE) + if(CONFIG_WATCHDOG AND (CONFIG_BOARDCTL_RESET_CAUSE + OR CONFIG_WATCHDOG_TIMEOUT_NOTIFIER)) nuttx_add_application( NAME cmocka_driver_watchdog diff --git a/testing/drivers/drivertest/Kconfig b/testing/drivers/drivertest/Kconfig index 24fcbe525b0..c0975e9b889 100644 --- a/testing/drivers/drivertest/Kconfig +++ b/testing/drivers/drivertest/Kconfig @@ -24,14 +24,6 @@ config TESTING_DRIVER_TEST_SIMPLE bool "Enable cmocka driver simple test" default n -config TESTING_DRIVER_TEST_WATCHDOG_ONLY - bool "Build only the watchdog notifier cmocka test" - default n - depends on WATCHDOG - ---help--- - Build only cmocka_driver_watchdog. This is useful for a minimal - simulator validation configuration without unrelated driver tests. - config TESTING_ONESHOT_TEST bool "Enable cmocka oneshot test" default n diff --git a/testing/drivers/drivertest/Makefile b/testing/drivers/drivertest/Makefile index 003d3d52af5..786d30d1dcb 100644 --- a/testing/drivers/drivertest/Makefile +++ b/testing/drivers/drivertest/Makefile @@ -26,11 +26,6 @@ PRIORITY = $(CONFIG_TESTING_DRIVER_TEST_PRIORITY) STACKSIZE = $(CONFIG_TESTING_DRIVER_TEST_STACKSIZE) MODULE = $(CONFIG_TESTING_DRIVER_TEST) -ifeq ($(CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY),y) -MAINSRC += drivertest_watchdog.c -PROGNAME += cmocka_driver_watchdog -else - ifneq ($(CONFIG_TESTING_DRIVER_TEST_SIMPLE),) MAINSRC += drivertest_simple.c PROGNAME += cmocka_driver_simple @@ -67,7 +62,7 @@ endif endif ifneq ($(CONFIG_WATCHDOG),) -ifneq ($(CONFIG_BOARDCTL_RESET_CAUSE),) +ifneq ($(CONFIG_BOARDCTL_RESET_CAUSE)$(CONFIG_WATCHDOG_TIMEOUT_NOTIFIER),) MAINSRC += drivertest_watchdog.c PROGNAME += cmocka_driver_watchdog endif @@ -163,6 +158,4 @@ MAINSRC += drivertest_pm_runtime.c PROGNAME += cmocka_driver_pm_runtime endif -endif - include $(APPDIR)/Application.mk diff --git a/testing/drivers/drivertest/drivertest_watchdog.c b/testing/drivers/drivertest/drivertest_watchdog.c index 2a1924ac30d..630b824146f 100644 --- a/testing/drivers/drivertest/drivertest_watchdog.c +++ b/testing/drivers/drivertest/drivertest_watchdog.c @@ -60,12 +60,6 @@ #define WDG_DEFAULT_TIMEOUT 2000 #define WDG_DEFAULT_TESTCASE 0 #define WDG_DEFAULT_DEVIATION 20 -#ifndef BOARDIOC_RESETCAUSE_SYS_CHIPPOR -# define BOARDIOC_RESETCAUSE_SYS_CHIPPOR 0 -#endif -#ifndef BOARDIOC_RESETCAUSE_SYS_RWDT -# define BOARDIOC_RESETCAUSE_SYS_RWDT 0 -#endif #if defined(CONFIG_ARCH_ARMV7A) && defined(CONFIG_ARCH_HAVE_TRUSTZONE) #define WDG_COUNT_TESTCASE 3 #else @@ -105,7 +99,7 @@ struct wdg_state_s #endif }; -#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY +#ifdef CONFIG_BOARDCTL_RESET_CAUSE static sem_t g_semaphore; #endif @@ -117,7 +111,7 @@ static sem_t g_semaphore; * Private Functions ****************************************************************************/ -#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY +#ifdef CONFIG_BOARDCTL_RESET_CAUSE /**************************************************************************** * Name: get_timestamp @@ -182,7 +176,7 @@ static int wdg_init(FAR struct wdg_state_s *state) return dev_fd; } -#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ +#endif /* CONFIG_BOARDCTL_RESET_CAUSE */ /**************************************************************************** * Name: show_usage @@ -302,7 +296,7 @@ static void parse_commandline(FAR struct wdg_state_s *wdg_state, int argc, } } -#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY +#ifdef CONFIG_BOARDCTL_RESET_CAUSE /**************************************************************************** * Name: capture_callback @@ -314,7 +308,7 @@ static int capture_callback(int irq, FAR void *context, FAR void *arg) return OK; } -#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ +#endif /* CONFIG_BOARDCTL_RESET_CAUSE */ #ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER @@ -520,7 +514,7 @@ static void drivertest_watchdog_notifier_race(FAR void **state) #endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ -#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY +#ifdef CONFIG_BOARDCTL_RESET_CAUSE /**************************************************************************** * Name: drivertest_watchdog_feeding @@ -536,9 +530,7 @@ static void drivertest_watchdog_feeding(FAR void **state) int ret; uint32_t start_ms; FAR struct wdg_state_s *wdg_state; -#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; -#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -549,10 +541,8 @@ static void drivertest_watchdog_feeding(FAR void **state) return; } -#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_CHIPPOR); -#endif dev_fd = wdg_init(wdg_state); @@ -596,9 +586,7 @@ static void drivertest_watchdog_feeding(FAR void **state) static void drivertest_watchdog_interrupts(FAR void **state) { FAR struct wdg_state_s *wdg_state; -#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; -#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -607,10 +595,8 @@ static void drivertest_watchdog_interrupts(FAR void **state) return; } -#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); -#endif wdg_init(wdg_state); @@ -645,9 +631,7 @@ static void drivertest_watchdog_loop(FAR void **state) int ret; static struct wdog_s wdog; FAR struct wdg_state_s *wdg_state; -#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; -#endif wdg_state = (FAR struct wdg_state_s *)*state; @@ -656,10 +640,8 @@ static void drivertest_watchdog_loop(FAR void **state) return; } -#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); -#endif wdg_init(wdg_state); @@ -688,19 +670,15 @@ static void drivertest_watchdog_api(FAR void **state) uint32_t start_ms; FAR struct wdg_state_s *wdg_state; struct watchdog_status_s status; -#ifdef CONFIG_BOARDCTL_RESET_CAUSE struct boardioc_reset_cause_s reset_cause; -#endif struct watchdog_capture_s watchdog_capture; wdg_state = (FAR struct wdg_state_s *)*state; assert_int_equal(wdg_state->test_case, 3); -#ifdef CONFIG_BOARDCTL_RESET_CAUSE boardctl(BOARDIOC_RESET_CAUSE, (uintptr_t)&reset_cause); assert_int_equal(reset_cause.cause, BOARDIOC_RESETCAUSE_SYS_RWDT); -#endif dev_fd = wdg_init(wdg_state); @@ -767,7 +745,7 @@ static void drivertest_watchdog_api(FAR void **state) assert_return_code(ret, OK); } -#endif /* CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY */ +#endif /* CONFIG_BOARDCTL_RESET_CAUSE */ /**************************************************************************** * Public Functions @@ -794,7 +772,7 @@ int main(int argc, FAR char *argv[]) const struct CMUnitTest tests[] = { -#ifndef CONFIG_TESTING_DRIVER_TEST_WATCHDOG_ONLY +#ifdef CONFIG_BOARDCTL_RESET_CAUSE cmocka_unit_test_prestate(drivertest_watchdog_feeding, &wdg_state), cmocka_unit_test_prestate(drivertest_watchdog_interrupts, &wdg_state), cmocka_unit_test_prestate(drivertest_watchdog_loop, &wdg_state),