From 4d2bc6ba46272de3498f7b1287ad91ac70cbbe1e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 29 Jul 2013 13:07:39 -0400 Subject: [PATCH] libwinpr-synch: add unit tests, initial waitable timer support --- winpr/libwinpr/synch/CMakeLists.txt | 3 + winpr/libwinpr/synch/event.c | 3 + winpr/libwinpr/synch/test/.gitignore | 3 + winpr/libwinpr/synch/test/CMakeLists.txt | 33 ++++++++++ winpr/libwinpr/synch/test/TestSynchEvent.c | 42 +++++++++++++ winpr/libwinpr/synch/test/TestSynchMutex.c | 21 +++++++ winpr/libwinpr/synch/test/TestSynchSemaphore.c | 21 +++++++ winpr/libwinpr/synch/test/TestSynchWaitableTimer.c | 71 ++++++++++++++++++++++ winpr/libwinpr/synch/timer.c | 24 ++++++-- winpr/libwinpr/synch/wait.c | 21 ++++++- 10 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 winpr/libwinpr/synch/test/.gitignore create mode 100644 winpr/libwinpr/synch/test/CMakeLists.txt create mode 100644 winpr/libwinpr/synch/test/TestSynchEvent.c create mode 100644 winpr/libwinpr/synch/test/TestSynchMutex.c create mode 100644 winpr/libwinpr/synch/test/TestSynchSemaphore.c create mode 100644 winpr/libwinpr/synch/test/TestSynchWaitableTimer.c diff --git a/winpr/libwinpr/synch/CMakeLists.txt b/winpr/libwinpr/synch/CMakeLists.txt index 1554511..885ccc4 100644 --- a/winpr/libwinpr/synch/CMakeLists.txt +++ b/winpr/libwinpr/synch/CMakeLists.txt @@ -64,3 +64,6 @@ endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/synch/event.c b/winpr/libwinpr/synch/event.c index 173afaf..ece585c 100644 --- a/winpr/libwinpr/synch/event.c +++ b/winpr/libwinpr/synch/event.c @@ -82,6 +82,9 @@ HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, WINPR_HANDLE_SET_TYPE(event, HANDLE_TYPE_EVENT); handle = (HANDLE) event; + + if (bInitialState) + SetEvent(handle); } if (!cs.LockSemaphore) diff --git a/winpr/libwinpr/synch/test/.gitignore b/winpr/libwinpr/synch/test/.gitignore new file mode 100644 index 0000000..7107fa9 --- /dev/null +++ b/winpr/libwinpr/synch/test/.gitignore @@ -0,0 +1,3 @@ +TestSynch +TestSynch.c + diff --git a/winpr/libwinpr/synch/test/CMakeLists.txt b/winpr/libwinpr/synch/test/CMakeLists.txt new file mode 100644 index 0000000..4ea150d --- /dev/null +++ b/winpr/libwinpr/synch/test/CMakeLists.txt @@ -0,0 +1,33 @@ + +set(MODULE_NAME "TestSynch") +set(MODULE_PREFIX "TEST_SYNCH") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestSynchEvent.c + TestSynchMutex.c + TestSynchSemaphore.c + TestSynchWaitableTimer.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-synch) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") diff --git a/winpr/libwinpr/synch/test/TestSynchEvent.c b/winpr/libwinpr/synch/test/TestSynchEvent.c new file mode 100644 index 0000000..1262613 --- /dev/null +++ b/winpr/libwinpr/synch/test/TestSynchEvent.c @@ -0,0 +1,42 @@ + +#include +#include + +int TestSynchEvent(int argc, char* argv[]) +{ + HANDLE event; + + event = CreateEvent(NULL, TRUE, TRUE, NULL); + + if (!event) + { + printf("CreateEvent failure\n"); + return -1; + } + + if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) + { + printf("WaitForSingleObject(event, INFINITE) failure\n"); + return -1; + } + + ResetEvent(event); + + if (WaitForSingleObject(event, 0) != WAIT_TIMEOUT) + { + printf("WaitForSingleObject(event, 0) failure\n"); + return -1; + } + + SetEvent(event); + + if (WaitForSingleObject(event, 0) != WAIT_OBJECT_0) + { + printf("WaitForSingleObject(event, 0) failure\n"); + return -1; + } + + CloseHandle(event); + + return 0; +} diff --git a/winpr/libwinpr/synch/test/TestSynchMutex.c b/winpr/libwinpr/synch/test/TestSynchMutex.c new file mode 100644 index 0000000..6d2a5df --- /dev/null +++ b/winpr/libwinpr/synch/test/TestSynchMutex.c @@ -0,0 +1,21 @@ + +#include +#include + +int TestSynchMutex(int argc, char* argv[]) +{ + HANDLE mutex; + + mutex = CreateMutex(NULL, FALSE, NULL); + + if (!mutex) + { + printf("CreateMutex failure\n"); + return -1; + } + + CloseHandle(mutex); + + return 0; +} + diff --git a/winpr/libwinpr/synch/test/TestSynchSemaphore.c b/winpr/libwinpr/synch/test/TestSynchSemaphore.c new file mode 100644 index 0000000..3a9fa16 --- /dev/null +++ b/winpr/libwinpr/synch/test/TestSynchSemaphore.c @@ -0,0 +1,21 @@ + +#include +#include + +int TestSynchSemaphore(int argc, char* argv[]) +{ + HANDLE semaphore; + + semaphore = CreateSemaphore(NULL, 0, 1, NULL); + + if (!semaphore) + { + printf("CreateSemaphore failure\n"); + return -1; + } + + CloseHandle(semaphore); + + return 0; +} + diff --git a/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c b/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c new file mode 100644 index 0000000..472a412 --- /dev/null +++ b/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c @@ -0,0 +1,71 @@ + +#include +#include + +int TestSynchWaitableTimer(int argc, char* argv[]) +{ + HANDLE timer; + LONG period; + LARGE_INTEGER due; + + timer = CreateWaitableTimer(NULL, TRUE, NULL); + + if (!timer) + { + printf("CreateWaitableTimer failure\n"); + return -1; + } + + due.QuadPart = -15000000LL; /* 1.5 seconds */ + + if (!SetWaitableTimer(timer, &due, 0, NULL, NULL, 0)) + { + printf("SetWaitableTimer failure\n"); + return -1; + } + + if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) + { + printf("WaitForSingleObject(timer, INFINITE) failure\n"); + return -1; + } + + printf("Timer Signaled\n"); + + if (WaitForSingleObject(timer, 2000) != WAIT_TIMEOUT) + { + printf("WaitForSingleObject(timer, 2000) failure\n"); + return -1; + } + + due.QuadPart = 0; + + period = 1200; /* 1.2 seconds */ + + if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0)) + { + printf("SetWaitableTimer failure\n"); + return -1; + } + + if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) + { + printf("WaitForSingleObject(timer, INFINITE) failure\n"); + return -1; + } + + printf("Timer Signaled\n"); + + if (WaitForMultipleObjects(1, &timer, FALSE, INFINITE) != WAIT_OBJECT_0) + { + printf("WaitForMultipleObjects(timer, INFINITE) failure\n"); + return -1; + } + + printf("Timer Signaled\n"); + + CloseHandle(timer); + + return 0; +} + diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 46d719c..10ecc19 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -117,7 +117,7 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio #ifdef __linux__ ZeroMemory(&(timer->timeout), sizeof(struct itimerspec)); - if (lpDueTime < 0) + if (lpDueTime->QuadPart < 0) { LONGLONG due = lpDueTime->QuadPart * (-1); @@ -126,24 +126,40 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio seconds = (due / 10000000); nanoseconds = ((due % 10000000) * 100); } + else if (lpDueTime->QuadPart == 0) + { + seconds = nanoseconds = 0; + } else { printf("SetWaitableTimer: implement absolute time\n"); + return FALSE; } - timer->timeout.it_value.tv_sec = seconds; /* seconds */ - timer->timeout.it_value.tv_nsec = nanoseconds; /* nanoseconds */ - if (lPeriod > 0) { timer->timeout.it_interval.tv_sec = (lPeriod / 1000); /* seconds */ timer->timeout.it_interval.tv_nsec = ((lPeriod % 1000) * 1000000); /* nanoseconds */ } + if (lpDueTime->QuadPart != 0) + { + timer->timeout.it_value.tv_sec = seconds; /* seconds */ + timer->timeout.it_value.tv_nsec = nanoseconds; /* nanoseconds */ + } + else + { + timer->timeout.it_value.tv_sec = timer->timeout.it_interval.tv_sec; /* seconds */ + timer->timeout.it_value.tv_nsec = timer->timeout.it_interval.tv_nsec; /* nanoseconds */ + } + status = timerfd_settime(timer->fd, 0, &(timer->timeout), NULL); if (status) + { + printf("SetWaitableTimer timerfd_settime failure: %d\n", status); return FALSE; + } #endif return TRUE; diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index 2c73d48..320b282 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -168,8 +168,8 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) if (timer->fd != -1) { int status; - int length; fd_set rfds; + UINT64 expirations; struct timeval timeout; FD_ZERO(&rfds); @@ -189,6 +189,11 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) if (status != 1) return WAIT_TIMEOUT; + + status = read(timer->fd, (void*) &expirations, sizeof(UINT64)); + + if (status != 8) + return WAIT_TIMEOUT; } else { @@ -304,11 +309,23 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl { if (Type == HANDLE_TYPE_SEMAPHORE) { - int length = read(fd, &length, 1); + int length; + + length = read(fd, &length, 1); if (length != 1) return WAIT_FAILED; } + else if (Type == HANDLE_TYPE_TIMER) + { + int length; + UINT64 expirations; + + length = read(fd, (void*) &expirations, sizeof(UINT64)); + + if (length != 8) + return WAIT_FAILED; + } return (WAIT_OBJECT_0 + index); } -- 2.7.4