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: // TODO:
} }
@ -47,13 +47,14 @@ int main(int argc, char *argv[])
## 1.2. 目录结构 ## 1.2. 目录结构
&emsp;&emsp;所有测试代码位于<test>目录下,<test>下的目录结构保持和<SDK>一致表示对应sdk代码模块的测试代码 &emsp;&emsp;所有测试代码位于< test >目录下,< test >下的目录结构保持和< SDK >一致表示对应sdk代码模块的测试代码
如果是芯片平台的test目录需要区分板载测试代码和x86 Linux系统的测试代码如下 如果是芯片平台的test目录需要区分板载测试代码和x86 Linux系统的测试代码如下
``` ```
└── hal └── hal
├── CMakeLists.txt ├── CMakeLists.txt
├── mainTest.cpp ├── mainTest.cpp
├── src // 芯片平台的测试代码 ├── src // 芯片平台的测试代码;
└── src_mock // Linux x86测试代码 需要对板载接口打桩进行测试; ├── 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 #ifndef LINUX_API_MOCK_H
#define LINUX_API_MOCK_H #define LINUX_API_MOCK_H
#include <gmock/gmock.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 "LinuxApiMock.h"
#include "ILog.h" #include "ILog.h"
#include "LinuxTestImpl.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), Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&openFd))); ReturnPointee(&openFd)));
EXPECT_CALL(*mock.get(), fx_tcgetattr(_, _)) EXPECT_CALL(*mock.get(), fx_tcgetattr(_, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), .WillRepeatedly(
WithArgs<0, 1>(Invoke(api_tcgetattr)), DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1>(Invoke(api_tcgetattr)),
ReturnPointee(&resultTcgetattr))); Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&resultTcgetattr)));
EXPECT_CALL(*mock.get(), fx_tcsetattr(_, _, _)) EXPECT_CALL(*mock.get(), fx_tcsetattr(_, _, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), .WillRepeatedly(
WithArgs<0, 1, 2>(Invoke(api_tcsetattr)), DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2>(Invoke(api_tcsetattr)),
ReturnPointee(&resultTcsetattr))); Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&resultTcsetattr)));
EXPECT_CALL(*mock.get(), fx_write(_, _, _)) EXPECT_CALL(*mock.get(), fx_write(_, _, _))
.WillRepeatedly(DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), .WillRepeatedly(
WithArgs<0, 1, 2>(Invoke(api_write)), DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2>(Invoke(api_write)),
ReturnPointee(&writeLength))); Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
ReturnPointee(&writeLength)));
} }
void LinuxTestImpl::Init() {} void LinuxTestImpl::Init() {}
void LinuxTestImpl::UnInit() void LinuxTestImpl::UnInit()

View File

