This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 8c22bb267b434092a8ac8642913a0f59bd5357be Author: ouyangxiangzhen <[email protected]> AuthorDate: Mon Jul 1 20:56:39 2024 +0800 testing/ostest: Add wdog_test to ostest This patch introduces wdog_test, which is used to ensure the functional correctness of the wdog module. Signed-off-by: ouyangxiangzhen <[email protected]> --- testing/ostest/CMakeLists.txt | 3 +- testing/ostest/Makefile | 2 +- testing/ostest/ostest.h | 4 + testing/ostest/ostest_main.c | 6 + testing/ostest/wdog.c | 255 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 268 insertions(+), 2 deletions(-) diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt index af66b2e69..92adb6991 100644 --- a/testing/ostest/CMakeLists.txt +++ b/testing/ostest/CMakeLists.txt @@ -27,7 +27,8 @@ if(CONFIG_TESTING_OSTEST) sigprocmask.c sighand.c signest.c - sighelper.c) + sighelper.c + wdog.c) if(CONFIG_DEV_NULL) list(APPEND SRCS dev_null.c) diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile index 5eabc405a..a430e9272 100644 --- a/testing/ostest/Makefile +++ b/testing/ostest/Makefile @@ -30,7 +30,7 @@ MODULE = $(CONFIG_TESTING_OSTEST) # NuttX OS Test CSRCS = getopt.c libc_memmem.c restart.c sigprocmask.c sighand.c \ - signest.c sighelper.c + signest.c sighelper.c wdog.c MAINSRC = ostest_main.c diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h index 046b580e8..f369319c2 100644 --- a/testing/ostest/ostest.h +++ b/testing/ostest/ostest.h @@ -209,6 +209,10 @@ void signest_test(void); void suspend_test(void); +/* wdog.c *******************************************************************/ + +void wdog_test(void); + /* posixtimers.c ************************************************************/ void timer_test(void); diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c index a426bf890..fa6e68df9 100644 --- a/testing/ostest/ostest_main.c +++ b/testing/ostest/ostest_main.c @@ -524,6 +524,12 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif +#ifndef CONFIG_BUILD_KERNEL + printf("\nuser_main: wdog test\n"); + wdog_test(); + check_test_memory_usage(); +#endif + #ifndef CONFIG_DISABLE_POSIX_TIMERS /* Verify posix timers (with SIGEV_SIGNAL) */ diff --git a/testing/ostest/wdog.c b/testing/ostest/wdog.c new file mode 100644 index 000000000..1c21625c0 --- /dev/null +++ b/testing/ostest/wdog.c @@ -0,0 +1,255 @@ +/**************************************************************************** + * apps/testing/ostest/wdog.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/wdog.h> + +#include <pthread.h> +#include <stdio.h> +#include <assert.h> +#include <unistd.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WDOGTEST_RAND_ITER 1024 +#define WDOGTEST_THREAD_NR 8 + +#define wdtest_assert(x) ASSERT(x) + +#define wdtest_printf(...) printf(__VA_ARGS__) + +/**************************************************************************** + * Private Type + ****************************************************************************/ + +typedef struct wdtest_param_s +{ + uint64_t callback_cnt; + clock_t triggerd_tick; +} wdtest_param_t; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifndef CONFIG_BUILD_KERNEL +static void wdtest_callback(wdparm_t param) +{ + struct timespec tp; + FAR wdtest_param_t *wdtest_param = (FAR wdtest_param_t *)param; + + clock_gettime(CLOCK_MONOTONIC, &tp); + + wdtest_param->callback_cnt += 1; + wdtest_param->triggerd_tick = clock_time2ticks(&tp); +} + +static void wdtest_once(FAR struct wdog_s *wdog, FAR wdtest_param_t *param, + sclock_t delay_ns) +{ + uint64_t cnt; + long diff; + clock_t wdset_tick; + struct timespec tp; + + clock_gettime(CLOCK_MONOTONIC, &tp); + + wdset_tick = clock_time2ticks(&tp); + cnt = param->callback_cnt; + wdtest_assert(wd_start(wdog, NSEC2TICK(delay_ns), wdtest_callback, + (wdparm_t)param) == OK); + usleep(delay_ns / 1000 + 1); + diff = (long)(param->triggerd_tick - wdset_tick); + wdtest_printf("wd_start with delay %ld ns, latency tick %ld\n", + (long)delay_ns, (long)(diff - NSEC2TICK(delay_ns))); + wdtest_assert(cnt + 1 == param->callback_cnt); +} + +static void wdtest_rand(FAR struct wdog_s *wdog, FAR wdtest_param_t *param, + sclock_t rand_ns) +{ + int idx; + sclock_t delay_ns; + uint64_t cnt = param->callback_cnt; + + for (idx = 0; idx < WDOGTEST_RAND_ITER; idx++) + { + delay_ns = rand() % rand_ns; + wdtest_assert(wd_start(wdog, NSEC2TICK(delay_ns), wdtest_callback, + (wdparm_t)param) == 0); + + /* Wait or Cancel 50/50 */ + + if (delay_ns % 2) + { + usleep((delay_ns / 1000) + 1); + wdtest_assert(cnt + 1 == param->callback_cnt); + } + else + { + wd_cancel(wdog); + } + + cnt = param->callback_cnt; + } +} + +static void wdog_test_run(FAR wdtest_param_t *param) +{ + uint64_t cnt; + sclock_t rest; + sclock_t delay; + struct wdog_s test_wdog = + { + 0 + }; + + /* Wrong arguments, all 7 combinations */ + + wdtest_assert(wd_start(NULL, 0, NULL, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(NULL, 0, wdtest_callback, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(NULL, -1, NULL, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(NULL, -1, wdtest_callback, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(&test_wdog, 0, NULL, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(&test_wdog, -1, NULL, (wdparm_t)NULL) != OK); + wdtest_assert(wd_start(&test_wdog, -1, wdtest_callback, (wdparm_t)NULL) + != OK); + + /* Delay = 0 */ + + wdtest_once(&test_wdog, param, 0); + + /* Delay > 0, small */ + + wdtest_once(&test_wdog, param, 1); + + /* Delay > 0, middle 100us */ + + wdtest_once(&test_wdog, param, 100000); + + /* Delay > 0, large ~123456us */ + + wdtest_once(&test_wdog, param, 123456789); + + /* Delay > 0, maximum */ + + cnt = param->callback_cnt; + + /* Maximum */ + + delay = ((clock_t)1 << (sizeof(sclock_t) * CHAR_BIT - 1)) - 1; + wdtest_assert(wd_start(&test_wdog, delay, + wdtest_callback, (wdparm_t)param) == OK); + + /* Sleep for 1s */ + + usleep(USEC_PER_SEC); + + /* Testing wd_gettime */ + + wdtest_assert(wd_gettime(NULL) == 0); + wdtest_assert(wd_cancel(NULL) != 0); + + /* Ensure watchdog not alarmed */ + + wdtest_assert(cnt == param->callback_cnt); + + rest = wd_gettime(&test_wdog); + + wdtest_assert(rest < delay && rest > (delay >> 1)); + + wdtest_printf("wd_start with maximum delay, cancel %ld\n", (long)rest); + + wdtest_assert(wd_cancel(&test_wdog) == 0); + + /* Delay wraparound (delay < 0) */ + + wdtest_assert(wd_start(&test_wdog, delay + 1, + wdtest_callback, (wdparm_t)param) != OK); + wdtest_assert(wd_gettime(&test_wdog) == 0); + + /* Random delay ~1024us */ + + wdtest_rand(&test_wdog, param, 1024); + + /* Random delay ~12345us */ + + wdtest_rand(&test_wdog, param, 12345); +} + +/* Multi threaded */ + +static FAR void *wdog_test_thread(FAR void *param) +{ + wdog_test_run(param); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void wdog_test(void) +{ + int ret; + unsigned int thread_id; + pthread_attr_t attr; + pthread_t pthreads[WDOGTEST_THREAD_NR]; + wdtest_param_t params[WDOGTEST_THREAD_NR] = + { + 0 + }; + + printf("wdog_test start...\n"); + + ret = pthread_attr_init(&attr); + if (ret) + { + wdtest_printf("pthread_attr_init failed %d\n", ret); + } + + /* Create wdog test thread */ + + for (thread_id = 0; thread_id < WDOGTEST_THREAD_NR; thread_id++) + { + pthread_create(&pthreads[thread_id], &attr, wdog_test_thread, + ¶ms[thread_id]); + } + + for (thread_id = 0; thread_id < WDOGTEST_THREAD_NR; thread_id++) + { + pthread_join(pthreads[thread_id], NULL); + } + + ret = pthread_attr_destroy(&attr); + if (ret) + { + wdtest_printf("pthread_attr_destroy failed %d\n", ret); + } + + printf("wdog_test end...\n"); +} +#endif
