From 182ce7fd17ff771c9065dff1bd3c1b92d91e2cc0 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 10 May 2021 08:31:43 +0200 Subject: validation: Add task manager tests --- spec/build/testsuites/validation/validation-0.yml | 13 + testsuites/validation/tc-task-construct-errors.c | 4 +- testsuites/validation/tc-task-create-errors.c | 4 +- testsuites/validation/tc-task-get-affinity.c | 492 +++++++ testsuites/validation/tc-task-get-priority.c | 579 ++++++++ testsuites/validation/tc-task-get-scheduler.c | 389 ++++++ testsuites/validation/tc-task-is-suspended.c | 390 ++++++ testsuites/validation/tc-task-restart.c | 719 ++++++++++ testsuites/validation/tc-task-resume.c | 378 ++++++ testsuites/validation/tc-task-set-affinity.c | 537 ++++++++ testsuites/validation/tc-task-set-priority.c | 550 ++++++++ testsuites/validation/tc-task-set-scheduler.c | 1454 +++++++++++++++++++++ testsuites/validation/tc-task-start.c | 822 ++++++++++++ testsuites/validation/tc-task-storage-size.c | 388 ++++++ testsuites/validation/tc-task-suspend.c | 378 ++++++ testsuites/validation/tc-task.c | 207 +++ 16 files changed, 7300 insertions(+), 4 deletions(-) create mode 100644 testsuites/validation/tc-task-get-affinity.c create mode 100644 testsuites/validation/tc-task-get-priority.c create mode 100644 testsuites/validation/tc-task-get-scheduler.c create mode 100644 testsuites/validation/tc-task-is-suspended.c create mode 100644 testsuites/validation/tc-task-restart.c create mode 100644 testsuites/validation/tc-task-resume.c create mode 100644 testsuites/validation/tc-task-set-affinity.c create mode 100644 testsuites/validation/tc-task-set-priority.c create mode 100644 testsuites/validation/tc-task-set-scheduler.c create mode 100644 testsuites/validation/tc-task-start.c create mode 100644 testsuites/validation/tc-task-storage-size.c create mode 100644 testsuites/validation/tc-task-suspend.c create mode 100644 testsuites/validation/tc-task.c diff --git a/spec/build/testsuites/validation/validation-0.yml b/spec/build/testsuites/validation/validation-0.yml index ffc070972e..c2f8d653e4 100644 --- a/spec/build/testsuites/validation/validation-0.yml +++ b/spec/build/testsuites/validation/validation-0.yml @@ -70,10 +70,23 @@ source: - testsuites/validation/tc-sem-set-priority.c - testsuites/validation/tc-signal-catch.c - testsuites/validation/tc-signal-send.c +- testsuites/validation/tc-task.c - testsuites/validation/tc-task-construct-errors.c - testsuites/validation/tc-task-create-errors.c +- testsuites/validation/tc-task-get-affinity.c +- testsuites/validation/tc-task-get-priority.c +- testsuites/validation/tc-task-get-scheduler.c - testsuites/validation/tc-task-ident.c +- testsuites/validation/tc-task-is-suspended.c - testsuites/validation/tc-task-mode.c +- testsuites/validation/tc-task-restart.c +- testsuites/validation/tc-task-resume.c +- testsuites/validation/tc-task-set-affinity.c +- testsuites/validation/tc-task-set-priority.c +- testsuites/validation/tc-task-set-scheduler.c +- testsuites/validation/tc-task-start.c +- testsuites/validation/tc-task-storage-size.c +- testsuites/validation/tc-task-suspend.c - testsuites/validation/tc-timer-create.c - testsuites/validation/tc-timer-delete.c - testsuites/validation/tc-timer-ident.c diff --git a/testsuites/validation/tc-task-construct-errors.c b/testsuites/validation/tc-task-construct-errors.c index e6f8c5faa5..c31ee29fb8 100644 --- a/testsuites/validation/tc-task-construct-errors.c +++ b/testsuites/validation/tc-task-construct-errors.c @@ -57,6 +57,8 @@ #include #include +#include "tx-support.h" + #include /** @@ -278,8 +280,6 @@ static const char * const * const RtemsTaskReqConstructErrors_PreDesc[] = { #define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) -#define INVALID_ID 0xffffffff - typedef RtemsTaskReqConstructErrors_Context Context; static _Thread_local int tls_variable; diff --git a/testsuites/validation/tc-task-create-errors.c b/testsuites/validation/tc-task-create-errors.c index 3121d753fc..c60344544e 100644 --- a/testsuites/validation/tc-task-create-errors.c +++ b/testsuites/validation/tc-task-create-errors.c @@ -57,6 +57,8 @@ #include #include +#include "tx-support.h" + #include /** @@ -247,8 +249,6 @@ static const char * const * const RtemsTaskReqCreateErrors_PreDesc[] = { #define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) -#define INVALID_ID 0xffffffff - typedef RtemsTaskReqCreateErrors_Context Context; static rtems_status_code Create( void *arg, uint32_t *id ) diff --git a/testsuites/validation/tc-task-get-affinity.c b/testsuites/validation/tc-task-get-affinity.c new file mode 100644 index 0000000000..fc50df997a --- /dev/null +++ b/testsuites/validation/tc-task-get-affinity.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqGetAffinity + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqGetAffinity \ + * spec:/rtems/task/req/get-affinity + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqGetAffinity_Pre_Id_Invalid, + RtemsTaskReqGetAffinity_Pre_Id_Task, + RtemsTaskReqGetAffinity_Pre_Id_NA +} RtemsTaskReqGetAffinity_Pre_Id; + +typedef enum { + RtemsTaskReqGetAffinity_Pre_CPUSetSize_Valid, + RtemsTaskReqGetAffinity_Pre_CPUSetSize_TooSmall, + RtemsTaskReqGetAffinity_Pre_CPUSetSize_Askew, + RtemsTaskReqGetAffinity_Pre_CPUSetSize_NA +} RtemsTaskReqGetAffinity_Pre_CPUSetSize; + +typedef enum { + RtemsTaskReqGetAffinity_Pre_CPUSet_Valid, + RtemsTaskReqGetAffinity_Pre_CPUSet_Null, + RtemsTaskReqGetAffinity_Pre_CPUSet_NA +} RtemsTaskReqGetAffinity_Pre_CPUSet; + +typedef enum { + RtemsTaskReqGetAffinity_Post_Status_Ok, + RtemsTaskReqGetAffinity_Post_Status_InvAddr, + RtemsTaskReqGetAffinity_Post_Status_InvId, + RtemsTaskReqGetAffinity_Post_Status_InvSize, + RtemsTaskReqGetAffinity_Post_Status_NA +} RtemsTaskReqGetAffinity_Post_Status; + +typedef enum { + RtemsTaskReqGetAffinity_Post_CPUSetObj_Set, + RtemsTaskReqGetAffinity_Post_CPUSetObj_Nop, + RtemsTaskReqGetAffinity_Post_CPUSetObj_NA +} RtemsTaskReqGetAffinity_Post_CPUSetObj; + +/** + * @brief Test context for spec:/rtems/task/req/get-affinity test case. + */ +typedef struct { + /** + * @brief This member provides the object referenced by the ``cpuset`` + * parameter. + */ + cpu_set_t cpuset_obj; + + /** + * @brief This member contains the return value of the + * rtems_task_get_affinity() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``cpusetsize`` parameter value. + */ + size_t cpusetsize; + + /** + * @brief This member specifies if the ``cpuset`` parameter value. + */ + cpu_set_t *cpuset; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 3 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqGetAffinity_Context; + +static RtemsTaskReqGetAffinity_Context + RtemsTaskReqGetAffinity_Instance; + +static const char * const RtemsTaskReqGetAffinity_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqGetAffinity_PreDesc_CPUSetSize[] = { + "Valid", + "TooSmall", + "Askew", + "NA" +}; + +static const char * const RtemsTaskReqGetAffinity_PreDesc_CPUSet[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const * const RtemsTaskReqGetAffinity_PreDesc[] = { + RtemsTaskReqGetAffinity_PreDesc_Id, + RtemsTaskReqGetAffinity_PreDesc_CPUSetSize, + RtemsTaskReqGetAffinity_PreDesc_CPUSet, + NULL +}; + +static void RtemsTaskReqGetAffinity_Pre_Id_Prepare( + RtemsTaskReqGetAffinity_Context *ctx, + RtemsTaskReqGetAffinity_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqGetAffinity_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqGetAffinity_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = RTEMS_SELF; + break; + } + + case RtemsTaskReqGetAffinity_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqGetAffinity_Pre_CPUSetSize_Prepare( + RtemsTaskReqGetAffinity_Context *ctx, + RtemsTaskReqGetAffinity_Pre_CPUSetSize state +) +{ + switch ( state ) { + case RtemsTaskReqGetAffinity_Pre_CPUSetSize_Valid: { + /* + * While the ``cpusetsize`` parameter is an integral multiple of the size + * of long, while the ``cpusetsize`` parameter specifies a processor set + * which is large enough to contain the processor affinity set of the + * task. + */ + ctx->cpusetsize = sizeof( ctx->cpuset_obj ); + break; + } + + case RtemsTaskReqGetAffinity_Pre_CPUSetSize_TooSmall: { + /* + * While the ``cpusetsize`` parameter is an integral multiple of the size + * of long, while the ``cpusetsize`` parameter specifies a processor set + * which is not large enough to contain the processor affinity set of the + * task. + */ + ctx->cpusetsize = 0; + break; + } + + case RtemsTaskReqGetAffinity_Pre_CPUSetSize_Askew: { + /* + * While the ``cpusetsize`` parameter is not an integral multiple of the + * size of long. + */ + ctx->cpusetsize = SIZE_MAX; + break; + } + + case RtemsTaskReqGetAffinity_Pre_CPUSetSize_NA: + break; + } +} + +static void RtemsTaskReqGetAffinity_Pre_CPUSet_Prepare( + RtemsTaskReqGetAffinity_Context *ctx, + RtemsTaskReqGetAffinity_Pre_CPUSet state +) +{ + switch ( state ) { + case RtemsTaskReqGetAffinity_Pre_CPUSet_Valid: { + /* + * While the ``cpuset`` parameter references an object of type cpu_set_t. + */ + ctx->cpuset = &ctx->cpuset_obj; + break; + } + + case RtemsTaskReqGetAffinity_Pre_CPUSet_Null: { + /* + * While the ``cpuset`` parameter is equal to NULL. + */ + ctx->cpuset = NULL; + break; + } + + case RtemsTaskReqGetAffinity_Pre_CPUSet_NA: + break; + } +} + +static void RtemsTaskReqGetAffinity_Post_Status_Check( + RtemsTaskReqGetAffinity_Context *ctx, + RtemsTaskReqGetAffinity_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqGetAffinity_Post_Status_Ok: { + /* + * The return status of rtems_task_get_affinity() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqGetAffinity_Post_Status_InvAddr: { + /* + * The return status of rtems_task_get_affinity() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqGetAffinity_Post_Status_InvId: { + /* + * The return status of rtems_task_get_affinity() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqGetAffinity_Post_Status_InvSize: { + /* + * The return status of rtems_task_get_affinity() shall be + * RTEMS_INVALID_SIZE. + */ + T_rsc( ctx->status, RTEMS_INVALID_SIZE ); + break; + } + + case RtemsTaskReqGetAffinity_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqGetAffinity_Post_CPUSetObj_Check( + RtemsTaskReqGetAffinity_Context *ctx, + RtemsTaskReqGetAffinity_Post_CPUSetObj state +) +{ + cpu_set_t set; + uint32_t cpu_index; + uint32_t cpu_max; + + switch ( state ) { + case RtemsTaskReqGetAffinity_Post_CPUSetObj_Set: { + /* + * The value of the object referenced by the ``cpuset`` parameter shall + * be set to the processor affinity set of the task specified by the + * ``id`` parameter at some point during the call after the return of the + * rtems_task_get_affinity() call. + */ + CPU_ZERO( &set ); + + cpu_max = rtems_scheduler_get_processor_maximum(); + + /* We need the online processors */ + if ( cpu_max > 4 ) { + cpu_max = 4; + } + + for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) { + CPU_SET( (int) cpu_index, &set ); + } + + T_eq_int( CPU_CMP( &ctx->cpuset_obj, &set ), 0 ); + break; + } + + case RtemsTaskReqGetAffinity_Post_CPUSetObj_Nop: { + /* + * Objects referenced by the ``cpuset`` parameter in past calls to + * rtems_task_get_affinity() shall not be accessed by the + * rtems_task_get_affinity() call. + */ + CPU_ZERO( &set ); + T_eq_int( CPU_CMP( &ctx->cpuset_obj, &set ), 0 ); + break; + } + + case RtemsTaskReqGetAffinity_Post_CPUSetObj_NA: + break; + } +} + +static void RtemsTaskReqGetAffinity_Prepare( + RtemsTaskReqGetAffinity_Context *ctx +) +{ + CPU_ZERO( &ctx->cpuset_obj ); +} + +static void RtemsTaskReqGetAffinity_Action( + RtemsTaskReqGetAffinity_Context *ctx +) +{ + ctx->status = rtems_task_get_affinity( + ctx->id, + ctx->cpusetsize, + ctx->cpuset + ); +} + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_CPUSetSize_NA : 1; + uint16_t Pre_CPUSet_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_CPUSetObj : 2; +} RtemsTaskReqGetAffinity_Entry; + +static const RtemsTaskReqGetAffinity_Entry +RtemsTaskReqGetAffinity_Entries[] = { + { 0, 0, 0, 0, RtemsTaskReqGetAffinity_Post_Status_InvAddr, + RtemsTaskReqGetAffinity_Post_CPUSetObj_Nop }, + { 0, 0, 0, 0, RtemsTaskReqGetAffinity_Post_Status_InvId, + RtemsTaskReqGetAffinity_Post_CPUSetObj_Nop }, + { 0, 0, 0, 0, RtemsTaskReqGetAffinity_Post_Status_InvSize, + RtemsTaskReqGetAffinity_Post_CPUSetObj_Nop }, + { 0, 0, 0, 0, RtemsTaskReqGetAffinity_Post_Status_Ok, + RtemsTaskReqGetAffinity_Post_CPUSetObj_Set } +}; + +static const uint8_t +RtemsTaskReqGetAffinity_Map[] = { + 1, 0, 1, 0, 1, 0, 3, 0, 2, 0, 2, 0 +}; + +static size_t RtemsTaskReqGetAffinity_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqGetAffinity_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqGetAffinity_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqGetAffinity_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = RtemsTaskReqGetAffinity_Scope, + .initial_context = &RtemsTaskReqGetAffinity_Instance +}; + +static inline RtemsTaskReqGetAffinity_Entry RtemsTaskReqGetAffinity_GetEntry( + size_t index +) +{ + return RtemsTaskReqGetAffinity_Entries[ + RtemsTaskReqGetAffinity_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqGetAffinity( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqGetAffinity, + &RtemsTaskReqGetAffinity_Fixture +) +{ + RtemsTaskReqGetAffinity_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqGetAffinity_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqGetAffinity_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqGetAffinity_Pre_CPUSetSize_Valid; + ctx->pcs[ 1 ] < RtemsTaskReqGetAffinity_Pre_CPUSetSize_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqGetAffinity_Pre_CPUSet_Valid; + ctx->pcs[ 2 ] < RtemsTaskReqGetAffinity_Pre_CPUSet_NA; + ++ctx->pcs[ 2 ] + ) { + RtemsTaskReqGetAffinity_Entry entry; + + entry = RtemsTaskReqGetAffinity_GetEntry( index ); + ++index; + + RtemsTaskReqGetAffinity_Prepare( ctx ); + RtemsTaskReqGetAffinity_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqGetAffinity_Pre_CPUSetSize_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqGetAffinity_Pre_CPUSet_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqGetAffinity_Action( ctx ); + RtemsTaskReqGetAffinity_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqGetAffinity_Post_CPUSetObj_Check( + ctx, + entry.Post_CPUSetObj + ); + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-get-priority.c b/testsuites/validation/tc-task-get-priority.c new file mode 100644 index 0000000000..5d69242f9c --- /dev/null +++ b/testsuites/validation/tc-task-get-priority.c @@ -0,0 +1,579 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqGetPriority + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "ts-config.h" +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqGetPriority \ + * spec:/rtems/task/req/get-priority + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqGetPriority_Pre_TaskId_Invalid, + RtemsTaskReqGetPriority_Pre_TaskId_Task, + RtemsTaskReqGetPriority_Pre_TaskId_NA +} RtemsTaskReqGetPriority_Pre_TaskId; + +typedef enum { + RtemsTaskReqGetPriority_Pre_SchedulerId_Invalid, + RtemsTaskReqGetPriority_Pre_SchedulerId_Scheduler, + RtemsTaskReqGetPriority_Pre_SchedulerId_NA +} RtemsTaskReqGetPriority_Pre_SchedulerId; + +typedef enum { + RtemsTaskReqGetPriority_Pre_Scheduler_Eligible, + RtemsTaskReqGetPriority_Pre_Scheduler_Ineligible, + RtemsTaskReqGetPriority_Pre_Scheduler_NA +} RtemsTaskReqGetPriority_Pre_Scheduler; + +typedef enum { + RtemsTaskReqGetPriority_Pre_Priority_Valid, + RtemsTaskReqGetPriority_Pre_Priority_Null, + RtemsTaskReqGetPriority_Pre_Priority_NA +} RtemsTaskReqGetPriority_Pre_Priority; + +typedef enum { + RtemsTaskReqGetPriority_Post_Status_Ok, + RtemsTaskReqGetPriority_Post_Status_InvAddr, + RtemsTaskReqGetPriority_Post_Status_InvId, + RtemsTaskReqGetPriority_Post_Status_NotDef, + RtemsTaskReqGetPriority_Post_Status_NA +} RtemsTaskReqGetPriority_Post_Status; + +typedef enum { + RtemsTaskReqGetPriority_Post_PriorityObj_Set, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop, + RtemsTaskReqGetPriority_Post_PriorityObj_NA +} RtemsTaskReqGetPriority_Post_PriorityObj; + +/** + * @brief Test context for spec:/rtems/task/req/get-priority test case. + */ +typedef struct { + /** + * @brief This member contains the scheduler A identifier. + */ + rtems_id scheduler_a_id; + + /** + * @brief This member contains the scheduler B identifier. + */ + rtems_id scheduler_b_id; + + /** + * @brief This member provides the object referenced by the ``priority`` + * parameter. + */ + rtems_task_priority priority_obj; + + /** + * @brief This member contains the return value of the + * rtems_task_get_priority() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``task_id`` parameter value. + */ + rtems_id task_id; + + /** + * @brief This member specifies if the ``scheduler_id`` parameter value. + */ + rtems_id scheduler_id; + + /** + * @brief This member specifies if the ``priority`` parameter value. + */ + rtems_id *priority; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 4 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqGetPriority_Context; + +static RtemsTaskReqGetPriority_Context + RtemsTaskReqGetPriority_Instance; + +static const char * const RtemsTaskReqGetPriority_PreDesc_TaskId[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqGetPriority_PreDesc_SchedulerId[] = { + "Invalid", + "Scheduler", + "NA" +}; + +static const char * const RtemsTaskReqGetPriority_PreDesc_Scheduler[] = { + "Eligible", + "Ineligible", + "NA" +}; + +static const char * const RtemsTaskReqGetPriority_PreDesc_Priority[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const * const RtemsTaskReqGetPriority_PreDesc[] = { + RtemsTaskReqGetPriority_PreDesc_TaskId, + RtemsTaskReqGetPriority_PreDesc_SchedulerId, + RtemsTaskReqGetPriority_PreDesc_Scheduler, + RtemsTaskReqGetPriority_PreDesc_Priority, + NULL +}; + +static void RtemsTaskReqGetPriority_Pre_TaskId_Prepare( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Pre_TaskId state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Pre_TaskId_Invalid: { + /* + * While the ``task_id`` parameter is not associated with a task. + */ + ctx->task_id = INVALID_ID; + break; + } + + case RtemsTaskReqGetPriority_Pre_TaskId_Task: { + /* + * While the ``task_id`` parameter is associated with a task. + */ + ctx->task_id = RTEMS_SELF; + break; + } + + case RtemsTaskReqGetPriority_Pre_TaskId_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Pre_SchedulerId_Prepare( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Pre_SchedulerId state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Pre_SchedulerId_Invalid: { + /* + * While the ``scheduler_id`` parameter is not associated with a + * scheduler. + */ + ctx->scheduler_id = INVALID_ID; + break; + } + + case RtemsTaskReqGetPriority_Pre_SchedulerId_Scheduler: { + /* + * While the ``scheduler_id`` parameter is associated with a scheduler. + */ + ctx->scheduler_id = ctx->scheduler_a_id; + break; + } + + case RtemsTaskReqGetPriority_Pre_SchedulerId_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Pre_Scheduler_Prepare( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Pre_Scheduler state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Pre_Scheduler_Eligible: { + /* + * While the ``scheduler_id`` parameter is associated with an eligible + * scheduler of the task specified by ``task_id``. + */ + ctx->scheduler_id = ctx->scheduler_a_id; + break; + } + + case RtemsTaskReqGetPriority_Pre_Scheduler_Ineligible: { + /* + * While the ``scheduler_id`` parameter is associated with an ineligible + * scheduler of the task specified by ``task_id``. + */ + ctx->scheduler_id = ctx->scheduler_b_id; + break; + } + + case RtemsTaskReqGetPriority_Pre_Scheduler_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Pre_Priority_Prepare( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Pre_Priority state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Pre_Priority_Valid: { + /* + * While the ``priority`` parameter references an object of type + * rtems_task_priority. + */ + ctx->priority = &ctx->priority_obj; + break; + } + + case RtemsTaskReqGetPriority_Pre_Priority_Null: { + /* + * While the ``priority`` parameter is equal to NULL. + */ + ctx->priority = NULL; + break; + } + + case RtemsTaskReqGetPriority_Pre_Priority_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Post_Status_Check( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Post_Status_Ok: { + /* + * The return status of rtems_task_get_priority() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqGetPriority_Post_Status_InvAddr: { + /* + * The return status of rtems_task_get_priority() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqGetPriority_Post_Status_InvId: { + /* + * The return status of rtems_task_get_priority() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqGetPriority_Post_Status_NotDef: { + /* + * The return status of rtems_task_get_priority() shall be + * RTEMS_NOT_DEFINED. + */ + T_rsc( ctx->status, RTEMS_NOT_DEFINED ); + break; + } + + case RtemsTaskReqGetPriority_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Post_PriorityObj_Check( + RtemsTaskReqGetPriority_Context *ctx, + RtemsTaskReqGetPriority_Post_PriorityObj state +) +{ + switch ( state ) { + case RtemsTaskReqGetPriority_Post_PriorityObj_Set: { + /* + * The value of the object referenced by the ``scheduler_id`` parameter + * shall be set to the object identifier of the home scheduler of the + * task specified by the ``task_id`` parameter at some point during the + * call after the return of the rtems_task_get_priority() call. + */ + T_eq_u32( ctx->priority_obj, PRIO_DEFAULT ); + break; + } + + case RtemsTaskReqGetPriority_Post_PriorityObj_Nop: { + /* + * Objects referenced by the ``scheduler_id`` parameter in past calls to + * rtems_task_get_priority() shall not be accessed by the + * rtems_task_get_priority() call. + */ + T_eq_u32( ctx->priority_obj, PRIO_INVALID ); + break; + } + + case RtemsTaskReqGetPriority_Post_PriorityObj_NA: + break; + } +} + +static void RtemsTaskReqGetPriority_Setup( + RtemsTaskReqGetPriority_Context *ctx +) +{ + rtems_status_code sc; + + sc = rtems_scheduler_ident( + TEST_SCHEDULER_A_NAME, + &ctx->scheduler_a_id + ); + T_rsc_success( sc ); + + #if defined(RTEMS_SMP) + sc = rtems_scheduler_ident( + TEST_SCHEDULER_B_NAME, + &ctx->scheduler_b_id + ); + T_rsc_success( sc ); + #endif +} + +static void RtemsTaskReqGetPriority_Setup_Wrap( void *arg ) +{ + RtemsTaskReqGetPriority_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqGetPriority_Setup( ctx ); +} + +static void RtemsTaskReqGetPriority_Prepare( + RtemsTaskReqGetPriority_Context *ctx +) +{ + ctx->priority_obj = PRIO_INVALID; +} + +static void RtemsTaskReqGetPriority_Action( + RtemsTaskReqGetPriority_Context *ctx +) +{ + ctx->status = rtems_task_get_priority( + ctx->task_id, + ctx->scheduler_id, + ctx->priority + ); +} + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_TaskId_NA : 1; + uint16_t Pre_SchedulerId_NA : 1; + uint16_t Pre_Scheduler_NA : 1; + uint16_t Pre_Priority_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_PriorityObj : 2; +} RtemsTaskReqGetPriority_Entry; + +static const RtemsTaskReqGetPriority_Entry +RtemsTaskReqGetPriority_Entries[] = { + { 0, 0, 0, 1, 0, RtemsTaskReqGetPriority_Post_Status_InvId, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop }, + { 0, 0, 0, 1, 0, RtemsTaskReqGetPriority_Post_Status_InvAddr, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop }, + { 0, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_Ok, + RtemsTaskReqGetPriority_Post_PriorityObj_Set }, + { 0, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_InvAddr, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop }, +#if defined(RTEMS_SMP) + { 0, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_NotDef, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop }, +#else + { 1, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_NA, + RtemsTaskReqGetPriority_Post_PriorityObj_NA }, +#endif +#if defined(RTEMS_SMP) + { 0, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_InvAddr, + RtemsTaskReqGetPriority_Post_PriorityObj_Nop } +#else + { 1, 0, 0, 0, 0, RtemsTaskReqGetPriority_Post_Status_NA, + RtemsTaskReqGetPriority_Post_PriorityObj_NA } +#endif +}; + +static const uint8_t +RtemsTaskReqGetPriority_Map[] = { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 4, 5 +}; + +static size_t RtemsTaskReqGetPriority_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqGetPriority_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqGetPriority_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqGetPriority_Fixture = { + .setup = RtemsTaskReqGetPriority_Setup_Wrap, + .stop = NULL, + .teardown = NULL, + .scope = RtemsTaskReqGetPriority_Scope, + .initial_context = &RtemsTaskReqGetPriority_Instance +}; + +static inline RtemsTaskReqGetPriority_Entry RtemsTaskReqGetPriority_GetEntry( + size_t index +) +{ + return RtemsTaskReqGetPriority_Entries[ + RtemsTaskReqGetPriority_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqGetPriority( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqGetPriority, + &RtemsTaskReqGetPriority_Fixture +) +{ + RtemsTaskReqGetPriority_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqGetPriority_Pre_TaskId_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqGetPriority_Pre_TaskId_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqGetPriority_Pre_SchedulerId_Invalid; + ctx->pcs[ 1 ] < RtemsTaskReqGetPriority_Pre_SchedulerId_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqGetPriority_Pre_Scheduler_Eligible; + ctx->pcs[ 2 ] < RtemsTaskReqGetPriority_Pre_Scheduler_NA; + ++ctx->pcs[ 2 ] + ) { + for ( + ctx->pcs[ 3 ] = RtemsTaskReqGetPriority_Pre_Priority_Valid; + ctx->pcs[ 3 ] < RtemsTaskReqGetPriority_Pre_Priority_NA; + ++ctx->pcs[ 3 ] + ) { + RtemsTaskReqGetPriority_Entry entry; + size_t pcs[ 4 ]; + + entry = RtemsTaskReqGetPriority_GetEntry( index ); + ++index; + + if ( entry.Skip ) { + continue; + } + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Scheduler_NA ) { + ctx->pcs[ 2 ] = RtemsTaskReqGetPriority_Pre_Scheduler_NA; + } + + RtemsTaskReqGetPriority_Prepare( ctx ); + RtemsTaskReqGetPriority_Pre_TaskId_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqGetPriority_Pre_SchedulerId_Prepare( + ctx, + ctx->pcs[ 1 ] + ); + RtemsTaskReqGetPriority_Pre_Scheduler_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqGetPriority_Pre_Priority_Prepare( ctx, ctx->pcs[ 3 ] ); + RtemsTaskReqGetPriority_Action( ctx ); + RtemsTaskReqGetPriority_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqGetPriority_Post_PriorityObj_Check( + ctx, + entry.Post_PriorityObj + ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-get-scheduler.c b/testsuites/validation/tc-task-get-scheduler.c new file mode 100644 index 0000000000..f6da709cee --- /dev/null +++ b/testsuites/validation/tc-task-get-scheduler.c @@ -0,0 +1,389 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqGetScheduler + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqGetScheduler \ + * spec:/rtems/task/req/get-scheduler + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqGetScheduler_Pre_Id_Invalid, + RtemsTaskReqGetScheduler_Pre_Id_Task, + RtemsTaskReqGetScheduler_Pre_Id_NA +} RtemsTaskReqGetScheduler_Pre_Id; + +typedef enum { + RtemsTaskReqGetScheduler_Pre_SchedulerID_Valid, + RtemsTaskReqGetScheduler_Pre_SchedulerID_Null, + RtemsTaskReqGetScheduler_Pre_SchedulerID_NA +} RtemsTaskReqGetScheduler_Pre_SchedulerID; + +typedef enum { + RtemsTaskReqGetScheduler_Post_Status_Ok, + RtemsTaskReqGetScheduler_Post_Status_InvAddr, + RtemsTaskReqGetScheduler_Post_Status_InvId, + RtemsTaskReqGetScheduler_Post_Status_NA +} RtemsTaskReqGetScheduler_Post_Status; + +typedef enum { + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Set, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Nop, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_NA +} RtemsTaskReqGetScheduler_Post_SchedulerIDObj; + +/** + * @brief Test context for spec:/rtems/task/req/get-scheduler test case. + */ +typedef struct { + /** + * @brief This member provides the object referenced by the ``scheduler_id`` + * parameter. + */ + rtems_id scheduler_id_obj; + + /** + * @brief This member contains the return value of the + * rtems_task_get_scheduler() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``task_id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``scheduler_id`` parameter value. + */ + rtems_id *scheduler_id; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 2 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqGetScheduler_Context; + +static RtemsTaskReqGetScheduler_Context + RtemsTaskReqGetScheduler_Instance; + +static const char * const RtemsTaskReqGetScheduler_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqGetScheduler_PreDesc_SchedulerID[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const * const RtemsTaskReqGetScheduler_PreDesc[] = { + RtemsTaskReqGetScheduler_PreDesc_Id, + RtemsTaskReqGetScheduler_PreDesc_SchedulerID, + NULL +}; + +static void RtemsTaskReqGetScheduler_Pre_Id_Prepare( + RtemsTaskReqGetScheduler_Context *ctx, + RtemsTaskReqGetScheduler_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqGetScheduler_Pre_Id_Invalid: { + /* + * While the ``task_id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqGetScheduler_Pre_Id_Task: { + /* + * While the ``task_id`` parameter is associated with a task. + */ + ctx->id = RTEMS_SELF; + break; + } + + case RtemsTaskReqGetScheduler_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqGetScheduler_Pre_SchedulerID_Prepare( + RtemsTaskReqGetScheduler_Context *ctx, + RtemsTaskReqGetScheduler_Pre_SchedulerID state +) +{ + switch ( state ) { + case RtemsTaskReqGetScheduler_Pre_SchedulerID_Valid: { + /* + * While the ``scheduler_id`` parameter references an object of type + * rtems_id. + */ + ctx->scheduler_id = &ctx->scheduler_id_obj; + break; + } + + case RtemsTaskReqGetScheduler_Pre_SchedulerID_Null: { + /* + * While the ``scheduler_id`` parameter is equal to NULL. + */ + ctx->scheduler_id = NULL; + break; + } + + case RtemsTaskReqGetScheduler_Pre_SchedulerID_NA: + break; + } +} + +static void RtemsTaskReqGetScheduler_Post_Status_Check( + RtemsTaskReqGetScheduler_Context *ctx, + RtemsTaskReqGetScheduler_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqGetScheduler_Post_Status_Ok: { + /* + * The return status of rtems_task_get_scheduler() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqGetScheduler_Post_Status_InvAddr: { + /* + * The return status of rtems_task_get_scheduler() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqGetScheduler_Post_Status_InvId: { + /* + * The return status of rtems_task_get_scheduler() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqGetScheduler_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Check( + RtemsTaskReqGetScheduler_Context *ctx, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj state +) +{ + switch ( state ) { + case RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Set: { + /* + * The value of the object referenced by the ``scheduler_id`` parameter + * shall be set to the object identifier of the home scheduler of the + * task specified by the ``task_id`` parameter at some point during the + * call after the return of the rtems_task_get_scheduler() call. + */ + T_eq_u32( ctx->scheduler_id_obj, 0x0f010001 ); + break; + } + + case RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Nop: { + /* + * Objects referenced by the ``scheduler_id`` parameter in past calls to + * rtems_task_get_scheduler() shall not be accessed by the + * rtems_task_get_scheduler() call. + */ + T_eq_u32( ctx->scheduler_id_obj, INVALID_ID ); + break; + } + + case RtemsTaskReqGetScheduler_Post_SchedulerIDObj_NA: + break; + } +} + +static void RtemsTaskReqGetScheduler_Prepare( + RtemsTaskReqGetScheduler_Context *ctx +) +{ + ctx->scheduler_id_obj = INVALID_ID; +} + +static void RtemsTaskReqGetScheduler_Action( + RtemsTaskReqGetScheduler_Context *ctx +) +{ + ctx->status = rtems_task_get_scheduler( ctx->id, ctx->scheduler_id ); +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Pre_SchedulerID_NA : 1; + uint8_t Post_Status : 2; + uint8_t Post_SchedulerIDObj : 2; +} RtemsTaskReqGetScheduler_Entry; + +static const RtemsTaskReqGetScheduler_Entry +RtemsTaskReqGetScheduler_Entries[] = { + { 0, 0, 0, RtemsTaskReqGetScheduler_Post_Status_InvAddr, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Nop }, + { 0, 0, 0, RtemsTaskReqGetScheduler_Post_Status_InvId, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Nop }, + { 0, 0, 0, RtemsTaskReqGetScheduler_Post_Status_Ok, + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Set } +}; + +static const uint8_t +RtemsTaskReqGetScheduler_Map[] = { + 1, 0, 2, 0 +}; + +static size_t RtemsTaskReqGetScheduler_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqGetScheduler_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqGetScheduler_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqGetScheduler_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = RtemsTaskReqGetScheduler_Scope, + .initial_context = &RtemsTaskReqGetScheduler_Instance +}; + +static inline RtemsTaskReqGetScheduler_Entry RtemsTaskReqGetScheduler_GetEntry( + size_t index +) +{ + return RtemsTaskReqGetScheduler_Entries[ + RtemsTaskReqGetScheduler_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqGetScheduler( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqGetScheduler, + &RtemsTaskReqGetScheduler_Fixture +) +{ + RtemsTaskReqGetScheduler_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqGetScheduler_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqGetScheduler_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqGetScheduler_Pre_SchedulerID_Valid; + ctx->pcs[ 1 ] < RtemsTaskReqGetScheduler_Pre_SchedulerID_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqGetScheduler_Entry entry; + + entry = RtemsTaskReqGetScheduler_GetEntry( index ); + ++index; + + RtemsTaskReqGetScheduler_Prepare( ctx ); + RtemsTaskReqGetScheduler_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqGetScheduler_Pre_SchedulerID_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqGetScheduler_Action( ctx ); + RtemsTaskReqGetScheduler_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqGetScheduler_Post_SchedulerIDObj_Check( + ctx, + entry.Post_SchedulerIDObj + ); + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-is-suspended.c b/testsuites/validation/tc-task-is-suspended.c new file mode 100644 index 0000000000..ce0e00a568 --- /dev/null +++ b/testsuites/validation/tc-task-is-suspended.c @@ -0,0 +1,390 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqIsSuspended + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqIsSuspended \ + * spec:/rtems/task/req/is-suspended + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqIsSuspended_Pre_Id_Invalid, + RtemsTaskReqIsSuspended_Pre_Id_Task, + RtemsTaskReqIsSuspended_Pre_Id_NA +} RtemsTaskReqIsSuspended_Pre_Id; + +typedef enum { + RtemsTaskReqIsSuspended_Pre_Suspended_Yes, + RtemsTaskReqIsSuspended_Pre_Suspended_No, + RtemsTaskReqIsSuspended_Pre_Suspended_NA +} RtemsTaskReqIsSuspended_Pre_Suspended; + +typedef enum { + RtemsTaskReqIsSuspended_Post_Status_Ok, + RtemsTaskReqIsSuspended_Post_Status_InvId, + RtemsTaskReqIsSuspended_Post_Status_AlrdySus, + RtemsTaskReqIsSuspended_Post_Status_NA +} RtemsTaskReqIsSuspended_Post_Status; + +/** + * @brief Test context for spec:/rtems/task/req/is-suspended test case. + */ +typedef struct { + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_is_suspended() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the + * rtems_task_is_suspended() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 2 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqIsSuspended_Context; + +static RtemsTaskReqIsSuspended_Context + RtemsTaskReqIsSuspended_Instance; + +static const char * const RtemsTaskReqIsSuspended_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqIsSuspended_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqIsSuspended_PreDesc[] = { + RtemsTaskReqIsSuspended_PreDesc_Id, + RtemsTaskReqIsSuspended_PreDesc_Suspended, + NULL +}; + +static void Worker( rtems_task_argument arg ) +{ + while ( true ) { + /* Do nothing */ + } +} + +static void RtemsTaskReqIsSuspended_Pre_Id_Prepare( + RtemsTaskReqIsSuspended_Context *ctx, + RtemsTaskReqIsSuspended_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqIsSuspended_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqIsSuspended_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqIsSuspended_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqIsSuspended_Pre_Suspended_Prepare( + RtemsTaskReqIsSuspended_Context *ctx, + RtemsTaskReqIsSuspended_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqIsSuspended_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqIsSuspended_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqIsSuspended_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqIsSuspended_Post_Status_Check( + RtemsTaskReqIsSuspended_Context *ctx, + RtemsTaskReqIsSuspended_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqIsSuspended_Post_Status_Ok: { + /* + * The return status of rtems_task_is_suspended() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqIsSuspended_Post_Status_InvId: { + /* + * The return status of rtems_task_is_suspended() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqIsSuspended_Post_Status_AlrdySus: { + /* + * The return status of rtems_task_is_suspended() shall be + * RTEMS_ALREADY_SUSPENDED. + */ + T_rsc( ctx->status, RTEMS_ALREADY_SUSPENDED ); + break; + } + + case RtemsTaskReqIsSuspended_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqIsSuspended_Setup( + RtemsTaskReqIsSuspended_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsTaskReqIsSuspended_Setup_Wrap( void *arg ) +{ + RtemsTaskReqIsSuspended_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqIsSuspended_Setup( ctx ); +} + +static void RtemsTaskReqIsSuspended_Teardown( + RtemsTaskReqIsSuspended_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +static void RtemsTaskReqIsSuspended_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqIsSuspended_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqIsSuspended_Teardown( ctx ); +} + +static void RtemsTaskReqIsSuspended_Action( + RtemsTaskReqIsSuspended_Context *ctx +) +{ + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->status = rtems_task_is_suspended( ctx->id ); + + if ( ctx->suspend ) { + ResumeTask( ctx->worker_id ); + } +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Pre_Suspended_NA : 1; + uint8_t Post_Status : 2; +} RtemsTaskReqIsSuspended_Entry; + +static const RtemsTaskReqIsSuspended_Entry +RtemsTaskReqIsSuspended_Entries[] = { + { 0, 0, 1, RtemsTaskReqIsSuspended_Post_Status_InvId }, + { 0, 0, 0, RtemsTaskReqIsSuspended_Post_Status_AlrdySus }, + { 0, 0, 0, RtemsTaskReqIsSuspended_Post_Status_Ok } +}; + +static const uint8_t +RtemsTaskReqIsSuspended_Map[] = { + 0, 0, 1, 2 +}; + +static size_t RtemsTaskReqIsSuspended_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqIsSuspended_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqIsSuspended_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqIsSuspended_Fixture = { + .setup = RtemsTaskReqIsSuspended_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqIsSuspended_Teardown_Wrap, + .scope = RtemsTaskReqIsSuspended_Scope, + .initial_context = &RtemsTaskReqIsSuspended_Instance +}; + +static inline RtemsTaskReqIsSuspended_Entry RtemsTaskReqIsSuspended_GetEntry( + size_t index +) +{ + return RtemsTaskReqIsSuspended_Entries[ + RtemsTaskReqIsSuspended_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqIsSuspended( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqIsSuspended, + &RtemsTaskReqIsSuspended_Fixture +) +{ + RtemsTaskReqIsSuspended_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqIsSuspended_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqIsSuspended_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqIsSuspended_Pre_Suspended_Yes; + ctx->pcs[ 1 ] < RtemsTaskReqIsSuspended_Pre_Suspended_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqIsSuspended_Entry entry; + size_t pcs[ 2 ]; + + entry = RtemsTaskReqIsSuspended_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqIsSuspended_Pre_Suspended_NA; + } + + RtemsTaskReqIsSuspended_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqIsSuspended_Pre_Suspended_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqIsSuspended_Action( ctx ); + RtemsTaskReqIsSuspended_Post_Status_Check( ctx, entry.Post_Status ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-restart.c b/testsuites/validation/tc-task-restart.c new file mode 100644 index 0000000000..da27412285 --- /dev/null +++ b/testsuites/validation/tc-task-restart.c @@ -0,0 +1,719 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqRestart + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqRestart spec:/rtems/task/req/restart + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqRestart_Pre_Id_Invalid, + RtemsTaskReqRestart_Pre_Id_Task, + RtemsTaskReqRestart_Pre_Id_NA +} RtemsTaskReqRestart_Pre_Id; + +typedef enum { + RtemsTaskReqRestart_Pre_Argument_Pointer, + RtemsTaskReqRestart_Pre_Argument_Number, + RtemsTaskReqRestart_Pre_Argument_NA +} RtemsTaskReqRestart_Pre_Argument; + +typedef enum { + RtemsTaskReqRestart_Pre_Dormant_Yes, + RtemsTaskReqRestart_Pre_Dormant_No, + RtemsTaskReqRestart_Pre_Dormant_NA +} RtemsTaskReqRestart_Pre_Dormant; + +typedef enum { + RtemsTaskReqRestart_Pre_Suspended_Yes, + RtemsTaskReqRestart_Pre_Suspended_No, + RtemsTaskReqRestart_Pre_Suspended_NA +} RtemsTaskReqRestart_Pre_Suspended; + +typedef enum { + RtemsTaskReqRestart_Post_Status_Ok, + RtemsTaskReqRestart_Post_Status_InvId, + RtemsTaskReqRestart_Post_Status_IncStat, + RtemsTaskReqRestart_Post_Status_NA +} RtemsTaskReqRestart_Post_Status; + +typedef enum { + RtemsTaskReqRestart_Post_Argument_Set, + RtemsTaskReqRestart_Post_Argument_Nop, + RtemsTaskReqRestart_Post_Argument_NA +} RtemsTaskReqRestart_Post_Argument; + +typedef enum { + RtemsTaskReqRestart_Post_Unblock_Yes, + RtemsTaskReqRestart_Post_Unblock_Nop, + RtemsTaskReqRestart_Post_Unblock_NA +} RtemsTaskReqRestart_Post_Unblock; + +typedef enum { + RtemsTaskReqRestart_Post_RestartExtensions_Yes, + RtemsTaskReqRestart_Post_RestartExtensions_Nop, + RtemsTaskReqRestart_Post_RestartExtensions_NA +} RtemsTaskReqRestart_Post_RestartExtensions; + +/** + * @brief Test context for spec:/rtems/task/req/restart test case. + */ +typedef struct { + /** + * @brief This member provides the scheduler operation records. + */ + T_scheduler_log_2 scheduler_log; + + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief This member contains the identifier of the test user extensions. + */ + rtems_id extension_id; + + /** + * @brief This member contains the count of thread restart extension calls. + */ + uint32_t restart_extension_calls; + + /** + * @brief This member contains the actual argument passed to the entry point. + */ + rtems_task_argument actual_argument; + + /** + * @brief This member contains the entry point counter. + */ + uint32_t counter; + + /** + * @brief If this member is true, then the worker is started before the + * rtems_task_restart() call. + */ + bool start; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_restart() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the rtems_task_restart() + * call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``argument`` parameter value. + */ + rtems_task_argument argument; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 4 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqRestart_Context; + +static RtemsTaskReqRestart_Context + RtemsTaskReqRestart_Instance; + +static const char * const RtemsTaskReqRestart_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqRestart_PreDesc_Argument[] = { + "Pointer", + "Number", + "NA" +}; + +static const char * const RtemsTaskReqRestart_PreDesc_Dormant[] = { + "Yes", + "No", + "NA" +}; + +static const char * const RtemsTaskReqRestart_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqRestart_PreDesc[] = { + RtemsTaskReqRestart_PreDesc_Id, + RtemsTaskReqRestart_PreDesc_Argument, + RtemsTaskReqRestart_PreDesc_Dormant, + RtemsTaskReqRestart_PreDesc_Suspended, + NULL +}; + +typedef RtemsTaskReqRestart_Context Context; + +static void Worker( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = &RtemsTaskReqRestart_Instance; + + while ( true ) { + ctx->actual_argument += arg; + ++ctx->counter; + Yield(); + } +} + +static void ThreadRestart( rtems_tcb *executing, rtems_tcb *restarted ) +{ + (void) executing; + (void) restarted; + + ++RtemsTaskReqRestart_Instance.restart_extension_calls; +} + +static const rtems_extensions_table extensions = { + .thread_restart = ThreadRestart +}; + +static void RtemsTaskReqRestart_Pre_Id_Prepare( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqRestart_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqRestart_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqRestart_Pre_Argument_Prepare( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Pre_Argument state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Pre_Argument_Pointer: { + /* + * While the entry point argument specified by the ``argument`` parameter + * is a pointer. + */ + ctx->argument = (rtems_task_argument) ctx; + break; + } + + case RtemsTaskReqRestart_Pre_Argument_Number: { + /* + * While the entry point argument specified by the ``argument`` parameter + * is a 32-bit number. + */ + ctx->argument = UINT32_C( 0x87654321 ); + break; + } + + case RtemsTaskReqRestart_Pre_Argument_NA: + break; + } +} + +static void RtemsTaskReqRestart_Pre_Dormant_Prepare( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Pre_Dormant state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Pre_Dormant_Yes: { + /* + * While the task specified by the ``id`` parameter is dormant. + */ + ctx->start = false; + break; + } + + case RtemsTaskReqRestart_Pre_Dormant_No: { + /* + * While the task specified by the ``id`` parameter is not dormant. + */ + ctx->start = true; + break; + } + + case RtemsTaskReqRestart_Pre_Dormant_NA: + break; + } +} + +static void RtemsTaskReqRestart_Pre_Suspended_Prepare( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqRestart_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqRestart_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqRestart_Post_Status_Check( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Post_Status_Ok: { + /* + * The return status of rtems_task_restart() shall be RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqRestart_Post_Status_InvId: { + /* + * The return status of rtems_task_restart() shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqRestart_Post_Status_IncStat: { + /* + * The return status of rtems_task_restart() shall be + * RTEMS_INCORRECT_STATE. + */ + T_rsc( ctx->status, RTEMS_INCORRECT_STATE ); + break; + } + + case RtemsTaskReqRestart_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqRestart_Post_Argument_Check( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Post_Argument state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Post_Argument_Set: { + /* + * The entry point argument of the task specified by the ``id`` parameter + * shall be set to the value specified by the ``argument`` parameter + * before the task is unblocked by the rtems_task_restart() call. + */ + T_eq_u32( ctx->actual_argument, ctx->argument ); + T_eq_u32( ctx->counter, 2 ); + break; + } + + case RtemsTaskReqRestart_Post_Argument_Nop: { + /* + * No entry point argument of a task shall be modified by the + * rtems_task_restart() call. + */ + T_eq_u32( ctx->actual_argument, 0 ); + + if ( ctx->start ) { + T_eq_u32( ctx->counter, 1 ); + } else { + T_eq_u32( ctx->counter, 0 ); + } + break; + } + + case RtemsTaskReqRestart_Post_Argument_NA: + break; + } +} + +static void RtemsTaskReqRestart_Post_Unblock_Check( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Post_Unblock state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Post_Unblock_Yes: { + /* + * The task specified by the ``id`` parameter shall be unblocked by the + * rtems_task_restart() call. + */ + if ( ctx->suspend ) { + T_eq_sz( ctx->scheduler_log.header.recorded, 1 ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].operation, + T_SCHEDULER_UNBLOCK + ); + } else { + T_eq_sz( ctx->scheduler_log.header.recorded, 2 ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].operation, + T_SCHEDULER_BLOCK + ); + T_eq_int( + ctx->scheduler_log.events[ 1 ].operation, + T_SCHEDULER_UNBLOCK + ); + } + break; + } + + case RtemsTaskReqRestart_Post_Unblock_Nop: { + /* + * No task shall be unblocked by the rtems_task_restart() call. + */ + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + break; + } + + case RtemsTaskReqRestart_Post_Unblock_NA: + break; + } +} + +static void RtemsTaskReqRestart_Post_RestartExtensions_Check( + RtemsTaskReqRestart_Context *ctx, + RtemsTaskReqRestart_Post_RestartExtensions state +) +{ + switch ( state ) { + case RtemsTaskReqRestart_Post_RestartExtensions_Yes: { + /* + * The thread restart user extensions shall be invoked by the + * rtems_task_restart() call. + */ + T_eq_u32( ctx->restart_extension_calls, 1 ); + break; + } + + case RtemsTaskReqRestart_Post_RestartExtensions_Nop: { + /* + * The thread restart user extensions shall not be invoked by the + * rtems_task_restart() call. + */ + T_eq_u32( ctx->restart_extension_calls, 0 ); + break; + } + + case RtemsTaskReqRestart_Post_RestartExtensions_NA: + break; + } +} + +static void RtemsTaskReqRestart_Setup( RtemsTaskReqRestart_Context *ctx ) +{ + rtems_status_code sc; + + sc = rtems_extension_create( + rtems_build_name( 'T', 'E', 'S', 'T' ), + &extensions, + &ctx->extension_id + ); + T_rsc_success( sc ); +} + +static void RtemsTaskReqRestart_Setup_Wrap( void *arg ) +{ + RtemsTaskReqRestart_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqRestart_Setup( ctx ); +} + +static void RtemsTaskReqRestart_Teardown( RtemsTaskReqRestart_Context *ctx ) +{ + rtems_status_code sc; + + sc = rtems_extension_delete( ctx->extension_id ); + T_rsc_success( sc ); +} + +static void RtemsTaskReqRestart_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqRestart_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqRestart_Teardown( ctx ); +} + +static void RtemsTaskReqRestart_Prepare( RtemsTaskReqRestart_Context *ctx ) +{ + ctx->actual_argument = 0; + ctx->counter = 0; + ctx->worker_id = CreateTask( "WORK", PRIO_DEFAULT ); +} + +static void RtemsTaskReqRestart_Action( RtemsTaskReqRestart_Context *ctx ) +{ + T_scheduler_log *log; + + if ( ctx->start ) { + StartTask( ctx->worker_id, Worker, 0 ); + Yield(); + } + + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->restart_extension_calls = 0; + + log = T_scheduler_record_2( &ctx->scheduler_log ); + T_null( log ); + + ctx->status = rtems_task_restart( ctx->id, ctx->argument ); + + log = T_scheduler_record( NULL ); + T_eq_ptr( &log->header, &ctx->scheduler_log.header ); + + Yield(); +} + +static void RtemsTaskReqRestart_Cleanup( RtemsTaskReqRestart_Context *ctx ) +{ + DeleteTask( ctx->worker_id ); +} + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_Argument_NA : 1; + uint16_t Pre_Dormant_NA : 1; + uint16_t Pre_Suspended_NA : 1; + uint16_t Post_Status : 2; + uint16_t Post_Argument : 2; + uint16_t Post_Unblock : 2; + uint16_t Post_RestartExtensions : 2; +} RtemsTaskReqRestart_Entry; + +static const RtemsTaskReqRestart_Entry +RtemsTaskReqRestart_Entries[] = { + { 0, 0, 0, 1, 1, RtemsTaskReqRestart_Post_Status_InvId, + RtemsTaskReqRestart_Post_Argument_Nop, + RtemsTaskReqRestart_Post_Unblock_Nop, + RtemsTaskReqRestart_Post_RestartExtensions_Nop }, + { 0, 0, 0, 0, 0, RtemsTaskReqRestart_Post_Status_IncStat, + RtemsTaskReqRestart_Post_Argument_Nop, + RtemsTaskReqRestart_Post_Unblock_Nop, + RtemsTaskReqRestart_Post_RestartExtensions_Nop }, + { 0, 0, 0, 0, 0, RtemsTaskReqRestart_Post_Status_Ok, + RtemsTaskReqRestart_Post_Argument_Set, + RtemsTaskReqRestart_Post_Unblock_Yes, + RtemsTaskReqRestart_Post_RestartExtensions_Yes } +}; + +static const uint8_t +RtemsTaskReqRestart_Map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 +}; + +static size_t RtemsTaskReqRestart_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqRestart_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqRestart_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqRestart_Fixture = { + .setup = RtemsTaskReqRestart_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqRestart_Teardown_Wrap, + .scope = RtemsTaskReqRestart_Scope, + .initial_context = &RtemsTaskReqRestart_Instance +}; + +static inline RtemsTaskReqRestart_Entry RtemsTaskReqRestart_GetEntry( + size_t index +) +{ + return RtemsTaskReqRestart_Entries[ + RtemsTaskReqRestart_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqRestart( void ) + */ +T_TEST_CASE_FIXTURE( RtemsTaskReqRestart, &RtemsTaskReqRestart_Fixture ) +{ + RtemsTaskReqRestart_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqRestart_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqRestart_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqRestart_Pre_Argument_Pointer; + ctx->pcs[ 1 ] < RtemsTaskReqRestart_Pre_Argument_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqRestart_Pre_Dormant_Yes; + ctx->pcs[ 2 ] < RtemsTaskReqRestart_Pre_Dormant_NA; + ++ctx->pcs[ 2 ] + ) { + for ( + ctx->pcs[ 3 ] = RtemsTaskReqRestart_Pre_Suspended_Yes; + ctx->pcs[ 3 ] < RtemsTaskReqRestart_Pre_Suspended_NA; + ++ctx->pcs[ 3 ] + ) { + RtemsTaskReqRestart_Entry entry; + size_t pcs[ 4 ]; + + entry = RtemsTaskReqRestart_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Dormant_NA ) { + ctx->pcs[ 2 ] = RtemsTaskReqRestart_Pre_Dormant_NA; + } + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 3 ] = RtemsTaskReqRestart_Pre_Suspended_NA; + } + + RtemsTaskReqRestart_Prepare( ctx ); + RtemsTaskReqRestart_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqRestart_Pre_Argument_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqRestart_Pre_Dormant_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqRestart_Pre_Suspended_Prepare( ctx, ctx->pcs[ 3 ] ); + RtemsTaskReqRestart_Action( ctx ); + RtemsTaskReqRestart_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqRestart_Post_Argument_Check( ctx, entry.Post_Argument ); + RtemsTaskReqRestart_Post_Unblock_Check( ctx, entry.Post_Unblock ); + RtemsTaskReqRestart_Post_RestartExtensions_Check( + ctx, + entry.Post_RestartExtensions + ); + RtemsTaskReqRestart_Cleanup( ctx ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-resume.c b/testsuites/validation/tc-task-resume.c new file mode 100644 index 0000000000..8a96ede9f7 --- /dev/null +++ b/testsuites/validation/tc-task-resume.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqResume + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqResume spec:/rtems/task/req/resume + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqResume_Pre_Id_Invalid, + RtemsTaskReqResume_Pre_Id_Task, + RtemsTaskReqResume_Pre_Id_NA +} RtemsTaskReqResume_Pre_Id; + +typedef enum { + RtemsTaskReqResume_Pre_Suspended_Yes, + RtemsTaskReqResume_Pre_Suspended_No, + RtemsTaskReqResume_Pre_Suspended_NA +} RtemsTaskReqResume_Pre_Suspended; + +typedef enum { + RtemsTaskReqResume_Post_Status_Ok, + RtemsTaskReqResume_Post_Status_InvId, + RtemsTaskReqResume_Post_Status_IncStat, + RtemsTaskReqResume_Post_Status_NA +} RtemsTaskReqResume_Post_Status; + +/** + * @brief Test context for spec:/rtems/task/req/resume test case. + */ +typedef struct { + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_resume() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the rtems_task_resume() + * call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 2 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqResume_Context; + +static RtemsTaskReqResume_Context + RtemsTaskReqResume_Instance; + +static const char * const RtemsTaskReqResume_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqResume_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqResume_PreDesc[] = { + RtemsTaskReqResume_PreDesc_Id, + RtemsTaskReqResume_PreDesc_Suspended, + NULL +}; + +static void Worker( rtems_task_argument arg ) +{ + while ( true ) { + /* Do nothing */ + } +} + +static void RtemsTaskReqResume_Pre_Id_Prepare( + RtemsTaskReqResume_Context *ctx, + RtemsTaskReqResume_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqResume_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqResume_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqResume_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqResume_Pre_Suspended_Prepare( + RtemsTaskReqResume_Context *ctx, + RtemsTaskReqResume_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqResume_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqResume_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqResume_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqResume_Post_Status_Check( + RtemsTaskReqResume_Context *ctx, + RtemsTaskReqResume_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqResume_Post_Status_Ok: { + /* + * The return status of rtems_task_resume() shall be RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqResume_Post_Status_InvId: { + /* + * The return status of rtems_task_resume() shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqResume_Post_Status_IncStat: { + /* + * The return status of rtems_task_resume() shall be + * RTEMS_INCORRECT_STATE. + */ + T_rsc( ctx->status, RTEMS_INCORRECT_STATE ); + break; + } + + case RtemsTaskReqResume_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqResume_Setup( RtemsTaskReqResume_Context *ctx ) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsTaskReqResume_Setup_Wrap( void *arg ) +{ + RtemsTaskReqResume_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqResume_Setup( ctx ); +} + +static void RtemsTaskReqResume_Teardown( RtemsTaskReqResume_Context *ctx ) +{ + DeleteTask( ctx->worker_id ); +} + +static void RtemsTaskReqResume_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqResume_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqResume_Teardown( ctx ); +} + +static void RtemsTaskReqResume_Action( RtemsTaskReqResume_Context *ctx ) +{ + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->status = rtems_task_resume( ctx->id ); + + if ( ctx->suspend && ctx->status != RTEMS_SUCCESSFUL ) { + ResumeTask( ctx->worker_id ); + } +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Pre_Suspended_NA : 1; + uint8_t Post_Status : 2; +} RtemsTaskReqResume_Entry; + +static const RtemsTaskReqResume_Entry +RtemsTaskReqResume_Entries[] = { + { 0, 0, 1, RtemsTaskReqResume_Post_Status_InvId }, + { 0, 0, 0, RtemsTaskReqResume_Post_Status_Ok }, + { 0, 0, 0, RtemsTaskReqResume_Post_Status_IncStat } +}; + +static const uint8_t +RtemsTaskReqResume_Map[] = { + 0, 0, 1, 2 +}; + +static size_t RtemsTaskReqResume_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqResume_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqResume_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqResume_Fixture = { + .setup = RtemsTaskReqResume_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqResume_Teardown_Wrap, + .scope = RtemsTaskReqResume_Scope, + .initial_context = &RtemsTaskReqResume_Instance +}; + +static inline RtemsTaskReqResume_Entry RtemsTaskReqResume_GetEntry( + size_t index +) +{ + return RtemsTaskReqResume_Entries[ + RtemsTaskReqResume_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqResume( void ) + */ +T_TEST_CASE_FIXTURE( RtemsTaskReqResume, &RtemsTaskReqResume_Fixture ) +{ + RtemsTaskReqResume_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqResume_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqResume_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqResume_Pre_Suspended_Yes; + ctx->pcs[ 1 ] < RtemsTaskReqResume_Pre_Suspended_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqResume_Entry entry; + size_t pcs[ 2 ]; + + entry = RtemsTaskReqResume_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqResume_Pre_Suspended_NA; + } + + RtemsTaskReqResume_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqResume_Pre_Suspended_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqResume_Action( ctx ); + RtemsTaskReqResume_Post_Status_Check( ctx, entry.Post_Status ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-set-affinity.c b/testsuites/validation/tc-task-set-affinity.c new file mode 100644 index 0000000000..d21f83495b --- /dev/null +++ b/testsuites/validation/tc-task-set-affinity.c @@ -0,0 +1,537 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqSetAffinity + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqSetAffinity \ + * spec:/rtems/task/req/set-affinity + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqSetAffinity_Pre_Id_Invalid, + RtemsTaskReqSetAffinity_Pre_Id_Task, + RtemsTaskReqSetAffinity_Pre_Id_NA +} RtemsTaskReqSetAffinity_Pre_Id; + +typedef enum { + RtemsTaskReqSetAffinity_Pre_CPUSetKind_Askew, + RtemsTaskReqSetAffinity_Pre_CPUSetKind_Huge, + RtemsTaskReqSetAffinity_Pre_CPUSetKind_Supported, + RtemsTaskReqSetAffinity_Pre_CPUSetKind_Unsupported, + RtemsTaskReqSetAffinity_Pre_CPUSetKind_NA +} RtemsTaskReqSetAffinity_Pre_CPUSetKind; + +typedef enum { + RtemsTaskReqSetAffinity_Pre_CPUSet_Valid, + RtemsTaskReqSetAffinity_Pre_CPUSet_Null, + RtemsTaskReqSetAffinity_Pre_CPUSet_NA +} RtemsTaskReqSetAffinity_Pre_CPUSet; + +typedef enum { + RtemsTaskReqSetAffinity_Post_Status_Ok, + RtemsTaskReqSetAffinity_Post_Status_InvAddr, + RtemsTaskReqSetAffinity_Post_Status_InvId, + RtemsTaskReqSetAffinity_Post_Status_InvNum, + RtemsTaskReqSetAffinity_Post_Status_NA +} RtemsTaskReqSetAffinity_Post_Status; + +typedef enum { + RtemsTaskReqSetAffinity_Post_SetAffinity_Yes, + RtemsTaskReqSetAffinity_Post_SetAffinity_Nop, + RtemsTaskReqSetAffinity_Post_SetAffinity_NA +} RtemsTaskReqSetAffinity_Post_SetAffinity; + +/** + * @brief Test context for spec:/rtems/task/req/set-affinity test case. + */ +typedef struct { + /** + * @brief This member provides the scheduler operation records. + */ + T_scheduler_log_2 scheduler_log;; + + /** + * @brief This member provides the object referenced by the ``cpuset`` + * parameter. + */ + cpu_set_t cpuset_obj[ 2 ]; + + /** + * @brief This member contains the return value of the + * rtems_task_set_affinity() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``cpusetsize`` parameter value. + */ + size_t cpusetsize; + + /** + * @brief This member specifies if the ``cpuset`` parameter value. + */ + cpu_set_t *cpuset; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 3 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqSetAffinity_Context; + +static RtemsTaskReqSetAffinity_Context + RtemsTaskReqSetAffinity_Instance; + +static const char * const RtemsTaskReqSetAffinity_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqSetAffinity_PreDesc_CPUSetKind[] = { + "Askew", + "Huge", + "Supported", + "Unsupported", + "NA" +}; + +static const char * const RtemsTaskReqSetAffinity_PreDesc_CPUSet[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const * const RtemsTaskReqSetAffinity_PreDesc[] = { + RtemsTaskReqSetAffinity_PreDesc_Id, + RtemsTaskReqSetAffinity_PreDesc_CPUSetKind, + RtemsTaskReqSetAffinity_PreDesc_CPUSet, + NULL +}; + +static void RtemsTaskReqSetAffinity_Pre_Id_Prepare( + RtemsTaskReqSetAffinity_Context *ctx, + RtemsTaskReqSetAffinity_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqSetAffinity_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqSetAffinity_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = RTEMS_SELF; + break; + } + + case RtemsTaskReqSetAffinity_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqSetAffinity_Pre_CPUSetKind_Prepare( + RtemsTaskReqSetAffinity_Context *ctx, + RtemsTaskReqSetAffinity_Pre_CPUSetKind state +) +{ + switch ( state ) { + case RtemsTaskReqSetAffinity_Pre_CPUSetKind_Askew: { + /* + * While the ``cpusetsize`` parameter is not an integral multiple of the + * size of long. + */ + ctx->cpusetsize = SIZE_MAX; + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSetKind_Huge: { + /* + * While the ``cpusetsize`` parameter is an integral multiple of the size + * of long, while the ``cpusetsize`` and ``cpuset`` parameter specify a + * processor set which exceeds the implementation limits. + */ + ctx->cpusetsize = sizeof( ctx->cpuset_obj ); + CPU_ZERO( &ctx->cpuset_obj[ 0 ] ); + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSetKind_Supported: { + /* + * While the ``cpusetsize`` parameter is an integral multiple of the size + * of long, while the ``cpusetsize`` and ``cpuset`` parameter specify a + * processor set which is an affinity set supported by the home scheduler + * of the task specified by the ``id`` parameter at some point during the + * rtems_task_set_affinity() call. + */ + ctx->cpusetsize = sizeof( ctx->cpuset_obj[ 0 ] ); + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSetKind_Unsupported: { + /* + * While the ``cpusetsize`` parameter is an integral multiple of the size + * of long, while the ``cpusetsize`` and ``cpuset`` parameter specify a + * processor set which is an affinity set not supported by the home + * scheduler of the task specified by the ``id`` parameter at some point + * during the rtems_task_set_affinity() call. + */ + ctx->cpusetsize = sizeof( ctx->cpuset_obj[ 0 ] ); + CPU_CLR( 0, &ctx->cpuset_obj[ 0 ] ); + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSetKind_NA: + break; + } +} + +static void RtemsTaskReqSetAffinity_Pre_CPUSet_Prepare( + RtemsTaskReqSetAffinity_Context *ctx, + RtemsTaskReqSetAffinity_Pre_CPUSet state +) +{ + switch ( state ) { + case RtemsTaskReqSetAffinity_Pre_CPUSet_Valid: { + /* + * While the ``cpuset`` parameter references an object of type cpu_set_t. + */ + ctx->cpuset = &ctx->cpuset_obj[ 0 ]; + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSet_Null: { + /* + * While the ``cpuset`` parameter is equal to NULL. + */ + ctx->cpuset = NULL; + break; + } + + case RtemsTaskReqSetAffinity_Pre_CPUSet_NA: + break; + } +} + +static void RtemsTaskReqSetAffinity_Post_Status_Check( + RtemsTaskReqSetAffinity_Context *ctx, + RtemsTaskReqSetAffinity_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqSetAffinity_Post_Status_Ok: { + /* + * The return status of rtems_task_set_affinity() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqSetAffinity_Post_Status_InvAddr: { + /* + * The return status of rtems_task_set_affinity() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqSetAffinity_Post_Status_InvId: { + /* + * The return status of rtems_task_set_affinity() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqSetAffinity_Post_Status_InvNum: { + /* + * The return status of rtems_task_set_affinity() shall be + * RTEMS_INVALID_NUMBER. + */ + T_rsc( ctx->status, RTEMS_INVALID_NUMBER ); + break; + } + + case RtemsTaskReqSetAffinity_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqSetAffinity_Post_SetAffinity_Check( + RtemsTaskReqSetAffinity_Context *ctx, + RtemsTaskReqSetAffinity_Post_SetAffinity state +) +{ + switch ( state ) { + case RtemsTaskReqSetAffinity_Post_SetAffinity_Yes: { + /* + * The affinity set of the task specified by the ``id`` parameter shall + * be set with respect to the home scheduler of the task at some point + * during the rtems_task_set_affinity() call. + */ + #if defined(RTEMS_SMP) + T_eq_sz( ctx->scheduler_log.header.recorded, 1 ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].operation, + T_SCHEDULER_SET_AFFINITY + ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].set_affinity.status, + STATUS_SUCCESSFUL + ); + #else + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + #endif + break; + } + + case RtemsTaskReqSetAffinity_Post_SetAffinity_Nop: { + /* + * No task affinity shall be modified by the rtems_task_set_affinity() + * call. + */ + #if defined(RTEMS_SMP) + if ( ctx->scheduler_log.header.recorded == 1 ) { + T_eq_int( + ctx->scheduler_log.events[ 0 ].operation, + T_SCHEDULER_SET_AFFINITY + ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].set_affinity.status, + STATUS_INVALID_NUMBER + ); + } else { + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + } + #else + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + #endif + break; + } + + case RtemsTaskReqSetAffinity_Post_SetAffinity_NA: + break; + } +} + +static void RtemsTaskReqSetAffinity_Prepare( + RtemsTaskReqSetAffinity_Context *ctx +) +{ + CPU_FILL_S( sizeof( ctx->cpuset_obj ), &ctx->cpuset_obj[ 0 ] ); +} + +static void RtemsTaskReqSetAffinity_Action( + RtemsTaskReqSetAffinity_Context *ctx +) +{ + T_scheduler_log *log; + + log = T_scheduler_record_2( &ctx->scheduler_log ); + T_null( log ); + + ctx->status = rtems_task_set_affinity( + ctx->id, + ctx->cpusetsize, + ctx->cpuset + ); + + log = T_scheduler_record( NULL ); + T_eq_ptr( &log->header, &ctx->scheduler_log.header ); +} + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_CPUSetKind_NA : 1; + uint16_t Pre_CPUSet_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_SetAffinity : 2; +} RtemsTaskReqSetAffinity_Entry; + +static const RtemsTaskReqSetAffinity_Entry +RtemsTaskReqSetAffinity_Entries[] = { + { 0, 0, 1, 0, RtemsTaskReqSetAffinity_Post_Status_InvAddr, + RtemsTaskReqSetAffinity_Post_SetAffinity_Nop }, + { 0, 0, 1, 0, RtemsTaskReqSetAffinity_Post_Status_InvId, + RtemsTaskReqSetAffinity_Post_SetAffinity_Nop }, + { 0, 0, 0, 0, RtemsTaskReqSetAffinity_Post_Status_InvNum, + RtemsTaskReqSetAffinity_Post_SetAffinity_Nop }, + { 0, 0, 0, 0, RtemsTaskReqSetAffinity_Post_Status_Ok, + RtemsTaskReqSetAffinity_Post_SetAffinity_Yes } +}; + +static const uint8_t +RtemsTaskReqSetAffinity_Map[] = { + 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 0, 3, 0, 2, 0 +}; + +static size_t RtemsTaskReqSetAffinity_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqSetAffinity_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqSetAffinity_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqSetAffinity_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = RtemsTaskReqSetAffinity_Scope, + .initial_context = &RtemsTaskReqSetAffinity_Instance +}; + +static inline RtemsTaskReqSetAffinity_Entry RtemsTaskReqSetAffinity_GetEntry( + size_t index +) +{ + return RtemsTaskReqSetAffinity_Entries[ + RtemsTaskReqSetAffinity_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqSetAffinity( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqSetAffinity, + &RtemsTaskReqSetAffinity_Fixture +) +{ + RtemsTaskReqSetAffinity_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqSetAffinity_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqSetAffinity_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqSetAffinity_Pre_CPUSetKind_Askew; + ctx->pcs[ 1 ] < RtemsTaskReqSetAffinity_Pre_CPUSetKind_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqSetAffinity_Pre_CPUSet_Valid; + ctx->pcs[ 2 ] < RtemsTaskReqSetAffinity_Pre_CPUSet_NA; + ++ctx->pcs[ 2 ] + ) { + RtemsTaskReqSetAffinity_Entry entry; + size_t pcs[ 3 ]; + + entry = RtemsTaskReqSetAffinity_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_CPUSetKind_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqSetAffinity_Pre_CPUSetKind_NA; + } + + RtemsTaskReqSetAffinity_Prepare( ctx ); + RtemsTaskReqSetAffinity_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqSetAffinity_Pre_CPUSetKind_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqSetAffinity_Pre_CPUSet_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqSetAffinity_Action( ctx ); + RtemsTaskReqSetAffinity_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqSetAffinity_Post_SetAffinity_Check( + ctx, + entry.Post_SetAffinity + ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-set-priority.c b/testsuites/validation/tc-task-set-priority.c new file mode 100644 index 0000000000..c301a01d49 --- /dev/null +++ b/testsuites/validation/tc-task-set-priority.c @@ -0,0 +1,550 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqSetPriority + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqSetPriority \ + * spec:/rtems/task/req/set-priority + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqSetPriority_Pre_Id_Invalid, + RtemsTaskReqSetPriority_Pre_Id_Task, + RtemsTaskReqSetPriority_Pre_Id_NA +} RtemsTaskReqSetPriority_Pre_Id; + +typedef enum { + RtemsTaskReqSetPriority_Pre_NewPriority_Current, + RtemsTaskReqSetPriority_Pre_NewPriority_Valid, + RtemsTaskReqSetPriority_Pre_NewPriority_Invalid, + RtemsTaskReqSetPriority_Pre_NewPriority_NA +} RtemsTaskReqSetPriority_Pre_NewPriority; + +typedef enum { + RtemsTaskReqSetPriority_Pre_OldPriority_Valid, + RtemsTaskReqSetPriority_Pre_OldPriority_Null, + RtemsTaskReqSetPriority_Pre_OldPriority_NA +} RtemsTaskReqSetPriority_Pre_OldPriority; + +typedef enum { + RtemsTaskReqSetPriority_Post_Status_Ok, + RtemsTaskReqSetPriority_Post_Status_InvAddr, + RtemsTaskReqSetPriority_Post_Status_InvId, + RtemsTaskReqSetPriority_Post_Status_InvPrio, + RtemsTaskReqSetPriority_Post_Status_NA +} RtemsTaskReqSetPriority_Post_Status; + +typedef enum { + RtemsTaskReqSetPriority_Post_Priority_Set, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_Priority_NA +} RtemsTaskReqSetPriority_Post_Priority; + +typedef enum { + RtemsTaskReqSetPriority_Post_OldPriorityObj_Set, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_NA +} RtemsTaskReqSetPriority_Post_OldPriorityObj; + +/** + * @brief Test context for spec:/rtems/task/req/set-priority test case. + */ +typedef struct { + /** + * @brief This member contains the worker task identifier. + */ + rtems_id worker_id; + + /** + * @brief This member provides the object referenced by the ``old_priority`` + * parameter. + */ + rtems_task_priority old_priority_obj; + + /** + * @brief This member contains the return value of the + * rtems_task_set_priority() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``new_priority`` parameter value. + */ + rtems_task_priority new_priority; + + /** + * @brief This member specifies if the ``old_priority`` parameter value. + */ + rtems_task_priority *old_priority; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 3 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqSetPriority_Context; + +static RtemsTaskReqSetPriority_Context + RtemsTaskReqSetPriority_Instance; + +static const char * const RtemsTaskReqSetPriority_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqSetPriority_PreDesc_NewPriority[] = { + "Current", + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsTaskReqSetPriority_PreDesc_OldPriority[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const * const RtemsTaskReqSetPriority_PreDesc[] = { + RtemsTaskReqSetPriority_PreDesc_Id, + RtemsTaskReqSetPriority_PreDesc_NewPriority, + RtemsTaskReqSetPriority_PreDesc_OldPriority, + NULL +}; + +static void RtemsTaskReqSetPriority_Pre_Id_Prepare( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqSetPriority_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqSetPriority_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Pre_NewPriority_Prepare( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Pre_NewPriority state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Pre_NewPriority_Current: { + /* + * While the value of the ``new_priority`` parameter is equal to + * RTEMS_CURRENT_PRIORITY. + */ + ctx->new_priority = RTEMS_CURRENT_PRIORITY; + break; + } + + case RtemsTaskReqSetPriority_Pre_NewPriority_Valid: { + /* + * While the value of the ``new_priority`` parameter is not equal to + * RTEMS_CURRENT_PRIORITY, while the value of the ``new_priority`` + * parameter is a valid task priority with respect to the home scheduler + * of the task specified by the ``id`` parameter at some point during the + * rtems_task_set_priority() call. + */ + ctx->new_priority = PRIO_HIGH; + break; + } + + case RtemsTaskReqSetPriority_Pre_NewPriority_Invalid: { + /* + * While the value of the ``new_priority`` parameter is not equal to + * RTEMS_CURRENT_PRIORITY, while the value of the ``new_priority`` + * parameter is an invalid task priority with respect to the home + * scheduler of the task specified by the ``id`` parameter at some point + * during the rtems_task_set_priority() call. + */ + ctx->new_priority = PRIO_INVALID; + break; + } + + case RtemsTaskReqSetPriority_Pre_NewPriority_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Pre_OldPriority_Prepare( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Pre_OldPriority state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Pre_OldPriority_Valid: { + /* + * While the ``old_priority`` parameter references an object of type + * rtems_task_priority. + */ + ctx->old_priority = &ctx->old_priority_obj; + break; + } + + case RtemsTaskReqSetPriority_Pre_OldPriority_Null: { + /* + * While the ``old_priority`` parameter is equal to NULL. + */ + ctx->old_priority = NULL; + break; + } + + case RtemsTaskReqSetPriority_Pre_OldPriority_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Post_Status_Check( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Post_Status_Ok: { + /* + * The return status of rtems_task_set_priority() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqSetPriority_Post_Status_InvAddr: { + /* + * The return status of rtems_task_set_priority() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqSetPriority_Post_Status_InvId: { + /* + * The return status of rtems_task_set_priority() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqSetPriority_Post_Status_InvPrio: { + /* + * The return status of rtems_task_set_priority() shall be + * RTEMS_INVALID_PRIORITY. + */ + T_rsc( ctx->status, RTEMS_INVALID_PRIORITY ); + break; + } + + case RtemsTaskReqSetPriority_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Post_Priority_Check( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Post_Priority state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Post_Priority_Set: { + /* + * The real priority of the task specified by the ``id`` parameter shall + * be set to the value specified by the ``new_priority`` parameter at + * some point during the rtems_task_set_priority() call. + */ + T_eq_u32( GetPriority( ctx->worker_id ), PRIO_HIGH ); + break; + } + + case RtemsTaskReqSetPriority_Post_Priority_Nop: { + /* + * No real priority of a task shall be modified by the + * rtems_task_set_priority() call. + */ + T_eq_u32( GetPriority( ctx->worker_id ), PRIO_LOW ); + break; + } + + case RtemsTaskReqSetPriority_Post_Priority_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Post_OldPriorityObj_Check( + RtemsTaskReqSetPriority_Context *ctx, + RtemsTaskReqSetPriority_Post_OldPriorityObj state +) +{ + switch ( state ) { + case RtemsTaskReqSetPriority_Post_OldPriorityObj_Set: { + /* + * The value of the object referenced by the ``old_priority`` parameter + * shall be set after the return of the rtems_task_set_priority() call to + * the current priority of the task specified by the ``id`` parameter at + * some point during the call and before the real priority is modified by + * the call if it is modified by the call. + */ + T_eq_u32( ctx->old_priority_obj, PRIO_LOW ); + break; + } + + case RtemsTaskReqSetPriority_Post_OldPriorityObj_Nop: { + /* + * Objects referenced by the ``old_priority`` parameter in past calls to + * rtems_task_set_priority() shall not be accessed by the + * rtems_task_set_priority() call. + */ + T_eq_u32( ctx->old_priority_obj, PRIO_INVALID ); + break; + } + + case RtemsTaskReqSetPriority_Post_OldPriorityObj_NA: + break; + } +} + +static void RtemsTaskReqSetPriority_Prepare( + RtemsTaskReqSetPriority_Context *ctx +) +{ + ctx->old_priority_obj = PRIO_INVALID; ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); +} + +static void RtemsTaskReqSetPriority_Action( + RtemsTaskReqSetPriority_Context *ctx +) +{ + ctx->status = rtems_task_set_priority( + ctx->id, + ctx->new_priority, + ctx->old_priority + ); +} + +static void RtemsTaskReqSetPriority_Cleanup( + RtemsTaskReqSetPriority_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_NewPriority_NA : 1; + uint16_t Pre_OldPriority_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_Priority : 2; + uint16_t Post_OldPriorityObj : 2; +} RtemsTaskReqSetPriority_Entry; + +static const RtemsTaskReqSetPriority_Entry +RtemsTaskReqSetPriority_Entries[] = { + { 0, 0, 0, 0, RtemsTaskReqSetPriority_Post_Status_InvId, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Nop }, + { 0, 0, 1, 0, RtemsTaskReqSetPriority_Post_Status_InvAddr, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Nop }, + { 0, 0, 0, 0, RtemsTaskReqSetPriority_Post_Status_InvAddr, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Nop }, + { 0, 0, 0, 0, RtemsTaskReqSetPriority_Post_Status_Ok, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Set }, + { 0, 0, 0, 0, RtemsTaskReqSetPriority_Post_Status_Ok, + RtemsTaskReqSetPriority_Post_Priority_Set, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Set }, + { 0, 0, 0, 0, RtemsTaskReqSetPriority_Post_Status_InvPrio, + RtemsTaskReqSetPriority_Post_Priority_Nop, + RtemsTaskReqSetPriority_Post_OldPriorityObj_Set } +}; + +static const uint8_t +RtemsTaskReqSetPriority_Map[] = { + 0, 1, 0, 1, 0, 1, 3, 2, 4, 2, 5, 2 +}; + +static size_t RtemsTaskReqSetPriority_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqSetPriority_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqSetPriority_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqSetPriority_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = RtemsTaskReqSetPriority_Scope, + .initial_context = &RtemsTaskReqSetPriority_Instance +}; + +static inline RtemsTaskReqSetPriority_Entry RtemsTaskReqSetPriority_GetEntry( + size_t index +) +{ + return RtemsTaskReqSetPriority_Entries[ + RtemsTaskReqSetPriority_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqSetPriority( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqSetPriority, + &RtemsTaskReqSetPriority_Fixture +) +{ + RtemsTaskReqSetPriority_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqSetPriority_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqSetPriority_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqSetPriority_Pre_NewPriority_Current; + ctx->pcs[ 1 ] < RtemsTaskReqSetPriority_Pre_NewPriority_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqSetPriority_Pre_OldPriority_Valid; + ctx->pcs[ 2 ] < RtemsTaskReqSetPriority_Pre_OldPriority_NA; + ++ctx->pcs[ 2 ] + ) { + RtemsTaskReqSetPriority_Entry entry; + size_t pcs[ 3 ]; + + entry = RtemsTaskReqSetPriority_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_NewPriority_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqSetPriority_Pre_NewPriority_NA; + } + + RtemsTaskReqSetPriority_Prepare( ctx ); + RtemsTaskReqSetPriority_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqSetPriority_Pre_NewPriority_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqSetPriority_Pre_OldPriority_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqSetPriority_Action( ctx ); + RtemsTaskReqSetPriority_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqSetPriority_Post_Priority_Check( + ctx, + entry.Post_Priority + ); + RtemsTaskReqSetPriority_Post_OldPriorityObj_Check( + ctx, + entry.Post_OldPriorityObj + ); + RtemsTaskReqSetPriority_Cleanup( ctx ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-set-scheduler.c b/testsuites/validation/tc-task-set-scheduler.c new file mode 100644 index 0000000000..7771cbf629 --- /dev/null +++ b/testsuites/validation/tc-task-set-scheduler.c @@ -0,0 +1,1454 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqSetScheduler + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ts-config.h" +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqSetScheduler \ + * spec:/rtems/task/req/set-scheduler + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqSetScheduler_Pre_TaskId_Task, + RtemsTaskReqSetScheduler_Pre_TaskId_Invalid, + RtemsTaskReqSetScheduler_Pre_TaskId_NA +} RtemsTaskReqSetScheduler_Pre_TaskId; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_Scheduler_Home, + RtemsTaskReqSetScheduler_Pre_Scheduler_Other, + RtemsTaskReqSetScheduler_Pre_Scheduler_NA +} RtemsTaskReqSetScheduler_Pre_Scheduler; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_Yes, + RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_No, + RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_NA +} RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_SchedulerId_Scheduler, + RtemsTaskReqSetScheduler_Pre_SchedulerId_Invalid, + RtemsTaskReqSetScheduler_Pre_SchedulerId_NA +} RtemsTaskReqSetScheduler_Pre_SchedulerId; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_Priority_Valid, + RtemsTaskReqSetScheduler_Pre_Priority_Invalid, + RtemsTaskReqSetScheduler_Pre_Priority_NA +} RtemsTaskReqSetScheduler_Pre_Priority; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_HomePriority_Real, + RtemsTaskReqSetScheduler_Pre_HomePriority_More, + RtemsTaskReqSetScheduler_Pre_HomePriority_NA +} RtemsTaskReqSetScheduler_Pre_HomePriority; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_EligiblePriorities_OnlyOne, + RtemsTaskReqSetScheduler_Pre_EligiblePriorities_More, + RtemsTaskReqSetScheduler_Pre_EligiblePriorities_NA +} RtemsTaskReqSetScheduler_Pre_EligiblePriorities; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_Pinned_Yes, + RtemsTaskReqSetScheduler_Pre_Pinned_No, + RtemsTaskReqSetScheduler_Pre_Pinned_NA +} RtemsTaskReqSetScheduler_Pre_Pinned; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_TaskState_Ready, + RtemsTaskReqSetScheduler_Pre_TaskState_Blocked, + RtemsTaskReqSetScheduler_Pre_TaskState_Enqueued, + RtemsTaskReqSetScheduler_Pre_TaskState_NA +} RtemsTaskReqSetScheduler_Pre_TaskState; + +typedef enum { + RtemsTaskReqSetScheduler_Pre_AffinitySupported_Yes, + RtemsTaskReqSetScheduler_Pre_AffinitySupported_No, + RtemsTaskReqSetScheduler_Pre_AffinitySupported_NA +} RtemsTaskReqSetScheduler_Pre_AffinitySupported; + +typedef enum { + RtemsTaskReqSetScheduler_Post_Status_Ok, + RtemsTaskReqSetScheduler_Post_Status_InvAddr, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Status_InvPrio, + RtemsTaskReqSetScheduler_Post_Status_InUse, + RtemsTaskReqSetScheduler_Post_Status_Unsat, + RtemsTaskReqSetScheduler_Post_Status_NA +} RtemsTaskReqSetScheduler_Post_Status; + +typedef enum { + RtemsTaskReqSetScheduler_Post_Scheduler_Set, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Scheduler_NA +} RtemsTaskReqSetScheduler_Post_Scheduler; + +typedef enum { + RtemsTaskReqSetScheduler_Post_Priority_Set, + RtemsTaskReqSetScheduler_Post_Priority_Nop, + RtemsTaskReqSetScheduler_Post_Priority_NA +} RtemsTaskReqSetScheduler_Post_Priority; + +/** + * @brief Test context for spec:/rtems/task/req/set-scheduler test case. + */ +typedef struct { + /** + * @brief This member contains the runner task identifier. + */ + rtems_id runner_id; + + /** + * @brief This member contains the scheduler A identifier. + */ + rtems_id scheduler_a_id; + + /** + * @brief This member contains the scheduler B identifier. + */ + rtems_id scheduler_b_id; + + /** + * @brief This member contains the scheduler D identifier. + */ + rtems_id scheduler_d_id; + + /** + * @brief This member contains the worker task identifiers. + */ + rtems_id worker_id[ 3 ]; + + /** + * @brief This member contains the mutex identifiers. + */ + rtems_id mutex_id[ 2 ]; + + /** + * @brief If this member is true, then the task shall have an additional + * priority for the home scheduler. + */ + bool additional_home_priority; + + /** + * @brief If this member is true, then the task shall have a second eligible + * scheduler. + */ + bool second_eligible_scheduler; + + /** + * @brief If this member is true, then the task shall be pinned to a + * processor. + */ + bool pinned; + + /** + * @brief If this member is true, then the task shall be blocked. + */ + bool blocked; + + /** + * @brief If this member is true, then the task shall be enqueued on a thread + * queue. + */ + bool enqueued; + + /** + * @brief This member specifies the scheduler identifier to set. + */ + rtems_id scheduler_to_set_id; + + /** + * @brief If this member is true, then the affinity of the task shall be + * supported by the scheduler. + */ + bool affinity_supported; + + /** + * @brief This member contains the return value of the + * rtems_task_set_scheduler() call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``task_id`` parameter value. + */ + rtems_id task_id; + + /** + * @brief This member specifies if the ``scheduler_id`` parameter value. + */ + rtems_id scheduler_id; + + /** + * @brief This member specifies if the ``priority`` parameter value. + */ + rtems_task_priority priority; + + /** + * @brief This member contains the identifier of the new scheduler. + */ + rtems_id new_scheduler;; + + /** + * @brief This member contains the new priorities of the task. + */ + rtems_task_priority new_priority[ 2 ]; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 10 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqSetScheduler_Context; + +static RtemsTaskReqSetScheduler_Context + RtemsTaskReqSetScheduler_Instance; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_TaskId[] = { + "Task", + "Invalid", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_Scheduler[] = { + "Home", + "Other", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_SchedulerHasCPU[] = { + "Yes", + "No", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_SchedulerId[] = { + "Scheduler", + "Invalid", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_Priority[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_HomePriority[] = { + "Real", + "More", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_EligiblePriorities[] = { + "OnlyOne", + "More", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_Pinned[] = { + "Yes", + "No", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_TaskState[] = { + "Ready", + "Blocked", + "Enqueued", + "NA" +}; + +static const char * const RtemsTaskReqSetScheduler_PreDesc_AffinitySupported[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqSetScheduler_PreDesc[] = { + RtemsTaskReqSetScheduler_PreDesc_TaskId, + RtemsTaskReqSetScheduler_PreDesc_Scheduler, + RtemsTaskReqSetScheduler_PreDesc_SchedulerHasCPU, + RtemsTaskReqSetScheduler_PreDesc_SchedulerId, + RtemsTaskReqSetScheduler_PreDesc_Priority, + RtemsTaskReqSetScheduler_PreDesc_HomePriority, + RtemsTaskReqSetScheduler_PreDesc_EligiblePriorities, + RtemsTaskReqSetScheduler_PreDesc_Pinned, + RtemsTaskReqSetScheduler_PreDesc_TaskState, + RtemsTaskReqSetScheduler_PreDesc_AffinitySupported, + NULL +}; + +typedef RtemsTaskReqSetScheduler_Context Context; + +#define EVENT_OBTAIN_MUTEX_A RTEMS_EVENT_0 + +#define EVENT_RELEASE_MUTEX_A RTEMS_EVENT_1 + +#define EVENT_OBTAIN_MUTEX_B RTEMS_EVENT_2 + +#define EVENT_RELEASE_MUTEX_B RTEMS_EVENT_3 + +#define EVENT_PIN RTEMS_EVENT_4 + +#define EVENT_UNPIN RTEMS_EVENT_5 + +#define EVENT_SET_LOW_PRIO RTEMS_EVENT_6 + +#define EVENT_RUNNER_SYNC_0 RTEMS_EVENT_7 + +#define EVENT_RUNNER_SYNC_1 RTEMS_EVENT_8 + +static void Worker( rtems_task_argument arg ) +{ + Context *ctx; + Thread_Control *executing; + + ctx = (Context *) arg; + executing = _Thread_Get_executing(); + + while ( true ) { + rtems_event_set events; + + events = ReceiveAnyEvents(); + + if ( ( events & EVENT_RUNNER_SYNC_0 ) != 0 ) { + SendEvents( ctx->runner_id, EVENT_RUNNER_SYNC_0 ); + } + + if ( ( events & EVENT_OBTAIN_MUTEX_A ) != 0 ) { + ObtainMutex( ctx->mutex_id[ 0 ] ); + } + + if ( ( events & EVENT_RELEASE_MUTEX_A ) != 0 ) { + ReleaseMutex( ctx->mutex_id[ 0 ] ); + } + + if ( ( events & EVENT_OBTAIN_MUTEX_B ) != 0 ) { + ObtainMutex( ctx->mutex_id[ 1 ] ); + } + + if ( ( events & EVENT_RELEASE_MUTEX_B ) != 0 ) { + ReleaseMutex( ctx->mutex_id[ 1 ] ); + } + + if ( ( events & EVENT_PIN ) != 0 ) { + _Thread_Pin( executing ); + } + + if ( ( events & EVENT_UNPIN ) != 0 ) { + _Thread_Unpin( executing, _Per_CPU_Get_snapshot() ); + } + + if ( ( events & EVENT_SET_LOW_PRIO ) != 0 ) { + SetSelfPriority( PRIO_LOW ); + } + + if ( ( events & EVENT_RUNNER_SYNC_1 ) != 0 ) { + SendEvents( ctx->runner_id, EVENT_RUNNER_SYNC_1 ); + } + } +} + +static void RtemsTaskReqSetScheduler_Pre_TaskId_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_TaskId state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_TaskId_Task: { + /* + * While the ``task_id`` parameter is associated with a task. + */ + ctx->task_id = ctx->worker_id[ 0 ]; + break; + } + + case RtemsTaskReqSetScheduler_Pre_TaskId_Invalid: { + /* + * While the ``task_id`` parameter is not associated with a task. + */ + ctx->task_id = INVALID_ID; + break; + } + + case RtemsTaskReqSetScheduler_Pre_TaskId_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_Scheduler_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_Scheduler state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_Scheduler_Home: { + /* + * While the scheduler specified by the ``scheduler_id`` parameter is the + * home scheduler of the task specified by the ``task_id`` parameter. + */ + ctx->scheduler_to_set_id = ctx->scheduler_a_id; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Scheduler_Other: { + /* + * While the scheduler specified by the ``scheduler_id`` parameter is not + * the home scheduler of the task specified by the ``task_id`` parameter. + */ + ctx->scheduler_to_set_id = ctx->scheduler_b_id; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Scheduler_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_Yes: { + /* + * While the scheduler specified by the ``scheduler_id`` parameter owns + * at least one processor. + */ + /* Already set by Scheduler pre-condition */ + break; + } + + case RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_No: { + /* + * While the scheduler specified by the ``scheduler_id`` parameter owns + * no processor. + */ + ctx->scheduler_to_set_id = ctx->scheduler_d_id; + break; + } + + case RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_SchedulerId_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_SchedulerId state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_SchedulerId_Scheduler: { + /* + * While the ``scheduler_id`` parameter is associated with a scheduler. + */ + ctx->scheduler_id = ctx->scheduler_to_set_id; + break; + } + + case RtemsTaskReqSetScheduler_Pre_SchedulerId_Invalid: { + /* + * While the ``scheduler_id`` parameter is not associated with a + * scheduler. + */ + ctx->scheduler_id = INVALID_ID; + break; + } + + case RtemsTaskReqSetScheduler_Pre_SchedulerId_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_Priority_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_Priority state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_Priority_Valid: { + /* + * While the task priority specified by the ``priority`` parameter is + * valid with respect to the scheduler specified by the ``scheduler_id`` + * parameter. + */ + ctx->priority = PRIO_VERY_LOW; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Priority_Invalid: { + /* + * While the task priority specified by the ``priority`` parameter is + * invalid with respect to the scheduler specified by the + * ``scheduler_id`` parameter. + */ + ctx->priority = PRIO_INVALID; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Priority_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_HomePriority_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_HomePriority state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_HomePriority_Real: { + /* + * While the current priority of the task specified by the ``task_id`` + * parameter consists only of the real priority. + */ + ctx->additional_home_priority = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_HomePriority_More: { + /* + * While the current priority of the task specified by the ``task_id`` + * parameter consists of more than the real priority. + */ + ctx->additional_home_priority = true; + break; + } + + case RtemsTaskReqSetScheduler_Pre_HomePriority_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_EligiblePriorities_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_EligiblePriorities state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_EligiblePriorities_OnlyOne: { + /* + * While the set of eligible priorities of the task specified by the + * ``task_id`` parameter consists of exactly the current priority. + */ + ctx->second_eligible_scheduler = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_EligiblePriorities_More: { + /* + * While the set of eligible priorities of the task specified by the + * ``task_id`` parameter consists of more than the current priority. + */ + ctx->second_eligible_scheduler = true; + break; + } + + case RtemsTaskReqSetScheduler_Pre_EligiblePriorities_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_Pinned_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_Pinned state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_Pinned_Yes: { + /* + * While the task specified by the ``task_id`` parameter is pinned. + */ + ctx->pinned = true; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Pinned_No: { + /* + * While the task specified by the ``task_id`` parameter is not pinned. + */ + ctx->pinned = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_Pinned_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_TaskState_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_TaskState state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_TaskState_Ready: { + /* + * While the task specified by the ``task_id`` parameter is ready. + */ + ctx->blocked = false; + ctx->enqueued = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_TaskState_Blocked: { + /* + * While the task specified by the ``task_id`` parameter is blocked, + * while the task specified by the ``task_id`` parameter is not enqueued + * on a wait queue. + */ + ctx->blocked = true; + ctx->enqueued = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_TaskState_Enqueued: { + /* + * While the task specified by the ``task_id`` parameter is blocked, + * while the task specified by the ``task_id`` parameter is enqueued on a + * wait queue. + */ + ctx->blocked = true; + ctx->enqueued = true; + break; + } + + case RtemsTaskReqSetScheduler_Pre_TaskState_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Pre_AffinitySupported_Prepare( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Pre_AffinitySupported state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Pre_AffinitySupported_Yes: { + /* + * While the affinity set of the task specified by the ``task_id`` + * parameter is supported by the scheduler specified by the + * ``scheduler_id`` parameter. + */ + ctx->affinity_supported = true; + break; + } + + case RtemsTaskReqSetScheduler_Pre_AffinitySupported_No: { + /* + * While the affinity set of the task specified by the ``task_id`` + * parameter is not supported by the scheduler specified by the + * ``scheduler_id`` parameter. + */ + ctx->affinity_supported = false; + break; + } + + case RtemsTaskReqSetScheduler_Pre_AffinitySupported_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Post_Status_Check( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Post_Status_Ok: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_InvAddr: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_InvId: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_InvPrio: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_INVALID_PRIORITY. + */ + T_rsc( ctx->status, RTEMS_INVALID_PRIORITY ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_InUse: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_RESOURCE_IN_USE. + */ + T_rsc( ctx->status, RTEMS_RESOURCE_IN_USE ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_Unsat: { + /* + * The return status of rtems_task_set_scheduler() shall be + * RTEMS_UNSATISFIED. + */ + T_rsc( ctx->status, RTEMS_UNSATISFIED ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Post_Scheduler_Check( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Post_Scheduler state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Post_Scheduler_Set: { + /* + * The home scheduler of the task specified by the ``task_id`` parameter + * shall be set to the scheduler specified by the ``scheduler_id`` + * parameter at some point during the rtems_task_set_scheduler() call. + */ + T_eq_u32( ctx->new_scheduler, ctx->scheduler_to_set_id ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Scheduler_Nop: { + /* + * No home scheduler of a task shall be modified by the + * rtems_task_set_scheduler() call. + */ + T_eq_u32( ctx->new_scheduler, ctx->scheduler_a_id ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Scheduler_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Post_Priority_Check( + RtemsTaskReqSetScheduler_Context *ctx, + RtemsTaskReqSetScheduler_Post_Priority state +) +{ + switch ( state ) { + case RtemsTaskReqSetScheduler_Post_Priority_Set: { + /* + * The real priority of the task specified by the ``task_id`` parameter + * shall be set to the priority specified by the ``priority`` parameter + * at some point during the rtems_task_set_scheduler() call. + */ + if ( ctx->scheduler_to_set_id == ctx->scheduler_a_id ) { + T_eq_u32( ctx->new_priority[ 0 ], PRIO_VERY_LOW ); + T_eq_u32( ctx->new_priority[ 1 ], PRIO_INVALID ); + } else { + T_eq_u32( ctx->new_priority[ 0 ], PRIO_INVALID ); + T_eq_u32( ctx->new_priority[ 1 ], PRIO_VERY_LOW ); + } + break; + } + + case RtemsTaskReqSetScheduler_Post_Priority_Nop: { + /* + * No task priority shall be modified by the rtems_task_set_scheduler() + * call. + */ + if ( ctx->blocked ) { + T_eq_u32( ctx->new_priority[ 0 ], PRIO_HIGH ); + } else { + T_eq_u32( ctx->new_priority[ 0 ], PRIO_LOW ); + } + + T_eq_u32( ctx->new_priority[ 1 ], PRIO_INVALID ); + break; + } + + case RtemsTaskReqSetScheduler_Post_Priority_NA: + break; + } +} + +static void RtemsTaskReqSetScheduler_Setup( + RtemsTaskReqSetScheduler_Context *ctx +) +{ + rtems_status_code sc; + size_t i; + + memset( ctx, 0, sizeof( *ctx ) ); + ctx->runner_id = rtems_task_self(); + SetSelfPriority( PRIO_NORMAL ); + + sc = rtems_scheduler_ident( + TEST_SCHEDULER_A_NAME, + &ctx->scheduler_a_id + ); + T_rsc_success( sc ); + + for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->mutex_id ); ++i ) { + ctx->mutex_id[ i ] = CreateMutex(); + } + + for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->worker_id ); ++i ) { + ctx->worker_id[ i ] = CreateTask( "WORK", PRIO_HIGH - i ); + StartTask( ctx->worker_id[ i ], Worker, ctx ); + } + + #if defined(RTEMS_SMP) + sc = rtems_scheduler_ident( TEST_SCHEDULER_B_NAME, &ctx->scheduler_b_id ); + T_rsc_success( sc ); + + sc = rtems_scheduler_ident( TEST_SCHEDULER_D_NAME, &ctx->scheduler_d_id ); + T_rsc_success( sc ); + + SetScheduler( ctx->worker_id[ 2 ], ctx->scheduler_b_id, PRIO_NORMAL ); + #else + ctx->scheduler_b_id = INVALID_ID; + #endif +} + +static void RtemsTaskReqSetScheduler_Setup_Wrap( void *arg ) +{ + RtemsTaskReqSetScheduler_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqSetScheduler_Setup( ctx ); +} + +static void RtemsTaskReqSetScheduler_Teardown( + RtemsTaskReqSetScheduler_Context *ctx +) +{ + size_t i; + + for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->worker_id ); ++i ) { + DeleteTask( ctx->worker_id[ i ] ); + } + + for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->mutex_id ); ++i ) { + DeleteMutex( ctx->mutex_id[ i ] ); + } + + RestoreRunnerPriority(); +} + +static void RtemsTaskReqSetScheduler_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqSetScheduler_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqSetScheduler_Teardown( ctx ); +} + +static void RtemsTaskReqSetScheduler_Action( + RtemsTaskReqSetScheduler_Context *ctx +) +{ + rtems_status_code sc; + + if ( ctx->additional_home_priority || ctx->second_eligible_scheduler ) { + SendEvents( ctx->worker_id[ 0 ], EVENT_OBTAIN_MUTEX_A ); + + if ( ctx->additional_home_priority ) { + SendEvents( ctx->worker_id[ 1 ], EVENT_OBTAIN_MUTEX_A ); + } + + if ( ctx->second_eligible_scheduler ) { + SendEvents( + ctx->worker_id[ 2 ], + EVENT_RUNNER_SYNC_0 | EVENT_OBTAIN_MUTEX_A + ); + ReceiveAllEvents( EVENT_RUNNER_SYNC_0 ); + WaitForExecutionStop( ctx->worker_id[ 2 ] ); + } + } + + if ( ctx->blocked && ctx->enqueued ) { + ObtainMutex( ctx->mutex_id[ 1 ] ); + SendEvents( ctx->worker_id[ 0 ], EVENT_OBTAIN_MUTEX_B ); + } + + if ( !ctx->affinity_supported ) { + SetAffinityOne( ctx->worker_id[ 0 ], 0 ); + } + + if ( ctx->pinned ) { + SendEvents( ctx->worker_id[ 0 ], EVENT_PIN ); + } + + if ( !ctx->blocked ) { + SendEvents( ctx->worker_id[ 0 ], EVENT_SET_LOW_PRIO ); + } + + ctx->status = rtems_task_set_scheduler( + ctx->task_id, + ctx->scheduler_id, + ctx->priority + ); + + ctx->new_scheduler = GetScheduler( ctx->worker_id[ 0 ] ); + + if ( ctx->pinned ) { + SendEvents( ctx->worker_id[ 0 ], EVENT_UNPIN ); + } + + if ( !ctx->affinity_supported ) { + SetAffinityAll( ctx->worker_id[ 0 ] ); + } + + if ( ctx->blocked && ctx->enqueued ) { + ReleaseMutex( ctx->mutex_id[ 1 ] ); + SendEvents( ctx->worker_id[ 0 ], EVENT_RELEASE_MUTEX_B ); + } + + if ( ctx->additional_home_priority || ctx->second_eligible_scheduler ) { + SendEvents( ctx->worker_id[ 0 ], EVENT_RELEASE_MUTEX_A ); + + if ( ctx->additional_home_priority ) { + SendEvents( ctx->worker_id[ 1 ], EVENT_RELEASE_MUTEX_A ); + } + + if ( ctx->second_eligible_scheduler ) { + SendEvents( + ctx->worker_id[ 2 ], + EVENT_RELEASE_MUTEX_A | EVENT_RUNNER_SYNC_1 + ); + ReceiveAllEvents( EVENT_RUNNER_SYNC_1 ); + } + } + + sc = rtems_task_get_priority( + ctx->worker_id[ 0 ], + ctx->scheduler_a_id, + &ctx->new_priority[ 0 ] + ); + + if ( sc == RTEMS_NOT_DEFINED ) { + ctx->new_priority[ 0 ] = PRIO_INVALID; + } else { + T_rsc_success( sc ); + } + + #if defined(RTEMS_SMP) + sc = rtems_task_get_priority( + ctx->worker_id[ 0 ], + ctx->scheduler_b_id, + &ctx->new_priority[ 1 ] + ); + + if ( sc == RTEMS_NOT_DEFINED ) { + ctx->new_priority[ 1 ] = PRIO_INVALID; + } else { + T_rsc_success( sc ); + } + #else + ctx->new_priority[ 1 ] = PRIO_INVALID; + #endif + + if ( ctx->status == RTEMS_SUCCESSFUL ) { + SetScheduler( ctx->worker_id[ 0 ], ctx->scheduler_a_id, PRIO_HIGH ); + } else if ( !ctx->blocked ) { + SetPriority( ctx->worker_id[ 0 ], PRIO_HIGH ); + } +} + +typedef struct { + uint32_t Skip : 1; + uint32_t Pre_TaskId_NA : 1; + uint32_t Pre_Scheduler_NA : 1; + uint32_t Pre_SchedulerHasCPU_NA : 1; + uint32_t Pre_SchedulerId_NA : 1; + uint32_t Pre_Priority_NA : 1; + uint32_t Pre_HomePriority_NA : 1; + uint32_t Pre_EligiblePriorities_NA : 1; + uint32_t Pre_Pinned_NA : 1; + uint32_t Pre_TaskState_NA : 1; + uint32_t Pre_AffinitySupported_NA : 1; + uint32_t Post_Status : 3; + uint32_t Post_Scheduler : 2; + uint32_t Post_Priority : 2; +} RtemsTaskReqSetScheduler_Entry; + +static const RtemsTaskReqSetScheduler_Entry +RtemsTaskReqSetScheduler_Entries[] = { +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + RtemsTaskReqSetScheduler_Post_Status_InvPrio, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + RtemsTaskReqSetScheduler_Post_Status_InvPrio, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + RtemsTaskReqSetScheduler_Post_Status_InUse, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif + { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, + { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + RtemsTaskReqSetScheduler_Post_Status_InvPrio, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA }, +#else + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + RtemsTaskReqSetScheduler_Post_Status_Unsat, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, +#endif + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + RtemsTaskReqSetScheduler_Post_Status_InvId, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + RtemsTaskReqSetScheduler_Post_Status_InvPrio, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + RtemsTaskReqSetScheduler_Post_Status_InUse, + RtemsTaskReqSetScheduler_Post_Scheduler_Nop, + RtemsTaskReqSetScheduler_Post_Priority_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_Ok, + RtemsTaskReqSetScheduler_Post_Scheduler_Set, + RtemsTaskReqSetScheduler_Post_Priority_Set }, +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_NA, + RtemsTaskReqSetScheduler_Post_Scheduler_NA, + RtemsTaskReqSetScheduler_Post_Priority_NA } +#else + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsTaskReqSetScheduler_Post_Status_Ok, + RtemsTaskReqSetScheduler_Post_Scheduler_Set, + RtemsTaskReqSetScheduler_Post_Priority_Set } +#endif +}; + +static const uint8_t +RtemsTaskReqSetScheduler_Map[] = { + 7, 0, 7, 0, 7, 0, 15, 3, 15, 3, 14, 3, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, + 0, 7, 0, 7, 0, 14, 3, 14, 3, 14, 3, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 4, 0, + 4, 0, 4, 0, 10, 3, 10, 3, 10, 3, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 10, 3, 10, 3, 10, 3, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 1, 0, 1, 0, + 1, 0, 8, 3, 8, 3, 8, 3, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 8, 3, 8, 3, 8, 3, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 8, 3, + 8, 3, 8, 3, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 8, 3, 8, 3, + 8, 3, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 7, 7, 7, 7, 16, 11, 16, 11, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 11, 11, 11, 11, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 0, 5, 0, + 5, 0, 12, 3, 12, 3, 12, 3, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, + 0, 12, 3, 12, 3, 12, 3, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 6, 0, 6, 0, 6, 0, + 13, 3, 13, 3, 13, 3, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, + 13, 3, 13, 3, 13, 3, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 2, 0, 2, 0, 2, 0, 9, + 3, 9, 3, 9, 3, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 9, 3, 9, + 3, 9, 3, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 9, 3, 9, 3, 9, + 3, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 9, 3, 9, 3, 9, 3, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static size_t RtemsTaskReqSetScheduler_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqSetScheduler_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqSetScheduler_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqSetScheduler_Fixture = { + .setup = RtemsTaskReqSetScheduler_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqSetScheduler_Teardown_Wrap, + .scope = RtemsTaskReqSetScheduler_Scope, + .initial_context = &RtemsTaskReqSetScheduler_Instance +}; + +static inline RtemsTaskReqSetScheduler_Entry RtemsTaskReqSetScheduler_GetEntry( + size_t index +) +{ + return RtemsTaskReqSetScheduler_Entries[ + RtemsTaskReqSetScheduler_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqSetScheduler( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqSetScheduler, + &RtemsTaskReqSetScheduler_Fixture +) +{ + RtemsTaskReqSetScheduler_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqSetScheduler_Pre_TaskId_Task; + ctx->pcs[ 0 ] < RtemsTaskReqSetScheduler_Pre_TaskId_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqSetScheduler_Pre_Scheduler_Home; + ctx->pcs[ 1 ] < RtemsTaskReqSetScheduler_Pre_Scheduler_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_Yes; + ctx->pcs[ 2 ] < RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_NA; + ++ctx->pcs[ 2 ] + ) { + for ( + ctx->pcs[ 3 ] = RtemsTaskReqSetScheduler_Pre_SchedulerId_Scheduler; + ctx->pcs[ 3 ] < RtemsTaskReqSetScheduler_Pre_SchedulerId_NA; + ++ctx->pcs[ 3 ] + ) { + for ( + ctx->pcs[ 4 ] = RtemsTaskReqSetScheduler_Pre_Priority_Valid; + ctx->pcs[ 4 ] < RtemsTaskReqSetScheduler_Pre_Priority_NA; + ++ctx->pcs[ 4 ] + ) { + for ( + ctx->pcs[ 5 ] = RtemsTaskReqSetScheduler_Pre_HomePriority_Real; + ctx->pcs[ 5 ] < RtemsTaskReqSetScheduler_Pre_HomePriority_NA; + ++ctx->pcs[ 5 ] + ) { + for ( + ctx->pcs[ 6 ] = RtemsTaskReqSetScheduler_Pre_EligiblePriorities_OnlyOne; + ctx->pcs[ 6 ] < RtemsTaskReqSetScheduler_Pre_EligiblePriorities_NA; + ++ctx->pcs[ 6 ] + ) { + for ( + ctx->pcs[ 7 ] = RtemsTaskReqSetScheduler_Pre_Pinned_Yes; + ctx->pcs[ 7 ] < RtemsTaskReqSetScheduler_Pre_Pinned_NA; + ++ctx->pcs[ 7 ] + ) { + for ( + ctx->pcs[ 8 ] = RtemsTaskReqSetScheduler_Pre_TaskState_Ready; + ctx->pcs[ 8 ] < RtemsTaskReqSetScheduler_Pre_TaskState_NA; + ++ctx->pcs[ 8 ] + ) { + for ( + ctx->pcs[ 9 ] = RtemsTaskReqSetScheduler_Pre_AffinitySupported_Yes; + ctx->pcs[ 9 ] < RtemsTaskReqSetScheduler_Pre_AffinitySupported_NA; + ++ctx->pcs[ 9 ] + ) { + RtemsTaskReqSetScheduler_Entry entry; + size_t pcs[ 10 ]; + + entry = RtemsTaskReqSetScheduler_GetEntry( index ); + ++index; + + if ( entry.Skip ) { + continue; + } + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Scheduler_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqSetScheduler_Pre_Scheduler_NA; + } + + if ( entry.Pre_SchedulerHasCPU_NA ) { + ctx->pcs[ 2 ] = RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_NA; + } + + if ( entry.Pre_Priority_NA ) { + ctx->pcs[ 4 ] = RtemsTaskReqSetScheduler_Pre_Priority_NA; + } + + if ( entry.Pre_HomePriority_NA ) { + ctx->pcs[ 5 ] = RtemsTaskReqSetScheduler_Pre_HomePriority_NA; + } + + if ( entry.Pre_EligiblePriorities_NA ) { + ctx->pcs[ 6 ] = RtemsTaskReqSetScheduler_Pre_EligiblePriorities_NA; + } + + if ( entry.Pre_Pinned_NA ) { + ctx->pcs[ 7 ] = RtemsTaskReqSetScheduler_Pre_Pinned_NA; + } + + if ( entry.Pre_TaskState_NA ) { + ctx->pcs[ 8 ] = RtemsTaskReqSetScheduler_Pre_TaskState_NA; + } + + if ( entry.Pre_AffinitySupported_NA ) { + ctx->pcs[ 9 ] = RtemsTaskReqSetScheduler_Pre_AffinitySupported_NA; + } + + RtemsTaskReqSetScheduler_Pre_TaskId_Prepare( + ctx, + ctx->pcs[ 0 ] + ); + RtemsTaskReqSetScheduler_Pre_Scheduler_Prepare( + ctx, + ctx->pcs[ 1 ] + ); + RtemsTaskReqSetScheduler_Pre_SchedulerHasCPU_Prepare( + ctx, + ctx->pcs[ 2 ] + ); + RtemsTaskReqSetScheduler_Pre_SchedulerId_Prepare( + ctx, + ctx->pcs[ 3 ] + ); + RtemsTaskReqSetScheduler_Pre_Priority_Prepare( + ctx, + ctx->pcs[ 4 ] + ); + RtemsTaskReqSetScheduler_Pre_HomePriority_Prepare( + ctx, + ctx->pcs[ 5 ] + ); + RtemsTaskReqSetScheduler_Pre_EligiblePriorities_Prepare( + ctx, + ctx->pcs[ 6 ] + ); + RtemsTaskReqSetScheduler_Pre_Pinned_Prepare( + ctx, + ctx->pcs[ 7 ] + ); + RtemsTaskReqSetScheduler_Pre_TaskState_Prepare( + ctx, + ctx->pcs[ 8 ] + ); + RtemsTaskReqSetScheduler_Pre_AffinitySupported_Prepare( + ctx, + ctx->pcs[ 9 ] + ); + RtemsTaskReqSetScheduler_Action( ctx ); + RtemsTaskReqSetScheduler_Post_Status_Check( + ctx, + entry.Post_Status + ); + RtemsTaskReqSetScheduler_Post_Scheduler_Check( + ctx, + entry.Post_Scheduler + ); + RtemsTaskReqSetScheduler_Post_Priority_Check( + ctx, + entry.Post_Priority + ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } + } + } + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-start.c b/testsuites/validation/tc-task-start.c new file mode 100644 index 0000000000..b90df1b4d8 --- /dev/null +++ b/testsuites/validation/tc-task-start.c @@ -0,0 +1,822 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqStart + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqStart spec:/rtems/task/req/start + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqStart_Pre_Id_Invalid, + RtemsTaskReqStart_Pre_Id_Task, + RtemsTaskReqStart_Pre_Id_NA +} RtemsTaskReqStart_Pre_Id; + +typedef enum { + RtemsTaskReqStart_Pre_EntryPoint_Valid, + RtemsTaskReqStart_Pre_EntryPoint_Null, + RtemsTaskReqStart_Pre_EntryPoint_NA +} RtemsTaskReqStart_Pre_EntryPoint; + +typedef enum { + RtemsTaskReqStart_Pre_Argument_Pointer, + RtemsTaskReqStart_Pre_Argument_Number, + RtemsTaskReqStart_Pre_Argument_NA +} RtemsTaskReqStart_Pre_Argument; + +typedef enum { + RtemsTaskReqStart_Pre_Dormant_Yes, + RtemsTaskReqStart_Pre_Dormant_No, + RtemsTaskReqStart_Pre_Dormant_NA +} RtemsTaskReqStart_Pre_Dormant; + +typedef enum { + RtemsTaskReqStart_Pre_Suspended_Yes, + RtemsTaskReqStart_Pre_Suspended_No, + RtemsTaskReqStart_Pre_Suspended_NA +} RtemsTaskReqStart_Pre_Suspended; + +typedef enum { + RtemsTaskReqStart_Post_Status_Ok, + RtemsTaskReqStart_Post_Status_InvAddr, + RtemsTaskReqStart_Post_Status_InvId, + RtemsTaskReqStart_Post_Status_IncStat, + RtemsTaskReqStart_Post_Status_NA +} RtemsTaskReqStart_Post_Status; + +typedef enum { + RtemsTaskReqStart_Post_EntryPoint_Set, + RtemsTaskReqStart_Post_EntryPoint_Nop, + RtemsTaskReqStart_Post_EntryPoint_NA +} RtemsTaskReqStart_Post_EntryPoint; + +typedef enum { + RtemsTaskReqStart_Post_Argument_Set, + RtemsTaskReqStart_Post_Argument_Nop, + RtemsTaskReqStart_Post_Argument_NA +} RtemsTaskReqStart_Post_Argument; + +typedef enum { + RtemsTaskReqStart_Post_Unblock_Yes, + RtemsTaskReqStart_Post_Unblock_Nop, + RtemsTaskReqStart_Post_Unblock_NA +} RtemsTaskReqStart_Post_Unblock; + +typedef enum { + RtemsTaskReqStart_Post_StartExtensions_Yes, + RtemsTaskReqStart_Post_StartExtensions_Nop, + RtemsTaskReqStart_Post_StartExtensions_NA +} RtemsTaskReqStart_Post_StartExtensions; + +/** + * @brief Test context for spec:/rtems/task/req/start test case. + */ +typedef struct { + /** + * @brief This member provides the scheduler operation records. + */ + T_scheduler_log_2 scheduler_log; + + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief This member contains the identifier of the test user extensions. + */ + rtems_id extension_id; + + /** + * @brief This member contains the count of thread start extension calls. + */ + uint32_t start_extension_calls; + + /** + * @brief This member contains the actual argument passed to the entry point. + */ + rtems_task_argument actual_argument; + + /** + * @brief This member contains the entry point counter. + */ + uint32_t counter; + + /** + * @brief If this member is true, then the worker is started before the + * rtems_task_start() call. + */ + bool start; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_start() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the rtems_task_start() + * call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member specifies if the ``entry_point`` parameter value. + */ + rtems_task_entry entry_point; + + /** + * @brief This member specifies if the ``argument`` parameter value. + */ + rtems_task_argument argument; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 5 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqStart_Context; + +static RtemsTaskReqStart_Context + RtemsTaskReqStart_Instance; + +static const char * const RtemsTaskReqStart_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqStart_PreDesc_EntryPoint[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsTaskReqStart_PreDesc_Argument[] = { + "Pointer", + "Number", + "NA" +}; + +static const char * const RtemsTaskReqStart_PreDesc_Dormant[] = { + "Yes", + "No", + "NA" +}; + +static const char * const RtemsTaskReqStart_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqStart_PreDesc[] = { + RtemsTaskReqStart_PreDesc_Id, + RtemsTaskReqStart_PreDesc_EntryPoint, + RtemsTaskReqStart_PreDesc_Argument, + RtemsTaskReqStart_PreDesc_Dormant, + RtemsTaskReqStart_PreDesc_Suspended, + NULL +}; + +typedef RtemsTaskReqStart_Context Context; + +static void WorkerA( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = &RtemsTaskReqStart_Instance; + + while ( true ) { + ctx->actual_argument += arg; + ++ctx->counter; + Yield(); + } +} + +static void WorkerB( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = &RtemsTaskReqStart_Instance; + + while ( true ) { + ctx->actual_argument += arg; + Yield(); + } +} + +static void ThreadStart( rtems_tcb *executing, rtems_tcb *started ) +{ + (void) executing; + (void) started; + + ++RtemsTaskReqStart_Instance.start_extension_calls; +} + +static const rtems_extensions_table extensions = { + .thread_start = ThreadStart +}; + +static void RtemsTaskReqStart_Pre_Id_Prepare( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqStart_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqStart_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqStart_Pre_EntryPoint_Prepare( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Pre_EntryPoint state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Pre_EntryPoint_Valid: { + /* + * While the task entry point specified by the ``entry_point`` parameter + * is valid. + */ + ctx->entry_point = WorkerA; + break; + } + + case RtemsTaskReqStart_Pre_EntryPoint_Null: { + /* + * While the task entry point specified by the ``entry_point`` parameter + * is equal to NULL. + */ + ctx->entry_point = NULL; + break; + } + + case RtemsTaskReqStart_Pre_EntryPoint_NA: + break; + } +} + +static void RtemsTaskReqStart_Pre_Argument_Prepare( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Pre_Argument state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Pre_Argument_Pointer: { + /* + * While the entry point argument specified by the ``argument`` parameter + * is a pointer. + */ + ctx->argument = (rtems_task_argument) ctx; + break; + } + + case RtemsTaskReqStart_Pre_Argument_Number: { + /* + * While the entry point argument specified by the ``argument`` parameter + * is a 32-bit number. + */ + ctx->argument = UINT32_C( 0x87654321 ); + break; + } + + case RtemsTaskReqStart_Pre_Argument_NA: + break; + } +} + +static void RtemsTaskReqStart_Pre_Dormant_Prepare( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Pre_Dormant state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Pre_Dormant_Yes: { + /* + * While the task specified by the ``id`` parameter is dormant. + */ + ctx->start = false; + break; + } + + case RtemsTaskReqStart_Pre_Dormant_No: { + /* + * While the task specified by the ``id`` parameter is not dormant. + */ + ctx->start = true; + break; + } + + case RtemsTaskReqStart_Pre_Dormant_NA: + break; + } +} + +static void RtemsTaskReqStart_Pre_Suspended_Prepare( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqStart_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqStart_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqStart_Post_Status_Check( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Post_Status_Ok: { + /* + * The return status of rtems_task_start() shall be RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqStart_Post_Status_InvAddr: { + /* + * The return status of rtems_task_start() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsTaskReqStart_Post_Status_InvId: { + /* + * The return status of rtems_task_start() shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqStart_Post_Status_IncStat: { + /* + * The return status of rtems_task_start() shall be + * RTEMS_INCORRECT_STATE. + */ + T_rsc( ctx->status, RTEMS_INCORRECT_STATE ); + break; + } + + case RtemsTaskReqStart_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqStart_Post_EntryPoint_Check( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Post_EntryPoint state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Post_EntryPoint_Set: { + /* + * The entry point of the task specified by the ``id`` parameter shall be + * set to the function specified by the ``entry_point`` parameter before + * the task is unblocked by the rtems_task_start() call. + */ + T_eq_u32( ctx->counter, 1 ); + break; + } + + case RtemsTaskReqStart_Post_EntryPoint_Nop: { + /* + * No entry point of a task shall be modified by the rtems_task_start() + * call. + */ + T_eq_u32( ctx->counter, 0 ); + break; + } + + case RtemsTaskReqStart_Post_EntryPoint_NA: + break; + } +} + +static void RtemsTaskReqStart_Post_Argument_Check( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Post_Argument state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Post_Argument_Set: { + /* + * The entry point argument of the task specified by the ``id`` parameter + * shall be set to the value specified by the ``argument`` parameter + * before the task is unblocked by the rtems_task_start() call. + */ + T_eq_u32( ctx->actual_argument, ctx->argument ); + break; + } + + case RtemsTaskReqStart_Post_Argument_Nop: { + /* + * No entry point argument of a task shall be modified by the + * rtems_task_start() call. + */ + T_eq_u32( ctx->actual_argument, 0 ); + break; + } + + case RtemsTaskReqStart_Post_Argument_NA: + break; + } +} + +static void RtemsTaskReqStart_Post_Unblock_Check( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Post_Unblock state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Post_Unblock_Yes: { + /* + * The task specified by the ``id`` parameter shall be unblocked by the + * rtems_task_start() call. + */ + T_eq_sz( ctx->scheduler_log.header.recorded, 1 ); + T_eq_int( + ctx->scheduler_log.events[ 0 ].operation, + T_SCHEDULER_UNBLOCK + ); + break; + } + + case RtemsTaskReqStart_Post_Unblock_Nop: { + /* + * No task shall be unblocked by the rtems_task_start() call. + */ + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + break; + } + + case RtemsTaskReqStart_Post_Unblock_NA: + break; + } +} + +static void RtemsTaskReqStart_Post_StartExtensions_Check( + RtemsTaskReqStart_Context *ctx, + RtemsTaskReqStart_Post_StartExtensions state +) +{ + switch ( state ) { + case RtemsTaskReqStart_Post_StartExtensions_Yes: { + /* + * The thread start user extensions shall be invoked by the + * rtems_task_start() call. + */ + T_eq_u32( ctx->start_extension_calls, 1 ); + break; + } + + case RtemsTaskReqStart_Post_StartExtensions_Nop: { + /* + * The thread start user extensions shall not be invoked by the + * rtems_task_start() call. + */ + T_eq_u32( ctx->start_extension_calls, 0 ); + break; + } + + case RtemsTaskReqStart_Post_StartExtensions_NA: + break; + } +} + +static void RtemsTaskReqStart_Setup( RtemsTaskReqStart_Context *ctx ) +{ + rtems_status_code sc; + + sc = rtems_extension_create( + rtems_build_name( 'T', 'E', 'S', 'T' ), + &extensions, + &ctx->extension_id + ); + T_rsc_success( sc ); +} + +static void RtemsTaskReqStart_Setup_Wrap( void *arg ) +{ + RtemsTaskReqStart_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqStart_Setup( ctx ); +} + +static void RtemsTaskReqStart_Teardown( RtemsTaskReqStart_Context *ctx ) +{ + rtems_status_code sc; + + sc = rtems_extension_delete( ctx->extension_id ); + T_rsc_success( sc ); +} + +static void RtemsTaskReqStart_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqStart_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqStart_Teardown( ctx ); +} + +static void RtemsTaskReqStart_Prepare( RtemsTaskReqStart_Context *ctx ) +{ + ctx->actual_argument = 0; + ctx->counter = 0; + ctx->worker_id = CreateTask( "WORK", PRIO_DEFAULT ); +} + +static void RtemsTaskReqStart_Action( RtemsTaskReqStart_Context *ctx ) +{ + T_scheduler_log *log; + + if ( ctx->start ) { + StartTask( ctx->worker_id, WorkerB, 0 ); + } + + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->start_extension_calls = 0; + + log = T_scheduler_record_2( &ctx->scheduler_log ); + T_null( log ); + + ctx->status = rtems_task_start( ctx->id, ctx->entry_point, ctx->argument ); + + log = T_scheduler_record( NULL ); + T_eq_ptr( &log->header, &ctx->scheduler_log.header ); + + Yield(); +} + +static void RtemsTaskReqStart_Cleanup( RtemsTaskReqStart_Context *ctx ) +{ + DeleteTask( ctx->worker_id ); +} + +typedef struct { + uint32_t Skip : 1; + uint32_t Pre_Id_NA : 1; + uint32_t Pre_EntryPoint_NA : 1; + uint32_t Pre_Argument_NA : 1; + uint32_t Pre_Dormant_NA : 1; + uint32_t Pre_Suspended_NA : 1; + uint32_t Post_Status : 3; + uint32_t Post_EntryPoint : 2; + uint32_t Post_Argument : 2; + uint32_t Post_Unblock : 2; + uint32_t Post_StartExtensions : 2; +} RtemsTaskReqStart_Entry; + +static const RtemsTaskReqStart_Entry +RtemsTaskReqStart_Entries[] = { + { 0, 0, 0, 0, 0, 0, RtemsTaskReqStart_Post_Status_InvAddr, + RtemsTaskReqStart_Post_EntryPoint_Nop, RtemsTaskReqStart_Post_Argument_Nop, + RtemsTaskReqStart_Post_Unblock_Nop, + RtemsTaskReqStart_Post_StartExtensions_Nop }, + { 0, 0, 0, 0, 1, 1, RtemsTaskReqStart_Post_Status_InvId, + RtemsTaskReqStart_Post_EntryPoint_Nop, RtemsTaskReqStart_Post_Argument_Nop, + RtemsTaskReqStart_Post_Unblock_Nop, + RtemsTaskReqStart_Post_StartExtensions_Nop }, + { 0, 0, 0, 0, 0, 0, RtemsTaskReqStart_Post_Status_Ok, + RtemsTaskReqStart_Post_EntryPoint_Set, RtemsTaskReqStart_Post_Argument_Set, + RtemsTaskReqStart_Post_Unblock_Yes, + RtemsTaskReqStart_Post_StartExtensions_Yes }, + { 0, 0, 0, 0, 0, 0, RtemsTaskReqStart_Post_Status_IncStat, + RtemsTaskReqStart_Post_EntryPoint_Nop, RtemsTaskReqStart_Post_Argument_Nop, + RtemsTaskReqStart_Post_Unblock_Nop, + RtemsTaskReqStart_Post_StartExtensions_Nop } +}; + +static const uint8_t +RtemsTaskReqStart_Map[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 2, 2, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0 +}; + +static size_t RtemsTaskReqStart_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqStart_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqStart_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqStart_Fixture = { + .setup = RtemsTaskReqStart_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqStart_Teardown_Wrap, + .scope = RtemsTaskReqStart_Scope, + .initial_context = &RtemsTaskReqStart_Instance +}; + +static inline RtemsTaskReqStart_Entry RtemsTaskReqStart_GetEntry( + size_t index +) +{ + return RtemsTaskReqStart_Entries[ + RtemsTaskReqStart_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqStart( void ) + */ +T_TEST_CASE_FIXTURE( RtemsTaskReqStart, &RtemsTaskReqStart_Fixture ) +{ + RtemsTaskReqStart_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqStart_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqStart_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqStart_Pre_EntryPoint_Valid; + ctx->pcs[ 1 ] < RtemsTaskReqStart_Pre_EntryPoint_NA; + ++ctx->pcs[ 1 ] + ) { + for ( + ctx->pcs[ 2 ] = RtemsTaskReqStart_Pre_Argument_Pointer; + ctx->pcs[ 2 ] < RtemsTaskReqStart_Pre_Argument_NA; + ++ctx->pcs[ 2 ] + ) { + for ( + ctx->pcs[ 3 ] = RtemsTaskReqStart_Pre_Dormant_Yes; + ctx->pcs[ 3 ] < RtemsTaskReqStart_Pre_Dormant_NA; + ++ctx->pcs[ 3 ] + ) { + for ( + ctx->pcs[ 4 ] = RtemsTaskReqStart_Pre_Suspended_Yes; + ctx->pcs[ 4 ] < RtemsTaskReqStart_Pre_Suspended_NA; + ++ctx->pcs[ 4 ] + ) { + RtemsTaskReqStart_Entry entry; + size_t pcs[ 5 ]; + + entry = RtemsTaskReqStart_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Dormant_NA ) { + ctx->pcs[ 3 ] = RtemsTaskReqStart_Pre_Dormant_NA; + } + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 4 ] = RtemsTaskReqStart_Pre_Suspended_NA; + } + + RtemsTaskReqStart_Prepare( ctx ); + RtemsTaskReqStart_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqStart_Pre_EntryPoint_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqStart_Pre_Argument_Prepare( ctx, ctx->pcs[ 2 ] ); + RtemsTaskReqStart_Pre_Dormant_Prepare( ctx, ctx->pcs[ 3 ] ); + RtemsTaskReqStart_Pre_Suspended_Prepare( ctx, ctx->pcs[ 4 ] ); + RtemsTaskReqStart_Action( ctx ); + RtemsTaskReqStart_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqStart_Post_EntryPoint_Check( + ctx, + entry.Post_EntryPoint + ); + RtemsTaskReqStart_Post_Argument_Check( ctx, entry.Post_Argument ); + RtemsTaskReqStart_Post_Unblock_Check( ctx, entry.Post_Unblock ); + RtemsTaskReqStart_Post_StartExtensions_Check( + ctx, + entry.Post_StartExtensions + ); + RtemsTaskReqStart_Cleanup( ctx ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-storage-size.c b/testsuites/validation/tc-task-storage-size.c new file mode 100644 index 0000000000..47523f7252 --- /dev/null +++ b/testsuites/validation/tc-task-storage-size.c @@ -0,0 +1,388 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqStorageSize + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqStorageSize \ + * spec:/rtems/task/req/storage-size + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqStorageSize_Pre_Id_Invalid, + RtemsTaskReqStorageSize_Pre_Id_Task, + RtemsTaskReqStorageSize_Pre_Id_NA +} RtemsTaskReqStorageSize_Pre_Id; + +typedef enum { + RtemsTaskReqStorageSize_Pre_Suspended_Yes, + RtemsTaskReqStorageSize_Pre_Suspended_No, + RtemsTaskReqStorageSize_Pre_Suspended_NA +} RtemsTaskReqStorageSize_Pre_Suspended; + +typedef enum { + RtemsTaskReqStorageSize_Post_Status_Ok, + RtemsTaskReqStorageSize_Post_Status_InvId, + RtemsTaskReqStorageSize_Post_Status_AlrdySus, + RtemsTaskReqStorageSize_Post_Status_NA +} RtemsTaskReqStorageSize_Post_Status; + +/** + * @brief Test context for spec:/rtems/task/req/storage-size test case. + */ +typedef struct { + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_suspend() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the rtems_task_suspend() + * call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 2 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqStorageSize_Context; + +static RtemsTaskReqStorageSize_Context + RtemsTaskReqStorageSize_Instance; + +static const char * const RtemsTaskReqStorageSize_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqStorageSize_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqStorageSize_PreDesc[] = { + RtemsTaskReqStorageSize_PreDesc_Id, + RtemsTaskReqStorageSize_PreDesc_Suspended, + NULL +}; + +static void Worker( rtems_task_argument arg ) +{ + while ( true ) { + /* Do nothing */ + } +} + +static void RtemsTaskReqStorageSize_Pre_Id_Prepare( + RtemsTaskReqStorageSize_Context *ctx, + RtemsTaskReqStorageSize_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqStorageSize_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqStorageSize_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqStorageSize_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqStorageSize_Pre_Suspended_Prepare( + RtemsTaskReqStorageSize_Context *ctx, + RtemsTaskReqStorageSize_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqStorageSize_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqStorageSize_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqStorageSize_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqStorageSize_Post_Status_Check( + RtemsTaskReqStorageSize_Context *ctx, + RtemsTaskReqStorageSize_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqStorageSize_Post_Status_Ok: { + /* + * The return status of rtems_task_suspend() shall be RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqStorageSize_Post_Status_InvId: { + /* + * The return status of rtems_task_suspend() shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqStorageSize_Post_Status_AlrdySus: { + /* + * The return status of rtems_task_suspend() shall be + * RTEMS_ALREADY_SUSPENDED. + */ + T_rsc( ctx->status, RTEMS_ALREADY_SUSPENDED ); + break; + } + + case RtemsTaskReqStorageSize_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqStorageSize_Setup( + RtemsTaskReqStorageSize_Context *ctx +) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsTaskReqStorageSize_Setup_Wrap( void *arg ) +{ + RtemsTaskReqStorageSize_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqStorageSize_Setup( ctx ); +} + +static void RtemsTaskReqStorageSize_Teardown( + RtemsTaskReqStorageSize_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); +} + +static void RtemsTaskReqStorageSize_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqStorageSize_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqStorageSize_Teardown( ctx ); +} + +static void RtemsTaskReqStorageSize_Action( + RtemsTaskReqStorageSize_Context *ctx +) +{ + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->status = rtems_task_suspend( ctx->id ); + + if ( ctx->suspend ) { + ResumeTask( ctx->worker_id ); + } +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Pre_Suspended_NA : 1; + uint8_t Post_Status : 2; +} RtemsTaskReqStorageSize_Entry; + +static const RtemsTaskReqStorageSize_Entry +RtemsTaskReqStorageSize_Entries[] = { + { 0, 0, 1, RtemsTaskReqStorageSize_Post_Status_InvId }, + { 0, 0, 0, RtemsTaskReqStorageSize_Post_Status_AlrdySus }, + { 0, 0, 0, RtemsTaskReqStorageSize_Post_Status_Ok } +}; + +static const uint8_t +RtemsTaskReqStorageSize_Map[] = { + 0, 0, 1, 2 +}; + +static size_t RtemsTaskReqStorageSize_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqStorageSize_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqStorageSize_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqStorageSize_Fixture = { + .setup = RtemsTaskReqStorageSize_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqStorageSize_Teardown_Wrap, + .scope = RtemsTaskReqStorageSize_Scope, + .initial_context = &RtemsTaskReqStorageSize_Instance +}; + +static inline RtemsTaskReqStorageSize_Entry RtemsTaskReqStorageSize_GetEntry( + size_t index +) +{ + return RtemsTaskReqStorageSize_Entries[ + RtemsTaskReqStorageSize_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqStorageSize( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsTaskReqStorageSize, + &RtemsTaskReqStorageSize_Fixture +) +{ + RtemsTaskReqStorageSize_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqStorageSize_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqStorageSize_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqStorageSize_Pre_Suspended_Yes; + ctx->pcs[ 1 ] < RtemsTaskReqStorageSize_Pre_Suspended_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqStorageSize_Entry entry; + size_t pcs[ 2 ]; + + entry = RtemsTaskReqStorageSize_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqStorageSize_Pre_Suspended_NA; + } + + RtemsTaskReqStorageSize_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqStorageSize_Pre_Suspended_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqStorageSize_Action( ctx ); + RtemsTaskReqStorageSize_Post_Status_Check( ctx, entry.Post_Status ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task-suspend.c b/testsuites/validation/tc-task-suspend.c new file mode 100644 index 0000000000..8b720d212e --- /dev/null +++ b/testsuites/validation/tc-task-suspend.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskReqSuspend + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskReqSuspend spec:/rtems/task/req/suspend + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + RtemsTaskReqSuspend_Pre_Id_Invalid, + RtemsTaskReqSuspend_Pre_Id_Task, + RtemsTaskReqSuspend_Pre_Id_NA +} RtemsTaskReqSuspend_Pre_Id; + +typedef enum { + RtemsTaskReqSuspend_Pre_Suspended_Yes, + RtemsTaskReqSuspend_Pre_Suspended_No, + RtemsTaskReqSuspend_Pre_Suspended_NA +} RtemsTaskReqSuspend_Pre_Suspended; + +typedef enum { + RtemsTaskReqSuspend_Post_Status_Ok, + RtemsTaskReqSuspend_Post_Status_InvId, + RtemsTaskReqSuspend_Post_Status_AlrdySus, + RtemsTaskReqSuspend_Post_Status_NA +} RtemsTaskReqSuspend_Post_Status; + +/** + * @brief Test context for spec:/rtems/task/req/suspend test case. + */ +typedef struct { + /** + * @brief This member contains the identifier of a task. + */ + rtems_id worker_id; + + /** + * @brief If this member is true, then the worker is suspended before the + * rtems_task_suspend() call. + */ + bool suspend; + + /** + * @brief This member contains the return value of the rtems_task_suspend() + * call. + */ + rtems_status_code status; + + /** + * @brief This member specifies if the ``id`` parameter value. + */ + rtems_id id; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 2 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} RtemsTaskReqSuspend_Context; + +static RtemsTaskReqSuspend_Context + RtemsTaskReqSuspend_Instance; + +static const char * const RtemsTaskReqSuspend_PreDesc_Id[] = { + "Invalid", + "Task", + "NA" +}; + +static const char * const RtemsTaskReqSuspend_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const RtemsTaskReqSuspend_PreDesc[] = { + RtemsTaskReqSuspend_PreDesc_Id, + RtemsTaskReqSuspend_PreDesc_Suspended, + NULL +}; + +static void Worker( rtems_task_argument arg ) +{ + while ( true ) { + /* Do nothing */ + } +} + +static void RtemsTaskReqSuspend_Pre_Id_Prepare( + RtemsTaskReqSuspend_Context *ctx, + RtemsTaskReqSuspend_Pre_Id state +) +{ + switch ( state ) { + case RtemsTaskReqSuspend_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is not associated with a task. + */ + ctx->id = INVALID_ID; + break; + } + + case RtemsTaskReqSuspend_Pre_Id_Task: { + /* + * While the ``id`` parameter is associated with a task. + */ + ctx->id = ctx->worker_id; + break; + } + + case RtemsTaskReqSuspend_Pre_Id_NA: + break; + } +} + +static void RtemsTaskReqSuspend_Pre_Suspended_Prepare( + RtemsTaskReqSuspend_Context *ctx, + RtemsTaskReqSuspend_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqSuspend_Pre_Suspended_Yes: { + /* + * While the task specified by the ``id`` parameter is suspended. + */ + ctx->suspend = true; + break; + } + + case RtemsTaskReqSuspend_Pre_Suspended_No: { + /* + * While the task specified by the ``id`` parameter is not suspended. + */ + ctx->suspend = false; + break; + } + + case RtemsTaskReqSuspend_Pre_Suspended_NA: + break; + } +} + +static void RtemsTaskReqSuspend_Post_Status_Check( + RtemsTaskReqSuspend_Context *ctx, + RtemsTaskReqSuspend_Post_Status state +) +{ + switch ( state ) { + case RtemsTaskReqSuspend_Post_Status_Ok: { + /* + * The return status of rtems_task_suspend() shall be RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsTaskReqSuspend_Post_Status_InvId: { + /* + * The return status of rtems_task_suspend() shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsTaskReqSuspend_Post_Status_AlrdySus: { + /* + * The return status of rtems_task_suspend() shall be + * RTEMS_ALREADY_SUSPENDED. + */ + T_rsc( ctx->status, RTEMS_ALREADY_SUSPENDED ); + break; + } + + case RtemsTaskReqSuspend_Post_Status_NA: + break; + } +} + +static void RtemsTaskReqSuspend_Setup( RtemsTaskReqSuspend_Context *ctx ) +{ + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsTaskReqSuspend_Setup_Wrap( void *arg ) +{ + RtemsTaskReqSuspend_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqSuspend_Setup( ctx ); +} + +static void RtemsTaskReqSuspend_Teardown( RtemsTaskReqSuspend_Context *ctx ) +{ + DeleteTask( ctx->worker_id ); +} + +static void RtemsTaskReqSuspend_Teardown_Wrap( void *arg ) +{ + RtemsTaskReqSuspend_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + RtemsTaskReqSuspend_Teardown( ctx ); +} + +static void RtemsTaskReqSuspend_Action( RtemsTaskReqSuspend_Context *ctx ) +{ + if ( ctx->suspend ) { + SuspendTask( ctx->worker_id ); + } + + ctx->status = rtems_task_suspend( ctx->id ); + + if ( ctx->suspend ) { + ResumeTask( ctx->worker_id ); + } +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Pre_Suspended_NA : 1; + uint8_t Post_Status : 2; +} RtemsTaskReqSuspend_Entry; + +static const RtemsTaskReqSuspend_Entry +RtemsTaskReqSuspend_Entries[] = { + { 0, 0, 1, RtemsTaskReqSuspend_Post_Status_InvId }, + { 0, 0, 0, RtemsTaskReqSuspend_Post_Status_AlrdySus }, + { 0, 0, 0, RtemsTaskReqSuspend_Post_Status_Ok } +}; + +static const uint8_t +RtemsTaskReqSuspend_Map[] = { + 0, 0, 1, 2 +}; + +static size_t RtemsTaskReqSuspend_Scope( void *arg, char *buf, size_t n ) +{ + RtemsTaskReqSuspend_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( RtemsTaskReqSuspend_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture RtemsTaskReqSuspend_Fixture = { + .setup = RtemsTaskReqSuspend_Setup_Wrap, + .stop = NULL, + .teardown = RtemsTaskReqSuspend_Teardown_Wrap, + .scope = RtemsTaskReqSuspend_Scope, + .initial_context = &RtemsTaskReqSuspend_Instance +}; + +static inline RtemsTaskReqSuspend_Entry RtemsTaskReqSuspend_GetEntry( + size_t index +) +{ + return RtemsTaskReqSuspend_Entries[ + RtemsTaskReqSuspend_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_RtemsTaskReqSuspend( void ) + */ +T_TEST_CASE_FIXTURE( RtemsTaskReqSuspend, &RtemsTaskReqSuspend_Fixture ) +{ + RtemsTaskReqSuspend_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = RtemsTaskReqSuspend_Pre_Id_Invalid; + ctx->pcs[ 0 ] < RtemsTaskReqSuspend_Pre_Id_NA; + ++ctx->pcs[ 0 ] + ) { + for ( + ctx->pcs[ 1 ] = RtemsTaskReqSuspend_Pre_Suspended_Yes; + ctx->pcs[ 1 ] < RtemsTaskReqSuspend_Pre_Suspended_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqSuspend_Entry entry; + size_t pcs[ 2 ]; + + entry = RtemsTaskReqSuspend_GetEntry( index ); + ++index; + + memcpy( pcs, ctx->pcs, sizeof( pcs ) ); + + if ( entry.Pre_Suspended_NA ) { + ctx->pcs[ 1 ] = RtemsTaskReqSuspend_Pre_Suspended_NA; + } + + RtemsTaskReqSuspend_Pre_Id_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqSuspend_Pre_Suspended_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqSuspend_Action( ctx ); + RtemsTaskReqSuspend_Post_Status_Check( ctx, entry.Post_Status ); + memcpy( ctx->pcs, pcs, sizeof( ctx->pcs ) ); + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-task.c b/testsuites/validation/tc-task.c new file mode 100644 index 0000000000..40fc309b6c --- /dev/null +++ b/testsuites/validation/tc-task.c @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsTaskValTask + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +/** + * @defgroup RTEMSTestCaseRtemsTaskValTask spec:/rtems/task/val/task + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @brief This test case collection provides validation test cases for + * requirements of the @ref RTEMSAPIClassicTasks. + * + * This test case performs the following actions: + * + * - Call rtems_task_self() check the returned value. + * + * - Check that the returned value is equal to the object identifier of the + * calling task. + * + * - Call rtems_task_iterate() with a visitor which always returns false. + * + * - Check that the all counter is equal to the count of tasks. Check that + * the calling task was visited exacly once. Firstly, this shows that + * rtems_task_iterate() used the parameters specified by ``visitor`` and + * ``arg``. Secondly, this shows that the iteration was done over all + * tasks. + * + * - Check that the object alloctor mutex was not owned before and after the + * call. Check that the object alloctor mutex was owned during the + * iteration. + * + * - Call rtems_task_iterate() with a visitor which returns true. + * + * - Check that the all counter is equal to one. This shows that the + * iteration stops when the visitor returns true. + * + * @{ + */ + +typedef struct { + bool owner_before; + bool owner_in_visitor; + bool owner_after; + uint32_t counter_all; + uint32_t counter_self; + bool done; +} TaskIterateContext; + +static bool TaskVisitor( rtems_tcb *tcb, void *arg ) +{ + TaskIterateContext *ctx; + + ctx = arg; + ++ctx->counter_all; + + if ( rtems_task_self() == tcb->Object.id ) { + ++ctx->counter_self; + } + + ctx->owner_in_visitor = _RTEMS_Allocator_is_owner(); + + return ctx->done; +} + +/** + * @brief Call rtems_task_self() check the returned value. + */ +static void RtemsTaskValTask_Action_0( void ) +{ + rtems_id id; + + id = rtems_task_self(); + + /* + * Check that the returned value is equal to the object identifier of the + * calling task. + */ + T_step_eq_u32( 0, id, 0x0a010001 ); +} + +/** + * @brief Call rtems_task_iterate() with a visitor which always returns false. + */ +static void RtemsTaskValTask_Action_1( void ) +{ + TaskIterateContext ctx; + uint32_t task_count; + + task_count = rtems_scheduler_get_processor_maximum(); + + if ( task_count > 4 ) { + task_count = 4; + } + + ++task_count; + + memset( &ctx, 0, sizeof( ctx ) ); + ctx.owner_before = _RTEMS_Allocator_is_owner(); + rtems_task_iterate( TaskVisitor, &ctx ); + ctx.owner_after = _RTEMS_Allocator_is_owner(); + + /* + * Check that the all counter is equal to the count of tasks. Check that the + * calling task was visited exacly once. Firstly, this shows that + * rtems_task_iterate() used the parameters specified by ``visitor`` and + * ``arg``. Secondly, this shows that the iteration was done over all tasks. + */ + T_step_eq_u32( 1, ctx.counter_all, task_count ); + T_step_eq_u32( 2, ctx.counter_self, 1 ); + + /* + * Check that the object alloctor mutex was not owned before and after the + * call. Check that the object alloctor mutex was owned during the + * iteration. + */ + T_step_false( 3, ctx.owner_before ); + T_step_true( 4, ctx.owner_in_visitor ); + T_step_false( 5, ctx.owner_after ); +} + +/** + * @brief Call rtems_task_iterate() with a visitor which returns true. + */ +static void RtemsTaskValTask_Action_2( void ) +{ + TaskIterateContext ctx; + + memset( &ctx, 0, sizeof( ctx ) ); + ctx.done = true; + rtems_task_iterate( TaskVisitor, &ctx ); + + /* + * Check that the all counter is equal to one. This shows that the iteration + * stops when the visitor returns true. + */ + T_step_eq_u32( 6, ctx.counter_all, 1 ); +} + +/** + * @fn void T_case_body_RtemsTaskValTask( void ) + */ +T_TEST_CASE( RtemsTaskValTask ) +{ + T_plan( 7 ); + + RtemsTaskValTask_Action_0(); + RtemsTaskValTask_Action_1(); + RtemsTaskValTask_Action_2(); +} + +/** @} */ -- cgit v1.2.3