Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:46

0001 /**
0002  * @file
0003  *
0004  * @brief Test TOD Set Hook
0005  *
0006  * @ingroup sptests
0007  */
0008 
0009 /*
0010  *  SPDX-License-Identifier: BSD-2-Clause
0011  *
0012  *  COPYRIGHT (c) 2019.
0013  *  On-Line Applications Research Corporation (OAR).
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 
0038 #include <rtems.h>
0039 #include <rtems/score/todimpl.h>
0040 
0041 #include <errno.h>
0042 #include <stdio.h>
0043 #include <time.h>
0044 #include "tmacros.h"
0045 
0046 /* #define TEST_DEBUG */
0047 
0048 const char rtems_test_name[] = "SPCLOCK TOD HOOK 1";
0049 
0050 typedef struct test_case {
0051   bool       do_settime; 
0052   bool       use_posix; 
0053   bool       do_hook1; 
0054   bool       do_hook2; 
0055   struct tm  tm;
0056 } testcase_t;
0057 
0058 testcase_t Cases[] = {
0059   /* should not trigger hooks when time not set */
0060   { false, false, false, false, { 0, 0, 9, 31, 11, 88 } },
0061   { false, false, true,  true,  { 0, 0, 9, 24, 5,  95 }  },
0062   /* should trigger hook when time is set with Classic API rtems_clock_set */
0063   { true,  false, false, false, { 0, 0, 9, 24, 5,   95 }  },
0064   { true,  false, false, false, { 0, 0, 9, 31, 11,  88 }  },
0065   { true,  false, true,  false, { 0, 0, 9, 31, 11,  88 }  },
0066   { true,  false, true,  true,  { 0, 0, 9, 24, 5,  105 }  },
0067   /* should trigger hook when time is set with POSIX API clock_settime */
0068   { true,  true,  false, false, { 0, 0, 9, 24, 5,   95 }  },
0069   { true,  true,  false, false, { 0, 9, 6, 14, 2,  114 }  },
0070   { true,  true,  true,  false, { 0, 0, 9, 31, 11,  88 }  },
0071   { true,  true,  true,  true,  { 0, 0, 9, 24, 5,  105 }  },
0072 };
0073 
0074 #define NUM_CASES (sizeof(Cases)/sizeof(testcase_t))
0075 
0076 static struct timespec tod_set;
0077 
0078 static bool hook1_executed;
0079 static bool hook2_executed;
0080 
0081 static Status_Control tod_hook1(
0082   TOD_Action             action,
0083   const struct timespec *tod
0084 )
0085 {
0086   rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
0087 
0088   rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
0089   rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
0090 
0091   hook1_executed = true;
0092 
0093   return STATUS_SUCCESSFUL;
0094 }
0095 
0096 static Status_Control tod_hook2(
0097   TOD_Action             action,
0098   const struct timespec *tod
0099 )
0100 {
0101   rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
0102 
0103   rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
0104   rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
0105 
0106   hook2_executed = true;
0107 
0108   return STATUS_SUCCESSFUL;
0109 }
0110 
0111 /*
0112  * Execute one positive test case.
0113  *
0114  * Assume no hooks registered at begining. Unregister if needed at the end.
0115  */
0116 static void do_positive_case(int i)
0117 {
0118   testcase_t  *testcase = &Cases[i];
0119   TOD_Hook     hook1;
0120   TOD_Hook     hook2;
0121 
0122   #ifdef TEST_DEBUG
0123     printf(
0124       "%d: do_settime=%d use_posix=%d do_hook1=%d do_hook2=%d\n",
0125       i,
0126       testcase->do_settime,
0127       testcase->use_posix,
0128       testcase->do_hook1,
0129       testcase->do_hook2
0130     );
0131   #endif
0132 
0133   _Chain_Initialize_node( &hook1.Node );
0134   hook1.handler = tod_hook1;
0135 
0136   _Chain_Initialize_node( &hook2.Node );
0137   hook2.handler = tod_hook2;
0138 
0139   hook1_executed = false;
0140   hook2_executed = false;
0141 
0142   /*
0143    * Register the TOD Hooks
0144    */
0145   if ( testcase->do_hook1 == true ) {
0146     _TOD_Hook_Register( &hook1 );
0147   }
0148 
0149   if ( testcase->do_hook2 == true ) {
0150     _TOD_Hook_Register( &hook2 );
0151   }
0152 
0153   /*
0154    * Now set the time and if registered, let the handlers fire
0155    */
0156   if ( testcase->do_settime == true ) {
0157     rtems_time_of_day   time;
0158     rtems_status_code   status;
0159     struct tm          *tm = &testcase->tm;
0160 
0161     tod_set.tv_sec = mktime( tm );
0162     tod_set.tv_nsec = 0;
0163 
0164     if ( testcase->use_posix == false ) {
0165       build_time(
0166         &time,
0167         tm->tm_mon + 1,
0168         tm->tm_mday,
0169         tm->tm_year + 1900,
0170         tm->tm_hour,
0171         tm->tm_min,
0172         0,
0173         0
0174       );
0175       status = rtems_clock_set( &time );
0176       directive_failed( status, "rtems_clock_set" );
0177     } else {
0178       int rc;
0179 
0180       rc = clock_settime( CLOCK_REALTIME, &tod_set );
0181       rtems_test_assert( rc == 0 ); 
0182     }
0183   }
0184 
0185   /*
0186    * Unregister the TOD hooks 
0187    */
0188   if ( testcase->do_hook1 == true ) {
0189     _TOD_Hook_Unregister( &hook1 );
0190   }
0191 
0192   if ( testcase->do_hook2 == true ) {
0193     _TOD_Hook_Unregister( &hook2 );
0194   }
0195 
0196   #ifdef TEST_DEBUG
0197     printf(
0198       "    hook1_executed=%d hook2_executed=%d\n",
0199       hook1_executed,
0200       hook2_executed
0201     );
0202   #endif
0203 
0204   /*
0205    * Check expected results
0206    */
0207   if ( testcase->do_hook1 == true ) {
0208     rtems_test_assert( testcase->do_settime == hook1_executed );
0209   } else {
0210     rtems_test_assert( hook1_executed == false );
0211   }
0212 
0213   if ( testcase->do_hook2 == true ) {
0214     rtems_test_assert( testcase->do_settime == hook2_executed );
0215   } else {
0216     rtems_test_assert( hook2_executed == false );
0217   }
0218 }
0219 
0220 static bool hook_error_executed;
0221 
0222 static Status_Control tod_hook_error(
0223   TOD_Action             action,
0224   const struct timespec *tod
0225 )
0226 {
0227   rtems_test_assert( action == TOD_ACTION_SET_CLOCK );
0228 
0229   rtems_test_assert( tod->tv_sec == tod_set.tv_sec );
0230   rtems_test_assert( tod->tv_nsec == tod_set.tv_nsec );
0231 
0232   hook_error_executed = true;
0233 
0234   return STATUS_NOT_OWNER;
0235 }
0236 /*
0237  * Execute one negative test case.
0238  *
0239  * Assume no hooks registered at begining. Unregister if needed at the end.
0240  */
0241 static void do_negative_case(bool use_posix)
0242 {
0243   TOD_Hook            hook_error;
0244   rtems_time_of_day   time;
0245   rtems_status_code   status;
0246   struct tm          *tm = &Cases[0].tm;
0247 
0248 
0249   _Chain_Initialize_node( &hook_error.Node );
0250   hook_error.handler = tod_hook_error;
0251 
0252   hook_error_executed = false;
0253 
0254   /*
0255    * Register the TOD Hooks
0256    */
0257   _TOD_Hook_Register( &hook_error );
0258 
0259   /*
0260    * Now set the time and if registered, let the handlers fire
0261    */
0262   tod_set.tv_sec = mktime( tm );
0263   tod_set.tv_nsec = 0;
0264 
0265   if ( use_posix == false ) {
0266     build_time(
0267       &time,
0268       tm->tm_mon + 1,
0269       tm->tm_mday,
0270       tm->tm_year + 1900,
0271       tm->tm_hour,
0272       tm->tm_min,
0273       0,
0274       0
0275     );
0276     status = rtems_clock_set( &time );
0277     rtems_test_assert( status == RTEMS_NOT_OWNER_OF_RESOURCE );
0278   } else {
0279     int rc;
0280 
0281     rc = clock_settime( CLOCK_REALTIME, &tod_set );
0282     rtems_test_assert( rc == -1 ); 
0283     rtems_test_assert( errno == EPERM ); 
0284   }
0285 
0286   /*
0287    * Unregister the TOD hooks 
0288    */
0289   _TOD_Hook_Unregister( &hook_error );
0290 
0291   /*
0292    * Check expected results
0293    */
0294   rtems_test_assert( hook_error_executed == true );
0295 }
0296 
0297 
0298 static rtems_task Init(rtems_task_argument ignored)
0299 {
0300   // rtems_status_code status;
0301   int               i;
0302 
0303   TEST_BEGIN();
0304 
0305   // test positive cases
0306   for (i=0 ; i < NUM_CASES ; i++) {
0307     do_positive_case( i );
0308   }
0309 
0310   // test error cases
0311   do_negative_case(false);
0312   do_negative_case(true);
0313 
0314   TEST_END();
0315 
0316   rtems_test_exit(0);
0317 }
0318 
0319 /* configuration information */
0320 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0321 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0322 
0323 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0324 
0325 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0326 #define CONFIGURE_MAXIMUM_TASKS 1
0327 
0328 #define CONFIGURE_INIT
0329 #include <rtems/confdefs.h>
0330