SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause copyrights: - Copyright (C) 2021 embedded brains GmbH & Co. KG enabled-by: true functional-type: action links: - role: interface-function uid: ../if/entry-remove post-conditions: - name: Status states: - name: Ok test-code: | T_rsc_success( ctx->status ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/successful:/name}. - name: InvAddr test-code: | T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/invalid-address:/name}. - name: IncStat test-code: | T_rsc( ctx->status, RTEMS_INCORRECT_STATE ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/incorrect-state:/name}. - name: InvId test-code: | T_rsc( ctx->status, RTEMS_INVALID_ID ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/invalid-id:/name}. - name: CalledFromISR test-code: | T_rsc( ctx->status, RTEMS_CALLED_FROM_ISR ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/called-from-isr:/name}. - name: Unsat test-code: | T_rsc( ctx->status, RTEMS_UNSATISFIED ); text: | The return status of ${../if/entry-remove:/name} shall be ${../../status/if/unsatisfied:/name}. test-epilogue: null test-prologue: null - name: Disabled states: - name: Nop test-code: | if ( !ctx->interrupt_occurred ) { T_eq( ctx->enabled_before, ctx->enabled_after ); } text: | The enabled status of the interrupt vector specified by ${../if/entry-remove:/params[0]/name} shall not be modified by the ${../if/entry-remove:/name} call. - name: 'Yes' test-code: | if ( ctx->attributes.can_disable ) { T_false( ctx->enabled_after ); } text: | The interrupt vector specified by ${../if/entry-remove:/params[0]/name} shall be disabled. - name: Maybe test-code: | /* The comment of pre-condition ``CanDisable`` for the ``Yes`` state. */ if ( ctx->attributes.can_disable ) { T_false( ctx->enabled_after ); } text: | The interrupt vector specified by ${../if/entry-remove:/params[0]/name} may be disabled. - name: 'No' test-code: | /* The comment of pre-condition ``CanDisable`` for the ``Yes`` state. */ if ( ctx->attributes.can_disable ) { T_false( ctx->enabled_after ); } text: | The interrupt vector specified by ${../if/entry-remove:/params[0]/name} shall not be disabled. test-epilogue: null test-prologue: null - name: Installed states: - name: 'No' test-code: | ctx->visited_entries = 0; sc = rtems_interrupt_handler_iterate( ctx->test_vector, VisitInstalledNo, ctx ); T_rsc_success( sc ); if ( ctx->other_installed && ctx->third_installed ) { expected_entries = 2; } else if ( ctx->other_installed ) { expected_entries = 1; } else { expected_entries = 0; } T_eq_u32( ctx->visited_entries, expected_entries ); if ( expected_entries > 0 ) { ctx->entry_counter = 0; bsp_interrupt_handler_dispatch_unchecked( ctx->test_vector ); T_eq_u32( ctx->entry_counter, 0 ); } else { rtems_interrupt_entry *first; first = bsp_interrupt_dispatch_table[ bsp_interrupt_dispatch_index( ctx->test_vector ) ]; T_null( first ); } text: | The entry referenced by ${../if/entry-remove:/params[1]/name} shall not be installed at the interrupt vector specified by ${../if/entry-remove:/params[0]/name}. - name: Nop test-code: | ctx->visited_entries = 0; sc = rtems_interrupt_handler_iterate( ctx->test_vector, VisitInstalledNop, ctx ); T_rsc_success( sc ); if ( ctx->installed && ctx->other_installed && ctx->third_installed ) { expected_entries = 3; } else if ( ctx->installed && ctx->other_installed ) { expected_entries = 2; } else if ( ctx->installed || ctx->other_installed ) { expected_entries = 1; } else { expected_entries = 0; } T_eq_u32( ctx->visited_entries, expected_entries ); if ( ctx->installed ) { ctx->entry_counter = 0; bsp_interrupt_handler_dispatch_unchecked( ctx->test_vector ); T_eq_u32( ctx->entry_counter, 1 ); } text: | The entries installed at the interrupt vector specified by ${../if/entry-remove:/params[0]/name} shall not be modified by the ${../if/entry-remove:/name} call. test-epilogue: null test-prologue: | rtems_status_code sc; uint32_t expected_entries; pre-conditions: - name: Vector states: - name: Valid test-code: | ctx->vector = ctx->test_vector; text: | While the ${../if/entry-remove:/params[0]/name} parameter is associated with an interrupt vector. - name: Invalid test-code: | ctx->vector = BSP_INTERRUPT_VECTOR_COUNT; text: | While the ${../if/entry-remove:/params[0]/name} parameter is not associated with an interrupt vector. test-epilogue: null test-prologue: null - name: Entry states: - name: Obj test-code: | ctx->entry = &ctx->entry_obj; text: | While the ${../if/entry-remove:/params[1]/name} parameter references an object of type ${../if/entry:/name}. - name: 'Null' test-code: | ctx->entry = NULL; text: | While the ${../if/entry-remove:/params[1]/name} parameter is equal to ${/c/if/null:/name}. test-epilogue: null test-prologue: null - name: Routine states: - name: Valid test-code: | rtems_interrupt_entry_initialize( &ctx->entry_obj, EntryRoutine, &entry_arg, info ); text: | While the handler routine of the entry referenced by the ${../if/entry-install:/params[1]/name} parameter is valid. - name: 'Null' test-code: | rtems_interrupt_entry_initialize( &ctx->entry_obj, NULL, &entry_arg, info ); text: | While the handler routine of the entry referenced by the ${../if/entry-install:/params[1]/name} parameter is equal to ${/c/if/null:/name}. test-epilogue: null test-prologue: null - name: EntryObj states: - name: Installed test-code: | ctx->installed = true; text: | While the entry referenced by the ${../if/entry-install:/params[1]/name} parameter is installed at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. - name: Match test-code: | ctx->installed = false; ctx->other_installed = true; ctx->match = true; text: | While the entry referenced by the ${../if/entry-install:/params[1]/name} parameter not installed at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter, while the entry referenced by the ${../if/entry-install:/params[1]/name} has a handler routine and argument pair which is equal to the handler routine and argument pair of an entry installed at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. - name: NoMatch test-code: | ctx->installed = false; ctx->other_installed = true; ctx->match = false; text: | While the entry referenced by the ${../if/entry-install:/params[1]/name} parameter not installed at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter, while the entry referenced by the ${../if/entry-install:/params[1]/name} has a handler routine and argument pair which is not equal to the handler routine and argument pairs of all entries installed at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. test-epilogue: null test-prologue: null - name: Init states: - name: 'Yes' test-code: | ctx->initialized = true; text: | While the service is initialized. - name: 'No' test-code: | ctx->initialized = false; text: | While the service is not initialized. test-epilogue: null test-prologue: null - name: ISR states: - name: 'Yes' test-code: | ctx->isr = true; text: | While ${../if/entry-remove:/name} is called from within interrupt context. - name: 'No' test-code: | ctx->isr = false; text: | While ${../if/entry-remove:/name} is not called from within interrupt context. test-epilogue: null test-prologue: null - name: CanDisable states: - name: 'Yes' test-code: | /* * This pre-condition depends on the attributes of an interrupt vector. * For the validation test of ${../if/entry-remove:/name} a testable * interrupt vector is determined by GetTestableInterruptVector(). The * implementation of ${../if/entry-remove:/name} uses * ${../if/vector-disable:/name} which is validated separately in detail. */ text: | While the interrupt vector associated with the ${../if/entry-remove:/params[0]/name} parameter can be disabled. - name: Maybe test-code: | /* See comment for ``Yes`` state */ text: | While the interrupt vector associated with the ${../if/entry-remove:/params[0]/name} parameter may be disabled. - name: 'No' test-code: | /* See comment for ``Yes`` state */ text: | While the interrupt vector associated with the ${../if/entry-remove:/params[0]/name} parameter cannot be disabled. test-epilogue: null test-prologue: null - name: First states: - name: 'Yes' test-code: | ctx->first = true; text: | While the entry referenced by the ${../if/entry-remove:/params[1]/name} parameter is installed as the first entry at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. - name: 'No' test-code: | ctx->first = false; text: | While the entry referenced by the ${../if/entry-remove:/params[1]/name} parameter is installed as not the first entry at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. test-epilogue: null test-prologue: null - name: Last states: - name: 'Yes' test-code: | ctx->last = true; text: | While the entry referenced by the ${../if/entry-remove:/params[1]/name} parameter is installed as the last entry at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. - name: 'No' test-code: | ctx->last = false; text: | While the entry referenced by the ${../if/entry-remove:/params[1]/name} parameter is installed as not the last entry at the interrupt vector specified by the ${../if/entry-remove:/params[0]/name} parameter. test-epilogue: null test-prologue: null rationale: null references: [] requirement-type: functional skip-reasons: {} test-action: | if ( ctx->installed ) { ctx->entry = &ctx->entry_obj; if ( ctx->first && ctx->last ) { Install( ctx, &ctx->entry_obj, EntryRoutine, &entry_arg ); } else if ( ctx->first ) { ctx->other_installed = true; Install( ctx, &ctx->entry_obj, EntryRoutine, &entry_arg ); Install( ctx, &ctx->other_entry, OtherRoutine, &other_arg ); } else if ( ctx->last ) { ctx->other_installed = true; Install( ctx, &ctx->other_entry, OtherRoutine, &other_arg ); Install( ctx, &ctx->entry_obj, EntryRoutine, &entry_arg ); } else { ctx->other_installed = true; ctx->third_installed = true; Install( ctx, &ctx->other_entry, OtherRoutine, &other_arg ); Install( ctx, &ctx->entry_obj, EntryRoutine, &entry_arg ); Install( ctx, &ctx->third_entry, ThirdRoutine, &third_arg ); } } else if ( ctx->other_installed ) { ctx->entry = &ctx->entry_obj; if ( ctx->match ) { Install( ctx, &ctx->other_entry, EntryRoutine, &entry_arg ); } else { Install( ctx, &ctx->other_entry, OtherRoutine, &other_arg ); } } if ( ctx->isr ) { CallWithinISR( Action, ctx ); } else { Action( ctx ); } test-brief: null test-cleanup: | rtems_status_code sc; if ( ctx->third_installed ) { sc = rtems_interrupt_entry_remove( ctx->test_vector, &ctx->third_entry ); T_rsc_success( sc ); } if ( ctx->other_installed ) { sc = rtems_interrupt_entry_remove( ctx->test_vector, &ctx->other_entry ); T_rsc_success( sc ); } if ( ctx->installed && ctx->status != RTEMS_SUCCESSFUL ) { sc = rtems_interrupt_entry_remove( ctx->test_vector, ctx->entry ); T_rsc_success( sc ); } test-context: - brief: | If this member is true, then the service was initialized during setup. description: null member: | bool initialized_during_setup - brief: | If this member is true, then an interrupt occurred. description: null member: | bool interrupt_occurred - brief: | This member provides a counter incremented by EntryRoutine(). description: null member: | uint32_t entry_counter; - brief: | This member provides another ${../if/entry:/name} object. description: null member: | rtems_interrupt_entry other_entry - brief: | If this member is true, then another entry was installed. description: null member: | bool other_installed - brief: | This member provides a third ${../if/entry:/name} object. description: null member: | rtems_interrupt_entry third_entry - brief: | If this member is true, then a third entry was installed. description: null member: | bool third_installed - brief: | If this member is true, then the entry is installed. description: null member: | bool installed - brief: | If this member is true, then the entry is installed as the first entry. description: null member: | bool first - brief: | If this member is true, then the entry is installed as the last entry. description: null member: | bool last - brief: | If this member is true, then the entry matches with another installed entry. description: null member: | bool match - brief: | This member provides the vector number of a testable interrupt vector. description: null member: | rtems_vector_number test_vector - brief: | If this member is true, then the testable interrupt vector was enabled at the test case begin. description: null member: | bool test_vector_was_enabled - brief: | This member provides the attributes of the testable interrupt vector. description: null member: | rtems_interrupt_attributes attributes - brief: | If this member is true, then the service shall be initialized. description: null member: | bool initialized - brief: | If this member is true, then ${../if/entry-remove:/name} shall be called from within interrupt context. description: null member: | bool isr - brief: | This member contains the enabled status before the ${../if/entry-remove:/name} call. description: null member: | bool enabled_before - brief: | This member contains the enabled status after the ${../if/entry-remove:/name} call. description: null member: | bool enabled_after - brief: | This member provides the count of visited entries. description: null member: | uint32_t visited_entries - brief: | This member provides the ${../if/entry:/name} object. description: null member: | rtems_interrupt_entry entry_obj - brief: | This member specifies if the ${../if/entry-remove:/params[0]/name} parameter value. description: null member: | rtems_vector_number vector - brief: | This member specifies if the ${../if/entry-remove:/params[1]/name} parameter value. description: null member: | rtems_interrupt_entry *entry; - brief: | This member contains the return value of the ${../if/entry-remove:/name} call. description: null member: | rtems_status_code status test-context-support: null test-description: null test-header: null test-includes: - rtems/irq-extension.h - bsp/irq-generic.h test-local-includes: - tx-support.h test-prepare: | ctx->interrupt_occurred = false; ctx->installed = false; ctx->other_installed = false; ctx->third_installed = false; test-setup: brief: null code: | rtems_status_code sc; ctx->initialized_during_setup = bsp_interrupt_is_initialized(); ctx->test_vector = GetTestableInterruptVector( NULL ); ctx->test_vector_was_enabled = false; (void) rtems_interrupt_vector_is_enabled( ctx->test_vector, &ctx->test_vector_was_enabled ); sc = rtems_interrupt_get_attributes( ctx->test_vector, &ctx->attributes ); T_rsc_success( sc ); description: null test-stop: null test-support: | typedef ${.:/test-context-type} Context; static char entry_arg; static char other_arg; static char third_arg; static const char info[] = "Info"; static void Install( Context *ctx, rtems_interrupt_entry *entry, rtems_interrupt_handler routine, void *arg ) { rtems_status_code sc; rtems_interrupt_entry_initialize( entry, routine, arg, info ); sc = rtems_interrupt_entry_install( ctx->test_vector, RTEMS_INTERRUPT_SHARED, entry ); T_rsc_success( sc ); } static void OtherRoutine( void *arg ) { Context *ctx; rtems_status_code sc; (void) arg; ctx = T_fixture_context(); sc = rtems_interrupt_vector_disable( ctx->test_vector ); T_rsc_success( sc ); ctx->interrupt_occurred = true; } static void ThirdRoutine( void *arg ) { T_eq_ptr( arg, &third_arg ); OtherRoutine( NULL ); } static void EntryRoutine( void *arg ) { Context *ctx; ctx = T_fixture_context(); ++ctx->entry_counter; T_eq_ptr( arg, &entry_arg ); OtherRoutine( NULL ); } static void Action( void *arg ) { Context *ctx; rtems_status_code sc; ctx = arg; sc = rtems_interrupt_vector_is_enabled( ctx->test_vector, &ctx->enabled_before ); T_rsc_success( sc ); bsp_interrupt_set_handler_unique( BSP_INTERRUPT_DISPATCH_TABLE_SIZE, ctx->initialized ); ctx->status = rtems_interrupt_entry_remove( ctx->vector, ctx->entry ); bsp_interrupt_set_handler_unique( BSP_INTERRUPT_DISPATCH_TABLE_SIZE, ctx->initialized_during_setup ); sc = rtems_interrupt_vector_is_enabled( ctx->test_vector, &ctx->enabled_after ); T_rsc_success( sc ); } static void VisitInstalledNo( void *arg, const char *entry_info, rtems_option options, rtems_interrupt_handler handler_routine, void *handler_arg ) { Context *ctx; uint32_t visited_entries; ctx = arg; visited_entries = ctx->visited_entries; T_eq_u32( options, RTEMS_INTERRUPT_SHARED ); T_eq_ptr( entry_info, info ); if ( visited_entries == 0 ) { T_eq_ptr( handler_routine, ctx->other_entry.handler ); T_eq_ptr( handler_arg, ctx->other_entry.arg ); } else if ( visited_entries == 1 ) { T_eq_ptr( handler_routine, ctx->third_entry.handler ); T_eq_ptr( handler_arg, ctx->third_entry.arg ); } ctx->visited_entries = visited_entries + 1; } static void VisitInstalledNop( void *arg, const char *entry_info, rtems_option options, rtems_interrupt_handler handler_routine, void *handler_arg ) { Context *ctx; uint32_t visited_entries; ctx = arg; visited_entries = ctx->visited_entries; T_eq_u32( options, RTEMS_INTERRUPT_SHARED ); T_eq_ptr( entry_info, info ); if ( visited_entries == 0 ) { if ( ctx->installed && ctx->first ) { T_eq_ptr( handler_routine, ctx->entry_obj.handler ); T_eq_ptr( handler_arg, ctx->entry_obj.arg ); } else { T_eq_ptr( info, ctx->other_entry.info ); T_eq_ptr( handler_routine, ctx->other_entry.handler ); T_eq_ptr( handler_arg, ctx->other_entry.arg ); } } else if ( visited_entries == 1 ) { if ( ctx->installed && ( ( !ctx->first && ctx->last ) || ( !ctx->first && !ctx->last ) ) ) { T_eq_ptr( handler_routine, ctx->entry_obj.handler ); T_eq_ptr( handler_arg, ctx->entry_obj.arg ); } else { T_eq_ptr( handler_routine, ctx->other_entry.handler ); T_eq_ptr( handler_arg, ctx->other_entry.arg ); } } else if ( visited_entries == 2 ) { if ( ctx->installed && !ctx->first && ctx->last ) { T_eq_ptr( handler_routine, ctx->entry_obj.handler ); T_eq_ptr( handler_arg, ctx->entry_obj.arg ); } else { T_eq_ptr( handler_routine, ctx->third_entry.handler ); T_eq_ptr( handler_arg, ctx->third_entry.arg ); } } ctx->visited_entries = visited_entries + 1; } test-target: testsuites/validation/tc-intr-entry-remove.c test-teardown: brief: null code: | if ( ctx->test_vector_was_enabled ) { (void) rtems_interrupt_vector_enable( ctx->test_vector ); } description: null text: ${.:text-template} transition-map: - enabled-by: true post-conditions: Status: Ok Disabled: - if: pre-conditions: First: 'Yes' Last: 'Yes' then-specified-by: CanDisable - else: Nop Installed: 'No' pre-conditions: Vector: - Valid Entry: - Obj Routine: - Valid EntryObj: - Installed Init: - 'Yes' ISR: - 'No' CanDisable: all First: all Last: all - enabled-by: true post-conditions: Status: Unsat Disabled: Nop Installed: N/A pre-conditions: Vector: - Valid Entry: - Obj Routine: - Valid EntryObj: - Match - NoMatch Init: - 'Yes' ISR: - 'No' CanDisable: all First: N/A Last: N/A - enabled-by: true post-conditions: Status: InvAddr Disabled: Nop Installed: N/A pre-conditions: Vector: - Valid Entry: - 'Null' Routine: N/A EntryObj: N/A Init: all ISR: all CanDisable: all First: N/A Last: N/A - enabled-by: true post-conditions: Status: InvAddr Disabled: N/A Installed: N/A pre-conditions: Vector: - Invalid Entry: - 'Null' Routine: N/A EntryObj: N/A Init: all ISR: all CanDisable: N/A First: N/A Last: N/A - enabled-by: true post-conditions: Status: IncStat Disabled: Nop Installed: N/A pre-conditions: Vector: - Valid Entry: - Obj Routine: all EntryObj: N/A Init: - 'No' ISR: all CanDisable: all First: N/A Last: N/A - enabled-by: true post-conditions: Status: IncStat Disabled: N/A Installed: N/A pre-conditions: Vector: - Invalid Entry: - Obj Routine: all EntryObj: N/A Init: - 'No' ISR: all CanDisable: N/A First: N/A Last: N/A - enabled-by: true post-conditions: Status: InvAddr Disabled: Nop Installed: N/A pre-conditions: Vector: - Valid Entry: - Obj Routine: - 'Null' EntryObj: N/A Init: - 'Yes' ISR: all CanDisable: all First: N/A Last: N/A - enabled-by: true post-conditions: Status: InvAddr Disabled: N/A Installed: N/A pre-conditions: Vector: - Invalid Entry: - Obj Routine: - 'Null' EntryObj: N/A Init: - 'Yes' CanDisable: N/A ISR: all First: N/A Last: N/A - enabled-by: true post-conditions: Status: InvId Disabled: N/A Installed: N/A pre-conditions: Vector: - Invalid Entry: - Obj Routine: - Valid EntryObj: N/A Init: - 'Yes' ISR: all CanDisable: N/A First: N/A Last: N/A - enabled-by: true post-conditions: Status: CalledFromISR Disabled: Nop Installed: Nop pre-conditions: Vector: - Valid Entry: - Obj Routine: - Valid EntryObj: - Installed Init: - 'Yes' ISR: - 'Yes' CanDisable: all First: all Last: all - enabled-by: true post-conditions: Status: CalledFromISR Disabled: Nop Installed: N/A pre-conditions: Vector: - Valid Entry: - Obj Routine: - Valid EntryObj: - Match - NoMatch Init: - 'Yes' ISR: - 'Yes' CanDisable: all First: N/A Last: N/A type: requirement