Improve:Optimize the write resend logic when sending.

This commit is contained in:
fancy 2024-01-28 17:47:58 -08:00
parent 328b12abc9
commit 06a0edbfd0
9 changed files with 183 additions and 46 deletions

View File

@ -12,7 +12,7 @@
示例:
```
TEST(SharedDataTest, UNIT_SharedData_DEME_Demo7)
TEST(SharedDataTest, UNIT_SharedData_EXAMPLE_Demo7)
{
// TODO:
}
@ -47,13 +47,14 @@ int main(int argc, char *argv[])
## 1.2. 目录结构
&emsp;&emsp;所有测试代码位于<test>目录下,<test>下的目录结构保持和<SDK>一致表示对应sdk代码模块的测试代码
&emsp;&emsp;所有测试代码位于< test >目录下,< test >下的目录结构保持和< SDK >一致表示对应sdk代码模块的测试代码
如果是芯片平台的test目录需要区分板载测试代码和x86 Linux系统的测试代码如下
```
└── hal
├── CMakeLists.txt
├── mainTest.cpp
├── src // 芯片平台的测试代码
└── src_mock // Linux x86测试代码 需要对板载接口打桩进行测试;
├── src // 芯片平台的测试代码;
├── src_mock // Linux x86测试代码 需要对板载接口打桩进行测试;
└── tool // 该模块需要对外复用的测试代码;
```

View File

@ -1,3 +1,17 @@
/*
* Copyright (c) 2023 Fancy Code.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LINUX_API_MOCK_H
#define LINUX_API_MOCK_H
#include <gmock/gmock.h>

View File

@ -1,3 +1,17 @@
/*
* Copyright (c) 2023 Fancy Code.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LinuxApiMock.h"
#include "ILog.h"
#include "LinuxTestImpl.h"

View File

@ -52,20 +52,23 @@ void LinuxTestImpl::ApiInit(std::shared_ptr<LinuxTest> &mock)
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&openFd)));
EXPECT_CALL(*mock.get(), fx_tcgetattr(_, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1>(Invoke(api_tcgetattr)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
ReturnPointee(&resultTcgetattr)));
.WillRepeatedly(
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1>(Invoke(api_tcgetattr)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&resultTcgetattr)));
EXPECT_CALL(*mock.get(), fx_tcsetattr(_, _, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1, 2>(Invoke(api_tcsetattr)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
ReturnPointee(&resultTcsetattr)));
.WillRepeatedly(
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1, 2>(Invoke(api_tcsetattr)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&resultTcsetattr)));
EXPECT_CALL(*mock.get(), fx_write(_, _, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1, 2>(Invoke(api_write)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
ReturnPointee(&writeLength)));
.WillRepeatedly(
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
WithArgs<0, 1, 2>(Invoke(api_write)),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&writeLength)));
}
void LinuxTestImpl::Init() {}
void LinuxTestImpl::UnInit()

View File

@ -47,7 +47,7 @@ public:
std::shared_ptr<LinuxApiMock> test = mLinuxTest;
LinuxApiMock::GetInstance(&test);
LinuxApiMock::GetInstance()->Init();
// UartDeviceDefaultInit(mLinuxTest, gUartDevice);
RegisterUartDevice(mLinuxTest, gUartDevice);
}
virtual void TearDown()
{
@ -60,18 +60,90 @@ public:
public:
std::shared_ptr<LinuxTest> mLinuxTest;
};
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.Demo
TEST_F(UartDeviceMockTest, Demo)
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_EXAMPLE_Demo
TEST_F(UartDeviceMockTest, UNIT_UartDevice_EXAMPLE_Demo)
{
void *object = CreateUartDevice(gUartDevice);
IUartOpen(object);
// IUartSend(object, nullptr, 0);
const char *SEND_BUF = "TEST";
ssize_t sendResult = IUartSend(object, SEND_BUF, strlen(SEND_BUF));
EXPECT_EQ(sendResult, static_cast<ssize_t>(strlen(SEND_BUF)));
// IUartRecv(object, nullptr, 0, 0);
// IUartTcflush(object);
IUartDeviceFree(object);
}
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.Test
TEST_F(UartDeviceMockTest, Test)
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_AUTO_ParameterEarror
/**
* @brief Construct a new test f object
* Is the interface accurate when testing parameter errors in this test case.
*/
TEST_F(UartDeviceMockTest, UNIT_UartDevice_AUTO_ParameterEarror)
{
char *deviceName = nullptr;
static uart_info uartDevice = {
deviceName,
1152000,
'N',
8,
1,
'N',
};
RegisterUartDevice(mLinuxTest, uartDevice);
void *object = CreateUartDevice(uartDevice);
IUartOpen(object);
IUartDeviceFree(object);
EXPECT_EQ(object, nullptr);
}
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_AUTO_ParameterEarror2
/**
* @brief Construct a new test f object
* Is the interface accurate when testing parameter errors in this test case.
*/
TEST_F(UartDeviceMockTest, UNIT_UartDevice_AUTO_ParameterEarror2)
{
// TODO:
// const char *SEND_BUF = "TEST";
// char *deviceName = (char *)malloc(strlen(SEND_BUF) + 1);
// memset(deviceName, 0, strlen(SEND_BUF) + 1);
// static uart_info uartDevice = {
// "deviceName",
// 1152000,
// 'N',
// 8,
// 1,
// 'N',
// };
// RegisterUartDevice(mLinuxTest, uartDevice);
// void *object = CreateUartDevice(uartDevice);
// IUartOpen(object);
// IUartDeviceFree(object);
// free(deviceName);
// deviceName = nullptr;
}
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_AUTO_WriteAllData
/**
* @brief Construct a new test f object
* This test case verifies whether the application will call the write function twice until all data is written when the
* write function does not write the length of the data.
*/
TEST_F(UartDeviceMockTest, UNIT_UartDevice_AUTO_WriteAllData)
{
const char *SEND_BUF = "TEST";
constexpr ssize_t SEND_LENGTH = 1; // less than static_cast<ssize_t>(strlen(SEND_BUF))
SetSendApiOnce(mLinuxTest, gUartDevice, SEND_LENGTH);
void *object = CreateUartDevice(gUartDevice);
IUartOpen(object);
ssize_t sendResult = IUartSend(object, SEND_BUF, strlen(SEND_BUF));
EXPECT_EQ(sendResult, static_cast<ssize_t>(strlen(SEND_BUF)));
IUartDeviceFree(object);
}
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_EXAMPLE_MultiThreadTest
/**
* @brief Construct a new test f object
* This test case tests whether the correct return value can be obtained when simulating multi-threaded operations on
* the interface.
*/
TEST_F(UartDeviceMockTest, UNIT_UartDevice_AUTO_MultiThreadTest)
{
auto openThread = [](void) {
LogInfo("===========openThread \n");
@ -84,9 +156,5 @@ TEST_F(UartDeviceMockTest, Test)
std::thread test2 = std::thread(openThread);
test2.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// std::thread(openThread2);
// IUartSend(object, nullptr, 0);
// IUartRecv(object, nullptr, 0, 0);
// IUartTcflush(object);
}
} // namespace UartDeviceMockTest

View File

@ -16,6 +16,7 @@
#define UART_DEVICE_TEST_TOOL_H
#include "LinuxApiMock.h"
#include "UartDevice.h"
#include <map>
class UartDeviceTestTool
{
public:
@ -25,7 +26,19 @@ public:
* @brief Enable the UartDevice module to run and debug on Ubuntu
*
* @param mock
* @param uart
*/
void UartDeviceDefaultInit(std::shared_ptr<LinuxTest> &mock, const uart_info &uart);
void RegisterUartDevice(std::shared_ptr<LinuxTest> &mock, const uart_info &uart);
/**
* @brief Set the Send Api object
*
* @param mock
* @param uart
* @param length
*/
void SetSendApiOnce(std::shared_ptr<LinuxTest> &mock, const uart_info &uart, const ssize_t &length);
private:
std::map<const char *, int> mDeviceMap;
};
#endif

View File

@ -14,16 +14,33 @@
*/
#include "UartDeviceTestTool.h"
#include "ILog.h"
void UartDeviceTestTool::UartDeviceDefaultInit(std::shared_ptr<LinuxTest> &mock, const uart_info &uart)
static size_t WRITE_COUNT = -1;
void UartDeviceTestTool::RegisterUartDevice(std::shared_ptr<LinuxTest> &mock, const uart_info &uart)
{
if (nullptr == uart.mDevice) {
LogError("Parament error, nullptr == uartInfo.mDevice\n");
return;
}
constexpr int TCGETATTR_SUCCEED = 0;
constexpr int TCSETATTR_SUCCEED = 0;
int uartFd = mock->GetHandleForMock();
LogInfo("uartFd = %d\n", uartFd);
EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, ::testing::_))
.WillRepeatedly(::testing::DoAll((::testing::Return(uartFd))));
EXPECT_CALL(*mock.get(), fx_tcgetattr(uartFd, ::testing::_))
.WillRepeatedly(::testing::DoAll(::testing::Return(TCGETATTR_SUCCEED)));
EXPECT_CALL(*mock.get(), fx_tcsetattr(uartFd, ::testing::_, ::testing::_))
.WillRepeatedly(::testing::DoAll(::testing::Return(TCSETATTR_SUCCEED)));
EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, _)).WillRepeatedly(DoAll((Return(uartFd))));
EXPECT_CALL(*mock.get(), fx_tcgetattr(uartFd, _)).WillRepeatedly(DoAll(Return(TCGETATTR_SUCCEED)));
EXPECT_CALL(*mock.get(), fx_tcsetattr(uartFd, _, _)).WillRepeatedly(DoAll(Return(TCSETATTR_SUCCEED)));
EXPECT_CALL(*mock.get(), fx_write(uartFd, _, _))
.WillRepeatedly(DoAll(SaveArg<2>(&WRITE_COUNT), ReturnPointee(&WRITE_COUNT)));
mDeviceMap[uart.mDevice] = uartFd;
}
void UartDeviceTestTool::SetSendApiOnce(std::shared_ptr<LinuxTest> &mock, const uart_info &uart, const ssize_t &length)
{
std::map<const char *, int>::iterator iter;
iter = mDeviceMap.find(uart.mDevice);
if (iter == mDeviceMap.end()) {
LogError("Can't found the uart device[%s].\n", uart.mDevice);
return;
}
EXPECT_CALL(*mock.get(), fx_write(mDeviceMap[uart.mDevice], _, _))
.WillOnce(DoAll(Return(length)))
.WillRepeatedly(DoAll(SaveArg<2>(&WRITE_COUNT), ReturnPointee(&WRITE_COUNT)));
}

View File

@ -23,11 +23,7 @@
#include <unistd.h>
int fx_system(const char *command) { return system(command); }
int fx_open(const char *pathname, int flags)
{
// printf("ssssssssssssssssssssssssssssssss\n");
return open(pathname, flags);
}
int fx_open(const char *pathname, int flags) { return open(pathname, flags); }
int fx_tcgetattr(int fd, struct termios *termios_p) { return tcgetattr(fd, termios_p); }
int fx_tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
{

View File

@ -40,19 +40,25 @@ const StatusCode UartDeviceImpl::UartOpen(void)
const size_t UartDeviceImpl::UartSend(const char *buff, const size_t &buffLength)
{
constexpr int SEND_FAILED = -1;
size_t len = 0;
size_t writeLength = 0;
if (nullptr == buff) {
LogError("data buff is nullptr.\n");
return SEND_FAILED;
}
if (mFd <= 0) {
LogError("open uart failed.\n");
return SEND_FAILED;
}
// TODO: what if write return less then buffLength?
len = write(mFd, buff, buffLength);
LogInfo("len = %d\n", len);
if (len == buffLength) {
return len;
size_t writeTotal = 0;
while (writeTotal < buffLength) {
writeLength = fx_write(mFd, buff, buffLength - writeTotal);
writeTotal += writeLength;
}
if (writeTotal == buffLength) {
return writeTotal;
}
tcflush(mFd, TCOFLUSH);
return len;
return writeTotal;
}
const size_t UartDeviceImpl::UartRecv(char *buff, const size_t &buffLength, const unsigned int &timeOutMs,
const unsigned int delayRead)
@ -243,8 +249,13 @@ static void UartImpllFree(void *ptr)
LogError("Unknow ptr.\n");
}
}
// static const char *test = "zhanqu";
UartDevice *NewUartDeviceImpl(const UartInfo &uartInfo)
{
if (nullptr == uartInfo.mDevice) {
LogError("Parament error, nullptr == uartInfo.mDevice\n");
return nullptr;
}
LogInfo("Create the uart device object.\n");
UartDeviceImpl_S *impl = (UartDeviceImpl_S *)malloc(sizeof(UartDeviceImpl_S));
UartDeviceImpl_S tmp;