move tests to separate dir

create macro "pip_test()" for easily add new tests
This commit is contained in:
2020-07-31 15:47:08 +03:00
parent e728b30e5e
commit 21111b3e67
8 changed files with 675 additions and 666 deletions

View File

@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(_PIP_MAJOR 1) set(_PIP_MAJOR 1)
set(_PIP_MINOR 99) set(_PIP_MINOR 99)
set(_PIP_REVISION 1) set(_PIP_REVISION 2)
set(_PIP_SUFFIX _prebeta) set(_PIP_SUFFIX _prebeta)
set(_PIP_COMPANY SHS) set(_PIP_COMPANY SHS)
set(_PIP_DOMAIN org.SHS) set(_PIP_DOMAIN org.SHS)
@@ -98,11 +98,7 @@ set(PIP_OPENCL "no")
set(PIP_LUA "no") set(PIP_LUA "no")
set(PIP_IOUTILS "yes") set(PIP_IOUTILS "yes")
set(PIP_UTILS_LIST) set(PIP_UTILS_LIST)
set(PIP_TESTS_LIST)
if (TESTS)
include(DownloadGTest)
set(PIP_CONCURRENT_TEST "lib/concurrent/test")
endif()
if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) if (DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(STATIC_LIB ON) set(STATIC_LIB ON)
@@ -199,6 +195,11 @@ foreach(F ${PIP_FOLDERS})
include_directories("${PIP_SRC_MAIN}/${F}") include_directories("${PIP_SRC_MAIN}/${F}")
gather_src("${PIP_SRC_MAIN}/${F}" CPP_LIB_MAIN HDRS PHDRS) gather_src("${PIP_SRC_MAIN}/${F}" CPP_LIB_MAIN HDRS PHDRS)
endforeach(F) endforeach(F)
if (TESTS)
add_subdirectory(tests)
endif()
# Crypt lib # Crypt lib
gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS) gather_src("${PIP_SRC_CRYPT}" CPP_LIB_CRYPT HDRS PHDRS)
@@ -226,11 +227,6 @@ gather_src("${PIP_SRC_CLOUD}" CPP_LIB_CLOUD HDRS PHDRS)
# LUA lib # LUA lib
gather_src("${PIP_SRC_LUA}" CPP_LIB_LUA HDRS PHDRS) gather_src("${PIP_SRC_LUA}" CPP_LIB_LUA HDRS PHDRS)
if (TESTS)
# Concurrent lib tests
gather_src("${PIP_CONCURRENT_TEST}" CPP_CONCURRENT_TEST HDRS PHDRS)
endif()
if(PIP_FREERTOS) if(PIP_FREERTOS)
add_definitions(-DPIP_FREERTOS) add_definitions(-DPIP_FREERTOS)
set(ICU OFF) set(ICU OFF)
@@ -579,15 +575,6 @@ if (NOT CROSSTOOLS)
list(APPEND PIP_LIBS_TARGETS pip_io_utils) list(APPEND PIP_LIBS_TARGETS pip_io_utils)
# Enable build tests for concurrent module
if(PIP_CONCURRENT_TEST)
add_executable(pip_concurrent_test ${CPP_CONCURRENT_TEST})
target_link_libraries(pip_concurrent_test pip gtest_main gmock_main)
add_test(NAME pip_concurrent_test COMMAND tests)
add_custom_target(pip_concurrent_test_perform ALL COMMAND pip_concurrent_test)
endif()
# Build cloud library if crypt enabled # Build cloud library if crypt enabled
if(sodium_FOUND) if(sodium_FOUND)
import_version(pip_cloud pip) import_version(pip_cloud pip)
@@ -800,6 +787,13 @@ message(" OpenCL : ${PIP_OPENCL}")
message(" IOUtils : ${PIP_IOUTILS}") message(" IOUtils : ${PIP_IOUTILS}")
message(" Cloud : ${PIP_CLOUD}") message(" Cloud : ${PIP_CLOUD}")
message(" Lua : ${PIP_LUA}") message(" Lua : ${PIP_LUA}")
if (PIP_TESTS_LIST)
message("")
message(" Tests:")
foreach(_test ${PIP_TESTS_LIST})
message(" * ${_test}")
endforeach()
endif()
message("") message("")
message(" Utilites:") message(" Utilites:")
foreach(_util ${PIP_UTILS_LIST}) foreach(_util ${PIP_UTILS_LIST})

