3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
26 /*! @file queue_send_blocking_utest.c */
28 /* C runtime includes. */
33 #include "../queue_utest_common.h"
37 #include "FreeRTOSConfig.h"
39 #include "mock_fake_port.h"
41 /* ============================ GLOBAL VARIABLES =========================== */
43 /* Used to share a QueueHandle_t between a test case and it's callbacks */
44 static QueueHandle_t xQueueHandleStatic;
46 /* ========================== CALLBACK FUNCTIONS =========================== */
48 /* ============================= Unity Fixtures ============================= */
53 vFakePortAssertIfInterruptPriorityInvalid_Ignore();
54 xQueueHandleStatic = NULL;
67 int suiteTearDown( int numFailures )
69 return commonSuiteTearDown( numFailures );
72 /* ========================== Helper functions =========================== */
74 /* ============================= Test Cases ============================== */
77 * @brief Callback for test_macro_xQueueSend_blocking_success which empties it's test queue.
79 static BaseType_t xQueueSend_locked_xTaskCheckForTimeOutCB( TimeOut_t * const pxTimeOut,
80 TickType_t * const pxTicksToWait,
83 BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
85 if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
87 uint32_t checkVal = INVALID_UINT32;
88 ( void ) xQueueReceiveFromISR( xQueueHandleStatic, &checkVal, NULL );
89 TEST_ASSERT_EQUAL( getLastMonotonicTestValue(), checkVal );
96 * @brief Test xQueueSend with timeout=10 on a full queue which is locked and
97 * has no tasks on it's WaitingToSend event list.
98 * @coverage prvUnlockQueue
100 void test_macro_xQueueSend_blocking_success_locked_no_pending( void )
102 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
104 /* Export for callbacks */
105 xQueueHandleStatic = xQueue;
107 uint32_t testVal = getNextMonotonicTestValue();
109 TEST_ASSERT_EQUAL( 0, uxQueueMessagesWaiting( xQueue ) );
111 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) );
113 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
115 xTaskCheckForTimeOut_Stub( &xQueueSend_locked_xTaskCheckForTimeOutCB );
116 xTaskResumeAll_Stub( &td_task_xTaskResumeAllStub );
118 uint32_t testVal2 = getLastMonotonicTestValue() + 12345;
120 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal2, TICKS_TO_WAIT ) );
122 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
124 /* Check that vPortYieldWithinAPI was called and would have yielded */
125 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
127 /* Check that vTaskMissedYield was not called */
128 TEST_ASSERT_EQUAL( 0, td_task_getCount_vTaskMissedYield() );
130 vQueueDelete( xQueue );
134 * @brief Callback used for xQueueSend blocking_locked tests.
136 static BaseType_t xQueueSend_xTaskResumeAllCallback( int cmock_num_calls )
138 BaseType_t xReturnValue = td_task_xTaskResumeAllStub( cmock_num_calls );
140 /* If td_task_xTaskResumeAllStub returns pdTRUE, a higher priority task is pending
141 * Send from an ISR to block */
142 if( pdTRUE == xReturnValue )
144 if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
146 uint32_t testVal = getNextMonotonicTestValue();
147 ( void ) xQueueSendFromISR( xQueueHandleStatic, &testVal, NULL );
155 * @brief Test xQueueSend with timeout=10 on a full queue which is locked and
156 * has a higher priority task on it's WaitingToSend event list.
157 * @coverage prvUnlockQueue
159 void test_macro_xQueueSend_blocking_fail_locked_high_prio_pending( void )
161 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
163 /* Export for callbacks */
164 xQueueHandleStatic = xQueue;
166 uint32_t testVal = getNextMonotonicTestValue();
168 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) );
170 xTaskCheckForTimeOut_Stub( &xQueueSend_locked_xTaskCheckForTimeOutCB );
171 xTaskResumeAll_Stub( &xQueueSend_xTaskResumeAllCallback );
173 /* this task is lower priority than the pending task */
174 td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
176 td_task_addFakeTaskWaitingToSendToQueue( xQueue );
178 uint32_t testVal2 = getLastMonotonicTestValue() + 12345;
180 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
182 TEST_ASSERT_EQUAL( pdFALSE, xQueueSend( xQueue, &testVal2, TICKS_TO_WAIT ) );
184 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
186 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
188 /* Check that xTaskResumeAll was called and would have yielded */
189 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT + 1, td_task_getCount_YieldFromTaskResumeAll() );
191 /* Check that vPortYieldWithinAPI was called and would have yielded */
192 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT - 1, td_task_getCount_vPortYieldWithinAPI() );
194 /* Check that vTaskMissedYield was called */
195 TEST_ASSERT_EQUAL( 1, td_task_getCount_vTaskMissedYield() );
197 vQueueDelete( xQueue );
201 * @brief Test xQueueSend with timeout=10 on a full queue which is locked and
202 * has a lower priority task on it's WaitingToSend event list.
203 * @coverage prvUnlockQueue
205 void test_macro_xQueueSend_blocking_success_locked_low_prio_pending( void )
207 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
209 /* Export for callbacks */
210 xQueueHandleStatic = xQueue;
212 uint32_t testVal = getNextMonotonicTestValue();
214 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) );
216 xTaskCheckForTimeOut_Stub( &xQueueSend_locked_xTaskCheckForTimeOutCB );
217 xTaskResumeAll_Stub( &xQueueSend_xTaskResumeAllCallback );
219 /* The pending task is lower priority */
220 td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
222 td_task_addFakeTaskWaitingToSendToQueue( xQueue );
224 uint32_t testVal2 = getLastMonotonicTestValue() + 12345;
226 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
228 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal2, TICKS_TO_WAIT ) );
230 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
232 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
234 /* Check that vPortYieldWithinAPI was called and would have yielded */
235 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
237 /* Check that vTaskMissedYield was not called */
238 TEST_ASSERT_EQUAL( 0, td_task_getCount_vTaskMissedYield() );
240 vQueueDelete( xQueue );
244 * @brief Test xQueueSend with taskSCHEDULER_SUSPENDED and timeout=10
245 * @details This should cause xQueueSend to configASSERT because it would
246 * block forever when the queue is full.
247 * @coverage xQueueGenericSend
249 void test_macro_xQueueSend_blocking_suspended_assert( void )
251 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
253 uint32_t testVal = getNextMonotonicTestValue();
255 fakeAssertExpectFail();
257 td_task_setSchedulerState( taskSCHEDULER_SUSPENDED );
259 TEST_ASSERT_EQUAL( 0, uxQueueMessagesWaiting( xQueue ) );
261 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 10 ) );
263 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
265 TEST_ASSERT_EQUAL( pdTRUE, fakeAssertGetFlagAndClear() );
267 td_task_setSchedulerState( taskSCHEDULER_RUNNING );
269 vQueueDelete( xQueue );
273 * @brief Test xQueueSend with taskSCHEDULER_RUNNING and timeout=10 on a full queue.
274 * @coverage xQueueGenericSend
276 void test_macro_xQueueSend_blocking_timeout( void )
278 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
280 uint32_t testVal = getNextMonotonicTestValue();
282 /* Fill up the queue */
283 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) );
285 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
287 TEST_ASSERT_EQUAL( errQUEUE_FULL, xQueueSend( xQueue, &testVal, TICKS_TO_WAIT ) );
289 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
291 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
293 /* Check that vPortYieldWithinAPI was called and would have yielded */
294 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
296 /* Check that vTaskMissedYield was not called */
297 TEST_ASSERT_EQUAL( 0, td_task_getCount_vTaskMissedYield() );
299 vQueueDelete( xQueue );
303 * @brief Test xQueueSend in blocking mode with a full locked queue.
304 * @details This test case verifies a situation that should never occur ( xQueueSend called on a locked queue ).
305 * @coverage xQueueGenericSend
307 void test_macro_xQueueSend_blocking_locked( void )
309 /* Create a new binary Queue */
310 QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
312 uint32_t testVal1 = getNextMonotonicTestValue();
315 TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal1, TICKS_TO_WAIT ) );
317 /* Set private lock counters */
318 vSetQueueRxLock( xQueue, queueLOCKED_UNMODIFIED );
319 vSetQueueTxLock( xQueue, queueLOCKED_UNMODIFIED );
321 uint32_t testVal2 = getNextMonotonicTestValue();
323 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
325 /* Call xQueueSend in blocking mode with the queue locked */
326 TEST_ASSERT_EQUAL( pdFALSE, xQueueSend( xQueue, &testVal2, TICKS_TO_WAIT ) );
328 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) );
330 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
332 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
334 /* Verify that the queue is now unlocked */
335 TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueRxLock( xQueue ) );
336 TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueTxLock( xQueue ) );
338 vQueueDelete( xQueue );