Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development/iptestadministrator #1704

Merged
merged 21 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3793120
[Tests/unit] : Do not depend on 'IPTestAdministrator' if not used
msieben Jun 20, 2024
1f58b65
Merge branch 'master' into development/iptestadministrator
msieben Jun 21, 2024
3eb94a9
Merge branch 'master' into development/iptestadministrator
msieben Jun 24, 2024
0674ec8
Merge branch 'master' into development/iptestadministrator
msieben Jun 24, 2024
dd920b9
Merge branch 'master' into development/iptestadministrator
MFransen69 Jun 25, 2024
c9156cb
Merge branch 'master' into development/iptestadministrator
msieben Jul 8, 2024
5e55df6
[Tests/unit/tests] : Cherry pick 'test_iptestmanager' from developmen…
msieben Jul 15, 2024
9579773
[Tests/unit / Tests/unit/tests] : Improve synchronization usage of 'I…
msieben Jul 15, 2024
8bc4c8a
[core/IPCChannel] : cherry-pick from 'development/ipcchannel_dangling…
msieben Jul 16, 2024
22e7e3b
Tests/unit/core] : align tests with '957977381dfa8137f1475131622390eb…
msieben Jul 16, 2024
346fb6e
[Tests/unit] : Improve synchronization with premature signalling
msieben Jul 22, 2024
3696efa
[Tests/unit] : Add test cases to 'Tests/unit/tests/test_iptestmanager…
msieben Jul 22, 2024
7c9a286
[Tests/unit/core] : align tests with '346fb6ec2a0da5058f7a581190e63c7…
msieben Jul 22, 2024
a7ef6b2
Merge branch 'master' into development/iptestadministrator
msieben Jul 24, 2024
3737343
[Tests/unit/core] : amend '7c9a286d1398de9f2b470b02bb58596120f0d8c9'
msieben Jul 25, 2024
9c470c7
[Tests/core/unit] : cherry pick from 'development/messageunit'
msieben Jul 26, 2024
be5e514
[Tests/unit/core] : Use 'IPTestAdministrator' for 'PopMessageShouldRe…
msieben Jul 26, 2024
a9f6728
[Tests/unit/IPTestAdministrator] : Try to prevent to leak shared memo…
msieben Aug 5, 2024
0bab1ba
Merge branch 'master' into development/iptestadministrator
msieben Aug 5, 2024
4c79de7
Revert "[core/IPCChannel] : cherry-pick from 'development/ipcchannel_…
msieben Aug 6, 2024
3505779
[Tests/unit/core] : disable 'test_ipc'
msieben Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
370 changes: 167 additions & 203 deletions Tests/unit/IPTestAdministrator.cpp

Large diffs are not rendered by default.

70 changes: 35 additions & 35 deletions Tests/unit/IPTestAdministrator.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,51 @@

#include <string>
#include <time.h>
#include <atomic>
#include <functional>

#ifndef MODULE_NAME
#include "Module.h"
#endif

#include <core/core.h>

#ifndef __LINUX__
static_assert(false, "Only LINUX is supported");
#endif

class IPTestAdministrator
{
private:
static constexpr uint32_t MaxWaitTime = 2; // In seconds
public :

using Callback = std::function<void (IPTestAdministrator&)>;

IPTestAdministrator(Callback /* executed by parent */, Callback /* executed by child */, const uint32_t initHandshakeValue, const uint32_t waitTime /* seconds */);
~IPTestAdministrator();

public:
typedef void (*OtherSideMain)(IPTestAdministrator & testAdmin);
IPTestAdministrator(const IPTestAdministrator&) = delete;
const IPTestAdministrator& operator=(const IPTestAdministrator&) = delete;

IPTestAdministrator(OtherSideMain otherSideMain, const uint32_t waitTime = MaxWaitTime);
IPTestAdministrator(OtherSideMain otherSideMain, void* data, const uint32_t waitTime = MaxWaitTime);
~IPTestAdministrator();
uint32_t Wait(uint32_t expectedHandshakeValue) const;
uint32_t Signal(uint32_t expectedNextHandshakeValue, uint8_t maxRetries = 0);

void ForkChildProcess(OtherSideMain otherSideMain);
// Method to sync the two test processes.
bool Sync(const std::string & str);
void WaitForChildCompletion();
uint32_t WaitTimeDivisor() const {
return _waitTimeDivisor;
}

void* Data() { return m_data; }
private:
static const uint32_t m_messageBufferSize = 1024;
private :

struct SharedData
{
pthread_mutex_t m_stateMutex; // Guards state (are we first or second?)
pthread_cond_t m_waitingForSecondCond; // Used to wait for second
pthread_mutex_t m_waitingForSecondCondMutex;
bool m_waitingForOther; // whether we are waiting for the other side or not
bool m_messageTheSame; // whether message comparison was a success
char m_message[m_messageBufferSize]; // Expected message string
bool m_backToNormal;
pthread_cond_t m_waitingForNormalCond; // To wait for first to restore state to normal
pthread_mutex_t m_waitingForNormalCondMutex;
};
struct SharedData
{
// std::atomic integral> has standard layout!
// A pointer may be converted to a pointer of the first non-static data element with reinterpret_cast
std::atomic<uint32_t> handshakeValue;
};

SharedData * m_sharedData;
pid_t m_childPid; // Set if we are parent processs.
void* m_data;
uint32_t m_maxWaitTime; // In seconds.
constexpr static uint32_t _waitTimeDivisor = 10;

const char * GetProcessName() const;
void TimedLock(pthread_mutex_t * mutex, const std::string & str);
void TimedWait(pthread_cond_t * cond, pthread_mutex_t * mutex, const std::string & str);

void FillTimeOut(timespec & timeSpec);
SharedData* _sharedData;
int _shm_id;
pid_t _pid;
uint32_t _waitTime; // Seconds
};
75 changes: 59 additions & 16 deletions Tests/unit/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