15
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,15 @@
include(DownloadGTest)
macro(pip_test NAME LIBS)
gather_src("${NAME}" CPP_${NAME}_TEST _T_H _T_PH)
set(_target pip_${NAME}_test)
add_executable(${_target} ${CPP_${NAME}_TEST})
target_link_libraries(${_target} pip ${LIBS} gtest_main gmock_main)
add_test(NAME ${_target} COMMAND tests)
add_custom_target(${_target}_perform ALL COMMAND ${_target})
list(APPEND PIP_TESTS_LIST "${NAME}")
set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE)
endmacro()
# Concurrent tests
pip_test(concurrent "")

View File

@@ -1,16 +1,16 @@
cmake_minimum_required(VERSION 2.8.2) cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE) project(googletest-download NONE)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add(googletest ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG "dea0216d0c6bc5e63cf5f6c8651cd268668032ec" GIT_TAG "dea0216d0c6bc5e63cf5f6c8651cd268668032ec"
GIT_CONFIG "advice.detachedHead=false" GIT_CONFIG "advice.detachedHead=false"
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""
INSTALL_COMMAND "" INSTALL_COMMAND ""
TEST_COMMAND "" TEST_COMMAND ""
) )

View File

@@ -1,264 +1,264 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "piblockingdequeue.h" #include "piblockingdequeue.h"
class MockConditionVar: public PIConditionVariable { class MockConditionVar: public PIConditionVariable {
public: public:
bool isWaitCalled = false; bool isWaitCalled = false;
bool isWaitForCalled = false; bool isWaitForCalled = false;
bool isTrueCondition = false; bool isTrueCondition = false;
int timeout = -1; int timeout = -1;
void wait(PIMutex& lk) override { void wait(PIMutex& lk) override {
isWaitCalled = true; isWaitCalled = true;
} }
void wait(PIMutex& lk, const std::function<bool()>& condition) override { void wait(PIMutex& lk, const std::function<bool()>& condition) override {
isWaitCalled = true; isWaitCalled = true;
lk.lock(); lk.lock();
isTrueCondition = condition(); isTrueCondition = condition();
lk.unlock(); lk.unlock();
} }
bool waitFor(PIMutex& lk, int timeoutMs) override { bool waitFor(PIMutex& lk, int timeoutMs) override {
isWaitForCalled = true; isWaitForCalled = true;
timeout = timeoutMs; timeout = timeoutMs;
return false; return false;
} }
bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override { bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override {
isWaitForCalled = true; isWaitForCalled = true;
lk.lock(); lk.lock();
isTrueCondition = condition(); isTrueCondition = condition();
timeout = timeoutMs; timeout = timeoutMs;
lk.unlock(); lk.unlock();
return isTrueCondition; return isTrueCondition;
} }
}; };
TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) { TEST(BlockingDequeueUnitTest, put_is_block_when_capacity_reach) {
size_t capacity = 0; size_t capacity = 0;
auto conditionVarAdd = new MockConditionVar(); auto conditionVarAdd = new MockConditionVar();
auto conditionVarRem = new MockConditionVar(); auto conditionVarRem = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem); PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
dequeue.put(11); dequeue.put(11);
ASSERT_TRUE(conditionVarRem->isWaitCalled); ASSERT_TRUE(conditionVarRem->isWaitCalled);
ASSERT_FALSE(conditionVarRem->isTrueCondition); ASSERT_FALSE(conditionVarRem->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) { TEST(BlockingDequeueUnitTest, offer_timedout_is_false_when_capacity_reach) {
size_t capacity = 0; size_t capacity = 0;
int timeout = 11; int timeout = 11;
auto conditionVarAdd = new MockConditionVar(); auto conditionVarAdd = new MockConditionVar();
auto conditionVarRem = new MockConditionVar(); auto conditionVarRem = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem); PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
ASSERT_FALSE(dequeue.offer(11, timeout)); ASSERT_FALSE(dequeue.offer(11, timeout));
} }
TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) { TEST(BlockingDequeueUnitTest, offer_timedout_is_block_when_capacity_reach) {
size_t capacity = 0; size_t capacity = 0;
int timeout = 11; int timeout = 11;
auto conditionVarAdd = new MockConditionVar(); auto conditionVarAdd = new MockConditionVar();
auto conditionVarRem = new MockConditionVar(); auto conditionVarRem = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem); PIBlockingDequeue<int> dequeue(capacity, conditionVarAdd, conditionVarRem);
dequeue.offer(11, timeout); dequeue.offer(11, timeout);
EXPECT_TRUE(conditionVarRem->isWaitForCalled); EXPECT_TRUE(conditionVarRem->isWaitForCalled);
EXPECT_EQ(timeout, conditionVarRem->timeout); EXPECT_EQ(timeout, conditionVarRem->timeout);
ASSERT_FALSE(conditionVarRem->isTrueCondition); ASSERT_FALSE(conditionVarRem->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) { TEST(BlockingDequeueUnitTest, offer_is_true_before_capacity_reach) {
size_t capacity = 1; size_t capacity = 1;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
ASSERT_TRUE(dequeue.offer(10)); ASSERT_TRUE(dequeue.offer(10));
} }
TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) { TEST(BlockingDequeueUnitTest, offer_is_false_when_capacity_reach) {
size_t capacity = 1; size_t capacity = 1;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
dequeue.offer(11); dequeue.offer(11);
ASSERT_FALSE(dequeue.offer(10)); ASSERT_FALSE(dequeue.offer(10));
} }
// TODO change take_is_block_when_empty to prevent segfault // TODO change take_is_block_when_empty to prevent segfault
TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) { TEST(DISABLED_BlockingDequeueUnitTest, take_is_block_when_empty) {
size_t capacity = 1; size_t capacity = 1;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
// May cause segfault because take front of empty queue // May cause segfault because take front of empty queue
dequeue.take(); dequeue.take();
EXPECT_TRUE(conditionVar->isWaitCalled); EXPECT_TRUE(conditionVar->isWaitCalled);
ASSERT_FALSE(conditionVar->isTrueCondition); ASSERT_FALSE(conditionVar->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) { TEST(BlockingDequeueUnitTest, take_is_not_block_when_not_empty) {
size_t capacity = 1; size_t capacity = 1;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
dequeue.take(); dequeue.take();
EXPECT_TRUE(conditionVar->isWaitCalled); EXPECT_TRUE(conditionVar->isWaitCalled);
ASSERT_TRUE(conditionVar->isTrueCondition); ASSERT_TRUE(conditionVar->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) { TEST(BlockingDequeueUnitTest, take_is_value_eq_to_offer_value) {
size_t capacity = 1; size_t capacity = 1;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.take(), 111); ASSERT_EQ(dequeue.take(), 111);
} }
TEST(BlockingDequeueUnitTest, take_is_last) { TEST(BlockingDequeueUnitTest, take_is_last) {
size_t capacity = 10; size_t capacity = 10;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
EXPECT_TRUE(dequeue.offer(111)); EXPECT_TRUE(dequeue.offer(111));
EXPECT_TRUE(dequeue.offer(222)); EXPECT_TRUE(dequeue.offer(222));
ASSERT_EQ(dequeue.take(), 111); ASSERT_EQ(dequeue.take(), 111);
ASSERT_EQ(dequeue.take(), 222); ASSERT_EQ(dequeue.take(), 222);
} }
TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) { TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) {
size_t capacity = 1; size_t capacity = 1;
bool isOk; bool isOk;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.poll(111, &isOk); dequeue.poll(111, &isOk);
EXPECT_FALSE(conditionVar->isWaitForCalled); EXPECT_FALSE(conditionVar->isWaitForCalled);
} }
TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) {
size_t capacity = 1; size_t capacity = 1;
bool isOk; bool isOk;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
ASSERT_EQ(dequeue.poll(111, &isOk), 111); ASSERT_EQ(dequeue.poll(111, &isOk), 111);
} }
TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) {
size_t capacity = 1; size_t capacity = 1;
bool isOk; bool isOk;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.poll(-1, &isOk), 111); ASSERT_EQ(dequeue.poll(-1, &isOk), 111);
} }
TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) { TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) {
size_t capacity = 1; size_t capacity = 1;
int timeout = 11; int timeout = 11;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.poll(timeout, 111); dequeue.poll(timeout, 111);
EXPECT_TRUE(conditionVar->isWaitForCalled); EXPECT_TRUE(conditionVar->isWaitForCalled);
EXPECT_EQ(timeout, conditionVar->timeout); EXPECT_EQ(timeout, conditionVar->timeout);
ASSERT_FALSE(conditionVar->isTrueCondition); ASSERT_FALSE(conditionVar->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) { TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) {
size_t capacity = 1; size_t capacity = 1;
int timeout = 11; int timeout = 11;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
ASSERT_EQ(dequeue.poll(timeout, 111), 111); ASSERT_EQ(dequeue.poll(timeout, 111), 111);
} }
TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) { TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) {
size_t capacity = 1; size_t capacity = 1;
int timeout = 11; int timeout = 11;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
dequeue.poll(timeout, -1); dequeue.poll(timeout, -1);
EXPECT_TRUE(conditionVar->isWaitForCalled); EXPECT_TRUE(conditionVar->isWaitForCalled);
ASSERT_TRUE(conditionVar->isTrueCondition); ASSERT_TRUE(conditionVar->isTrueCondition);
} }
TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) { TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) {
size_t capacity = 1; size_t capacity = 1;
int timeout = 11; int timeout = 11;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.poll(timeout, -1), 111); ASSERT_EQ(dequeue.poll(timeout, -1), 111);
} }
TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) { TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) {
size_t capacity = 10; size_t capacity = 10;
auto conditionVar = new MockConditionVar(); auto conditionVar = new MockConditionVar();
PIBlockingDequeue<int> dequeue(capacity, conditionVar); PIBlockingDequeue<int> dequeue(capacity, conditionVar);
dequeue.offer(111); dequeue.offer(111);
dequeue.offer(222); dequeue.offer(222);
ASSERT_EQ(dequeue.poll(10, -1), 111); ASSERT_EQ(dequeue.poll(10, -1), 111);
ASSERT_EQ(dequeue.poll(10, -1), 222); ASSERT_EQ(dequeue.poll(10, -1), 222);
} }
TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) { TEST(BlockingDequeueUnitTest, capacity_is_eq_constructor_capacity) {
size_t capacity = 10; size_t capacity = 10;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
ASSERT_EQ(dequeue.capacity(), capacity); ASSERT_EQ(dequeue.capacity(), capacity);
} }
TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) { TEST(BlockingDequeueUnitTest, remainingCapacity_is_dif_of_capacity_and_size) {
size_t capacity = 2; size_t capacity = 2;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
ASSERT_EQ(dequeue.remainingCapacity(), capacity); ASSERT_EQ(dequeue.remainingCapacity(), capacity);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1); ASSERT_EQ(dequeue.remainingCapacity(), capacity - 1);
} }
TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) { TEST(BlockingDequeueUnitTest, remainingCapacity_is_zero_when_capacity_reach) {
size_t capacity = 1; size_t capacity = 1;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
dequeue.offer(111); dequeue.offer(111);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.remainingCapacity(), 0); ASSERT_EQ(dequeue.remainingCapacity(), 0);
} }
TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) { TEST(BlockingDequeueUnitTest, size_is_eq_to_num_of_elements) {
size_t capacity = 1; size_t capacity = 1;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
ASSERT_EQ(dequeue.size(), 0); ASSERT_EQ(dequeue.size(), 0);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.size(), 1); ASSERT_EQ(dequeue.size(), 1);
} }
TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) { TEST(BlockingDequeueUnitTest, size_is_eq_to_capacity_when_capacity_reach) {
size_t capacity = 1; size_t capacity = 1;
PIBlockingDequeue<int> dequeue(capacity); PIBlockingDequeue<int> dequeue(capacity);
dequeue.offer(111); dequeue.offer(111);
dequeue.offer(111); dequeue.offer(111);
ASSERT_EQ(dequeue.size(), capacity); ASSERT_EQ(dequeue.size(), capacity);
} }
TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) { TEST(BlockingDequeueUnitTest, drainTo_is_elements_moved) {
size_t capacity = 10; size_t capacity = 10;
PIDeque<int> refDeque; PIDeque<int> refDeque;
for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10);
PIBlockingDequeue<int> blockingDequeue(refDeque); PIBlockingDequeue<int> blockingDequeue(refDeque);
PIDeque<int> deque; PIDeque<int> deque;
blockingDequeue.drainTo(deque); blockingDequeue.drainTo(deque);
ASSERT_EQ(blockingDequeue.size(), 0); ASSERT_EQ(blockingDequeue.size(), 0);
ASSERT_TRUE(deque == refDeque); ASSERT_TRUE(deque == refDeque);
} }
TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) { TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_size_when_all_moved) {
size_t capacity = 10; size_t capacity = 10;
PIDeque<int> refDeque; PIDeque<int> refDeque;
for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10);
PIBlockingDequeue<int> blockingDequeue(refDeque); PIBlockingDequeue<int> blockingDequeue(refDeque);
PIDeque<int> deque; PIDeque<int> deque;
ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size()); ASSERT_EQ(blockingDequeue.drainTo(deque), refDeque.size());
} }
TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) { TEST(BlockingDequeueUnitTest, drainTo_is_ret_eq_to_maxCount) {
size_t capacity = 10; size_t capacity = 10;
PIDeque<int> refDeque; PIDeque<int> refDeque;
for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10); for (size_t i = 0; i < capacity / 2; ++i) refDeque.push_back(i * 10);
PIBlockingDequeue<int> blockingDequeue(refDeque); PIBlockingDequeue<int> blockingDequeue(refDeque);
PIDeque<int> deque; PIDeque<int> deque;
ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1); ASSERT_EQ(blockingDequeue.drainTo(deque, refDeque.size() - 1), refDeque.size() - 1);
} }

