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,
+                     &params[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

Reply via email to