7 Commits

Author SHA1 Message Date
edb7189013 disable gmock build and remove obsolete tests 2026-03-21 13:31:29 +03:00
fe3b30bd49 version 5.6.1
patch deploy_tool: procDpkg now prioritize "non-cross" and "non-dev" packages, then only "non-cross"
add PIP_MANUAL_TEST CMake option
2026-03-20 13:00:24 +03:00
a1be5be5a1 increase timeout and remove sleep 2026-03-18 15:01:17 +03:00
99c99c39c2 separate cmake opts for tests 2026-03-18 13:39:01 +03:00
ba63e72bfa Merge pull request 'disable exeptions in cmake' (#199) from disable_exeptions into master
Reviewed-on: #199
2026-03-18 11:48:54 +03:00
ba57aa0144 disable exceptions on win 2026-03-18 09:40:32 +03:00
ccbf86f781 disable exeptions in cmake 2026-03-18 09:30:28 +03:00
14 changed files with 67 additions and 739 deletions

View File

@@ -97,8 +97,10 @@ public:
{ {
int code = lua_pcall (L, nargs, nresults, msgh); int code = lua_pcall (L, nargs, nresults, msgh);
if (code != LUABRIDGE_LUA_OK) if (code != LUABRIDGE_LUA_OK) {
Throw (LuaException (L, code)); // Throw (LuaException (L, code));
assert(true);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -128,7 +130,8 @@ protected:
private: private:
static int throwAtPanic (lua_State* L) static int throwAtPanic (lua_State* L)
{ {
throw LuaException (L, -1); // throw LuaException (L, -1);
return -1;
} }
}; };

View File

@@ -101,7 +101,8 @@ protected:
{ {
if (m_stackSize == 0) if (m_stackSize == 0)
{ {
throw std::logic_error ("Unable to continue registration"); std::cerr << ("Unable to continue registration");
assert(true);
} }
} }
}; };
@@ -1054,7 +1055,8 @@ public:
{ {
if (m_stackSize == 1) if (m_stackSize == 1)
{ {
throw std::logic_error ("endNamespace () called on global namespace"); std::cerr << ("endNamespace () called on global namespace");
assert(true);
} }
assert (m_stackSize > 1); assert (m_stackSize > 1);
@@ -1150,7 +1152,8 @@ public:
{ {
if (m_stackSize == 1) if (m_stackSize == 1)
{ {
throw std::logic_error ("addProperty () called on global namespace"); std::cerr << ("addProperty () called on global namespace");
assert(true);
} }
assert (lua_istable (L, -1)); // Stack: namespace table (ns) assert (lua_istable (L, -1)); // Stack: namespace table (ns)

View File

@@ -33,6 +33,7 @@
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
#include <iostream>
namespace luabridge { namespace luabridge {
@@ -320,7 +321,8 @@ public:
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
if (!lua_istable (L, -1)) if (!lua_istable (L, -1))
{ {
throw std::logic_error ("The class is not registered in LuaBridge"); std::cerr << ("The class is not registered in LuaBridge");
assert(true);
} }
lua_setmetatable (L, -2); lua_setmetatable (L, -2);
return ud; return ud;
@@ -375,7 +377,8 @@ private:
lua_rawgetp (L, LUA_REGISTRYINDEX, key); lua_rawgetp (L, LUA_REGISTRYINDEX, key);
if (!lua_istable (L, -1)) if (!lua_istable (L, -1))
{ {
throw std::logic_error ("The class is not registered in LuaBridge"); std::cerr << ("The class is not registered in LuaBridge");
assert(true);
} }
lua_setmetatable (L, -2); lua_setmetatable (L, -2);
} }

View File

@@ -6,7 +6,7 @@ endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 6) set(PIP_MINOR 6)
set(PIP_REVISION 0) set(PIP_REVISION 1)
set(PIP_SUFFIX ) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS) set(PIP_DOMAIN org.SHS)
@@ -67,11 +67,13 @@ set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "")
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT}) option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
option(STD_IOSTREAM "Building with std iostream operators support" OFF) option(STD_IOSTREAM "Building with std iostream operators support" OFF)
option(INTROSPECTION "Build with introspection" OFF) option(INTROSPECTION "Build with introspection" OFF)
option(TESTS "Build tests and perform their before install step" OFF) option(TESTS "Build tests" OFF)
option(TESTS_RUN "Run tests before install step" OFF)
option(COVERAGE "Build project with coverage info" OFF) option(COVERAGE "Build project with coverage info" OFF)
option(PIP_FFTW_F "Support fftw module for float" ON) option(PIP_FFTW_F "Support fftw module for float" ON)
option(PIP_FFTW_L "Support fftw module for long double" ON) option(PIP_FFTW_L "Support fftw module for long double" ON)
option(PIP_FFTW_Q "Support fftw module for quad double" OFF) option(PIP_FFTW_Q "Support fftw module for quad double" OFF)
option(PIP_MANUAL_TEST "Build dev test (main.cpp)" OFF)
set(PIP_UTILS 1) set(PIP_UTILS 1)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
@@ -360,10 +362,10 @@ endif()
if(WIN32) if(WIN32)
add_definitions(-DPSAPI_VERSION=1) add_definitions(-DPSAPI_VERSION=1)
if(${C_COMPILER} STREQUAL "cl.exe") if(${C_COMPILER} STREQUAL "cl.exe")
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0") set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0 /EH-")
endif() endif()
else() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fno-exceptions")
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS) if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
endif() endif()
@@ -592,12 +594,14 @@ if (NOT CROSSTOOLS)
#target_link_libraries(pip_plugin pip) #target_link_libraries(pip_plugin pip)
if (NOT DEFINED ANDROID_PLATFORM) if (NOT DEFINED ANDROID_PLATFORM)
if(microhttpd_FOUND AND curl_FOUND) if (PIP_MANUAL_TEST)
add_executable(pip_test "main.cpp") if(microhttpd_FOUND AND curl_FOUND)
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client) add_executable(pip_test "main.cpp")
if(sodium_FOUND) target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client)
add_executable(pip_cloud_test "main_picloud_test.cpp") if(sodium_FOUND)
target_link_libraries(pip_cloud_test pip_cloud) add_executable(pip_cloud_test "main_picloud_test.cpp")
target_link_libraries(pip_cloud_test pip_cloud)
endif()
endif() endif()
endif() endif()
endif() endif()
@@ -823,6 +827,9 @@ if (PIP_TESTS_LIST)
foreach(_test ${PIP_TESTS_LIST}) foreach(_test ${PIP_TESTS_LIST})
message(" * ${_test}") message(" * ${_test}")
endforeach() endforeach()
if (TESTS_RUN)
message("TESTS_RUN ON -> Run tests before install step")
endif()
else() else()
message(" Tests: skip (tests off)") message(" Tests: skip (tests off)")
endif() endif()

