174 lines
8.1 KiB
C++
174 lines
8.1 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 "LinuxTestImpl.h"
|
|
#include "GtestUsing.h"
|
|
#include "ILog.h"
|
|
#include "LinuxApiMock.h"
|
|
#include "WrapApi.h"
|
|
#include <bits/types/struct_timeval.h>
|
|
#include <gmock/gmock-spec-builders.h>
|
|
#include <memory>
|
|
#include <stdio.h>
|
|
#include <sys/select.h>
|
|
#include <sys/stat.h>
|
|
#include <termios.h>
|
|
#include <thread>
|
|
/**
|
|
* @brief The simulated interface has been subjected to lock serial processing to ensure that the return value can be
|
|
* safely returned through multiple threads. However, this may affect the timing of the test code, which is not very
|
|
* reasonable. If the behavior of the simulated interface is redefined, the impact can be ignored.
|
|
* @param mock
|
|
*/
|
|
void LinuxTestImpl::ApiInit(std::shared_ptr<LinuxTest> &mock)
|
|
{
|
|
LogInfo("ApiInit\n");
|
|
static int openFd = -1;
|
|
auto api_open = [=](const char *pathname, int flags) {
|
|
LogInfo("Call __real_fx_open, pathname = %s.\n", pathname);
|
|
openFd = __real_fx_open(pathname, flags);
|
|
LogInfo("openFd = %d\n", openFd);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_open(_, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1>(Invoke(api_open)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&openFd)));
|
|
static int resultTcgetattr = -1;
|
|
auto api_tcgetattr = [=](int fd, struct termios *termios_p) {
|
|
resultTcgetattr = __real_fx_tcgetattr(fd, termios_p);
|
|
LogInfo("resultTcgetattr = %d\n", resultTcgetattr);
|
|
};
|
|
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::ApiUnlockThread),
|
|
ReturnPointee(&resultTcgetattr)));
|
|
static int resultTcsetattr = -1;
|
|
auto api_tcsetattr = [=](int fd, int optional_actions, const struct termios *termios_p) {
|
|
resultTcsetattr = __real_fx_tcsetattr(fd, optional_actions, termios_p);
|
|
LogInfo("resultTcsetattr = %d\n", resultTcsetattr);
|
|
};
|
|
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::ApiUnlockThread),
|
|
ReturnPointee(&resultTcsetattr)));
|
|
static int writeLength = -1;
|
|
auto api_write = [=](int fd, const void *buf, size_t count) {
|
|
writeLength = __real_fx_write(fd, buf, count);
|
|
LogInfo("writeLength = %d\n", writeLength);
|
|
};
|
|
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::ApiUnlockThread),
|
|
ReturnPointee(&writeLength)));
|
|
static int readLength = -1;
|
|
auto api_read = [=](int fd, void *buf, size_t count) {
|
|
readLength = __real_fx_read(fd, buf, count);
|
|
LogInfo("readLength = %d\n", readLength);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_read(_, _, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1, 2>(Invoke(api_read)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&readLength)));
|
|
static int selectResult = -1;
|
|
auto api_select = [=](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
|
|
selectResult = __real_fx_select(nfds, readfds, writefds, exceptfds, timeout);
|
|
LogInfo("selectResult = %d\n", selectResult);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_select(_, _, _, _, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1, 2, 3, 4>(Invoke(api_select)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&selectResult)));
|
|
static int fstatResult = -1;
|
|
auto api_fstat = [=](int fd, struct stat *statbuf) {
|
|
LogInfo("Call __real_fx_fstat, fd = %d.\n", fd);
|
|
fstatResult = __real_fx_fstat(fd, statbuf);
|
|
LogInfo("fstatResult = %d\n", fstatResult);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_fstat(_, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1>(Invoke(api_fstat)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&fstatResult)));
|
|
static int accessResult = -1;
|
|
auto api_access = [=](const char *pathname, int mode) {
|
|
accessResult = __real_fx_access(pathname, mode);
|
|
LogInfo("accessResult = %d\n", accessResult);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_access(_, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1>(Invoke(api_access)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&accessResult)));
|
|
static FILE *fopenResult = nullptr;
|
|
auto api_fopen = [=](const char *pathname, const char *mode) {
|
|
fopenResult = __real_fx_fopen(pathname, mode);
|
|
};
|
|
EXPECT_CALL(*mock.get(), fx_fopen(_, _))
|
|
.WillRepeatedly(
|
|
DoAll(Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiLock),
|
|
WithArgs<0, 1>(Invoke(api_fopen)),
|
|
Invoke((std::dynamic_pointer_cast<LinuxTestImpl>(mock)).get(), &LinuxTestImpl::ApiUnlockThread),
|
|
ReturnPointee(&fopenResult)));
|
|
}
|
|
void LinuxTestImpl::Init()
|
|
{
|
|
}
|
|
void LinuxTestImpl::UnInit()
|
|
{
|
|
if (mApiThread.joinable()) {
|
|
mApiThread.join();
|
|
}
|
|
}
|
|
void LinuxTestImpl::ApiLock(void)
|
|
{
|
|
/**
|
|
* @brief This has been optimized and does not require locking; Place the lock position in the WrapApi file, and
|
|
* lock the Mock function to ensure that it returns the value of the global variable before it can return, to avoid
|
|
* the problem of obtaining incorrect return values due to multithreading timing errors.
|
|
*/
|
|
// mApiMutex.lock();
|
|
// LogInfo("lock api.\n");
|
|
}
|
|
void LinuxTestImpl::ApiUnlock(void)
|
|
{
|
|
// mApiMutex.unlock();
|
|
// LogInfo("unlock api.\n");
|
|
}
|
|
void LinuxTestImpl::ApiUnlockThread(void)
|
|
{
|
|
// LogInfo("ApiUnlockThread\n");
|
|
// if (mApiThread.joinable()) {
|
|
// mApiThread.join();
|
|
// }
|
|
// auto api_unlock = [](std::shared_ptr<LinuxTestImpl> test) {
|
|
// std::this_thread::sleep_for(std::chrono::milliseconds(API_LOCK_TIME_MS));
|
|
// test->ApiUnlock();
|
|
// };
|
|
// std::shared_ptr<LinuxTestImpl> test = std::dynamic_pointer_cast<LinuxTestImpl>(LinuxTest::shared_from_this());
|
|
// mApiThread = std::thread(api_unlock, test);
|
|
} |