summaryrefslogtreecommitdiffstats
path: root/testsuites
diff options
context:
space:
mode:
authorJoel Sherrill <joel@rtems.org>2019-11-12 09:33:41 -0600
committerJoel Sherrill <joel@rtems.org>2019-12-11 15:22:33 -0600
commit08bd7d36cee1b041d54ee9dbace86a1b810938af (patch)
tree18de7bd20167d7430c82810d375534c56dfedb91 /testsuites
parentpipe: Use condition variables (diff)
downloadrtems-08bd7d36cee1b041d54ee9dbace86a1b810938af.tar.bz2
Add TOD Hooks to allow BSP to take action when TOD is set
Two use cases were envisioned for this. 1) a BSP or application which desires to update a real-time clock when the RTEMS TOD is set. 2) a paravirtualized BSP can use this to propagate setting the time in an RTEMS application to the hosting environment. This enables the entire set of applications in the virtualized environments to have a single consistent TOD.
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/sptests/Makefile.am9
-rw-r--r--testsuites/sptests/configure.ac1
-rw-r--r--testsuites/sptests/spclock_todhook01/init.c330
-rw-r--r--testsuites/sptests/spclock_todhook01/spclock_todhook01.doc35
-rw-r--r--testsuites/sptests/spclock_todhook01/spclock_todhook01.scn2
5 files changed, 377 insertions, 0 deletions
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 09751b6d58..f127c2b2e8 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -707,6 +707,15 @@ spclock_err02_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spclock_err02) \
$(support_includes)
endif
+if TEST_spclock_todhook01
+sp_tests += spclock_todhook01
+sp_screens += spclock_todhook01/spclock_todhook01.scn
+sp_docs += spclock_todhook01/spclock_todhook01.doc
+spclock_todhook01_SOURCES = spclock_todhook01/init.c
+spclock_todhook01_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spclock_todhook01) \
+ $(support_includes)
+endif
+
if TEST_spconfig01
sp_tests += spconfig01
sp_screens += spconfig01/spconfig01.scn
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 467d2417f5..d8816d80f0 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -116,6 +116,7 @@ RTEMS_TEST_CHECK([spcbssched03])
RTEMS_TEST_CHECK([spchain])
RTEMS_TEST_CHECK([spclock_err01])
RTEMS_TEST_CHECK([spclock_err02])
+RTEMS_TEST_CHECK([spclock_todhook01])
RTEMS_TEST_CHECK([spconfig01])
RTEMS_TEST_CHECK([spconfig02])
RTEMS_TEST_CHECK([spconsole01])
diff --git a/testsuites/sptests/spclock_todhook01/init.c b/testsuites/sptests/spclock_todhook01/init.c
new file mode 100644
index 0000000000..26f0ff9b48
--- /dev/null
+++ b/testsuites/sptests/spclock_todhook01/init.c
@@ -0,0 +1,330 @@
+/**
+ * @file
+ *
+ * @brief Test TOD Set Hook
+ *
+ * @ingroup sptests
+ */
+
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * COPYRIGHT (c) 2019.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <rtems.h>
+#include <rtems/score/todimpl.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#include "tmacros.h"
+
+/* #define TEST_DEBUG */
+
+const char rtems_test_name[] = "SPCLOCK TOD HOOK 1";
+
+typedef struct test_case {
+ bool do_settime;
+ bool use_posix;
+ bool do_hook1;
+ bool do_hook2;
+ struct tm tm;
+} testcase_t;
+
+testcase_t Cases[] = {
+ /* should not trigger hooks when time not set */
+ { false, false, false, false, { 0, 0, 9, 31, 11, 88 } },
+ { false, false, true, true, { 0, 0, 9, 24, 5, 95 } },
+ /* should trigger hook when time is set with Classic API rtems_clock_set */
+ { true, false, false, false, { 0, 0, 9, 24, 5, 95 } },
+ { true, false, false, false, { 0, 0, 9, 31, 11, 88 } },
+ { true, false, true, false, { 0, 0, 9, 31, 11, 88 } },
+ { true, false, true, true, { 0, 0, 9, 24, 5, 105 } },
+ /* should trigger hook when time is set with POSIX API clock_settime */
+ { true, true, false, false, { 0, 0, 9, 24, 5, 95 } },
+ { true, true, false, false, { 0, 9, 6, 14, 2, 114 } },
+ { true, true, true, false, { 0, 0, 9, 31, 11, 88 } },
+ { true, true, true, true, { 0, 0, 9, 24, 5, 105 } },
+};
+
+#define NUM_CASES (sizeof(Cases)/sizeof(testcase_t))
+
+static struct timespec tod_set;
+
+static bool hook1_executed;
+static bool hook2_executed;
+
+static bool tod_hook1(
+ TOD_Action action,
+ const struct timespec *tod
+)
+{
+ rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+ rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+ rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+ hook1_executed = true;
+
+ return true;
+}
+
+static bool tod_hook2(
+ TOD_Action action,
+ const struct timespec *tod
+)
+{
+ rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+ rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+ rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+ hook2_executed = true;
+
+ return true;
+}
+
+/*
+ * Execute one positive test case.
+ *
+ * Assume no hooks registered at begining. Unregister if needed at the end.
+ */
+static void do_positive_case(int i)
+{
+ testcase_t *testcase = &Cases[i];
+ TOD_Hook hook1;
+ TOD_Hook hook2;
+
+ #ifdef TEST_DEBUG
+ printf(
+ "%d: do_settime=%d use_posix=%d do_hook1=%d do_hook2=%d\n",
+ i,
+ testcase->do_settime,
+ testcase->use_posix,
+ testcase->do_hook1,
+ testcase->do_hook2
+ );
+ #endif
+
+ _Chain_Initialize_node( &hook1.Node );
+ hook1.handler = tod_hook1;
+
+ _Chain_Initialize_node( &hook2.Node );
+ hook2.handler = tod_hook2;
+
+ hook1_executed = false;
+ hook2_executed = false;
+
+ /*
+ * Register the TOD Hooks
+ */
+ if ( testcase->do_hook1 == true ) {
+ _TOD_Hook_Register( &hook1 );
+ }
+
+ if ( testcase->do_hook2 == true ) {
+ _TOD_Hook_Register( &hook2 );
+ }
+
+ /*
+ * Now set the time and if registered, let the handlers fire
+ */
+ if ( testcase->do_settime == true ) {
+ rtems_time_of_day time;
+ rtems_status_code status;
+ struct tm *tm = &testcase->tm;
+
+ tod_set.tv_sec = mktime( tm );
+ tod_set.tv_nsec = 0;
+
+ if ( testcase->use_posix == false ) {
+ build_time(
+ &time,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ 0,
+ 0
+ );
+ status = rtems_clock_set( &time );
+ directive_failed( status, "rtems_clock_set" );
+ } else {
+ int rc;
+
+ rc = clock_settime( CLOCK_REALTIME, &tod_set );
+ rtems_test_assert( rc == 0 );
+ }
+ }
+
+ /*
+ * Unregister the TOD hooks
+ */
+ if ( testcase->do_hook1 == true ) {
+ _TOD_Hook_Unregister( &hook1 );
+ }
+
+ if ( testcase->do_hook2 == true ) {
+ _TOD_Hook_Unregister( &hook2 );
+ }
+
+ #ifdef TEST_DEBUG
+ printf(
+ " hook1_executed=%d hook2_executed=%d\n",
+ hook1_executed,
+ hook2_executed
+ );
+ #endif
+
+ /*
+ * Check expected results
+ */
+ if ( testcase->do_hook1 == true ) {
+ rtems_test_assert( testcase->do_settime == hook1_executed );
+ } else {
+ rtems_test_assert( hook1_executed == false );
+ }
+
+ if ( testcase->do_hook2 == true ) {
+ rtems_test_assert( testcase->do_settime == hook2_executed );
+ } else {
+ rtems_test_assert( hook2_executed == false );
+ }
+}
+
+static bool hook_error_executed;
+
+static bool tod_hook_error(
+ TOD_Action action,
+ const struct timespec *tod
+)
+{
+ rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
+
+ rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
+ rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
+
+ hook_error_executed = true;
+
+ return false;
+}
+/*
+ * Execute one negative test case.
+ *
+ * Assume no hooks registered at begining. Unregister if needed at the end.
+ */
+static void do_negative_case(bool use_posix)
+{
+ TOD_Hook hook_error;
+ rtems_time_of_day time;
+ rtems_status_code status;
+ struct tm *tm = &Cases[0].tm;
+
+
+ _Chain_Initialize_node( &hook_error.Node );
+ hook_error.handler = tod_hook_error;
+
+ hook_error_executed = false;
+
+ /*
+ * Register the TOD Hooks
+ */
+ _TOD_Hook_Register( &hook_error );
+
+ /*
+ * Now set the time and if registered, let the handlers fire
+ */
+ tod_set.tv_sec = mktime( tm );
+ tod_set.tv_nsec = 0;
+
+ if ( use_posix == false ) {
+ build_time(
+ &time,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ 0,
+ 0
+ );
+ status = rtems_clock_set( &time );
+ rtems_test_assert( status == RTEMS_IO_ERROR );
+ } else {
+ int rc;
+
+ rc = clock_settime( CLOCK_REALTIME, &tod_set );
+ rtems_test_assert( rc == -1 );
+ rtems_test_assert( errno == EPERM );
+ }
+
+ /*
+ * Unregister the TOD hooks
+ */
+ _TOD_Hook_Unregister( &hook_error );
+
+ /*
+ * Check expected results
+ */
+ rtems_test_assert( hook_error_executed == true );
+}
+
+
+static rtems_task Init(rtems_task_argument ignored)
+{
+ // rtems_status_code status;
+ int i;
+
+ TEST_BEGIN();
+
+ // test positive cases
+ for (i=0 ; i < NUM_CASES ; i++) {
+ do_positive_case( i );
+ }
+
+ // test error cases
+ do_negative_case(false);
+ do_negative_case(true);
+
+ TEST_END();
+
+ rtems_test_exit(0);
+}
+
+/* configuration information */
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
diff --git a/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc b/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc
new file mode 100644
index 0000000000..0be564edb6
--- /dev/null
+++ b/testsuites/sptests/spclock_todhook01/spclock_todhook01.doc
@@ -0,0 +1,35 @@
+# COPYRIGHT (c) 1989-2014.
+# On-Line Applications Research Corporation (OAR).
+#
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.com/license/LICENSE.
+#
+
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: spclock_todhook01
+
+directives:
+ _TOD_Hook_Register
+ _TOD_Hook_Unregister
+ rtems_clock_set
+ clock_settime
+
+
+concepts:
+
+- Verifies that TOD Hooks can be registered
+
+- Verifies that TOD Hooks can be unregistered
+
+- Verifies that an empty TOD Hooks set is properly processed when the TOD is set
+
+- Verifies that TOD Hooks are executed when the TOD is set
+
+- Verifies that a TOD Hook returning an error is properly reported by
+ rtems_clock_set
+
+- Verifies that a TOD Hook returning an error is properly reported by
+ clock_settime
diff --git a/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn b/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn
new file mode 100644
index 0000000000..b54c10e317
--- /dev/null
+++ b/testsuites/sptests/spclock_todhook01/spclock_todhook01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPCLOCK TOD HOOK 1 ***
+*** END OF TEST SPCLOCK TOD HOOK 1 ***