freertos: Fix stream buffer send-receive test

The stream buffer send-receive test preivously contained the following bugs:

- "sender" task would send 101 bytes instead of 100
- The main task would return before "sender" task sends its 101st item. Thus
  the sender task would cause memory corruption when accessing "tc" structure
  allocated on the main task's stack

This commit fixes and simplifies the stream buffer test.
This commit is contained in:
Darian Leung
2023-02-24 16:28:13 +08:00
parent 66bc1293aa
commit 241dbcaa9c

View File

@ -1,103 +1,74 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/stream_buffer.h" #include "freertos/stream_buffer.h"
#include "freertos/message_buffer.h"
#include "unity.h" #include "unity.h"
#include "test_utils.h" #include "test_utils.h"
typedef struct { #define TEST_NUM_BYTES 100
StreamBufferHandle_t sb; #define TEST_RECEIVER_TIMEOUT_TICKS pdMS_TO_TICKS(1000) // 1ms timeout for receiver task
SemaphoreHandle_t end_test;
bool send_fail;
bool receive_fail;
bool produce_isr;
}test_context;
static void producer_task(void *arg) typedef struct {
StreamBufferHandle_t stream_buffer;
SemaphoreHandle_t done_sem;
} test_args_t;
static void sender_task(void *arg)
{ {
test_context *tc = arg; test_args_t *test_args = (test_args_t *)arg;
uint8_t produced = 0;
printf("Starting sender task... \n"); printf("Starting sender task... \n");
while(produced < 100) { for (int i = 0; i < TEST_NUM_BYTES; i++) {
// Send a single byte, with the byte's value being the number of bytes sent thus far
if(!tc->produce_isr) { uint8_t data = (uint8_t)i;
BaseType_t result = xStreamBufferSend(tc->sb, &produced, 1, 0); TEST_ASSERT_EQUAL(1, xStreamBufferSend(test_args->stream_buffer, &data, 1, 0));
if(!result) { // Short delay to give a chance for receiver task to receive
tc->send_fail = true;
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL);
} else {
produced++;
}
}
vTaskDelay(1); vTaskDelay(1);
} }
tc->send_fail = false; xSemaphoreGive(test_args->done_sem);
vTaskDelete(NULL); vTaskDelete(NULL);
} }
static void receiver_task(void *arg) static void receiver_task(void *arg)
{ {
test_context *tc = arg; test_args_t *test_args = (test_args_t *)arg;
uint8_t expected_consumed = 0;
printf("Starting receiver task... \n"); printf("Starting receiver task... \n");
for(;;){ for (int i = 0; i < TEST_NUM_BYTES; i++) {
uint8_t read_byte = 0xFF; // Receive a single byte. The received byte's value being the number of bytes sent/received thus far
uint32_t result = xStreamBufferReceive(tc->sb, &read_byte, 1, 1000); uint8_t data;
TEST_ASSERT_EQUAL(1, xStreamBufferReceive(test_args->stream_buffer, &data, 1, TEST_RECEIVER_TIMEOUT_TICKS));
if((read_byte != expected_consumed) || !result) { TEST_ASSERT_EQUAL(i, data);
tc->receive_fail = true;
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL);
} else {
expected_consumed++;
if(expected_consumed == 99) {
break;
}
}
} }
tc->receive_fail = false; xSemaphoreGive(test_args->done_sem);
xSemaphoreGive(tc->end_test);
vTaskDelete(NULL); vTaskDelete(NULL);
} }
TEST_CASE("Send-receive stream buffer test", "[freertos]") TEST_CASE("Stream Buffer: Send-receive tasks", "[freertos]")
{ {
BaseType_t result; test_args_t test_args;
test_context tc; test_args.stream_buffer = xStreamBufferCreate(TEST_NUM_BYTES, 1);
test_args.done_sem = xSemaphoreCreateCounting(2, 0);
TEST_ASSERT_NOT_NULL(test_args.stream_buffer);
TEST_ASSERT_NOT_NULL(test_args.done_sem);
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(sender_task, "sender", 4096, &test_args, UNITY_FREERTOS_PRIORITY + 2, NULL, 0));
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(receiver_task, "receiver", 4096, &test_args, UNITY_FREERTOS_PRIORITY + 1, NULL, 1));
tc.sb = xStreamBufferCreate(128, 1); // Wait for both tasks to complete
tc.end_test = xSemaphoreCreateBinary(); for (int i = 0; i < 2; i++) {
xSemaphoreTake(test_args.done_sem, portMAX_DELAY);
}
TEST_ASSERT(tc.sb); vStreamBufferDelete(test_args.stream_buffer);
TEST_ASSERT(tc.end_test); vSemaphoreDelete(test_args.done_sem);
tc.send_fail = false;
tc.receive_fail = false;
tc.produce_isr = false;
result = xTaskCreatePinnedToCore(producer_task, "sender", 4096, &tc, UNITY_FREERTOS_PRIORITY + 2, NULL, 0);
TEST_ASSERT(result == pdTRUE);
result = xTaskCreatePinnedToCore(receiver_task, "receiver", 4096, &tc, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
TEST_ASSERT(result == pdTRUE);
result = xSemaphoreTake(tc.end_test, 2000);
TEST_ASSERT(result == pdTRUE);
vTaskDelay(1);
TEST_ASSERT(tc.send_fail == false);
TEST_ASSERT(tc.receive_fail == false);
vStreamBufferDelete(tc.sb);
vSemaphoreDelete(tc.end_test);
} }