View File

@@ -726,6 +726,7 @@ inline bool piDeleteSafety(T *& pointer) {
//! \~english In this example "Error!" will be printed on every \b false function return. //! \~english In this example "Error!" will be printed on every \b false function return.
//! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции. //! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции.
class PIP_EXPORT PIScopeExitCall { class PIP_EXPORT PIScopeExitCall {
NO_COPY_CLASS(PIScopeExitCall)
public: public:
//! \~\brief //! \~\brief
//! \~english Constructor that takes a function to execute //! \~english Constructor that takes a function to execute
@@ -758,8 +759,6 @@ public:
} }
private: private:
NO_COPY_CLASS(PIScopeExitCall)
std::function<void()> func; std::function<void()> func;
}; };
@@ -768,14 +767,14 @@ private:
//! \~english Inherit from this class to make your class non-trivially copyable. //! \~english Inherit from this class to make your class non-trivially copyable.
//! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым. //! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым.
struct PIP_EXPORT PINonTriviallyCopyable { struct PIP_EXPORT PINonTriviallyCopyable {
PINonTriviallyCopyable() noexcept = default; PINonTriviallyCopyable() = default;
PINonTriviallyCopyable(const PINonTriviallyCopyable &) noexcept = default; PINonTriviallyCopyable(const PINonTriviallyCopyable &) = default;
PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept; PINonTriviallyCopyable(PINonTriviallyCopyable &&) ;
PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) noexcept = default; PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) = default;
PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) noexcept = default; PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) = default;
~PINonTriviallyCopyable() = default; ~PINonTriviallyCopyable() = default;
}; };
inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept = default; inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) = default;
//! \~\brief //! \~\brief

View File

