From 5fb7ce8835ea3829a623cf38a4c81afd4c4ca0dc Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 9 Dec 2021 16:21:08 +0100 Subject: validation: Test futex support The test source code is generated from specification items by the "./spec2modules.py" script contained in the git://git.rtems.org/rtems-central.git Git repository. Please read the "How-To" section in the "Software Requirements Engineering" chapter of the RTEMS Software Engineering manual to get more information about the process. Update #3716. --- .../validation/validation-no-clock-0.yml | 2 + testsuites/validation/tc-futex-wait.c | 411 +++++++++++++++++++ testsuites/validation/tc-futex-wake.c | 433 +++++++++++++++++++++ 3 files changed, 846 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-no-clock-0.yml b/spec/build/testsuites/validation/validation-no-clock-0.yml index 488286bc4f..a90fb9c35f 100644 --- a/spec/build/testsuites/validation/validation-no-clock-0.yml +++ b/spec/build/testsuites/validation/validation-no-clock-0.yml @@ -27,6 +27,8 @@ source: - testsuites/validation/tc-clock-set.c - testsuites/validation/tc-cpuuse.c - testsuites/validation/tc-events.c +- testsuites/validation/tc-futex-wait.c +- testsuites/validation/tc-futex-wake.c - testsuites/validation/tc-intr.c - testsuites/validation/tc-io-getchark.c - testsuites/validation/tc-io-putc.c diff --git a/testsuites/validation/tc-futex-wait.c b/testsuites/validation/tc-futex-wait.c new file mode 100644 index 0000000000..396b26525f --- /dev/null +++ b/testsuites/validation/tc-futex-wait.c @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseNewlibReqFutexWait + */ + +/* + * 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 RTEMSTestCaseNewlibReqFutexWait spec:/newlib/req/futex-wait + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + NewlibReqFutexWait_Pre_State_Equal, + NewlibReqFutexWait_Pre_State_NotEqual, + NewlibReqFutexWait_Pre_State_NA +} NewlibReqFutexWait_Pre_State; + +typedef enum { + NewlibReqFutexWait_Post_Result_Zero, + NewlibReqFutexWait_Post_Result_EAGAIN, + NewlibReqFutexWait_Post_Result_NA +} NewlibReqFutexWait_Post_Result; + +typedef enum { + NewlibReqFutexWait_Post_Enqueue_No, + NewlibReqFutexWait_Post_Enqueue_Yes, + NewlibReqFutexWait_Post_Enqueue_NA +} NewlibReqFutexWait_Post_Enqueue; + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_State_NA : 1; + uint8_t Post_Result : 2; + uint8_t Post_Enqueue : 2; +} NewlibReqFutexWait_Entry; + +/** + * @brief Test context for spec:/newlib/req/futex-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. + */ + NewlibReqFutexWait_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} NewlibReqFutexWait_Context; + +static NewlibReqFutexWait_Context + NewlibReqFutexWait_Instance; + +static const char * const NewlibReqFutexWait_PreDesc_State[] = { + "Equal", + "NotEqual", + "NA" +}; + +static const char * const * const NewlibReqFutexWait_PreDesc[] = { + NewlibReqFutexWait_PreDesc_State, + NULL +}; + +typedef NewlibReqFutexWait_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 NewlibReqFutexWait_Pre_State_Prepare( + NewlibReqFutexWait_Context *ctx, + NewlibReqFutexWait_Pre_State state +) +{ + switch ( state ) { + case NewlibReqFutexWait_Pre_State_Equal: { + /* + * While the expected futex state value is equal to the actual futex + * state value. + */ + ctx->expected_value = 0; + break; + } + + case NewlibReqFutexWait_Pre_State_NotEqual: { + /* + * While the expected futex state value is not equal to the actual futex + * state value. + */ + ctx->expected_value = 1; + break; + } + + case NewlibReqFutexWait_Pre_State_NA: + break; + } +} + +static void NewlibReqFutexWait_Post_Result_Check( + NewlibReqFutexWait_Context *ctx, + NewlibReqFutexWait_Post_Result state +) +{ + int eno; + + switch ( state ) { + case NewlibReqFutexWait_Post_Result_Zero: { + /* + * The return status of _Futex_Wait() shall be zero. + */ + /* This result is checked by Enqueue() */ + break; + } + + case NewlibReqFutexWait_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 NewlibReqFutexWait_Post_Result_NA: + break; + } +} + +static void NewlibReqFutexWait_Post_Enqueue_Check( + NewlibReqFutexWait_Context *ctx, + NewlibReqFutexWait_Post_Enqueue state +) +{ + switch ( state ) { + case NewlibReqFutexWait_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 NewlibReqFutexWait_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 NewlibReqFutexWait_Post_Enqueue_NA: + break; + } +} + +static void NewlibReqFutexWait_Setup( NewlibReqFutexWait_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 = TQDoNothingSuccessfully; + ctx->tq_ctx.convert_status = TQConvertStatusPOSIX; + TQInitialize( &ctx->tq_ctx ); +} + +static void NewlibReqFutexWait_Setup_Wrap( void *arg ) +{ + NewlibReqFutexWait_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + NewlibReqFutexWait_Setup( ctx ); +} + +static void NewlibReqFutexWait_Teardown( NewlibReqFutexWait_Context *ctx ) +{ + TQDestroy( &ctx->tq_ctx ); +} + +static void NewlibReqFutexWait_Teardown_Wrap( void *arg ) +{ + NewlibReqFutexWait_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + NewlibReqFutexWait_Teardown( ctx ); +} + +static void NewlibReqFutexWait_Prepare( NewlibReqFutexWait_Context *ctx ) +{ + _Futex_Initialize( &ctx->futex ); + ctx->state = 0; +} + +static void NewlibReqFutexWait_Action( NewlibReqFutexWait_Context *ctx ) +{ + /* The action is performed in the post-conditions. */ +} + +static void NewlibReqFutexWait_Cleanup( NewlibReqFutexWait_Context *ctx ) +{ + _Futex_Destroy( &ctx->futex ); +} + +static const NewlibReqFutexWait_Entry +NewlibReqFutexWait_Entries[] = { + { 0, 0, NewlibReqFutexWait_Post_Result_Zero, + NewlibReqFutexWait_Post_Enqueue_Yes }, + { 0, 0, NewlibReqFutexWait_Post_Result_EAGAIN, + NewlibReqFutexWait_Post_Enqueue_No } +}; + +static const uint8_t +NewlibReqFutexWait_Map[] = { + 0, 1 +}; + +static size_t NewlibReqFutexWait_Scope( void *arg, char *buf, size_t n ) +{ + NewlibReqFutexWait_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( NewlibReqFutexWait_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture NewlibReqFutexWait_Fixture = { + .setup = NewlibReqFutexWait_Setup_Wrap, + .stop = NULL, + .teardown = NewlibReqFutexWait_Teardown_Wrap, + .scope = NewlibReqFutexWait_Scope, + .initial_context = &NewlibReqFutexWait_Instance +}; + +static inline NewlibReqFutexWait_Entry NewlibReqFutexWait_PopEntry( + NewlibReqFutexWait_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return NewlibReqFutexWait_Entries[ + NewlibReqFutexWait_Map[ index ] + ]; +} + +static void NewlibReqFutexWait_TestVariant( NewlibReqFutexWait_Context *ctx ) +{ + NewlibReqFutexWait_Pre_State_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + NewlibReqFutexWait_Action( ctx ); + NewlibReqFutexWait_Post_Result_Check( ctx, ctx->Map.entry.Post_Result ); + NewlibReqFutexWait_Post_Enqueue_Check( ctx, ctx->Map.entry.Post_Enqueue ); +} + +/** + * @fn void T_case_body_NewlibReqFutexWait( void ) + */ +T_TEST_CASE_FIXTURE( NewlibReqFutexWait, &NewlibReqFutexWait_Fixture ) +{ + NewlibReqFutexWait_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = NewlibReqFutexWait_Pre_State_Equal; + ctx->Map.pcs[ 0 ] < NewlibReqFutexWait_Pre_State_NA; + ++ctx->Map.pcs[ 0 ] + ) { + ctx->Map.entry = NewlibReqFutexWait_PopEntry( ctx ); + NewlibReqFutexWait_Prepare( ctx ); + NewlibReqFutexWait_TestVariant( ctx ); + NewlibReqFutexWait_Cleanup( ctx ); + } +} + +/** @} */ diff --git a/testsuites/validation/tc-futex-wake.c b/testsuites/validation/tc-futex-wake.c new file mode 100644 index 0000000000..1d996d1d2b --- /dev/null +++ b/testsuites/validation/tc-futex-wake.c @@ -0,0 +1,433 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseNewlibReqFutexWake + */ + +/* + * 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 RTEMSTestCaseNewlibReqFutexWake spec:/newlib/req/futex-wake + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + NewlibReqFutexWake_Pre_Count_Negative, + NewlibReqFutexWake_Pre_Count_Partial, + NewlibReqFutexWake_Pre_Count_All, + NewlibReqFutexWake_Pre_Count_NA +} NewlibReqFutexWake_Pre_Count; + +typedef enum { + NewlibReqFutexWake_Post_Result_Count, + NewlibReqFutexWake_Post_Result_NA +} NewlibReqFutexWake_Post_Result; + +typedef enum { + NewlibReqFutexWake_Post_Flush_No, + NewlibReqFutexWake_Post_Flush_Partial, + NewlibReqFutexWake_Post_Flush_All, + NewlibReqFutexWake_Post_Flush_NA +} NewlibReqFutexWake_Post_Flush; + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Count_NA : 1; + uint8_t Post_Result : 1; + uint8_t Post_Flush : 2; +} NewlibReqFutexWake_Entry; + +/** + * @brief Test context for spec:/newlib/req/futex-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. + */ + NewlibReqFutexWake_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} NewlibReqFutexWake_Context; + +static NewlibReqFutexWake_Context + NewlibReqFutexWake_Instance; + +static const char * const NewlibReqFutexWake_PreDesc_Count[] = { + "Negative", + "Partial", + "All", + "NA" +}; + +static const char * const * const NewlibReqFutexWake_PreDesc[] = { + NewlibReqFutexWake_PreDesc_Count, + NULL +}; + +typedef NewlibReqFutexWake_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 NewlibReqFutexWake_Pre_Count_Prepare( + NewlibReqFutexWake_Context *ctx, + NewlibReqFutexWake_Pre_Count state +) +{ + switch ( state ) { + case NewlibReqFutexWake_Pre_Count_Negative: { + /* + * While the ``count`` parameter is less than zero. + */ + /* This state is prepared by Enqueue() */ + break; + } + + case NewlibReqFutexWake_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 NewlibReqFutexWake_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 NewlibReqFutexWake_Pre_Count_NA: + break; + } +} + +static void NewlibReqFutexWake_Post_Result_Check( + NewlibReqFutexWake_Context *ctx, + NewlibReqFutexWake_Post_Result state +) +{ + switch ( state ) { + case NewlibReqFutexWake_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 NewlibReqFutexWake_Post_Result_NA: + break; + } +} + +static void NewlibReqFutexWake_Post_Flush_Check( + NewlibReqFutexWake_Context *ctx, + NewlibReqFutexWake_Post_Flush state +) +{ + switch ( state ) { + case NewlibReqFutexWake_Post_Flush_No: { + /* + * No thread shall be extracted from the thread queue of the futex + * object. + */ + /* This state is checked by Enqueue() */ + break; + } + + case NewlibReqFutexWake_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 NewlibReqFutexWake_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 NewlibReqFutexWake_Post_Flush_NA: + break; + } +} + +static void NewlibReqFutexWake_Setup( NewlibReqFutexWake_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 = TQDoNothingSuccessfully; + ctx->tq_ctx.convert_status = TQConvertStatusPOSIX; + TQInitialize( &ctx->tq_ctx ); +} + +static void NewlibReqFutexWake_Setup_Wrap( void *arg ) +{ + NewlibReqFutexWake_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + NewlibReqFutexWake_Setup( ctx ); +} + +static void NewlibReqFutexWake_Teardown( NewlibReqFutexWake_Context *ctx ) +{ + TQDestroy( &ctx->tq_ctx ); +} + +static void NewlibReqFutexWake_Teardown_Wrap( void *arg ) +{ + NewlibReqFutexWake_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + NewlibReqFutexWake_Teardown( ctx ); +} + +static void NewlibReqFutexWake_Prepare( NewlibReqFutexWake_Context *ctx ) +{ + _Futex_Initialize( &ctx->futex ); +} + +static void NewlibReqFutexWake_Action( NewlibReqFutexWake_Context *ctx ) +{ + /* The action is performed in the ``Flush`` post-condition ``All`` state. */ +} + +static void NewlibReqFutexWake_Cleanup( NewlibReqFutexWake_Context *ctx ) +{ + _Futex_Destroy( &ctx->futex ); +} + +static const NewlibReqFutexWake_Entry +NewlibReqFutexWake_Entries[] = { + { 0, 0, NewlibReqFutexWake_Post_Result_Count, + NewlibReqFutexWake_Post_Flush_No }, + { 0, 0, NewlibReqFutexWake_Post_Result_Count, + NewlibReqFutexWake_Post_Flush_Partial }, + { 0, 0, NewlibReqFutexWake_Post_Result_Count, + NewlibReqFutexWake_Post_Flush_All } +}; + +static const uint8_t +NewlibReqFutexWake_Map[] = { + 0, 1, 2 +}; + +static size_t NewlibReqFutexWake_Scope( void *arg, char *buf, size_t n ) +{ + NewlibReqFutexWake_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( NewlibReqFutexWake_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture NewlibReqFutexWake_Fixture = { + .setup = NewlibReqFutexWake_Setup_Wrap, + .stop = NULL, + .teardown = NewlibReqFutexWake_Teardown_Wrap, + .scope = NewlibReqFutexWake_Scope, + .initial_context = &NewlibReqFutexWake_Instance +}; + +static inline NewlibReqFutexWake_Entry NewlibReqFutexWake_PopEntry( + NewlibReqFutexWake_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return NewlibReqFutexWake_Entries[ + NewlibReqFutexWake_Map[ index ] + ]; +} + +static void NewlibReqFutexWake_TestVariant( NewlibReqFutexWake_Context *ctx ) +{ + NewlibReqFutexWake_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + NewlibReqFutexWake_Action( ctx ); + NewlibReqFutexWake_Post_Result_Check( ctx, ctx->Map.entry.Post_Result ); + NewlibReqFutexWake_Post_Flush_Check( ctx, ctx->Map.entry.Post_Flush ); +} + +/** + * @fn void T_case_body_NewlibReqFutexWake( void ) + */ +T_TEST_CASE_FIXTURE( NewlibReqFutexWake, &NewlibReqFutexWake_Fixture ) +{ + NewlibReqFutexWake_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = NewlibReqFutexWake_Pre_Count_Negative; + ctx->Map.pcs[ 0 ] < NewlibReqFutexWake_Pre_Count_NA; + ++ctx->Map.pcs[ 0 ] + ) { + ctx->Map.entry = NewlibReqFutexWake_PopEntry( ctx ); + NewlibReqFutexWake_Prepare( ctx ); + NewlibReqFutexWake_TestVariant( ctx ); + NewlibReqFutexWake_Cleanup( ctx ); + } +} + +/** @} */ -- cgit v1.2.3