diff options
Diffstat (limited to 'spec/rtems/ratemon/req/cancel.yml')
-rw-r--r-- | spec/rtems/ratemon/req/cancel.yml | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/spec/rtems/ratemon/req/cancel.yml b/spec/rtems/ratemon/req/cancel.yml new file mode 100644 index 00000000..26aafd21 --- /dev/null +++ b/spec/rtems/ratemon/req/cancel.yml @@ -0,0 +1,537 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) +enabled-by: true +functional-type: action +links: +- role: interface-function + uid: ../if/cancel +post-conditions: +- name: Status + states: + - name: Ok + test-code: | + T_rsc_success( ctx->status ); + text: | + The return status of ${../if/cancel:/name} shall be + ${../../status/if/successful:/name} + - name: InvId + test-code: | + T_rsc( ctx->status, RTEMS_INVALID_ID ); + text: | + The return status of ${../if/cancel:/name} shall be + ${../../status/if/invalid-id:/name}. + - name: NotOwn + test-code: | + T_rsc( ctx->status, RTEMS_NOT_OWNER_OF_RESOURCE ); + text: | + The return status of ${../if/cancel:/name} shall be + ${../../status/if/not-owner-of-resource:/name}. + test-epilogue: null + test-prologue: null +- name: State + states: + - name: Inactive + test-code: | + T_eq_int( ctx->period_status.state, RATE_MONOTONIC_INACTIVE ); + text: | + The ${../glossary/state:/term} of the period shall be + ${../glossary/inactive:/term} after the return of the + ${../if/cancel:/name} call. + - name: Nop + test-code: | + T_eq_u32( ctx->period_status.state, ctx->previous_state ); + text: | + Objects referenced by the ${../if/cancel:/params[0]/name} + parameter in past calls to ${../if/cancel:/name} shall not be + accessed by the ${../if/cancel:/name} call (see also + ${../glossary/nop:/term}). + test-epilogue: null + test-prologue: null +- name: Postponed + states: + - name: Zero + test-code: | + T_eq_u32( ctx->period_status.postponed_jobs_count, 0 ); + text: | + There shall be no ${../glossary/postponedjob:/plural} + after the return of the ${../if/cancel:/name} call. + - name: One + test-code: | + T_eq_u32( ctx->period_status.postponed_jobs_count, 1 ); + text: | + The number of ${../glossary/postponedjob:/plural} shall not be + changed by the past call to ${../if/cancel:/name}. + - name: Several + test-code: | + T_eq_u32( + ctx->period_status.postponed_jobs_count, + ctx->postponed_jobs_count + ); + text: | + The number of ${../glossary/postponedjob:/plural} shall not be + changed by the past call to ${../if/cancel:/name}. + - name: Nop + test-code: | + T_eq_u32( ctx->period_status.postponed_jobs_count, + ctx->postponed_jobs_count ); + text: | + Objects referenced by the ${../if/cancel:/params[0]/name} + parameter in past calls to ${../if/cancel:/name} shall not be + accessed by the ${../if/cancel:/name} call (see also + ${../glossary/nop:/term}). + test-epilogue: null + test-prologue: null +- name: Scheduler + states: + - name: Called + test-code: | + /* Cannot be tested as the effect is unknown. */ + text: | + The last call of the ${../if/cancel:/name} function shall execute + the ``cancel_job`` ${../glossary/scheduleroperation:/term} of the + ${/glossary/scheduler-home:/term}. + - name: Nop + test-code: | + /* Cannot be tested as the effect is unknown. */ + text: | + The last call of the ${../if/cancel:/name} function shall not execute + any ${../glossary/scheduleroperation:/term}. + test-epilogue: null + test-prologue: null +pre-conditions: +- name: Id + states: + - name: Valid + test-code: | + ctx->id_param = ctx->period_id; + text: | + While the ${../if/cancel:/params[0]/name} parameter is valid. + - name: Invalid + test-code: | + ctx->id_param = RTEMS_ID_NONE; + text: | + While the ${../if/cancel:/params[0]/name} parameter is invalid. + test-epilogue: null + test-prologue: null +- name: Caller + states: + - name: OwnerTask + test-code: | + ctx->do_action = Action; + text: | + While the ${/glossary/task:/term} invoking ${../if/cancel:/name} is + the ${/glossary/task:/term} which created the period - + the ${../glossary/ownertask:/term}. + - name: OtherTask + test-code: | + ctx->do_action = WorkerTaskAction; + text: | + While the ${/glossary/task:/term} invoking ${../if/cancel:/name} is not + the ${../glossary/ownertask:/term}. + test-epilogue: null + test-prologue: null +- name: State + states: + - name: Inactive + test-code: | + /* Nothing to do here as the period is newly created. */ + ctx->previous_state = RATE_MONOTONIC_INACTIVE; + text: | + While the ${../if/cancel:/params[0]/name} parameter references an + period object in ${../glossary/inactive:/term} + ${../glossary/state:/term}. + - name: Active + test-code: | + rtems_status_code status; + status = rtems_rate_monotonic_period( ctx->period_id, period_length ); + T_rsc_success( status ); + ctx->previous_state = RATE_MONOTONIC_ACTIVE; + text: | + While the ${../if/cancel:/params[0]/name} parameter references an + period object in ${../glossary/active:/term} ${../glossary/state:/term}. + - name: Expired + test-code: | + rtems_status_code status; + status = rtems_rate_monotonic_period( ctx->period_id, period_length ); + T_rsc_success( status ); + ctx->previous_state = RATE_MONOTONIC_EXPIRED; + text: | + While the ${../if/cancel:/params[0]/name} parameter references an + period object in ${../glossary/expired:/term} + ${../glossary/state:/term}. + test-epilogue: null + test-prologue: null +- name: Postponed + states: + - name: Zero + test-code: | + ctx->postponed_jobs_count = 0; + text: | + While the period is not in ${../glossary/expired:/term} + ${../glossary/state:/term}. + - name: One + test-code: | + CreatePostponedJobs( ctx, 1 ); + text: | + While there is one ${../glossary/postponedjob:/term}. + - name: Several + test-code: | + CreatePostponedJobs( ctx, 5 ); + text: | + While there are two or more ${../glossary/postponedjob:/plural}. + test-epilogue: null + test-prologue: null +rationale: null +references: [] +requirement-type: functional +skip-reasons: + NotInInactiveState: | + ${../glossary/postponedjob:/plural} do not exist in + ${../glossary/inactive:/term} ${../glossary/state:/term}. + NeverInExpiredState: | + There must be ${../glossary/postponedjob:/plural} in + ${../glossary/expired:/term} ${../glossary/state:/term}. +test-action: | + rtems_status_code status; + + ctx->do_action( ctx ); + + status = rtems_rate_monotonic_get_status( + ctx->period_id, + &ctx->period_status + ); + T_rsc_success( status ); +test-brief: null +test-cleanup: | + T_rsc_success( rtems_rate_monotonic_delete( ctx->period_id ) ); +test-context: +- brief: | + This member contains a valid identifier of a period. + description: null + member: | + rtems_id period_id +- brief: | + This member is used to receive the ${../if/period-status:/name} + after the action. + description: null + member: | + rtems_rate_monotonic_period_status period_status +- brief: | + This member specifies the ${../if/cancel:/params[0]/name} parameter + for the action. + description: null + member: | + rtems_id id_param +- brief: | + This member contains the returned ${/glossary/statuscode:/term} + of the action. + description: null + member: | + rtems_status_code status +- brief: | + This member contains the pointer to the function which executes the action. + description: | + The action is either executed by the ${../glossary/ownertask:/term} + or by the worker ${/glossary/task:/term} depending on the function pointer + used here. ``argument`` is a pointer to this context structure. + member: | + void ( *do_action )( void *ctx ) +- brief: | + This member contains the ${/glossary/task:/term} identifier of the + ${../glossary/ownertask:/term}. + description: null + member: | + rtems_id task_id +- brief: | + This member contains the ${/glossary/task:/term} identifier of the + worker ${/glossary/task:/term} (which is not the + ${../glossary/ownertask:/term}). + description: null + member: | + rtems_id worker_id +- brief: | + This member contains a backup of the ${/glossary/priority-task:/term} + before the execution of this test. + description: null + member: | + rtems_id original_priority +- brief: | + This member contains the number of ${../glossary/postponedjob:/plural} + before the action. + description: null + member: | + uint32_t postponed_jobs_count +- brief: | + This member contains the ${../glossary/state:/term} + before the action. + description: null + member: | + rtems_rate_monotonic_period_states previous_state +test-context-support: null +test-description: null +test-header: null +test-includes: +- rtems.h +test-local-includes: +- tx-support.h +test-prepare: | + rtems_status_code status; + status = rtems_rate_monotonic_create( + rtems_build_name( 'R', 'M', 'O', 'N' ), + &ctx->period_id + ); + T_rsc_success( status ); + + ctx->postponed_jobs_count = 0; +test-setup: + brief: null + code: | + rtems_status_code status; + rtems_task_priority priority; + rtems_event_set event_set; + ctx->worker_id = RTEMS_INVALID_ID; + + status = rtems_task_ident( + RTEMS_SELF, + RTEMS_SEARCH_ALL_NODES, + &ctx->task_id + ); + T_rsc_success( status ); + + status = rtems_task_set_priority( + RTEMS_SELF, + RTEMS_CURRENT_PRIORITY, + &ctx->original_priority + ); + T_rsc_success( status ); + + status = rtems_task_set_priority( + RTEMS_SELF, + background_task_priority, + &priority + ); + T_rsc_success( status ); + + status = rtems_task_create( + rtems_build_name( 'W', 'O', 'R', 'K' ), + foreground_task_priority, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &ctx->worker_id + ); + T_rsc_success( status ); + + /* Defensive programming: clean away any pending events */ + status = rtems_event_receive( + RTEMS_ALL_EVENTS, + RTEMS_NO_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &event_set + ); + T_true( status == RTEMS_SUCCESSFUL || status == RTEMS_UNSATISFIED ); + + status = rtems_task_start( + ctx->worker_id, + WorkerTask, + (rtems_task_argument) NULL + ); + T_rsc_success( status ); + description: null +test-stop: null +test-support: | + static const rtems_interval period_length = 5; + static const rtems_task_priority background_task_priority = 100; + static const rtems_task_priority foreground_task_priority = 10; + static const rtems_event_set wake_main_task_event = RTEMS_EVENT_17; + + static void TickTheClock( + RtemsRatemonReqCancel_Context *ctx, + uint32_t ticks + ) + { + uint32_t i; + for ( i = 0; i < ticks; ++i ) { + TimecounterTick(); + } + } + + static void Action( void *ctx_in ) + { + RtemsRatemonReqCancel_Context *ctx = ctx_in; + ctx->status = rtems_rate_monotonic_cancel( ctx->id_param ); + } + + RTEMS_INLINE_ROUTINE void WorkerTask( unsigned int argument ) + { + RtemsRatemonReqCancel_Context *ctx = + (RtemsRatemonReqCancel_Context *) argument; + + if ( ctx != NULL ) { + Action( ctx ); + T_rsc_success( rtems_event_send( ctx->task_id, wake_main_task_event ) ); + } + + T_rsc_success( rtems_task_suspend( RTEMS_SELF ) ); + } + + RTEMS_INLINE_ROUTINE void WorkerTaskAction( void *ctx_in ) + { + rtems_status_code status; + rtems_event_set event_set; + RtemsRatemonReqCancel_Context *ctx = ctx_in; + + status = rtems_task_restart( ctx->worker_id, (rtems_task_argument) ctx ); + T_rsc_success( status ); + + /* Wait till the worker task finishes */ + status = rtems_event_receive( + wake_main_task_event, + RTEMS_DEFAULT_OPTIONS, + RTEMS_NO_TIMEOUT, + &event_set + ); + T_rsc_success( status ); + } + + static void CreatePostponedJobs( + RtemsRatemonReqCancel_Context *ctx, + uint32_t jobs_count + ) + { + rtems_status_code status; + ctx->postponed_jobs_count = jobs_count; + if ( ctx->previous_state == RATE_MONOTONIC_ACTIVE ) { + TickTheClock( ctx, ( jobs_count + 1 ) * period_length ); + status = rtems_rate_monotonic_period( ctx->period_id, period_length ); + T_rsc( status, RTEMS_TIMEOUT ); + } else { + /* ctx->previous_state == RATE_MONOTONIC_INACTIVE || _EXPIRED */ + TickTheClock( ctx, jobs_count * period_length ); + } + } +test-target: testsuites/validation/tc-ratemon-cancel.c +test-teardown: + brief: null + code: | + rtems_status_code status; + rtems_task_priority priority; + + T_rsc_success( rtems_task_delete( ctx->worker_id ) ); + + status = rtems_task_set_priority( + RTEMS_SELF, + ctx->original_priority, + &priority + ); + T_rsc_success( status ); + description: null +text: ${.:text-template} +transition-map: +- enabled-by: true + post-conditions: + Status: Ok + State: Inactive + Postponed: N/A + Scheduler: Called + pre-conditions: + Id: + - Valid + Caller: + - OwnerTask + State: + - Inactive + Postponed: N/A +- enabled-by: true + post-conditions: + Status: Ok + State: Inactive + Postponed: + - specified-by: Postponed + Scheduler: Called + pre-conditions: + Id: + - Valid + Caller: + - OwnerTask + State: + - Active + - Expired + Postponed: all +- enabled-by: true + post-conditions: + Status: InvId + State: Nop + Postponed: Nop + Scheduler: Nop + pre-conditions: + Id: + - Invalid + Caller: all + State: + - Inactive + Postponed: N/A +- enabled-by: true + post-conditions: + Status: InvId + State: Nop + Postponed: Nop + Scheduler: Nop + pre-conditions: + Id: + - Invalid + Caller: all + State: + - Active + - Expired + Postponed: all +- enabled-by: true + post-conditions: + Status: NotOwn + State: Nop + Postponed: Nop + Scheduler: Nop + pre-conditions: + Id: + - Valid + Caller: + - OtherTask + State: + - Inactive + Postponed: N/A +- enabled-by: true + post-conditions: + Status: NotOwn + State: Nop + Postponed: Nop + Scheduler: Nop + pre-conditions: + Id: + - Valid + Caller: + - OtherTask + State: + - Active + - Expired + Postponed: all +- enabled-by: true + post-conditions: NotInInactiveState + pre-conditions: + Id: all + Caller: all + State: + - Inactive + Postponed: + - One + - Several +- enabled-by: true + post-conditions: NeverInExpiredState + pre-conditions: + Id: all + Caller: all + State: + - Expired + Postponed: + - Zero +type: requirement |