Minor nits. On Thu, Jul 20, 2023 at 7:40 AM Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > > From: Frank Kühndel <frank.kuehn...@embedded-brains.de> > > This unit test covers code paths of the Message Handler which are only > reached by through POSIX message queue API. > > Update #3716. > --- > .../build/testsuites/unit/unit-no-clock-0.yml | 1 + > testsuites/unit/tc-score-msgq.c | 452 ++++++++++++++++++ > 2 files changed, 453 insertions(+) > create mode 100644 testsuites/unit/tc-score-msgq.c > > diff --git a/spec/build/testsuites/unit/unit-no-clock-0.yml > b/spec/build/testsuites/unit/unit-no-clock-0.yml > index 57cd279a7a..517b84284d 100644 > --- a/spec/build/testsuites/unit/unit-no-clock-0.yml > +++ b/spec/build/testsuites/unit/unit-no-clock-0.yml > @@ -12,6 +12,7 @@ ldflags: [] > links: [] > source: > - testsuites/unit/tc-misaligned-builtin-memcpy.c > +- testsuites/unit/tc-score-msgq.c > - testsuites/unit/tc-score-rbtree.c > - testsuites/unit/ts-unit-no-clock-0.c > stlib: [] > diff --git a/testsuites/unit/tc-score-msgq.c b/testsuites/unit/tc-score-msgq.c > new file mode 100644 > index 0000000000..c4baa6d53e > --- /dev/null > +++ b/testsuites/unit/tc-score-msgq.c > @@ -0,0 +1,452 @@ > +/* SPDX-License-Identifier: BSD-2-Clause */ > + > +/** > + * @file > + * > + * @ingroup ScoreMsgqUnitMsgq > + */ > + > +/* > + * Copyright (C) 2021 embedded brains GmbH & Co. KG > + * > + * 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 <rtems.h> > +#include <rtems/rtems/messageimpl.h> > +#include <rtems/rtems/statusimpl.h> > +#include <rtems/score/coremsgimpl.h> > + > +#include "../validation/tx-support.h" > + > +#include <rtems/test.h> > + > +/** > + * @defgroup ScoreMsgqUnitMsgq spec:/score/msgq/unit/msgq > + * > + * @ingroup TestsuitesUnitNoClock0 > + * > + * @brief Unit tests for the Message Queue Handler. > + * > + * Parts of the files ``cpukit/score/src/coremsginsert.c``, > + * ``cpukit/score/src/coremsgseize.c``, and > + * ``cpukit/score/src/coremsgsubmit.c`` are only executed by the POSIX API. > + * Currently, the pre-qualified subset of RTEMS does not contain the POSIX > API. > + * This test exercises the code parts otherwise only reached by the POSIX API > + * to achieve full code coverage. > + * > + * This test case performs the following actions: > + * > + * - Use _CORE_message_queue_Insert_message() to insert two messages into a > + * message queue and use the POSIX message priority to define their order > in > + * the queue. > + * > + * - Check that _CORE_message_queue_Submit() was executed successfully. > + * > + * - Check that the messages are in right order in the message queue. "in the right" or "in correct"
> + * > + * - Submit three messages into a message queue which can only store two and > + * have the third submit() blocked till a seize() occurs. > + * > + * - Check that the third _CORE_message_queue_Submit() did actually block > + * till there was room for the message in the message queue. > + * > + * - Submit messages in the queue from within an ISR. > + * > + * - Check that the first two messages were successfully send. sent > + * > + * - Check that trying to send the third message from ISR when the message > + * queue was full was rejected. > + * > + * @{ > + */ > + > +#define MAXIMUM_PENDING_MESSAGES 2 > +#define MAXIMUM_MESSAGE_SIZE 3 > + > +static void WorkerTask( rtems_task_argument argument ); > + > +/** > + * @brief Test context for spec:/score/msgq/unit/msgq 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 task identifier of the worker task. > + */ > + rtems_id worker_id; > + > + /** > + * @brief This member indicated whether the worker task is currently > sending > + * a message (``true``) or whether it is waiting to receive an event > + * (``false``).. extra period > + */ > + bool is_worker_working; > + > + /** > + * @brief This member contains the returned status code of the > SendMessage() > + * function. > + */ > + rtems_status_code send_status; > +} ScoreMsgqUnitMsgq_Context; > + > +static ScoreMsgqUnitMsgq_Context > + ScoreMsgqUnitMsgq_Instance; > + > +#define EVENT_SEND RTEMS_EVENT_17 > +#define MESSAGE_CONTENT_LOW { 1, 2, 3 } > +#define MESSAGE_CONTENT_HIGH { 4, 5 } > +#define MESSAGE_PRIORITY_LOW 5 > +#define MESSAGE_PRIORITY_HIGH 7 > +#define DO_WAIT true > + > +typedef ScoreMsgqUnitMsgq_Context Context; > + > +/* > + * This is a code fragment from rtems_message_queue_send() with the > + * specialty that it uses a POSIX priority and the sender > + * task will wait in case the queue is full. > + */ > +static rtems_status_code SubmitMessage( > + rtems_id id, > + uint8_t *message, > + size_t message_size, > + unsigned int posix_piority > +) > +{ > + rtems_status_code status; > + Thread_queue_Context queue_context; > + Message_queue_Control *the_message_queue; > + > + T_assert_lt_uint( posix_piority, MQ_PRIO_MAX ); > + > + the_message_queue = _Message_queue_Get( > + id, > + &queue_context > + ); > + T_assert_not_null( the_message_queue ); > + > + /* The next two calls are from _POSIX_Message_queue_Send_support() */ > + _Thread_queue_Context_set_enqueue_callout( > + &queue_context, > + _Thread_queue_Enqueue_do_nothing_extra > + ); > + _Thread_queue_Context_set_timeout_argument( &queue_context, NULL, true ); > + > + _CORE_message_queue_Acquire_critical( > + &the_message_queue->message_queue, > + &queue_context > + ); > + > + status = _CORE_message_queue_Submit( > + &the_message_queue->message_queue, > + _Thread_Executing, > + message, > + message_size, > + (CORE_message_queue_Submit_types) ( posix_piority * -1 ), > + DO_WAIT, > + &queue_context > + ); > + > + return _Status_Get( status ); > +} > + > +static rtems_status_code ReceiveMessage( > + rtems_id id, > + void *buffer, > + size_t *size > +) > +{ > + return rtems_message_queue_receive( > + id, > + buffer, > + size, > + RTEMS_LOCAL | RTEMS_NO_WAIT, > + RTEMS_NO_TIMEOUT > + ); > +} > + > +static rtems_status_code ReceiveOneMessages( Context *ctx ) > +{ > + uint8_t message_buffer[ MAXIMUM_MESSAGE_SIZE ]; > + size_t message_size; > + > + return ReceiveMessage( > + ctx->message_queue_id, > + &message_buffer, > + &message_size > + ); > +} > + > +static void SendMessage( Context *ctx ) > +{ > + uint8_t message[] = { 100, 101, 102 }; > + ctx->send_status = SubmitMessage( > + ctx->message_queue_id, > + message, > + sizeof( message ), > + MESSAGE_PRIORITY_LOW > + ); > +} > + > +static void WorkerTask( rtems_task_argument argument ) > +{ > + Context *ctx = (Context *) argument; > + > + while ( true ) { > + ctx->is_worker_working = false; > + ReceiveAnyEvents(); > + ctx->is_worker_working = true; > + SendMessage( ctx ); > + T_assert_rsc_success( ctx->send_status ); > + } > +} > + > +static void WorkerSendMessage( Context *ctx ) > +{ > + SendEvents( ctx->worker_id, EVENT_SEND ); > +} > + > +static void ScoreMsgqUnitMsgq_Setup( ScoreMsgqUnitMsgq_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 ); > + > + SetSelfPriority( PRIO_NORMAL ); > + > + ctx->worker_id = CreateTask( "WORK", PRIO_HIGH ); > + StartTask( ctx->worker_id, WorkerTask, ctx ); > +} > + > +static void ScoreMsgqUnitMsgq_Setup_Wrap( void *arg ) > +{ > + ScoreMsgqUnitMsgq_Context *ctx; > + > + ctx = arg; > + ScoreMsgqUnitMsgq_Setup( ctx ); > +} > + > +static void ScoreMsgqUnitMsgq_Teardown( ScoreMsgqUnitMsgq_Context *ctx ) > +{ > + DeleteTask( ctx->worker_id ); > + RestoreRunnerPriority(); > + T_rsc_success( rtems_message_queue_delete( ctx->message_queue_id ) ); > +} > + > +static void ScoreMsgqUnitMsgq_Teardown_Wrap( void *arg ) > +{ > + ScoreMsgqUnitMsgq_Context *ctx; > + > + ctx = arg; > + ScoreMsgqUnitMsgq_Teardown( ctx ); > +} > + > +static T_fixture ScoreMsgqUnitMsgq_Fixture = { > + .setup = ScoreMsgqUnitMsgq_Setup_Wrap, > + .stop = NULL, > + .teardown = ScoreMsgqUnitMsgq_Teardown_Wrap, > + .scope = NULL, > + .initial_context = &ScoreMsgqUnitMsgq_Instance > +}; > + > +/** > + * @brief Use _CORE_message_queue_Insert_message() to insert two messages > into > + * a message queue and use the POSIX message priority to define their order > + * in the queue. > + */ > +static void ScoreMsgqUnitMsgq_Action_0( ScoreMsgqUnitMsgq_Context *ctx ) > +{ > + rtems_status_code status_submit_low; > + rtems_status_code status_submit_high; > + rtems_status_code status_receive_low; > + rtems_status_code status_receive_high; > + uint8_t message_low[] = MESSAGE_CONTENT_LOW; > + uint8_t message_high[] = MESSAGE_CONTENT_HIGH; > + uint8_t message_buffer_low[ MAXIMUM_MESSAGE_SIZE ]; > + uint8_t message_buffer_high[ MAXIMUM_MESSAGE_SIZE ]; > + size_t message_size_low; > + size_t message_size_high; > + > + status_submit_low = SubmitMessage( > + ctx->message_queue_id, > + message_low, > + sizeof( message_low ), > + MESSAGE_PRIORITY_LOW > + ); > + > + status_submit_high = SubmitMessage( > + ctx->message_queue_id, > + message_high, > + sizeof( message_high ), > + MESSAGE_PRIORITY_HIGH > + ); > + > + status_receive_high = ReceiveMessage( > + ctx->message_queue_id, > + &message_buffer_high, > + &message_size_high > + ); > + > + status_receive_low = ReceiveMessage( > + ctx->message_queue_id, > + &message_buffer_low, > + &message_size_low > + ); > + > + /* > + * Check that _CORE_message_queue_Submit() was executed successfully. > + */ > + T_rsc_success( status_submit_low ); > + T_rsc_success( status_submit_high ); > + > + /* > + * Check that the messages are in right order in the message queue. > + */ > + T_rsc_success( status_receive_high ); > + T_eq_sz( message_size_high, sizeof( message_high ) ); > + T_eq_mem( message_buffer_high, message_high, message_size_high ); > + > + T_rsc_success( status_receive_low ); > + T_eq_sz( message_size_low, sizeof( message_low ) ); > + T_eq_mem( message_buffer_low, message_low, message_size_low ); > +} > + > +/** > + * @brief Submit three messages into a message queue which can only store two > + * and have the third submit() blocked till a seize() occurs. > + */ > +static void ScoreMsgqUnitMsgq_Action_1( ScoreMsgqUnitMsgq_Context *ctx ) > +{ > + bool is_worker_blocked_after_third_send; > + bool is_worker_blocked_after_first_receive; > + > + WorkerSendMessage( ctx ); > + WorkerSendMessage( ctx ); > + WorkerSendMessage( ctx ); > + is_worker_blocked_after_third_send = ctx->is_worker_working; > + > + T_rsc_success( ReceiveOneMessages( ctx ) ); > + is_worker_blocked_after_first_receive = ctx->is_worker_working; > + > + T_rsc_success( ReceiveOneMessages( ctx ) ); > + T_rsc_success( ReceiveOneMessages( ctx ) ); > + > + /* > + * Check that the third _CORE_message_queue_Submit() did actually block > till > + * there was room for the message in the message queue. > + */ > + T_true( is_worker_blocked_after_third_send ); > + T_true( !is_worker_blocked_after_first_receive ); > +} > + > +/** > + * @brief Submit messages in the queue from within an ISR. > + */ > +static void ScoreMsgqUnitMsgq_Action_2( ScoreMsgqUnitMsgq_Context *ctx ) > +{ > + rtems_status_code status_send_first_message; > + rtems_status_code status_send_second_message; > + rtems_status_code status_send_third_message; > + > + CallWithinISR( ( void (*)(void*) ) SendMessage, ctx ); > + status_send_first_message = ctx->send_status; > + CallWithinISR( ( void (*)(void*) ) SendMessage, ctx ); > + status_send_second_message = ctx->send_status; > + CallWithinISR( ( void (*)(void*) ) SendMessage, ctx ); > + status_send_third_message = ctx->send_status; > + > + T_rsc_success( ReceiveOneMessages( ctx ) ); > + T_rsc_success( ReceiveOneMessages( ctx ) ); > + > + /* > + * Check that the first two messages were successfully send. > + */ > + T_assert_rsc_success( status_send_first_message ); > + T_assert_rsc_success( status_send_second_message ); > + > + /* > + * Check that trying to send the third message from ISR when the message > + * queue was full was rejected. > + */ > + T_rsc( status_send_third_message, STATUS_CLASSIC_INTERNAL_ERROR ); > +} > + > +/** > + * @fn void T_case_body_ScoreMsgqUnitMsgq( void ) > + */ > +T_TEST_CASE_FIXTURE( ScoreMsgqUnitMsgq, &ScoreMsgqUnitMsgq_Fixture ) > +{ > + ScoreMsgqUnitMsgq_Context *ctx; > + > + ctx = T_fixture_context(); > + > + ScoreMsgqUnitMsgq_Action_0( ctx ); > + ScoreMsgqUnitMsgq_Action_1( ctx ); > + ScoreMsgqUnitMsgq_Action_2( ctx ); > +} > + > +/** @} */ > -- > 2.35.3 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel