From 04fb7b604061e3bba58d5e839dba41c79a392b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20K=C3=BChndel?= Date: Thu, 9 Dec 2021 16:12:55 +0100 Subject: validation: Test Message Manager 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/performance-no-clock-0.yml | 1 + spec/build/testsuites/validation/validation-0.yml | 1 - .../validation/validation-no-clock-0.yml | 8 + testsuites/validation/tc-message-broadcast.c | 1204 ++++++++++++++++ .../validation/tc-message-construct-errors.c | 932 ------------- testsuites/validation/tc-message-construct.c | 1059 ++++++++++++++ testsuites/validation/tc-message-delete.c | 479 +++++++ testsuites/validation/tc-message-flush-pending.c | 982 +++++++++++++ testsuites/validation/tc-message-ident.c | 126 ++ testsuites/validation/tc-message-macros.c | 147 ++ testsuites/validation/tc-message-performance.c | 886 ++++++++++++ testsuites/validation/tc-message-receive.c | 1474 ++++++++++++++++++++ testsuites/validation/tc-message-urgent-send.c | 1167 ++++++++++++++++ 13 files changed, 7533 insertions(+), 933 deletions(-) create mode 100644 testsuites/validation/tc-message-broadcast.c delete mode 100644 testsuites/validation/tc-message-construct-errors.c create mode 100644 testsuites/validation/tc-message-construct.c create mode 100644 testsuites/validation/tc-message-delete.c create mode 100644 testsuites/validation/tc-message-flush-pending.c create mode 100644 testsuites/validation/tc-message-ident.c create mode 100644 testsuites/validation/tc-message-macros.c create mode 100644 testsuites/validation/tc-message-performance.c create mode 100644 testsuites/validation/tc-message-receive.c create mode 100644 testsuites/validation/tc-message-urgent-send.c diff --git a/spec/build/testsuites/validation/performance-no-clock-0.yml b/spec/build/testsuites/validation/performance-no-clock-0.yml index 8d87df0ca7..612a11d636 100644 --- a/spec/build/testsuites/validation/performance-no-clock-0.yml +++ b/spec/build/testsuites/validation/performance-no-clock-0.yml @@ -13,6 +13,7 @@ links: [] source: - testsuites/validation/tc-barrier-performance.c - testsuites/validation/tc-event-performance.c +- testsuites/validation/tc-message-performance.c - testsuites/validation/ts-performance-no-clock-0.c stlib: [] target: testsuites/validation/ts-performance-no-clock-0.exe diff --git a/spec/build/testsuites/validation/validation-0.yml b/spec/build/testsuites/validation/validation-0.yml index 03a6f4385c..6419717479 100644 --- a/spec/build/testsuites/validation/validation-0.yml +++ b/spec/build/testsuites/validation/validation-0.yml @@ -13,7 +13,6 @@ links: [] source: - testsuites/validation/tc-acfg-appl-needs-clock-driver.c - testsuites/validation/tc-event-send-receive.c -- testsuites/validation/tc-message-construct-errors.c - testsuites/validation/tc-object.c - testsuites/validation/tc-signal-catch.c - testsuites/validation/tc-signal-send.c diff --git a/spec/build/testsuites/validation/validation-no-clock-0.yml b/spec/build/testsuites/validation/validation-no-clock-0.yml index 616f681f9f..1b68da8798 100644 --- a/spec/build/testsuites/validation/validation-no-clock-0.yml +++ b/spec/build/testsuites/validation/validation-no-clock-0.yml @@ -31,6 +31,14 @@ source: - testsuites/validation/tc-io-getchark.c - testsuites/validation/tc-io-putc.c - testsuites/validation/tc-io-put-char.c +- testsuites/validation/tc-message-broadcast.c +- testsuites/validation/tc-message-construct.c +- testsuites/validation/tc-message-delete.c +- testsuites/validation/tc-message-flush-pending.c +- testsuites/validation/tc-message-ident.c +- testsuites/validation/tc-message-macros.c +- testsuites/validation/tc-message-receive.c +- testsuites/validation/tc-message-urgent-send.c - testsuites/validation/tc-score-fatal.c - testsuites/validation/tr-event-constant.c - testsuites/validation/tr-mtx-seize-try.c diff --git a/testsuites/validation/tc-message-broadcast.c b/testsuites/validation/tc-message-broadcast.c new file mode 100644 index 0000000000..62e5aa5c7e --- /dev/null +++ b/testsuites/validation/tc-message-broadcast.c @@ -0,0 +1,1204 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqBroadcast + */ + +/* + * 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 RTEMSTestCaseRtemsMessageReqBroadcast \ + * spec:/rtems/message/req/broadcast + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqBroadcast_Pre_SendBuffer_Valid, + RtemsMessageReqBroadcast_Pre_SendBuffer_Null, + RtemsMessageReqBroadcast_Pre_SendBuffer_NA +} RtemsMessageReqBroadcast_Pre_SendBuffer; + +typedef enum { + RtemsMessageReqBroadcast_Pre_Count_Valid, + RtemsMessageReqBroadcast_Pre_Count_Null, + RtemsMessageReqBroadcast_Pre_Count_NA +} RtemsMessageReqBroadcast_Pre_Count; + +typedef enum { + RtemsMessageReqBroadcast_Pre_Id_Valid, + RtemsMessageReqBroadcast_Pre_Id_Invalid, + RtemsMessageReqBroadcast_Pre_Id_NA +} RtemsMessageReqBroadcast_Pre_Id; + +typedef enum { + RtemsMessageReqBroadcast_Pre_MsgSize_Zero, + RtemsMessageReqBroadcast_Pre_MsgSize_SomeSize, + RtemsMessageReqBroadcast_Pre_MsgSize_MaxSize, + RtemsMessageReqBroadcast_Pre_MsgSize_TooLarge, + RtemsMessageReqBroadcast_Pre_MsgSize_NA +} RtemsMessageReqBroadcast_Pre_MsgSize; + +typedef enum { + RtemsMessageReqBroadcast_Pre_MsgQueue_Empty, + RtemsMessageReqBroadcast_Pre_MsgQueue_Several, + RtemsMessageReqBroadcast_Pre_MsgQueue_NA +} RtemsMessageReqBroadcast_Pre_MsgQueue; + +typedef enum { + RtemsMessageReqBroadcast_Pre_Receivers_Waiting, + RtemsMessageReqBroadcast_Pre_Receivers_None, + RtemsMessageReqBroadcast_Pre_Receivers_NA +} RtemsMessageReqBroadcast_Pre_Receivers; + +typedef enum { + RtemsMessageReqBroadcast_Pre_Storage_Nop, + RtemsMessageReqBroadcast_Pre_Storage_NA +} RtemsMessageReqBroadcast_Pre_Storage; + +typedef enum { + RtemsMessageReqBroadcast_Post_Status_Ok, + RtemsMessageReqBroadcast_Post_Status_InvId, + RtemsMessageReqBroadcast_Post_Status_InvAddr, + RtemsMessageReqBroadcast_Post_Status_InvSize, + RtemsMessageReqBroadcast_Post_Status_NA +} RtemsMessageReqBroadcast_Post_Status; + +typedef enum { + RtemsMessageReqBroadcast_Post_Count_Zero, + RtemsMessageReqBroadcast_Post_Count_Set, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_Count_NA +} RtemsMessageReqBroadcast_Post_Count; + +typedef enum { + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_NA +} RtemsMessageReqBroadcast_Post_MsgQueue; + +typedef enum { + RtemsMessageReqBroadcast_Post_Receivers_Unblocked, + RtemsMessageReqBroadcast_Post_Receivers_Nop, + RtemsMessageReqBroadcast_Post_Receivers_NA +} RtemsMessageReqBroadcast_Post_Receivers; + +typedef enum { + RtemsMessageReqBroadcast_Post_RecSize_Message, + RtemsMessageReqBroadcast_Post_RecSize_Nop, + RtemsMessageReqBroadcast_Post_RecSize_NA +} RtemsMessageReqBroadcast_Post_RecSize; + +typedef enum { + RtemsMessageReqBroadcast_Post_RecBuffer_Message, + RtemsMessageReqBroadcast_Post_RecBuffer_Nop, + RtemsMessageReqBroadcast_Post_RecBuffer_NA +} RtemsMessageReqBroadcast_Post_RecBuffer; + +typedef struct { + uint32_t Skip : 1; + uint32_t Pre_SendBuffer_NA : 1; + uint32_t Pre_Count_NA : 1; + uint32_t Pre_Id_NA : 1; + uint32_t Pre_MsgSize_NA : 1; + uint32_t Pre_MsgQueue_NA : 1; + uint32_t Pre_Receivers_NA : 1; + uint32_t Pre_Storage_NA : 1; + uint32_t Post_Status : 3; + uint32_t Post_Count : 2; + uint32_t Post_MsgQueue : 1; + uint32_t Post_Receivers : 2; + uint32_t Post_RecSize : 2; + uint32_t Post_RecBuffer : 2; +} RtemsMessageReqBroadcast_Entry; + +#define MAXIMUM_PENDING_MESSAGES 3 +#define MAXIMUM_MESSAGE_SIZE 5 +#define NUMBER_OF_WORKERS 3 + +/** + * @brief Test context for spec:/rtems/message/req/broadcast test case. + */ +typedef struct { + /** + * @brief This member contains a valid ID of a message queue. + */ + rtems_id message_queue_id; + + /** + * @brief This member is used as storage area for the message queue. + */ + RTEMS_MESSAGE_QUEUE_BUFFER( MAXIMUM_MESSAGE_SIZE ) + storage_area[ MAXIMUM_PENDING_MESSAGES ]; + + /** + * @brief This member contains a buffer to receive messages from the queue. + */ + uint8_t receive_buffer[ NUMBER_OF_WORKERS ][ MAXIMUM_MESSAGE_SIZE ]; + + /** + * @brief This member contains several buffers to receive a messages size. + */ + size_t receive_size[ NUMBER_OF_WORKERS ]; + + /** + * @brief This member contains the returned status codes of the receivers. + */ + rtems_status_code receive_status[ NUMBER_OF_WORKERS ]; + + /** + * @brief This member specifies the ``id`` parameter of the action. + */ + rtems_id id_param; + + /** + * @brief This member specifies the ``buffer`` parameter of the action. + */ + const void *buffer_param; + + /** + * @brief This member specifies the ``size`` parameter of the action. + */ + size_t size_param; + + /** + * @brief This member specifies the ``count`` parameter of the action. + */ + uint32_t *count_param; + + /** + * @brief This member contains the returned status code of the action. + */ + rtems_status_code status; + + /** + * @brief This member contains the value returned in parameter ``count`` of + * the action. + */ + uint32_t count; + + /** + * @brief This member contains the task identifiers of the worker tasks. + */ + rtems_id worker_id[ NUMBER_OF_WORKERS ]; + + /** + * @brief This member contains a pointer to a function which is executed to + * check that the action has not changed the content of the message queue. + */ + void (*check_msgq_unchanged)( void *ctx_in ); + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 7 ]; + + /** + * @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. + */ + RtemsMessageReqBroadcast_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqBroadcast_Context; + +static RtemsMessageReqBroadcast_Context + RtemsMessageReqBroadcast_Instance; + +static const char * const RtemsMessageReqBroadcast_PreDesc_SendBuffer[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_Count[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_Id[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_MsgSize[] = { + "Zero", + "SomeSize", + "MaxSize", + "TooLarge", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_MsgQueue[] = { + "Empty", + "Several", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_Receivers[] = { + "Waiting", + "None", + "NA" +}; + +static const char * const RtemsMessageReqBroadcast_PreDesc_Storage[] = { + "Nop", + "NA" +}; + +static const char * const * const RtemsMessageReqBroadcast_PreDesc[] = { + RtemsMessageReqBroadcast_PreDesc_SendBuffer, + RtemsMessageReqBroadcast_PreDesc_Count, + RtemsMessageReqBroadcast_PreDesc_Id, + RtemsMessageReqBroadcast_PreDesc_MsgSize, + RtemsMessageReqBroadcast_PreDesc_MsgQueue, + RtemsMessageReqBroadcast_PreDesc_Receivers, + RtemsMessageReqBroadcast_PreDesc_Storage, + NULL +}; + +typedef RtemsMessageReqBroadcast_Context Context; +static const rtems_interval TIMEOUT_TICKS = 1; +static const rtems_event_set EVENT_RECEIVE = RTEMS_EVENT_17; +static const uint8_t message[ MAXIMUM_MESSAGE_SIZE ] = + { 13, 42, 99, 222, 101 }; +static const uint8_t queued_message[] = { 200, 201, 202 }; + +static void Receive( Context *ctx, size_t worker_index ) +{ + ctx->receive_status[worker_index] = rtems_message_queue_receive( + ctx->message_queue_id, + ctx->receive_buffer[worker_index], + &ctx->receive_size[worker_index], + RTEMS_WAIT, + TIMEOUT_TICKS + ); +} + +static void WorkerTask( rtems_task_argument argument ) +{ + static size_t worker_number = 0; + size_t worker_index = worker_number++; + Context *ctx = (Context *) argument; + + while ( true ) { + ReceiveAnyEvents(); + Receive( ctx, worker_index ); + } +} + +static void CheckForNoMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + (void) message_buffer; + (void) message_size; + T_rsc( status, RTEMS_UNSATISFIED ); +} + +static void CheckForMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + T_rsc_success( status ); + T_eq_u32( message_size, ctx->size_param ); + T_eq_mem( message_buffer, message, ctx->size_param ); +} + +static void CheckForQueuedMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc_success( status ); + T_eq_u32( message_size, sizeof( queued_message ) ); + T_eq_mem( message_buffer, queued_message, sizeof( queued_message ) ); +} + +static void PopMessage( + Context *ctx, + void (*check_fn)( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size + ) +) +{ + rtems_status_code status; + uint8_t message_buffer[ MAXIMUM_MESSAGE_SIZE ]; + size_t message_size; + + status = rtems_message_queue_receive( + ctx->message_queue_id, + &message_buffer, + &message_size, + RTEMS_LOCAL | RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT + ); + + check_fn( ctx, status, message_buffer, message_size ); +} + +static void CheckForNoMessageInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + PopMessage( ctx, CheckForNoMessage ); +} + +static void CheckForSeveralMessagesInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + PopMessage( ctx, CheckForQueuedMessage ); + PopMessage( ctx, CheckForQueuedMessage ); + PopMessage( ctx, CheckForNoMessage ); +} + +static void SendMsg( Context *ctx ) +{ + rtems_status_code status; + + status = rtems_message_queue_send( + ctx->message_queue_id, + queued_message, + sizeof( queued_message ) + ); + T_rsc_success( status ); +} + +static void RtemsMessageReqBroadcast_Pre_SendBuffer_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_SendBuffer state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_SendBuffer_Valid: { + /* + * While the ``buffer`` parameter references a memory area where the + * message to be sent is stored. + */ + ctx->buffer_param = &message; + break; + } + + case RtemsMessageReqBroadcast_Pre_SendBuffer_Null: { + /* + * While the ``buffer`` parameter is NULL. + */ + ctx->buffer_param = NULL; + break; + } + + case RtemsMessageReqBroadcast_Pre_SendBuffer_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_Count_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_Count state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_Count_Valid: { + /* + * While the ``count`` parameter references an ``uint32_t`` object. + */ + ctx->count_param = &ctx->count; + break; + } + + case RtemsMessageReqBroadcast_Pre_Count_Null: { + /* + * While the ``count`` parameter is NULL. + */ + ctx->count_param = NULL; + break; + } + + case RtemsMessageReqBroadcast_Pre_Count_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_Id_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_Id_Valid: { + /* + * While the ``id`` parameter is valid. + */ + ctx->id_param = ctx->message_queue_id; + break; + } + + case RtemsMessageReqBroadcast_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is invalid. + */ + ctx->id_param = RTEMS_ID_NONE; + break; + } + + case RtemsMessageReqBroadcast_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_MsgSize_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_MsgSize state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_MsgSize_Zero: { + /* + * While the ``size`` parameter is 0. + */ + ctx->size_param = 0; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgSize_SomeSize: { + /* + * While the ``size`` parameter has a value between 0 and the maximum + * message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE / 2 + 1; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgSize_MaxSize: { + /* + * While the ``size`` parameter has a value of the maximum message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgSize_TooLarge: { + /* + * While the ``size`` parameter has a value greater than the maximum + * message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE + 1; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgSize_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_MsgQueue_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_MsgQueue_Empty: { + /* + * While there is no message in the message queue. + */ + /* Message queue is already empty. */ + ctx->check_msgq_unchanged = CheckForNoMessageInQueue; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgQueue_Several: { + /* + * While there are messages in the message queue. + */ + SendMsg( ctx ); + SendMsg( ctx ); + ctx->check_msgq_unchanged = CheckForSeveralMessagesInQueue; + break; + } + + case RtemsMessageReqBroadcast_Pre_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_Receivers_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_Receivers state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_Receivers_Waiting: { + /* + * While one or more receivers are waiting to receive a message. + */ + size_t i; + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + SendEvents( ctx->worker_id[i], EVENT_RECEIVE ); + } + break; + } + + case RtemsMessageReqBroadcast_Pre_Receivers_None: { + /* + * While no receiver is waiting to receive a message. + */ + /* There is already no receiver waiting. */ + break; + } + + case RtemsMessageReqBroadcast_Pre_Receivers_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Pre_Storage_Prepare( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Pre_Storage state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Pre_Storage_Nop: { + /* + * While the memory area to which a pointer is provided as member + * storage_area of type rtems_message_queue_config when the message queue + * is constructed by rtems_message_queue_construct() is altered only by + * the RTEMS operating system. + */ + /* Only a requirement text. */ + break; + } + + case RtemsMessageReqBroadcast_Pre_Storage_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_Status_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Post_Status_Ok: { + /* + * The return status of rtems_message_queue_broadcast() shall be + * RTEMS_SUCCESSFUL + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqBroadcast_Post_Status_InvId: { + /* + * The return status of rtems_message_queue_broadcast() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsMessageReqBroadcast_Post_Status_InvAddr: { + /* + * The return status of rtems_message_queue_broadcast() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsMessageReqBroadcast_Post_Status_InvSize: { + /* + * The return status of rtems_message_queue_broadcast() shall be + * RTEMS_INVALID_SIZE. + */ + T_rsc( ctx->status, RTEMS_INVALID_SIZE ); + break; + } + + case RtemsMessageReqBroadcast_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_Count_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_Count state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Post_Count_Zero: { + /* + * The value of the object referenced by the ``count`` parameter shall be + * set to 0 after the return of the rtems_message_queue_broadcast() call. + */ + T_eq_u32( ctx->count, 0 ); + break; + } + + case RtemsMessageReqBroadcast_Post_Count_Set: { + /* + * The value of the object referenced by the ``count`` parameter shall be + * set to the number of tasks unblocked (see unblock) by the call to + * directive rtems_message_queue_broadcast() after the return of the + * rtems_message_queue_broadcast() call. + */ + T_eq_u32( ctx->count, NUMBER_OF_WORKERS ); + break; + } + + case RtemsMessageReqBroadcast_Post_Count_Nop: { + /* + * The value of the object referenced by the ``count`` parameter in past + * call to rtems_message_queue_broadcast() shall not be accessed by the + * rtems_message_queue_broadcast() call (see also Nop). + */ + T_eq_u32( ctx->count, UINT8_MAX ); + break; + } + + case RtemsMessageReqBroadcast_Post_Count_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_MsgQueue_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqBroadcast_Post_MsgQueue_Nop: { + /* + * Objects referenced by the ``id`` parameter in the past call to + * rtems_message_queue_broadcast() shall not be accessed by that call + * (see also Nop). + */ + ctx->check_msgq_unchanged( ctx ); + break; + } + + case RtemsMessageReqBroadcast_Post_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_Receivers_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_Receivers state +) +{ + size_t i; + + switch ( state ) { + case RtemsMessageReqBroadcast_Post_Receivers_Unblocked: { + /* + * The call to the rtems_message_queue_broadcast() directive shall + * unblock all receivers waiting for a message at the message queue. + * + * Note: Currently, rtems_message_queue_broadcast() unblocks receivers in + * a none-atomic way. Meaning, it will not only unblock those receivers + * it finds waiting at the queue when rtems_message_queue_broadcast() is + * invoked but also any new receivers which start waiting for messages + * after rtems_message_queue_broadcast() is invoked and before it + * returns. This may lead to infinite unblocking loops. + */ + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + T_rsc_success( ctx->receive_status[i] ); + } + break; + } + + case RtemsMessageReqBroadcast_Post_Receivers_Nop: { + /* + * The receivers waiting for a message at the message queue shall not be + * affected by the call to the rtems_message_queue_broadcast() directive. + */ + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + T_rsc( ctx->receive_status[i], RTEMS_TIMEOUT ); + } + break; + } + + case RtemsMessageReqBroadcast_Post_Receivers_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_RecSize_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_RecSize state +) +{ + size_t i; + + switch ( state ) { + case RtemsMessageReqBroadcast_Post_RecSize_Message: { + /* + * The values of the objects referenced by the ``size`` parameter in all + * calls to rtems_message_queue_receive() which are unblocked (see + * unblock) by the rtems_message_queue_broadcast() call shall be set to + * the same value as provided by parameter ``size`` of the + * rtems_message_queue_broadcast() call after the return of the + * rtems_message_queue_broadcast() call. + */ + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + CheckForMessage( + ctx, + ctx->receive_status[i], + ctx->receive_buffer[i], + ctx->receive_size[i] + ); + } + break; + } + + case RtemsMessageReqBroadcast_Post_RecSize_Nop: { + /* + * Objects referenced by the ``size`` parameter in past calls to + * rtems_message_queue_receive() shall not be accessed by the + * rtems_message_queue_broadcast() call (see also Nop). + */ + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + T_eq_sz( ctx->receive_size[i], SIZE_MAX ); + } + break; + } + + case RtemsMessageReqBroadcast_Post_RecSize_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Post_RecBuffer_Check( + RtemsMessageReqBroadcast_Context *ctx, + RtemsMessageReqBroadcast_Post_RecBuffer state +) +{ + size_t w, i; + + switch ( state ) { + case RtemsMessageReqBroadcast_Post_RecBuffer_Message: { + /* + * Bytes 0 till ``size`` - 1 of the object referenced by the ``buffer`` + * parameter in all calls to rtems_message_queue_receive() which are + * unblocked (see unblock) by the rtems_message_queue_broadcast() call + * shall be set to the same values as bytes 0 till ``size`` - 1 of the + * object referenced by parameter ``buffer`` of the + * rtems_message_queue_broadcast() call after the return of the + * rtems_message_queue_receive() call. + */ + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + CheckForMessage( + ctx, + ctx->receive_status[i], + ctx->receive_buffer[i], + ctx->receive_size[i] + ); + } + break; + } + + case RtemsMessageReqBroadcast_Post_RecBuffer_Nop: { + /* + * Objects referenced by the ``buffer`` parameter in past calls to + * rtems_message_queue_receive() shall not be accessed by the + * rtems_message_queue_broadcast() call (see also Nop). + */ + for ( w = 0; w < NUMBER_OF_WORKERS; ++w ) { + for ( i = 0; i < MAXIMUM_MESSAGE_SIZE; ++i ) { + T_eq_u8( ctx->receive_buffer[w][i], UINT8_MAX ); + } + } + break; + } + + case RtemsMessageReqBroadcast_Post_RecBuffer_NA: + break; + } +} + +static void RtemsMessageReqBroadcast_Setup( + RtemsMessageReqBroadcast_Context *ctx +) +{ + size_t i; + SetSelfPriority( PRIO_NORMAL ); + + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + ctx->worker_id[i] = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id[i], WorkerTask, ctx ); + } +} + +static void RtemsMessageReqBroadcast_Setup_Wrap( void *arg ) +{ + RtemsMessageReqBroadcast_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqBroadcast_Setup( ctx ); +} + +static void RtemsMessageReqBroadcast_Teardown( + RtemsMessageReqBroadcast_Context *ctx +) +{ + size_t i; + + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + DeleteTask( ctx->worker_id[i] ); + } + RestoreRunnerPriority(); +} + +static void RtemsMessageReqBroadcast_Teardown_Wrap( void *arg ) +{ + RtemsMessageReqBroadcast_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqBroadcast_Teardown( ctx ); +} + +static void RtemsMessageReqBroadcast_Prepare( + RtemsMessageReqBroadcast_Context *ctx +) +{ + rtems_status_code status; + size_t i; + + rtems_message_queue_config config = { + .name = rtems_build_name( 'M', 'S', 'G', 'Q' ), + .maximum_pending_messages = MAXIMUM_PENDING_MESSAGES, + .maximum_message_size = MAXIMUM_MESSAGE_SIZE, + .storage_area = ctx->storage_area, + .storage_size = sizeof( ctx->storage_area ), + .storage_free = NULL, + .attributes = RTEMS_DEFAULT_ATTRIBUTES + }; + + status = rtems_message_queue_construct( + &config, + &ctx->message_queue_id + ); + T_rsc_success( status ); + + ctx->count = UINT8_MAX; + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + ctx->receive_size[i] = SIZE_MAX; + memset( ctx->receive_buffer[i], UINT8_MAX, MAXIMUM_MESSAGE_SIZE ); + } +} + +static void RtemsMessageReqBroadcast_Action( + RtemsMessageReqBroadcast_Context *ctx +) +{ + ctx->status = rtems_message_queue_broadcast( + ctx->id_param, + ctx->buffer_param, + ctx->size_param, + ctx->count_param + ); + + FinalClockTick(); +} + +static void RtemsMessageReqBroadcast_Cleanup( + RtemsMessageReqBroadcast_Context *ctx +) +{ + T_rsc_success( rtems_message_queue_delete( ctx->message_queue_id ) ); +} + +static const RtemsMessageReqBroadcast_Entry +RtemsMessageReqBroadcast_Entries[] = { + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvAddr, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_NA, + RtemsMessageReqBroadcast_Post_RecSize_NA, + RtemsMessageReqBroadcast_Post_RecBuffer_NA }, + { 1, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_NA, + RtemsMessageReqBroadcast_Post_Count_NA, + RtemsMessageReqBroadcast_Post_MsgQueue_NA, + RtemsMessageReqBroadcast_Post_Receivers_NA, + RtemsMessageReqBroadcast_Post_RecSize_NA, + RtemsMessageReqBroadcast_Post_RecBuffer_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvAddr, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_Nop, + RtemsMessageReqBroadcast_Post_RecSize_Nop, + RtemsMessageReqBroadcast_Post_RecBuffer_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvId, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_NA, + RtemsMessageReqBroadcast_Post_RecSize_NA, + RtemsMessageReqBroadcast_Post_RecBuffer_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_Ok, + RtemsMessageReqBroadcast_Post_Count_Zero, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_NA, + RtemsMessageReqBroadcast_Post_RecSize_NA, + RtemsMessageReqBroadcast_Post_RecBuffer_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvId, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_Nop, + RtemsMessageReqBroadcast_Post_RecSize_Nop, + RtemsMessageReqBroadcast_Post_RecBuffer_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_Ok, + RtemsMessageReqBroadcast_Post_Count_Set, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_Unblocked, + RtemsMessageReqBroadcast_Post_RecSize_Message, + RtemsMessageReqBroadcast_Post_RecBuffer_Message }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvSize, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_NA, + RtemsMessageReqBroadcast_Post_RecSize_NA, + RtemsMessageReqBroadcast_Post_RecBuffer_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqBroadcast_Post_Status_InvSize, + RtemsMessageReqBroadcast_Post_Count_Nop, + RtemsMessageReqBroadcast_Post_MsgQueue_Nop, + RtemsMessageReqBroadcast_Post_Receivers_Nop, + RtemsMessageReqBroadcast_Post_RecSize_Nop, + RtemsMessageReqBroadcast_Post_RecBuffer_Nop } +}; + +static const uint8_t +RtemsMessageReqBroadcast_Map[] = { + 6, 4, 1, 4, 6, 4, 1, 4, 6, 4, 1, 4, 8, 7, 1, 7, 5, 3, 1, 3, 5, 3, 1, 3, 5, 3, + 1, 3, 5, 3, 1, 3, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, + 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, + 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0 +}; + +static size_t RtemsMessageReqBroadcast_Scope( void *arg, char *buf, size_t n ) +{ + RtemsMessageReqBroadcast_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( + RtemsMessageReqBroadcast_PreDesc, + buf, + n, + ctx->Map.pcs + ); + } + + return 0; +} + +static T_fixture RtemsMessageReqBroadcast_Fixture = { + .setup = RtemsMessageReqBroadcast_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageReqBroadcast_Teardown_Wrap, + .scope = RtemsMessageReqBroadcast_Scope, + .initial_context = &RtemsMessageReqBroadcast_Instance +}; + +static inline RtemsMessageReqBroadcast_Entry RtemsMessageReqBroadcast_PopEntry( + RtemsMessageReqBroadcast_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqBroadcast_Entries[ + RtemsMessageReqBroadcast_Map[ index ] + ]; +} + +static void RtemsMessageReqBroadcast_TestVariant( + RtemsMessageReqBroadcast_Context *ctx +) +{ + RtemsMessageReqBroadcast_Pre_SendBuffer_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqBroadcast_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + RtemsMessageReqBroadcast_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + RtemsMessageReqBroadcast_Pre_MsgSize_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + RtemsMessageReqBroadcast_Pre_MsgQueue_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + RtemsMessageReqBroadcast_Pre_Receivers_Prepare( ctx, ctx->Map.pcs[ 5 ] ); + RtemsMessageReqBroadcast_Pre_Storage_Prepare( ctx, ctx->Map.pcs[ 6 ] ); + RtemsMessageReqBroadcast_Action( ctx ); + RtemsMessageReqBroadcast_Post_Status_Check( + ctx, + ctx->Map.entry.Post_Status + ); + RtemsMessageReqBroadcast_Post_Count_Check( ctx, ctx->Map.entry.Post_Count ); + RtemsMessageReqBroadcast_Post_MsgQueue_Check( + ctx, + ctx->Map.entry.Post_MsgQueue + ); + RtemsMessageReqBroadcast_Post_Receivers_Check( + ctx, + ctx->Map.entry.Post_Receivers + ); + RtemsMessageReqBroadcast_Post_RecSize_Check( + ctx, + ctx->Map.entry.Post_RecSize + ); + RtemsMessageReqBroadcast_Post_RecBuffer_Check( + ctx, + ctx->Map.entry.Post_RecBuffer + ); +} + +/** + * @fn void T_case_body_RtemsMessageReqBroadcast( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsMessageReqBroadcast, + &RtemsMessageReqBroadcast_Fixture +) +{ + RtemsMessageReqBroadcast_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqBroadcast_Pre_SendBuffer_Valid; + ctx->Map.pcs[ 0 ] < RtemsMessageReqBroadcast_Pre_SendBuffer_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = RtemsMessageReqBroadcast_Pre_Count_Valid; + ctx->Map.pcs[ 1 ] < RtemsMessageReqBroadcast_Pre_Count_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = RtemsMessageReqBroadcast_Pre_Id_Valid; + ctx->Map.pcs[ 2 ] < RtemsMessageReqBroadcast_Pre_Id_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = RtemsMessageReqBroadcast_Pre_MsgSize_Zero; + ctx->Map.pcs[ 3 ] < RtemsMessageReqBroadcast_Pre_MsgSize_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = RtemsMessageReqBroadcast_Pre_MsgQueue_Empty; + ctx->Map.pcs[ 4 ] < RtemsMessageReqBroadcast_Pre_MsgQueue_NA; + ++ctx->Map.pcs[ 4 ] + ) { + for ( + ctx->Map.pcs[ 5 ] = RtemsMessageReqBroadcast_Pre_Receivers_Waiting; + ctx->Map.pcs[ 5 ] < RtemsMessageReqBroadcast_Pre_Receivers_NA; + ++ctx->Map.pcs[ 5 ] + ) { + for ( + ctx->Map.pcs[ 6 ] = RtemsMessageReqBroadcast_Pre_Storage_Nop; + ctx->Map.pcs[ 6 ] < RtemsMessageReqBroadcast_Pre_Storage_NA; + ++ctx->Map.pcs[ 6 ] + ) { + ctx->Map.entry = RtemsMessageReqBroadcast_PopEntry( ctx ); + + if ( ctx->Map.entry.Skip ) { + continue; + } + + RtemsMessageReqBroadcast_Prepare( ctx ); + RtemsMessageReqBroadcast_TestVariant( ctx ); + RtemsMessageReqBroadcast_Cleanup( ctx ); + } + } + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-message-construct-errors.c b/testsuites/validation/tc-message-construct-errors.c deleted file mode 100644 index 570160b947..0000000000 --- a/testsuites/validation/tc-message-construct-errors.c +++ /dev/null @@ -1,932 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSTestCaseRtemsMessageReqConstructErrors - */ - -/* - * Copyright (C) 2020, 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 RTEMSTestCaseRtemsMessageReqConstructErrors \ - * spec:/rtems/message/req/construct-errors - * - * @ingroup RTEMSTestSuiteTestsuitesValidation0 - * - * @{ - */ - -typedef enum { - RtemsMessageReqConstructErrors_Pre_Config_Valid, - RtemsMessageReqConstructErrors_Pre_Config_Null, - RtemsMessageReqConstructErrors_Pre_Config_NA -} RtemsMessageReqConstructErrors_Pre_Config; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_Name_Valid, - RtemsMessageReqConstructErrors_Pre_Name_Invalid, - RtemsMessageReqConstructErrors_Pre_Name_NA -} RtemsMessageReqConstructErrors_Pre_Name; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_Id_Id, - RtemsMessageReqConstructErrors_Pre_Id_Null, - RtemsMessageReqConstructErrors_Pre_Id_NA -} RtemsMessageReqConstructErrors_Pre_Id; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_MaxPending_Valid, - RtemsMessageReqConstructErrors_Pre_MaxPending_Zero, - RtemsMessageReqConstructErrors_Pre_MaxPending_Big, - RtemsMessageReqConstructErrors_Pre_MaxPending_NA -} RtemsMessageReqConstructErrors_Pre_MaxPending; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_MaxSize_Valid, - RtemsMessageReqConstructErrors_Pre_MaxSize_Zero, - RtemsMessageReqConstructErrors_Pre_MaxSize_Big, - RtemsMessageReqConstructErrors_Pre_MaxSize_NA -} RtemsMessageReqConstructErrors_Pre_MaxSize; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_Free_Yes, - RtemsMessageReqConstructErrors_Pre_Free_No, - RtemsMessageReqConstructErrors_Pre_Free_NA -} RtemsMessageReqConstructErrors_Pre_Free; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_Area_Valid, - RtemsMessageReqConstructErrors_Pre_Area_Null, - RtemsMessageReqConstructErrors_Pre_Area_NA -} RtemsMessageReqConstructErrors_Pre_Area; - -typedef enum { - RtemsMessageReqConstructErrors_Pre_AreaSize_Valid, - RtemsMessageReqConstructErrors_Pre_AreaSize_Invalid, - RtemsMessageReqConstructErrors_Pre_AreaSize_NA -} RtemsMessageReqConstructErrors_Pre_AreaSize; - -typedef enum { - RtemsMessageReqConstructErrors_Post_Status_Ok, - RtemsMessageReqConstructErrors_Post_Status_InvAddr, - RtemsMessageReqConstructErrors_Post_Status_InvName, - RtemsMessageReqConstructErrors_Post_Status_InvNum, - RtemsMessageReqConstructErrors_Post_Status_InvSize, - RtemsMessageReqConstructErrors_Post_Status_TooMany, - RtemsMessageReqConstructErrors_Post_Status_Unsat, - RtemsMessageReqConstructErrors_Post_Status_NA -} RtemsMessageReqConstructErrors_Post_Status; - -typedef enum { - RtemsMessageReqConstructErrors_Post_Name_Valid, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_Name_NA -} RtemsMessageReqConstructErrors_Post_Name; - -typedef enum { - RtemsMessageReqConstructErrors_Post_IdVar_Set, - RtemsMessageReqConstructErrors_Post_IdVar_Nop, - RtemsMessageReqConstructErrors_Post_IdVar_NA -} RtemsMessageReqConstructErrors_Post_IdVar; - -/** - * @brief Test context for spec:/rtems/message/req/construct-errors test case. - */ -typedef struct { - rtems_status_code status; - - const rtems_message_queue_config *config; - - rtems_message_queue_config config_value; - - rtems_id *id; - - rtems_id id_value; - - void *seized_objects; - - /** - * @brief This member defines the pre-condition states for the next action. - */ - size_t pcs[ 8 ]; - - /** - * @brief This member indicates if the test action loop is currently - * executed. - */ - bool in_action_loop; -} RtemsMessageReqConstructErrors_Context; - -static RtemsMessageReqConstructErrors_Context - RtemsMessageReqConstructErrors_Instance; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_Config[] = { - "Valid", - "Null", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_Name[] = { - "Valid", - "Invalid", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_Id[] = { - "Id", - "Null", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_MaxPending[] = { - "Valid", - "Zero", - "Big", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_MaxSize[] = { - "Valid", - "Zero", - "Big", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_Free[] = { - "Yes", - "No", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_Area[] = { - "Valid", - "Null", - "NA" -}; - -static const char * const RtemsMessageReqConstructErrors_PreDesc_AreaSize[] = { - "Valid", - "Invalid", - "NA" -}; - -static const char * const * const RtemsMessageReqConstructErrors_PreDesc[] = { - RtemsMessageReqConstructErrors_PreDesc_Config, - RtemsMessageReqConstructErrors_PreDesc_Name, - RtemsMessageReqConstructErrors_PreDesc_Id, - RtemsMessageReqConstructErrors_PreDesc_MaxPending, - RtemsMessageReqConstructErrors_PreDesc_MaxSize, - RtemsMessageReqConstructErrors_PreDesc_Free, - RtemsMessageReqConstructErrors_PreDesc_Area, - RtemsMessageReqConstructErrors_PreDesc_AreaSize, - NULL -}; - -#define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) - -#define MAX_MESSAGE_QUEUES 4 - -#define MAX_PENDING_MESSAGES 1 - -#define MAX_MESSAGE_SIZE 1 - -static RTEMS_MESSAGE_QUEUE_BUFFER( MAX_MESSAGE_SIZE ) - buffers_to_seize[ MAX_MESSAGE_QUEUES ][ MAX_PENDING_MESSAGES ]; - -static RTEMS_MESSAGE_QUEUE_BUFFER( MAX_MESSAGE_SIZE ) - buffers[ MAX_PENDING_MESSAGES ]; - -static rtems_status_code Create( void *arg, uint32_t *id ) -{ - rtems_message_queue_config config; - size_t *i; - - i = arg; - T_quiet_lt_sz( *i, MAX_MESSAGE_QUEUES ); - - memset( &config, 0, sizeof( config ) ); - config.name = rtems_build_name( 'S', 'I', 'Z', 'E' ); - config.maximum_pending_messages = MAX_PENDING_MESSAGES; - config.maximum_message_size = MAX_MESSAGE_SIZE; - config.storage_size = sizeof( buffers_to_seize[ *i ] ); - config.storage_area = buffers_to_seize[ *i ]; - config.attributes = RTEMS_DEFAULT_ATTRIBUTES; - - ++(*i); - - return rtems_message_queue_construct( &config, id ); -} - -static void RtemsMessageReqConstructErrors_Pre_Config_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_Config state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_Config_Valid: { - /* - * While the ``config`` parameter references an object of type - * rtems_message_queue_config. - */ - ctx->config = &ctx->config_value; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Config_Null: { - /* - * While the ``config`` parameter is NULL. - */ - ctx->config = NULL; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Config_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_Name_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_Name state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_Name_Valid: { - /* - * While the name of the message queue configuration is valid. - */ - ctx->config_value.name = NAME; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Name_Invalid: { - /* - * While the name of the message queue configuration is invalid. - */ - ctx->config_value.name = 0; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Name_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_Id_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_Id state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_Id_Id: { - /* - * While the ``id`` parameter references an object of type rtems_id. - */ - ctx->id = &ctx->id_value; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Id_Null: { - /* - * While the ``id`` parameter is NULL. - */ - ctx->id = NULL; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Id_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_MaxPending_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_MaxPending state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_MaxPending_Valid: { - /* - * While the maximum number of pending messages of the message queue - * configuration is valid. - */ - ctx->config_value.maximum_pending_messages = MAX_PENDING_MESSAGES; - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxPending_Zero: { - /* - * While the maximum number of pending messages of the message queue - * configuration is zero. - */ - ctx->config_value.maximum_pending_messages = 0; - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxPending_Big: { - /* - * While the maximum number of pending messages of the message queue - * configuration is big enough so that a calculation to get the message - * buffer storage area size overflows. - */ - ctx->config_value.maximum_pending_messages = UINT32_MAX; - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxPending_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_MaxSize_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_MaxSize state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_MaxSize_Valid: { - /* - * While the maximum message size of the message queue configuration is - * valid. - */ - if ( ctx->config_value.maximum_pending_messages == UINT32_MAX ) { - /* - * At least on 64-bit systems we need a bit of help to ensure that we - * meet the Big state of the MaxPending pre-condition. The following - * message size is valid with respect to calculations involving only - * the message size. - */ - ctx->config_value.maximum_message_size = SIZE_MAX - sizeof( uintptr_t ) + - 1 - sizeof( CORE_message_queue_Buffer ); - } else { - ctx->config_value.maximum_message_size = MAX_MESSAGE_SIZE; - } - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxSize_Zero: { - /* - * While the maximum message size of the message queue configuration is - * zero. - */ - ctx->config_value.maximum_message_size = 0; - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxSize_Big: { - /* - * While the maximum message size of the message queue configuration is - * big enough so that a calculation to get the message buffer storage - * area size overflows. - */ - ctx->config_value.maximum_message_size = SIZE_MAX; - break; - } - - case RtemsMessageReqConstructErrors_Pre_MaxSize_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_Free_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_Free state -) -{ - size_t i; - - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_Free_Yes: { - /* - * While the system has at least one inactive message queue object - * available. - */ - /* Nothing to do */ - break; - } - - case RtemsMessageReqConstructErrors_Pre_Free_No: { - /* - * While the system has no inactive message queue object available. - */ - i = 0; - ctx->seized_objects = T_seize_objects( Create, &i ); - break; - } - - case RtemsMessageReqConstructErrors_Pre_Free_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_Area_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_Area state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_Area_Valid: { - /* - * While the message buffer storage area begin pointer of the message - * queue configuration is valid. - */ - ctx->config_value.storage_area = buffers; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Area_Null: { - /* - * While the message buffer storage area begin pointer of the message - * queue configuration is NULL. - */ - ctx->config_value.storage_area = NULL; - break; - } - - case RtemsMessageReqConstructErrors_Pre_Area_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Pre_AreaSize_Prepare( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Pre_AreaSize state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Pre_AreaSize_Valid: { - /* - * While the message buffer storage area size of the message queue - * configuration is valid. - */ - ctx->config_value.storage_size = sizeof( buffers ); - break; - } - - case RtemsMessageReqConstructErrors_Pre_AreaSize_Invalid: { - /* - * While the message buffer storage area size of the message queue - * configuration is invalid. - */ - ctx->config_value.storage_size = SIZE_MAX; - break; - } - - case RtemsMessageReqConstructErrors_Pre_AreaSize_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Post_Status_Check( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Post_Status state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Post_Status_Ok: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_SUCCESSFUL. - */ - T_rsc_success( ctx->status ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_InvAddr: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_INVALID_ADDRESS. - */ - T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_InvName: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_INVALID_NAME. - */ - T_rsc( ctx->status, RTEMS_INVALID_NAME ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_InvNum: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_INVALID_NUMBER. - */ - T_rsc( ctx->status, RTEMS_INVALID_NUMBER ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_InvSize: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_INVALID_SIZE. - */ - T_rsc( ctx->status, RTEMS_INVALID_SIZE ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_TooMany: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_TOO_MANY. - */ - T_rsc( ctx->status, RTEMS_TOO_MANY ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_Unsat: { - /* - * The return status of rtems_message_queue_construct() shall be - * RTEMS_UNSATISFIED. - */ - T_rsc( ctx->status, RTEMS_UNSATISFIED ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Status_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Post_Name_Check( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Post_Name state -) -{ - rtems_status_code sc; - rtems_id id; - - switch ( state ) { - case RtemsMessageReqConstructErrors_Post_Name_Valid: { - /* - * The unique object name shall identify the message queue constructed by - * the rtems_message_queue_construct() call. - */ - id = 0; - sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); - T_rsc_success( sc ); - T_eq_u32( id, ctx->id_value ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Name_Invalid: { - /* - * The unique object name shall not identify a message queue. - */ - sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); - T_rsc( sc, RTEMS_INVALID_NAME ); - break; - } - - case RtemsMessageReqConstructErrors_Post_Name_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Post_IdVar_Check( - RtemsMessageReqConstructErrors_Context *ctx, - RtemsMessageReqConstructErrors_Post_IdVar state -) -{ - switch ( state ) { - case RtemsMessageReqConstructErrors_Post_IdVar_Set: { - /* - * The value of the object referenced by the ``id`` parameter shall be - * set to the object identifier of the constructed message queue after - * the return of the rtems_message_queue_construct() call. - */ - T_eq_ptr( ctx->id, &ctx->id_value ); - T_ne_u32( ctx->id_value, INVALID_ID ); - break; - } - - case RtemsMessageReqConstructErrors_Post_IdVar_Nop: { - /* - * Objects referenced by the ``id`` parameter in past calls to - * rtems_message_queue_construct() shall not be accessed by the - * rtems_message_queue_construct() call. - */ - T_eq_u32( ctx->id_value, INVALID_ID ); - break; - } - - case RtemsMessageReqConstructErrors_Post_IdVar_NA: - break; - } -} - -static void RtemsMessageReqConstructErrors_Prepare( - RtemsMessageReqConstructErrors_Context *ctx -) -{ - ctx->id_value = INVALID_ID; - memset( &ctx->config_value, 0, sizeof( ctx->config_value ) ); -} - -static void RtemsMessageReqConstructErrors_Action( - RtemsMessageReqConstructErrors_Context *ctx -) -{ - ctx->status = rtems_message_queue_construct( ctx->config, ctx->id ); -} - -static void RtemsMessageReqConstructErrors_Cleanup( - RtemsMessageReqConstructErrors_Context *ctx -) -{ - if ( ctx->id_value != INVALID_ID ) { - rtems_status_code sc; - - sc = rtems_message_queue_delete( ctx->id_value ); - T_rsc_success( sc ); - - ctx->id_value = INVALID_ID; - } - - T_surrender_objects( &ctx->seized_objects, rtems_message_queue_delete ); -} - -typedef struct { - uint16_t Skip : 1; - uint16_t Pre_Config_NA : 1; - uint16_t Pre_Name_NA : 1; - uint16_t Pre_Id_NA : 1; - uint16_t Pre_MaxPending_NA : 1; - uint16_t Pre_MaxSize_NA : 1; - uint16_t Pre_Free_NA : 1; - uint16_t Pre_Area_NA : 1; - uint16_t Pre_AreaSize_NA : 1; - uint16_t Post_Status : 3; - uint16_t Post_Name : 2; - uint16_t Post_IdVar : 2; -} RtemsMessageReqConstructErrors_Entry; - -static const RtemsMessageReqConstructErrors_Entry -RtemsMessageReqConstructErrors_Entries[] = { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_InvAddr, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_InvName, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_InvNum, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_InvSize, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_TooMany, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, - RtemsMessageReqConstructErrors_Post_Status_Unsat, - RtemsMessageReqConstructErrors_Post_Name_Invalid, - RtemsMessageReqConstructErrors_Post_IdVar_Nop }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstructErrors_Post_Status_Ok, - RtemsMessageReqConstructErrors_Post_Name_Valid, - RtemsMessageReqConstructErrors_Post_IdVar_Set } -}; - -static const uint8_t -RtemsMessageReqConstructErrors_Map[] = { - 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 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, - 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 -}; - -static size_t RtemsMessageReqConstructErrors_Scope( - void *arg, - char *buf, - size_t n -) -{ - RtemsMessageReqConstructErrors_Context *ctx; - - ctx = arg; - - if ( ctx->in_action_loop ) { - return T_get_scope( - RtemsMessageReqConstructErrors_PreDesc, - buf, - n, - ctx->pcs - ); - } - - return 0; -} - -static T_fixture RtemsMessageReqConstructErrors_Fixture = { - .setup = NULL, - .stop = NULL, - .teardown = NULL, - .scope = RtemsMessageReqConstructErrors_Scope, - .initial_context = &RtemsMessageReqConstructErrors_Instance -}; - -static inline RtemsMessageReqConstructErrors_Entry -RtemsMessageReqConstructErrors_GetEntry( size_t index ) -{ - return RtemsMessageReqConstructErrors_Entries[ - RtemsMessageReqConstructErrors_Map[ index ] - ]; -} - -/** - * @fn void T_case_body_RtemsMessageReqConstructErrors( void ) - */ -T_TEST_CASE_FIXTURE( - RtemsMessageReqConstructErrors, - &RtemsMessageReqConstructErrors_Fixture -) -{ - RtemsMessageReqConstructErrors_Context *ctx; - size_t index; - - ctx = T_fixture_context(); - ctx->in_action_loop = true; - index = 0; - - for ( - ctx->pcs[ 0 ] = RtemsMessageReqConstructErrors_Pre_Config_Valid; - ctx->pcs[ 0 ] < RtemsMessageReqConstructErrors_Pre_Config_NA; - ++ctx->pcs[ 0 ] - ) { - for ( - ctx->pcs[ 1 ] = RtemsMessageReqConstructErrors_Pre_Name_Valid; - ctx->pcs[ 1 ] < RtemsMessageReqConstructErrors_Pre_Name_NA; - ++ctx->pcs[ 1 ] - ) { - for ( - ctx->pcs[ 2 ] = RtemsMessageReqConstructErrors_Pre_Id_Id; - ctx->pcs[ 2 ] < RtemsMessageReqConstructErrors_Pre_Id_NA; - ++ctx->pcs[ 2 ] - ) { - for ( - ctx->pcs[ 3 ] = RtemsMessageReqConstructErrors_Pre_MaxPending_Valid; - ctx->pcs[ 3 ] < RtemsMessageReqConstructErrors_Pre_MaxPending_NA; - ++ctx->pcs[ 3 ] - ) { - for ( - ctx->pcs[ 4 ] = RtemsMessageReqConstructErrors_Pre_MaxSize_Valid; - ctx->pcs[ 4 ] < RtemsMessageReqConstructErrors_Pre_MaxSize_NA; - ++ctx->pcs[ 4 ] - ) { - for ( - ctx->pcs[ 5 ] = RtemsMessageReqConstructErrors_Pre_Free_Yes; - ctx->pcs[ 5 ] < RtemsMessageReqConstructErrors_Pre_Free_NA; - ++ctx->pcs[ 5 ] - ) { - for ( - ctx->pcs[ 6 ] = RtemsMessageReqConstructErrors_Pre_Area_Valid; - ctx->pcs[ 6 ] < RtemsMessageReqConstructErrors_Pre_Area_NA; - ++ctx->pcs[ 6 ] - ) { - for ( - ctx->pcs[ 7 ] = RtemsMessageReqConstructErrors_Pre_AreaSize_Valid; - ctx->pcs[ 7 ] < RtemsMessageReqConstructErrors_Pre_AreaSize_NA; - ++ctx->pcs[ 7 ] - ) { - RtemsMessageReqConstructErrors_Entry entry; - - entry = RtemsMessageReqConstructErrors_GetEntry( index ); - ++index; - - RtemsMessageReqConstructErrors_Prepare( ctx ); - RtemsMessageReqConstructErrors_Pre_Config_Prepare( - ctx, - ctx->pcs[ 0 ] - ); - RtemsMessageReqConstructErrors_Pre_Name_Prepare( - ctx, - ctx->pcs[ 1 ] - ); - RtemsMessageReqConstructErrors_Pre_Id_Prepare( - ctx, - ctx->pcs[ 2 ] - ); - RtemsMessageReqConstructErrors_Pre_MaxPending_Prepare( - ctx, - ctx->pcs[ 3 ] - ); - RtemsMessageReqConstructErrors_Pre_MaxSize_Prepare( - ctx, - ctx->pcs[ 4 ] - ); - RtemsMessageReqConstructErrors_Pre_Free_Prepare( - ctx, - ctx->pcs[ 5 ] - ); - RtemsMessageReqConstructErrors_Pre_Area_Prepare( - ctx, - ctx->pcs[ 6 ] - ); - RtemsMessageReqConstructErrors_Pre_AreaSize_Prepare( - ctx, - ctx->pcs[ 7 ] - ); - RtemsMessageReqConstructErrors_Action( ctx ); - RtemsMessageReqConstructErrors_Post_Status_Check( - ctx, - entry.Post_Status - ); - RtemsMessageReqConstructErrors_Post_Name_Check( - ctx, - entry.Post_Name - ); - RtemsMessageReqConstructErrors_Post_IdVar_Check( - ctx, - entry.Post_IdVar - ); - RtemsMessageReqConstructErrors_Cleanup( ctx ); - } - } - } - } - } - } - } - } -} - -/** @} */ diff --git a/testsuites/validation/tc-message-construct.c b/testsuites/validation/tc-message-construct.c new file mode 100644 index 0000000000..a7093b28e1 --- /dev/null +++ b/testsuites/validation/tc-message-construct.c @@ -0,0 +1,1059 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqConstruct + */ + +/* + * Copyright (C) 2020, 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 RTEMSTestCaseRtemsMessageReqConstruct \ + * spec:/rtems/message/req/construct + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqConstruct_Pre_Config_Valid, + RtemsMessageReqConstruct_Pre_Config_Null, + RtemsMessageReqConstruct_Pre_Config_NA +} RtemsMessageReqConstruct_Pre_Config; + +typedef enum { + RtemsMessageReqConstruct_Pre_Name_Valid, + RtemsMessageReqConstruct_Pre_Name_Invalid, + RtemsMessageReqConstruct_Pre_Name_NA +} RtemsMessageReqConstruct_Pre_Name; + +typedef enum { + RtemsMessageReqConstruct_Pre_Id_Id, + RtemsMessageReqConstruct_Pre_Id_Null, + RtemsMessageReqConstruct_Pre_Id_NA +} RtemsMessageReqConstruct_Pre_Id; + +typedef enum { + RtemsMessageReqConstruct_Pre_MaxPending_Valid, + RtemsMessageReqConstruct_Pre_MaxPending_Zero, + RtemsMessageReqConstruct_Pre_MaxPending_Big, + RtemsMessageReqConstruct_Pre_MaxPending_NA +} RtemsMessageReqConstruct_Pre_MaxPending; + +typedef enum { + RtemsMessageReqConstruct_Pre_MaxSize_Valid, + RtemsMessageReqConstruct_Pre_MaxSize_Zero, + RtemsMessageReqConstruct_Pre_MaxSize_Big, + RtemsMessageReqConstruct_Pre_MaxSize_NA +} RtemsMessageReqConstruct_Pre_MaxSize; + +typedef enum { + RtemsMessageReqConstruct_Pre_Free_Yes, + RtemsMessageReqConstruct_Pre_Free_No, + RtemsMessageReqConstruct_Pre_Free_NA +} RtemsMessageReqConstruct_Pre_Free; + +typedef enum { + RtemsMessageReqConstruct_Pre_Area_Valid, + RtemsMessageReqConstruct_Pre_Area_Null, + RtemsMessageReqConstruct_Pre_Area_NA +} RtemsMessageReqConstruct_Pre_Area; + +typedef enum { + RtemsMessageReqConstruct_Pre_AreaSize_Valid, + RtemsMessageReqConstruct_Pre_AreaSize_Invalid, + RtemsMessageReqConstruct_Pre_AreaSize_NA +} RtemsMessageReqConstruct_Pre_AreaSize; + +typedef enum { + RtemsMessageReqConstruct_Pre_StorageFree_Null, + RtemsMessageReqConstruct_Pre_StorageFree_Handler, + RtemsMessageReqConstruct_Pre_StorageFree_NA +} RtemsMessageReqConstruct_Pre_StorageFree; + +typedef enum { + RtemsMessageReqConstruct_Post_Status_Ok, + RtemsMessageReqConstruct_Post_Status_InvAddr, + RtemsMessageReqConstruct_Post_Status_InvName, + RtemsMessageReqConstruct_Post_Status_InvNum, + RtemsMessageReqConstruct_Post_Status_InvSize, + RtemsMessageReqConstruct_Post_Status_TooMany, + RtemsMessageReqConstruct_Post_Status_Unsat, + RtemsMessageReqConstruct_Post_Status_NA +} RtemsMessageReqConstruct_Post_Status; + +typedef enum { + RtemsMessageReqConstruct_Post_Name_Valid, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_Name_NA +} RtemsMessageReqConstruct_Post_Name; + +typedef enum { + RtemsMessageReqConstruct_Post_IdObj_Set, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_IdObj_NA +} RtemsMessageReqConstruct_Post_IdObj; + +typedef enum { + RtemsMessageReqConstruct_Post_StorageFree_Free, + RtemsMessageReqConstruct_Post_StorageFree_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA +} RtemsMessageReqConstruct_Post_StorageFree; + +typedef struct { + uint32_t Skip : 1; + uint32_t Pre_Config_NA : 1; + uint32_t Pre_Name_NA : 1; + uint32_t Pre_Id_NA : 1; + uint32_t Pre_MaxPending_NA : 1; + uint32_t Pre_MaxSize_NA : 1; + uint32_t Pre_Free_NA : 1; + uint32_t Pre_Area_NA : 1; + uint32_t Pre_AreaSize_NA : 1; + uint32_t Pre_StorageFree_NA : 1; + uint32_t Post_Status : 3; + uint32_t Post_Name : 2; + uint32_t Post_IdObj : 2; + uint32_t Post_StorageFree : 2; +} RtemsMessageReqConstruct_Entry; + +/** + * @brief Test context for spec:/rtems/message/req/construct test case. + */ +typedef struct { + rtems_status_code status; + + const rtems_message_queue_config *config; + + rtems_message_queue_config config_obj; + + rtems_id *id; + + rtems_id id_obj; + + void *seized_objects; + + uint32_t storage_free_counter; + + uint32_t expected_storage_free_counter; + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 9 ]; + + /** + * @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. + */ + RtemsMessageReqConstruct_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqConstruct_Context; + +static RtemsMessageReqConstruct_Context + RtemsMessageReqConstruct_Instance; + +static const char * const RtemsMessageReqConstruct_PreDesc_Config[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_Name[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_Id[] = { + "Id", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_MaxPending[] = { + "Valid", + "Zero", + "Big", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_MaxSize[] = { + "Valid", + "Zero", + "Big", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_Free[] = { + "Yes", + "No", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_Area[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_AreaSize[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqConstruct_PreDesc_StorageFree[] = { + "Null", + "Handler", + "NA" +}; + +static const char * const * const RtemsMessageReqConstruct_PreDesc[] = { + RtemsMessageReqConstruct_PreDesc_Config, + RtemsMessageReqConstruct_PreDesc_Name, + RtemsMessageReqConstruct_PreDesc_Id, + RtemsMessageReqConstruct_PreDesc_MaxPending, + RtemsMessageReqConstruct_PreDesc_MaxSize, + RtemsMessageReqConstruct_PreDesc_Free, + RtemsMessageReqConstruct_PreDesc_Area, + RtemsMessageReqConstruct_PreDesc_AreaSize, + RtemsMessageReqConstruct_PreDesc_StorageFree, + NULL +}; + +#define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) + +#define MAX_MESSAGE_QUEUES 4 + +#define MAX_PENDING_MESSAGES 1 + +#define MAX_MESSAGE_SIZE 1 + +typedef RtemsMessageReqConstruct_Context Context; + +static RTEMS_MESSAGE_QUEUE_BUFFER( MAX_MESSAGE_SIZE ) + buffers_to_seize[ MAX_MESSAGE_QUEUES ][ MAX_PENDING_MESSAGES ]; + +static RTEMS_MESSAGE_QUEUE_BUFFER( MAX_MESSAGE_SIZE ) + buffers[ MAX_PENDING_MESSAGES ]; + +static rtems_status_code Create( void *arg, uint32_t *id ) +{ + rtems_message_queue_config config; + size_t *i; + + i = arg; + T_quiet_lt_sz( *i, MAX_MESSAGE_QUEUES ); + + memset( &config, 0, sizeof( config ) ); + config.name = rtems_build_name( 'S', 'I', 'Z', 'E' ); + config.maximum_pending_messages = MAX_PENDING_MESSAGES; + config.maximum_message_size = MAX_MESSAGE_SIZE; + config.storage_size = sizeof( buffers_to_seize[ *i ] ); + config.storage_area = buffers_to_seize[ *i ]; + config.attributes = RTEMS_DEFAULT_ATTRIBUTES; + + ++(*i); + + return rtems_message_queue_construct( &config, id ); +} + +static void StorageFree( void *ptr ) +{ + Context *ctx; + + ctx = T_fixture_context(); + T_eq_ptr( ptr, buffers ); + ++ctx->storage_free_counter; +} + +static void RtemsMessageReqConstruct_Pre_Config_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_Config state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_Config_Valid: { + /* + * While the ``config`` parameter references an object of type + * rtems_message_queue_config. + */ + ctx->config = &ctx->config_obj; + break; + } + + case RtemsMessageReqConstruct_Pre_Config_Null: { + /* + * While the ``config`` parameter is NULL. + */ + ctx->config = NULL; + break; + } + + case RtemsMessageReqConstruct_Pre_Config_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_Name_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_Name state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_Name_Valid: { + /* + * While the name of the message queue configuration is valid. + */ + ctx->config_obj.name = NAME; + break; + } + + case RtemsMessageReqConstruct_Pre_Name_Invalid: { + /* + * While the name of the message queue configuration is invalid. + */ + ctx->config_obj.name = 0; + break; + } + + case RtemsMessageReqConstruct_Pre_Name_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_Id_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_Id_Id: { + /* + * While the ``id`` parameter references an object of type rtems_id. + */ + ctx->id = &ctx->id_obj; + break; + } + + case RtemsMessageReqConstruct_Pre_Id_Null: { + /* + * While the ``id`` parameter is NULL. + */ + ctx->id = NULL; + break; + } + + case RtemsMessageReqConstruct_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_MaxPending_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_MaxPending state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_MaxPending_Valid: { + /* + * While the maximum number of pending messages of the message queue + * configuration is valid. + */ + ctx->config_obj.maximum_pending_messages = MAX_PENDING_MESSAGES; + break; + } + + case RtemsMessageReqConstruct_Pre_MaxPending_Zero: { + /* + * While the maximum number of pending messages of the message queue + * configuration is zero. + */ + ctx->config_obj.maximum_pending_messages = 0; + break; + } + + case RtemsMessageReqConstruct_Pre_MaxPending_Big: { + /* + * While the maximum number of pending messages of the message queue + * configuration is big enough so that a calculation to get the message + * buffer storage area size overflows. + */ + ctx->config_obj.maximum_pending_messages = UINT32_MAX; + break; + } + + case RtemsMessageReqConstruct_Pre_MaxPending_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_MaxSize_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_MaxSize state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_MaxSize_Valid: { + /* + * While the maximum message size of the message queue configuration is + * valid. + */ + if ( ctx->config_obj.maximum_pending_messages == UINT32_MAX ) { + /* + * At least on 64-bit systems we need a bit of help to ensure that we + * meet the Big state of the MaxPending pre-condition. The following + * message size is valid with respect to calculations involving only + * the message size. + */ + ctx->config_obj.maximum_message_size = SIZE_MAX - sizeof( uintptr_t ) + + 1 - sizeof( CORE_message_queue_Buffer ); + } else { + ctx->config_obj.maximum_message_size = MAX_MESSAGE_SIZE; + } + break; + } + + case RtemsMessageReqConstruct_Pre_MaxSize_Zero: { + /* + * While the maximum message size of the message queue configuration is + * zero. + */ + ctx->config_obj.maximum_message_size = 0; + break; + } + + case RtemsMessageReqConstruct_Pre_MaxSize_Big: { + /* + * While the maximum message size of the message queue configuration is + * big enough so that a calculation to get the message buffer storage + * area size overflows. + */ + ctx->config_obj.maximum_message_size = SIZE_MAX; + break; + } + + case RtemsMessageReqConstruct_Pre_MaxSize_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_Free_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_Free state +) +{ + size_t i; + + switch ( state ) { + case RtemsMessageReqConstruct_Pre_Free_Yes: { + /* + * While the system has at least one inactive message queue object + * available. + */ + /* Nothing to do */ + break; + } + + case RtemsMessageReqConstruct_Pre_Free_No: { + /* + * While the system has no inactive message queue object available. + */ + i = 0; + ctx->seized_objects = T_seize_objects( Create, &i ); + break; + } + + case RtemsMessageReqConstruct_Pre_Free_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_Area_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_Area state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_Area_Valid: { + /* + * While the message buffer storage area begin pointer of the message + * queue configuration is valid. + */ + ctx->config_obj.storage_area = buffers; + break; + } + + case RtemsMessageReqConstruct_Pre_Area_Null: { + /* + * While the message buffer storage area begin pointer of the message + * queue configuration is NULL. + */ + ctx->config_obj.storage_area = NULL; + break; + } + + case RtemsMessageReqConstruct_Pre_Area_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_AreaSize_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_AreaSize state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_AreaSize_Valid: { + /* + * While the message buffer storage area size of the message queue + * configuration is valid. + */ + ctx->config_obj.storage_size = sizeof( buffers ); + break; + } + + case RtemsMessageReqConstruct_Pre_AreaSize_Invalid: { + /* + * While the message buffer storage area size of the message queue + * configuration is invalid. + */ + ctx->config_obj.storage_size = SIZE_MAX; + break; + } + + case RtemsMessageReqConstruct_Pre_AreaSize_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Pre_StorageFree_Prepare( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Pre_StorageFree state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Pre_StorageFree_Null: { + /* + * While the storage free member of the message queue configuration is + * equal to NULL. + */ + ctx->config_obj.storage_free = NULL; + break; + } + + case RtemsMessageReqConstruct_Pre_StorageFree_Handler: { + /* + * While the storage free member of the message queue configuration + * references a storage free handler. + */ + ctx->config_obj.storage_free = StorageFree; + break; + } + + case RtemsMessageReqConstruct_Pre_StorageFree_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Post_Status_Check( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Post_Status_Ok: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_SUCCESSFUL. + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_InvAddr: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_InvName: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_INVALID_NAME. + */ + T_rsc( ctx->status, RTEMS_INVALID_NAME ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_InvNum: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_INVALID_NUMBER. + */ + T_rsc( ctx->status, RTEMS_INVALID_NUMBER ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_InvSize: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_INVALID_SIZE. + */ + T_rsc( ctx->status, RTEMS_INVALID_SIZE ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_TooMany: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_TOO_MANY. + */ + T_rsc( ctx->status, RTEMS_TOO_MANY ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_Unsat: { + /* + * The return status of rtems_message_queue_construct() shall be + * RTEMS_UNSATISFIED. + */ + T_rsc( ctx->status, RTEMS_UNSATISFIED ); + break; + } + + case RtemsMessageReqConstruct_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Post_Name_Check( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Post_Name state +) +{ + rtems_status_code sc; + rtems_id id; + + switch ( state ) { + case RtemsMessageReqConstruct_Post_Name_Valid: { + /* + * The unique object name shall identify the message queue constructed by + * the rtems_message_queue_construct() call. + */ + id = 0; + sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); + T_rsc_success( sc ); + T_eq_u32( id, ctx->id_obj ); + break; + } + + case RtemsMessageReqConstruct_Post_Name_Invalid: { + /* + * The unique object name shall not identify a message queue. + */ + sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); + T_rsc( sc, RTEMS_INVALID_NAME ); + break; + } + + case RtemsMessageReqConstruct_Post_Name_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Post_IdObj_Check( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Post_IdObj state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Post_IdObj_Set: { + /* + * The value of the object referenced by the ``id`` parameter shall be + * set to the object identifier of the constructed message queue after + * the return of the rtems_message_queue_construct() call. + */ + T_eq_ptr( ctx->id, &ctx->id_obj ); + T_ne_u32( ctx->id_obj, INVALID_ID ); + break; + } + + case RtemsMessageReqConstruct_Post_IdObj_Nop: { + /* + * Objects referenced by the ``id`` parameter in past calls to + * rtems_message_queue_construct() shall not be accessed by the + * rtems_message_queue_construct() call. + */ + T_eq_u32( ctx->id_obj, INVALID_ID ); + break; + } + + case RtemsMessageReqConstruct_Post_IdObj_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Post_StorageFree_Check( + RtemsMessageReqConstruct_Context *ctx, + RtemsMessageReqConstruct_Post_StorageFree state +) +{ + switch ( state ) { + case RtemsMessageReqConstruct_Post_StorageFree_Free: { + /* + * The storage free handler of the message queue configuration specified + * by the ``config`` parameter shall be used to free the message queue + * storage area. + */ + ctx->expected_storage_free_counter = 1; + break; + } + + case RtemsMessageReqConstruct_Post_StorageFree_Nop: { + /* + * No operation shall be performed to free the message queue storage + * area. + */ + ctx->expected_storage_free_counter = 0; + break; + } + + case RtemsMessageReqConstruct_Post_StorageFree_NA: + break; + } +} + +static void RtemsMessageReqConstruct_Prepare( + RtemsMessageReqConstruct_Context *ctx +) +{ + ctx->id_obj = INVALID_ID; + ctx->storage_free_counter = 0; + ctx->expected_storage_free_counter = UINT32_MAX; + memset( &ctx->config_obj, 0, sizeof( ctx->config_obj ) ); +} + +static void RtemsMessageReqConstruct_Action( + RtemsMessageReqConstruct_Context *ctx +) +{ + ctx->status = rtems_message_queue_construct( ctx->config, ctx->id ); +} + +static void RtemsMessageReqConstruct_Cleanup( + RtemsMessageReqConstruct_Context *ctx +) +{ + if ( ctx->id_obj != INVALID_ID ) { + rtems_status_code sc; + + sc = rtems_message_queue_delete( ctx->id_obj ); + T_rsc_success( sc ); + + T_eq_u32( ctx->storage_free_counter, ctx->expected_storage_free_counter ); + } else { + T_eq_u32( ctx->storage_free_counter, 0 ); + } + + T_surrender_objects( &ctx->seized_objects, rtems_message_queue_delete ); +} + +static const RtemsMessageReqConstruct_Entry +RtemsMessageReqConstruct_Entries[] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_InvAddr, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_InvName, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_InvNum, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_InvSize, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_TooMany, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_Unsat, + RtemsMessageReqConstruct_Post_Name_Invalid, + RtemsMessageReqConstruct_Post_IdObj_Nop, + RtemsMessageReqConstruct_Post_StorageFree_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_Ok, + RtemsMessageReqConstruct_Post_Name_Valid, + RtemsMessageReqConstruct_Post_IdObj_Set, + RtemsMessageReqConstruct_Post_StorageFree_Nop }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqConstruct_Post_Status_Ok, + RtemsMessageReqConstruct_Post_Name_Valid, + RtemsMessageReqConstruct_Post_IdObj_Set, + RtemsMessageReqConstruct_Post_StorageFree_Free } +}; + +static const uint8_t +RtemsMessageReqConstruct_Map[] = { + 6, 7, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 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, + 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static size_t RtemsMessageReqConstruct_Scope( void *arg, char *buf, size_t n ) +{ + RtemsMessageReqConstruct_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( + RtemsMessageReqConstruct_PreDesc, + buf, + n, + ctx->Map.pcs + ); + } + + return 0; +} + +static T_fixture RtemsMessageReqConstruct_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = RtemsMessageReqConstruct_Scope, + .initial_context = &RtemsMessageReqConstruct_Instance +}; + +static inline RtemsMessageReqConstruct_Entry RtemsMessageReqConstruct_PopEntry( + RtemsMessageReqConstruct_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqConstruct_Entries[ + RtemsMessageReqConstruct_Map[ index ] + ]; +} + +static void RtemsMessageReqConstruct_TestVariant( + RtemsMessageReqConstruct_Context *ctx +) +{ + RtemsMessageReqConstruct_Pre_Config_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqConstruct_Pre_Name_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + RtemsMessageReqConstruct_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + RtemsMessageReqConstruct_Pre_MaxPending_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + RtemsMessageReqConstruct_Pre_MaxSize_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + RtemsMessageReqConstruct_Pre_Free_Prepare( ctx, ctx->Map.pcs[ 5 ] ); + RtemsMessageReqConstruct_Pre_Area_Prepare( ctx, ctx->Map.pcs[ 6 ] ); + RtemsMessageReqConstruct_Pre_AreaSize_Prepare( ctx, ctx->Map.pcs[ 7 ] ); + RtemsMessageReqConstruct_Pre_StorageFree_Prepare( ctx, ctx->Map.pcs[ 8 ] ); + RtemsMessageReqConstruct_Action( ctx ); + RtemsMessageReqConstruct_Post_Status_Check( + ctx, + ctx->Map.entry.Post_Status + ); + RtemsMessageReqConstruct_Post_Name_Check( ctx, ctx->Map.entry.Post_Name ); + RtemsMessageReqConstruct_Post_IdObj_Check( ctx, ctx->Map.entry.Post_IdObj ); + RtemsMessageReqConstruct_Post_StorageFree_Check( + ctx, + ctx->Map.entry.Post_StorageFree + ); +} + +/** + * @fn void T_case_body_RtemsMessageReqConstruct( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsMessageReqConstruct, + &RtemsMessageReqConstruct_Fixture +) +{ + RtemsMessageReqConstruct_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqConstruct_Pre_Config_Valid; + ctx->Map.pcs[ 0 ] < RtemsMessageReqConstruct_Pre_Config_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = RtemsMessageReqConstruct_Pre_Name_Valid; + ctx->Map.pcs[ 1 ] < RtemsMessageReqConstruct_Pre_Name_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = RtemsMessageReqConstruct_Pre_Id_Id; + ctx->Map.pcs[ 2 ] < RtemsMessageReqConstruct_Pre_Id_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = RtemsMessageReqConstruct_Pre_MaxPending_Valid; + ctx->Map.pcs[ 3 ] < RtemsMessageReqConstruct_Pre_MaxPending_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = RtemsMessageReqConstruct_Pre_MaxSize_Valid; + ctx->Map.pcs[ 4 ] < RtemsMessageReqConstruct_Pre_MaxSize_NA; + ++ctx->Map.pcs[ 4 ] + ) { + for ( + ctx->Map.pcs[ 5 ] = RtemsMessageReqConstruct_Pre_Free_Yes; + ctx->Map.pcs[ 5 ] < RtemsMessageReqConstruct_Pre_Free_NA; + ++ctx->Map.pcs[ 5 ] + ) { + for ( + ctx->Map.pcs[ 6 ] = RtemsMessageReqConstruct_Pre_Area_Valid; + ctx->Map.pcs[ 6 ] < RtemsMessageReqConstruct_Pre_Area_NA; + ++ctx->Map.pcs[ 6 ] + ) { + for ( + ctx->Map.pcs[ 7 ] = RtemsMessageReqConstruct_Pre_AreaSize_Valid; + ctx->Map.pcs[ 7 ] < RtemsMessageReqConstruct_Pre_AreaSize_NA; + ++ctx->Map.pcs[ 7 ] + ) { + for ( + ctx->Map.pcs[ 8 ] = RtemsMessageReqConstruct_Pre_StorageFree_Null; + ctx->Map.pcs[ 8 ] < RtemsMessageReqConstruct_Pre_StorageFree_NA; + ++ctx->Map.pcs[ 8 ] + ) { + ctx->Map.entry = RtemsMessageReqConstruct_PopEntry( ctx ); + RtemsMessageReqConstruct_Prepare( ctx ); + RtemsMessageReqConstruct_TestVariant( ctx ); + RtemsMessageReqConstruct_Cleanup( ctx ); + } + } + } + } + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-message-delete.c b/testsuites/validation/tc-message-delete.c new file mode 100644 index 0000000000..0835a5c5e9 --- /dev/null +++ b/testsuites/validation/tc-message-delete.c @@ -0,0 +1,479 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqDelete + */ + +/* + * 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 RTEMSTestCaseRtemsMessageReqDelete spec:/rtems/message/req/delete + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqDelete_Pre_Id_NoObj, + RtemsMessageReqDelete_Pre_Id_MsgQueue, + RtemsMessageReqDelete_Pre_Id_NA +} RtemsMessageReqDelete_Pre_Id; + +typedef enum { + RtemsMessageReqDelete_Post_Status_Ok, + RtemsMessageReqDelete_Post_Status_InvId, + RtemsMessageReqDelete_Post_Status_NA +} RtemsMessageReqDelete_Post_Status; + +typedef enum { + RtemsMessageReqDelete_Post_Name_Valid, + RtemsMessageReqDelete_Post_Name_Invalid, + RtemsMessageReqDelete_Post_Name_NA +} RtemsMessageReqDelete_Post_Name; + +typedef enum { + RtemsMessageReqDelete_Post_Flush_Yes, + RtemsMessageReqDelete_Post_Flush_No, + RtemsMessageReqDelete_Post_Flush_NA +} RtemsMessageReqDelete_Post_Flush; + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_Id_NA : 1; + uint8_t Post_Status : 2; + uint8_t Post_Name : 2; + uint8_t Post_Flush : 2; +} RtemsMessageReqDelete_Entry; + +/** + * @brief Test context for spec:/rtems/message/req/delete test case. + */ +typedef struct { + rtems_id worker_id; + + rtems_id message_queue_id; + + uint32_t wait_done; + + uint32_t wait_expected; + + rtems_id id; + + rtems_status_code status; + + 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. + */ + RtemsMessageReqDelete_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqDelete_Context; + +static RtemsMessageReqDelete_Context + RtemsMessageReqDelete_Instance; + +static const char * const RtemsMessageReqDelete_PreDesc_Id[] = { + "NoObj", + "MsgQueue", + "NA" +}; + +static const char * const * const RtemsMessageReqDelete_PreDesc[] = { + RtemsMessageReqDelete_PreDesc_Id, + NULL +}; + +#define NAME rtems_build_name( 'T', 'E', 'S', 'T' ) + +#define MAX_PENDING_MESSAGES 1 + +#define MAX_MESSAGE_SIZE 1 + +typedef RtemsMessageReqDelete_Context Context; + +static RTEMS_MESSAGE_QUEUE_BUFFER( MAX_MESSAGE_SIZE ) + buffers[ MAX_PENDING_MESSAGES ]; + +static void Worker( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = (Context *) arg; + + while ( true ) { + rtems_status_code sc; + rtems_message_queue_config config; + char buffer[ MAX_MESSAGE_SIZE ]; + size_t size; + rtems_task_priority prio; + + memset( &config, 0, sizeof( config ) ); + config.name = NAME; + config.maximum_pending_messages = MAX_PENDING_MESSAGES; + config.maximum_message_size = MAX_MESSAGE_SIZE; + config.storage_size = sizeof( buffers ); + config.storage_area = buffers; + config.attributes = RTEMS_DEFAULT_ATTRIBUTES; + + T_eq_u32( ctx->message_queue_id, 0 ); + + sc = rtems_message_queue_construct( &config, &ctx->message_queue_id ); + T_rsc_success( sc ); + + size = SIZE_MAX; + sc = rtems_message_queue_receive( + ctx->message_queue_id, + buffer, + &size, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT + ); + T_rsc( sc, RTEMS_OBJECT_WAS_DELETED ); + T_eq_sz( size, SIZE_MAX ); + + ++ctx->wait_done; + + prio = SetSelfPriority( PRIO_LOW ); + T_eq_u32( prio, PRIO_HIGH ); + } +} + +static void RtemsMessageReqDelete_Pre_Id_Prepare( + RtemsMessageReqDelete_Context *ctx, + RtemsMessageReqDelete_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqDelete_Pre_Id_NoObj: { + /* + * While the ``id`` parameter is not associated with a message queue. + */ + ctx->id = 0; + break; + } + + case RtemsMessageReqDelete_Pre_Id_MsgQueue: { + /* + * While the ``id`` parameter is associated with a message queue. + */ + ctx->id = ctx->message_queue_id; + break; + } + + case RtemsMessageReqDelete_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqDelete_Post_Status_Check( + RtemsMessageReqDelete_Context *ctx, + RtemsMessageReqDelete_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqDelete_Post_Status_Ok: { + /* + * The return status of rtems_message_queue_delete() shall be + * RTEMS_SUCCESSFUL. + */ + ctx->message_queue_id = 0; + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqDelete_Post_Status_InvId: { + /* + * The return status of rtems_message_queue_delete() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsMessageReqDelete_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqDelete_Post_Name_Check( + RtemsMessageReqDelete_Context *ctx, + RtemsMessageReqDelete_Post_Name state +) +{ + rtems_status_code sc; + rtems_id id; + + switch ( state ) { + case RtemsMessageReqDelete_Post_Name_Valid: { + /* + * The unique object name shall identify a message queue. + */ + id = 0; + sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); + T_rsc_success( sc ); + T_eq_u32( id, ctx->message_queue_id ); + break; + } + + case RtemsMessageReqDelete_Post_Name_Invalid: { + /* + * The unique object name shall not identify a message queue. + */ + sc = rtems_message_queue_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id ); + T_rsc( sc, RTEMS_INVALID_NAME ); + break; + } + + case RtemsMessageReqDelete_Post_Name_NA: + break; + } +} + +static void RtemsMessageReqDelete_Post_Flush_Check( + RtemsMessageReqDelete_Context *ctx, + RtemsMessageReqDelete_Post_Flush state +) +{ + switch ( state ) { + case RtemsMessageReqDelete_Post_Flush_Yes: { + /* + * Tasks waiting at the message queue shall be unblocked. + */ + ++ctx->wait_expected; + T_eq_u32( ctx->wait_done, ctx->wait_expected ); + break; + } + + case RtemsMessageReqDelete_Post_Flush_No: { + /* + * Tasks waiting at the message queue shall remain blocked. + */ + T_eq_u32( ctx->wait_done, ctx->wait_expected ); + break; + } + + case RtemsMessageReqDelete_Post_Flush_NA: + break; + } +} + +static void RtemsMessageReqDelete_Setup( RtemsMessageReqDelete_Context *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); + SetSelfPriority( PRIO_NORMAL ); + ctx->worker_id = CreateTask( "WORK", PRIO_LOW ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsMessageReqDelete_Setup_Wrap( void *arg ) +{ + RtemsMessageReqDelete_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqDelete_Setup( ctx ); +} + +static void RtemsMessageReqDelete_Teardown( + RtemsMessageReqDelete_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); + RestoreRunnerPriority(); +} + +static void RtemsMessageReqDelete_Teardown_Wrap( void *arg ) +{ + RtemsMessageReqDelete_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqDelete_Teardown( ctx ); +} + +static void RtemsMessageReqDelete_Prepare( RtemsMessageReqDelete_Context *ctx ) +{ + rtems_task_priority prio; + + prio = SetPriority( ctx->worker_id, PRIO_HIGH ); + T_true( prio == PRIO_LOW || prio == PRIO_HIGH ); +} + +static void RtemsMessageReqDelete_Action( RtemsMessageReqDelete_Context *ctx ) +{ + ctx->status = rtems_message_queue_delete( ctx->id ); +} + +static void RtemsMessageReqDelete_Cleanup( RtemsMessageReqDelete_Context *ctx ) +{ + if ( ctx->message_queue_id != 0 ) { + rtems_status_code sc; + + sc = rtems_message_queue_delete( ctx->message_queue_id ); + T_rsc_success( sc ); + + ++ctx->wait_expected; + T_eq_u32( ctx->wait_done, ctx->wait_expected ); + + ctx->message_queue_id = 0; + } +} + +static const RtemsMessageReqDelete_Entry +RtemsMessageReqDelete_Entries[] = { + { 0, 0, RtemsMessageReqDelete_Post_Status_InvId, + RtemsMessageReqDelete_Post_Name_Valid, RtemsMessageReqDelete_Post_Flush_No }, + { 0, 0, RtemsMessageReqDelete_Post_Status_Ok, + RtemsMessageReqDelete_Post_Name_Invalid, + RtemsMessageReqDelete_Post_Flush_Yes } +}; + +static const uint8_t +RtemsMessageReqDelete_Map[] = { + 0, 1 +}; + +static size_t RtemsMessageReqDelete_Scope( void *arg, char *buf, size_t n ) +{ + RtemsMessageReqDelete_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( RtemsMessageReqDelete_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture RtemsMessageReqDelete_Fixture = { + .setup = RtemsMessageReqDelete_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageReqDelete_Teardown_Wrap, + .scope = RtemsMessageReqDelete_Scope, + .initial_context = &RtemsMessageReqDelete_Instance +}; + +static inline RtemsMessageReqDelete_Entry RtemsMessageReqDelete_PopEntry( + RtemsMessageReqDelete_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqDelete_Entries[ + RtemsMessageReqDelete_Map[ index ] + ]; +} + +static void RtemsMessageReqDelete_TestVariant( + RtemsMessageReqDelete_Context *ctx +) +{ + RtemsMessageReqDelete_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqDelete_Action( ctx ); + RtemsMessageReqDelete_Post_Status_Check( ctx, ctx->Map.entry.Post_Status ); + RtemsMessageReqDelete_Post_Name_Check( ctx, ctx->Map.entry.Post_Name ); + RtemsMessageReqDelete_Post_Flush_Check( ctx, ctx->Map.entry.Post_Flush ); +} + +/** + * @fn void T_case_body_RtemsMessageReqDelete( void ) + */ +T_TEST_CASE_FIXTURE( RtemsMessageReqDelete, &RtemsMessageReqDelete_Fixture ) +{ + RtemsMessageReqDelete_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqDelete_Pre_Id_NoObj; + ctx->Map.pcs[ 0 ] < RtemsMessageReqDelete_Pre_Id_NA; + ++ctx->Map.pcs[ 0 ] + ) { + ctx->Map.entry = RtemsMessageReqDelete_PopEntry( ctx ); + RtemsMessageReqDelete_Prepare( ctx ); + RtemsMessageReqDelete_TestVariant( ctx ); + RtemsMessageReqDelete_Cleanup( ctx ); + } +} + +/** @} */ diff --git a/testsuites/validation/tc-message-flush-pending.c b/testsuites/validation/tc-message-flush-pending.c new file mode 100644 index 0000000000..67d2ede6bd --- /dev/null +++ b/testsuites/validation/tc-message-flush-pending.c @@ -0,0 +1,982 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqFlushPending + */ + +/* + * 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 RTEMSTestCaseRtemsMessageReqFlushPending \ + * spec:/rtems/message/req/flush-pending + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqFlushPending_Pre_Count_Valid, + RtemsMessageReqFlushPending_Pre_Count_Null, + RtemsMessageReqFlushPending_Pre_Count_NA +} RtemsMessageReqFlushPending_Pre_Count; + +typedef enum { + RtemsMessageReqFlushPending_Pre_Id_Valid, + RtemsMessageReqFlushPending_Pre_Id_Invalid, + RtemsMessageReqFlushPending_Pre_Id_NA +} RtemsMessageReqFlushPending_Pre_Id; + +typedef enum { + RtemsMessageReqFlushPending_Pre_MsgQueue_Empty, + RtemsMessageReqFlushPending_Pre_MsgQueue_Several, + RtemsMessageReqFlushPending_Pre_MsgQueue_NA +} RtemsMessageReqFlushPending_Pre_MsgQueue; + +typedef enum { + RtemsMessageReqFlushPending_Pre_Receivers_Waiting, + RtemsMessageReqFlushPending_Pre_Receivers_None, + RtemsMessageReqFlushPending_Pre_Receivers_NA +} RtemsMessageReqFlushPending_Pre_Receivers; + +typedef enum { + RtemsMessageReqFlushPending_Pre_Directive_Flush, + RtemsMessageReqFlushPending_Pre_Directive_Pending, + RtemsMessageReqFlushPending_Pre_Directive_NA +} RtemsMessageReqFlushPending_Pre_Directive; + +typedef enum { + RtemsMessageReqFlushPending_Pre_Storage_Nop, + RtemsMessageReqFlushPending_Pre_Storage_NA +} RtemsMessageReqFlushPending_Pre_Storage; + +typedef enum { + RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Status_InvId, + RtemsMessageReqFlushPending_Post_Status_InvAddr, + RtemsMessageReqFlushPending_Post_Status_NA +} RtemsMessageReqFlushPending_Post_Status; + +typedef enum { + RtemsMessageReqFlushPending_Post_Count_Zero, + RtemsMessageReqFlushPending_Post_Count_Set, + RtemsMessageReqFlushPending_Post_Count_Nop, + RtemsMessageReqFlushPending_Post_Count_NA +} RtemsMessageReqFlushPending_Post_Count; + +typedef enum { + RtemsMessageReqFlushPending_Post_MsgQueue_Empty, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_MsgQueue_NA +} RtemsMessageReqFlushPending_Post_MsgQueue; + +typedef enum { + RtemsMessageReqFlushPending_Post_Receivers_Nop, + RtemsMessageReqFlushPending_Post_Receivers_NA +} RtemsMessageReqFlushPending_Post_Receivers; + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Count_NA : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_MsgQueue_NA : 1; + uint16_t Pre_Receivers_NA : 1; + uint16_t Pre_Directive_NA : 1; + uint16_t Pre_Storage_NA : 1; + uint16_t Post_Status : 2; + uint16_t Post_Count : 2; + uint16_t Post_MsgQueue : 2; + uint16_t Post_Receivers : 1; +} RtemsMessageReqFlushPending_Entry; + +#define MAXIMUM_PENDING_MESSAGES 3 +#define MAXIMUM_MESSAGE_SIZE 5 +#define NUMBER_OF_WORKERS 3 + +/** + * @brief Test context for spec:/rtems/message/req/flush-pending test case. + */ +typedef struct { + /** + * @brief This member contains a valid ID of a message queue. + */ + rtems_id message_queue_id; + + /** + * @brief This member is used as storage area for the message queue. + */ + RTEMS_MESSAGE_QUEUE_BUFFER( MAXIMUM_MESSAGE_SIZE ) + storage_area[ MAXIMUM_PENDING_MESSAGES ]; + + /** + * @brief This member contains the returned status codes of the receivers. + */ + rtems_status_code receive_status[ NUMBER_OF_WORKERS ]; + + /** + * @brief This member specifies the directive to be called as action. + * + * This is either rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending(). + */ + rtems_status_code (*action)( rtems_id id, uint32_t *count ); + + /** + * @brief This member specifies the ``id`` parameter of the action. + */ + rtems_id id_param; + + /** + * @brief This member specifies the ``count`` parameter of the action. + */ + uint32_t *count_param; + + /** + * @brief This member contains the returned status code of the action. + */ + rtems_status_code status; + + /** + * @brief This member contains the value returned in parameter ``count`` of + * the action. + */ + uint32_t count; + + /** + * @brief This member contains the task identifiers of the worker tasks. + */ + rtems_id worker_id[ NUMBER_OF_WORKERS ]; + + /** + * @brief This member contains a pointer to a function which is executed to + * check that the action has not changed the content of the message queue. + */ + void (*check_msgq_unchanged)( void *ctx_in ); + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 6 ]; + + /** + * @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. + */ + RtemsMessageReqFlushPending_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqFlushPending_Context; + +static RtemsMessageReqFlushPending_Context + RtemsMessageReqFlushPending_Instance; + +static const char * const RtemsMessageReqFlushPending_PreDesc_Count[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqFlushPending_PreDesc_Id[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqFlushPending_PreDesc_MsgQueue[] = { + "Empty", + "Several", + "NA" +}; + +static const char * const RtemsMessageReqFlushPending_PreDesc_Receivers[] = { + "Waiting", + "None", + "NA" +}; + +static const char * const RtemsMessageReqFlushPending_PreDesc_Directive[] = { + "Flush", + "Pending", + "NA" +}; + +static const char * const RtemsMessageReqFlushPending_PreDesc_Storage[] = { + "Nop", + "NA" +}; + +static const char * const * const RtemsMessageReqFlushPending_PreDesc[] = { + RtemsMessageReqFlushPending_PreDesc_Count, + RtemsMessageReqFlushPending_PreDesc_Id, + RtemsMessageReqFlushPending_PreDesc_MsgQueue, + RtemsMessageReqFlushPending_PreDesc_Receivers, + RtemsMessageReqFlushPending_PreDesc_Directive, + RtemsMessageReqFlushPending_PreDesc_Storage, + NULL +}; + +typedef RtemsMessageReqFlushPending_Context Context; +static const uint32_t NUMBER_OF_PENDING_MESSAGES = 2; +static const rtems_interval TIMEOUT_TICKS = 1; +static const rtems_event_set EVENT_RECEIVE = RTEMS_EVENT_17; +static const uint8_t queued_message[] = { 200, 201, 202 }; + +static void Receive( Context *ctx, size_t worker_index ) +{ + size_t size; + uint8_t buffer[ MAXIMUM_MESSAGE_SIZE ]; + + ctx->receive_status[worker_index] = rtems_message_queue_receive( + ctx->message_queue_id, + buffer, + &size, + RTEMS_WAIT, + TIMEOUT_TICKS + ); +} + +static void WorkerTask( rtems_task_argument argument ) +{ + static size_t worker_number = 0; + size_t worker_index = worker_number++; + Context *ctx = (Context *) argument; + + while ( true ) { + ReceiveAnyEvents(); + Receive( ctx, worker_index ); + } +} + +static void CheckForNoMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + (void) message_buffer; + (void) message_size; + T_rsc( status, RTEMS_UNSATISFIED ); +} + +static void CheckForQueuedMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc_success( status ); + T_eq_u32( message_size, sizeof( queued_message ) ); + T_eq_mem( message_buffer, queued_message, sizeof( queued_message ) ); +} + +static void PopMessage( + Context *ctx, + void (*check_fn)( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size + ) +) +{ + rtems_status_code status; + uint8_t message_buffer[ MAXIMUM_MESSAGE_SIZE ]; + size_t message_size; + + status = rtems_message_queue_receive( + ctx->message_queue_id, + &message_buffer, + &message_size, + RTEMS_LOCAL | RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT + ); + + check_fn( ctx, status, message_buffer, message_size ); +} + +static void CheckForNoMessageInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + PopMessage( ctx, CheckForNoMessage ); +} + +static void CheckForSeveralMessagesInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + uint32_t i; + for ( i = 0; i < NUMBER_OF_PENDING_MESSAGES; ++i ) { + PopMessage( ctx, CheckForQueuedMessage ); + } + PopMessage( ctx, CheckForNoMessage ); +} + +static void SendMsg( Context *ctx ) +{ + rtems_status_code status; + + status = rtems_message_queue_send( + ctx->message_queue_id, + queued_message, + sizeof( queued_message ) + ); + T_rsc_success( status ); +} + +static void RtemsMessageReqFlushPending_Pre_Count_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_Count state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_Count_Valid: { + /* + * While the ``count`` parameter references an ``uint32_t`` object. + */ + ctx->count_param = &ctx->count; + break; + } + + case RtemsMessageReqFlushPending_Pre_Count_Null: { + /* + * While the ``count`` parameter is NULL. + */ + ctx->count_param = NULL; + break; + } + + case RtemsMessageReqFlushPending_Pre_Count_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Pre_Id_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_Id_Valid: { + /* + * While the ``id`` parameter is valid. + */ + ctx->id_param = ctx->message_queue_id; + break; + } + + case RtemsMessageReqFlushPending_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is invalid. + */ + ctx->id_param = RTEMS_ID_NONE; + break; + } + + case RtemsMessageReqFlushPending_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Pre_MsgQueue_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_MsgQueue_Empty: { + /* + * While there is no message in the message queue. + */ + /* Message queue is already empty. */ + ctx->check_msgq_unchanged = CheckForNoMessageInQueue; + break; + } + + case RtemsMessageReqFlushPending_Pre_MsgQueue_Several: { + /* + * While there are messages in the message queue. + */ + uint32_t i; + for ( i = 0; i < NUMBER_OF_PENDING_MESSAGES; ++i ) { + SendMsg( ctx ); + } + ctx->check_msgq_unchanged = CheckForSeveralMessagesInQueue; + break; + } + + case RtemsMessageReqFlushPending_Pre_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Pre_Receivers_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_Receivers state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_Receivers_Waiting: { + /* + * While one or more receivers are waiting to receive a message. + */ + size_t i; + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + SendEvents( ctx->worker_id[i], EVENT_RECEIVE ); + } + break; + } + + case RtemsMessageReqFlushPending_Pre_Receivers_None: { + /* + * While no receiver is waiting to receive a message. + */ + /* There is already no receiver waiting. */ + break; + } + + case RtemsMessageReqFlushPending_Pre_Receivers_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Pre_Directive_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_Directive state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_Directive_Flush: { + /* + * While the directive rtems_message_queue_flush() is called. + */ + ctx->action = rtems_message_queue_flush; + break; + } + + case RtemsMessageReqFlushPending_Pre_Directive_Pending: { + /* + * While the directive rtems_message_queue_get_number_pending() is + * called. + */ + ctx->action = rtems_message_queue_get_number_pending; + break; + } + + case RtemsMessageReqFlushPending_Pre_Directive_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Pre_Storage_Prepare( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Pre_Storage state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Pre_Storage_Nop: { + /* + * While the memory area to which a pointer is provided as member + * storage_area of type rtems_message_queue_config when the message queue + * is constructed by rtems_message_queue_construct() is altered only by + * the RTEMS operating system. + */ + /* Only a requirement text. */ + break; + } + + case RtemsMessageReqFlushPending_Pre_Storage_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Post_Status_Check( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Post_Status_Ok: { + /* + * The return status of the called directive (rtems_message_queue_flush() + * or rtems_message_queue_get_number_pending()) shall be RTEMS_SUCCESSFUL + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqFlushPending_Post_Status_InvId: { + /* + * The return status of the called directive (rtems_message_queue_flush() + * or rtems_message_queue_get_number_pending()) shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsMessageReqFlushPending_Post_Status_InvAddr: { + /* + * The return status of the called directive (rtems_message_queue_flush() + * or rtems_message_queue_get_number_pending()) shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsMessageReqFlushPending_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Post_Count_Check( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Post_Count state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Post_Count_Zero: { + /* + * The value of the object referenced by the ``count`` parameter shall be + * 0 after the return of the rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending() call. + */ + T_eq_u32( ctx->count, 0 ); + break; + } + + case RtemsMessageReqFlushPending_Post_Count_Set: { + /* + * The rtems_message_queue_get_number_pending() directive shall set the + * value of the object referenced by the ``count`` parameter to the + * number of messages present in the message queue at a point in time + * during the single execution of the + * rtems_message_queue_get_number_pending() directive. + * + * The rtems_message_queue_flush() directive shall set the value of the + * object referenced by the ``count`` parameter to the number of messages + * it removed from the message queue during the single execution of the + * rtems_message_queue_flush() directive. + */ + T_eq_u32( ctx->count, NUMBER_OF_PENDING_MESSAGES ); + break; + } + + case RtemsMessageReqFlushPending_Post_Count_Nop: { + /* + * The value of the object referenced by the ``count`` parameter in past + * call to rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending() shall not be accessed by the + * rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending() call (see also Nop). + */ + T_eq_u32( ctx->count, UINT8_MAX ); + break; + } + + case RtemsMessageReqFlushPending_Post_Count_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Post_MsgQueue_Check( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Post_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Post_MsgQueue_Empty: { + /* + * The message queue shall contain no messages after the last call to + * ``id``. + */ + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqFlushPending_Post_MsgQueue_Nop: { + /* + * Objects referenced by the ``id`` parameter in the past call to + * rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending() shall not be changed by that + * call (see also Nop). + */ + ctx->check_msgq_unchanged( ctx ); + break; + } + + case RtemsMessageReqFlushPending_Post_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Post_Receivers_Check( + RtemsMessageReqFlushPending_Context *ctx, + RtemsMessageReqFlushPending_Post_Receivers state +) +{ + switch ( state ) { + case RtemsMessageReqFlushPending_Post_Receivers_Nop: { + /* + * The receivers waiting for a message at the message queue shall not be + * affected by the call to the rtems_message_queue_flush() or + * rtems_message_queue_get_number_pending() directive. + */ + size_t i; + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + T_rsc( ctx->receive_status[i], RTEMS_TIMEOUT ); + } + break; + } + + case RtemsMessageReqFlushPending_Post_Receivers_NA: + break; + } +} + +static void RtemsMessageReqFlushPending_Setup( + RtemsMessageReqFlushPending_Context *ctx +) +{ + size_t i; + SetSelfPriority( PRIO_NORMAL ); + + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + ctx->worker_id[i] = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id[i], WorkerTask, ctx ); + } +} + +static void RtemsMessageReqFlushPending_Setup_Wrap( void *arg ) +{ + RtemsMessageReqFlushPending_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqFlushPending_Setup( ctx ); +} + +static void RtemsMessageReqFlushPending_Teardown( + RtemsMessageReqFlushPending_Context *ctx +) +{ + size_t i; + + for ( i = 0; i < NUMBER_OF_WORKERS; ++i ) { + DeleteTask( ctx->worker_id[i] ); + } + RestoreRunnerPriority(); +} + +static void RtemsMessageReqFlushPending_Teardown_Wrap( void *arg ) +{ + RtemsMessageReqFlushPending_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqFlushPending_Teardown( ctx ); +} + +static void RtemsMessageReqFlushPending_Prepare( + RtemsMessageReqFlushPending_Context *ctx +) +{ + rtems_status_code status; + + rtems_message_queue_config config = { + .name = rtems_build_name( 'M', 'S', 'G', 'Q' ), + .maximum_pending_messages = MAXIMUM_PENDING_MESSAGES, + .maximum_message_size = MAXIMUM_MESSAGE_SIZE, + .storage_area = ctx->storage_area, + .storage_size = sizeof( ctx->storage_area ), + .storage_free = NULL, + .attributes = RTEMS_DEFAULT_ATTRIBUTES + }; + + status = rtems_message_queue_construct( + &config, + &ctx->message_queue_id + ); + T_rsc_success( status ); + + ctx->count = UINT8_MAX; +} + +static void RtemsMessageReqFlushPending_Action( + RtemsMessageReqFlushPending_Context *ctx +) +{ + ctx->status = (ctx->action)( + ctx->id_param, + ctx->count_param + ); + + FinalClockTick(); +} + +static void RtemsMessageReqFlushPending_Cleanup( + RtemsMessageReqFlushPending_Context *ctx +) +{ + T_rsc_success( rtems_message_queue_delete( ctx->message_queue_id ) ); +} + +static const RtemsMessageReqFlushPending_Entry +RtemsMessageReqFlushPending_Entries[] = { + { 1, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_NA, + RtemsMessageReqFlushPending_Post_Count_NA, + RtemsMessageReqFlushPending_Post_MsgQueue_NA, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_InvAddr, + RtemsMessageReqFlushPending_Post_Count_Nop, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_InvId, + RtemsMessageReqFlushPending_Post_Count_Nop, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_InvAddr, + RtemsMessageReqFlushPending_Post_Count_Nop, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_Nop }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_InvId, + RtemsMessageReqFlushPending_Post_Count_Nop, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_Nop }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Zero, + RtemsMessageReqFlushPending_Post_MsgQueue_Empty, + RtemsMessageReqFlushPending_Post_Receivers_Nop }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Zero, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_Nop }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Zero, + RtemsMessageReqFlushPending_Post_MsgQueue_Empty, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Zero, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Set, + RtemsMessageReqFlushPending_Post_MsgQueue_Empty, + RtemsMessageReqFlushPending_Post_Receivers_NA }, + { 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqFlushPending_Post_Status_Ok, + RtemsMessageReqFlushPending_Post_Count_Set, + RtemsMessageReqFlushPending_Post_MsgQueue_Nop, + RtemsMessageReqFlushPending_Post_Receivers_NA } +}; + +static const uint8_t +RtemsMessageReqFlushPending_Map[] = { + 5, 6, 7, 8, 0, 0, 9, 10, 4, 4, 2, 2, 0, 0, 2, 2, 3, 3, 1, 1, 0, 0, 1, 1, 3, + 3, 1, 1, 0, 0, 1, 1 +}; + +static size_t RtemsMessageReqFlushPending_Scope( + void *arg, + char *buf, + size_t n +) +{ + RtemsMessageReqFlushPending_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( + RtemsMessageReqFlushPending_PreDesc, + buf, + n, + ctx->Map.pcs + ); + } + + return 0; +} + +static T_fixture RtemsMessageReqFlushPending_Fixture = { + .setup = RtemsMessageReqFlushPending_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageReqFlushPending_Teardown_Wrap, + .scope = RtemsMessageReqFlushPending_Scope, + .initial_context = &RtemsMessageReqFlushPending_Instance +}; + +static inline RtemsMessageReqFlushPending_Entry +RtemsMessageReqFlushPending_PopEntry( + RtemsMessageReqFlushPending_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqFlushPending_Entries[ + RtemsMessageReqFlushPending_Map[ index ] + ]; +} + +static void RtemsMessageReqFlushPending_TestVariant( + RtemsMessageReqFlushPending_Context *ctx +) +{ + RtemsMessageReqFlushPending_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqFlushPending_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + RtemsMessageReqFlushPending_Pre_MsgQueue_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + RtemsMessageReqFlushPending_Pre_Receivers_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + RtemsMessageReqFlushPending_Pre_Directive_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + RtemsMessageReqFlushPending_Pre_Storage_Prepare( ctx, ctx->Map.pcs[ 5 ] ); + RtemsMessageReqFlushPending_Action( ctx ); + RtemsMessageReqFlushPending_Post_Status_Check( + ctx, + ctx->Map.entry.Post_Status + ); + RtemsMessageReqFlushPending_Post_Count_Check( + ctx, + ctx->Map.entry.Post_Count + ); + RtemsMessageReqFlushPending_Post_MsgQueue_Check( + ctx, + ctx->Map.entry.Post_MsgQueue + ); + RtemsMessageReqFlushPending_Post_Receivers_Check( + ctx, + ctx->Map.entry.Post_Receivers + ); +} + +/** + * @fn void T_case_body_RtemsMessageReqFlushPending( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsMessageReqFlushPending, + &RtemsMessageReqFlushPending_Fixture +) +{ + RtemsMessageReqFlushPending_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqFlushPending_Pre_Count_Valid; + ctx->Map.pcs[ 0 ] < RtemsMessageReqFlushPending_Pre_Count_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = RtemsMessageReqFlushPending_Pre_Id_Valid; + ctx->Map.pcs[ 1 ] < RtemsMessageReqFlushPending_Pre_Id_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = RtemsMessageReqFlushPending_Pre_MsgQueue_Empty; + ctx->Map.pcs[ 2 ] < RtemsMessageReqFlushPending_Pre_MsgQueue_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = RtemsMessageReqFlushPending_Pre_Receivers_Waiting; + ctx->Map.pcs[ 3 ] < RtemsMessageReqFlushPending_Pre_Receivers_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = RtemsMessageReqFlushPending_Pre_Directive_Flush; + ctx->Map.pcs[ 4 ] < RtemsMessageReqFlushPending_Pre_Directive_NA; + ++ctx->Map.pcs[ 4 ] + ) { + for ( + ctx->Map.pcs[ 5 ] = RtemsMessageReqFlushPending_Pre_Storage_Nop; + ctx->Map.pcs[ 5 ] < RtemsMessageReqFlushPending_Pre_Storage_NA; + ++ctx->Map.pcs[ 5 ] + ) { + ctx->Map.entry = RtemsMessageReqFlushPending_PopEntry( ctx ); + + if ( ctx->Map.entry.Skip ) { + continue; + } + + RtemsMessageReqFlushPending_Prepare( ctx ); + RtemsMessageReqFlushPending_TestVariant( ctx ); + RtemsMessageReqFlushPending_Cleanup( ctx ); + } + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-message-ident.c b/testsuites/validation/tc-message-ident.c new file mode 100644 index 0000000000..74759b525e --- /dev/null +++ b/testsuites/validation/tc-message-ident.c @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageValIdent + */ + +/* + * Copyright (C) 2020 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 "tr-object-ident.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsMessageValIdent spec:/rtems/message/val/ident + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @brief Test the rtems_message_queue_ident() directive. + * + * This test case performs the following actions: + * + * - Run the generic object identification tests for Classic API message queue + * class objects defined by /rtems/req/ident. + * + * @{ + */ + +static RTEMS_MESSAGE_QUEUE_BUFFER( 1 ) ClassicMessageIdentBuffers[ 1 ]; + +static rtems_message_queue_config ClassicObjectIdentConfig = { + .name = ClassicObjectIdentName, + .maximum_pending_messages = RTEMS_ARRAY_SIZE( ClassicMessageIdentBuffers ), + .maximum_message_size = 1, + .storage_area = ClassicMessageIdentBuffers, + .storage_size = sizeof( ClassicMessageIdentBuffers ), + .attributes = RTEMS_DEFAULT_ATTRIBUTES +}; + +static rtems_status_code ClassicMessageIdentAction( + rtems_name name, + uint32_t node, + rtems_id *id +) +{ + return rtems_message_queue_ident( name, node, id ); +} + +/** + * @brief Run the generic object identification tests for Classic API message + * queue class objects defined by /rtems/req/ident. + */ +static void RtemsMessageValIdent_Action_0( void ) +{ + rtems_status_code sc; + rtems_id id_local_object; + + sc = rtems_message_queue_construct( + &ClassicObjectIdentConfig, + &id_local_object + ); + T_assert_rsc_success( sc ); + + RtemsReqIdent_Run( + id_local_object, + ClassicMessageIdentAction + ); + + sc = rtems_message_queue_delete( id_local_object ); + T_rsc_success( sc ); +} + +/** + * @fn void T_case_body_RtemsMessageValIdent( void ) + */ +T_TEST_CASE( RtemsMessageValIdent ) +{ + RtemsMessageValIdent_Action_0(); +} + +/** @} */ diff --git a/testsuites/validation/tc-message-macros.c b/testsuites/validation/tc-message-macros.c new file mode 100644 index 0000000000..f8e6a46252 --- /dev/null +++ b/testsuites/validation/tc-message-macros.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageValMessageMacros + */ + +/* + * 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 + +/** + * @defgroup RTEMSTestCaseRtemsMessageValMessageMacros \ + * spec:/rtems/message/val/message-macros + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @brief Tests the macros of the @ref RTEMSAPIClassicMessage. + * + * This test case performs the following actions: + * + * - Check the RTEMS_MESSAGE_QUEUE_BUFFER() macro. + * + * - Check that the object defined by the RTEMS_MESSAGE_QUEUE_BUFFER() + * expression has the desired size. rtems_message_queue_construct() will + * return RTEMS_UNSATISFIED instead of RTEMS_SUCCESSFUL if the object + * defined by the RTEMS_MESSAGE_QUEUE_BUFFER() expression has incorrect + * size. + * + * @{ + */ + +/** + * @brief Check the RTEMS_MESSAGE_QUEUE_BUFFER() macro. + */ +static void RtemsMessageValMessageMacros_Action_0( void ) +{ + rtems_status_code status; + rtems_id id; + + static const uint32_t maximum_pending_messages_0 = 1; + static const size_t maximum_message_size_0 = 1; + RTEMS_MESSAGE_QUEUE_BUFFER( maximum_message_size_0 ) + storage_area_0[ maximum_pending_messages_0 ]; + rtems_message_queue_config config_0 = { + .name = rtems_build_name( 'M', 'S', 'G', '0' ), + .maximum_pending_messages = maximum_pending_messages_0, + .maximum_message_size = maximum_message_size_0, + .storage_area = storage_area_0, + .storage_size = sizeof( storage_area_0 ), + .storage_free = NULL, + .attributes = RTEMS_DEFAULT_OPTIONS + }; + + static const uint32_t maximum_pending_messages_1 = 3; + static const size_t maximum_message_size_1 = 5; + RTEMS_MESSAGE_QUEUE_BUFFER( maximum_message_size_1 ) + storage_area_1[ maximum_pending_messages_1 ]; + rtems_message_queue_config config_1 = { + .name = rtems_build_name( 'M', 'S', 'G', '1' ), + .maximum_pending_messages = maximum_pending_messages_1, + .maximum_message_size = maximum_message_size_1, + .storage_area = storage_area_1, + .storage_size = sizeof( storage_area_1 ), + .storage_free = NULL, + .attributes = RTEMS_DEFAULT_OPTIONS + }; + + /* + * Check that the object defined by the RTEMS_MESSAGE_QUEUE_BUFFER() + * expression has the desired size. rtems_message_queue_construct() will + * return RTEMS_UNSATISFIED instead of RTEMS_SUCCESSFUL if the object defined + * by the RTEMS_MESSAGE_QUEUE_BUFFER() expression has incorrect size. + */ + status = rtems_message_queue_construct( + &config_0, + &id + ); + T_step_rsc_success( 0, status ); + T_step_rsc_success( 1, rtems_message_queue_delete( id ) ); + + status = rtems_message_queue_construct( + &config_1, + &id + ); + T_step_rsc_success( 2, status ); + T_step_rsc_success( 3, rtems_message_queue_delete( id ) ); +} + +/** + * @fn void T_case_body_RtemsMessageValMessageMacros( void ) + */ +T_TEST_CASE( RtemsMessageValMessageMacros ) +{ + T_plan( 4 ); + + RtemsMessageValMessageMacros_Action_0(); +} + +/** @} */ diff --git a/testsuites/validation/tc-message-performance.c b/testsuites/validation/tc-message-performance.c new file mode 100644 index 0000000000..162c094078 --- /dev/null +++ b/testsuites/validation/tc-message-performance.c @@ -0,0 +1,886 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageValPerf + */ + +/* + * 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 RTEMSTestCaseRtemsMessageValPerf spec:/rtems/message/val/perf + * + * @ingroup RTEMSTestSuiteTestsuitesPerformanceNoClock0 + * + * @brief This test case provides a context to run @ref RTEMSAPIClassicMessage + * performance tests. + * + * @{ + */ + +/** + * @brief Test context for spec:/rtems/message/val/perf test case. + */ +typedef struct { + /** + * @brief This member provides a message queue identifier. + */ + rtems_id queue_id; + + /** + * @brief This member provides a worker identifier. + */ + rtems_id worker_id; + + /** + * @brief This member provides a status code. + */ + rtems_status_code status; + + /** + * @brief This member references the measure runtime context. + */ + T_measure_runtime_context *context; + + /** + * @brief This member provides the measure runtime request. + */ + T_measure_runtime_request request; + + /** + * @brief This member provides an optional measurement begin time point. + */ + T_ticks begin; + + /** + * @brief This member provides an optional measurement end time point. + */ + T_ticks end; +} RtemsMessageValPerf_Context; + +static RtemsMessageValPerf_Context + RtemsMessageValPerf_Instance; + +#define MAXIMUM_PENDING_MESSAGES 1 + +#define MAXIMUM_MESSAGE_SIZE 8 + +typedef RtemsMessageValPerf_Context Context; + +typedef enum { + EVENT_END = RTEMS_EVENT_0, + EVENT_SEND = RTEMS_EVENT_1, + EVENT_SEND_END = RTEMS_EVENT_2, + EVENT_RECEIVE = RTEMS_EVENT_3, + EVENT_RECEIVE_END = RTEMS_EVENT_4 +} Event; + +static RTEMS_MESSAGE_QUEUE_BUFFER( MAXIMUM_MESSAGE_SIZE ) + storage_area[ MAXIMUM_PENDING_MESSAGES ]; + +rtems_message_queue_config config = { + .name = OBJECT_NAME, + .maximum_pending_messages = MAXIMUM_PENDING_MESSAGES, + .maximum_message_size = MAXIMUM_MESSAGE_SIZE, + .storage_area = storage_area, + .storage_size = sizeof( storage_area ) +}; + +static void Send( const Context *ctx, rtems_event_set events ) +{ + SendEvents( ctx->worker_id, events ); +} + +static void Worker( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = (Context *) arg; + + while ( true ) { + rtems_event_set events; + rtems_status_code sc; + T_ticks ticks; + uint64_t message; + + sc = rtems_event_receive( + RTEMS_ALL_EVENTS, + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &events + ); + ticks = T_tick(); + T_quiet_rsc_success( sc ); + + if ( ( events & EVENT_END ) != 0 ) { + ctx->end = ticks; + } + + if ( ( events & EVENT_SEND ) != 0 ) { + message = 0; + sc = rtems_message_queue_send( + ctx->queue_id, + &message, + sizeof( message ) + ); + ticks = T_tick(); + T_quiet_rsc_success( sc ); + + if ( ( events & EVENT_SEND_END ) != 0 ) { + ctx->end = ticks; + } + } + + if ( ( events & EVENT_RECEIVE ) != 0 ) { + size_t size; + + sc = rtems_message_queue_receive( + ctx->queue_id, + &message, + &size, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT + ); + ticks = T_tick(); + T_quiet_rsc_success( sc ); + + if ( ( events & EVENT_RECEIVE_END ) != 0 ) { + ctx->end = ticks; + } + } + } +} + +static void RtemsMessageValPerf_Setup_Context( + RtemsMessageValPerf_Context *ctx +) +{ + T_measure_runtime_config config; + + memset( &config, 0, sizeof( config ) ); + config.sample_count = 100; + ctx->request.arg = ctx; + ctx->request.flags = T_MEASURE_RUNTIME_REPORT_SAMPLES; + ctx->context = T_measure_runtime_create( &config ); + T_assert_not_null( ctx->context ); +} + +/** + * @brief Create a message queue and a worker task. + */ +static void RtemsMessageValPerf_Setup( RtemsMessageValPerf_Context *ctx ) +{ + rtems_status_code sc; + + SetSelfPriority( PRIO_NORMAL ); + + sc = rtems_message_queue_construct( &config, &ctx->queue_id ); + T_rsc_success( sc ); + + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id, Worker, ctx ); +} + +static void RtemsMessageValPerf_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageValPerf_Setup_Context( ctx ); + RtemsMessageValPerf_Setup( ctx ); +} + +/** + * @brief Delete the worker task and the message queue. + */ +static void RtemsMessageValPerf_Teardown( RtemsMessageValPerf_Context *ctx ) +{ + rtems_status_code sc; + + DeleteTask( ctx->worker_id ); + + sc = rtems_message_queue_delete( ctx->queue_id ); + T_rsc_success( sc ); + + RestoreRunnerPriority(); +} + +static void RtemsMessageValPerf_Teardown_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageValPerf_Teardown( ctx ); +} + +static T_fixture RtemsMessageValPerf_Fixture = { + .setup = RtemsMessageValPerf_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageValPerf_Teardown_Wrap, + .scope = NULL, + .initial_context = &RtemsMessageValPerf_Instance +}; + +/** + * @brief Try to receive a message. + */ +static void RtemsMessageReqPerfReceiveTry_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + size_t size; + + ctx->status = rtems_message_queue_receive( + ctx->queue_id, + &message, + &size, + RTEMS_NO_WAIT, + 0 + ); +} + +static void RtemsMessageReqPerfReceiveTry_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfReceiveTry_Body( ctx ); +} + +/** + * @brief Discard samples interrupted by a clock tick. + */ +static bool RtemsMessageReqPerfReceiveTry_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc( ctx->status, RTEMS_UNSATISFIED ); + + return tic == toc; +} + +static bool RtemsMessageReqPerfReceiveTry_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfReceiveTry_Teardown( ctx, delta, tic, toc, retry ); +} + +/** + * @brief Schedule a message send. + */ +static void RtemsMessageReqPerfReceiveWaitForever_Setup( + RtemsMessageValPerf_Context *ctx +) +{ + SetPriority( ctx->worker_id, PRIO_LOW ); + Send( ctx, EVENT_END | EVENT_SEND ); +} + +static void RtemsMessageReqPerfReceiveWaitForever_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfReceiveWaitForever_Setup( ctx ); +} + +/** + * @brief Receive a message. Wait forever. + */ +static void RtemsMessageReqPerfReceiveWaitForever_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + size_t size; + + ctx->begin = T_tick(); + ctx->status = rtems_message_queue_receive( + ctx->queue_id, + &message, + &size, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT + ); +} + +static void RtemsMessageReqPerfReceiveWaitForever_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfReceiveWaitForever_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Restore the worker priority. Discard + * samples interrupted by a clock tick. + */ +static bool RtemsMessageReqPerfReceiveWaitForever_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + SetPriority( ctx->worker_id, PRIO_HIGH ); + + return tic == toc; +} + +static bool RtemsMessageReqPerfReceiveWaitForever_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfReceiveWaitForever_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Schedule a message send. + */ +static void RtemsMessageReqPerfReceiveWaitTimed_Setup( + RtemsMessageValPerf_Context *ctx +) +{ + SetPriority( ctx->worker_id, PRIO_LOW ); + Send( ctx, EVENT_END | EVENT_SEND ); +} + +static void RtemsMessageReqPerfReceiveWaitTimed_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfReceiveWaitTimed_Setup( ctx ); +} + +/** + * @brief Receive a message. Wait with a timeout. + */ +static void RtemsMessageReqPerfReceiveWaitTimed_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + size_t size; + + ctx->begin = T_tick(); + ctx->status = rtems_message_queue_receive( + ctx->queue_id, + &message, + &size, + RTEMS_WAIT, + UINT32_MAX + ); +} + +static void RtemsMessageReqPerfReceiveWaitTimed_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfReceiveWaitTimed_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Restore the worker priority. Discard + * samples interrupted by a clock tick. + */ +static bool RtemsMessageReqPerfReceiveWaitTimed_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + SetPriority( ctx->worker_id, PRIO_HIGH ); + + return tic == toc; +} + +static bool RtemsMessageReqPerfReceiveWaitTimed_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfReceiveWaitTimed_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Send a message. + */ +static void RtemsMessageReqPerfSend_Body( RtemsMessageValPerf_Context *ctx ) +{ + uint64_t message; + + ctx->status = rtems_message_queue_send( + ctx->queue_id, + &message, + sizeof( message ) + ); +} + +static void RtemsMessageReqPerfSend_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSend_Body( ctx ); +} + +/** + * @brief Flush the message queue. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsMessageReqPerfSend_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + rtems_status_code sc; + uint32_t count; + + T_quiet_rsc_success( ctx->status ); + + sc = rtems_message_queue_flush( ctx->queue_id, &count ); + T_quiet_rsc_success( sc ); + T_quiet_eq_u32( count, 1 ); + + return tic == toc; +} + +static bool RtemsMessageReqPerfSend_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfSend_Teardown( ctx, delta, tic, toc, retry ); +} + +/** + * @brief Let the worker wait on the message queue. + */ +static void RtemsMessageReqPerfSendOther_Setup( + RtemsMessageValPerf_Context *ctx +) +{ + Send( ctx, EVENT_RECEIVE ); + SetPriority( ctx->worker_id, PRIO_LOW ); +} + +static void RtemsMessageReqPerfSendOther_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendOther_Setup( ctx ); +} + +/** + * @brief Send a message. + */ +static void RtemsMessageReqPerfSendOther_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + + ctx->status = rtems_message_queue_send( + ctx->queue_id, + &message, + sizeof( message ) + ); +} + +static void RtemsMessageReqPerfSendOther_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendOther_Body( ctx ); +} + +/** + * @brief Restore the worker priority. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsMessageReqPerfSendOther_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + SetPriority( ctx->worker_id, PRIO_HIGH ); + + return tic == toc; +} + +static bool RtemsMessageReqPerfSendOther_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfSendOther_Teardown( ctx, delta, tic, toc, retry ); +} + +#if defined(RTEMS_SMP) +/** + * @brief Move worker to scheduler B. + */ +static void RtemsMessageReqPerfSendOtherCpu_Prepare( + RtemsMessageValPerf_Context *ctx +) +{ + SetScheduler( ctx->worker_id, SCHEDULER_B_ID, PRIO_NORMAL ); +} + +/** + * @brief Let the worker wait on the message queue. + */ +static void RtemsMessageReqPerfSendOtherCpu_Setup( + RtemsMessageValPerf_Context *ctx +) +{ + Send( ctx, EVENT_RECEIVE | EVENT_RECEIVE_END ); + WaitForNextTask( 1, ctx->worker_id ); +} + +static void RtemsMessageReqPerfSendOtherCpu_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendOtherCpu_Setup( ctx ); +} + +/** + * @brief Send a message. + */ +static void RtemsMessageReqPerfSendOtherCpu_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + + ctx->begin = T_tick(); + ctx->status = rtems_message_queue_send( + ctx->queue_id, + &message, + sizeof( message ) + ); +} + +static void RtemsMessageReqPerfSendOtherCpu_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendOtherCpu_Body( ctx ); +} + +/** + * @brief Make sure the worker waits for the next event. Set the measured + * runtime. Discard samples interrupted by a clock tick. + */ +static bool RtemsMessageReqPerfSendOtherCpu_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + WaitForNextTask( 1, ctx->worker_id ); + *delta = ctx->end - ctx->begin; + + return tic == toc; +} + +static bool RtemsMessageReqPerfSendOtherCpu_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfSendOtherCpu_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @brief Move worker to scheduler A. + */ +static void RtemsMessageReqPerfSendOtherCpu_Cleanup( + RtemsMessageValPerf_Context *ctx +) +{ + SetScheduler( ctx->worker_id, SCHEDULER_A_ID, PRIO_HIGH ); +} +#endif + +/** + * @brief Let the worker wait on the message queue. + */ +static void RtemsMessageReqPerfSendPreempt_Setup( + RtemsMessageValPerf_Context *ctx +) +{ + Send( ctx, EVENT_RECEIVE | EVENT_RECEIVE_END ); +} + +static void RtemsMessageReqPerfSendPreempt_Setup_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendPreempt_Setup( ctx ); +} + +/** + * @brief Send a message. + */ +static void RtemsMessageReqPerfSendPreempt_Body( + RtemsMessageValPerf_Context *ctx +) +{ + uint64_t message; + + ctx->begin = T_tick(); + ctx->status = rtems_message_queue_send( + ctx->queue_id, + &message, + sizeof( message ) + ); +} + +static void RtemsMessageReqPerfSendPreempt_Body_Wrap( void *arg ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + RtemsMessageReqPerfSendPreempt_Body( ctx ); +} + +/** + * @brief Set the measured runtime. Discard samples interrupted by a clock + * tick. + */ +static bool RtemsMessageReqPerfSendPreempt_Teardown( + RtemsMessageValPerf_Context *ctx, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + T_quiet_rsc_success( ctx->status ); + + *delta = ctx->end - ctx->begin; + + return tic == toc; +} + +static bool RtemsMessageReqPerfSendPreempt_Teardown_Wrap( + void *arg, + T_ticks *delta, + uint32_t tic, + uint32_t toc, + unsigned int retry +) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = arg; + return RtemsMessageReqPerfSendPreempt_Teardown( + ctx, + delta, + tic, + toc, + retry + ); +} + +/** + * @fn void T_case_body_RtemsMessageValPerf( void ) + */ +T_TEST_CASE_FIXTURE( RtemsMessageValPerf, &RtemsMessageValPerf_Fixture ) +{ + RtemsMessageValPerf_Context *ctx; + + ctx = T_fixture_context(); + + ctx->request.name = "RtemsMessageReqPerfReceiveTry"; + ctx->request.setup = NULL; + ctx->request.body = RtemsMessageReqPerfReceiveTry_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfReceiveTry_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + ctx->request.name = "RtemsMessageReqPerfReceiveWaitForever"; + ctx->request.setup = RtemsMessageReqPerfReceiveWaitForever_Setup_Wrap; + ctx->request.body = RtemsMessageReqPerfReceiveWaitForever_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfReceiveWaitForever_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + ctx->request.name = "RtemsMessageReqPerfReceiveWaitTimed"; + ctx->request.setup = RtemsMessageReqPerfReceiveWaitTimed_Setup_Wrap; + ctx->request.body = RtemsMessageReqPerfReceiveWaitTimed_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfReceiveWaitTimed_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + ctx->request.name = "RtemsMessageReqPerfSend"; + ctx->request.setup = NULL; + ctx->request.body = RtemsMessageReqPerfSend_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfSend_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + ctx->request.name = "RtemsMessageReqPerfSendOther"; + ctx->request.setup = RtemsMessageReqPerfSendOther_Setup_Wrap; + ctx->request.body = RtemsMessageReqPerfSendOther_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfSendOther_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + + #if defined(RTEMS_SMP) + RtemsMessageReqPerfSendOtherCpu_Prepare( ctx ); + ctx->request.name = "RtemsMessageReqPerfSendOtherCpu"; + ctx->request.setup = RtemsMessageReqPerfSendOtherCpu_Setup_Wrap; + ctx->request.body = RtemsMessageReqPerfSendOtherCpu_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfSendOtherCpu_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); + RtemsMessageReqPerfSendOtherCpu_Cleanup( ctx ); + #endif + + ctx->request.name = "RtemsMessageReqPerfSendPreempt"; + ctx->request.setup = RtemsMessageReqPerfSendPreempt_Setup_Wrap; + ctx->request.body = RtemsMessageReqPerfSendPreempt_Body_Wrap; + ctx->request.teardown = RtemsMessageReqPerfSendPreempt_Teardown_Wrap; + T_measure_runtime( ctx->context, &ctx->request ); +} + +/** @} */ diff --git a/testsuites/validation/tc-message-receive.c b/testsuites/validation/tc-message-receive.c new file mode 100644 index 0000000000..02a8ba9062 --- /dev/null +++ b/testsuites/validation/tc-message-receive.c @@ -0,0 +1,1474 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqReceive + */ + +/* + * 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 "tr-tq-enqueue-fifo.h" +#include "tr-tq-enqueue-priority.h" +#include "tx-support.h" +#include "tx-thread-queue.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsMessageReqReceive \ + * spec:/rtems/message/req/receive + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqReceive_Pre_Buffer_Valid, + RtemsMessageReqReceive_Pre_Buffer_Null, + RtemsMessageReqReceive_Pre_Buffer_NA +} RtemsMessageReqReceive_Pre_Buffer; + +typedef enum { + RtemsMessageReqReceive_Pre_Size_Valid, + RtemsMessageReqReceive_Pre_Size_Null, + RtemsMessageReqReceive_Pre_Size_NA +} RtemsMessageReqReceive_Pre_Size; + +typedef enum { + RtemsMessageReqReceive_Pre_Id_Valid, + RtemsMessageReqReceive_Pre_Id_Invalid, + RtemsMessageReqReceive_Pre_Id_NA +} RtemsMessageReqReceive_Pre_Id; + +typedef enum { + RtemsMessageReqReceive_Pre_DuringWait_Nop, + RtemsMessageReqReceive_Pre_DuringWait_Deleted, + RtemsMessageReqReceive_Pre_DuringWait_NA +} RtemsMessageReqReceive_Pre_DuringWait; + +typedef enum { + RtemsMessageReqReceive_Pre_TaskQueue_Fifo, + RtemsMessageReqReceive_Pre_TaskQueue_Priority, + RtemsMessageReqReceive_Pre_TaskQueue_NA +} RtemsMessageReqReceive_Pre_TaskQueue; + +typedef enum { + RtemsMessageReqReceive_Pre_Wait_No, + RtemsMessageReqReceive_Pre_Wait_Timeout, + RtemsMessageReqReceive_Pre_Wait_Forever, + RtemsMessageReqReceive_Pre_Wait_NA +} RtemsMessageReqReceive_Pre_Wait; + +typedef enum { + RtemsMessageReqReceive_Pre_MsgQueue_Empty, + RtemsMessageReqReceive_Pre_MsgQueue_One, + RtemsMessageReqReceive_Pre_MsgQueue_Several, + RtemsMessageReqReceive_Pre_MsgQueue_NA +} RtemsMessageReqReceive_Pre_MsgQueue; + +typedef enum { + RtemsMessageReqReceive_Pre_Storage_Nop, + RtemsMessageReqReceive_Pre_Storage_NA +} RtemsMessageReqReceive_Pre_Storage; + +typedef enum { + RtemsMessageReqReceive_Post_Status_Ok, + RtemsMessageReqReceive_Post_Status_InvId, + RtemsMessageReqReceive_Post_Status_InvAddr, + RtemsMessageReqReceive_Post_Status_Unsat, + RtemsMessageReqReceive_Post_Status_Timeout, + RtemsMessageReqReceive_Post_Status_Deleted, + RtemsMessageReqReceive_Post_Status_NA +} RtemsMessageReqReceive_Post_Status; + +typedef enum { + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Delay_Ticks, + RtemsMessageReqReceive_Post_Delay_Forever, + RtemsMessageReqReceive_Post_Delay_NA +} RtemsMessageReqReceive_Post_Delay; + +typedef enum { + RtemsMessageReqReceive_Post_Size_First, + RtemsMessageReqReceive_Post_Size_Nop, + RtemsMessageReqReceive_Post_Size_NA +} RtemsMessageReqReceive_Post_Size; + +typedef enum { + RtemsMessageReqReceive_Post_Msg_First, + RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_Msg_NA +} RtemsMessageReqReceive_Post_Msg; + +typedef enum { + RtemsMessageReqReceive_Post_MsgQueue_Empty, + RtemsMessageReqReceive_Post_MsgQueue_OneLess, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_MsgQueue_NA +} RtemsMessageReqReceive_Post_MsgQueue; + +typedef enum { + RtemsMessageReqReceive_Post_Tasks_Fifo, + RtemsMessageReqReceive_Post_Tasks_Priority, + RtemsMessageReqReceive_Post_Tasks_NA +} RtemsMessageReqReceive_Post_Tasks; + +typedef struct { + uint32_t Skip : 1; + uint32_t Pre_Buffer_NA : 1; + uint32_t Pre_Size_NA : 1; + uint32_t Pre_Id_NA : 1; + uint32_t Pre_DuringWait_NA : 1; + uint32_t Pre_TaskQueue_NA : 1; + uint32_t Pre_Wait_NA : 1; + uint32_t Pre_MsgQueue_NA : 1; + uint32_t Pre_Storage_NA : 1; + uint32_t Post_Status : 3; + uint32_t Post_Delay : 2; + uint32_t Post_Size : 2; + uint32_t Post_Msg : 2; + uint32_t Post_MsgQueue : 2; + uint32_t Post_Tasks : 2; +} RtemsMessageReqReceive_Entry; + +#define MAXIMUM_PENDING_MESSAGES 3 +#define MAXIMUM_MESSAGE_SIZE 5 + +/** + * @brief Test context for spec:/rtems/message/req/receive test case. + */ +typedef struct { + /** + * @brief This member contains the thread queue test context. + */ + TQContext tq_ctx; + + /** + * @brief This member specifies the attribute set of the message queue. + */ + rtems_attribute attribute_set; + + /** + * @brief This member is used as storage area for the message queue. + */ + RTEMS_MESSAGE_QUEUE_BUFFER( MAXIMUM_MESSAGE_SIZE ) + storage_area[ MAXIMUM_PENDING_MESSAGES]; + + /** + * @brief This member contains always the same arbitrary number ``magic``. + * + * It is used for run-time type checking. + */ + uint32_t magic;; + + /** + * @brief This member contains a number which is sent as next message. + */ + uint8_t send_msg_counter; + + /** + * @brief This member contains a buffer to receive messages from the queue. + */ + uint8_t receive_buffer[ MAXIMUM_MESSAGE_SIZE ]; + + /** + * @brief This member contains a buffer to receive the messages size. + */ + size_t receive_size; + + /** + * @brief This member specifies the ``id`` parameter for the action. + */ + rtems_id id_param; + + /** + * @brief This member specifies the ``buffer`` parameter for the action. + */ + void *buffer_param; + + /** + * @brief This member specifies the ``size`` parameter for the action. + */ + size_t *size_param; + + /** + * @brief This member specifies the ``option_set`` parameter for the action. + */ + rtems_option option_set_param; + + /** + * @brief This member specifies the ``timeout`` parameter for the action. + */ + rtems_interval timeout_param; + + /** + * @brief This member contains the returned status code of the action. + */ + rtems_status_code status; + + /** + * @brief This member contains the duration of the action in ticks. + */ + uint32_t action_duration; + + /** + * @brief This member contains the task identifier of the main task. + */ + rtems_id task_id; + + /** + * @brief This member contains the task identifier of the worker task. + */ + rtems_id worker_id; + + /** + * @brief This member contains a pointer to a function which is executed + * while the worker is waiting to receive a message (`delete(), nop()``). + */ + void (*concurrent_activity)( void *ctx_in ); + + /** + * @brief This member contains a pointer to a function which is executed to + * check that the action has not changed the content of the message queue. + */ + void (*check_msgq_unchanged)( void *ctx_in ); + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 8 ]; + + /** + * @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. + */ + RtemsMessageReqReceive_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqReceive_Context; + +static RtemsMessageReqReceive_Context + RtemsMessageReqReceive_Instance; + +static const char * const RtemsMessageReqReceive_PreDesc_Buffer[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_Size[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_Id[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_DuringWait[] = { + "Nop", + "Deleted", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_TaskQueue[] = { + "Fifo", + "Priority", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_Wait[] = { + "No", + "Timeout", + "Forever", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_MsgQueue[] = { + "Empty", + "One", + "Several", + "NA" +}; + +static const char * const RtemsMessageReqReceive_PreDesc_Storage[] = { + "Nop", + "NA" +}; + +static const char * const * const RtemsMessageReqReceive_PreDesc[] = { + RtemsMessageReqReceive_PreDesc_Buffer, + RtemsMessageReqReceive_PreDesc_Size, + RtemsMessageReqReceive_PreDesc_Id, + RtemsMessageReqReceive_PreDesc_DuringWait, + RtemsMessageReqReceive_PreDesc_TaskQueue, + RtemsMessageReqReceive_PreDesc_Wait, + RtemsMessageReqReceive_PreDesc_MsgQueue, + RtemsMessageReqReceive_PreDesc_Storage, + NULL +}; + +typedef RtemsMessageReqReceive_Context Context; +static const uint32_t magic = 0xA55CA3D1; /* an arbitrary number */ +static const rtems_interval timeout_ticks = 3; +static const rtems_event_set wake_main_task_event = RTEMS_EVENT_17; + +static void DoAction( void *ctx_in ) +{ + Context *ctx = ctx_in; + ctx->status = rtems_message_queue_receive( + ctx->id_param, + ctx->buffer_param, + ctx->size_param, + ctx->option_set_param, + ctx->timeout_param + ); +} + +static void WorkerTask( unsigned int argument ) +{ + Context *ctx = (Context *) argument; + if ( ctx != NULL ) { + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + DoAction( ctx ); + T_rsc_success( rtems_event_send( ctx->task_id, wake_main_task_event ) ); + } + T_rsc_success( rtems_task_suspend( RTEMS_SELF ) ); +} + +static void WorkerDoAction( void *ctx_in ) +{ + rtems_status_code status; + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + status = rtems_task_restart( ctx->worker_id, (rtems_task_argument) ctx ); + T_rsc_success( status ); +} + +static uint32_t WaitForWorker( Context *ctx ) +{ + uint32_t ticks_to_wait = timeout_ticks + 1; + rtems_status_code status; + rtems_event_set event_set; + + for ( ; ticks_to_wait > 0; --ticks_to_wait ) { + /* Check whether the worker finished executing the action */ + status = rtems_event_receive( + RTEMS_PENDING_EVENTS, + RTEMS_NO_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &event_set + ); + T_rsc_success( status ); + + if ( ( event_set & wake_main_task_event ) == wake_main_task_event ) { + break; + } + TimecounterTick(); + } + + if ( ctx->timeout_param != RTEMS_NO_TIMEOUT ) { + /* Wait till the worker task finishes */ + status = rtems_event_receive( + wake_main_task_event, + RTEMS_DEFAULT_OPTIONS, + RTEMS_NO_TIMEOUT, + &event_set + ); + T_rsc_success( status ); + } + + return timeout_ticks + 1 - ticks_to_wait; +} + +static void MessageQueueSetup( Context *ctx ) +{ + rtems_status_code status; + /* Sanity check: Make sure the message queue does not exist, yet. */ + T_assert_eq_u32( ctx->tq_ctx.thread_queue_id, RTEMS_ID_NONE ); + rtems_message_queue_config config = { + .name = rtems_build_name( 'M', 'S', 'G', 'Q' ), + .maximum_pending_messages = MAXIMUM_PENDING_MESSAGES, + .maximum_message_size = MAXIMUM_MESSAGE_SIZE, + .storage_area = ctx->storage_area, + .storage_size = sizeof( ctx->storage_area ), + .storage_free = NULL, + .attributes = ctx->attribute_set + }; + + status = rtems_message_queue_construct( + &config, + &ctx->tq_ctx.thread_queue_id + ); + T_rsc_success( status ); + + if ( ctx->id_param != RTEMS_ID_NONE ) { + ctx->id_param = ctx->tq_ctx.thread_queue_id; + } +} + +static void MessageQueueTeardown( Context *ctx ) +{ + rtems_status_code status; + if ( ctx->tq_ctx.thread_queue_id != RTEMS_ID_NONE ) { + status = rtems_message_queue_delete( ctx->tq_ctx.thread_queue_id ); + T_rsc_success( status ); + ctx->tq_ctx.thread_queue_id = RTEMS_ID_NONE; + } +} + +static void CheckForNoMessage( + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) message_buffer; + (void) message_size; + T_rsc( status, RTEMS_UNSATISFIED ); +} + +static void CheckForFirstMessage( + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + T_rsc_success( status ); + T_eq_u32( message_size, 1 ); + T_eq_u8( message_buffer[0], 0 ); +} + +static void CheckForSecondMessage( + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + T_rsc_success( status ); + T_eq_u32( message_size, 3 ); + T_eq_u8( message_buffer[0], 1 ); + T_eq_u8( message_buffer[1], 1 ); + T_eq_u8( message_buffer[2], 1 ); +} + +static void CheckForThirdMessage( + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + T_rsc_success( status ); + T_eq_u32( message_size, 5 ); + T_eq_u8( message_buffer[0], 2 ); + T_eq_u8( message_buffer[1], 2 ); + T_eq_u8( message_buffer[2], 2 ); + T_eq_u8( message_buffer[3], 2 ); + T_eq_u8( message_buffer[4], 2 ); +} + +static void PopMessage( + Context *ctx, + void (*check_fn)( + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size + ) +) +{ + rtems_status_code status; + uint8_t message_buffer[ MAXIMUM_MESSAGE_SIZE ]; + size_t message_size; + + status = rtems_message_queue_receive( + ctx->tq_ctx.thread_queue_id, + &message_buffer, + &message_size, + RTEMS_LOCAL | RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT + ); + + check_fn( status, message_buffer, message_size ); +} + +static void CheckForNoMessageInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + PopMessage( ctx, CheckForNoMessage ); +} + +static void CheckForOneMessageInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + PopMessage( ctx, CheckForFirstMessage ); + PopMessage( ctx, CheckForNoMessage ); +} + +static void CheckForSeveralMessagesInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + PopMessage( ctx, CheckForFirstMessage ); + PopMessage( ctx, CheckForSecondMessage ); + PopMessage( ctx, CheckForThirdMessage ); + PopMessage( ctx, CheckForNoMessage ); +} + +static void MessageQueueNop( void *ctx_in ) +{ + (void) ctx_in; +} + +static void MessageQueueDelete( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + MessageQueueTeardown( ctx ); +} + +static Context *ToContext( TQContext *tqctx ) +{ + Context *ctx = RTEMS_CONTAINER_OF( tqctx, Context, tq_ctx ); + T_assert_eq_u32( ctx->magic, magic ); /* Run-time type check */ + return ctx; +} + +static Status_Control ReceiveMsg( TQContext *tqctx, TQWait wait ) +{ + Context *ctx = ToContext( tqctx ); + rtems_status_code status; + rtems_option option_set; + rtems_interval timeout; + + switch ( wait ) { + case TQ_WAIT_FOREVER: + option_set = RTEMS_WAIT; + timeout = RTEMS_NO_TIMEOUT; + break; + case TQ_WAIT_TIMED: + option_set = RTEMS_WAIT; + timeout = UINT32_MAX; + break; + default: + option_set = RTEMS_NO_WAIT; + timeout = 0; + break; + } + + status = rtems_message_queue_receive( + ctx->tq_ctx.thread_queue_id, + ctx->receive_buffer, + &ctx->receive_size, + option_set, + timeout + ); + + return STATUS_BUILD( status, 0 ); +} + +static void SendMsg( TQContext *tqctx ) +{ + Context *ctx = ToContext( tqctx ); + rtems_status_code status; + uint8_t msg[ MAXIMUM_MESSAGE_SIZE ]; + + memset( msg, ctx->send_msg_counter, MAXIMUM_MESSAGE_SIZE ); + status = rtems_message_queue_send( + ctx->tq_ctx.thread_queue_id, + msg, + ( ctx->send_msg_counter * 2 ) % MAXIMUM_MESSAGE_SIZE + 1 + ); + T_rsc_success( status ); + ++ctx->send_msg_counter; +} + +static void EnqueuePrepare( TQContext *tqctx ) +{ + Status_Control status; + + /* Check that the message queue is empty */ + status = TQEnqueue( tqctx, TQ_NO_WAIT ); + T_eq_int( status, STATUS_BUILD( RTEMS_UNSATISFIED, 0 ) ); +} + +static void EnqueueDone( TQContext *tqctx ) +{ + uint32_t i; + + for ( i = 0; i < tqctx->how_many; ++i ) { + SendMsg( tqctx ); + } +} + +static void RtemsMessageReqReceive_Pre_Buffer_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_Buffer state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_Buffer_Valid: { + /* + * While the ``buffer`` parameter references a memory area able to store + * a message up to the maximum size permitted in this message queue. + */ + ctx->buffer_param = ctx->receive_buffer; + break; + } + + case RtemsMessageReqReceive_Pre_Buffer_Null: { + /* + * While the ``buffer`` parameter is NULL. + */ + ctx->buffer_param = NULL; + break; + } + + case RtemsMessageReqReceive_Pre_Buffer_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_Size_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_Size state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_Size_Valid: { + /* + * While the ``size`` parameter references an object of type ``size_t``. + */ + ctx->size_param = &ctx->receive_size; + break; + } + + case RtemsMessageReqReceive_Pre_Size_Null: { + /* + * While the ``size`` parameter is NULL. + */ + ctx->size_param = NULL; + break; + } + + case RtemsMessageReqReceive_Pre_Size_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_Id_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_Id_Valid: { + /* + * While the ``id`` parameter is valid. + */ + ctx->id_param = 1; + break; + } + + case RtemsMessageReqReceive_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is invalid. + */ + ctx->id_param = RTEMS_ID_NONE; + break; + } + + case RtemsMessageReqReceive_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_DuringWait_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_DuringWait state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_DuringWait_Nop: { + /* + * While no rtems_message_queue_delete() directive is called successfully + * on the message queue during the time one or more tasks are waiting to + * receive messages. + */ + ctx->concurrent_activity = MessageQueueNop; + break; + } + + case RtemsMessageReqReceive_Pre_DuringWait_Deleted: { + /* + * While rtems_message_queue_delete() is called successfully on the + * message queue while one or more tasks are waiting to receive messages. + */ + ctx->concurrent_activity = MessageQueueDelete; + break; + } + + case RtemsMessageReqReceive_Pre_DuringWait_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_TaskQueue_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_TaskQueue state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_TaskQueue_Fifo: { + /* + * While the member attributes of type rtems_message_queue_config + * contains value RTEMS_FIFO when the message queue is constructed. + * + * Note: RTEMS_GLOBAL is not part of the space profile because no remote + * nodes are supported. + */ + ctx->attribute_set = RTEMS_LOCAL | RTEMS_FIFO; + break; + } + + case RtemsMessageReqReceive_Pre_TaskQueue_Priority: { + /* + * While the member attributes of type rtems_message_queue_config + * contains value RTEMS_PRIORITY when the message queue is constructed. + * + * Note: RTEMS_GLOBAL is not part of the space profile because no remote + * nodes are supported. + */ + ctx->attribute_set = RTEMS_LOCAL | RTEMS_PRIORITY; + break; + } + + case RtemsMessageReqReceive_Pre_TaskQueue_NA: + break; + } + + MessageQueueSetup( ctx ); +} + +static void RtemsMessageReqReceive_Pre_Wait_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_Wait state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_Wait_No: { + /* + * While the ``option_set`` parameter indicates the RTEMS_NO_WAIT option. + */ + ctx->tq_ctx.wait = TQ_NO_WAIT; + ctx->option_set_param = RTEMS_NO_WAIT; + ctx->timeout_param = 1; /* 0 would be RTEMS_NO_TIMEOUT */ + break; + } + + case RtemsMessageReqReceive_Pre_Wait_Timeout: { + /* + * While the ``option_set`` parameter indicates the RTEMS_WAIT option, + * while the ``timeout`` parameter is not equal to RTEMS_NO_TIMEOUT. + */ + ctx->tq_ctx.wait = TQ_WAIT_TIMED; + ctx->option_set_param = RTEMS_WAIT; + ctx->timeout_param = timeout_ticks; + break; + } + + case RtemsMessageReqReceive_Pre_Wait_Forever: { + /* + * While the ``option_set`` parameter indicates the RTEMS_WAIT option, + * while the ``timeout`` parameter is equal to RTEMS_NO_TIMEOUT. + */ + ctx->tq_ctx.wait = TQ_WAIT_FOREVER; + ctx->option_set_param = RTEMS_WAIT; + ctx->timeout_param = RTEMS_NO_TIMEOUT; + break; + } + + case RtemsMessageReqReceive_Pre_Wait_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_MsgQueue_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_MsgQueue_Empty: { + /* + * While there is no message in the message queue. + */ + /* Message queue is already empty. */ + ctx->check_msgq_unchanged = CheckForNoMessageInQueue; + break; + } + + case RtemsMessageReqReceive_Pre_MsgQueue_One: { + /* + * While there is exactly one message in the message queue. + */ + SendMsg( &( ctx->tq_ctx ) ); + ctx->check_msgq_unchanged = CheckForOneMessageInQueue; + break; + } + + case RtemsMessageReqReceive_Pre_MsgQueue_Several: { + /* + * While there are more than one message in the message queue. + */ + SendMsg( &( ctx->tq_ctx ) ); + SendMsg( &( ctx->tq_ctx ) ); + SendMsg( &( ctx->tq_ctx ) ); + ctx->check_msgq_unchanged = CheckForSeveralMessagesInQueue; + break; + } + + case RtemsMessageReqReceive_Pre_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqReceive_Pre_Storage_Prepare( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Pre_Storage state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Pre_Storage_Nop: { + /* + * While the memory area to which a pointer is provided as member + * storage_area of type rtems_message_queue_config when the message queue + * is constructed by rtems_message_queue_construct() is altered only by + * the RTEMS operating system. + */ + /* Only a requirement text. */ + break; + } + + case RtemsMessageReqReceive_Pre_Storage_NA: + break; + } +} + +static void RtemsMessageReqReceive_Post_Status_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Post_Status_Ok: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_SUCCESSFUL + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqReceive_Post_Status_InvId: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsMessageReqReceive_Post_Status_InvAddr: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsMessageReqReceive_Post_Status_Unsat: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_UNSATISFIED. + */ + T_rsc( ctx->status, RTEMS_UNSATISFIED ); + break; + } + + case RtemsMessageReqReceive_Post_Status_Timeout: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_TIMEOUT. + */ + T_rsc( ctx->status, RTEMS_TIMEOUT ); + break; + } + + case RtemsMessageReqReceive_Post_Status_Deleted: { + /* + * The return status of rtems_message_queue_receive() shall be + * RTEMS_OBJECT_WAS_DELETED. + */ + T_rsc( ctx->status, RTEMS_OBJECT_WAS_DELETED ); + break; + } + + case RtemsMessageReqReceive_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqReceive_Post_Delay_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_Delay state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Post_Delay_None: { + /* + * The rtems_message_queue_receive() call shall return immediately. + */ + T_eq_u32( ctx->action_duration, 0 ); + break; + } + + case RtemsMessageReqReceive_Post_Delay_Ticks: { + /* + * The rtems_message_queue_receive() call shall return after the timeout + * period in ticks. + */ + T_eq_u32( ctx->action_duration, timeout_ticks ); + break; + } + + case RtemsMessageReqReceive_Post_Delay_Forever: { + /* + * The rtems_message_queue_receive() call shall not return. + */ + T_gt_u32( ctx->action_duration, timeout_ticks ); + break; + } + + case RtemsMessageReqReceive_Post_Delay_NA: + break; + } +} + +static void RtemsMessageReqReceive_Post_Size_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_Size state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Post_Size_First: { + /* + * The value of the object referenced by the ``size`` parameter shall be + * set to the size of the first message (the same value as provided by + * parameter ``size`` of the rtems_message_queue_send() or + * rtems_message_queue_urgent() directive which added the message to the + * queue) after the return of the rtems_message_queue_receive() call. + */ + CheckForFirstMessage( + ctx->status, + ctx->receive_buffer, + ctx->receive_size + ); + break; + } + + case RtemsMessageReqReceive_Post_Size_Nop: { + /* + * Objects referenced by the ``size`` parameter in past calls to + * rtems_message_queue_receive() shall not be accessed by the + * rtems_message_queue_receive() call (see also Nop). + */ + T_eq_sz( ctx->receive_size, SIZE_MAX ); + break; + } + + case RtemsMessageReqReceive_Post_Size_NA: + break; + } +} + +static void RtemsMessageReqReceive_Post_Msg_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_Msg state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Post_Msg_First: { + /* + * The bytes 0 till ``size`` - 1 of the object referenced by the + * ``option_set`` parameter shall contain a copy of the content of the + * first message (all bytes unchanged and in the same order as provided + * by parameter ``buffer`` of the rtems_message_queue_send() or + * rtems_message_queue_urgent() directive which added the message to the + * queue) after the return of the rtems_message_queue_receive() call. + */ + CheckForFirstMessage( + ctx->status, + ctx->receive_buffer, + ctx->receive_size + ); + break; + } + + case RtemsMessageReqReceive_Post_Msg_Nop: { + /* + * Objects referenced by the ``option_set`` parameter in past calls to + * rtems_message_queue_receive() shall not be accessed by the + * rtems_message_queue_receive() call (see also Nop). + */ + int i; + for ( i = 0; i < MAXIMUM_MESSAGE_SIZE; ++i ) { + T_eq_u8( ctx->receive_buffer[i], UINT8_MAX ); + } + break; + } + + case RtemsMessageReqReceive_Post_Msg_NA: + break; + } +} + +static void RtemsMessageReqReceive_Post_MsgQueue_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqReceive_Post_MsgQueue_Empty: { + /* + * The message queue shall be empty after the return of the + * rtems_message_queue_receive() call. + */ + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqReceive_Post_MsgQueue_OneLess: { + /* + * The first message shall be removed from the message queue after the + * return of the rtems_message_queue_receive() call. + */ + PopMessage( ctx, CheckForSecondMessage ); + PopMessage( ctx, CheckForThirdMessage ); + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqReceive_Post_MsgQueue_Nop: { + /* + * Objects referenced by the ``id`` parameter in past calls to + * rtems_message_queue_receive() shall not be accessed by the + * rtems_message_queue_receive() call (see also Nop). + */ + ctx->check_msgq_unchanged( ctx ); + break; + } + + case RtemsMessageReqReceive_Post_MsgQueue_NA: + break; + } + + MessageQueueTeardown( ctx ); +} + +static void RtemsMessageReqReceive_Post_Tasks_Check( + RtemsMessageReqReceive_Context *ctx, + RtemsMessageReqReceive_Post_Tasks state +) +{ + MessageQueueSetup( ctx ); + + switch ( state ) { + case RtemsMessageReqReceive_Post_Tasks_Fifo: { + /* + * Where the thread queue uses the FIFO discipline, the calling thread + * shall be enqueued in FIFO order. + */ + ScoreTqReqEnqueueFifo_Run( &ctx->tq_ctx ); + break; + } + + case RtemsMessageReqReceive_Post_Tasks_Priority: { + /* + * Where the thread queue uses the priority discipline, the calling + * thread shall be enqueued in priority order. + */ + ScoreTqReqEnqueuePriority_Run( &ctx->tq_ctx ); + break; + } + + case RtemsMessageReqReceive_Post_Tasks_NA: + break; + } + + MessageQueueTeardown( ctx ); +} + +static void RtemsMessageReqReceive_Setup( RtemsMessageReqReceive_Context *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); + ctx->magic = magic; + ctx->tq_ctx.enqueue = ReceiveMsg; + ctx->tq_ctx.surrender = TQDoNothingSuccessfully; + ctx->tq_ctx.convert_status = TQConvertStatusClassic; + ctx->tq_ctx.enqueue_prepare = EnqueuePrepare; + ctx->tq_ctx.enqueue_done = EnqueueDone; + TQInitialize( &ctx->tq_ctx ); + + /* + * ctx->tq_ctx.thread_queue_id = RTEMS_ID_NONE indicates that the message + * queue does currently not exist. A message queue is created + * two times in a row in a single test cycle. First after the attributes + * are set in the preconditions. That queue is used for all tests of + * usual message queue requirements. Second a message queue is recreated + * in the tasks post-conditions for the tests of the task queue. + * To avoid an accidentally creation of a second + * message queue without the first being deleted prior, + * ctx->tq_ctx.thread_queue_id is checked for being RTEMS_ID_NONE before + * any message queue is created - a run-time sanity check. + */ + ctx->tq_ctx.thread_queue_id = RTEMS_ID_NONE; + ctx->task_id = rtems_task_self(); + + /* Note: TQInitialize() will assign the "main" task priority PRIO_NORMAL */ + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id, WorkerTask, NULL ); +} + +static void RtemsMessageReqReceive_Setup_Wrap( void *arg ) +{ + RtemsMessageReqReceive_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqReceive_Setup( ctx ); +} + +static void RtemsMessageReqReceive_Teardown( + RtemsMessageReqReceive_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); + TQDestroy( &ctx->tq_ctx ); + (void) PollAnyEvents(); +} + +static void RtemsMessageReqReceive_Teardown_Wrap( void *arg ) +{ + RtemsMessageReqReceive_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqReceive_Teardown( ctx ); +} + +static void RtemsMessageReqReceive_Prepare( + RtemsMessageReqReceive_Context *ctx +) +{ + /* Clean away pending events - happens after RTEMS_WAIT + RTEMS_NO_TIMEOUT */ + (void) PollAnyEvents(); + + ctx->send_msg_counter = 0; + ctx->receive_size = SIZE_MAX; + memset( ctx->receive_buffer, UINT8_MAX, MAXIMUM_MESSAGE_SIZE ); +} + +static void RtemsMessageReqReceive_Action( + RtemsMessageReqReceive_Context *ctx +) +{ + WorkerDoAction( ctx ); + ctx->concurrent_activity( ctx ); + ctx->action_duration = WaitForWorker( ctx ); +} + +static const RtemsMessageReqReceive_Entry +RtemsMessageReqReceive_Entries[] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_InvAddr, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_InvAddr, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_NA, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_InvId, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_InvId, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_NA, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 1, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_NA, + RtemsMessageReqReceive_Post_Delay_NA, RtemsMessageReqReceive_Post_Size_NA, + RtemsMessageReqReceive_Post_Msg_NA, + RtemsMessageReqReceive_Post_MsgQueue_NA, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Ok, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_First, + RtemsMessageReqReceive_Post_Msg_First, + RtemsMessageReqReceive_Post_MsgQueue_Empty, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Ok, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_First, + RtemsMessageReqReceive_Post_Msg_First, + RtemsMessageReqReceive_Post_MsgQueue_OneLess, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Deleted, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_NA, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Unsat, + RtemsMessageReqReceive_Post_Delay_None, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Timeout, + RtemsMessageReqReceive_Post_Delay_Ticks, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_Fifo }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_NA, + RtemsMessageReqReceive_Post_Delay_Forever, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_Fifo }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_Timeout, + RtemsMessageReqReceive_Post_Delay_Ticks, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_Priority }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqReceive_Post_Status_NA, + RtemsMessageReqReceive_Post_Delay_Forever, + RtemsMessageReqReceive_Post_Size_Nop, RtemsMessageReqReceive_Post_Msg_Nop, + RtemsMessageReqReceive_Post_MsgQueue_Nop, + RtemsMessageReqReceive_Post_Tasks_Priority } +}; + +static const uint8_t +RtemsMessageReqReceive_Map[] = { + 8, 5, 6, 9, 5, 6, 10, 5, 6, 8, 5, 6, 11, 5, 6, 12, 5, 6, 4, 4, 4, 7, 4, 4, 7, + 4, 4, 4, 4, 4, 7, 4, 4, 7, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1 +}; + +static size_t RtemsMessageReqReceive_Scope( void *arg, char *buf, size_t n ) +{ + RtemsMessageReqReceive_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( RtemsMessageReqReceive_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture RtemsMessageReqReceive_Fixture = { + .setup = RtemsMessageReqReceive_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageReqReceive_Teardown_Wrap, + .scope = RtemsMessageReqReceive_Scope, + .initial_context = &RtemsMessageReqReceive_Instance +}; + +static inline RtemsMessageReqReceive_Entry RtemsMessageReqReceive_PopEntry( + RtemsMessageReqReceive_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqReceive_Entries[ + RtemsMessageReqReceive_Map[ index ] + ]; +} + +static void RtemsMessageReqReceive_TestVariant( + RtemsMessageReqReceive_Context *ctx +) +{ + RtemsMessageReqReceive_Pre_Buffer_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqReceive_Pre_Size_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + RtemsMessageReqReceive_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + RtemsMessageReqReceive_Pre_DuringWait_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + RtemsMessageReqReceive_Pre_TaskQueue_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + RtemsMessageReqReceive_Pre_Wait_Prepare( ctx, ctx->Map.pcs[ 5 ] ); + RtemsMessageReqReceive_Pre_MsgQueue_Prepare( ctx, ctx->Map.pcs[ 6 ] ); + RtemsMessageReqReceive_Pre_Storage_Prepare( ctx, ctx->Map.pcs[ 7 ] ); + RtemsMessageReqReceive_Action( ctx ); + RtemsMessageReqReceive_Post_Status_Check( ctx, ctx->Map.entry.Post_Status ); + RtemsMessageReqReceive_Post_Delay_Check( ctx, ctx->Map.entry.Post_Delay ); + RtemsMessageReqReceive_Post_Size_Check( ctx, ctx->Map.entry.Post_Size ); + RtemsMessageReqReceive_Post_Msg_Check( ctx, ctx->Map.entry.Post_Msg ); + RtemsMessageReqReceive_Post_MsgQueue_Check( + ctx, + ctx->Map.entry.Post_MsgQueue + ); + RtemsMessageReqReceive_Post_Tasks_Check( ctx, ctx->Map.entry.Post_Tasks ); +} + +/** + * @fn void T_case_body_RtemsMessageReqReceive( void ) + */ +T_TEST_CASE_FIXTURE( RtemsMessageReqReceive, &RtemsMessageReqReceive_Fixture ) +{ + RtemsMessageReqReceive_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqReceive_Pre_Buffer_Valid; + ctx->Map.pcs[ 0 ] < RtemsMessageReqReceive_Pre_Buffer_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = RtemsMessageReqReceive_Pre_Size_Valid; + ctx->Map.pcs[ 1 ] < RtemsMessageReqReceive_Pre_Size_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = RtemsMessageReqReceive_Pre_Id_Valid; + ctx->Map.pcs[ 2 ] < RtemsMessageReqReceive_Pre_Id_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = RtemsMessageReqReceive_Pre_DuringWait_Nop; + ctx->Map.pcs[ 3 ] < RtemsMessageReqReceive_Pre_DuringWait_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = RtemsMessageReqReceive_Pre_TaskQueue_Fifo; + ctx->Map.pcs[ 4 ] < RtemsMessageReqReceive_Pre_TaskQueue_NA; + ++ctx->Map.pcs[ 4 ] + ) { + for ( + ctx->Map.pcs[ 5 ] = RtemsMessageReqReceive_Pre_Wait_No; + ctx->Map.pcs[ 5 ] < RtemsMessageReqReceive_Pre_Wait_NA; + ++ctx->Map.pcs[ 5 ] + ) { + for ( + ctx->Map.pcs[ 6 ] = RtemsMessageReqReceive_Pre_MsgQueue_Empty; + ctx->Map.pcs[ 6 ] < RtemsMessageReqReceive_Pre_MsgQueue_NA; + ++ctx->Map.pcs[ 6 ] + ) { + for ( + ctx->Map.pcs[ 7 ] = RtemsMessageReqReceive_Pre_Storage_Nop; + ctx->Map.pcs[ 7 ] < RtemsMessageReqReceive_Pre_Storage_NA; + ++ctx->Map.pcs[ 7 ] + ) { + ctx->Map.entry = RtemsMessageReqReceive_PopEntry( ctx ); + + if ( ctx->Map.entry.Skip ) { + continue; + } + + RtemsMessageReqReceive_Prepare( ctx ); + RtemsMessageReqReceive_TestVariant( ctx ); + } + } + } + } + } + } + } + } +} + +/** @} */ diff --git a/testsuites/validation/tc-message-urgent-send.c b/testsuites/validation/tc-message-urgent-send.c new file mode 100644 index 0000000000..fb42f94b84 --- /dev/null +++ b/testsuites/validation/tc-message-urgent-send.c @@ -0,0 +1,1167 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsMessageReqUrgentSend + */ + +/* + * 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 RTEMSTestCaseRtemsMessageReqUrgentSend \ + * spec:/rtems/message/req/urgent-send + * + * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Buffer_Valid, + RtemsMessageReqUrgentSend_Pre_Buffer_Null, + RtemsMessageReqUrgentSend_Pre_Buffer_NA +} RtemsMessageReqUrgentSend_Pre_Buffer; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Id_Valid, + RtemsMessageReqUrgentSend_Pre_Id_Invalid, + RtemsMessageReqUrgentSend_Pre_Id_NA +} RtemsMessageReqUrgentSend_Pre_Id; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Size_Zero, + RtemsMessageReqUrgentSend_Pre_Size_SomeSize, + RtemsMessageReqUrgentSend_Pre_Size_MaxSize, + RtemsMessageReqUrgentSend_Pre_Size_TooLarge, + RtemsMessageReqUrgentSend_Pre_Size_NA +} RtemsMessageReqUrgentSend_Pre_Size; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_MsgQueue_Empty, + RtemsMessageReqUrgentSend_Pre_MsgQueue_One, + RtemsMessageReqUrgentSend_Pre_MsgQueue_Several, + RtemsMessageReqUrgentSend_Pre_MsgQueue_Full, + RtemsMessageReqUrgentSend_Pre_MsgQueue_NA +} RtemsMessageReqUrgentSend_Pre_MsgQueue; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Receiver_Waiting, + RtemsMessageReqUrgentSend_Pre_Receiver_No, + RtemsMessageReqUrgentSend_Pre_Receiver_NA +} RtemsMessageReqUrgentSend_Pre_Receiver; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Directive_Send, + RtemsMessageReqUrgentSend_Pre_Directive_Urgent, + RtemsMessageReqUrgentSend_Pre_Directive_NA +} RtemsMessageReqUrgentSend_Pre_Directive; + +typedef enum { + RtemsMessageReqUrgentSend_Pre_Storage_Nop, + RtemsMessageReqUrgentSend_Pre_Storage_NA +} RtemsMessageReqUrgentSend_Pre_Storage; + +typedef enum { + RtemsMessageReqUrgentSend_Post_Status_Ok, + RtemsMessageReqUrgentSend_Post_Status_InvId, + RtemsMessageReqUrgentSend_Post_Status_InvAddr, + RtemsMessageReqUrgentSend_Post_Status_InvSize, + RtemsMessageReqUrgentSend_Post_Status_TooMany, + RtemsMessageReqUrgentSend_Post_Status_NA +} RtemsMessageReqUrgentSend_Post_Status; + +typedef enum { + RtemsMessageReqUrgentSend_Post_MsgQueue_Empty, + RtemsMessageReqUrgentSend_Post_MsgQueue_One, + RtemsMessageReqUrgentSend_Post_MsgQueue_Prepend, + RtemsMessageReqUrgentSend_Post_MsgQueue_Append, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_MsgQueue_NA +} RtemsMessageReqUrgentSend_Post_MsgQueue; + +typedef enum { + RtemsMessageReqUrgentSend_Post_Receiver_GotMsg, + RtemsMessageReqUrgentSend_Post_Receiver_Waiting, + RtemsMessageReqUrgentSend_Post_Receiver_NA +} RtemsMessageReqUrgentSend_Post_Receiver; + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Buffer_NA : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Pre_Size_NA : 1; + uint16_t Pre_MsgQueue_NA : 1; + uint16_t Pre_Receiver_NA : 1; + uint16_t Pre_Directive_NA : 1; + uint16_t Pre_Storage_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_MsgQueue : 3; + uint16_t Post_Receiver : 2; +} RtemsMessageReqUrgentSend_Entry; + +#define MAXIMUM_PENDING_MESSAGES 3 +#define MAXIMUM_MESSAGE_SIZE 5 + +/** + * @brief Test context for spec:/rtems/message/req/urgent-send test case. + */ +typedef struct { + /** + * @brief This member contains a valid ID of a message queue. + */ + rtems_id message_queue_id; + + /** + * @brief This member is used as storage area for the message queue. + */ + RTEMS_MESSAGE_QUEUE_BUFFER( MAXIMUM_MESSAGE_SIZE ) + storage_area[ MAXIMUM_PENDING_MESSAGES]; + + /** + * @brief This member contains always the same arbitrary number ``magic``. + * + * It is used for run-time type checking. + */ + uint32_t magic;; + + /** + * @brief This member contains a number which is sent as next message. + */ + uint8_t send_msg_counter; + + /** + * @brief This member contains a buffer to receive messages from the queue. + */ + uint8_t receive_buffer[ MAXIMUM_MESSAGE_SIZE ]; + + /** + * @brief This member contains a buffer to receive the messages size. + */ + size_t receive_size; + + /** + * @brief This member contains the returned status code of the receiver. + */ + rtems_status_code receive_status; + + /** + * @brief This member indicates whether the a receiver task should be started + * to receive a message. + */ + bool is_receiver_waiting; + + /** + * @brief This member contains the message to be sent by the action. + */ + uint8_t send_message[ MAXIMUM_MESSAGE_SIZE ]; + + /** + * @brief This member specifies the directive to be called as action. + * + * This is either rtems_message_queue_send() or rtems_message_queue_urgent(). + */ + rtems_status_code (*action)( rtems_id id, const void *buffer, size_t size ); + + /** + * @brief This member specifies the ``id`` parameter for the action. + */ + rtems_id id_param; + + /** + * @brief This member specifies the ``buffer`` parameter for the action. + */ + void *buffer_param; + + /** + * @brief This member specifies the ``size`` parameter for the action. + */ + size_t size_param; + + /** + * @brief This member contains the returned status code of the action. + */ + rtems_status_code status; + + /** + * @brief This member contains the task identifier of the worker task. + */ + rtems_id worker_id; + + /** + * @brief This member contains a pointer to a function which is executed to + * check that the action has not changed the content of the message queue. + */ + void (*check_msgq_unchanged)( void *ctx_in ); + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 7 ]; + + /** + * @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. + */ + RtemsMessageReqUrgentSend_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} RtemsMessageReqUrgentSend_Context; + +static RtemsMessageReqUrgentSend_Context + RtemsMessageReqUrgentSend_Instance; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Buffer[] = { + "Valid", + "Null", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Id[] = { + "Valid", + "Invalid", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Size[] = { + "Zero", + "SomeSize", + "MaxSize", + "TooLarge", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_MsgQueue[] = { + "Empty", + "One", + "Several", + "Full", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Receiver[] = { + "Waiting", + "No", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Directive[] = { + "Send", + "Urgent", + "NA" +}; + +static const char * const RtemsMessageReqUrgentSend_PreDesc_Storage[] = { + "Nop", + "NA" +}; + +static const char * const * const RtemsMessageReqUrgentSend_PreDesc[] = { + RtemsMessageReqUrgentSend_PreDesc_Buffer, + RtemsMessageReqUrgentSend_PreDesc_Id, + RtemsMessageReqUrgentSend_PreDesc_Size, + RtemsMessageReqUrgentSend_PreDesc_MsgQueue, + RtemsMessageReqUrgentSend_PreDesc_Receiver, + RtemsMessageReqUrgentSend_PreDesc_Directive, + RtemsMessageReqUrgentSend_PreDesc_Storage, + NULL +}; + +typedef RtemsMessageReqUrgentSend_Context Context; +static const uint32_t MAGIC = 0xA66FE31; /* an arbitrary number */ +static const rtems_interval TIMEOUT_TICKS = 1; +static const rtems_event_set EVENT_RECEIVE = RTEMS_EVENT_17; + +static void Receive( Context *ctx ) +{ + ctx->receive_status = rtems_message_queue_receive( + ctx->message_queue_id, + ctx->receive_buffer, + &ctx->receive_size, + RTEMS_WAIT, + TIMEOUT_TICKS + ); +} + +static void WorkerTask( rtems_task_argument argument ) +{ + Context *ctx = (Context *) argument; + + while ( true ) { + rtems_event_set events; + + events = ReceiveAnyEvents(); + + if ( ( events & EVENT_RECEIVE ) != 0 ) { + Receive( ctx ); + } + } +} + +static void CheckForNoMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc( status, RTEMS_UNSATISFIED ); +} + +static void CheckForFirstMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc_success( status ); + T_eq_u32( message_size, 1 ); + T_eq_u8( message_buffer[0], 0 ); +} + +static void CheckForSecondMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc_success( status ); + T_eq_u32( message_size, 3 ); + T_eq_u8( message_buffer[0], 1 ); + T_eq_u8( message_buffer[1], 1 ); + T_eq_u8( message_buffer[2], 1 ); +} + +static void CheckForThirdMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + (void) ctx; + T_rsc_success( status ); + T_eq_u32( message_size, 5 ); + T_eq_u8( message_buffer[0], 2 ); + T_eq_u8( message_buffer[1], 2 ); + T_eq_u8( message_buffer[2], 2 ); + T_eq_u8( message_buffer[3], 2 ); + T_eq_u8( message_buffer[4], 2 ); +} + +static void CheckForSendMessage( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size +) +{ + size_t i; + T_rsc_success( status ); + T_eq_u32( message_size, ctx->size_param ); + for ( i = 0; i < ctx->size_param; ++i ) { + T_eq_u8( message_buffer[i], ctx->send_message[i] ); + } +} + +static void PopMessage( + Context *ctx, + void (*check_fn)( + Context *ctx, + rtems_status_code status, + uint8_t *message_buffer, + size_t message_size + ) +) +{ + rtems_status_code status; + uint8_t message_buffer[ MAXIMUM_MESSAGE_SIZE ]; + size_t message_size; + + status = rtems_message_queue_receive( + ctx->message_queue_id, + &message_buffer, + &message_size, + RTEMS_LOCAL | RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT + ); + + check_fn( ctx, status, message_buffer, message_size ); +} + +static void CheckForNoMessageInQueue( void *ctx_in ) +{} + +static void CheckForOneMessageInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, MAGIC ); /* Run-time type check */ + PopMessage( ctx, CheckForFirstMessage ); +} + +static void CheckForSeveralMessagesInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, MAGIC ); /* Run-time type check */ + PopMessage( ctx, CheckForFirstMessage ); + PopMessage( ctx, CheckForSecondMessage ); +} + +static void CheckForAllMessagesInQueue( void *ctx_in ) +{ + Context *ctx = ctx_in; + T_assert_eq_u32( ctx->magic, MAGIC ); /* Run-time type check */ + PopMessage( ctx, CheckForFirstMessage ); + PopMessage( ctx, CheckForSecondMessage ); + PopMessage( ctx, CheckForThirdMessage ); +} + +static void SendMsg( Context *ctx ) +{ + rtems_status_code status; + uint8_t msg[ MAXIMUM_MESSAGE_SIZE ]; + + memset( msg, ctx->send_msg_counter, MAXIMUM_MESSAGE_SIZE ); + status = rtems_message_queue_send( + ctx->message_queue_id, + msg, + ( ctx->send_msg_counter * 2 ) % MAXIMUM_MESSAGE_SIZE + 1 + ); + T_rsc_success( status ); + ++ctx->send_msg_counter; +} + +static void RtemsMessageReqUrgentSend_Pre_Buffer_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Buffer state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Buffer_Valid: { + /* + * While the ``buffer`` parameter references a memory area where the + * message to be sent is stored. + */ + uint8_t i; + for ( i = 0; i < MAXIMUM_MESSAGE_SIZE; ++i ) { + ctx->send_message[i] = 42 + i; + } + ctx->buffer_param = &ctx->send_message; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Buffer_Null: { + /* + * While the ``buffer`` parameter is NULL. + */ + ctx->buffer_param = NULL; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Buffer_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_Id_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Id state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Id_Valid: { + /* + * While the ``id`` parameter is valid. + */ + ctx->id_param = ctx->message_queue_id; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Id_Invalid: { + /* + * While the ``id`` parameter is invalid. + */ + ctx->id_param = RTEMS_ID_NONE; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Id_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_Size_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Size state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Size_Zero: { + /* + * While the ``size`` parameter is 0. + */ + ctx->size_param = 0; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Size_SomeSize: { + /* + * While the ``size`` parameter has a value between 0 and the maximum + * message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE / 2 + 1; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Size_MaxSize: { + /* + * While the ``size`` parameter has a value of the maximum message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Size_TooLarge: { + /* + * While the ``size`` parameter has a value greater than the maximum + * message size. + */ + ctx->size_param = MAXIMUM_MESSAGE_SIZE + 1; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Size_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_MsgQueue_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_MsgQueue_Empty: { + /* + * While there is no message in the message queue. + */ + /* Message queue is already empty. */ + ctx->check_msgq_unchanged = CheckForNoMessageInQueue; + break; + } + + case RtemsMessageReqUrgentSend_Pre_MsgQueue_One: { + /* + * While there is exactly one message in the message queue. + */ + SendMsg( ctx ); + ctx->check_msgq_unchanged = CheckForOneMessageInQueue; + break; + } + + case RtemsMessageReqUrgentSend_Pre_MsgQueue_Several: { + /* + * While there are more than one and less than maximum pending messages + * in the message queue. + */ + SendMsg( ctx ); + SendMsg( ctx ); + ctx->check_msgq_unchanged = CheckForSeveralMessagesInQueue; + break; + } + + case RtemsMessageReqUrgentSend_Pre_MsgQueue_Full: { + /* + * While there are maximum pending messages in the message queue. + */ + SendMsg( ctx ); + SendMsg( ctx ); + SendMsg( ctx ); + ctx->check_msgq_unchanged = CheckForAllMessagesInQueue; + break; + } + + case RtemsMessageReqUrgentSend_Pre_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_Receiver_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Receiver state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Receiver_Waiting: { + /* + * While a receiver is waiting to receive a message. + */ + ctx->is_receiver_waiting = true; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Receiver_No: { + /* + * While no receiver is waiting to receive a message. + */ + ctx->is_receiver_waiting = false; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Receiver_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_Directive_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Directive state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Directive_Send: { + /* + * While the directive rtems_message_queue_send() is called. + */ + ctx->action = rtems_message_queue_send; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Directive_Urgent: { + /* + * While the directive rtems_message_queue_urgent() is called. + */ + ctx->action = rtems_message_queue_urgent; + break; + } + + case RtemsMessageReqUrgentSend_Pre_Directive_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Pre_Storage_Prepare( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Pre_Storage state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Pre_Storage_Nop: { + /* + * While the memory area to which a pointer is provided as member + * storage_area of type rtems_message_queue_config when the message queue + * is constructed by rtems_message_queue_construct() is altered only by + * the RTEMS operating system. + */ + /* Only a requirement text. */ + break; + } + + case RtemsMessageReqUrgentSend_Pre_Storage_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Post_Status_Check( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Post_Status state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Post_Status_Ok: { + /* + * The return status of the called directive (rtems_message_queue_send() + * or rtems_message_queue_urgent()) shall be RTEMS_SUCCESSFUL + */ + T_rsc_success( ctx->status ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Status_InvId: { + /* + * The return status of the called directive (rtems_message_queue_send() + * or rtems_message_queue_urgent()) shall be RTEMS_INVALID_ID. + */ + T_rsc( ctx->status, RTEMS_INVALID_ID ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Status_InvAddr: { + /* + * The return status of the called directive (rtems_message_queue_send() + * or rtems_message_queue_urgent()) shall be RTEMS_INVALID_ADDRESS. + */ + T_rsc( ctx->status, RTEMS_INVALID_ADDRESS ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Status_InvSize: { + /* + * The return status of the called directive (rtems_message_queue_send() + * or rtems_message_queue_urgent()) shall be RTEMS_INVALID_SIZE. + */ + T_rsc( ctx->status, RTEMS_INVALID_SIZE ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Status_TooMany: { + /* + * The return status of the called directive (rtems_message_queue_send() + * or rtems_message_queue_urgent()) shall be RTEMS_TOO_MANY. + */ + T_rsc( ctx->status, RTEMS_TOO_MANY ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Status_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Post_MsgQueue_Check( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Post_MsgQueue state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Post_MsgQueue_Empty: { + /* + * The message queue shall be empty after the return of the + * rtems_message_queue_send() or rtems_message_queue_urgent() call. + */ + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqUrgentSend_Post_MsgQueue_One: { + /* + * The message queue shall contain only the send message after the return + * of the rtems_message_queue_send() or rtems_message_queue_urgent() + * call. + */ + PopMessage( ctx, CheckForSendMessage ); + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqUrgentSend_Post_MsgQueue_Prepend: { + /* + * The message queue shall contain the message send by the last call to + * rtems_message_queue_urgent() as first message followed by all the + * messages which were in the message queue before that call (in the same + * order and each message with the same content and size). + */ + PopMessage( ctx, CheckForSendMessage ); + ctx->check_msgq_unchanged( ctx ); + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqUrgentSend_Post_MsgQueue_Append: { + /* + * The message queue shall contain the message send by the last call to + * rtems_message_queue_send() as last message preceded by all the + * messages which were in the message queue before that call (in the same + * order and each message with the same content and size). + */ + ctx->check_msgq_unchanged( ctx ); + PopMessage( ctx, CheckForSendMessage ); + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqUrgentSend_Post_MsgQueue_Nop: { + /* + * Objects referenced by the ``id`` parameter in past call to + * rtems_message_queue_send() or rtems_message_queue_urgent() shall not + * be accessed by that call (see also Nop). + */ + ctx->check_msgq_unchanged( ctx ); + PopMessage( ctx, CheckForNoMessage ); + break; + } + + case RtemsMessageReqUrgentSend_Post_MsgQueue_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Post_Receiver_Check( + RtemsMessageReqUrgentSend_Context *ctx, + RtemsMessageReqUrgentSend_Post_Receiver state +) +{ + switch ( state ) { + case RtemsMessageReqUrgentSend_Post_Receiver_GotMsg: { + /* + * The receiver shall receive the message send by the last call to the + * rtems_message_queue_send() or rtems_message_queue_urgent() directive. + */ + CheckForSendMessage( + ctx, + ctx->receive_status, + ctx->receive_buffer, + ctx->receive_size + ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Receiver_Waiting: { + /* + * The receiver shall still wait to receive a message after the last call + * to the rtems_message_queue_send() or rtems_message_queue_urgent() + * directive. + */ + T_rsc( ctx->receive_status, RTEMS_TIMEOUT ); + break; + } + + case RtemsMessageReqUrgentSend_Post_Receiver_NA: + break; + } +} + +static void RtemsMessageReqUrgentSend_Setup( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + ctx->magic = MAGIC; + + SetSelfPriority( PRIO_NORMAL ); + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); + StartTask( ctx->worker_id, WorkerTask, ctx ); +} + +static void RtemsMessageReqUrgentSend_Setup_Wrap( void *arg ) +{ + RtemsMessageReqUrgentSend_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqUrgentSend_Setup( ctx ); +} + +static void RtemsMessageReqUrgentSend_Teardown( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + DeleteTask( ctx->worker_id ); + RestoreRunnerPriority(); +} + +static void RtemsMessageReqUrgentSend_Teardown_Wrap( void *arg ) +{ + RtemsMessageReqUrgentSend_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + RtemsMessageReqUrgentSend_Teardown( ctx ); +} + +static void RtemsMessageReqUrgentSend_Prepare( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + rtems_status_code status; + + ctx->send_msg_counter = 0; + + rtems_message_queue_config config = { + .name = rtems_build_name( 'M', 'S', 'G', 'Q' ), + .maximum_pending_messages = MAXIMUM_PENDING_MESSAGES, + .maximum_message_size = MAXIMUM_MESSAGE_SIZE, + .storage_area = ctx->storage_area, + .storage_size = sizeof( ctx->storage_area ), + .storage_free = NULL, + .attributes = RTEMS_DEFAULT_ATTRIBUTES + }; + + status = rtems_message_queue_construct( + &config, + &ctx->message_queue_id + ); + T_rsc_success( status ); +} + +static void RtemsMessageReqUrgentSend_Action( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + if ( ctx->is_receiver_waiting ) { + SendEvents( ctx->worker_id, EVENT_RECEIVE ); + } + + ctx->status = (ctx->action)( + ctx->id_param, + ctx->buffer_param, + ctx->size_param + ); + + if ( ctx->is_receiver_waiting ) { + FinalClockTick(); + } +} + +static void RtemsMessageReqUrgentSend_Cleanup( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + T_rsc_success( rtems_message_queue_delete( ctx->message_queue_id ) ); +} + +static const RtemsMessageReqUrgentSend_Entry +RtemsMessageReqUrgentSend_Entries[] = { + { 1, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_NA, + RtemsMessageReqUrgentSend_Post_MsgQueue_NA, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvAddr, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvId, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvAddr, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_Waiting }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvSize, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvId, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_Waiting }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_Ok, + RtemsMessageReqUrgentSend_Post_MsgQueue_Empty, + RtemsMessageReqUrgentSend_Post_Receiver_GotMsg }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_Ok, + RtemsMessageReqUrgentSend_Post_MsgQueue_One, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_Ok, + RtemsMessageReqUrgentSend_Post_MsgQueue_Append, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_Ok, + RtemsMessageReqUrgentSend_Post_MsgQueue_Prepend, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_TooMany, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_NA }, + { 0, 0, 0, 0, 0, 0, 0, 0, RtemsMessageReqUrgentSend_Post_Status_InvSize, + RtemsMessageReqUrgentSend_Post_MsgQueue_Nop, + RtemsMessageReqUrgentSend_Post_Receiver_Waiting } +}; + +static const uint8_t +RtemsMessageReqUrgentSend_Map[] = { + 6, 6, 7, 7, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0, 10, 10, 6, 6, 7, 7, 0, 0, 8, 9, 0, + 0, 8, 9, 0, 0, 10, 10, 6, 6, 7, 7, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0, 10, 10, 11, + 11, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 5, 5, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 5, 5, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 5, 5, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 5, 5, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 3, 3, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, + 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 +}; + +static size_t RtemsMessageReqUrgentSend_Scope( void *arg, char *buf, size_t n ) +{ + RtemsMessageReqUrgentSend_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( + RtemsMessageReqUrgentSend_PreDesc, + buf, + n, + ctx->Map.pcs + ); + } + + return 0; +} + +static T_fixture RtemsMessageReqUrgentSend_Fixture = { + .setup = RtemsMessageReqUrgentSend_Setup_Wrap, + .stop = NULL, + .teardown = RtemsMessageReqUrgentSend_Teardown_Wrap, + .scope = RtemsMessageReqUrgentSend_Scope, + .initial_context = &RtemsMessageReqUrgentSend_Instance +}; + +static inline RtemsMessageReqUrgentSend_Entry +RtemsMessageReqUrgentSend_PopEntry( RtemsMessageReqUrgentSend_Context *ctx ) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return RtemsMessageReqUrgentSend_Entries[ + RtemsMessageReqUrgentSend_Map[ index ] + ]; +} + +static void RtemsMessageReqUrgentSend_TestVariant( + RtemsMessageReqUrgentSend_Context *ctx +) +{ + RtemsMessageReqUrgentSend_Pre_Buffer_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + RtemsMessageReqUrgentSend_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + RtemsMessageReqUrgentSend_Pre_Size_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + RtemsMessageReqUrgentSend_Pre_MsgQueue_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + RtemsMessageReqUrgentSend_Pre_Receiver_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + RtemsMessageReqUrgentSend_Pre_Directive_Prepare( ctx, ctx->Map.pcs[ 5 ] ); + RtemsMessageReqUrgentSend_Pre_Storage_Prepare( ctx, ctx->Map.pcs[ 6 ] ); + RtemsMessageReqUrgentSend_Action( ctx ); + RtemsMessageReqUrgentSend_Post_Status_Check( + ctx, + ctx->Map.entry.Post_Status + ); + RtemsMessageReqUrgentSend_Post_MsgQueue_Check( + ctx, + ctx->Map.entry.Post_MsgQueue + ); + RtemsMessageReqUrgentSend_Post_Receiver_Check( + ctx, + ctx->Map.entry.Post_Receiver + ); +} + +/** + * @fn void T_case_body_RtemsMessageReqUrgentSend( void ) + */ +T_TEST_CASE_FIXTURE( + RtemsMessageReqUrgentSend, + &RtemsMessageReqUrgentSend_Fixture +) +{ + RtemsMessageReqUrgentSend_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = RtemsMessageReqUrgentSend_Pre_Buffer_Valid; + ctx->Map.pcs[ 0 ] < RtemsMessageReqUrgentSend_Pre_Buffer_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = RtemsMessageReqUrgentSend_Pre_Id_Valid; + ctx->Map.pcs[ 1 ] < RtemsMessageReqUrgentSend_Pre_Id_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = RtemsMessageReqUrgentSend_Pre_Size_Zero; + ctx->Map.pcs[ 2 ] < RtemsMessageReqUrgentSend_Pre_Size_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = RtemsMessageReqUrgentSend_Pre_MsgQueue_Empty; + ctx->Map.pcs[ 3 ] < RtemsMessageReqUrgentSend_Pre_MsgQueue_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = RtemsMessageReqUrgentSend_Pre_Receiver_Waiting; + ctx->Map.pcs[ 4 ] < RtemsMessageReqUrgentSend_Pre_Receiver_NA; + ++ctx->Map.pcs[ 4 ] + ) { + for ( + ctx->Map.pcs[ 5 ] = RtemsMessageReqUrgentSend_Pre_Directive_Send; + ctx->Map.pcs[ 5 ] < RtemsMessageReqUrgentSend_Pre_Directive_NA; + ++ctx->Map.pcs[ 5 ] + ) { + for ( + ctx->Map.pcs[ 6 ] = RtemsMessageReqUrgentSend_Pre_Storage_Nop; + ctx->Map.pcs[ 6 ] < RtemsMessageReqUrgentSend_Pre_Storage_NA; + ++ctx->Map.pcs[ 6 ] + ) { + ctx->Map.entry = RtemsMessageReqUrgentSend_PopEntry( ctx ); + + if ( ctx->Map.entry.Skip ) { + continue; + } + + RtemsMessageReqUrgentSend_Prepare( ctx ); + RtemsMessageReqUrgentSend_TestVariant( ctx ); + RtemsMessageReqUrgentSend_Cleanup( ctx ); + } + } + } + } + } + } + } +} + +/** @} */ -- cgit v1.2.3