Self tests (#3242)
* SelfTests: Added a cEvent stress-test. * cNetwork: Fixed startup event hang. The original code used to hang with a ~ 1:50000 chance, because on Linux the cEvent was destroyed before its "Set()" returned.
This commit is contained in:
parent
4e2c92d15f
commit
1462e4f70e
@ -91,10 +91,8 @@ void cNetworkSingleton::Initialise(void)
|
|||||||
|
|
||||||
// Create the event loop thread:
|
// Create the event loop thread:
|
||||||
m_HasTerminated = false;
|
m_HasTerminated = false;
|
||||||
m_StartupEvent.reset(new cEvent);
|
|
||||||
m_EventLoopThread = std::thread(RunEventLoop, this);
|
m_EventLoopThread = std::thread(RunEventLoop, this);
|
||||||
m_StartupEvent->Wait(); // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too soon would hang, see #3228)
|
m_StartupEvent.Wait(); // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too soon would hang, see #3228)
|
||||||
m_StartupEvent.reset(); // Don't need the cEvent any more, release all its resources
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,8 +167,7 @@ void cNetworkSingleton::SignalizeStartup(evutil_socket_t a_Socket, short a_Event
|
|||||||
{
|
{
|
||||||
auto self = reinterpret_cast<cNetworkSingleton *>(a_Self);
|
auto self = reinterpret_cast<cNetworkSingleton *>(a_Self);
|
||||||
ASSERT(self != nullptr);
|
ASSERT(self != nullptr);
|
||||||
ASSERT(self->m_StartupEvent != nullptr);
|
self->m_StartupEvent.Set();
|
||||||
self->m_StartupEvent->Set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ protected:
|
|||||||
std::thread m_EventLoopThread;
|
std::thread m_EventLoopThread;
|
||||||
|
|
||||||
/** Event that is signalled once the startup is finished and the LibEvent loop is running. */
|
/** Event that is signalled once the startup is finished and the LibEvent loop is running. */
|
||||||
UniquePtr<cEvent> m_StartupEvent;
|
cEvent m_StartupEvent;
|
||||||
|
|
||||||
|
|
||||||
/** Converts LibEvent-generated log events into log messages in MCS log. */
|
/** Converts LibEvent-generated log events into log messages in MCS log. */
|
||||||
|
@ -15,4 +15,5 @@ add_subdirectory(CompositeChat)
|
|||||||
add_subdirectory(HTTP)
|
add_subdirectory(HTTP)
|
||||||
add_subdirectory(LoadablePieces)
|
add_subdirectory(LoadablePieces)
|
||||||
add_subdirectory(Network)
|
add_subdirectory(Network)
|
||||||
|
add_subdirectory(OSSupport)
|
||||||
add_subdirectory(SchematicFileSerializer)
|
add_subdirectory(SchematicFileSerializer)
|
||||||
|
50
tests/OSSupport/CMakeLists.txt
Normal file
50
tests/OSSupport/CMakeLists.txt
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/)
|
||||||
|
|
||||||
|
add_definitions(-DTEST_GLOBALS=1)
|
||||||
|
|
||||||
|
# Create a single OSSupport library that contains all the OSSupport code used in the tests:
|
||||||
|
# Only needed for Windows; Linux already defines the OSSupport lib
|
||||||
|
if (WIN32)
|
||||||
|
set (OSSupport_SRCS
|
||||||
|
${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
|
||||||
|
)
|
||||||
|
set (OSSupport_HDRS
|
||||||
|
${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/OSSupport/Event.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/StringUtils.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/Globals.h
|
||||||
|
)
|
||||||
|
add_library(OSSupport
|
||||||
|
${OSSupport_SRCS}
|
||||||
|
${OSSupport_HDRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Define individual tests:
|
||||||
|
|
||||||
|
# StressEvent: Stress-test the cEvent implementation:
|
||||||
|
add_executable(StressEvent-exe StressEvent.cpp)
|
||||||
|
target_link_libraries(StressEvent-exe OSSupport)
|
||||||
|
add_test(NAME StressEvent-test COMMAND StressEvent-exe)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Put all the tests into a solution folder (MSVC):
|
||||||
|
set_target_properties(
|
||||||
|
StressEvent-exe
|
||||||
|
PROPERTIES FOLDER Tests/OSSupport
|
||||||
|
)
|
||||||
|
set_target_properties(
|
||||||
|
OSSupport
|
||||||
|
PROPERTIES FOLDER Lib
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
60
tests/OSSupport/StressEvent.cpp
Normal file
60
tests/OSSupport/StressEvent.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
// StressEvent.cpp
|
||||||
|
|
||||||
|
// Stress-tests the cEvent implementation
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Number of repetitions of the thread loops. */
|
||||||
|
const int NUM_REPETITIONS = 5000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Forward declarations are needed for clang
|
||||||
|
void runThread(cEvent * a_Event1, cEvent * a_Event2, const char * a_ThreadName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Function that runs in a separate thread, notifies event1 and waits for event2, in a loop, NUM_REPETITIONS times.
|
||||||
|
This basically simulates a producer / consumer pattern with 2 events, one for "queue empty", the other for "queue full". */
|
||||||
|
void runThread(cEvent * a_Event1, cEvent * a_Event2, const char * a_ThreadName)
|
||||||
|
{
|
||||||
|
LOG("Thread %s started", a_ThreadName);
|
||||||
|
for (int i = 0; i < NUM_REPETITIONS; ++i)
|
||||||
|
{
|
||||||
|
// LOGD("%s: Waiting for event %p (%d)", a_ThreadName, a_Event2, i);
|
||||||
|
a_Event2->Wait();
|
||||||
|
// LOGD("%s: Setting event %p (%d)", a_ThreadName, a_Event1, i);
|
||||||
|
a_Event1->SetAll();
|
||||||
|
}
|
||||||
|
LOG("Thread %s finished", a_ThreadName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
LOG("Test started");
|
||||||
|
cEvent event1, event2;
|
||||||
|
event1.Set();
|
||||||
|
std::thread thread1(&runThread, &event1, &event2, "A");
|
||||||
|
std::thread thread2(&runThread, &event2, &event1, "B");
|
||||||
|
thread1.join();
|
||||||
|
thread2.join();
|
||||||
|
LOG("Test finished");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user