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 2782ed0721cc9f6069fe6e9bf53ceb67e69bf71b
Author: yangguangcai <[email protected]>
AuthorDate: Wed Mar 29 14:59:30 2023 +0800

    test/drivertest:add oneshot test and posix timer test.
    
    Signed-off-by: yangguangcai <[email protected]>
---
 testing/drivertest/Makefile                 |  12 ++
 testing/drivertest/drivertest_oneshot.c     | 223 ++++++++++++++++++++++++++++
 testing/drivertest/drivertest_posix_timer.c | 222 +++++++++++++++++++++++++++
 3 files changed, 457 insertions(+)

diff --git a/testing/drivertest/Makefile b/testing/drivertest/Makefile
index 3e4aa0a6e..5005f5152 100644
--- a/testing/drivertest/Makefile
+++ b/testing/drivertest/Makefile
@@ -45,6 +45,18 @@ MAINSRC  += drivertest_timer.c
 PROGNAME += cmocka_driver_timer
 endif
 
+ifneq ($(CONFIG_ONESHOT),)
+MAINSRC  += drivertest_oneshot.c
+PROGNAME += cmocka_driver_oneshot
+endif
+
+ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
+ifneq ($(CONFIG_SIG_EVTHREAD),)
+MAINSRC  += drivertest_posix_timer.c
+PROGNAME += cmocka_posix_timer
+endif
+endif
+
 ifneq ($(CONFIG_PWM),)
 MAINSRC  += drivertest_pwm.c
 PROGNAME += cmocka_driver_pwm
