瀏覽代碼

use deterministic clock for unit tests

Julius Pfrommer 7 年之前
父節點
當前提交
9c003b37dc

+ 26 - 12
CMakeLists.txt

@@ -187,6 +187,7 @@ set(exported_headers ${PROJECT_BINARY_DIR}/src_generated/ua_config.h
                      ${PROJECT_SOURCE_DIR}/plugins/ua_network_tcp.h
                      ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.h
                      ${PROJECT_SOURCE_DIR}/plugins/ua_config_standard.h)
+
 set(internal_headers ${PROJECT_SOURCE_DIR}/deps/queue.h
                      ${PROJECT_SOURCE_DIR}/deps/pcg_basic.h
                      ${PROJECT_SOURCE_DIR}/deps/libc_time.h
@@ -207,6 +208,8 @@ set(internal_headers ${PROJECT_SOURCE_DIR}/deps/queue.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_server_internal.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_services.h
                      ${PROJECT_SOURCE_DIR}/src/client/ua_client_internal.h)
+
+# TODO: make client optional
 set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_SOURCE_DIR}/src/ua_types_encoding_binary.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
@@ -240,14 +243,14 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_SOURCE_DIR}/src/client/ua_client.c
                 ${PROJECT_SOURCE_DIR}/src/client/ua_client_highlevel.c
                 ${PROJECT_SOURCE_DIR}/src/client/ua_client_highlevel_subscriptions.c
-                # plugins and dependencies
-                ${PROJECT_SOURCE_DIR}/plugins/ua_network_tcp.c
-                ${PROJECT_SOURCE_DIR}/plugins/ua_clock.c
-                ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
-                ${PROJECT_SOURCE_DIR}/plugins/ua_config_standard.c
+                # dependencies
                 ${PROJECT_SOURCE_DIR}/deps/libc_time.c
                 ${PROJECT_SOURCE_DIR}/deps/pcg_basic.c)
-                ##TODO: make client stuff optional
+
+set(default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_network_tcp.c
+                           ${PROJECT_SOURCE_DIR}/plugins/ua_clock.c
+                           ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
+                           ${PROJECT_SOURCE_DIR}/plugins/ua_config_standard.c)
 
 if(UA_ENABLE_EMBEDDED_LIBC)
   list(APPEND lib_sources ${PROJECT_SOURCE_DIR}/deps/libc_string.c)