@ -47,7 +47,7 @@ public:
std::shared_ptr<LinuxApiMock> test = mLinuxTest; std::shared_ptr<LinuxApiMock> test = mLinuxTest;
LinuxApiMock::GetInstance(&test); LinuxApiMock::GetInstance(&test);
LinuxApiMock::GetInstance()->Init(); LinuxApiMock::GetInstance()->Init();
// UartDeviceDefaultInit(mLinuxTest, gUartDevice); RegisterUartDevice(mLinuxTest, gUartDevice);
} }
virtual void TearDown() virtual void TearDown()
{ {
@ -60,18 +60,90 @@ public:
public: public:
std::shared_ptr<LinuxTest> mLinuxTest; std::shared_ptr<LinuxTest> mLinuxTest;
}; };
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.Demo // ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_EXAMPLE_Demo
TEST_F(UartDeviceMockTest, Demo) TEST_F(UartDeviceMockTest, UNIT_UartDevice_EXAMPLE_Demo)
{ {
void *object = CreateUartDevice(gUartDevice); void *object = CreateUartDevice(gUartDevice);
IUartOpen(object); 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); // IUartRecv(object, nullptr, 0, 0);
// IUartTcflush(object); // IUartTcflush(object);
IUartDeviceFree(object); IUartDeviceFree(object);
} }
// ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.Test // ../output_files/test/bin/UartDeviceTest --gtest_filter=UartDeviceMockTest.UNIT_UartDevice_AUTO_ParameterEarror
TEST_F(UartDeviceMockTest, Test) /**
* @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) { auto openThread = [](void) {
LogInfo("===========openThread \n"); LogInfo("===========openThread \n");
@ -84,9 +156,5 @@ TEST_F(UartDeviceMockTest, Test)
std::thread test2 = std::thread(openThread); std::thread test2 = std::thread(openThread);
test2.detach(); test2.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 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 } // namespace UartDeviceMockTest

View File

@ -16,6 +16,7 @@
#define UART_DEVICE_TEST_TOOL_H #define UART_DEVICE_TEST_TOOL_H
#include "LinuxApiMock.h" #include "LinuxApiMock.h"
#include "UartDevice.h" #include "UartDevice.h"
#include <map>
class UartDeviceTestTool class UartDeviceTestTool
{ {
public: public:
@ -25,7 +26,19 @@ public:
* @brief Enable the UartDevice module to run and debug on Ubuntu * @brief Enable the UartDevice module to run and debug on Ubuntu
* *
* @param mock * @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 #endif

View File

@ -14,16 +14,33 @@
*/ */
#include "UartDeviceTestTool.h" #include "UartDeviceTestTool.h"
#include "ILog.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 TCGETATTR_SUCCEED = 0;
constexpr int TCSETATTR_SUCCEED = 0; constexpr int TCSETATTR_SUCCEED = 0;
int uartFd = mock->GetHandleForMock(); int uartFd = mock->GetHandleForMock();
LogInfo("uartFd = %d\n", uartFd); LogInfo("uartFd = %d\n", uartFd);
EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, ::testing::_)) EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, _)).WillRepeatedly(DoAll((Return(uartFd))));
.WillRepeatedly(::testing::DoAll((::testing::Return(uartFd)))); EXPECT_CALL(*mock.get(), fx_tcgetattr(uartFd, _)).WillRepeatedly(DoAll(Return(TCGETATTR_SUCCEED)));
EXPECT_CALL(*mock.get(), fx_tcgetattr(uartFd, ::testing::_)) EXPECT_CALL(*mock.get(), fx_tcsetattr(uartFd, _, _)).WillRepeatedly(DoAll(Return(TCSETATTR_SUCCEED)));
.WillRepeatedly(::testing::DoAll(::testing::Return(TCGETATTR_SUCCEED))); EXPECT_CALL(*mock.get(), fx_write(uartFd, _, _))
EXPECT_CALL(*mock.get(), fx_tcsetattr(uartFd, ::testing::_, ::testing::_)) .WillRepeatedly(DoAll(SaveArg<2>(&WRITE_COUNT), ReturnPointee(&WRITE_COUNT)));
.WillRepeatedly(::testing::DoAll(::testing::Return(TCSETATTR_SUCCEED))); 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> #include <unistd.h>
int fx_system(const char *command) { return system(command); } int fx_system(const char *command) { return system(command); }
int fx_open(const char *pathname, int flags) int fx_open(const char *pathname, int flags) { return open(pathname, flags); }
{
// printf("ssssssssssssssssssssssssssssssss\n");
return open(pathname, flags);
}
int fx_tcgetattr(int fd, struct termios *termios_p) { return tcgetattr(fd, termios_p); } 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) 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) const size_t UartDeviceImpl::UartSend(const char *buff, const size_t &buffLength)
{ {
constexpr int SEND_FAILED = -1; 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) { if (mFd <= 0) {
LogError("open uart failed.\n"); LogError("open uart failed.\n");
return SEND_FAILED; return SEND_FAILED;
} }
// TODO: what if write return less then buffLength? size_t writeTotal = 0;
len = write(mFd, buff, buffLength); while (writeTotal < buffLength) {
LogInfo("len = %d\n", len); writeLength = fx_write(mFd, buff, buffLength - writeTotal);
if (len == buffLength) { writeTotal += writeLength;
return len; }
if (writeTotal == buffLength) {
return writeTotal;
} }
tcflush(mFd, TCOFLUSH); tcflush(mFd, TCOFLUSH);
return len; return writeTotal;
} }
const size_t UartDeviceImpl::UartRecv(char *buff, const size_t &buffLength, const unsigned int &timeOutMs, const size_t UartDeviceImpl::UartRecv(char *buff, const size_t &buffLength, const unsigned int &timeOutMs,
const unsigned int delayRead) const unsigned int delayRead)
@ -243,8 +249,13 @@ static void UartImpllFree(void *ptr)
LogError("Unknow ptr.\n"); LogError("Unknow ptr.\n");
} }
} }
// static const char *test = "zhanqu";
UartDevice *NewUartDeviceImpl(const UartInfo &uartInfo) 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"); LogInfo("Create the uart device object.\n");
UartDeviceImpl_S *impl = (UartDeviceImpl_S *)malloc(sizeof(UartDeviceImpl_S)); UartDeviceImpl_S *impl = (UartDeviceImpl_S *)malloc(sizeof(UartDeviceImpl_S));
UartDeviceImpl_S tmp; UartDeviceImpl_S tmp;