View File

@@ -1,53 +1,53 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "piconditionvar.h" #include "piconditionvar.h"
#include "pithread.h" #include "pithread.h"
#include "testutil.h" #include "testutil.h"
class ConditionLock : public ::testing::Test, public TestUtil { class ConditionLock : public ::testing::Test, public TestUtil {
public: public:
PIMutex* m = new PIMutex(); PIMutex* m = new PIMutex();
}; };
TEST_F(ConditionLock, lock_is_protect) { TEST_F(ConditionLock, lock_is_protect) {
m->lock(); m->lock();
bool* isProtect = new bool(true); bool* isProtect = new bool(true);
createThread([&](){ createThread([&](){
m->lock(); m->lock();
*isProtect = false; *isProtect = false;
}); });
EXPECT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); EXPECT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
ASSERT_TRUE(*isProtect); ASSERT_TRUE(*isProtect);
} }
TEST_F(ConditionLock, unlock_is_release) { TEST_F(ConditionLock, unlock_is_release) {
m->lock(); m->lock();
bool* isReleased = new bool(false); bool* isReleased = new bool(false);
m->unlock(); m->unlock();
createThread([&](){ createThread([&](){
m->lock(); m->lock();
*isReleased = true; *isReleased = true;
m->unlock(); m->unlock();
}); });
ASSERT_TRUE(*isReleased); ASSERT_TRUE(*isReleased);
} }
TEST_F(ConditionLock, tryLock_is_false_when_locked) { TEST_F(ConditionLock, tryLock_is_false_when_locked) {
createThread([&](){ createThread([&](){
m->lock(); m->lock();
piMSleep(WAIT_THREAD_TIME_MS); piMSleep(WAIT_THREAD_TIME_MS);
}); });
ASSERT_FALSE(m->tryLock()); ASSERT_FALSE(m->tryLock());
} }
TEST_F(ConditionLock, tryLock_is_true_when_unlocked) { TEST_F(ConditionLock, tryLock_is_true_when_unlocked) {
ASSERT_TRUE(m->tryLock()); ASSERT_TRUE(m->tryLock());
} }
TEST_F(ConditionLock, tryLock_is_recursive_lock_enable) { TEST_F(ConditionLock, tryLock_is_recursive_lock_enable) {
m->lock(); m->lock();
ASSERT_TRUE(m->tryLock()); ASSERT_TRUE(m->tryLock());
} }