set(TEST_RUNNER_NAME "Thunder_test_core")



if(LINUX)
# IPTestAdministrator only supported on LINUX platform
add_executable(${TEST_RUNNER_NAME}
../IPTestAdministrator.cpp
#test_cyclicbuffer.cpp
Expand All @@ -28,12 +28,12 @@ add_executable(${TEST_RUNNER_NAME}
test_doorbell.cpp
test_enumerate.cpp
test_event.cpp
test_hex2strserialization.cpp
test_filesystem.cpp
test_frametype.cpp
test_hash.cpp
test_hex2strserialization.cpp
#test_ipc.cpp
test_ipcclient.cpp
test_ipc.cpp
test_iso639.cpp
test_iterator.cpp
test_jsonparser.cpp
Expand Down Expand Up @@ -79,20 +79,63 @@ add_executable(${TEST_RUNNER_NAME}
test_websockettext.cpp
test_workerpool.cpp
test_xgetopt.cpp
test_message_dispatcher.cpp
)
#[[ if(MESSAGING)
target_sources(${TEST_RUNNER_NAME} PRIVATE test_message_unit.cpp)
target_link_libraries(${TEST_RUNNER_NAME}
ThunderMessaging
)
#[[
target_sources(${TEST_RUNNER_NAME} PRIVATE test_message_unit.cpp)
target_link_libraries(${TEST_RUNNER_NAME}
ThunderMessaging
)
]]
else()
target_sources(${TEST_RUNNER_NAME} PRIVATE test_tracing.cpp)
target_link_libraries(${TEST_RUNNER_NAME}
ThunderTracing
)
endif() ]]
add_executable(${TEST_RUNNER_NAME}
test_databuffer.cpp
test_dataelement.cpp
test_dataelementfile.cpp
test_enumerate.cpp
test_event.cpp
test_filesystem.cpp
test_frametype.cpp
test_hash.cpp
test_hex2strserialization.cpp
test_iso639.cpp
test_iterator.cpp
test_jsonparser.cpp
test_keyvalue.cpp
test_library.cpp
test_lockablecontainer.cpp
test_measurementtype.cpp
test_memberavailability.cpp
# test_message_dispatcher.cpp
test_messageException.cpp
test_networkinfo.cpp
test_nodeid.cpp
test_numbertype.cpp
test_optional.cpp
test_parser.cpp
test_portability.cpp
test_processinfo.cpp
test_queue.cpp
test_rangetype.cpp
test_readwritelock.cpp
test_rectangle.cpp
test_semaphore.cpp
test_singleton.cpp
test_statetrigger.cpp
test_stopwatch.cpp
test_synchronize.cpp
test_systeminfo.cpp
test_textfragment.cpp
test_textreader.cpp
test_thread.cpp
test_threadpool.cpp
test_time.cpp
test_timer.cpp
test_tristate.cpp
#test_valuerecorder.cpp
test_workerpool.cpp
test_xgetopt.cpp
)
endif()

set_source_files_properties(test_systeminfo.cpp PROPERTIES COMPILE_OPTIONS "-fexceptions")

Expand Down
8 changes: 4 additions & 4 deletions Tests/unit/core/test_cyclicbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
* limitations under the License.
*/

#ifdef __APPLE__
#include <time.h>
#endif

#include <gtest/gtest.h>

#ifndef MODULE_NAME
Expand All @@ -27,10 +31,6 @@

#include "../IPTestAdministrator.h"

#ifdef __APPLE__
#include <time.h>
#endif

