update parser (#5)

This commit is contained in:
tompzf
2026-01-16 11:40:02 +01:00
committed by GitHub
parent 5039a37131
commit 234be8917f
115 changed files with 14038 additions and 5380 deletions

View File

@@ -53,16 +53,11 @@ endif()
# Add the communication unittest
add_test(NAME UnitTest_InprocMemTests COMMAND UnitTest_InprocMemTests)
#TODO Shared memory tests during complete rebuild fail on Windows when compiling with MINGW. This is due to race conditions occuring
# only when the system is under heavy load (like during a complete rebuild). The tests have been disabled for the moment and a
# bug report is filed here: https://dev.azure.com/SW4ZF/AZP-074_DivDI_SofDCarResearch/_workitems/edit/608134
if ((NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (NOT WIN32))
# Execute the test
add_custom_command(TARGET UnitTest_InprocMemTests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_InprocMemTests>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_InprocMemTests.xml
VERBATIM
)
endif()
# Shared mem buffer test
add_executable(UnitTest_SharedMemBufferTests
@@ -85,16 +80,11 @@ endif()
# Add the communication unittest
add_test(NAME UnitTest_SharedMemBufferTests COMMAND UnitTest_SharedMemBufferTests)
#TODO Shared memory tests during complete rebuild fail on Windows when compiling with MINGW. This is due to race conditions occuring
# only when the system is under heavy load (like during a complete rebuild). The tests have been disabled for the moment and a
# bug report is filed here: https://dev.azure.com/SW4ZF/AZP-074_DivDI_SofDCarResearch/_workitems/edit/608134
if ((NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (NOT WIN32))
# Execute the test
add_custom_command(TARGET UnitTest_SharedMemBufferTests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_SharedMemBufferTests>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_SharedMemBufferTests.xml
VERBATIM
)
endif()
# Shared mem connection test
add_executable(UnitTest_SharedMemConnectTests
@@ -115,16 +105,11 @@ endif()
# Add the communication unittest
add_test(NAME UnitTest_SharedMemConnectTests COMMAND UnitTest_SharedMemConnectTests)
#TODO Shared memory tests during complete rebuild fail on Windows when compiling with MINGW. This is due to race conditions occuring
# only when the system is under heavy load (like during a complete rebuild). The tests have been disabled for the moment and a
# bug report is filed here: https://dev.azure.com/SW4ZF/AZP-074_DivDI_SofDCarResearch/_workitems/edit/608134
if ((NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (NOT WIN32))
# Execute the test
add_custom_command(TARGET UnitTest_SharedMemConnectTests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_SharedMemConnectTests>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_SharedMemConnectTests.xml
VERBATIM
)
endif()
# Shared mem large data test
@@ -146,16 +131,11 @@ endif()
# Add the communication unittest
add_test(NAME UnitTest_SharedMemLargeDataTests COMMAND UnitTest_SharedMemLargeDataTests)
#TODO Shared memory tests during complete rebuild fail on Windows when compiling with MINGW. This is due to race conditions occuring
# only when the system is under heavy load (like during a complete rebuild). The tests have been disabled for the moment and a
# bug report is filed here: https://dev.azure.com/SW4ZF/AZP-074_DivDI_SofDCarResearch/_workitems/edit/608134
if ((NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (NOT WIN32))
# Execute the test
add_custom_command(TARGET UnitTest_SharedMemLargeDataTests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env TEST_EXECUTION_MODE=CMake "$<TARGET_FILE:UnitTest_SharedMemLargeDataTests>" --gtest_output=xml:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/UnitTest_SharedMemLargeDataTests.xml
VERBATIM
)
endif()
# Build dependencies
add_dependencies(UnitTest_SharedMemTests_App_Repeater core_services)

View File

@@ -4,7 +4,7 @@
#define TIME_TRACKING
#include "../../../sdv_services/ipc_shared_mem/channel_mgnt.cpp"
#include "../../../sdv_services/ipc_shared_mem/connection.cpp"
#include "../../../sdv_services/ipc_shared_mem/connection.cpp" // Tracing is enabled/disabled in the connection.h file
#include "../../../sdv_services/ipc_shared_mem/watchdog.cpp"
#include "../../../sdv_services/ipc_shared_mem/mem_buffer_accessor.cpp"
#include <sstream>
@@ -12,6 +12,7 @@
#include <iostream>
#include <fstream>
#include <queue>
#include <atomic>
#ifdef __GNUC__
#include <unistd.h>
@@ -67,6 +68,8 @@ public:
{
// Send the same data back again (if needed).
std::unique_lock<std::mutex> lock(m_mtxData);
m_nReceiveCallCnt++;
m_nPackageReceiveCnt += seqData.size();
m_queueSendData.push(seqData);
lock.unlock();
@@ -93,7 +96,10 @@ public:
// Send the data back to the sender
if (m_pSend)
{
m_pSend->SendData(seqData);
m_nSendCallCnt++;
}
}
}
@@ -184,6 +190,33 @@ public:
m_threadSender.join();
}
/**
* @brief Get the receive call count.
* @return The amount of receive calls that has been made.
*/
size_t GetReceiveCallCount() const
{
return m_nReceiveCallCnt;
}
/**
* @brief Get the package call count.
* @return The amount of packages that have been received.
*/
size_t GetPackageReceiveCount() const
{
return m_nPackageReceiveCnt;
}
/**
* @brief Get the send call count.
* @return The amount of send calls that has been made.
*/
size_t GetSendCallCount() const
{
return m_nSendCallCnt;
}
private:
sdv::ipc::IDataSend* m_pSend = nullptr; ///< Send interface to implement repeating function.
mutable std::mutex m_mtxData; ///< Protect data access.
@@ -191,9 +224,12 @@ private:
std::condition_variable m_cvDisconnect; ///< Disconnect event.
std::condition_variable m_cvReceived; ///< Receive event.
std::thread m_threadSender; ///< Thread to send data.
bool m_bConnected = false; ///< Set when connected was triggered.
bool m_bDisconnect = false; ///< Set when shutdown was triggered.
bool m_bShutdown = false; ///< Set when shutdown is processed.
std::atomic_bool m_bConnected = false; ///< Set when connected was triggered.
std::atomic_bool m_bDisconnect = false; ///< Set when shutdown was triggered.
std::atomic_bool m_bShutdown = false; ///< Set when shutdown is processed.
std::atomic_size_t m_nReceiveCallCnt = 0; ///< Receive call counter.
std::atomic_size_t m_nPackageReceiveCnt = 0; ///< Package receive counter.
std::atomic_size_t m_nSendCallCnt = 0; ///< Send call counter.
};
@@ -280,15 +316,18 @@ extern "C" int main(int argc, char* argv[])
// Open the control channel endpoint
sdv::TObjectPtr ptrControlConnection;
sdv::ipc::IConnect* pControlConnect = nullptr;
CReceiver receiverControl;
uint64_t uiControlEventCookie = 0;
if (!ssControlConnectString.empty())
{
TRACE(bServer ? "Server" : "Client", ": Start of control channel connection...");
ptrControlConnection = mgntControlMgntChannel.Access(ssControlConnectString);
if (!ptrControlConnection) return -12;
sdv::ipc::IConnect* pControlConnect = ptrControlConnection.GetInterface<sdv::ipc::IConnect>();
pControlConnect = ptrControlConnection.GetInterface<sdv::ipc::IConnect>();
if (!pControlConnect) return -13;
if (!pControlConnect->RegisterStatusEventCallback(&receiverControl)) return -20;
uiControlEventCookie = pControlConnect->RegisterStatusEventCallback(&receiverControl);
if (!uiControlEventCookie) return -20;
if (!pControlConnect->AsyncConnect(&receiverControl)) return -14;
if (!pControlConnect->WaitForConnection(250)) return -5; // Note: Connection should be possible within 250ms.
if (pControlConnect->GetStatus() != sdv::ipc::EConnectStatus::connected) return -15;
@@ -339,8 +378,10 @@ Size = 1024000
// Establish the connection
sdv::ipc::IConnect* pDataConnect = ptrDataConnection.GetInterface<sdv::ipc::IConnect>();
uint64_t uiDataEventCookie = 0;
if (!pDataConnect) return -3;
if (!pDataConnect->RegisterStatusEventCallback(&receiverData)) return -21;
uiDataEventCookie = pDataConnect->RegisterStatusEventCallback(&receiverData);
if (!uiDataEventCookie) return -21;
if (!pDataConnect->AsyncConnect(&receiverData)) return -4;
if (!pDataConnect->WaitForConnection(10000)) return -5; // Note: Connection should be possible within 10000ms.
if (pDataConnect->GetStatus() != sdv::ipc::EConnectStatus::connected) return -5;
@@ -358,12 +399,17 @@ Size = 1024000
// Repeat data until disconnect occurrs (differentiate between forced and not forced to allow two apps to start at the
// same time).
receiverData.WaitUntilDisconnect(bForceTerminate ? 800 : 1600);
std::cout << "App " << (bServer ? "server" : "client") << " connect process disconnecting..." << std::endl;
TRACE("App ", bServer ? "server" : "client", " connect process disconnecting...");
}
// Statistics
TRACE("Receive was called ", receiverData.GetReceiveCallCount(), " times (", receiverData.GetPackageReceiveCount(),
" packages).");
TRACE("Send was called ", receiverData.GetSendCallCount(), " times.");
if (bForceTerminate)
{
std::cout << "Forced termination of app " << (bServer ? "server" : "client") << " connect process..." << std::endl;
TRACE("Forced termination of app ", bServer ? "server" : "client", " connect process...");
#ifdef _MSC_VER
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif
@@ -371,9 +417,11 @@ Size = 1024000
}
// Initiate shutdown
if (pDataConnect && uiDataEventCookie) pDataConnect->UnregisterStatusEventCallback(uiDataEventCookie);
ptrDataConnection.Clear();
mgntDataMgntChannel.Shutdown();
if (mgntDataMgntChannel.GetStatus() != sdv::EObjectStatus::destruction_pending) return -6;
if (pControlConnect && uiControlEventCookie) pControlConnect->UnregisterStatusEventCallback(uiControlEventCookie);
ptrControlConnection.Clear();
mgntControlMgntChannel.Shutdown();
if (mgntControlMgntChannel.GetStatus() != sdv::EObjectStatus::destruction_pending) return -16;

View File

@@ -2,6 +2,7 @@
#include "../../../sdv_services/ipc_shared_mem/in_process_mem_buffer.h"
#include <support/app_control.h>
#include "pattern_gen.h"
#include <atomic>
TEST(InProcessMemoryBufferTest, Instantiate)
{
@@ -26,7 +27,7 @@ TEST(InProcessMemoryBufferTest, TriggerTestRx)
CInProcMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvStart;
std::mutex mtxStart;
@@ -75,7 +76,7 @@ TEST(InProcessMemoryBufferTest, TriggerTestTx)
CInProcMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvStart;
std::mutex mtxStart;
@@ -124,7 +125,7 @@ TEST(InProcessMemoryBufferTest, TriggerTestRxTx)
CInProcMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvSenderStart, cvReceiverStart;
std::mutex mtxReceiverStart;

View File

@@ -5,6 +5,7 @@
#include "../../../sdv_services/ipc_shared_mem/channel_mgnt.cpp"
#include "../../../sdv_services/ipc_shared_mem/watchdog.cpp"
#include "../../../sdv_services/ipc_shared_mem/mem_buffer_accessor.cpp"
#include <cstring>
/**
* @brief Load support modules to publish the needed services.
@@ -28,8 +29,30 @@ extern "C" int wmain(int argc, wchar_t* argv[])
extern "C" int main(int argc, char* argv[])
#endif
{
CProcessWatchdog watchdog;
// Check for the --gtest_repeat option.
bool bRepeatEnabled = false;
for (int iIndex = 0; iIndex < argc; iIndex++)
{
if (!argv[iIndex])
continue;
#if defined(_WIN32) && defined(_UNICODE)
bRepeatEnabled |= std::wcsncmp(argv[iIndex], L"--gtest_repeat", 14) == 0;
#else
bRepeatEnabled |= std::strncmp(argv[iIndex], "--gtest_repeat", 14) == 0;
#endif
}
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
// When repeat is enabled, do not enable the watchdog.
if (bRepeatEnabled)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
else
{
CProcessWatchdog watchdog;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
}

View File

@@ -3,6 +3,7 @@
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
#include "pattern_gen.h"
#include "../../../sdv_services/ipc_shared_mem/mem_buffer_accessor.h"

View File

@@ -2,6 +2,7 @@
#define PATTERN_GEN_H
#include <thread>
#include <atomic>
#include "../../../sdv_services/ipc_shared_mem/mem_buffer_accessor.h"
/**
@@ -43,8 +44,8 @@ public:
private:
CMemBufferAccessorTx& m_raccessorOut; //!< Reference to the output accessor
std::thread m_thread; //!< Processing thread
bool m_bStarted = false; //!< Set by the thread when started.
bool m_bShutdown = false; //!< When set, shutdown the thread.
std::atomic_bool m_bStarted = false; //!< Set by the thread when started.
std::atomic_bool m_bShutdown = false; //!< When set, shutdown the thread.
uint32_t m_uiDelayMs = 0u; //!< Delay (in ms) to insert while processing.
uint32_t m_uiCycleCnt = 0u; //!< Amount of packets
uint32_t m_uiPacketCnt = 0u; //!< Amount of packets

View File

@@ -1,5 +1,6 @@
#include <filesystem>
#include <fstream>
#include <atomic>
#include "gtest/gtest.h"
#include "pattern_gen.h"
#include "../../../sdv_services/ipc_shared_mem/shared_mem_buffer_posix.h"
@@ -28,10 +29,14 @@ TEST(SharedMemoryBufferTest, CreateBuffer)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
appcontrol.Shutdown();
}
@@ -42,12 +47,16 @@ TEST(SharedMemoryBufferTest, TriggerTestRx)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvStart;
std::mutex mtxStart;
@@ -91,12 +100,16 @@ TEST(SharedMemoryBufferTest, TriggerTestTx)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvStart;
std::mutex mtxStart;
@@ -140,16 +153,21 @@ TEST(SharedMemoryBufferTest, TriggerTestRxTx)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
bool bShutdown = false;
std::atomic_bool bShutdown = false;
size_t nCorrectCnt = 0;
std::condition_variable cvSenderStart, cvReceiverStart;
std::mutex mtxReceiverStart;
std::mutex mtxSenderStart;
auto fnWaitForTriggerReceiver = [&]()
{
std::unique_lock<std::mutex> lockReceiver(mtxReceiverStart);
@@ -166,9 +184,6 @@ TEST(SharedMemoryBufferTest, TriggerTestRxTx)
std::unique_lock<std::mutex> lockSender(mtxSenderStart);
lockSender.unlock();
cvSenderStart.notify_all();
std::unique_lock<std::mutex> lockReceiver(mtxReceiverStart);
cvReceiverStart.wait(lockReceiver);
lockReceiver.unlock();
while (!bShutdown)
{
bool bResult = sender.WaitForFreeSpace(200);
@@ -179,14 +194,15 @@ TEST(SharedMemoryBufferTest, TriggerTestRxTx)
};
std::unique_lock<std::mutex> lockStartSender(mtxSenderStart);
std::unique_lock<std::mutex> lockStartReceiver(mtxReceiverStart);
std::thread threadSender(fnWaitForTriggerSender);
std::thread threadReceiver(fnWaitForTriggerReceiver);
cvSenderStart.wait(lockStartSender);
lockStartSender.unlock();
std::unique_lock<std::mutex> lockStartReceiver(mtxReceiverStart);
std::thread threadReceiver(fnWaitForTriggerReceiver);
//CHECKPOINT();
cvReceiverStart.wait(lockStartReceiver);
lockStartReceiver.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(25)); // Needed for the threads to enter their loop.
std::this_thread::sleep_for(std::chrono::milliseconds(25)); // Needed for the threads to enter their loop.
for (size_t n = 0; n < 200; n++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
@@ -210,10 +226,14 @@ TEST(SharedMemoryBufferTest, SimpleSynchronousWriteRead)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
EXPECT_TRUE(sender.TryWrite("HELLO", 6));
auto optPacket = receiver.TryRead();
@@ -229,10 +249,14 @@ TEST(SharedMemoryBufferTest, ReadWithoutSending)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
auto optPacket = receiver.TryRead();
EXPECT_FALSE(optPacket);
@@ -246,10 +270,14 @@ TEST(SharedMemoryBufferTest, RequestReadPacketSize)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
EXPECT_TRUE(sender.TryWrite("HELLO", 5));
@@ -266,10 +294,14 @@ TEST(SharedMemoryBufferTest, FragmentRead)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
EXPECT_TRUE(sender.TryWrite("HELLO", 6));
EXPECT_TRUE(sender.TryWrite("HELLO2", 7));
@@ -296,10 +328,14 @@ TEST(SharedMemoryBufferTest, BufferBoundary)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender(256);
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
// The buffer header has 16 bytes
// Each allocation is 8 bytes header, 6 bytes data and 2 bytes alignment
@@ -353,10 +389,14 @@ TEST(SharedMemoryBufferTest, ReserveCommitAccessReleaseNonChronologicalOrder)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender(256);
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
// Reserve buffers for strings
// The buffer header has 16 bytes
@@ -464,10 +504,14 @@ TEST(SharedMemoryBufferTest, SendReceivePattern)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
CPatternReceiver pattern_inspector(receiver);
CPatternSender pattern_generator(sender);
@@ -501,10 +545,14 @@ TEST(SharedMemoryBufferTest, DelayedSendReceivePattern)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
CPatternReceiver pattern_inspector(receiver);
CPatternSender pattern_generator(sender, 10);
@@ -538,10 +586,14 @@ TEST(SharedMemoryBufferTest, SendDelayedReceivePattern)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx sender;
EXPECT_TRUE(sender.IsValid());
if (!sender.IsValid())
std::cout << "ERROR sender: " << sender.GetError() << std::endl;
ASSERT_TRUE(sender.IsValid());
CSharedMemBufferRx receiver(sender.GetConnectionString());
EXPECT_TRUE(receiver.IsValid());
if (!receiver.IsValid())
std::cout << "ERROR receiver: " << receiver.GetError() << std::endl;
ASSERT_TRUE(receiver.IsValid());
CPatternReceiver pattern_inspector(receiver, 10);
CPatternSender pattern_generator(sender);
@@ -575,9 +627,13 @@ TEST(SharedMemoryBufferTest, SendRepeatReceivePattern)
ASSERT_TRUE(appcontrol.Startup(""));
CSharedMemBufferTx bufferTX;
EXPECT_TRUE(bufferTX.IsValid());
if (!bufferTX.IsValid())
std::cout << "ERROR TX: " << bufferTX.GetError() << std::endl;
ASSERT_TRUE(bufferTX.IsValid());
CSharedMemBufferRx bufferRX;
EXPECT_TRUE(bufferRX.IsValid());
if (!bufferTX.IsValid())
std::cout << "ERROR RX: " << bufferTX.GetError() << std::endl;
ASSERT_TRUE(bufferRX.IsValid());
// The connection string containing the RX and TX strings for the repeater
std::string ssConnectionString = bufferTX.GetConnectionString() + "\n" + bufferRX.GetConnectionString();
@@ -630,9 +686,13 @@ Mode = "Essential")code"));
LoadSupportServices();
CSharedMemBufferTx bufferTX;
EXPECT_TRUE(bufferTX.IsValid());
if (!bufferTX.IsValid())
std::cout << "ERROR TX: " << bufferTX.GetError() << std::endl;
ASSERT_TRUE(bufferTX.IsValid());
CSharedMemBufferRx bufferRX;
EXPECT_TRUE(bufferRX.IsValid());
if (!bufferTX.IsValid())
std::cout << "ERROR RX: " << bufferTX.GetError() << std::endl;
ASSERT_TRUE(bufferRX.IsValid());
// Start process
sdv::process::IProcessControl* pProcessControl = sdv::core::GetObject<sdv::process::IProcessControl>("ProcessControlService");

View File

@@ -10,6 +10,7 @@
#include <algorithm>
#include <condition_variable>
#include <queue>
#include <atomic>
/**
* @brief Receiver helper class.
@@ -21,8 +22,7 @@ public:
* @brief Constructor
* @param[in] bEnableEvent When set, enable the connection event callback interface.
*/
CConnectReceiver(bool bEnableEvent = false) : m_bEnableEvent(bEnableEvent),
m_threadDecoupledSend(&CConnectReceiver::DecoupledSendThread, this)
CConnectReceiver(bool bEnableEvent = false) : m_bEnableEvent(bEnableEvent)
{}
/**
@@ -31,6 +31,8 @@ public:
~CConnectReceiver()
{
m_bShutdown = true;
std::unique_lock<std::mutex> lock(m_mtxData);
lock.unlock();
if (m_threadDecoupledSend.joinable())
m_threadDecoupledSend.join();
}
@@ -64,6 +66,10 @@ public:
// Copy the data
m_seqDataCopy = seqData;
// Start the processing thread if needed
if (!m_threadDecoupledSend.joinable()) m_threadDecoupledSend =
std::thread(&CConnectReceiver::DecoupledSendThread, this);
// Store data into the queue for sending.
m_queueDecoupledSend.push(std::move(seqData));
m_cvDecoupledSend.notify_all();
@@ -170,7 +176,7 @@ private:
std::thread m_threadDecoupledSend; ///< Decoupled send thread.
std::queue<sdv::sequence<sdv::pointer<uint8_t>>> m_queueDecoupledSend; ///< Data queue for sending.
std::condition_variable m_cvDecoupledSend; ///< Trigger decoupled sending.
bool m_bShutdown = false; ///< Shutdown send thread.
std::atomic_bool m_bShutdown = false; ///< Shutdown send thread.
};
/**

View File

@@ -7,10 +7,11 @@
#include <../global/base64.h>
#include <support/sdv_core.h>
#include <support/app_control.h>
#include <support/sdv_test_macro.h>
#include "../../include/sdv_test_macro.h"
#include <interfaces/ipc.h>
#include <algorithm>
#include <queue>
#include <atomic>
/**
* @brief Load support modules to publish the needed services.
@@ -27,8 +28,7 @@ public:
* @brief Constructor
* @param[in] bEnableEvent When set, enable the connection event callback interface.
*/
CLargeDataReceiver(bool bEnableEvent = false) : m_bEnableEvent(bEnableEvent),
m_threadDecoupledSend(&CLargeDataReceiver::DecoupledSendThread, this)
CLargeDataReceiver(bool bEnableEvent = false) : m_bEnableEvent(bEnableEvent)
{}
/**
@@ -37,6 +37,8 @@ public:
~CLargeDataReceiver()
{
m_bShutdown = true;
std::unique_lock<std::mutex> lock(m_mtxData);
lock.unlock();
if (m_threadDecoupledSend.joinable())
m_threadDecoupledSend.join();
}
@@ -73,6 +75,10 @@ public:
for (const sdv::pointer<uint8_t>& rptrData : seqData)
m_queueDataCopy.push(rptrData);
// Start the processing thread if needed
if (!m_threadDecoupledSend.joinable())
m_threadDecoupledSend = std::thread(&CLargeDataReceiver::DecoupledSendThread, this);
// Store data into the queue for sending.
m_queueDecoupledSend.push(std::move(seqData));
m_cvDecoupledSend.notify_all();
@@ -87,7 +93,7 @@ public:
/**
* @brief Wait until the caller hasn't sent anything anymore for 1 second.
*/
void WaitForNoActivity(sdv::IInterfaceAccess* pSender, size_t nCount = 1, uint32_t uiTimeoutMs = 20000)
void WaitForNoActivity(sdv::IInterfaceAccess* pSender, [[maybe_unused]] size_t nCount = 1, uint32_t uiTimeoutMs = 1000)
{
CConnection* pConnection = dynamic_cast<CConnection*>(pSender);
double dTimeout = static_cast<double>(uiTimeoutMs) / 1000.0;
@@ -237,16 +243,16 @@ private:
sdv::ipc::IDataSend* m_pSend = nullptr; ///< Send interface to implement repeating function.
mutable std::mutex m_mtxData; ///< Protect data access.
std::queue<sdv::pointer<uint8_t>> m_queueDataCopy; ///< Copy of the data.
sdv::ipc::EConnectStatus m_eStatus = sdv::ipc::EConnectStatus::uninitialized; ///< Current received status.
std::atomic<sdv::ipc::EConnectStatus> m_eStatus = sdv::ipc::EConnectStatus::uninitialized; ///< Current received status.
bool m_bConnectError = false; ///< Connection error ocurred.
bool m_bCommError = false; ///< Communication error occurred.
bool m_bForcedDisconnect = false; ///< Force disconnect.
size_t m_nCount = 0; ///< Receive counter.
std::atomic_size_t m_nCount = 0; ///< Receive counter.
std::condition_variable m_cvReceived; ///< Receive event.
std::thread m_threadDecoupledSend; ///< Decoupled send thread.
std::queue<sdv::sequence<sdv::pointer<uint8_t>>> m_queueDecoupledSend; ///< Data queue for sending.
std::condition_variable m_cvDecoupledSend; ///< Trigger decoupled sending.
bool m_bShutdown = false; ///< Shutdown send thread.
std::atomic_bool m_bShutdown = false; ///< Shutdown send thread.
};
TEST(SharedMemChannelService, CommunicateOneLargeBlock)
@@ -341,6 +347,7 @@ Size = 1024000
EXPECT_NO_THROW(ptrServerConnection.Clear());
EXPECT_NO_THROW(mgntServer.Shutdown());
EXPECT_NO_THROW(mgntClient.Shutdown());
EXPECT_EQ(mgntServer.GetStatus(), sdv::EObjectStatus::destruction_pending);
@@ -371,6 +378,7 @@ Size = 1024000
EXPECT_NE(sChannelEndpoint.pConnection, nullptr);
EXPECT_FALSE(sChannelEndpoint.ssConnectString.empty());
sdv::TObjectPtr ptrServerConnection(sChannelEndpoint.pConnection);
sdv::TObjectPtr ptrClientConnection = mgntClient.Access(sChannelEndpoint.ssConnectString);
EXPECT_TRUE(ptrServerConnection);
@@ -439,7 +447,7 @@ Size = 1024000
}
EXPECT_EQ(nCnt, 30);
nCnt = 0;
nCnt = 0;
bCorrect = true;
EXPECT_EQ(receiverClient.GetReceiveCount(), 30u);
while (bCorrect)
@@ -467,6 +475,7 @@ Size = 1024000
EXPECT_NO_THROW(ptrServerConnection.Clear());
EXPECT_NO_THROW(mgntServer.Shutdown());
EXPECT_NO_THROW(mgntClient.Shutdown());
EXPECT_EQ(mgntServer.GetStatus(), sdv::EObjectStatus::destruction_pending);
@@ -582,6 +591,7 @@ Size = 1024000
EXPECT_NO_THROW(ptrServerConnection.Clear());
EXPECT_NO_THROW(mgntServer.Shutdown());
EXPECT_NO_THROW(mgntClient.Shutdown());
EXPECT_EQ(mgntServer.GetStatus(), sdv::EObjectStatus::destruction_pending);
@@ -650,6 +660,7 @@ Size = 1024000
// Try send; should succeed, since connected
EXPECT_TRUE(pServerSend->SendData(seqPattern));
receiverServer.WaitForNoActivity(ptrServerConnection);
EXPECT_EQ(receiverServer.GetReceiveCount(), 1u);
auto ptrServerPattern = receiverServer.GetData();
ASSERT_EQ(ptrServerPattern.size(), nCount * sizeof(uint32_t));
pData = reinterpret_cast<uint32_t*>(ptrServerPattern.get());
@@ -730,13 +741,15 @@ Size = 1024000
TRACE("Connection estabished...");
appcontrol.SetRunningMode();
EXPECT_EQ(receiverServer.GetReceiveCount(), 0u);
// Try send; should succeed, since connected
for (size_t nCnt = 0; nCnt < 30; nCnt++)
{
if(SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_TIMING_EXPECT_EQ(pServerSend->SendData(seqPattern), true, sdv::TEST::WARNING_REDUCED);
SDV_EXPECT_EQ_WARN(pServerSend->SendData(seqPattern), true, sdv_test::WARNING_REDUCED);
else
SDV_TIMING_EXPECT_EQ(pServerSend->SendData(seqPattern), true, sdv::TEST::WARNING_ENABLED);
SDV_EXPECT_EQ_WARN(pServerSend->SendData(seqPattern), true, sdv_test::WARNING_ENABLED);
}
receiverServer.WaitForNoActivity(ptrServerConnection, 30);
@@ -744,9 +757,9 @@ Size = 1024000
size_t nCnt = 0;
bool bCorrect = true;
if(SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_TIMING_EXPECT_EQ(receiverServer.GetReceiveCount(), 30u, sdv::TEST::WARNING_REDUCED);
SDV_EXPECT_EQ_WARN(receiverServer.GetReceiveCount(), 30u, sdv_test::WARNING_REDUCED);
else
SDV_TIMING_EXPECT_EQ(receiverServer.GetReceiveCount(), 30u, sdv::TEST::WARNING_ENABLED);
SDV_EXPECT_EQ_WARN(receiverServer.GetReceiveCount(), 30u, sdv_test::WARNING_ENABLED);
while (bCorrect)
{
auto ptrServerPattern = receiverServer.GetData();
@@ -765,9 +778,9 @@ Size = 1024000
}
}
if(SDV_IS_RUNNING_TESTS_WITH_CMAKE_BUILD)
SDV_TIMING_EXPECT_EQ(nCnt, 30, sdv::TEST::WARNING_REDUCED);
SDV_EXPECT_EQ_WARN(nCnt, 30u, sdv_test::WARNING_REDUCED);
else
SDV_TIMING_EXPECT_EQ(nCnt, 30, sdv::TEST::WARNING_ENABLED);
SDV_EXPECT_EQ_WARN(nCnt, 30u, sdv_test::WARNING_ENABLED);
appcontrol.SetConfigMode();