View File

@@ -1,200 +1,200 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "piconditionvar.h" #include "piconditionvar.h"
#include "pithread.h" #include "pithread.h"
#include "testutil.h" #include "testutil.h"
class ConditionVariable : public ::testing::Test, public TestUtil { class ConditionVariable : public ::testing::Test, public TestUtil {
public: public:
PIMutex m; PIMutex m;
PIConditionVariable* variable; PIConditionVariable* variable;
protected: protected:
void SetUp() override { void SetUp() override {
variable = new PIConditionVariable(); variable = new PIConditionVariable();
adapterFunctionDefault = [&](){ adapterFunctionDefault = [&](){
m.lock(); m.lock();
variable->wait(m); variable->wait(m);
m.unlock(); m.unlock();
}; };
} }
}; };
TEST_F(ConditionVariable, wait_is_block) { TEST_F(ConditionVariable, wait_is_block) {
createThread(); createThread();
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) { TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) {
variable->notifyOne(); variable->notifyOne();
createThread(); createThread();
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) { TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) {
variable->notifyAll(); variable->notifyAll();
createThread(); createThread();
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) { TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) {
createThread(); createThread();
variable->notifyOne(); variable->notifyOne();
ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) { TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) {
PIVector<PIThread*> threads; PIVector<PIThread*> threads;
for (int i = 0; i < THREAD_COUNT; ++i) { for (int i = 0; i < THREAD_COUNT; ++i) {
threads.push_back(new PIThread([=](){ adapterFunctionDefault(); })); threads.push_back(new PIThread([=](){ adapterFunctionDefault(); }));
} }
piForeach(PIThread* thread, threads) thread->startOnce(); piForeach(PIThread* thread, threads) thread->startOnce();
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
variable->notifyAll(); variable->notifyAll();
PITimeMeasurer measurer; PITimeMeasurer measurer;
piForeach(PIThread* thread, threads) { piForeach(PIThread* thread, threads) {
int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m(); int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m();
thread->waitForFinish(timeout > 0 ? timeout : 0); thread->waitForFinish(timeout > 0 ? timeout : 0);
} }
for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running"; for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running";
piForeach(PIThread* thread, threads) delete thread; piForeach(PIThread* thread, threads) delete thread;
} }
TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) { TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) {
PIVector<PIThread*> threads; PIVector<PIThread*> threads;
for (int i = 0; i < THREAD_COUNT; ++i) { for (int i = 0; i < THREAD_COUNT; ++i) {
threads.push_back(new PIThread(adapterFunctionDefault)); threads.push_back(new PIThread(adapterFunctionDefault));
} }
piForeach(PIThread* thread, threads) thread->startOnce(); piForeach(PIThread* thread, threads) thread->startOnce();
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
variable->notifyOne(); variable->notifyOne();
piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT);
int runningThreadCount = 0; int runningThreadCount = 0;
piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++; piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++;
ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1); ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1);
} }
TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) { TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) {
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->wait(m); variable->wait(m);
piMSleep(2 * WAIT_THREAD_TIME_MS); piMSleep(2 * WAIT_THREAD_TIME_MS);
// Missing unlock // Missing unlock
}); });
variable->notifyOne(); variable->notifyOne();
msleep(WAIT_THREAD_TIME_MS); msleep(WAIT_THREAD_TIME_MS);
ASSERT_FALSE(m.tryLock()); ASSERT_FALSE(m.tryLock());
} }
TEST_F(ConditionVariable, wait_condition_is_block) { TEST_F(ConditionVariable, wait_condition_is_block) {
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->wait(m, [](){ return false; }); variable->wait(m, [](){ return false; });
m.unlock(); m.unlock();
}); });
ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) { TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) {
bool isConditionChecked = false; bool isConditionChecked = false;
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->wait(m, [&](){ variable->wait(m, [&](){
isConditionChecked = true; isConditionChecked = true;
return false; return false;
}); });
m.unlock(); m.unlock();
}); });
m.lock(); m.lock();
ASSERT_TRUE(isConditionChecked); ASSERT_TRUE(isConditionChecked);
m.unlock(); m.unlock();
} }
TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) { TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) {
bool isConditionChecked; bool isConditionChecked;
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->wait(m, [&](){ variable->wait(m, [&](){
isConditionChecked = true; isConditionChecked = true;
return false; return false;
}); });
m.unlock(); m.unlock();
}); });
m.lock(); m.lock();
isConditionChecked = false; isConditionChecked = false;
m.unlock(); m.unlock();
variable->notifyOne(); variable->notifyOne();
msleep(threadStartTime + 1); msleep(threadStartTime + 1);
m.lock(); m.lock();
ASSERT_TRUE(isConditionChecked); ASSERT_TRUE(isConditionChecked);
m.unlock(); m.unlock();
} }
TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) { TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) {
bool condition = false; bool condition = false;
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->wait(m, [&](){ return condition; }); variable->wait(m, [&](){ return condition; });
m.unlock(); m.unlock();
}); });
m.lock(); m.lock();
condition = true; condition = true;
m.unlock(); m.unlock();
variable->notifyOne(); variable->notifyOne();
ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS));
} }
TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) { TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) {
createThread([&](){ createThread([&](){
PITimeMeasurer measurer; PITimeMeasurer measurer;
m.lock(); m.lock();
variable->waitFor(m, WAIT_THREAD_TIME_MS * 2); variable->waitFor(m, WAIT_THREAD_TIME_MS * 2);
m.unlock(); m.unlock();
// Not reliable because spurious wakeup may happen // Not reliable because spurious wakeup may happen
ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS); ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS);
}); });
EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3)); EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3));
} }
TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) { TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) {
std::atomic_bool isUnblock(false); std::atomic_bool isUnblock(false);
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->waitFor(m, WAIT_THREAD_TIME_MS); variable->waitFor(m, WAIT_THREAD_TIME_MS);
isUnblock = true; isUnblock = true;
m.unlock(); m.unlock();
}); });
// Test failed if suspend forever // Test failed if suspend forever
EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS));
ASSERT_TRUE(isUnblock); ASSERT_TRUE(isUnblock);
} }
TEST_F(ConditionVariable, waitFor_is_false_when_timeout) { TEST_F(ConditionVariable, waitFor_is_false_when_timeout) {
bool waitRet = true; bool waitRet = true;
createThread([&](){ createThread([&](){
m.lock(); m.lock();
waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS); waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS);
m.unlock(); m.unlock();
}); });
EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS));
ASSERT_FALSE(waitRet); ASSERT_FALSE(waitRet);
} }
TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) { TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) {
bool condition = false; bool condition = false;
createThread([&](){ createThread([&](){
m.lock(); m.lock();
variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; }); variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; });
m.unlock(); m.unlock();
}); });
EXPECT_TRUE(thread->isRunning()); EXPECT_TRUE(thread->isRunning());
m.lock(); m.lock();
condition = true; condition = true;
m.unlock(); m.unlock();
variable->notifyOne(); variable->notifyOne();
msleep(WAIT_THREAD_TIME_MS); msleep(WAIT_THREAD_TIME_MS);
ASSERT_FALSE(thread->isRunning()); ASSERT_FALSE(thread->isRunning());
} }