namespace Thunder {
namespace Tests {
namespace Core {
Expand Down
103 changes: 58 additions & 45 deletions Tests/unit/core/test_doorbell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,74 +33,87 @@ namespace Core {

TEST(Core_DoorBell, simpleSet)
{
std::string fileName {"/tmp/doorbell01"};
auto lambdaFunc = [fileName] (IPTestAdministrator & testAdmin) {
constexpr uint32_t initHandshakeValue = 0, maxWaitTime = 4, maxWaitTimeMs = 4000, maxInitTime = 2000;
constexpr uint8_t maxRetries = 1;

const std::string fileName {"/tmp/doorbell01"};

IPTestAdministrator::Callback callback_child = [&](IPTestAdministrator& testAdmin) {
::Thunder::Core::DoorBell doorBell(fileName.c_str());

EXPECT_EQ(doorBell.Wait(::Thunder::Core::infinite), ::Thunder::Core::ERROR_NONE);
if (doorBell.Wait(::Thunder::Core::infinite) == ::Thunder::Core::ERROR_NONE) {
doorBell.Acknowledge();
testAdmin.Sync("First ring");
}

EXPECT_EQ(doorBell.Wait(::Thunder::Core::infinite), ::Thunder::Core::ERROR_NONE);
if (doorBell.Wait(::Thunder::Core::infinite) == ::Thunder::Core::ERROR_NONE) {
doorBell.Acknowledge();
testAdmin.Sync("Second ring");
}
ASSERT_EQ(doorBell.Wait(maxWaitTimeMs), ::Thunder::Core::ERROR_NONE);
doorBell.Acknowledge();

ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);

ASSERT_EQ(doorBell.Wait(maxWaitTimeMs), ::Thunder::Core::ERROR_NONE);
doorBell.Acknowledge();

ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);

doorBell.Relinquish();
};

static std::function<void (IPTestAdministrator&)> lambdaVar = lambdaFunc;

IPTestAdministrator::OtherSideMain otherSide = [](IPTestAdministrator& testAdmin ) { lambdaVar(testAdmin); };
IPTestAdministrator::Callback callback_parent = [&](IPTestAdministrator& testAdmin) {
// a small delay so the child can be set up
SleepMs(maxInitTime);

IPTestAdministrator testAdmin(otherSide);
{
::Thunder::Core::DoorBell doorBell(fileName.c_str());
::SleepMs(10);

doorBell.Ring();
testAdmin.Sync("First ring");
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);

doorBell.Ring();
testAdmin.Sync("Second ring");
}
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);
};

IPTestAdministrator testAdmin(callback_parent, callback_child, initHandshakeValue, maxWaitTime);

// Code after this line is executed by both parent and child

::Thunder::Core::Singleton::Dispose();
}

TEST(Core_DoorBell, simpleSetReversed)
{

constexpr uint32_t initHandshakeValue = 0, maxWaitTime = 4, maxWaitTimeMs = 4000, maxInitTime = 2000;
constexpr uint8_t maxRetries = 1;

std::string fileName {"/tmp/doorbell02"};
auto lambdaFunc = [fileName] (IPTestAdministrator & testAdmin) {
const std::string fileName {"/tmp/doorbell02"};

IPTestAdministrator::Callback callback_child = [&](IPTestAdministrator& testAdmin) {
::Thunder::Core::DoorBell doorBell(fileName.c_str());
::SleepMs(10);

// A small delay so the child can be set up
SleepMs(maxInitTime);

doorBell.Ring();
testAdmin.Sync("First ring");
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);

doorBell.Ring();
testAdmin.Sync("Second ring");
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);
};

static std::function<void (IPTestAdministrator&)> lambdaVar = lambdaFunc;
IPTestAdministrator::Callback callback_parent = [&](IPTestAdministrator& testAdmin) {
::Thunder::Core::DoorBell doorBell(fileName.c_str());

IPTestAdministrator::OtherSideMain otherSide = [](IPTestAdministrator& testAdmin ) { lambdaVar(testAdmin); };
ASSERT_EQ(doorBell.Wait(maxWaitTimeMs), ::Thunder::Core::ERROR_NONE);
doorBell.Acknowledge();

ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);

ASSERT_EQ(doorBell.Wait(maxWaitTimeMs), ::Thunder::Core::ERROR_NONE);
doorBell.Acknowledge();

ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);

IPTestAdministrator testAdmin(otherSide);
{
::Thunder::Core::DoorBell doorBell(fileName.c_str());
EXPECT_EQ(doorBell.Wait(::Thunder::Core::infinite), ::Thunder::Core::ERROR_NONE);
if (doorBell.Wait(::Thunder::Core::infinite) == ::Thunder::Core::ERROR_NONE) {
doorBell.Acknowledge();
testAdmin.Sync("First ring");
}

EXPECT_EQ(doorBell.Wait(::Thunder::Core::infinite), ::Thunder::Core::ERROR_NONE);
if (doorBell.Wait(::Thunder::Core::infinite) == ::Thunder::Core::ERROR_NONE) {
doorBell.Acknowledge();
testAdmin.Sync("Second ring");
}
doorBell.Relinquish();
}
};

IPTestAdministrator testAdmin(callback_parent, callback_child, initHandshakeValue, maxWaitTime);

// Code after this line is executed by both parent and child

::Thunder::Core::Singleton::Dispose();
}

Expand Down
Loading