-
Notifications
You must be signed in to change notification settings - Fork 752
testing/drivers: add watchdog notifier cmocka coverage #3639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Zepp-Hanzj
wants to merge
5
commits into
apache:master
Choose a base branch
from
Zepp-Hanzj:fix/watchdog-notifier-tests
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+237
−3
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
9a2faa8
testing/drivers: add watchdog notifier tests
Zepp-Hanzj 8fa68e9
testing/drivers: add watchdog notifier cmocka coverage
Zepp-Hanzj 764e0a0
testing/drivers: fix watchdog-only build
Zepp-Hanzj b4167a1
testing/drivers: fix watchdog-only CMake condition
Zepp-Hanzj f26a62d
testing/drivers: gate watchdog tests by capability
Zepp-Hanzj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,8 +43,11 @@ | |
| #include <stdint.h> | ||
| #include <cmocka.h> | ||
| #include <time.h> | ||
| #include <pthread.h> | ||
|
|
||
| #include <nuttx/arch.h> | ||
| #include <nuttx/notifier.h> | ||
| #include <nuttx/nuttx.h> | ||
| #include <nuttx/timers/watchdog.h> | ||
|
|
||
| /**************************************************************************** | ||
|
|
@@ -88,9 +91,17 @@ 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 | ||
| }; | ||
|
|
||
| #ifdef CONFIG_BOARDCTL_RESET_CAUSE | ||
| static sem_t g_semaphore; | ||
| #endif | ||
|
|
||
| /**************************************************************************** | ||
| * Private Data | ||
|
|
@@ -100,6 +111,8 @@ static sem_t g_semaphore; | |
| * Private Functions | ||
| ****************************************************************************/ | ||
|
|
||
| #ifdef CONFIG_BOARDCTL_RESET_CAUSE | ||
|
|
||
| /**************************************************************************** | ||
| * Name: get_timestamp | ||
| ****************************************************************************/ | ||
|
|
@@ -163,6 +176,8 @@ static int wdg_init(FAR struct wdg_state_s *state) | |
| return dev_fd; | ||
| } | ||
|
|
||
| #endif /* CONFIG_BOARDCTL_RESET_CAUSE */ | ||
|
|
||
| /**************************************************************************** | ||
| * Name: show_usage | ||
| ****************************************************************************/ | ||
|
|
@@ -281,6 +296,8 @@ static void parse_commandline(FAR struct wdg_state_s *wdg_state, int argc, | |
| } | ||
| } | ||
|
|
||
| #ifdef CONFIG_BOARDCTL_RESET_CAUSE | ||
|
|
||
| /**************************************************************************** | ||
| * Name: capture_callback | ||
| ****************************************************************************/ | ||
|
|
@@ -291,6 +308,214 @@ static int capture_callback(int irq, FAR void *context, FAR void *arg) | |
| return OK; | ||
| } | ||
|
|
||
| #endif /* CONFIG_BOARDCTL_RESET_CAUSE */ | ||
|
|
||
| #ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER | ||
|
|
||
| struct watchdog_notifier_test_nb_s | ||
| { | ||
| struct notifier_block nb; | ||
| int id; | ||
| }; | ||
|
|
||
| static FAR struct wdg_state_s *g_notifier_test_state; | ||
|
|
||
| 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 = container_of(nb, struct watchdog_notifier_test_nb_s, nb); | ||
| index = g_notifier_test_state->notifier_calls; | ||
| if (index < 8) | ||
| { | ||
| 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_state->notifier_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) | ||
| { | ||
| FAR struct wdg_state_s *wdg_state = *state; | ||
|
|
||
| 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(); | ||
| 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. | ||
| */ | ||
|
|
||
| watchdog_notifier_chain_register(&low.nb); | ||
| watchdog_notifier_chain_register(&low.nb); | ||
| watchdog_notifier_chain_register(&high.nb); | ||
|
|
||
| watchdog_automonitor_timeout(); | ||
|
|
||
| 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(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(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(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); | ||
| } | ||
|
|
||
| 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 */ | ||
|
|
||
| #ifdef CONFIG_BOARDCTL_RESET_CAUSE | ||
|
|
||
| /**************************************************************************** | ||
| * Name: drivertest_watchdog_feeding | ||
| * | ||
|
|
@@ -520,6 +745,8 @@ static void drivertest_watchdog_api(FAR void **state) | |
| assert_return_code(ret, OK); | ||
| } | ||
|
|
||
| #endif /* CONFIG_BOARDCTL_RESET_CAUSE */ | ||
|
|
||
| /**************************************************************************** | ||
| * Public Functions | ||
| ****************************************************************************/ | ||
|
|
@@ -545,11 +772,17 @@ int main(int argc, FAR char *argv[]) | |
|
|
||
| const struct CMUnitTest tests[] = | ||
| { | ||
| #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), | ||
| #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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| #endif | ||
| #ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER | ||
| cmocka_unit_test_prestate(drivertest_watchdog_notifier, &wdg_state), | ||
| cmocka_unit_test_prestate(drivertest_watchdog_notifier_race, &wdg_state) | ||
| #endif | ||
| }; | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.