View File

@@ -1,54 +1,54 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "pithreadpoolexecutor.h" #include "pithreadpoolexecutor.h"
#include "pimutex.h" #include "pimutex.h"
const int WAIT_THREAD_TIME_MS = 30; const int WAIT_THREAD_TIME_MS = 30;
TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) { TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) {
PIMutex m; PIMutex m;
int invokedRunnables = 0; int invokedRunnables = 0;
PIThreadPoolExecutor executorService(1); PIThreadPoolExecutor executorService(1);
executorService.execute([&]() { executorService.execute([&]() {
m.lock(); m.lock();
invokedRunnables++; invokedRunnables++;
m.unlock(); m.unlock();
}); });
piMSleep(WAIT_THREAD_TIME_MS); piMSleep(WAIT_THREAD_TIME_MS);
ASSERT_EQ(invokedRunnables, 1); ASSERT_EQ(invokedRunnables, 1);
} }
TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) { TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) {
bool isRunnableInvoke = false; bool isRunnableInvoke = false;
PIThreadPoolExecutor executorService(1); PIThreadPoolExecutor executorService(1);
executorService.shutdown(); executorService.shutdown();
executorService.execute([&]() { executorService.execute([&]() {
isRunnableInvoke = true; isRunnableInvoke = true;
}); });
piMSleep(WAIT_THREAD_TIME_MS); piMSleep(WAIT_THREAD_TIME_MS);
ASSERT_FALSE(isRunnableInvoke); ASSERT_FALSE(isRunnableInvoke);
} }
TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) { TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) {
bool isRunnableInvoke = false; bool isRunnableInvoke = false;
PIThreadPoolExecutor executorService(1); PIThreadPoolExecutor executorService(1);
executorService.execute([&]() { executorService.execute([&]() {
piMSleep(WAIT_THREAD_TIME_MS); piMSleep(WAIT_THREAD_TIME_MS);
isRunnableInvoke = true; isRunnableInvoke = true;
}); });
executorService.shutdown(); executorService.shutdown();
piMSleep(2 * WAIT_THREAD_TIME_MS); piMSleep(2 * WAIT_THREAD_TIME_MS);
ASSERT_TRUE(isRunnableInvoke); ASSERT_TRUE(isRunnableInvoke);
} }
TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) { TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) {
PIThreadPoolExecutor executorService(1); PIThreadPoolExecutor executorService(1);
executorService.execute([&]() { executorService.execute([&]() {
piMSleep(2 * WAIT_THREAD_TIME_MS); piMSleep(2 * WAIT_THREAD_TIME_MS);
}); });
executorService.shutdown(); executorService.shutdown();
PITimeMeasurer measurer; PITimeMeasurer measurer;
ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS)); ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS));
double waitTime = measurer.elapsed_m(); double waitTime = measurer.elapsed_m();
ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS); ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS);
ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS); ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS);
} }

