/* * packetusart_unittest.cpp * * Created on: Dec 2, 2019 * Author: abody */ #include #include #include #include #include #include #include #include static inline uint32_t RoundUpTo4(uint32_t inp) { return (inp + 3) & 0xfffc; } DMA_TypeDef* DMA1 __attribute__((weak)); DMA_TypeDef* DMA2 __attribute__((weak)); static DMA_TypeDef fakeDma1, fakeDma2; static CRC_TypeDef fakeCrc; static USART_TypeDef fakeUsart; static struct usartstatus_t usartStatus; static struct crcstatus_t crcStatus; uint8_t testData[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //static uint32_t expected_stream; //static uint32_t expected_srcaddress; //static uint32_t expected_dstaddress; //static uint32_t expected_length; //static void *expected_customptr; //static uint8_t expected_success; //static struct usartstatus_t * expectedUsartStatus; static uint32_t expectedStreams[2] = { 0,7 }; struct crcstatus_t *expectedCrcStatus; struct crcslot_t *expectedCrcSlotListItem; struct crctask_t *expectedTasks; uint8_t expectedTaskCount; uint32_t expectedCrcLength; uint32_t expectedLength; void* expectedCrcEnqueueAddress; void *expectedTransmitBuffer; static uint32_t expectedStream; uint32_t expectedSrcAddress; uint32_t expectedDstAddress; uint32_t expectedDirection; uint32_t fakePacketReceivedCallbackParam; // this isn't a real mov but we use the mockinginfrastructure // to automate administration (call count, etc) DEFINE_MOCK(FakePacketReceivedCallback, mock, void* userParam, struct usart_buffer_t *buffer) { EXPECT_EQ((void*)&fakePacketReceivedCallbackParam, userParam); LEAVE_MOCK } DEFINE_MOCK(Dma_Init, mock, struct dmainfo_t* dmaInfo, DMA_TypeDef *dma, uint32_t stream) { Dma_Init__(dmaInfo, dma, stream); LEAVE_MOCK } DEFINE_MOCK(Crc_AttachTasks, mock, struct crcstatus_t *status, struct crcslot_t *slot, struct crctask_t *tasks, uint8_t taskCount) { EXPECT_EQ(status, expectedCrcStatus); EXPECT_EQ(slot, expectedCrcSlotListItem); EXPECT_EQ(tasks, expectedTasks); EXPECT_EQ(taskCount, expectedTaskCount); Crc_AttachTasks__(status, slot, tasks, taskCount); LEAVE_MOCK } DEFINE_MOCK(LL_DMA_EnableIT_TC, init, DMA_TypeDef *dma, uint32_t stream) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStreams[MOCK_VAR(LL_DMA_EnableIT_TC, init, callcount)-1]); LEAVE_MOCK } DEFINE_MOCK(LL_DMA_EnableIT_TE, init, DMA_TypeDef *dma, uint32_t stream) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStreams[MOCK_VAR(LL_DMA_EnableIT_TE, init, callcount)-1]); LEAVE_MOCK } DEFINE_MOCK_RET(uint32_t, LL_USART_DMA_GetRegAddr, mock, USART_TypeDef *usart) { RETURN_MOCK_PREDEF(LL_USART_DMA_GetRegAddr, mock) } DEFINE_MOCK(LL_DMA_ConfigAddresses, mock, DMA_TypeDef* dma, uint32_t stream, uint32_t srcAddress, uint32_t dstAddress, uint32_t direction) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStream); EXPECT_EQ(srcAddress, expectedSrcAddress); EXPECT_EQ(dstAddress, expectedDstAddress); EXPECT_EQ(direction, expectedDirection); LEAVE_MOCK } DEFINE_MOCK(LL_DMA_SetDataLength, mock, DMA_TypeDef* dma, uint32_t stream, uint32_t length) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStream); EXPECT_EQ(length, expectedLength); LEAVE_MOCK } DEFINE_MOCK_RET(uint32_t, LL_DMA_GetDataLength, mock, DMA_TypeDef* dma, uint32_t stream) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStream); RETURN_MOCK_PREDEF(LL_DMA_GetDataLength, mock) } DEFINE_MOCK(LL_DMA_EnableStream, mock, DMA_TypeDef* dma, uint32_t stream) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStream); LEAVE_MOCK } DEFINE_MOCK(LL_DMA_DisableStream, mock, DMA_TypeDef* dma, uint32_t stream) { EXPECT_EQ(dma, &fakeDma1); EXPECT_EQ(stream, expectedStream); LEAVE_MOCK } DEFINE_MOCK(LL_USART_EnableDMAReq_TX, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_EnableDMAReq_RX, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_EnableIT_IDLE, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_EnableIT_TC, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_DisableIT_TC, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK_RET(uint32_t, LL_USART_IsActiveFlag_IDLE, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); RETURN_MOCK_PREDEF(LL_USART_IsActiveFlag_IDLE, mock) } DEFINE_MOCK_RET(uint32_t, LL_USART_IsActiveFlag_TC, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); RETURN_MOCK_PREDEF(LL_USART_IsActiveFlag_TC, mock) } DEFINE_MOCK(LL_USART_ClearFlag_IDLE, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK; } DEFINE_MOCK_RET(uint32_t, LL_USART_IsEnabledIT_IDLE, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); RETURN_MOCK_PREDEF(LL_USART_IsEnabledIT_IDLE, mock) } DEFINE_MOCK_RET(uint32_t, LL_USART_IsEnabledIT_TC, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); RETURN_MOCK_PREDEF(LL_USART_IsEnabledIT_TC, mock) } DEFINE_MOCK(LL_USART_EnableDirectionTx, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_DisableDirectionTx, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK(LL_USART_ClearFlag_ORE, mock, USART_TypeDef *usart) { EXPECT_EQ(usart, &fakeUsart); LEAVE_MOCK } DEFINE_MOCK_RET(uint8_t, Crc_Enqueue, mock, struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task, void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam) { EXPECT_EQ(expectedCrcLength, len); EXPECT_EQ(expectedCrcEnqueueAddress, address); RETURN_MOCK_PREDEF(Crc_Enqueue, mock); } DEFINE_MOCK_RET(uint8_t, Crc_IsTaskQueued, mock, struct crcslot_t *slot, uint8_t task) { RETURN_MOCK_PREDEF(Crc_IsTaskQueued, mock); } DEFINE_MOCK(Pu_SetupTransmit, mock, USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) { EXPECT_EQ(buffer, expectedTransmitBuffer); EXPECT_EQ(length, expectedLength); LEAVE_MOCK } DEFINE_MOCK_RET(uint8_t, Pu_CheckHeader, proxy, struct usartpacket_t *packet) { RETURN_MOCK(Pu_CheckHeader, proxy, Pu_CheckHeader__(packet)); } DEFINE_MOCK(Pu_SetupReceive, mock, struct usartstatus_t *status) { LEAVE_MOCK } struct PacketUsart : public ::testing::Test { void SetUp() { DMA1 = &fakeDma1; DMA2 = &fakeDma2; memset(&usartStatus, 0x5a, sizeof(usartStatus)); Crc_InitStatus(&crcStatus, &fakeCrc, &fakeDma2, 4); expectedCrcStatus = &crcStatus; expectedCrcSlotListItem = &usartStatus.crcSlot; expectedTasks = usartStatus.crcTasks; expectedTaskCount = 2; } }; ////////////////////////////////////////////////////////////////////////////// TEST_F(PacketUsart, Init) { ACTIVATE_MOCK(Dma_Init, mock); ACTIVATE_MOCK(Crc_AttachTasks, mock); ACTIVATE_MOCK(LL_DMA_EnableIT_TC, init); ACTIVATE_MOCK(LL_DMA_EnableIT_TE, init); ACTIVATE_MOCK(LL_USART_EnableIT_IDLE, mock); Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); EXPECT_EQ(fakeDma1.LIFCR, DMA_LISR_TCIF0 | DMA_LISR_HTIF0 | DMA_LISR_TEIF0 | DMA_LISR_FEIF0 | DMA_LISR_DMEIF0); EXPECT_EQ(fakeDma1.HIFCR, DMA_HISR_TCIF7 | DMA_HISR_HTIF7 | DMA_HISR_TEIF7 | DMA_HISR_FEIF7 | DMA_HISR_DMEIF7); EXPECT_EQ(MOCK_CALLCOUNT(Dma_Init, mock), 2); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableIT_TC, init), 2); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableIT_TE, init), 2); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_IDLE, mock), 1); EXPECT_EQ(usartStatus.usart, &fakeUsart); EXPECT_EQ(usartStatus.txBuffer.usartStatus, &usartStatus); EXPECT_EQ(usartStatus.txBuffer.busy, 0); EXPECT_EQ(usartStatus.txBuffer.error, 0); EXPECT_EQ(usartStatus.txBuffer.requestedLength, 0); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); EXPECT_EQ(usartStatus.rxBuffers[0].requestedLength, 0); EXPECT_EQ(usartStatus.rxBuffers[0].usartStatus, &usartStatus ); EXPECT_EQ(usartStatus.rxBuffers[1].busy, 0); EXPECT_EQ(usartStatus.rxBuffers[1].error, 0); EXPECT_EQ(usartStatus.rxBuffers[1].requestedLength, 0); EXPECT_EQ(usartStatus.rxBuffers[1].usartStatus, &usartStatus ); EXPECT_TRUE(usartStatus.packetReceivedCallback == FakePacketReceivedCallback_mock); EXPECT_EQ(usartStatus.packetReceivedCallbackParam, &fakePacketReceivedCallbackParam); EXPECT_EQ(usartStatus.rxSerial, (uint8_t)-1); EXPECT_EQ(usartStatus.txSerial, 0); EXPECT_EQ(usartStatus.activeRxBuf, 0); EXPECT_EQ(usartStatus.crcStatus, &crcStatus); } TEST_F(PacketUsart, GetTxBuffer) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); EXPECT_EQ(Pu_GetTxBuffer(&usartStatus), (unsigned char*)&usartStatus.txBuffer.packet.payload); } // SetupTransmit should set all engines (DMA, USART) up properly for starting the transmission TEST_F(PacketUsart, SetupTransmit) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); expectedStream = 7; expectedSrcAddress = (uint32_t)testData; expectedDstAddress = (uint32_t)&fakeUsart.DR; expectedDirection = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; expectedLength = sizeof(testData); ACTIVATE_MOCK(LL_DMA_ConfigAddresses, mock); ACTIVATE_MOCK(LL_DMA_SetDataLength , mock); ACTIVATE_MOCK(LL_DMA_EnableStream , mock); ACTIVATE_MOCK(LL_USART_EnableDMAReq_TX, mock); ACTIVATE_MOCK_RV(LL_USART_DMA_GetRegAddr, mock, expectedDstAddress); Pu_SetupTransmit(&fakeUsart, &fakeDma1, 7, testData, sizeof(testData)); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_ConfigAddresses, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_SetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableStream, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableDMAReq_TX, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DMA_GetRegAddr, mock), 1); } // Testing Pu_Post, not waiting for the crc scheduler to start processing our block TEST_F(PacketUsart, Post_copy_nowait) { struct usartpacketheader_t expectedHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); expectedTransmitBuffer = &usartStatus.txBuffer.packet; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 1); Pu_Post(&usartStatus, testData, sizeof(testData), false); EXPECT_EQ(usartStatus.txBuffer.busy, 1); EXPECT_EQ(usartStatus.txBuffer.requestedLength, expectedLength); EXPECT_EQ(memcmp(&usartStatus.txBuffer.packet.header, &expectedHeader, sizeof(expectedHeader)), 0); EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_SetupTransmit, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsTaskQueued, mock), 0); } // Posting with free CRC engine (will execute our block immediately) TEST_F(PacketUsart, Post_copy_wait_nodelay) { expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); expectedTransmitBuffer = &usartStatus.txBuffer.packet; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 0); Pu_Post(&usartStatus, testData, sizeof(testData), true); EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsTaskQueued, mock), 1); } // Posting with with busy CRC engine should block our call TEST_F(PacketUsart, Post_copy_wait_delay) { expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); expectedTransmitBuffer = &usartStatus.txBuffer.packet; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 1); // black magic to test if the function blocks (at least for 100ms) std::promise promiseFinished; auto futureResult = promiseFinished.get_future(); pthread_t th; std::thread t([](std::promise& finished) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); Pu_Post(&usartStatus, testData, sizeof(testData), true);; finished.set_value(true); }, std::ref(promiseFinished)); th = t.native_handle(); t.detach(); EXPECT_EQ(futureResult.wait_for(std::chrono::milliseconds(100)), std::future_status::timeout); Crc_IsTaskQueued_mock_retval = 0; auto waitResult(futureResult.wait_for(std::chrono::milliseconds(100))); EXPECT_NE(waitResult, std::future_status::timeout); if(waitResult == std::future_status::timeout) pthread_cancel(th); } // HandleTxDmaIrq_tc should enable USART TC interrupt and disable DMA stream TEST_F(PacketUsart, HandleTxDmaIrq_tc) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_Post(&usartStatus, testData, sizeof(testData), true); memset(&fakeDma1, 0, sizeof(fakeDma1)); fakeDma1.HISR = DMA_HISR_TCIF7; expectedStream = 7; ACTIVATE_MOCK(LL_USART_EnableIT_TC, mock); ACTIVATE_MOCK(LL_DMA_DisableStream, mock); Pu_HandleTxDmaIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_TC, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); EXPECT_EQ(fakeDma1.HIFCR, DMA_HIFCR_CTCIF7); } // HandleTxDmaIrq_te should enable USART TC interrupt disable DMA stream and set the error flag TEST_F(PacketUsart, HandleTxDmaIrq_te) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_Post(&usartStatus, testData, sizeof(testData), true); memset(&fakeDma1, 0, sizeof(fakeDma1)); fakeDma1.HISR = DMA_HISR_TEIF7; expectedStream = 7; Pu_HandleTxDmaIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_TC, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); EXPECT_EQ(fakeDma1.HIFCR, DMA_HIFCR_CTEIF7); EXPECT_EQ(usartStatus.txBuffer.error, 1); } // HandleUsartIrq_tc should disable USART TC interrupt, pulse TX direction enabled to enforce an idle frame // and mark the tx buffer as free TEST_F(PacketUsart, HandleUsartIrq_tc) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_Post(&usartStatus, testData, sizeof(testData), true); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 0); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); ACTIVATE_MOCK(LL_USART_DisableIT_TC, mock); ACTIVATE_MOCK(LL_USART_EnableDirectionTx, mock); ACTIVATE_MOCK(LL_USART_DisableDirectionTx, mock); Pu_HandleUsartIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DisableIT_TC, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DisableDirectionTx, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableDirectionTx, mock), 1); EXPECT_EQ(usartStatus.txBuffer.busy, 0); } // SetupReceive must set USART and DMA engine up for reception TEST_F(PacketUsart, SetupReceive) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); expectedStream = 0; expectedDstAddress = (uint32_t)&usartStatus.rxBuffers[usartStatus.activeRxBuf].packet; expectedSrcAddress = (uint32_t)&fakeUsart.DR; expectedDirection = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; expectedLength = sizeof(struct usartpacket_t); ACTIVATE_MOCK(LL_DMA_ConfigAddresses, mock); ACTIVATE_MOCK(LL_DMA_SetDataLength , mock); ACTIVATE_MOCK(LL_DMA_EnableStream , mock); ACTIVATE_MOCK(LL_USART_EnableDMAReq_RX, mock); ACTIVATE_MOCK(LL_USART_ClearFlag_ORE, mock); ACTIVATE_MOCK_RV(LL_USART_DMA_GetRegAddr, mock, expectedSrcAddress); Pu_SetupReceive(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_ConfigAddresses, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_SetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableStream, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableDMAReq_RX, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_ORE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DMA_GetRegAddr, mock), 1); } // Test HandleUsartIrq with a received packet having a correct header checksum TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_ok) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); expectedStream = 0; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t)); ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); ACTIVATE_MOCK(LL_DMA_DisableStream, mock); Pu_HandleUsartIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } // Test HandleUsartIrq with a received packet having a incorrect header checksum TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_bad) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); expectedStream = 0; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t)); ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); ACTIVATE_MOCK(LL_DMA_DisableStream, mock); Pu_HandleUsartIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); EXPECT_NE(usartStatus.rxBuffers[0].error, 0); EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); } // Packet reception should continue if the packet is not fully received yet TEST_F(PacketUsart, HandleUsartIrq_idle_tooshort) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); expectedStream = 0; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t) + 1); ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); ACTIVATE_MOCK(LL_DMA_DisableStream, mock); Pu_HandleUsartIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 0); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } // Packet reception should continue if the packet is shorter than the packet header TEST_F(PacketUsart, HandleUsartIrq_idle_tooshortforheadercheck) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); expectedStream = 0; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - 3); ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); ACTIVATE_MOCK(LL_DMA_DisableStream, mock); Pu_HandleUsartIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 0); EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } // Reception DMA engine transfer complete interrupt is the real verification point of the packet // verify that the packet is really checked TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrok) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); memset(&fakeDma1, 0, sizeof(fakeDma1)); memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); expectedStream = 0; expectedCrcEnqueueAddress = &usartStatus.rxBuffers[0].packet; expectedCrcLength = RoundUpTo4(usartStatus.rxBuffers[0].packet.header.payloadLength) + sizeof(struct usartpacketheader_t); fakeDma1.LISR = DMA_LISR_TCIF0; ACTIVATE_MOCK(Pu_CheckHeader, proxy); ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 0); ACTIVATE_MOCK(Pu_SetupReceive, mock); Pu_HandleRxDmaIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_SetupReceive, mock), 1); EXPECT_EQ(fakeDma1.LIFCR, DMA_LIFCR_CTCIF0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } // In case of the header fails on the end of packet reception error flag should be set TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrfail) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); memset(&fakeDma1, 0, sizeof(fakeDma1)); memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); expectedStream = 0; expectedCrcEnqueueAddress = &usartStatus.rxBuffers[0].packet; expectedCrcLength = RoundUpTo4(usartStatus.rxBuffers[0].packet.header.payloadLength) + sizeof(struct usartpacketheader_t); fakeDma1.LISR = DMA_LISR_TCIF0; ACTIVATE_MOCK(Pu_CheckHeader, proxy); ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 0); ACTIVATE_MOCK(Pu_SetupReceive, mock); Pu_HandleRxDmaIrq(&usartStatus); EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 0); EXPECT_EQ(fakeDma1.LIFCR, DMA_LIFCR_CTCIF0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 1); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } // successfull CRC32 check, CRC32 match, callback should be called, busy flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_match) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa55a; MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } // successfull CRC32 check, CRC32 mismatch, callback should be called, // both busy and error flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_mismatch) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa5a5; MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); EXPECT_NE(usartStatus.rxBuffers[0].error, 0); } //failed CRC32 check, callback should be called, // both busy and error flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_failure) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); Pu_SetupReceive(&usartStatus); struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa5a5; MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); EXPECT_NE(usartStatus.rxBuffers[0].error, 0); }