diff --git a/testing/drivertest/drivertest_oneshot.c 
b/testing/drivertest/drivertest_oneshot.c
new file mode 100644
index 000000000..5971bb93c
--- /dev/null
+++ b/testing/drivertest/drivertest_oneshot.c
@@ -0,0 +1,223 @@
+/****************************************************************************
+ * apps/testing/drivertest/drivertest_oneshot.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 <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <nuttx/timers/oneshot.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DEFAULT_TIME_OUT 5
+#define ONESHOT_SIGNO 13
+#define ONESHOT_DEFAULT_NSAMPLES 5
+
+#define OPTARG_TO_VALUE(value, type, base)                            \
+  do                                                                  \
+    {                                                                 \
+      FAR char *ptr;                                                  \
+      value = (type)strtoul(optarg, &ptr, base);                      \
+      if (*ptr != '\0')                                               \
+        {                                                             \
+          printf("Parameter error: -%c %s\n", ch, optarg);            \
+          show_usage(argv[0], EXIT_FAILURE);                          \
+        }                                                             \
+    } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct oneshot_state_s
+{
+  int maxdelay;
+  int fre;
+  char devpath[PATH_MAX];
+  struct oneshot_start_s oneshot;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: show_usage
+ ****************************************************************************/
+
+static void show_usage(FAR const char *progname, int exitcode)
+{
+  printf("Usage: %s"
+         " -s <seconds> -d <path>\n",
+         progname);
+
+  exit(exitcode);
+}
+
+/****************************************************************************
+ * Name: parse_commandline
+ ****************************************************************************/
+
+static void parse_commandline(FAR struct oneshot_state_s *oneshot_state,
+                              int argc, FAR char **argv)
+{
+  int ch;
+  time_t converted;
+
+  while ((ch = getopt(argc, argv, "s:d:")) != ERROR)
+    {
+      switch (ch)
+        {
+          case 's':
+            OPTARG_TO_VALUE(converted, time_t, 10);
+            if (converted < 1 || converted > INT_MAX)
+              {
+                printf("signal out of range: %ld\n", converted);
+                show_usage(argv[0], EXIT_FAILURE);
+              }
+
+            oneshot_state->oneshot.ts.tv_sec = converted;
+            break;
+
+          case 'd':
+            strlcpy(oneshot_state->devpath, optarg,
+                                sizeof(oneshot_state->devpath));
+            break;
+
+          case '?':
+            printf("Unsupported option: %s\n", optarg);
+            show_usage(argv[0], EXIT_FAILURE);
+            break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: test_case_oneshot
+ ****************************************************************************/
+
+static void test_case_oneshot(FAR void **state)
+{
+  int ret;
+  int fd;
+  int i;
+  struct timespec trigger_before;
+  struct timespec ts;
+  struct timespec timespec_sub;
+  sigset_t set;
+  FAR struct oneshot_state_s *oneshot_state =
+    (FAR struct oneshot_state_s *)*state;
+
+  oneshot_state->oneshot.pid = getpid();
+
+  signal(ONESHOT_SIGNO, SIG_IGN);
+  sigemptyset(&set);
+  sigaddset(&set, ONESHOT_SIGNO);
+  oneshot_state->oneshot.event.sigev_notify = SIGEV_SIGNAL;
+  oneshot_state->oneshot.event.sigev_signo = ONESHOT_SIGNO;
+  oneshot_state->oneshot.event.sigev_value.sival_ptr = NULL;
+
+  fd = open(oneshot_state->devpath, O_RDONLY);
+  assert_true(fd > 0);
+
+  /* Get MaxDelay */
+
+  ret = ioctl(fd, OSIOC_MAXDELAY, &ts);
+  assert_return_code(ret, OK);
+
+  syslog(LOG_DEBUG, "maxdelay sec:%ld\n", ts.tv_sec);
+  syslog(LOG_DEBUG, "maxdelay nsec:%ld\n", ts.tv_nsec);
+
+  for (i = 0; i < ONESHOT_DEFAULT_NSAMPLES; i++)
+    {
+      /* Start the oneshot */
+
+      ret = ioctl(fd, OSIOC_START, &oneshot_state->oneshot);
+      assert_return_code(ret, OK);
+
+      /* Get current ts */
+
+      ret = ioctl(fd, OSIOC_CURRENT, &ts);
+      assert_return_code(ret, OK);
+      trigger_before = ts;
+
+      ret = sigwaitinfo(&set, NULL);
+      assert_return_code(ret, ONESHOT_SIGNO);
+
+      ret = ioctl(fd, OSIOC_CURRENT, &ts);
+      assert_return_code(ret, OK);
+
+      clock_timespec_subtract(&ts, &trigger_before, &timespec_sub);
+      assert_int_equal(oneshot_state->oneshot.ts.tv_sec,
+                       timespec_sub.tv_sec);
+      assert_in_range(timespec_sub.tv_nsec, 0, NSEC_PER_MSEC);
+    }
+
+  ret = ioctl(fd, OSIOC_START, &oneshot_state->oneshot);
+  assert_return_code(ret, OK);
+
+  /* Cancel the oneshot */
+
+  ret = ioctl(fd, OSIOC_CANCEL, &ts);
+  assert_return_code(ret, OK);
+
+  clock_timespec_subtract(&oneshot_state->oneshot.ts,
+                          &ts, &timespec_sub);
+  assert_int_equal(0, timespec_sub.tv_sec);
+
+  close(fd);
+}
+
+int main(int argc, FAR char *argv[])
+{
+  struct oneshot_state_s oneshot_state =
+  {
+    .devpath = "/dev/oneshot",
+    .oneshot.ts.tv_sec = DEFAULT_TIME_OUT,
+    .oneshot.ts.tv_nsec = 0
+  };
+
+  const struct CMUnitTest tests[] =
+  {
+    cmocka_unit_test_prestate(test_case_oneshot, &oneshot_state)
+  };
+
+  parse_commandline(&oneshot_state, argc, argv);
+
+  return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/testing/drivertest/drivertest_posix_timer.c 
b/testing/drivertest/drivertest_posix_timer.c
new file mode 100644
index 000000000..c042acda6
--- /dev/null
+++ b/testing/drivertest/drivertest_posix_timer.c
@@ -0,0 +1,222 @@
+/****************************************************************************
+ * apps/testing/drivertest/drivertest_posix_timer.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 <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <syslog.h>
+#include <nuttx/timers/timer.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RTC_DEFAULT_DEVIATION 10
+#define DEFAULT_TIME_OUT      2
+#define SLEEPSECONDS          10
+#define COMEINCALLBACK        0
+
+#define OPTARG_TO_VALUE(value, type, base)                            \
+  do                                                                  \
+    {                                                                 \
+      FAR char *ptr;                                                  \
+      value = (type)strtoul(optarg, &ptr, base);                      \
+      if (*ptr != '\0')                                               \
+        {                                                             \
+          printf("Parameter error: -%c %s\n", ch, optarg);            \
+          show_usage(argv[0], EXIT_FAILURE);                          \
+        }                                                             \
+    } while (0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct posix_timer_state_s
+{
+  struct itimerspec it;
+};
+
+struct sigev_para_s
+{
+  int tim;
+  int interval;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: show_usage
+ ****************************************************************************/
+
+static void show_usage(FAR const char *progname, int exitcode)
+{
+  printf("Usage: %s"
+         " -s <timeout seconds>\n",
+         progname);
+
+  exit(exitcode);
+}
+
+/****************************************************************************
+ * Name: parse_commandline
+ ****************************************************************************/
+
+static void parse_commandline(
+  FAR struct posix_timer_state_s *posix_timer_state,
+  int argc, FAR char **argv)
+{
+  int ch;
+  int converted;
+
+  while ((ch = getopt(argc, argv, "s:")) != ERROR)
+    {
+      switch (ch)
+        {
+          case 's':
+            OPTARG_TO_VALUE(converted, uint32_t, 10);
+            if (converted < 1 || converted > INT_MAX)
+              {
+                printf("signal out of range: %d\n", converted);
+                show_usage(argv[0], EXIT_FAILURE);
+              }
+
+            posix_timer_state->it.it_value.tv_sec = (uint32_t)converted;
+            posix_timer_state->it.it_interval.tv_sec = (uint32_t)converted;
+            break;
+
+          case '?':
+            printf("Unsupported option: %s\n", optarg);
+            show_usage(argv[0], EXIT_FAILURE);
+            break;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: get_timestamp
+ ****************************************************************************/
+
+static uint32_t get_timestamp(void)
+{
+  struct timespec ts;
+  uint32_t ms;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+  return ms;
+}
+
+/****************************************************************************
+ * Name: posix_timer_callback
+ ****************************************************************************/
+
+static void posix_timer_callback(union sigval arg)
+{
+  FAR struct sigev_para_s *sigev_para = (struct sigev_para_s *)arg.sival_ptr;
+  int range = get_timestamp() - (*sigev_para).tim;
+  assert_in_range(range,
+                  (*sigev_para).interval * 1000 - RTC_DEFAULT_DEVIATION,
+                  (*sigev_para).interval * 1000 + RTC_DEFAULT_DEVIATION);
+  syslog(LOG_DEBUG, "callback trigger!!!\n");
+  (*sigev_para).tim = get_timestamp();
+}
+
+/****************************************************************************
+ * Name: test_case_posix_timer
+ ****************************************************************************/
+
+static void test_case_posix_timer(FAR void **state)
+{
+  int ret;
+  timer_t timerid;
+  struct sigevent event;
+  struct sigev_para_s sigev_para;
+
+  FAR struct posix_timer_state_s *posix_timer_state;
+  struct itimerspec it;
+
+  memset(&it, 0, sizeof(it));
+  posix_timer_state = (FAR struct posix_timer_state_s *)*state;
+
+  event.sigev_notify = SIGEV_THREAD;
+  event.sigev_notify_function = posix_timer_callback;
+  event.sigev_notify_attributes = NULL;
+  event.sigev_value.sival_ptr = (struct sigev_para_s *)&sigev_para;
+
+  /* Create the timer */
+
+  ret = timer_create(CLOCK_MONOTONIC, &event, &timerid);
+  assert_return_code(ret, OK);
+
+  /* Start the timer */
+
+  ret = timer_settime(timerid, 0, &(posix_timer_state->it), NULL);
+  assert_return_code(ret, OK);
+
+  sigev_para.interval = posix_timer_state->it.it_interval.tv_sec;
+  sigev_para.tim = get_timestamp();
+
+  /* Get the timer status */
+
+  ret = timer_gettime(timerid, &it);
+  assert_return_code(ret, OK);
+  assert_in_range(it.it_value.tv_sec, 0,
+                  posix_timer_state->it.it_value.tv_sec);
+  assert_return_code(it.it_interval.tv_sec,
+                     posix_timer_state->it.it_interval.tv_sec);
+
+  sleep(SLEEPSECONDS);
+
+  /* Delete the timer */
+
+  ret = timer_delete(timerid);
+  assert_return_code(ret, OK);
+}
+
+int main(int argc, FAR char *argv[])
+{
+  struct posix_timer_state_s posix_timer_state =
+  {
+    .it.it_value.tv_sec     = DEFAULT_TIME_OUT,
+    .it.it_value.tv_nsec    = 0,
+    .it.it_interval.tv_sec  = DEFAULT_TIME_OUT,
+    .it.it_interval.tv_nsec = 0
+  };
+
+  const struct CMUnitTest tests[] =
+  {
+    cmocka_unit_test_prestate(test_case_posix_timer, &posix_timer_state)
+  };
+
+  parse_commandline(&posix_timer_state, argc, argv);
+
+  return cmocka_run_group_tests(tests, NULL, NULL);
+}

Reply via email to