hunting/test/utils/UartDevice/tool/src/UartDeviceTestTool.cpp
2024-06-21 11:07:44 +08:00

145 lines
6.4 KiB
C++

/*
* 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 "UartDeviceTestTool.h"
#include "GtestUsing.h"
#include "ILog.h"
#include "LinuxApiMock.h"
#include "UartDevice.h"
#if defined(__x86_64__)
#include <bits/types/struct_timeval.h>
#endif
#include <chrono>
#include <cstdio>
#include <gmock/gmock-spec-builders.h>
#include <map>
#include <memory>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <thread>
static size_t WRITE_COUNT = -1;
constexpr int INVALID_FD = -1;
int UartDeviceTestTool::RegisterUartDevice(std::shared_ptr<LinuxTest> &mock, const UartInfo &uart)
{
if (nullptr == uart.mDevice) {
LogError("Parament error, nullptr == uartInfo.mDevice\n");
return INVALID_FD;
}
constexpr int TCGETATTR_SUCCEED = 0;
constexpr int TCSETATTR_SUCCEED = 0;
int uartFd = mock->GetHandleForMock();
LogInfo("device = %s, uartFd = %d\n", uart.mDevice, uartFd);
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)));
auto selectTimeOut =
[=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
long long timeMs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(timeMs));
};
EXPECT_CALL(*mock.get(), fx_select(uartFd + 1, _, _, _, _))
.WillRepeatedly(DoAll(WithArgs<0, 1, 2, 3, 4>(Invoke(selectTimeOut)), Return(MOCK_SELECT_TIME_OUT)));
EXPECT_CALL(*mock.get(), fx_read(uartFd, _, _)).WillRepeatedly(DoAll(Return(UART_DEVICE_READ_NOTHING)));
mDeviceMap[uart.mDevice] = uartFd;
return uartFd;
}
int UartDeviceTestTool::GetDeviceMockFd(const UartInfo &uart)
{
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 INVALID_FD;
}
return mDeviceMap[uart.mDevice];
}
void UartDeviceTestTool::UnregisterUartDevice(const UartInfo &uart)
{
std::map<const char *, int>::iterator iter;
iter = mDeviceMap.find(uart.mDevice);
if (iter != mDeviceMap.end()) {
mDeviceMap.erase(iter);
return;
}
LogError("Can't found the uart device[%s].\n", uart.mDevice);
}
void UartDeviceTestTool::SetSendApiOnce(std::shared_ptr<LinuxTest> &mock, const UartInfo &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)));
}
void UartDeviceTestTool::SetRecvApiOnce(std::shared_ptr<LinuxTest> &mock, const UartInfo &uart, void *recvBuff,
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;
}
int uartFd = mDeviceMap[uart.mDevice];
auto selectSucceed =
[=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
FD_ZERO(readfds);
FD_SET(uartFd, readfds);
};
auto selectTimeOut =
[=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
long long timeMs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(timeMs));
};
constexpr int SELECT_READABLE = 1;
EXPECT_CALL(*mock.get(), fx_select(uartFd + 1, _, _, _, _))
.WillOnce(DoAll(WithArgs<0, 1, 2, 3, 4>(Invoke(selectSucceed)), Return(SELECT_READABLE)))
.WillRepeatedly(DoAll(WithArgs<0, 1, 2, 3, 4>(Invoke(selectTimeOut)), Return(MOCK_SELECT_TIME_OUT)));
auto readBuf = [=, &mock](int fd, void *buf, size_t count) {
memcpy(buf, recvBuff, length);
};
EXPECT_CALL(*mock.get(), fx_read(uartFd, _, _))
.WillOnce(DoAll(WithArgs<0, 1, 2>(Invoke(readBuf)), Return(length)))
.WillRepeatedly(DoAll(Return(UART_DEVICE_READ_NOTHING)));
}
void UartDeviceTestTool::SetUartDeviceOpenFailed(std::shared_ptr<LinuxTest> &mock, const UartInfo &uart)
{
LogInfo("SetUartDeviceOpenFailed[%s], will return -1\n", uart.mDevice);
EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, _)).WillRepeatedly(DoAll((Return(-1))));
}
void UartDeviceTestTool::SetUartDeviceReadNothing(std::shared_ptr<LinuxTest> &mock, const UartInfo &uart)
{
SetUartDeviceTimeOut(mock, uart);
int uartFd = mDeviceMap[uart.mDevice];
EXPECT_CALL(*mock.get(), fx_read(uartFd, _, _)).WillRepeatedly(DoAll(Return(UART_DEVICE_READ_NOTHING)));
}
void UartDeviceTestTool::SetUartDeviceTimeOut(std::shared_ptr<LinuxTest> &mock, const UartInfo &uart)
{
int uartFd = mDeviceMap[uart.mDevice];
auto selectTimeOut =
[=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
long long timeMs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(timeMs));
};
EXPECT_CALL(*mock.get(), fx_select(uartFd + 1, _, _, _, _))
.WillRepeatedly(DoAll(WithArgs<0, 1, 2, 3, 4>(Invoke(selectTimeOut)), Return(MOCK_SELECT_TIME_OUT)));
}