@@ -338,13 +341,13 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.h
                    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py
                            ${OPEN62541_VER_COMMIT} ${CMAKE_CURRENT_BINARY_DIR}/open62541.h ${exported_headers}
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py
-                           ${exported_headers}
-                           ${internal_headers})
+                           ${exported_headers} ${internal_headers})
 
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.c
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py
-                           ${OPEN62541_VER_COMMIT} ${CMAKE_CURRENT_BINARY_DIR}/open62541.c ${internal_headers} ${lib_sources}
+                           ${OPEN62541_VER_COMMIT} ${CMAKE_CURRENT_BINARY_DIR}/open62541.c
+                           ${internal_headers} ${lib_sources} ${default_plugin_sources}
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${internal_headers} ${lib_sources})
 
 ADD_CUSTOM_TARGET(open625451_amalgamation DEPENDS ${PROJECT_BINARY_DIR}/open62541.h
@@ -374,19 +377,27 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/nodeset.h ${PROJEC
 if(UA_ENABLE_AMALGAMATION)
     add_library(open62541-object OBJECT ${PROJECT_BINARY_DIR}/open62541.c ${PROJECT_BINARY_DIR}/open62541.h)
     target_include_directories(open62541-object PRIVATE ${PROJECT_BINARY_DIR})
+    add_library(open62541 $<TARGET_OBJECTS:open62541-object>)
+
     if(UA_COMPILE_AS_CXX)
         set_source_files_properties(${PROJECT_BINARY_DIR}/open62541.c PROPERTIES LANGUAGE CXX)
     endif()
 else()
     add_definitions(-DUA_NO_AMALGAMATION)
     add_library(open62541-object OBJECT ${lib_sources} ${internal_headers} ${exported_headers})
-    target_include_directories(open62541-object PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/plugins)
+    target_include_directories(open62541-object PRIVATE ${PROJECT_SOURCE_DIR}/src)
+
+    add_library(open62541-plugins OBJECT ${default_plugin_sources} ${exported_headers})
+    target_include_directories(open62541-plugins PRIVATE ${PROJECT_SOURCE_DIR}/plugins)
+    target_include_directories(open62541-plugins PRIVATE ${PROJECT_BINARY_DIR}/src_generated)
+
+    add_library(open62541 $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-plugins>)
 
     if(UA_COMPILE_AS_CXX)
         set_source_files_properties(${lib_sources} PROPERTIES LANGUAGE CXX)
+        set_source_files_properties(${default_plugin_sources} PROPERTIES LANGUAGE CXX)
     endif()
 endif()
-add_library(open62541 $<TARGET_OBJECTS:open62541-object>)
 target_link_libraries(open62541 ${open62541_LIBRARIES})
 
 target_compile_definitions(open62541-object PRIVATE -DUA_DYNAMIC_LINKING_EXPORT)
@@ -411,7 +422,10 @@ if(UA_BUILD_EXAMPLES)
 endif()
 
 if(UA_BUILD_UNIT_TESTS)
-    target_compile_definitions(open62541-object PRIVATE UA_BUILD_UNIT_TESTS) # Export some internal functions
+    if(UA_ENABLE_AMALGAMATION)
+        # Cannot compile tests with amalgamation. Amalgamation uses the default plugins, not the testing plugins
+        message(FATAL_ERROR "Unit tests cannot be generated with source amalgamation enabled")
+    endif()
     enable_testing()
     add_subdirectory(tests)
 endif()

+ 20 - 28
examples/CMakeLists.txt

@@ -3,12 +3,12 @@ include_directories(${PROJECT_SOURCE_DIR}/plugins)
 include_directories(${PROJECT_BINARY_DIR})
 
 if(UA_ENABLE_AMALGAMATION)
-    include_directories(${PROJECT_BINARY_DIR}) # contain open62541.h
+    include_directories(${PROJECT_BINARY_DIR}) # contains open62541.h
 else()
     add_definitions(-DUA_NO_AMALGAMATION)
 endif()
 
-list(APPEND LIBS ${open62541_LIBRARIES})
+list(APPEND LIBS open62541 ${open62541_LIBRARIES})
 if(NOT WIN32)
   list(APPEND LIBS pthread)
   if (NOT APPLE)
@@ -21,49 +21,41 @@ if(UA_ENABLE_MULTITHREADING)
   list(APPEND LIBS urcu-cds urcu urcu-common)
 endif(UA_ENABLE_MULTITHREADING)
 
-
-set(STATIC_OBJECTS $<TARGET_OBJECTS:open62541-object>)
-if(WIN32 AND BUILD_SHARED_LIBS)
-	# on windows the .dll.a file has to be used for the linker
-	list(APPEND LIBS open62541)
-	set(STATIC_OBJECTS "")
-endif()
-
 #############
 # Tutorials #
 #############
 
-add_executable(tutorial_datatypes tutorial_datatypes.c ${STATIC_OBJECTS})
+add_executable(tutorial_datatypes tutorial_datatypes.c)
 add_dependencies(tutorial_datatypes open625451_amalgamation)
 target_link_libraries(tutorial_datatypes ${LIBS})
 
-add_executable(tutorial_server_firststeps tutorial_server_firststeps.c ${STATIC_OBJECTS})
+add_executable(tutorial_server_firststeps tutorial_server_firststeps.c)
 add_dependencies(tutorial_server_firststeps open625451_amalgamation)
 target_link_libraries(tutorial_server_firststeps ${LIBS})
 
-add_executable(tutorial_server_variable tutorial_server_variable.c ${STATIC_OBJECTS})
+add_executable(tutorial_server_variable tutorial_server_variable.c)
 add_dependencies(tutorial_server_variable open625451_amalgamation)
 target_link_libraries(tutorial_server_variable ${LIBS})
 
-add_executable(tutorial_server_datasource tutorial_server_datasource.c ${STATIC_OBJECTS})
+add_executable(tutorial_server_datasource tutorial_server_datasource.c)
 add_dependencies(tutorial_server_datasource open625451_amalgamation)
 target_link_libraries(tutorial_server_datasource ${LIBS})
 
-add_executable(tutorial_server_variabletype tutorial_server_variabletype.c ${STATIC_OBJECTS})
+add_executable(tutorial_server_variabletype tutorial_server_variabletype.c)
 add_dependencies(tutorial_server_variabletype open625451_amalgamation)
 target_link_libraries(tutorial_server_variabletype ${LIBS})
 
-add_executable(tutorial_server_object tutorial_server_object.c ${STATIC_OBJECTS})
+add_executable(tutorial_server_object tutorial_server_object.c)
 add_dependencies(tutorial_server_object open625451_amalgamation)
 target_link_libraries(tutorial_server_object ${LIBS})
 
 if(UA_ENABLE_METHODCALLS)
-  add_executable(tutorial_server_method tutorial_server_method.c ${STATIC_OBJECTS})
+  add_executable(tutorial_server_method tutorial_server_method.c)
   add_dependencies(tutorial_server_method open625451_amalgamation)
   target_link_libraries(tutorial_server_method ${LIBS})
 endif()
 
-add_executable(tutorial_client_firststeps tutorial_client_firststeps.c ${STATIC_OBJECTS})
+add_executable(tutorial_client_firststeps tutorial_client_firststeps.c)
 add_dependencies(tutorial_client_firststeps open625451_amalgamation)
 target_link_libraries(tutorial_client_firststeps ${LIBS})
 
@@ -71,11 +63,11 @@ target_link_libraries(tutorial_client_firststeps ${LIBS})
 # Example Server #
 ##################
 
-add_executable(server server.c ${STATIC_OBJECTS})
+add_executable(server server.c)
 target_link_libraries(server ${LIBS})
 
 if(UA_ENABLE_NONSTANDARD_UDP)
-  add_executable(server_udp server_udp.c ${STATIC_OBJECTS} ${PROJECT_SOURCE_DIR}/plugins/ua_network_udp.c)
+  add_executable(server_udp server_udp.c ${PROJECT_SOURCE_DIR}/plugins/ua_network_udp.c)
   target_link_libraries(server_udp ${LIBS})
 endif()
 
@@ -83,28 +75,28 @@ endif()
 # Example Client #
 ##################
 
-add_executable(client client.c ${STATIC_OBJECTS})
+add_executable(client client.c)
 target_link_libraries(client ${LIBS})
 
 ####################
 # Feature Examples #
 ####################
 
-add_executable(server_mainloop server_mainloop.c ${STATIC_OBJECTS})
+add_executable(server_mainloop server_mainloop.c)
 target_link_libraries(server_mainloop ${LIBS})
 
-add_executable(server_instantiation server_instantiation.c ${STATIC_OBJECTS})
+add_executable(server_instantiation server_instantiation.c)
 target_link_libraries(server_instantiation ${LIBS})
 
-add_executable(server_repeated_job server_repeated_job.c ${STATIC_OBJECTS})
+add_executable(server_repeated_job server_repeated_job.c)
 target_link_libraries(server_repeated_job ${LIBS})
 
-add_executable(server_inheritance server_inheritance.c ${STATIC_OBJECTS})
+add_executable(server_inheritance server_inheritance.c)
 target_link_libraries(server_inheritance ${LIBS})
 
 if(NOT BUILD_SHARED_LIBS AND UA_BUILD_EXAMPLES_NODESET_COMPILER)
   # needs internal methods which are not exported in the dynamic lib
-  add_executable(server_nodeset server_nodeset.c ${PROJECT_BINARY_DIR}/src_generated/nodeset.c ${STATIC_OBJECTS})
+  add_executable(server_nodeset server_nodeset.c ${PROJECT_BINARY_DIR}/src_generated/nodeset.c)
   target_link_libraries(server_nodeset ${LIBS})
   target_include_directories(server_nodeset PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/deps) # needs an internal header
 endif()
@@ -118,13 +110,13 @@ if(UA_BUILD_SELFSIGNED_CERTIFICATE)
                              
   add_custom_target(selfsigned ALL DEPENDS server_cert.der ca.crt)
 
-  add_executable(server_certificate server_certificate.c ${STATIC_OBJECTS} server_cert.der ca.crt)
+  add_executable(server_certificate server_certificate.c server_cert.der ca.crt)
   target_link_libraries(server_certificate ${LIBS})
 endif()
 
 if(NOT BUILD_SHARED_LIBS)
   # needs internal methods which are not exported in the dynamic lib
-  add_executable(server_readspeed server_readspeed.c ${STATIC_OBJECTS})
+  add_executable(server_readspeed server_readspeed.c)
   target_include_directories(server_readspeed PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/deps) # needs an internal header
   target_link_libraries(server_readspeed ${LIBS})
 endif()

+ 30 - 17
tests/CMakeLists.txt

@@ -5,12 +5,25 @@ include_directories(${PROJECT_SOURCE_DIR}/plugins)
 include_directories(${PROJECT_BINARY_DIR}/src_generated)
 include_directories(${CHECK_INCLUDE_DIRS})
 
+# Load CMake Packages
 find_package(Check REQUIRED)
 find_package(Threads REQUIRED)
 if(UA_ENABLE_VALGRIND_UNIT_TESTS)
     find_package(Valgrind REQUIRED)
 endif()
 
+# Build the plugins used for testing
+set(test_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_network_tcp.c
+                        ${PROJECT_SOURCE_DIR}/tests/testing_clock.c
+                        ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
+                        ${PROJECT_SOURCE_DIR}/plugins/ua_config_standard.c
+                        ${PROJECT_SOURCE_DIR}/tests/testing_clock.c)
+
+add_library(open62541-testplugins OBJECT ${test_plugin_sources})
+add_dependencies(open62541-testplugins open62541)
+target_include_directories(open62541-testplugins PRIVATE ${PROJECT_SOURCE_DIR}/plugins)
+target_include_directories(open62541-testplugins PRIVATE ${PROJECT_BINARY_DIR}/src_generated)
+
 set(LIBS ${CHECK_LIBRARIES} ${open62541_LIBRARIES})
 if(NOT WIN32)
   list(APPEND LIBS pthread m)
@@ -41,57 +54,57 @@ endmacro()
 # the unit test are built directly on the open62541 object files. so they can
 # access symbols that are hidden/not exported to the shared library
 
-add_executable(check_types_builtin check_types_builtin.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_types_builtin check_types_builtin.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_types_builtin ${LIBS})
 add_test_valgrind(types_builtin ${CMAKE_CURRENT_BINARY_DIR}/check_types_builtin)
 
-add_executable(check_types_memory check_types_memory.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_types_memory check_types_memory.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_types_memory ${LIBS})
 add_test_valgrind(types_memory ${CMAKE_CURRENT_BINARY_DIR}/check_types_memory)
 
-add_executable(check_types_range check_types_range.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_types_range check_types_range.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_types_range ${LIBS})
 add_test_valgrind(types_range ${CMAKE_CURRENT_BINARY_DIR}/check_types_range)
 
-add_executable(check_chunking check_chunking.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_chunking check_chunking.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_chunking ${LIBS})
 add_test_valgrind(chunking ${CMAKE_CURRENT_BINARY_DIR}/check_chunking)
 
-add_executable(check_utils check_utils.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_utils check_utils.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_utils ${LIBS})
 add_test_valgrind(check_utils ${CMAKE_CURRENT_BINARY_DIR}/check_utils)
 
 # Test Server
 
-add_executable(check_services_view check_services_view.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_services_view check_services_view.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_view ${LIBS})
 add_test_valgrind(services_view ${CMAKE_CURRENT_BINARY_DIR}/check_services_view)
 
-add_executable(check_services_attributes check_services_attributes.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_services_attributes check_services_attributes.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_attributes ${LIBS})
 add_test_valgrind(services_attributes ${CMAKE_CURRENT_BINARY_DIR}/check_services_attributes)
 
-add_executable(check_services_nodemanagement check_services_nodemanagement.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_services_nodemanagement check_services_nodemanagement.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_nodemanagement ${LIBS})
 add_test_valgrind(services_nodemanagement ${CMAKE_CURRENT_BINARY_DIR}/check_services_nodemanagement)
 
-add_executable(check_services_subscriptions check_services_subscriptions.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_services_subscriptions check_services_subscriptions.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_subscriptions ${LIBS})
 add_test_valgrind(check_services_subscriptions ${CMAKE_CURRENT_BINARY_DIR}/check_services_subscriptions)
 
-add_executable(check_nodestore check_nodestore.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_nodestore check_nodestore.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_nodestore ${LIBS})
 add_test_valgrind(nodestore ${CMAKE_CURRENT_BINARY_DIR}/check_nodestore)
 
-add_executable(check_session check_session.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_session check_session.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_session ${LIBS})
 add_test_valgrind(session ${CMAKE_CURRENT_BINARY_DIR}/check_session)
 
-add_executable(check_server_jobs check_server_jobs.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_server_jobs check_server_jobs.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_server_jobs ${LIBS})
 add_test_valgrind(check_server_jobs ${CMAKE_CURRENT_BINARY_DIR}/check_server_jobs)
 
-add_executable(check_server_userspace check_server_userspace.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_server_userspace check_server_userspace.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_server_userspace ${LIBS})
 add_test_valgrind(check_server_userspace ${CMAKE_CURRENT_BINARY_DIR}/check_server_userspace)
 
@@ -121,7 +134,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
 add_custom_target(client_HELOPN.bin DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin")
 add_custom_target(client_CreateActivateSession.bin DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin")
 
-add_executable(check_server_binary_messages check_server_binary_messages.c testing_networklayers.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_server_binary_messages check_server_binary_messages.c testing_networklayers.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_include_directories(check_server_binary_messages PRIVATE ${PROJECT_SOURCE_DIR}/src/server)
 target_link_libraries(check_server_binary_messages ${LIBS})
 add_dependencies(check_server_binary_messages client_HELOPN.bin)
@@ -146,14 +159,14 @@ add_test_valgrind(check_server_binary_messages_write ${CMAKE_CURRENT_BINARY_DIR}
 
 # Test Client
 
-add_executable(check_client check_client.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_client check_client.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client ${LIBS})
 add_test_valgrind(check_client ${CMAKE_CURRENT_BINARY_DIR}/check_client)
 
-add_executable(check_client_subscriptions check_client_subscriptions.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_client_subscriptions check_client_subscriptions.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_subscriptions ${LIBS})
 add_test_valgrind(check_client_subscriptions ${CMAKE_CURRENT_BINARY_DIR}/check_client_subscriptions)
 
-add_executable(check_client_highlevel check_client_highlevel.c $<TARGET_OBJECTS:open62541-object>)
+add_executable(check_client_highlevel check_client_highlevel.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_highlevel ${LIBS})
 add_test_valgrind(check_client_highlevel ${CMAKE_CURRENT_BINARY_DIR}/check_client_highlevel)

+ 4 - 0
tests/check_client_subscriptions.c

@@ -12,7 +12,9 @@
 #include "ua_client_highlevel.h"
 #include "ua_config_standard.h"
 #include "ua_network_tcp.h"
+
 #include "check.h"
+#include "testing_clock.h"
 
 UA_Server *server;
 UA_Boolean *running;
@@ -67,6 +69,8 @@ START_TEST(Client_subscription) {
                                                       UA_ATTRIBUTEID_VALUE, monitoredItemHandler, NULL, &monId);
     ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
 
+    UA_sleep((UA_DateTime)UA_SubscriptionSettings_standard.requestedPublishingInterval + 1);
+
     notificationReceived = false;
     retval = UA_Client_Subscriptions_manuallySendPublishRequest(client);
     ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);

+ 4 - 4
tests/check_server_jobs.c

@@ -7,7 +7,7 @@
 #include "ua_config_standard.h"
 
 #include "check.h"
-#include <unistd.h>
+#include "testing_clock.h"
 
 UA_Server *server = NULL;
 
@@ -40,11 +40,11 @@ START_TEST(Server_addRemoveRepeatedJob) {
     UA_Server_run_iterate(server, false);
 
     /* Wait until the job has surely timed out */
-    usleep(15*1000);
+    UA_sleep(15);
     UA_Server_run_iterate(server, false);
 
     /* Wait a bit longer until the workers have picked up the dispatched job */
-    usleep(15*1000);
+    UA_sleep(15);
     ck_assert_uint_eq(*executed, true);
 
     UA_Server_removeRepeatedJob(server, id);
@@ -67,7 +67,7 @@ START_TEST(Server_repeatedJobRemoveItself) {
     };
     UA_Server_addRepeatedJob(server, rj, 10, jobId);
 
-    usleep(15*1000);
+    UA_sleep(15);
     UA_Server_run_iterate(server, false);
 
     UA_Guid_delete(jobId);

+ 4 - 4
tests/check_services_subscriptions.c

@@ -9,7 +9,7 @@
 #include "ua_config_standard.h"
 
 #include "check.h"
-#include <unistd.h>
+#include "testing_clock.h"
 
 UA_Server *server = NULL;
 
@@ -162,7 +162,7 @@ START_TEST(Server_publishCallback) {
     UA_CreateSubscriptionResponse_deleteMembers(&response);
 
     /* Sleep until the publishing interval times out */
-    usleep((useconds_t)(publishingInterval * 1000) + 1000);
+    UA_sleep((UA_DateTime)publishingInterval + 1);
 
     /* Keepalive is set to max initially */
     UA_Subscription *sub;
@@ -171,9 +171,9 @@ START_TEST(Server_publishCallback) {
 
     UA_Server_run_iterate(server, false);
 #ifdef UA_ENABLE_MULTITHREADING
-    usleep((useconds_t)(publishingInterval * 1000) + 1000);
+    UA_sleep(publishingInterval + 1);
     UA_Server_run_iterate(server, false);
-    usleep((useconds_t)(publishingInterval * 1000) + 1000);
+    UA_sleep(publishingInterval + 1);
 #endif
 
     LIST_FOREACH(sub, &adminSession.serverSubscriptions, listEntry)

+ 2 - 1
tests/check_session.c

@@ -41,7 +41,7 @@ START_TEST(Session_updateLifetime_ShallWork) {
     tmpDateTime = session.validTill;
     UA_Session_updateLifetime(&session);
 
-    UA_Int32 result = (session.validTill > tmpDateTime);
+    UA_Int32 result = (session.validTill >= tmpDateTime);
     ck_assert_int_gt(result,0);
 }
 END_TEST
@@ -64,6 +64,7 @@ int main(void) {
 
     s = testSuite_Session();
     sr = srunner_create(s);
+    srunner_set_fork_status(sr, CK_NOFORK);
     srunner_run_all(sr,CK_NORMAL);
     number_failed += srunner_ntests_failed(sr);
     srunner_free(sr);

+ 20 - 0
tests/testing_clock.c

@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "testing_clock.h"
+
+UA_DateTime testingClock = 0;
+
+UA_DateTime UA_DateTime_now(void) {
+    return testingClock;
+}
+
+UA_DateTime UA_DateTime_nowMonotonic(void) {
+    return testingClock;
+}
+
+void
+UA_sleep(UA_DateTime duration) {
+    testingClock += duration * UA_MSEC_TO_DATETIME;
+}

+ 20 - 0
tests/testing_clock.h

@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TESTING_CLOCK_H_
+#define TESTING_CLOCK_H_
+
+#include "ua_types.h"
+
+/* The testing clock is used for reproducible unit tests that require precise
+ * timings. It implements the following functions from ua_types.h. They return a
+ * deterministic time that can be advanced manually with UA_sleep.
+ *
+ * UA_DateTime UA_EXPORT UA_DateTime_now(void);
+ * UA_DateTime UA_EXPORT UA_DateTime_nowMonotonic(void); */
+
+/* Forwards the testing clock by the given duration in ms */
+ void UA_sleep(UA_DateTime duration);
+
+#endif /* TESTING_CLOCK_H_ */