added seperate cmake project for utest
this project uses a fake rtos, and compiles for native test this is to test some lib seperate form the rest of the system
This commit is contained in:
1
tests/native/.gitignore
vendored
Normal file
1
tests/native/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build/
|
||||
26
tests/native/.vscode/launch.json
vendored
Normal file
26
tests/native/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [ {
|
||||
"name": "Debug CLS_Master_Test",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/CLS_Master_Unity",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
//"preLaunchTask": "build" // If you have a build task setup
|
||||
}]
|
||||
}
|
||||
34
tests/native/CMakeLists.txt
Normal file
34
tests/native/CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# set the project name
|
||||
project(CLS_Master_Unity)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME})
|
||||
target_sources(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
tests.c
|
||||
mock_os/mock_os.c
|
||||
../lib/Unity/src/unity.c
|
||||
)
|
||||
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
./
|
||||
../lib/Unity/src
|
||||
)
|
||||
|
||||
include_directories(mock_os)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/nanopb/extra)
|
||||
find_package(Nanopb REQUIRED)
|
||||
include_directories(${NANOPB_INCLUDE_DIRS})
|
||||
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH proto ../../proto/firmware.proto)
|
||||
add_library(PROTOS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||
target_include_directories(PROTOS PUBLIC ${NANOPB_INCLUDE_DIRS} ${PROJECT_BINARY_DIR})
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
|
||||
|
||||
add_subdirectory(../../Application/Tasks Tasks)
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tasks)
|
||||
107
tests/native/mock_os/cmsis_os2.h
Normal file
107
tests/native/mock_os/cmsis_os2.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "stdint.h"
|
||||
|
||||
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
|
||||
|
||||
/// Status code values returned by CMSIS-RTOS functions.
|
||||
typedef enum {
|
||||
osOK = 0, ///< Operation completed successfully.
|
||||
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
|
||||
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
|
||||
osErrorResource = -3, ///< Resource not available.
|
||||
osErrorParameter = -4, ///< Parameter error.
|
||||
osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
|
||||
osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
|
||||
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osStatus_t;
|
||||
|
||||
|
||||
/// Priority values.
|
||||
typedef enum {
|
||||
osPriorityNone = 0, ///< No priority (not initialized).
|
||||
osPriorityIdle = 1, ///< Reserved for Idle thread.
|
||||
osPriorityLow = 8, ///< Priority: low
|
||||
osPriorityLow1 = 8+1, ///< Priority: low + 1
|
||||
osPriorityLow2 = 8+2, ///< Priority: low + 2
|
||||
osPriorityLow3 = 8+3, ///< Priority: low + 3
|
||||
osPriorityLow4 = 8+4, ///< Priority: low + 4
|
||||
osPriorityLow5 = 8+5, ///< Priority: low + 5
|
||||
osPriorityLow6 = 8+6, ///< Priority: low + 6
|
||||
osPriorityLow7 = 8+7, ///< Priority: low + 7
|
||||
osPriorityBelowNormal = 16, ///< Priority: below normal
|
||||
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
|
||||
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
|
||||
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
|
||||
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
|
||||
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
|
||||
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
|
||||
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
|
||||
osPriorityNormal = 24, ///< Priority: normal
|
||||
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
|
||||
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
|
||||
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
|
||||
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
|
||||
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
|
||||
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
|
||||
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
|
||||
osPriorityAboveNormal = 32, ///< Priority: above normal
|
||||
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
|
||||
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
|
||||
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
|
||||
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
|
||||
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
|
||||
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
|
||||
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
|
||||
osPriorityHigh = 40, ///< Priority: high
|
||||
osPriorityHigh1 = 40+1, ///< Priority: high + 1
|
||||
osPriorityHigh2 = 40+2, ///< Priority: high + 2
|
||||
osPriorityHigh3 = 40+3, ///< Priority: high + 3
|
||||
osPriorityHigh4 = 40+4, ///< Priority: high + 4
|
||||
osPriorityHigh5 = 40+5, ///< Priority: high + 5
|
||||
osPriorityHigh6 = 40+6, ///< Priority: high + 6
|
||||
osPriorityHigh7 = 40+7, ///< Priority: high + 7
|
||||
osPriorityRealtime = 48, ///< Priority: realtime
|
||||
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
|
||||
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
|
||||
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
|
||||
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
|
||||
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
|
||||
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
|
||||
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
|
||||
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
|
||||
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
|
||||
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osPriority_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name; ///< name of the thread
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *stack_mem; ///< memory for stack
|
||||
uint32_t stack_size; ///< size of stack
|
||||
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
|
||||
uint32_t reserved; ///< reserved (must be 0)
|
||||
} osThreadAttr_t;
|
||||
|
||||
|
||||
|
||||
/// Attributes structure for message queue.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the message queue
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *mq_mem; ///< memory for data storage
|
||||
uint32_t mq_size; ///< size of provided memory for data storage
|
||||
} osMessageQueueAttr_t;
|
||||
|
||||
|
||||
typedef void (*osThreadFunc_t) (void *argument);
|
||||
typedef void* osMessageQueueId_t;
|
||||
typedef void* osThreadId_t;
|
||||
void Error_Handler();
|
||||
|
||||
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
|
||||
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
|
||||
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
|
||||
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) ;
|
||||
63
tests/native/mock_os/mock_os.c
Normal file
63
tests/native/mock_os/mock_os.c
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
#include "cmsis_os2.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
void Error_Handler() {
|
||||
|
||||
}
|
||||
|
||||
void MX_USB_DEVICE_Init() {
|
||||
|
||||
}
|
||||
|
||||
#define NUM_BUFFERS 10
|
||||
static uint32_t mockQueue[NUM_BUFFERS];
|
||||
static int mockQueueFront = 0;
|
||||
static int mockQueueBack = 0;
|
||||
static bool mockQueueEmpty = true;
|
||||
|
||||
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
|
||||
{
|
||||
return (osThreadId_t)1;
|
||||
}
|
||||
|
||||
osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
|
||||
if (!mockQueueEmpty)
|
||||
{
|
||||
// Remove the message from the queue
|
||||
*(uint32_t *)msg_ptr = mockQueue[mockQueueFront];
|
||||
mockQueueFront = (mockQueueFront + 1) % NUM_BUFFERS;
|
||||
if (mockQueueFront == mockQueueBack)
|
||||
{
|
||||
mockQueueEmpty = true;
|
||||
}
|
||||
return osOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The queue is empty
|
||||
return osErrorResource;
|
||||
}
|
||||
}
|
||||
|
||||
osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
|
||||
if (mockQueueEmpty || mockQueueBack != mockQueueFront)
|
||||
{
|
||||
// Add the message to the queue
|
||||
mockQueue[mockQueueBack] = *(uint32_t *)msg_ptr;
|
||||
mockQueueBack = (mockQueueBack + 1) % NUM_BUFFERS;
|
||||
mockQueueEmpty = false;
|
||||
return osOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The queue is full
|
||||
return osErrorResource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
|
||||
return &mockQueue;
|
||||
}
|
||||
|
||||
1
tests/native/mock_os/usb_device.h
Normal file
1
tests/native/mock_os/usb_device.h
Normal file
@@ -0,0 +1 @@
|
||||
void MX_USB_DEVICE_Init();
|
||||
166
tests/native/tests.c
Normal file
166
tests/native/tests.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "unity.h"
|
||||
|
||||
#include "UsbDataHandler.h"
|
||||
#include "pb_encode.h"
|
||||
#include "firmware.pb.h"
|
||||
|
||||
void setUp() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define START_PACKAES 10
|
||||
#define START_SIZE 123456
|
||||
#define START_CRC 0xffff
|
||||
#define START_DEVICE 0x04
|
||||
#define START_NAME "slave0x04.bin"
|
||||
|
||||
#define PACK_COUTNER 3
|
||||
#define PACK_CRC 0xabcd
|
||||
#define PACK_DEVICE 0x04
|
||||
#define PACK_DATA_SIZE 50
|
||||
|
||||
#define ACK_COUTNER 43
|
||||
#define ACK_CRC 0xabcdef
|
||||
#define ACK_DEVICE 0x9
|
||||
|
||||
#define DONE_CRC 0xffffffff
|
||||
#define DONE_DEVICE 0xf
|
||||
#define DONE_SIZE 1024 * 65
|
||||
|
||||
uint16_t StartCounter = 0;
|
||||
uint16_t PackageCounter = 0;
|
||||
uint16_t AckCounter = 0;
|
||||
uint16_t DoneCounter = 0;
|
||||
|
||||
|
||||
void transmit_package(uint16_t id, const pb_msgdesc_t *fields , const void* msg){
|
||||
UsbDataPacket buffer = {0};
|
||||
buffer.head.type = id;
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer(buffer.data, sizeof(buffer.data));
|
||||
pb_encode(&ostream, fields, msg);
|
||||
buffer.head.length= ostream.bytes_written;
|
||||
|
||||
buffer.head.check = UsbDataPacket_head_sum(&buffer);
|
||||
|
||||
UsbDataHandler_RxCallback((uint8_t*)(&buffer), buffer.head.length+sizeof(UsbDataPacketHead));
|
||||
}
|
||||
|
||||
void test_UsbDataHandler(void) {
|
||||
// Set up the module
|
||||
UsbDataHandler_Start();
|
||||
|
||||
// Call the runner with no messages this should do nothing
|
||||
UsbDataHandler_Runner();
|
||||
|
||||
FirmwareStart start ={
|
||||
.name=START_NAME,
|
||||
.packages=START_PACKAES,
|
||||
.size=START_SIZE,
|
||||
.crc_fw=START_CRC,
|
||||
.device_id=START_DEVICE,
|
||||
};
|
||||
transmit_package(0xf01, FirmwareStart_fields, &start);
|
||||
|
||||
// Call the runner with start message in the queue
|
||||
UsbDataHandler_Runner();
|
||||
TEST_ASSERT_EQUAL(StartCounter,1);
|
||||
|
||||
|
||||
//Put 2 packages in the buffer an parse them
|
||||
transmit_package(0xf01, FirmwareStart_fields, &start);
|
||||
transmit_package(0xf01, FirmwareStart_fields, &start);
|
||||
UsbDataHandler_Runner();
|
||||
UsbDataHandler_Runner();
|
||||
TEST_ASSERT_EQUAL(StartCounter,3);
|
||||
|
||||
|
||||
|
||||
FirmwarePackage pack = {
|
||||
.counter =PACK_COUTNER ,
|
||||
.crc_pac = PACK_CRC,
|
||||
.device_id= PACK_DEVICE,
|
||||
.data={.size = PACK_DATA_SIZE,
|
||||
.bytes={0}
|
||||
},
|
||||
};
|
||||
transmit_package(0xf02, FirmwarePackage_fields, &pack);
|
||||
UsbDataHandler_Runner();
|
||||
TEST_ASSERT_EQUAL(PackageCounter,1);
|
||||
|
||||
FirmwarePackageAck ack = {
|
||||
.ack =true,
|
||||
.counter = ACK_COUTNER,
|
||||
.crc_pac = ACK_CRC,
|
||||
.device_id = ACK_DEVICE,
|
||||
};
|
||||
transmit_package(0xf04, FirmwarePackageAck_fields, &ack);
|
||||
UsbDataHandler_Runner();
|
||||
TEST_ASSERT_EQUAL(PackageCounter,1);
|
||||
|
||||
|
||||
FirmwareDone done = {
|
||||
.crc_fw = DONE_CRC,
|
||||
.device_id = DONE_DEVICE,
|
||||
.size = DONE_SIZE,
|
||||
};
|
||||
|
||||
transmit_package(0xf03, FirmwareDone_fields, &done);
|
||||
UsbDataHandler_Runner();
|
||||
TEST_ASSERT_EQUAL(DoneCounter,1);
|
||||
|
||||
}
|
||||
|
||||
void tearDown() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_UsbDataHandler);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
|
||||
void DataClbk_FirmwareStart(void * msg, uint32_t length) {
|
||||
FirmwareStart start;
|
||||
memcpy(&start,msg,sizeof(start));
|
||||
TEST_ASSERT_EQUAL(START_SIZE, start.size);
|
||||
TEST_ASSERT_EQUAL(START_PACKAES, start.packages);
|
||||
TEST_ASSERT_EQUAL(START_CRC, start.crc_fw);
|
||||
TEST_ASSERT_EQUAL(START_DEVICE, start.device_id);
|
||||
TEST_ASSERT_EQUAL_STRING(START_NAME,start.name);
|
||||
StartCounter++;
|
||||
}
|
||||
void DataClbk_FirmwarePackage(void * msg, uint32_t length) {
|
||||
FirmwarePackage pack;
|
||||
memcpy(&pack,msg,sizeof(pack));
|
||||
TEST_ASSERT_EQUAL(FirmwarePackage_size, length);
|
||||
TEST_ASSERT_EQUAL(PACK_COUTNER, pack.counter);
|
||||
TEST_ASSERT_EQUAL(PACK_CRC, pack.crc_pac);
|
||||
TEST_ASSERT_EQUAL(PACK_DEVICE, pack.device_id);
|
||||
TEST_ASSERT_EQUAL(PACK_DATA_SIZE, pack.data.size);
|
||||
PackageCounter++;
|
||||
}
|
||||
void DataClbk_FirmwarePackageAck(void * msg, uint32_t length) {
|
||||
FirmwarePackageAck ack;
|
||||
memcpy(&ack,msg,sizeof(ack));
|
||||
TEST_ASSERT_EQUAL(FirmwarePackageAck_size, length);
|
||||
TEST_ASSERT(ack.ack);
|
||||
TEST_ASSERT_EQUAL(ACK_COUTNER, ack.counter);
|
||||
TEST_ASSERT_EQUAL(ACK_CRC, ack.crc_pac);
|
||||
TEST_ASSERT_EQUAL(ACK_DEVICE, ack.device_id);
|
||||
|
||||
AckCounter++;
|
||||
}
|
||||
void DataClbk_FirmwareDone(void * msg, uint32_t length) {
|
||||
FirmwareDone done;
|
||||
memcpy(&done,msg,sizeof(done));
|
||||
TEST_ASSERT_EQUAL(FirmwareDone_size, length);
|
||||
TEST_ASSERT_EQUAL(DONE_CRC,done.crc_fw);
|
||||
TEST_ASSERT_EQUAL(DONE_DEVICE,done.device_id);
|
||||
TEST_ASSERT_EQUAL(DONE_SIZE,done.size);
|
||||
DoneCounter++;
|
||||
}
|
||||
Reference in New Issue
Block a user