@@ -13,6 +13,7 @@ FetchContent_Declare(
) )
# For Windows: Prevent overriding the parent project's compiler/linker settings # For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(BUILD_GMOCK OFF CACHE BOOL "Build Google Mock" FORCE)
FetchContent_MakeAvailable(googletest) FetchContent_MakeAvailable(googletest)
enable_testing() enable_testing()
@@ -24,13 +25,14 @@ macro(pip_test NAME)
file(GLOB _HDRS "${NAME}/*.h") file(GLOB _HDRS "${NAME}/*.h")
set(_target pip_${NAME}_test) set(_target pip_${NAME}_test)
add_executable(${_target} ${_CPPS} ${_HDRS}) add_executable(${_target} ${_CPPS} ${_HDRS})
target_link_libraries(${_target} pip ${ARGN} gtest_main) target_link_libraries(${_target} pip ${ARGN} gtest_main)
gtest_discover_tests(${_target}) if (TESTS_RUN)
gtest_discover_tests(${_target})
endif()
list(APPEND PIP_TESTS_LIST "${NAME}") list(APPEND PIP_TESTS_LIST "${NAME}")
set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE) set(PIP_TESTS_LIST ${PIP_TESTS_LIST} PARENT_SCOPE)
endmacro() endmacro()
#pip_test(concurrent)
pip_test(math) pip_test(math)
pip_test(core) pip_test(core)
pip_test(piobject) pip_test(piobject)

View File