View File

@@ -1,60 +1,60 @@
#ifndef AWRCANFLASHER_TESTUTIL_H #ifndef AWRCANFLASHER_TESTUTIL_H
#define AWRCANFLASHER_TESTUTIL_H #define AWRCANFLASHER_TESTUTIL_H
#include "pithread.h" #include "pithread.h"
#include <atomic> #include <atomic>
/** /**
* Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests * Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests
* write "Start thread timeout reach!" message. You can reduce it if you want increase test performance. * write "Start thread timeout reach!" message. You can reduce it if you want increase test performance.
*/ */
const int WAIT_THREAD_TIME_MS = 40; const int WAIT_THREAD_TIME_MS = 40;
const int THREAD_COUNT = 5; const int THREAD_COUNT = 5;
class TestUtil: public PIObject { class TestUtil: public PIObject {
PIOBJECT(TestUtil) PIOBJECT(TestUtil)
public: public:
double threadStartTime; double threadStartTime;
PIThread* thread = new PIThread(); PIThread* thread = new PIThread();
std::atomic_bool isRunning; std::atomic_bool isRunning;
std::function<void()> adapterFunctionDefault; std::function<void()> adapterFunctionDefault;
TestUtil() : isRunning(false) {} TestUtil() : isRunning(false) {}
bool createThread(const std::function<void()>& fun = nullptr, PIThread* thread_ = nullptr) { bool createThread(const std::function<void()>& fun = nullptr, PIThread* thread_ = nullptr) {
std::function<void()> actualFun = fun == nullptr ? adapterFunctionDefault : fun; std::function<void()> actualFun = fun == nullptr ? adapterFunctionDefault : fun;
if (thread_ == nullptr) thread_ = thread; if (thread_ == nullptr) thread_ = thread;
thread_->startOnce([=](void*){ thread_->startOnce([=](void*){
isRunning = true; isRunning = true;
actualFun(); actualFun();
}); });
return waitThread(thread_); return waitThread(thread_);
} }
bool waitThread(PIThread* thread_, bool runningStatus = true) { bool waitThread(PIThread* thread_, bool runningStatus = true) {
PITimeMeasurer measurer; PITimeMeasurer measurer;
bool isTimeout = !thread_->waitForStart(WAIT_THREAD_TIME_MS); bool isTimeout = !thread_->waitForStart(WAIT_THREAD_TIME_MS);
while (!isRunning) { while (!isRunning) {
isTimeout = WAIT_THREAD_TIME_MS <= measurer.elapsed_m(); isTimeout = WAIT_THREAD_TIME_MS <= measurer.elapsed_m();
if (isTimeout) break; if (isTimeout) break;
piUSleep(100); piUSleep(100);
} }
threadStartTime = measurer.elapsed_m(); threadStartTime = measurer.elapsed_m();
if (isTimeout) piCout << "Start thread timeout reach!"; if (isTimeout) piCout << "Start thread timeout reach!";
if (threadStartTime > 1) { if (threadStartTime > 1) {
piCout << "Start time" << threadStartTime << "ms"; piCout << "Start time" << threadStartTime << "ms";
} else if (threadStartTime > 0.001) { } else if (threadStartTime > 0.001) {
piCout << "Start time" << threadStartTime * 1000 << "mcs"; piCout << "Start time" << threadStartTime * 1000 << "mcs";
} else { } else {
piCout << "Start time" << threadStartTime * 1000 * 1000 << "ns"; piCout << "Start time" << threadStartTime * 1000 * 1000 << "ns";
} }
return !isTimeout; return !isTimeout;
} }
}; };
#endif //AWRCANFLASHER_TESTUTIL_H #endif //AWRCANFLASHER_TESTUTIL_H