/* * 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 "ILog.h" #include /** * @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 &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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1>(Invoke(api_open)), Invoke((std::dynamic_pointer_cast(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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1>(Invoke(api_tcgetattr)), Invoke((std::dynamic_pointer_cast(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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2>(Invoke(api_tcsetattr)), Invoke((std::dynamic_pointer_cast(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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2>(Invoke(api_write)), Invoke((std::dynamic_pointer_cast(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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2>(Invoke(api_read)), Invoke((std::dynamic_pointer_cast(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(mock)).get(), &LinuxTestImpl::ApiLock), WithArgs<0, 1, 2, 3, 4>(Invoke(api_select)), Invoke((std::dynamic_pointer_cast(mock)).get(), &LinuxTestImpl::ApiUnlockThread), ReturnPointee(&selectResult))); } void LinuxTestImpl::Init() {} void LinuxTestImpl::UnInit() { if (mApiThread.joinable()) { mApiThread.join(); } } void LinuxTestImpl::ApiLock(void) { 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 test) { std::this_thread::sleep_for(std::chrono::milliseconds(API_LOCK_TIME_MS)); test->ApiUnlock(); }; std::shared_ptr test = std::dynamic_pointer_cast(LinuxTest::shared_from_this()); mApiThread = std::thread(api_unlock, test); }