SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause copyrights: - Copyright (C) 2020, 2021 embedded brains GmbH (http://www.embedded-brains.de) enabled-by: true functional-type: action links: - role: interface-function uid: ../if/construct post-conditions: - name: Status states: - name: Ok test-code: | T_rsc_success( ctx->status ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/successful:/name}. - name: InvAddr test-code: | T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/invalid-address:/name}. - name: InvName test-code: | T_rsc( ctx->status, RTEMS_INVALID_NAME ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/invalid-name:/name}. - name: InvPrio test-code: | T_rsc( ctx->status, RTEMS_INVALID_PRIORITY ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/invalid-priority:/name}. - name: InvSize test-code: | T_rsc( ctx->status, RTEMS_INVALID_SIZE ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/invalid-size:/name}. - name: TooMany test-code: | T_rsc( ctx->status, RTEMS_TOO_MANY ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/too-many:/name}. - name: Unsat test-code: | T_rsc( ctx->status, RTEMS_UNSATISFIED ); text: | The return status of ${../if/construct:/name} shall be ${../../status/if/unsatisfied:/name}. test-epilogue: null test-prologue: null - name: Name states: - name: Valid test-code: | id = 0; sc = rtems_task_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); T_rsc_success( sc ); T_eq_u32( id, ctx->id_value ); text: | The unique object name shall identify the task constructed by the ${../if/construct:/name} call. - name: Invalid test-code: | sc = rtems_task_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); T_rsc( sc, RTEMS_INVALID_NAME ); text: | The unique object name shall not identify a task. test-epilogue: null test-prologue: | rtems_status_code sc; rtems_id id; - name: IdVar states: - name: Set test-code: | T_eq_ptr( ctx->id, &ctx->id_value ); T_ne_u32( ctx->id_value, INVALID_ID ); text: | The value of the object referenced by the ${../if/construct:/params[1]/name} parameter shall be set to the object identifier of the constructed task after the return of the ${../if/construct:/name} call. - name: Nop test-code: | T_eq_u32( ctx->id_value, INVALID_ID ); text: | Objects referenced by the ${../if/construct:/params[1]/name} parameter in past calls to ${../if/construct:/name} shall not be accessed by the ${../if/construct:/name} call. test-epilogue: null test-prologue: null - name: CreateExt states: - name: All test-code: | T_eq_u32( ctx->create_extension_calls, 2 ); text: | The create user extensions shall be invoked during the ${../if/construct:/name} call. - name: UpToFailing test-code: | T_eq_u32( ctx->create_extension_calls, 1 ); text: | The create user extensions up to the failing extension shall be invoked during the ${../if/construct:/name} call. - name: 'No' test-code: | T_eq_u32( ctx->create_extension_calls, 0 ); text: | The create user extensions shall not be invoked during the ${../if/construct:/name} call. test-epilogue: null test-prologue: null - name: DelExt states: - name: 'Yes' test-code: | T_eq_u32( ctx->delete_extension_calls, 2 ); text: | The delete user extensions shall be invoked during the ${../if/construct:/name} call. - name: 'No' test-code: | T_eq_u32( ctx->delete_extension_calls, 0 ); text: | The delete user extensions shall not be invoked during the ${../if/construct:/name} call. test-epilogue: null test-prologue: null - name: StoFree states: - name: 'Yes' test-code: | T_eq_u32( ctx->storage_free_calls, 1 ); text: | The storage free handler of the task configuration shall be invoked during the ${../if/construct:/name} call. - name: 'No' test-code: | T_eq_u32( ctx->storage_free_calls, 0 ); text: | The storage free handler of the task configuration shall not be invoked during the ${../if/construct:/name} call. test-epilogue: null test-prologue: null pre-conditions: - name: Config states: - name: Valid test-code: | ctx->config = &ctx->config_value; text: | While the ${../if/construct:/params[0]/name} parameter references an object of type ${../if/config:/name}. - name: 'Null' test-code: | ctx->config = NULL; text: | While the ${../if/construct:/params[0]/name} parameter is ${/c/if/null:/name}. test-epilogue: null test-prologue: null - name: Name states: - name: Valid test-code: | ctx->config_value.name = NAME; text: | While the name of the task configuration is valid. - name: Inv test-code: | ctx->config_value.name = 0; text: | While the name of the task configuration is invalid. test-epilogue: null test-prologue: null - name: Id states: - name: Valid test-code: | ctx->id = &ctx->id_value; text: | While the ${../if/construct:/params[1]/name} parameter references an object of type ${../../type/if/id:/name}. - name: 'Null' test-code: | ctx->id = NULL; text: | While the ${../if/construct:/params[1]/name} parameter is ${/c/if/null:/name}. test-epilogue: null test-prologue: null - name: SysTsk states: - name: 'Yes' test-code: | ctx->config_value.attributes |= RTEMS_SYSTEM_TASK; text: | While the attributes of the task configuration specifies a system task. - name: 'No' test-code: | /* Nothing to do */ text: | While the attributes of the task configuration specifies an application task. test-epilogue: null test-prologue: null - name: Prio states: - name: Valid test-code: | ctx->config_value.initial_priority = 254; text: | While the initial priority of the task configuration is valid and non-zero. - name: Zero test-code: | ctx->config_value.initial_priority = 0; text: | While the initial priority of the task configuration is zero. - name: Inv test-code: | ctx->config_value.initial_priority = 0xffffffff; text: | While the initial priority of the task configuration is invalid. test-epilogue: null test-prologue: null - name: Free states: - name: 'Yes' test-code: | /* Nothing to do */ text: | While the system has at least one inactive task object available. - name: 'No' test-code: | ctx->seized_objects = T_seize_objects( Create, ctx ); text: | While the system has no inactive task object available. test-epilogue: null test-prologue: null - name: TLS states: - name: Enough test-code: | ctx->config_value.maximum_thread_local_storage_size = MAX_TLS_SIZE; text: | While the maximum thread-local storage size of the task configuration is greater than or equal to the thread-local storage size. - name: Small test-code: | ctx->config_value.maximum_thread_local_storage_size = 0; text: | While the maximum thread-local storage size of the task configuration is less than the thread-local storage size. test-epilogue: null test-prologue: null - name: Stack states: - name: Enough test-code: | ctx->stack_size = RTEMS_MINIMUM_STACK_SIZE; text: | While the task stack size of the task configuration is greater than or equal to the configured minimum size. - name: Small test-code: | ctx->stack_size = 0; text: | While the task stack size of the task configuration is less than the configured minimum size. test-epilogue: null test-prologue: null - name: Ext states: - name: Ok test-code: | ctx->create_extension_status = true; text: | While none of the task create extensions fails. - name: Err test-code: | ctx->create_extension_status = false; text: | While at least one of the task create extensions fails. test-epilogue: null test-prologue: null rationale: null references: [] requirement-type: functional skip-reasons: {} test-action: | ctx->create_extension_calls = 0; ctx->delete_extension_calls = 0; ctx->storage_free_calls = 0; ctx->config_value.storage_size = RTEMS_TASK_STORAGE_SIZE( ctx->config_value.maximum_thread_local_storage_size + ctx->stack_size, ctx->config_value.attributes ); ctx->status = rtems_task_construct( ctx->config, ctx->id ); test-brief: null test-cleanup: | if ( ctx->id_value != INVALID_ID ) { rtems_status_code sc; sc = rtems_task_delete( ctx->id_value ); T_rsc_success( sc ); ctx->id_value = INVALID_ID; } T_surrender_objects( &ctx->seized_objects, rtems_task_delete ); test-context: - brief: null description: null member: | rtems_status_code status - brief: null description: null member: | const rtems_task_config *config - brief: null description: null member: | rtems_task_config config_value - brief: null description: null member: | rtems_id *id - brief: null description: null member: | rtems_id id_value - brief: null description: null member: | bool create_extension_status - brief: null description: null member: | uint32_t create_extension_calls - brief: null description: null member: | uint32_t delete_extension_calls - brief: null description: null member: | uint32_t storage_free_calls - brief: null description: null member: | size_t stack_size - brief: null description: null member: | rtems_id extension_ids[ 2 ] - brief: null description: null member: | void *seized_objects test-context-support: null test-description: null test-header: null test-includes: - rtems.h - string.h - rtems/score/apimutex.h - rtems/score/threadimpl.h test-local-includes: - tx-support.h test-prepare: | _RTEMS_Lock_allocator(); _Thread_Kill_zombies(); _RTEMS_Unlock_allocator(); ctx->id_value = INVALID_ID; memset( &ctx->config_value, 0, sizeof( ctx->config_value ) ); ctx->config_value.storage_area = task_storage, ctx->config_value.storage_free = StorageFree; test-setup: brief: null code: | rtems_status_code sc; int var; var = tls_variable; RTEMS_OBFUSCATE_VARIABLE( var ); tls_variable = var; sc = rtems_extension_create( rtems_build_name( 'E', 'X', 'T', '1' ), &extensions[ 0 ], &ctx->extension_ids[ 0 ] ); T_rsc_success( sc ); sc = rtems_extension_create( rtems_build_name( 'E', 'X', 'T', '2' ), &extensions[ 1 ], &ctx->extension_ids[ 1 ] ); T_rsc_success( sc ); description: null test-stop: null test-support: | #define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) typedef RtemsTaskReqConstructErrors_Context Context; static _Thread_local int tls_variable; #define MAX_TLS_SIZE RTEMS_ALIGN_UP( 128, RTEMS_TASK_STORAGE_ALIGNMENT ) RTEMS_ALIGNED( RTEMS_TASK_STORAGE_ALIGNMENT ) static char task_storage[ RTEMS_TASK_STORAGE_SIZE( MAX_TLS_SIZE + RTEMS_MINIMUM_STACK_SIZE, RTEMS_FLOATING_POINT ) ]; static const rtems_task_config seize_task_config = { .name = rtems_build_name( 'S', 'I', 'Z', 'E' ), .initial_priority = 1, .storage_area = task_storage, .storage_size = sizeof( task_storage ), .maximum_thread_local_storage_size = MAX_TLS_SIZE, .initial_modes = RTEMS_DEFAULT_MODES, .attributes = RTEMS_DEFAULT_MODES }; static void StorageFree( void *ptr ) { T_eq_ptr( ptr, task_storage ); ++RtemsTaskReqConstructErrors_Instance.storage_free_calls; } static rtems_status_code Create( void *arg, uint32_t *id ) { Context *ctx; bool create_extension_status; rtems_status_code sc; ctx = arg; create_extension_status = ctx->create_extension_status; ctx->create_extension_status = true; sc = rtems_task_construct( &seize_task_config, id ); ctx->create_extension_status = create_extension_status; return sc; } static bool ThreadCreate( rtems_tcb *executing, rtems_tcb *created ) { (void) executing; (void) created; ++RtemsTaskReqConstructErrors_Instance.create_extension_calls; return RtemsTaskReqConstructErrors_Instance.create_extension_status; } static bool SecondThreadCreate( rtems_tcb *executing, rtems_tcb *created ) { (void) executing; (void) created; ++RtemsTaskReqConstructErrors_Instance.create_extension_calls; return true; } static void ThreadDelete( rtems_tcb *executing, rtems_tcb *deleted ) { (void) executing; (void) deleted; ++RtemsTaskReqConstructErrors_Instance.delete_extension_calls; } static const rtems_extensions_table extensions[] = { { .thread_create = ThreadCreate, .thread_delete = ThreadDelete }, { .thread_create = SecondThreadCreate, .thread_delete = ThreadDelete } }; test-target: testsuites/validation/tc-task-construct-errors.c test-teardown: brief: null code: | rtems_status_code sc; sc = rtems_extension_delete( ctx->extension_ids[ 0 ] ); T_rsc_success( sc ); sc = rtems_extension_delete( ctx->extension_ids[ 1 ] ); T_rsc_success( sc ); description: null text: ${.:text-template} transition-map: - enabled-by: true post-conditions: Status: - if: pre-conditions: Config: 'Null' then: InvAddr - if: pre-conditions: Name: Inv then: InvName - if: pre-conditions: Id: 'Null' then: InvAddr - if: pre-conditions: Prio: Zero SysTsk: 'No' then: InvPrio - if: pre-conditions: Prio: Inv then: InvPrio - if: pre-conditions: Free: 'No' then: TooMany - if: pre-conditions: TLS: Small then: InvSize - if: pre-conditions: Stack: Small then: InvSize - if: pre-conditions: Ext: Err then: Unsat - else: Ok Name: - if: post-conditions: Status: Ok then: Valid - else: Invalid IdVar: - if: post-conditions: Status: Ok then: Set - else: Nop CreateExt: - if: post-conditions: Status: Ok then: All - if: post-conditions: Status: Unsat then: UpToFailing - else: 'No' DelExt: - if: post-conditions: Status: Unsat then: 'Yes' - else: 'No' StoFree: - if: post-conditions: Status: Unsat then: 'Yes' - else: 'No' pre-conditions: Config: all Ext: all Id: all Name: all SysTsk: all Prio: all Stack: all TLS: all Free: all type: requirement