@@ -33,7 +33,7 @@ TEST(ClientServer, OneClient) {
auto const loop_timeout = 1000_ms; auto const loop_timeout = 1000_ms;
auto s = createServer<false, true>(); auto s = createServer<false, true>();
piMinSleep(); piMinSleep();
auto c = createAndConnectClient<TestClient<false, false>>(); auto c = createAndConnectClient<TestClient<false, false>>();
waitLoop([s]() { return s->clientsCount() > 0; }, loop_timeout); waitLoop([s]() { return s->clientsCount() > 0; }, loop_timeout);
EXPECT_EQ(1, s->clientsCount()); EXPECT_EQ(1, s->clientsCount());
@@ -103,7 +103,7 @@ int getClientsPings(const PIVector<ClientSendThread *> & clients) {
TEST(ClientServer, ManyClients) { TEST(ClientServer, ManyClients) {
auto const loop_timeout = 100_ms; auto const loop_timeout = 1_s;
constexpr int clients_count = 20; constexpr int clients_count = 20;
PIVector<ClientSendThread *> clients; PIVector<ClientSendThread *> clients;
auto s = createServer<false, false, 100_KiB>(); auto s = createServer<false, false, 100_KiB>();
@@ -139,8 +139,9 @@ TEST(ClientServer, ManyClients) {
for (const auto c: clients) { for (const auto c: clients) {
c->startSend(); c->startSend();
} }
loop_timeout.sleep(); waitLoop([&clients]() { return getClientsPings(clients) > clients_count * 2; }, loop_timeout);
EXPECT_TRUE(getClientsPings(clients) > clients_count * 2); EXPECT_TRUE(getClientsPings(clients) > clients_count * 2);
waitLoop([s]() { return getServerPongs(s) > clients_count * 2; }, loop_timeout);
EXPECT_TRUE(getServerPongs(s) > clients_count * 2); EXPECT_TRUE(getServerPongs(s) > clients_count * 2);
piDeleteAllAndClear(clients); piDeleteAllAndClear(clients);
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout); waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
@@ -149,7 +150,7 @@ TEST(ClientServer, ManyClients) {
} }
TEST(ClientServer, DynamicClients) { TEST(ClientServer, DynamicClients) {
auto const loop_timeout = 10_ms; auto const loop_timeout = 3_s;
constexpr int clients_count = 20; constexpr int clients_count = 20;
PIVector<ClientSendThread *> clients; PIVector<ClientSendThread *> clients;
PIMutex clients_mutex; PIMutex clients_mutex;
@@ -199,15 +200,14 @@ TEST(ClientServer, DynamicClients) {
}, },
130_Hz); 130_Hz);
(loop_timeout * clients_count).sleep(); waitLoop([s]() { return s->clientsCount() >= 10; }, loop_timeout);
EXPECT_GE(s->clientsCount(), 10); EXPECT_GE(s->clientsCount(), 10);
deleteThread.stopAndWait(); deleteThread.stopAndWait();
spawnThread.stopAndWait(); spawnThread.stopAndWait();
piDeleteAllAndClear(clients); piDeleteAllAndClear(clients);
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout * clients_count); waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
EXPECT_EQ(0, s->clientsCount()); EXPECT_EQ(0, s->clientsCount());
delete s; delete s;

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,57 +0,0 @@
#include "pithreadnotifier.h"
#include "gtest/gtest.h"
TEST(PIThreadNotifierTest, One) {
PIThreadNotifier n;
int cnt = 0;
PIThread t1(
[&n, &cnt]() {
n.wait();
cnt++;
},
true);
piMSleep(10);
n.notifyOnce();
piMSleep(10);
ASSERT_EQ(cnt, 1);
n.notifyOnce();
piMSleep(10);
ASSERT_EQ(cnt, 2);
}
TEST(PIThreadNotifierTest, Two) {
PIThreadNotifier n;
int cnt1 = 0;
int cnt2 = 0;
int cnt3 = 0;
PIThread t1(
[&n, &cnt1]() {
n.wait();
cnt1++;
piMSleep(2);
},
true);
PIThread t2(
[&n, &cnt2]() {
n.wait();
cnt2++;
piMSleep(2);
},
true);
PIThread t3(
[&n, &cnt3]() {
n.notifyOnce();
cnt3++;
piMSleep(1);
},
true);
piMSleep(20);
t3.stop(true);
piMSleep(100);
t1.stop();
t2.stop();
ASSERT_EQ(cnt1 + cnt2, cnt3);
}

View File

@@ -1,62 +0,0 @@
#ifndef AWRCANFLASHER_TESTUTIL_H
#define AWRCANFLASHER_TESTUTIL_H
#include "pithread.h"
#include <atomic>
/**
* 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.
*/
const int WAIT_THREAD_TIME_MS = 400;
const int THREAD_COUNT = 5;
class TestUtil: public PIObject {
PIOBJECT(TestUtil)
public:
double threadStartTime;
PIThread * thread = new PIThread();
std::atomic_bool isRunning;
std::function<void()> adapterFunctionDefault;
TestUtil(): isRunning(false) {}
bool createThread(const std::function<void()> & fun = nullptr, PIThread * thread_ = nullptr) {
std::function<void()> actualFun = fun == nullptr ? adapterFunctionDefault : fun;
if (thread_ == nullptr) thread_ = thread;
thread_->startOnce([=](void *) {
isRunning = true;
actualFun();
});
return waitThread(thread_);
}
bool waitThread(PIThread * thread_, bool runningStatus = true) {
PITimeMeasurer measurer;
bool isTimeout = !thread_->waitForStart(WAIT_THREAD_TIME_MS);
while (!isRunning) {
isTimeout = WAIT_THREAD_TIME_MS <= measurer.elapsed_m();
if (isTimeout) break;
piUSleep(100);
}
threadStartTime = measurer.elapsed_m();
if (isTimeout) piCout << "Start thread timeout reach!";
if (threadStartTime > 1) {
piCout << "Start time" << threadStartTime << "ms";
} else if (threadStartTime > 0.001) {
piCout << "Start time" << threadStartTime * 1000 << "mcs";
} else {
piCout << "Start time" << threadStartTime * 1000 * 1000 << "ns";
}
return !isTimeout;
}
};
#endif // AWRCANFLASHER_TESTUTIL_H

View File

@@ -467,11 +467,20 @@ bool procDpkg(const PIString & l) {
if (!vs.isEmpty()) { if (!vs.isEmpty()) {
PIStringList lines = vs.split('\n').reverse(); PIStringList lines = vs.split('\n').reverse();
for (auto l: lines) { for (auto l: lines) {
auto sl = l; l = l.left(l.find(":"));
l = l.left(l.find(":")); if (!l.isEmpty() && !l.contains(' ') && !l.endsWith("-cross") && !l.endsWith("-dev")) {
if (!l.isEmpty() && !l.endsWith("-cross") && !l.contains(' ')) all_deps << l; // PICout(true) << "** found \"" << l << "\" in \"" << sl << "\"";
// PICout(true) << "** found \"" << l << "\" in \"" << sl << "\""; all_deps << l;
return true; return true;
}
}
for (auto l: lines) {
l = l.left(l.find(":"));
if (!l.isEmpty() && !l.contains(' ') && !l.endsWith("-cross")) {
// PICout(true) << "** found \"" << l << "\" in \"" << sl << "\"";
all_deps << l;
return true;
}
} }
} }
// piCout << "No dep on" << l; // piCout << "No dep on" << l;