From 2cfb1bf7676409dfdda18111d0b141101591f90d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 31 Aug 2021 15:21:44 +0200 Subject: validation: Test futex operations --- spec/build/testsuites/validation/validation-0.yml | 2 + testsuites/validation/tc-futex-wait.c | 411 +++++++++++++++++++++ testsuites/validation/tc-futex-wake.c | 431 ++++++++++++++++++++++ 3 files changed, 844 insertions(+) create mode 100644 testsuites/validation/tc-futex-wait.c create mode 100644 testsuites/validation/tc-futex-wake.c diff --git a/spec/build/testsuites/validation/validation-0.yml b/spec/build/testsuites/validation/validation-0.yml index de1c7f07ca..2c3b65b862 100644 --- a/spec/build/testsuites/validation/validation-0.yml +++ b/spec/build/testsuites/validation/validation-0.yml @@ -23,6 +23,8 @@ source: - testsuites/validation/tc-cache.c - testsuites/validation/tc-events.c - testsuites/validation/tc-event-send-receive.c +- testsuites/validation/tc-futex-wait.c +- testsuites/validation/tc-futex-wake.c - testsuites/validation/tc-intr-clear.c - testsuites/validation/tc-intr-entry-install.c - testsuites/validation/tc-intr-entry-remove.c diff --git a/testsuites/validation/tc-futex-wait.c b/testsuites/validation/tc-futex-wait.c new file mode 100644 index 0000000000..02c772409c --- /dev/null +++ b/testsuites/validation/tc-futex-wait.c @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseScoreFutexReqWait + */ + +/* + * 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 "tr-tq-enqueue-fifo.h" +#include "tx-thread-queue.h" + +#include + +/** + * @defgroup RTEMSTestCaseScoreFutexReqWait spec:/score/futex/req/wait + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + ScoreFutexReqWait_Pre_State_Equal, + ScoreFutexReqWait_Pre_State_NotEqual, + ScoreFutexReqWait_Pre_State_NA +} ScoreFutexReqWait_Pre_State; + +typedef enum { + ScoreFutexReqWait_Post_Result_Zero, + ScoreFutexReqWait_Post_Result_EAGAIN, + ScoreFutexReqWait_Post_Result_NA +} ScoreFutexReqWait_Post_Result; + +typedef enum { + ScoreFutexReqWait_Post_Enqueue_No, + ScoreFutexReqWait_Post_Enqueue_Yes, + ScoreFutexReqWait_Post_Enqueue_NA +} ScoreFutexReqWait_Post_Enqueue; + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_State_NA : 1; + uint8_t Post_Result : 2; + uint8_t Post_Enqueue : 2; +} ScoreFutexReqWait_Entry; + +/** + * @brief Test context for spec:/score/futex/req/wait test case. + */ +typedef struct { + /** + * @brief This member contains the thread queue test context. + */ + TQContext tq_ctx;; + + /** + * @brief This member specifies the expected futex state value. + */ + int expected_value; + + /** + * @brief This member provides the futex object. + */ + struct _Futex_Control futex; + + /** + * @brief This member provides the futex state. + */ + int state; + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 1 ]; + + /** + * @brief If this member is true, then the test action loop is executed. + */ + bool in_action_loop; + + /** + * @brief This member contains the next transition map index. + */ + size_t index; + + /** + * @brief This member contains the current transition map entry. + */ + ScoreFutexReqWait_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} ScoreFutexReqWait_Context; + +static ScoreFutexReqWait_Context + ScoreFutexReqWait_Instance; + +static const char * const ScoreFutexReqWait_PreDesc_State[] = { + "Equal", + "NotEqual", + "NA" +}; + +static const char * const * const ScoreFutexReqWait_PreDesc[] = { + ScoreFutexReqWait_PreDesc_State, + NULL +}; + +typedef ScoreFutexReqWait_Context Context; + +static Context *ToContext( TQContext *tq_ctx ) +{ + return RTEMS_CONTAINER_OF( tq_ctx, Context, tq_ctx ); +} + +static Status_Control Enqueue( TQContext *tq_ctx, TQWait wait ) +{ + Context *ctx; + int eno; + + ctx = ToContext( tq_ctx ); + eno = _Futex_Wait( &ctx->futex, &ctx->state, ctx->expected_value ); + T_eq_int( eno, 0 ); + + return STATUS_BUILD( 0, eno ); +} + +static void EnqueueDone( TQContext *tq_ctx ) +{ + Context *ctx; + int count; + + ctx = ToContext( tq_ctx ); + count = _Futex_Wake( &ctx->futex, INT_MAX ); + T_eq_int( count, (int) ctx->tq_ctx.how_many ); +} + +static void ScoreFutexReqWait_Pre_State_Prepare( + ScoreFutexReqWait_Context *ctx, + ScoreFutexReqWait_Pre_State state +) +{ + switch ( state ) { + case ScoreFutexReqWait_Pre_State_Equal: { + /* + * While the expected futex state value is equal to the actual futex + * state value. + */ + ctx->expected_value = 0; + break; + } + + case ScoreFutexReqWait_Pre_State_NotEqual: { + /* + * While the expected futex state value is not equal to the actual futex + * state value. + */ + ctx->expected_value = 1; + break; + } + + case ScoreFutexReqWait_Pre_State_NA: + break; + } +} + +static void ScoreFutexReqWait_Post_Result_Check( + ScoreFutexReqWait_Context *ctx, + ScoreFutexReqWait_Post_Result state +) +{ + int eno; + + switch ( state ) { + case ScoreFutexReqWait_Post_Result_Zero: { + /* + * The return status of _Futex_Wait shall be zero. + */ + /* This result is checked by Enqueue() */ + break; + } + + case ScoreFutexReqWait_Post_Result_EAGAIN: { + /* + * The return status of _Futex_Wait shall be EAGAIN. + */ + eno = _Futex_Wait( &ctx->futex, &ctx->state, ctx->expected_value ); + T_eq_int( eno, EAGAIN ); + break; + } + + case ScoreFutexReqWait_Post_Result_NA: + break; + } +} + +static void ScoreFutexReqWait_Post_Enqueue_Check( + ScoreFutexReqWait_Context *ctx, + ScoreFutexReqWait_Post_Enqueue state +) +{ + switch ( state ) { + case ScoreFutexReqWait_Post_Enqueue_No: { + /* + * The calling thread shall not be enqueued on the thread queue of the + * futex object. + */ + /* The runner would block forever */ + break; + } + + case ScoreFutexReqWait_Post_Enqueue_Yes: { + /* + * The calling thread shall be enqueued in FIFO order on the thread queue + * of the futex object. + */ + ScoreTqReqEnqueueFifo_Run( &ctx->tq_ctx ); + break; + } + + case ScoreFutexReqWait_Post_Enqueue_NA: + break; + } +} + +static void ScoreFutexReqWait_Setup( ScoreFutexReqWait_Context *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); + ctx->tq_ctx.discipline = TQ_FIFO; + ctx->tq_ctx.wait = TQ_WAIT_FOREVER; + ctx->tq_ctx.enqueue_prepare = TQDoNothing; + ctx->tq_ctx.enqueue = Enqueue; + ctx->tq_ctx.enqueue_done = EnqueueDone; + ctx->tq_ctx.surrender = TQDoNothing; + ctx->tq_ctx.convert_status = TQConvertStatusPOSIX; + TQInitialize( &ctx->tq_ctx ); +} + +static void ScoreFutexReqWait_Setup_Wrap( void *arg ) +{ + ScoreFutexReqWait_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreFutexReqWait_Setup( ctx ); +} + +static void ScoreFutexReqWait_Teardown( ScoreFutexReqWait_Context *ctx ) +{ + TQDestroy( &ctx->tq_ctx ); +} + +static void ScoreFutexReqWait_Teardown_Wrap( void *arg ) +{ + ScoreFutexReqWait_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreFutexReqWait_Teardown( ctx ); +} + +static void ScoreFutexReqWait_Prepare( ScoreFutexReqWait_Context *ctx ) +{ + _Futex_Initialize( &ctx->futex ); + ctx->state = 0; +} + +static void ScoreFutexReqWait_Action( ScoreFutexReqWait_Context *ctx ) +{ + /* The action is performed in the post-conditions. */ +} + +static void ScoreFutexReqWait_Cleanup( ScoreFutexReqWait_Context *ctx ) +{ + _Futex_Destroy( &ctx->futex ); +} + +static const ScoreFutexReqWait_Entry +ScoreFutexReqWait_Entries[] = { + { 0, 0, ScoreFutexReqWait_Post_Result_Zero, + ScoreFutexReqWait_Post_Enqueue_Yes }, + { 0, 0, ScoreFutexReqWait_Post_Result_EAGAIN, + ScoreFutexReqWait_Post_Enqueue_No } +}; + +static const uint8_t +ScoreFutexReqWait_Map[] = { + 0, 1 +}; + +static size_t ScoreFutexReqWait_Scope( void *arg, char *buf, size_t n ) +{ + ScoreFutexReqWait_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( ScoreFutexReqWait_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture ScoreFutexReqWait_Fixture = { + .setup = ScoreFutexReqWait_Setup_Wrap, + .stop = NULL, + .teardown = ScoreFutexReqWait_Teardown_Wrap, + .scope = ScoreFutexReqWait_Scope, + .initial_context = &ScoreFutexReqWait_Instance +}; + +static inline ScoreFutexReqWait_Entry ScoreFutexReqWait_PopEntry( + ScoreFutexReqWait_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return ScoreFutexReqWait_Entries[ + ScoreFutexReqWait_Map[ index ] + ]; +} + +static void ScoreFutexReqWait_TestVariant( ScoreFutexReqWait_Context *ctx ) +{ + ScoreFutexReqWait_Pre_State_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + ScoreFutexReqWait_Action( ctx ); + ScoreFutexReqWait_Post_Result_Check( ctx, ctx->Map.entry.Post_Result ); + ScoreFutexReqWait_Post_Enqueue_Check( ctx, ctx->Map.entry.Post_Enqueue ); +} + +/** + * @fn void T_case_body_ScoreFutexReqWait( void ) + */ +T_TEST_CASE_FIXTURE( ScoreFutexReqWait, &ScoreFutexReqWait_Fixture ) +{ + ScoreFutexReqWait_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = ScoreFutexReqWait_Pre_State_Equal; + ctx->Map.pcs[ 0 ] < ScoreFutexReqWait_Pre_State_NA; + ++ctx->Map.pcs[ 0 ] + ) { + ctx->Map.entry = ScoreFutexReqWait_PopEntry( ctx ); + ScoreFutexReqWait_Prepare( ctx ); + ScoreFutexReqWait_TestVariant( ctx ); + ScoreFutexReqWait_Cleanup( ctx ); + } +} + +/** @} */ diff --git a/testsuites/validation/tc-futex-wake.c b/testsuites/validation/tc-futex-wake.c new file mode 100644 index 0000000000..daa1b8d8dd --- /dev/null +++ b/testsuites/validation/tc-futex-wake.c @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseScoreFutexReqWake + */ + +/* + * 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 "tr-tq-flush-fifo.h" +#include "tx-thread-queue.h" + +#include + +/** + * @defgroup RTEMSTestCaseScoreFutexReqWake spec:/score/futex/req/wake + * + * @ingroup RTEMSTestSuiteTestsuitesValidation0 + * + * @{ + */ + +typedef enum { + ScoreFutexReqWake_Pre_Count_Negative, + ScoreFutexReqWake_Pre_Count_Partial, + ScoreFutexReqWake_Pre_Count_All, + ScoreFutexReqWake_Pre_Count_NA +} ScoreFutexReqWake_Pre_Count; + +typedef enum { + ScoreFutexReqWake_Post_Result_Count, + ScoreFutexReqWake_Post_Result_NA +} ScoreFutexReqWake_Post_Result; + +typedef enum { + ScoreFutexReqWake_Post_Flush_No, + ScoreFutexReqWake_Post_Flush_Partial, + ScoreFutexReqWake_Post_Flush_All, + ScoreFutexReqWake_Post_Flush_NA +} ScoreFutexReqWake_Post_Flush; + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Count_NA : 1; + uint8_t Post_Result : 1; + uint8_t Post_Flush : 2; +} ScoreFutexReqWake_Entry; + +/** + * @brief Test context for spec:/score/futex/req/wake test case. + */ +typedef struct { + /** + * @brief This member contains the thread queue test context. + */ + TQContext tq_ctx;; + + /** + * @brief This member provides the futex object. + */ + struct _Futex_Control futex; + + /** + * @brief This member provides the futex state. + */ + int state; + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 1 ]; + + /** + * @brief If this member is true, then the test action loop is executed. + */ + bool in_action_loop; + + /** + * @brief This member contains the next transition map index. + */ + size_t index; + + /** + * @brief This member contains the current transition map entry. + */ + ScoreFutexReqWake_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} ScoreFutexReqWake_Context; + +static ScoreFutexReqWake_Context + ScoreFutexReqWake_Instance; + +static const char * const ScoreFutexReqWake_PreDesc_Count[] = { + "Negative", + "Partial", + "All", + "NA" +}; + +static const char * const * const ScoreFutexReqWake_PreDesc[] = { + ScoreFutexReqWake_PreDesc_Count, + NULL +}; + +typedef ScoreFutexReqWake_Context Context; + +static Context *ToContext( TQContext *tq_ctx ) +{ + return RTEMS_CONTAINER_OF( tq_ctx, Context, tq_ctx ); +} + +static Status_Control Enqueue( TQContext *tq_ctx, TQWait wait ) +{ + Context *ctx; + int count; + int eno; + + ctx = ToContext( tq_ctx ); + + count = _Futex_Wake( &ctx->futex, -1 ); + T_eq_int( count, 0 ); + + count = _Futex_Wake( &ctx->futex, 0 ); + T_eq_int( count, 0 ); + + eno = _Futex_Wait( &ctx->futex, &ctx->state, 0 ); + T_eq_int( eno, 0 ); + + return STATUS_BUILD( 0, eno ); +} + +static void Flush( TQContext *tq_ctx ) +{ + Context *ctx; + int count; + int how_many; + + ctx = ToContext( tq_ctx ); + how_many = (int) ctx->tq_ctx.how_many; + + count = _Futex_Wake( &ctx->futex, 1 ); + T_eq_int( count, how_many > 0 ? 1 : 0 ); + + count = _Futex_Wake( &ctx->futex, INT_MAX ); + T_eq_int( count, how_many > 1 ? how_many - 1 : 0 ); +} + +static void ScoreFutexReqWake_Pre_Count_Prepare( + ScoreFutexReqWake_Context *ctx, + ScoreFutexReqWake_Pre_Count state +) +{ + switch ( state ) { + case ScoreFutexReqWake_Pre_Count_Negative: { + /* + * While the ``count`` parameter is less than zero. + */ + /* This state is prepared by Enqueue() */ + break; + } + + case ScoreFutexReqWake_Pre_Count_Partial: { + /* + * While the ``count`` parameter is greater than or equal to zero, while + * the ``count`` parameter is less than the count of threads enqueued on + * the thread queue of the futex object. + */ + /* This state is prepared by Flush() */ + break; + } + + case ScoreFutexReqWake_Pre_Count_All: { + /* + * While the ``count`` parameter is greater than or equal to zero, while + * the ``count`` parameter is greater than or equal to the count of + * threads enqueued on the thread queue of the futex object. + */ + /* This state is prepared by Flush() */ + break; + } + + case ScoreFutexReqWake_Pre_Count_NA: + break; + } +} + +static void ScoreFutexReqWake_Post_Result_Check( + ScoreFutexReqWake_Context *ctx, + ScoreFutexReqWake_Post_Result state +) +{ + switch ( state ) { + case ScoreFutexReqWake_Post_Result_Count: { + /* + * The return status of _Futex_Wake shall be the count of threads + * extracted from the thread queue of the futex object. + */ + /* This result is checked by Flush() */ + break; + } + + case ScoreFutexReqWake_Post_Result_NA: + break; + } +} + +static void ScoreFutexReqWake_Post_Flush_Check( + ScoreFutexReqWake_Context *ctx, + ScoreFutexReqWake_Post_Flush state +) +{ + switch ( state ) { + case ScoreFutexReqWake_Post_Flush_No: { + /* + * No thread shall be extracted from the thread queue of the futex + * object. + */ + /* This state is checked by Enqueue() */ + break; + } + + case ScoreFutexReqWake_Post_Flush_Partial: { + /* + * The first count threads specified by the ``count`` parameter shall be + * extracted from the thread queue of the futex object in FIFO order. + */ + /* This state is checked by Flush() */ + break; + } + + case ScoreFutexReqWake_Post_Flush_All: { + /* + * All threads shall be extracted from the thread queue of the futex + * object in FIFO order. + */ + ScoreTqReqFlushFifo_Run( &ctx->tq_ctx ); + break; + } + + case ScoreFutexReqWake_Post_Flush_NA: + break; + } +} + +static void ScoreFutexReqWake_Setup( ScoreFutexReqWake_Context *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); + ctx->tq_ctx.discipline = TQ_FIFO; + ctx->tq_ctx.wait = TQ_WAIT_FOREVER; + ctx->tq_ctx.enqueue_prepare = TQDoNothing; + ctx->tq_ctx.enqueue = Enqueue; + ctx->tq_ctx.enqueue_done = TQDoNothing; + ctx->tq_ctx.flush = Flush; + ctx->tq_ctx.surrender = TQDoNothing; + ctx->tq_ctx.convert_status = TQConvertStatusPOSIX; + TQInitialize( &ctx->tq_ctx ); +} + +static void ScoreFutexReqWake_Setup_Wrap( void *arg ) +{ + ScoreFutexReqWake_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreFutexReqWake_Setup( ctx ); +} + +static void ScoreFutexReqWake_Teardown( ScoreFutexReqWake_Context *ctx ) +{ + TQDestroy( &ctx->tq_ctx ); +} + +static void ScoreFutexReqWake_Teardown_Wrap( void *arg ) +{ + ScoreFutexReqWake_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreFutexReqWake_Teardown( ctx ); +} + +static void ScoreFutexReqWake_Prepare( ScoreFutexReqWake_Context *ctx ) +{ + _Futex_Initialize( &ctx->futex ); +} + +static void ScoreFutexReqWake_Action( ScoreFutexReqWake_Context *ctx ) +{ + /* The action is performed in the ``Flush`` post-condition ``All`` state. */ +} + +static void ScoreFutexReqWake_Cleanup( ScoreFutexReqWake_Context *ctx ) +{ + _Futex_Destroy( &ctx->futex ); +} + +static const ScoreFutexReqWake_Entry +ScoreFutexReqWake_Entries[] = { + { 0, 0, ScoreFutexReqWake_Post_Result_Count, ScoreFutexReqWake_Post_Flush_No }, + { 0, 0, ScoreFutexReqWake_Post_Result_Count, + ScoreFutexReqWake_Post_Flush_Partial }, + { 0, 0, ScoreFutexReqWake_Post_Result_Count, ScoreFutexReqWake_Post_Flush_All } +}; + +static const uint8_t +ScoreFutexReqWake_Map[] = { + 0, 1, 2 +}; + +static size_t ScoreFutexReqWake_Scope( void *arg, char *buf, size_t n ) +{ + ScoreFutexReqWake_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( ScoreFutexReqWake_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture ScoreFutexReqWake_Fixture = { + .setup = ScoreFutexReqWake_Setup_Wrap, + .stop = NULL, + .teardown = ScoreFutexReqWake_Teardown_Wrap, + .scope = ScoreFutexReqWake_Scope, + .initial_context = &ScoreFutexReqWake_Instance +}; + +static inline ScoreFutexReqWake_Entry ScoreFutexReqWake_PopEntry( + ScoreFutexReqWake_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return ScoreFutexReqWake_Entries[ + ScoreFutexReqWake_Map[ index ] + ]; +} + +static void ScoreFutexReqWake_TestVariant( ScoreFutexReqWake_Context *ctx ) +{ + ScoreFutexReqWake_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + ScoreFutexReqWake_Action( ctx ); + ScoreFutexReqWake_Post_Result_Check( ctx, ctx->Map.entry.Post_Result ); + ScoreFutexReqWake_Post_Flush_Check( ctx, ctx->Map.entry.Post_Flush ); +} + +/** + * @fn void T_case_body_ScoreFutexReqWake( void ) + */ +T_TEST_CASE_FIXTURE( ScoreFutexReqWake, &ScoreFutexReqWake_Fixture ) +{ + ScoreFutexReqWake_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = ScoreFutexReqWake_Pre_Count_Negative; + ctx->Map.pcs[ 0 ] < ScoreFutexReqWake_Pre_Count_NA; + ++ctx->Map.pcs[ 0 ] + ) { + ctx->Map.entry = ScoreFutexReqWake_PopEntry( ctx ); + ScoreFutexReqWake_Prepare( ctx ); + ScoreFutexReqWake_TestVariant( ctx ); + ScoreFutexReqWake_Cleanup( ctx ); + } +} + +/** @} */ -- cgit v1.2.3