Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsClockReqSet
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
0049  */
0050 
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include <rtems.h>
0056 #include <rtems/score/todimpl.h>
0057 
0058 #include <rtems/test.h>
0059 
0060 /**
0061  * @defgroup RtemsClockReqSet spec:/rtems/clock/req/set
0062  *
0063  * @ingroup TestsuitesValidationNoClock0
0064  *
0065  * @{
0066  */
0067 
0068 typedef enum {
0069   RtemsClockReqSet_Pre_ToD_Valid,
0070   RtemsClockReqSet_Pre_ToD_ValidLeap4,
0071   RtemsClockReqSet_Pre_ToD_ValidLeap400,
0072   RtemsClockReqSet_Pre_ToD_Youngest,
0073   RtemsClockReqSet_Pre_ToD_Oldest,
0074   RtemsClockReqSet_Pre_ToD_TooJung,
0075   RtemsClockReqSet_Pre_ToD_TooOld,
0076   RtemsClockReqSet_Pre_ToD_InvMonth0,
0077   RtemsClockReqSet_Pre_ToD_InvMonth,
0078   RtemsClockReqSet_Pre_ToD_InvDay0,
0079   RtemsClockReqSet_Pre_ToD_InvDay,
0080   RtemsClockReqSet_Pre_ToD_InvHour,
0081   RtemsClockReqSet_Pre_ToD_InvMinute,
0082   RtemsClockReqSet_Pre_ToD_InvSecond,
0083   RtemsClockReqSet_Pre_ToD_InvTicks,
0084   RtemsClockReqSet_Pre_ToD_InvLeap4,
0085   RtemsClockReqSet_Pre_ToD_InvLeap100,
0086   RtemsClockReqSet_Pre_ToD_InvLeap400,
0087   RtemsClockReqSet_Pre_ToD_AtTimer,
0088   RtemsClockReqSet_Pre_ToD_BeforeTimer,
0089   RtemsClockReqSet_Pre_ToD_AfterTimer,
0090   RtemsClockReqSet_Pre_ToD_Null,
0091   RtemsClockReqSet_Pre_ToD_NA
0092 } RtemsClockReqSet_Pre_ToD;
0093 
0094 typedef enum {
0095   RtemsClockReqSet_Pre_Hook_None,
0096   RtemsClockReqSet_Pre_Hook_Ok,
0097   RtemsClockReqSet_Pre_Hook_NotOk,
0098   RtemsClockReqSet_Pre_Hook_NA
0099 } RtemsClockReqSet_Pre_Hook;
0100 
0101 typedef enum {
0102   RtemsClockReqSet_Post_Status_Ok,
0103   RtemsClockReqSet_Post_Status_InvAddr,
0104   RtemsClockReqSet_Post_Status_InvClk,
0105   RtemsClockReqSet_Post_Status_Hook,
0106   RtemsClockReqSet_Post_Status_NA
0107 } RtemsClockReqSet_Post_Status;
0108 
0109 typedef enum {
0110   RtemsClockReqSet_Post_Clock_Set,
0111   RtemsClockReqSet_Post_Clock_Nop,
0112   RtemsClockReqSet_Post_Clock_NA
0113 } RtemsClockReqSet_Post_Clock;
0114 
0115 typedef enum {
0116   RtemsClockReqSet_Post_Timer_Triggered,
0117   RtemsClockReqSet_Post_Timer_Nop,
0118   RtemsClockReqSet_Post_Timer_NA
0119 } RtemsClockReqSet_Post_Timer;
0120 
0121 typedef struct {
0122   uint16_t Skip : 1;
0123   uint16_t Pre_ToD_NA : 1;
0124   uint16_t Pre_Hook_NA : 1;
0125   uint16_t Post_Status : 3;
0126   uint16_t Post_Clock : 2;
0127   uint16_t Post_Timer : 2;
0128 } RtemsClockReqSet_Entry;
0129 
0130 /**
0131  * @brief Test context for spec:/rtems/clock/req/set test case.
0132  */
0133 typedef struct {
0134   rtems_status_code status;
0135 
0136   bool register_hook;
0137 
0138   Status_Control hook_status;
0139 
0140   rtems_time_of_day *target_tod;
0141 
0142   rtems_time_of_day target_tod_value;
0143 
0144   rtems_time_of_day tod_before;
0145 
0146   rtems_status_code get_tod_before_status;
0147 
0148   rtems_time_of_day tod_after;
0149 
0150   rtems_status_code get_tod_after_status;
0151 
0152   rtems_id timer_id;
0153 
0154   int timer_routine_counter;
0155 
0156   rtems_time_of_day timer_routine_tod;
0157 
0158   struct {
0159     /**
0160      * @brief This member defines the pre-condition states for the next action.
0161      */
0162     size_t pcs[ 2 ];
0163 
0164     /**
0165      * @brief If this member is true, then the test action loop is executed.
0166      */
0167     bool in_action_loop;
0168 
0169     /**
0170      * @brief This member contains the next transition map index.
0171      */
0172     size_t index;
0173 
0174     /**
0175      * @brief This member contains the current transition map entry.
0176      */
0177     RtemsClockReqSet_Entry entry;
0178 
0179     /**
0180      * @brief If this member is true, then the current transition variant
0181      *   should be skipped.
0182      */
0183     bool skip;
0184   } Map;
0185 } RtemsClockReqSet_Context;
0186 
0187 static RtemsClockReqSet_Context
0188   RtemsClockReqSet_Instance;
0189 
0190 static const char * const RtemsClockReqSet_PreDesc_ToD[] = {
0191   "Valid",
0192   "ValidLeap4",
0193   "ValidLeap400",
0194   "Youngest",
0195   "Oldest",
0196   "TooJung",
0197   "TooOld",
0198   "InvMonth0",
0199   "InvMonth",
0200   "InvDay0",
0201   "InvDay",
0202   "InvHour",
0203   "InvMinute",
0204   "InvSecond",
0205   "InvTicks",
0206   "InvLeap4",
0207   "InvLeap100",
0208   "InvLeap400",
0209   "AtTimer",
0210   "BeforeTimer",
0211   "AfterTimer",
0212   "Null",
0213   "NA"
0214 };
0215 
0216 static const char * const RtemsClockReqSet_PreDesc_Hook[] = {
0217   "None",
0218   "Ok",
0219   "NotOk",
0220   "NA"
0221 };
0222 
0223 static const char * const * const RtemsClockReqSet_PreDesc[] = {
0224   RtemsClockReqSet_PreDesc_ToD,
0225   RtemsClockReqSet_PreDesc_Hook,
0226   NULL
0227 };
0228 
0229 typedef RtemsClockReqSet_Context Context;
0230 
0231 static rtems_timer_service_routine _TOD_timer_routine(
0232   rtems_id   timer_id,
0233   void      *user_data
0234 )
0235 {
0236   Context *ctx = user_data;
0237   rtems_status_code status;
0238   ++ctx->timer_routine_counter;
0239   status = rtems_clock_get_tod( &ctx->timer_routine_tod );
0240   T_rsc_success( status );
0241 }
0242 
0243 static void _TOD_prepare_timer( Context *ctx )
0244 {
0245   rtems_status_code status;
0246   rtems_time_of_day tod = { 1988, 1, 1, 0, 0, 0, 0 };
0247 
0248   status = rtems_clock_set( &tod );
0249   T_rsc_success( status );
0250 
0251   tod.year = 1989;
0252   status = rtems_timer_fire_when(
0253     ctx->timer_id,
0254     &tod,
0255     _TOD_timer_routine,
0256     ctx
0257   );
0258   T_rsc_success( status );
0259 }
0260 
0261 static Status_Control TODHook(
0262   TOD_Action             action,
0263   const struct timespec *tod
0264 )
0265 {
0266   Context *ctx;
0267 
0268   ctx = T_fixture_context();
0269   T_eq_int( action, TOD_ACTION_SET_CLOCK );
0270   T_not_null( tod );
0271 
0272   return ctx->hook_status;
0273 }
0274 
0275 static void RtemsClockReqSet_Pre_ToD_Prepare(
0276   RtemsClockReqSet_Context *ctx,
0277   RtemsClockReqSet_Pre_ToD  state
0278 )
0279 {
0280   switch ( state ) {
0281     case RtemsClockReqSet_Pre_ToD_Valid: {
0282       /*
0283        * While the ``time_of_day`` parameter references an arbitrary valid date
0284        * and time between 1988-01-01T00:00:00.000000000Z and
0285        * 2105-12-31T23:59:59.999999999Z.
0286        */
0287       ctx->target_tod_value =
0288         (rtems_time_of_day) { 2021, 3, 11, 11, 10, 59,
0289         rtems_clock_get_ticks_per_second() / 2 };
0290       break;
0291     }
0292 
0293     case RtemsClockReqSet_Pre_ToD_ValidLeap4: {
0294       /*
0295        * While the ``time_of_day`` parameter references a date for a leap year
0296        * with the value of 29th of February.
0297        */
0298       ctx->target_tod_value =
0299         (rtems_time_of_day) { 2096, 2, 29, 0, 0, 0, 0 };
0300       break;
0301     }
0302 
0303     case RtemsClockReqSet_Pre_ToD_ValidLeap400: {
0304       /*
0305        * While the ``time_of_day`` parameter references a date for a leap year
0306        * with the value of 29th of February.
0307        */
0308       ctx->target_tod_value =
0309         (rtems_time_of_day) { 2000, 2, 29, 0, 0, 0, 0 };
0310       break;
0311     }
0312 
0313     case RtemsClockReqSet_Pre_ToD_Youngest: {
0314       /*
0315        * While the ``time_of_day`` parameter references the youngest date and
0316        * time accepted (1988-01-01T00:00:00.000000000Z).
0317        */
0318       ctx->target_tod_value =
0319         (rtems_time_of_day) { 1988, 1, 1, 0, 0, 0, 0 };
0320       break;
0321     }
0322 
0323     case RtemsClockReqSet_Pre_ToD_Oldest: {
0324       /*
0325        * While the ``time_of_day`` parameter references the oldest date and
0326        * time accepted (2099-12-31T23:59:59.999999999Z).
0327        */
0328       ctx->target_tod_value =
0329         (rtems_time_of_day) { 2099, 12, 31, 23, 59, 59,
0330         rtems_clock_get_ticks_per_second() - 1 };
0331       break;
0332     }
0333 
0334     case RtemsClockReqSet_Pre_ToD_TooJung: {
0335       /*
0336        * While the ``time_of_day`` parameter references a valid date and time
0337        * younger than 1988-01-01T00:00:00.000000000Z.
0338        */
0339       ctx->target_tod_value =
0340         (rtems_time_of_day) { 1987, 12, 31, 23, 59, 59,
0341         rtems_clock_get_ticks_per_second() - 1 };
0342       break;
0343     }
0344 
0345     case RtemsClockReqSet_Pre_ToD_TooOld: {
0346       /*
0347        * While the ``time_of_day`` parameter references a valid date and time
0348        * older than 2105-12-31T23:59:59.999999999Z.
0349        */
0350       ctx->target_tod_value =
0351         (rtems_time_of_day) { 2106, 1, 1, 0, 0, 0, 0 };
0352       break;
0353     }
0354 
0355     case RtemsClockReqSet_Pre_ToD_InvMonth0: {
0356       /*
0357        * While the ``time_of_day`` parameter is invalid because the value of
0358        * the month is 0.
0359        */
0360       ctx->target_tod_value =
0361         (rtems_time_of_day) { 2021, 0, 11, 11, 10, 59, 1 };
0362       break;
0363     }
0364 
0365     case RtemsClockReqSet_Pre_ToD_InvMonth: {
0366       /*
0367        * While the ``time_of_day`` parameter is invalid because the value of
0368        * the month is larger than 12.
0369        */
0370       ctx->target_tod_value =
0371         (rtems_time_of_day) { 2021, 13, 11, 11, 10, 59, 1 };
0372       break;
0373     }
0374 
0375     case RtemsClockReqSet_Pre_ToD_InvDay0: {
0376       /*
0377        * While the ``time_of_day`` parameter is invalid because the value of
0378        * the day is 0.
0379        */
0380       ctx->target_tod_value =
0381         (rtems_time_of_day) { 2021, 3, 0, 11, 10, 59, 1 };
0382       break;
0383     }
0384 
0385     case RtemsClockReqSet_Pre_ToD_InvDay: {
0386       /*
0387        * While the ``time_of_day`` parameter is invalid because the value of
0388        * the day is larger than the days of the month.
0389        */
0390       ctx->target_tod_value =
0391         (rtems_time_of_day) { 2021, 2, 29, 11, 10, 59, 1 };
0392       break;
0393     }
0394 
0395     case RtemsClockReqSet_Pre_ToD_InvHour: {
0396       /*
0397        * While the ``time_of_day`` parameter is invalid because the value of
0398        * the hour is larger than 23.
0399        */
0400       ctx->target_tod_value =
0401         (rtems_time_of_day) { 2021, 3, 11, 24, 10, 59, 1 };
0402       break;
0403     }
0404 
0405     case RtemsClockReqSet_Pre_ToD_InvMinute: {
0406       /*
0407        * While the ``time_of_day`` parameter is invalid because the value of
0408        * the minute is larger than 59.
0409        */
0410       ctx->target_tod_value =
0411         (rtems_time_of_day) { 2021, 3, 11, 11, 60, 59, 1 };
0412       break;
0413     }
0414 
0415     case RtemsClockReqSet_Pre_ToD_InvSecond: {
0416       /*
0417        * While the ``time_of_day`` parameter is invalid because the value of
0418        * the second is larger than 59.
0419        */
0420       ctx->target_tod_value =
0421         (rtems_time_of_day) { 2021, 3, 11, 11, 10, 60, 1 };
0422       break;
0423     }
0424 
0425     case RtemsClockReqSet_Pre_ToD_InvTicks: {
0426       /*
0427        * While the ``time_of_day`` parameter is invalid because the value of
0428        * the ticks are larger or equal to the ticks per second.
0429        */
0430       ctx->target_tod_value =
0431         (rtems_time_of_day) { 2021, 3, 11, 11, 10, 60,
0432         rtems_clock_get_ticks_per_second() };
0433       break;
0434     }
0435 
0436     case RtemsClockReqSet_Pre_ToD_InvLeap4: {
0437       /*
0438        * While the ``time_of_day`` parameter is invalid because the value 30th
0439        * of February does not exist in a leap year.
0440        */
0441       ctx->target_tod_value =
0442         (rtems_time_of_day) { 2104, 2, 30, 0, 0, 0, 0 };
0443       break;
0444     }
0445 
0446     case RtemsClockReqSet_Pre_ToD_InvLeap100: {
0447       /*
0448        * While the ``time_of_day`` parameter is invalid because the value 29th
0449        * of February does not exist in a non-leap year.
0450        */
0451       ctx->target_tod_value =
0452         (rtems_time_of_day) { 2100, 2, 29, 0, 0, 0, 0 };
0453       break;
0454     }
0455 
0456     case RtemsClockReqSet_Pre_ToD_InvLeap400: {
0457       /*
0458        * While the ``time_of_day`` parameter is invalid because the value 30th
0459        * of February does not exist in a leap year.
0460        */
0461       ctx->target_tod_value =
0462         (rtems_time_of_day) { 2000, 2, 30, 0, 0, 0, 0 };
0463       break;
0464     }
0465 
0466     case RtemsClockReqSet_Pre_ToD_AtTimer: {
0467       /*
0468        * While the ``time_of_day`` parameter references the same point in time
0469        * when a timer should fire.
0470        */
0471       ctx->target_tod_value =
0472         (rtems_time_of_day) { 1989, 1, 1, 0, 0, 0, 0 };
0473       _TOD_prepare_timer( ctx );
0474       break;
0475     }
0476 
0477     case RtemsClockReqSet_Pre_ToD_BeforeTimer: {
0478       /*
0479        * While the ``time_of_day`` parameter references a point in time before
0480        * a timer should fire.
0481        */
0482       ctx->target_tod_value =
0483         (rtems_time_of_day) { 1988, 12, 31, 23, 59, 59, 0 };
0484       _TOD_prepare_timer( ctx );
0485       break;
0486     }
0487 
0488     case RtemsClockReqSet_Pre_ToD_AfterTimer: {
0489       /*
0490        * While the ``time_of_day`` parameter references a point in time after a
0491        * timer should fire.
0492        */
0493       ctx->target_tod_value =
0494         (rtems_time_of_day) { 1989, 1, 1, 1, 0, 0, 0 };
0495       _TOD_prepare_timer( ctx );
0496       break;
0497     }
0498 
0499     case RtemsClockReqSet_Pre_ToD_Null: {
0500       /*
0501        * WHile the ``time_of_day`` parameter is NULL.
0502        */
0503       ctx->target_tod = NULL;
0504       break;
0505     }
0506 
0507     case RtemsClockReqSet_Pre_ToD_NA:
0508       break;
0509   }
0510 }
0511 
0512 static void RtemsClockReqSet_Pre_Hook_Prepare(
0513   RtemsClockReqSet_Context *ctx,
0514   RtemsClockReqSet_Pre_Hook state
0515 )
0516 {
0517   switch ( state ) {
0518     case RtemsClockReqSet_Pre_Hook_None: {
0519       /*
0520        * While no TOD hook is registered.
0521        */
0522       ctx->register_hook = false;
0523       break;
0524     }
0525 
0526     case RtemsClockReqSet_Pre_Hook_Ok: {
0527       /*
0528        * While all TOD hooks invoked by the rtems_clock_set() call return a
0529        * status code equal to STATUS_SUCCESSFUL.
0530        */
0531       ctx->register_hook = true;
0532       ctx->hook_status = STATUS_SUCCESSFUL;
0533       break;
0534     }
0535 
0536     case RtemsClockReqSet_Pre_Hook_NotOk: {
0537       /*
0538        * While at least one TOD hook invoked by the rtems_clock_set() call
0539        * returns a status code not equal to STATUS_SUCCESSFUL.
0540        */
0541       ctx->register_hook = true;
0542       ctx->hook_status = STATUS_UNAVAILABLE;
0543       break;
0544     }
0545 
0546     case RtemsClockReqSet_Pre_Hook_NA:
0547       break;
0548   }
0549 }
0550 
0551 static void RtemsClockReqSet_Post_Status_Check(
0552   RtemsClockReqSet_Context    *ctx,
0553   RtemsClockReqSet_Post_Status state
0554 )
0555 {
0556   switch ( state ) {
0557     case RtemsClockReqSet_Post_Status_Ok: {
0558       /*
0559        * The return status of rtems_clock_set() shall be RTEMS_SUCCESSFUL
0560        */
0561       T_rsc_success( ctx->status );
0562       break;
0563     }
0564 
0565     case RtemsClockReqSet_Post_Status_InvAddr: {
0566       /*
0567        * The return status of rtems_clock_set() shall be RTEMS_INVALID_ADDRESS.
0568        */
0569       T_rsc( ctx->status, RTEMS_INVALID_ADDRESS );
0570       break;
0571     }
0572 
0573     case RtemsClockReqSet_Post_Status_InvClk: {
0574       /*
0575        * The return status of rtems_clock_set() shall be RTEMS_INVALID_CLOCK.
0576        */
0577       T_rsc( ctx->status, RTEMS_INVALID_CLOCK );
0578       break;
0579     }
0580 
0581     case RtemsClockReqSet_Post_Status_Hook: {
0582       /*
0583        * The return status of rtems_clock_set() shall be derived from the
0584        * status returned by the TOD hook.
0585        */
0586       T_rsc( ctx->status, RTEMS_UNSATISFIED );
0587       break;
0588     }
0589 
0590     case RtemsClockReqSet_Post_Status_NA:
0591       break;
0592   }
0593 }
0594 
0595 static void RtemsClockReqSet_Post_Clock_Check(
0596   RtemsClockReqSet_Context   *ctx,
0597   RtemsClockReqSet_Post_Clock state
0598 )
0599 {
0600   switch ( state ) {
0601     case RtemsClockReqSet_Post_Clock_Set: {
0602       /*
0603        * The CLOCK_REALTIME shall be set to the values of the object referenced
0604        * by the ``time_of_day`` parameter during the rtems_clock_set() call.
0605        */
0606       T_eq_ptr( ctx->target_tod, &ctx->target_tod_value );
0607       T_rsc_success( ctx->get_tod_after_status );
0608       T_eq_u32( ctx->tod_after.year, ctx->target_tod_value.year );
0609       T_eq_u32( ctx->tod_after.month, ctx->target_tod_value.month );
0610       T_eq_u32( ctx->tod_after.day, ctx->target_tod_value.day );
0611       T_eq_u32( ctx->tod_after.hour, ctx->target_tod_value.hour );
0612       T_eq_u32( ctx->tod_after.minute, ctx->target_tod_value.minute );
0613       T_eq_u32( ctx->tod_after.second, ctx->target_tod_value.second );
0614       /* rtems_clock_set() or rtems_clock_get_tod() cause an error of 1 tick */
0615       T_ge_u32( ctx->tod_after.ticks + 1, ctx->target_tod_value.ticks );
0616       T_le_u32( ctx->tod_after.ticks, ctx->target_tod_value.ticks );
0617       break;
0618     }
0619 
0620     case RtemsClockReqSet_Post_Clock_Nop: {
0621       /*
0622        * The state of the CLOCK_REALTIME shall not be changed by the
0623        * rtems_clock_set() call.
0624        */
0625       T_rsc_success( ctx->get_tod_before_status );
0626       T_eq_u32( ctx->tod_after.year, ctx->tod_before.year );
0627       T_eq_u32( ctx->tod_after.month, ctx->tod_before.month );
0628       T_eq_u32( ctx->tod_after.day, ctx->tod_before.day );
0629       T_eq_u32( ctx->tod_after.hour, ctx->tod_before.hour );
0630       T_eq_u32( ctx->tod_after.minute, ctx->tod_before.minute );
0631       T_eq_u32( ctx->tod_after.second, ctx->tod_before.second );
0632       T_eq_u32( ctx->tod_after.ticks, ctx->tod_before.ticks );
0633       break;
0634     }
0635 
0636     case RtemsClockReqSet_Post_Clock_NA:
0637       break;
0638   }
0639 }
0640 
0641 static void RtemsClockReqSet_Post_Timer_Check(
0642   RtemsClockReqSet_Context   *ctx,
0643   RtemsClockReqSet_Post_Timer state
0644 )
0645 {
0646   switch ( state ) {
0647     case RtemsClockReqSet_Post_Timer_Triggered: {
0648       /*
0649        * The timer routine shall be executed once after the CLOCK_REALTIME has
0650        * been set and before the execution of the rtems_clock_set() call
0651        * terminates.
0652        */
0653       T_eq_int( ctx->timer_routine_counter, 1 );
0654       T_eq_u32( ctx->timer_routine_tod.year, 1989 );
0655       T_eq_u32( ctx->timer_routine_tod.month, 1 );
0656       T_eq_u32( ctx->timer_routine_tod.day, 1 );
0657       T_eq_u32( ctx->timer_routine_tod.minute, 0 );
0658       T_eq_u32( ctx->timer_routine_tod.second, 0 );
0659       T_eq_u32( ctx->timer_routine_tod.ticks, 0 );
0660       break;
0661     }
0662 
0663     case RtemsClockReqSet_Post_Timer_Nop: {
0664       /*
0665        * The the timer routine shall not be invoked during the
0666        * rtems_clock_set() call.
0667        */
0668       T_eq_int( ctx->timer_routine_counter, 0 );
0669       break;
0670     }
0671 
0672     case RtemsClockReqSet_Post_Timer_NA:
0673       break;
0674   }
0675 }
0676 
0677 static void RtemsClockReqSet_Setup( RtemsClockReqSet_Context *ctx )
0678 {
0679   rtems_status_code status;
0680   rtems_name timer_name = rtems_build_name( 'T', 'M', 'R', '0' );
0681   ctx->timer_id = RTEMS_ID_NONE;
0682 
0683   ctx->target_tod = &ctx->target_tod_value;
0684 
0685   status = rtems_timer_create( timer_name, &ctx->timer_id );
0686   T_rsc_success( status );
0687 }
0688 
0689 static void RtemsClockReqSet_Setup_Wrap( void *arg )
0690 {
0691   RtemsClockReqSet_Context *ctx;
0692 
0693   ctx = arg;
0694   ctx->Map.in_action_loop = false;
0695   RtemsClockReqSet_Setup( ctx );
0696 }
0697 
0698 static void RtemsClockReqSet_Teardown( RtemsClockReqSet_Context *ctx )
0699 {
0700   rtems_status_code status;
0701 
0702   if ( RTEMS_ID_NONE != ctx->timer_id ) {
0703     status = rtems_timer_delete( ctx->timer_id );
0704     T_rsc_success( status );
0705   }
0706 }
0707 
0708 static void RtemsClockReqSet_Teardown_Wrap( void *arg )
0709 {
0710   RtemsClockReqSet_Context *ctx;
0711 
0712   ctx = arg;
0713   ctx->Map.in_action_loop = false;
0714   RtemsClockReqSet_Teardown( ctx );
0715 }
0716 
0717 static void RtemsClockReqSet_Prepare( RtemsClockReqSet_Context *ctx )
0718 {
0719   rtems_status_code status;
0720 
0721   status = rtems_timer_cancel( ctx->timer_id );
0722   T_rsc_success( status );
0723   ctx->timer_routine_counter = 0;
0724   ctx->timer_routine_tod = (rtems_time_of_day) { 0, 0, 0, 0, 0, 0, 0 };
0725 }
0726 
0727 static void RtemsClockReqSet_Action( RtemsClockReqSet_Context *ctx )
0728 {
0729   TOD_Hook hook = {
0730     .handler = TODHook
0731   };
0732 
0733   if ( ctx->register_hook ) {
0734     _TOD_Hook_Register( &hook );
0735   }
0736 
0737   ctx->get_tod_before_status = rtems_clock_get_tod( &ctx->tod_before );
0738   ctx->status = rtems_clock_set( ctx->target_tod );
0739   ctx->get_tod_after_status = rtems_clock_get_tod( &ctx->tod_after );
0740 
0741   if ( ctx->register_hook ) {
0742     _TOD_Hook_Unregister( &hook );
0743   }
0744 }
0745 
0746 static const RtemsClockReqSet_Entry
0747 RtemsClockReqSet_Entries[] = {
0748   { 0, 0, 0, RtemsClockReqSet_Post_Status_InvClk,
0749     RtemsClockReqSet_Post_Clock_Nop, RtemsClockReqSet_Post_Timer_Nop },
0750   { 0, 0, 0, RtemsClockReqSet_Post_Status_Ok, RtemsClockReqSet_Post_Clock_Set,
0751     RtemsClockReqSet_Post_Timer_Nop },
0752   { 0, 0, 0, RtemsClockReqSet_Post_Status_Hook,
0753     RtemsClockReqSet_Post_Clock_Nop, RtemsClockReqSet_Post_Timer_Nop },
0754   { 0, 0, 0, RtemsClockReqSet_Post_Status_Ok, RtemsClockReqSet_Post_Clock_Set,
0755     RtemsClockReqSet_Post_Timer_Triggered },
0756   { 0, 0, 0, RtemsClockReqSet_Post_Status_InvAddr,
0757     RtemsClockReqSet_Post_Clock_Nop, RtemsClockReqSet_Post_Timer_Nop }
0758 };
0759 
0760 static const uint8_t
0761 RtemsClockReqSet_Map[] = {
0762   1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0763   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0764   0, 0, 3, 3, 2, 1, 1, 2, 3, 3, 2, 4, 4, 4
0765 };
0766 
0767 static size_t RtemsClockReqSet_Scope( void *arg, char *buf, size_t n )
0768 {
0769   RtemsClockReqSet_Context *ctx;
0770 
0771   ctx = arg;
0772 
0773   if ( ctx->Map.in_action_loop ) {
0774     return T_get_scope( RtemsClockReqSet_PreDesc, buf, n, ctx->Map.pcs );
0775   }
0776 
0777   return 0;
0778 }
0779 
0780 static T_fixture RtemsClockReqSet_Fixture = {
0781   .setup = RtemsClockReqSet_Setup_Wrap,
0782   .stop = NULL,
0783   .teardown = RtemsClockReqSet_Teardown_Wrap,
0784   .scope = RtemsClockReqSet_Scope,
0785   .initial_context = &RtemsClockReqSet_Instance
0786 };
0787 
0788 static inline RtemsClockReqSet_Entry RtemsClockReqSet_PopEntry(
0789   RtemsClockReqSet_Context *ctx
0790 )
0791 {
0792   size_t index;
0793 
0794   index = ctx->Map.index;
0795   ctx->Map.index = index + 1;
0796   return RtemsClockReqSet_Entries[
0797     RtemsClockReqSet_Map[ index ]
0798   ];
0799 }
0800 
0801 static void RtemsClockReqSet_TestVariant( RtemsClockReqSet_Context *ctx )
0802 {
0803   RtemsClockReqSet_Pre_ToD_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0804   RtemsClockReqSet_Pre_Hook_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0805   RtemsClockReqSet_Action( ctx );
0806   RtemsClockReqSet_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0807   RtemsClockReqSet_Post_Clock_Check( ctx, ctx->Map.entry.Post_Clock );
0808   RtemsClockReqSet_Post_Timer_Check( ctx, ctx->Map.entry.Post_Timer );
0809 }
0810 
0811 /**
0812  * @fn void T_case_body_RtemsClockReqSet( void )
0813  */
0814 T_TEST_CASE_FIXTURE( RtemsClockReqSet, &RtemsClockReqSet_Fixture )
0815 {
0816   RtemsClockReqSet_Context *ctx;
0817 
0818   ctx = T_fixture_context();
0819   ctx->Map.in_action_loop = true;
0820   ctx->Map.index = 0;
0821 
0822   for (
0823     ctx->Map.pcs[ 0 ] = RtemsClockReqSet_Pre_ToD_Valid;
0824     ctx->Map.pcs[ 0 ] < RtemsClockReqSet_Pre_ToD_NA;
0825     ++ctx->Map.pcs[ 0 ]
0826   ) {
0827     for (
0828       ctx->Map.pcs[ 1 ] = RtemsClockReqSet_Pre_Hook_None;
0829       ctx->Map.pcs[ 1 ] < RtemsClockReqSet_Pre_Hook_NA;
0830       ++ctx->Map.pcs[ 1 ]
0831     ) {
0832       ctx->Map.entry = RtemsClockReqSet_PopEntry( ctx );
0833       RtemsClockReqSet_Prepare( ctx );
0834       RtemsClockReqSet_TestVariant( ctx );
0835     }
0836   }
0837 }
0838 
0839 /** @} */