From e7f5ae354c425199135deb71e5b9e2f129267378 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 4 Mar 2020 11:14:51 +0100 Subject: [PATCH] Fix security handshake test Isolate domains by using unique tags when running tests that are using security handshake. And updated coding style and some minor refactoring in fsm and timed_cb tests. Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 6 +- src/security/core/tests/authentication.c | 10 +- .../core/tests/common/config_env.h.in | 2 +- src/security/core/tests/dds_security_core.c | 546 ------------- src/security/core/tests/fsm.c | 581 ++++++++++++++ src/security/core/tests/handshake.c | 38 +- .../core/tests/secure_communication.c | 9 +- src/security/core/tests/tc_fsm.c | 757 ------------------ src/security/core/tests/timed_cb.c | 374 +++++++++ 9 files changed, 990 insertions(+), 1333 deletions(-) delete mode 100644 src/security/core/tests/dds_security_core.c create mode 100644 src/security/core/tests/fsm.c delete mode 100644 src/security/core/tests/tc_fsm.c create mode 100644 src/security/core/tests/timed_cb.c diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index af2b446..5618269 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -62,8 +62,8 @@ function(add_wrapper libname linklibs) endfunction() set(security_core_test_sources - "tc_fsm.c" - "dds_security_core.c" + "fsm.c" + "timed_cb.c" "security_utils.c" ) @@ -102,8 +102,6 @@ target_include_directories( set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc") set(plugin_wrapper_lib_dir "${CMAKE_CURRENT_BINARY_DIR}") -file(TO_NATIVE_PATH "/" file_path_sep) -string(REPLACE "\\" "\\\\" file_path_sep ${file_path_sep}) configure_file("common/config_env.h.in" "common/config_env.h") target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests) diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 1ed8ce6..2d13079 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -19,6 +19,7 @@ #include "dds/version.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" @@ -36,8 +37,11 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " " config" " " " " @@ -87,8 +91,8 @@ static void authentication_init(bool different_ca, const char * trusted_ca_dir, { NULL, NULL, 0 } }; - char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1); - char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2); + char *conf1 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars1); + char *conf2 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars2); CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars1), 0); CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0); g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); diff --git a/src/security/core/tests/common/config_env.h.in b/src/security/core/tests/common/config_env.h.in index a3773f1..d4811fc 100644 --- a/src/security/core/tests/common/config_env.h.in +++ b/src/security/core/tests/common/config_env.h.in @@ -12,7 +12,7 @@ #ifndef CONFIG_ENV_H #define CONFIG_ENV_H -#define FILE_PATH_SEP "@file_path_sep@" +#define FILE_PATH_SEP "/" #define COMMON_ETC_DIR "@common_etc_dir@" #define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@" #define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" diff --git a/src/security/core/tests/dds_security_core.c b/src/security/core/tests/dds_security_core.c deleted file mode 100644 index aef1e4f..0000000 --- a/src/security/core/tests/dds_security_core.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include -#include "CUnit/Test.h" - -#include "dds/security/core/dds_security_timed_cb.h" -#include "dds/ddsrt/misc.h" - -#define SEQ_SIZE (16) - -typedef struct { - struct dds_security_timed_dispatcher_t *d; - dds_security_timed_cb_kind kind; - void *listener; - void *arg; - dds_time_t time; -} tc__sequence_data; - -static int g_sequence_idx = 0; -static tc__sequence_data g_sequence_array[SEQ_SIZE]; - -static void simple_callback(struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - DDSRT_UNUSED_ARG(d); - DDSRT_UNUSED_ARG(kind); - DDSRT_UNUSED_ARG(listener); - - if (*((bool *)arg) == false) - { - *((bool *)arg) = true; - } - else - { - *((bool *)arg) = false; - } -} - -static int g_order_callback_idx = 0; -static void* g_order_callback[2] = {(void*)NULL, (void*)NULL}; -static void order_callback(struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - DDSRT_UNUSED_ARG(d); - DDSRT_UNUSED_ARG(kind); - DDSRT_UNUSED_ARG(listener); - - g_order_callback[g_order_callback_idx] = arg; - g_order_callback_idx++; -} - -static void -tc__callback( - struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - if (g_sequence_idx < SEQ_SIZE) { - g_sequence_array[g_sequence_idx].d = d; - g_sequence_array[g_sequence_idx].arg = arg; - g_sequence_array[g_sequence_idx].kind = kind; - g_sequence_array[g_sequence_idx].listener = listener; - g_sequence_array[g_sequence_idx].time = dds_time(); - } - g_sequence_idx++; -} - -CU_Test(dds_security_timed_cb, simple_test) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, simple_order) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - dds_time_t future; - dds_time_t future2; - - d1 = dds_security_timed_dispatcher_new(tcb); - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - future = dds_time() + DDS_MSECS(20); - future2 = future; - dds_security_timed_dispatcher_add(tcb, d1, order_callback, future, (void*)1); - dds_security_timed_dispatcher_add(tcb, d1, order_callback, future2, (void*)2); - dds_security_timed_dispatcher_enable(tcb, d1, (void*)&g_order_callback); - dds_sleepfor(DDS_MSECS(10)); - - dds_security_timed_dispatcher_free(tcb, d1); - - CU_ASSERT_EQUAL_FATAL(g_order_callback[0], (void*)1); - CU_ASSERT_EQUAL_FATAL(g_order_callback[1], (void*)2); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_enabled_and_disabled) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - CU_ASSERT_FALSE(test_var); - - dds_security_timed_dispatcher_disable(tcb, d1); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_FALSE(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, simple_test_with_future) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - dds_time_t far_future = now + DDS_SECS(10); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_multiple_dispatchers) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - dds_time_t far_future = now + DDS_SECS(10); - - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - dds_security_timed_dispatcher_enable(tcb, d2, (void*)NULL); - - dds_security_timed_dispatcher_free(tcb, d2); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_not_enabled_multiple_dispatchers) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - CU_ASSERT_PTR_NOT_NULL_FATAL(d2); - - dds_security_timed_dispatcher_free(tcb, d2); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); - - CU_PASS("Timed callbacks enabled and disabled without add"); -} - -CU_Test(dds_security_timed_cb, test_create_dispatcher) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - struct dds_security_timed_dispatcher_t *d3 = NULL; - struct dds_security_timed_dispatcher_t *d4 = NULL; - struct dds_security_timed_dispatcher_t *d5 = NULL; - bool ok = false; - - dds_time_t now = dds_time(); - dds_time_t past = now - DDS_SECS(1); - dds_time_t present = now + DDS_SECS(1); - dds_time_t future = present + DDS_SECS(1); - dds_time_t future2 = future + DDS_SECS(10); - - /************************************************************************* - * Check if dispatchers can be created - *************************************************************************/ - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - CU_ASSERT_PTR_NOT_NULL_FATAL(d2); - - /************************************************************************* - * Check if adding callbacks succeeds - *************************************************************************/ - - /* The last argument is a sequence number in which - * the callbacks are expected to be called. */ - /* We can only really check if it crashes or not... */ - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*)1); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, past, (void*)0); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*)2); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*)7); - - CU_PASS("Added callbacks") - - /************************************************************************* - * Check if dispatchers can be created - *************************************************************************/ - d3 = dds_security_timed_dispatcher_new(tcb); - d4 = dds_security_timed_dispatcher_new(tcb); - d5 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d3); - CU_ASSERT_PTR_NOT_NULL_FATAL(d4); - CU_ASSERT_PTR_NOT_NULL_FATAL(d5); - - - /************************************************************************* - * Check if enabling dispatchers succeeds - *************************************************************************/ - - /* The sleeps are added to get the timing between - * 'present' and 'past' callbacks right. */ - /* We can only really check if it crashes or not... */ - dds_sleepfor(DDS_MSECS(600)); - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - dds_security_timed_dispatcher_enable(tcb, d2, (void*) d2); - dds_security_timed_dispatcher_enable(tcb, d3, (void*)NULL); - /* Specifically not enabling d4 and d5. */ - dds_sleepfor(DDS_MSECS(600)); - CU_PASS("Enabled dds_security_timed_dispatchers."); - - /************************************************************************* - * Check if adding callbacks succeeds - *************************************************************************/ - - /* The last argument is a sequence number in which - * the callbacks are expected to be called. */ - /* We can only really check if it crashes or not... */ - dds_security_timed_dispatcher_add(tcb, d4, tc__callback, past, (void*)99); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, future, (void*) 8); - dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*) 9); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, past, (void*) 3); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future2, (void*)10); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*) 4); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*) 5); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*) 6); - dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*)11); - CU_PASS("Added callbacks."); - - - /************************************************************************* - * Check if timeout callbacks are triggered in the right sequence - *************************************************************************/ - - int idx; - int timeout = 200; /* 2 seconds */ - - /* Wait for the callbacks to have been triggered. - * Ignore the ones in the far future. */ - while ((g_sequence_idx < 8) && (timeout > 0)) { - dds_sleepfor(DDS_MSECS(10)); - timeout--; - } - - /* Print and check sequence of triggered callbacks. */ - for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { - int seq = (int)(long long)(g_sequence_array[idx].arg); - struct dds_security_timed_dispatcher_t *expected_d; - void *expected_l; - - /* - * Sequence checks. - */ - if ((seq == 1) || (seq == 6) || (seq == 3) || (seq == 10) || (seq == 4) || (seq == 7)) { - expected_d = d1; - expected_l = NULL; - } else if ((seq == 0) || (seq == 2) || (seq == 8) || (seq == 5)) { - expected_d = d2; - expected_l = d2; - } else if (seq == 9) { - expected_d = d3; - expected_l = NULL; - } else if (seq == 99) { - expected_d = d4; - expected_l = NULL; - CU_FAIL("Unexpected callback on a disabled dispatcher"); - ok = false; - } else { - expected_d = NULL; - expected_l = NULL; - CU_FAIL(sprintf("Unknown sequence idx received %d", seq)); - ok = false; - } - - if (seq != idx) { - /* 6 and 7 order may be mixed since the order is not defined for same time stamp */ - if (!((seq == 6 && idx == 7) || (seq == 7 && idx == 6))) - { - printf("Unexpected sequence ordering %d vs %d\n", seq, idx); - CU_FAIL("Unexpected sequence ordering"); - ok = false; - } - } - if (seq > 8) { - CU_FAIL(sprintf("Unexpected sequence idx %d of the far future", seq)); - ok = false; - } - if (idx > 8) { - CU_FAIL(sprintf("Too many callbacks %d", idx)); - ok = false; - } - - /* - * Callback contents checks. - */ - if (expected_d != NULL) { - if (g_sequence_array[idx].d != expected_d) { - printf("Unexpected dispatcher %p vs %p\n", g_sequence_array[idx].d, expected_d); - CU_FAIL("Unexpected dispatcher"); - ok = false; - } - if (g_sequence_array[idx].listener != expected_l) { - CU_FAIL(sprintf("Unexpected listener %p vs %p", g_sequence_array[idx].listener, expected_l)); - ok = false; - } - } - - /* - * Callback kind check. - */ - if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { - CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); - ok = false; - } - } - if (g_sequence_idx < 8) { - CU_FAIL(sprintf("Received %d callbacks, while 9 are expected", - g_sequence_idx + 1)); - ok = false; - } - if (ok) { - CU_FAIL(sprintf("Received timeout callbacks.")); - } - - /* Reset callback index to catch the deletion ones. */ - g_sequence_idx = 0; - - - /************************************************************************* - * Check if deleting succeeds with dispatchers in different states - *************************************************************************/ - /* We can only really check if it crashes or not... */ - if (d1) { - dds_security_timed_dispatcher_free(tcb, d1); - } - if (d2) { - dds_security_timed_dispatcher_free(tcb, d2); - } - if (d3) { - dds_security_timed_dispatcher_free(tcb, d3); - } - if (d4) { - dds_security_timed_dispatcher_free(tcb, d4); - } - if (d5) { - dds_security_timed_dispatcher_free(tcb, d5); - } - CU_PASS("Deleted dispatchers."); - - - /************************************************************************* - * Check if deletion callbacks are triggered - *************************************************************************/ - if (ok) { - timeout = 200; /* 2 seconds */ - - /* Wait for the callbacks to have been triggered. - * Ignore the ones in the far future. */ - while ((g_sequence_idx < 4) && (timeout > 0)) { - dds_sleepfor(DDS_MSECS(10)); - timeout--; - } - - /* Print and check sequence of triggered callbacks. */ - for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { - int seq = (int)(long long)(g_sequence_array[idx].arg); - struct dds_security_timed_dispatcher_t *expected_d; - - /* - * Human (somewhat) readable format. - */ - // tc__sequence_data_print(&(g_sequence_array[idx])); - - /* - * Sequence checks. - */ - if (seq == 99) { - expected_d = d4; - } else if ((seq == 9) || (seq == 11)) { - expected_d = d3; - } else if (seq == 10) { - expected_d = d1; - } else { - expected_d = NULL; - CU_FAIL(sprintf("Unexpected sequence idx received %d", seq)); - ok = false; - } - if (idx > 4) { - CU_FAIL(sprintf("Too many callbacks %d", idx)); - ok = false; - } - - /* - * Callback contents checks. - */ - if (expected_d != NULL) { - if (g_sequence_array[idx].d != expected_d) { - CU_FAIL(sprintf("Unexpected dispatcher %p vs %p", g_sequence_array[idx].d, expected_d)); - ok = false; - } - if (g_sequence_array[idx].listener != NULL) { - CU_FAIL(sprintf("Unexpected listener %p vs NULL", g_sequence_array[idx].listener)); - ok = false; - } - } - - /* - * Callback kind check. - */ - if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_DELETE) { - CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); - ok = false; - } - } - if (g_sequence_idx < 4) { - CU_FAIL(sprintf("Received %d callbacks, while 3 are expected", - g_sequence_idx + 1)); - ok = false; - } - if (ok) { - CU_PASS("Received deletion callbacks."); - } - } - - dds_security_timed_cb_free(tcb); -} diff --git a/src/security/core/tests/fsm.c b/src/security/core/tests/fsm.c new file mode 100644 index 0000000..e947dfe --- /dev/null +++ b/src/security/core/tests/fsm.c @@ -0,0 +1,581 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" + +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/misc.h" +#include "dds/dds.h" +#include "dds__types.h" +#include "dds__entity.h" +#include "dds/security/core/dds_security_fsm.h" + +#define CHECK_BIT(var, pos) ((var) & (1<<(pos))) +#define FSM_AUTH_ARG 10 + +static dds_entity_t g_participant = 0; +static ddsrt_mutex_t g_lock; +static struct dds_security_fsm_control *g_fsm_control = NULL; + +#define DO_SIMPLE(name, var, bit) static void name(struct dds_security_fsm *fsm, void *arg) { \ + DDSRT_UNUSED_ARG(fsm); \ + DDSRT_UNUSED_ARG(arg); \ + printf("Transition %s\n", __FUNCTION__); \ + ddsrt_mutex_lock(&g_lock); \ + visited_##var |= 1u << (bit); \ + ddsrt_mutex_unlock(&g_lock); \ +} + +typedef enum { + VALIDATION_PENDING_RETRY, + VALIDATION_FAILED, + VALIDATION_OK, + VALIDATION_OK_FINAL_MESSAGE, + VALIDATION_PENDING_HANDSHAKE_MESSAGE, + VALIDATION_PENDING_HANDSHAKE_REQUEST, + plugin_ret_MAX +} plugin_ret; + +static struct dds_security_fsm *fsm_auth; +static uint32_t visited_auth = 0; +static uint32_t correct_fsm = 0; +static uint32_t correct_arg = 0; +static int validate_remote_identity_first = 1; +static int begin_handshake_reply_first = 1; + + +static plugin_ret validate_remote_identity(void) +{ + printf("validate_remote_identity - %d\n", validate_remote_identity_first); + if (validate_remote_identity_first) + { + validate_remote_identity_first = 0; + return VALIDATION_PENDING_RETRY; + } + return VALIDATION_PENDING_HANDSHAKE_MESSAGE; +} + +static plugin_ret begin_handshake_reply(void) +{ + printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); + if (begin_handshake_reply_first) + { + begin_handshake_reply_first = 0; + return VALIDATION_PENDING_RETRY; + } + return VALIDATION_OK_FINAL_MESSAGE; +} + +static plugin_ret get_shared_secret(void) +{ + return VALIDATION_OK; +} + +/* State actions */ +static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + plugin_ret ret = validate_remote_identity(); + printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); +} + +static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + plugin_ret ret = begin_handshake_reply(); + if (ret == VALIDATION_OK_FINAL_MESSAGE) + ret = get_shared_secret(); + printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); +} + +/* A few states from the handshake state-machine. */ +static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0}; +static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; +static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; +static dds_security_fsm_state state_beginHandshakeReply = {fsm_begin_handshake_reply, 0}; +static dds_security_fsm_state state_beginHsReplyWait = {NULL, 100000000}; + +static void a(struct dds_security_fsm *fsm, void *arg) +{ + printf("[%p] Transition %s\n", fsm, __FUNCTION__); + ddsrt_mutex_lock (&g_lock); + if (arg != NULL) + correct_arg = *((int *)arg) == FSM_AUTH_ARG ? 1 : 0; + correct_fsm = (fsm == fsm_auth) ? 1 : 0; + visited_auth |= 1u << 0; + ddsrt_mutex_unlock (&g_lock); +} + +DO_SIMPLE(b, auth, 1) +DO_SIMPLE(c, auth, 2) +DO_SIMPLE(d, auth, 3) +DO_SIMPLE(e, auth, 4) +DO_SIMPLE(f, auth, 5) +DO_SIMPLE(g, auth, 6) +DO_SIMPLE(h, auth, 7) + +#define SHM_MSG_RECEIVED (plugin_ret_MAX + 1) + +/* + * .--. + * |##|--------------------------------------. + * '--' a() v + * .----------------------------------------------------. + * | StateValidateRemoteIdentity | + * |----------------------------------------------------| + * .------>| fsm_validate_remote_identity() | + * | | - dispatch VALIDATION_PENDING_RETRY | + * 100ms| | - dispatch VALIDATION_PENDING_HANDSHAKE_MESSAGE | + * d() | '----------------------------------------------------' + * | VALIDATION_PENDING_RETRY| | VALIDATION_PENDING_HANDSHAKE_MESSAGE + * | b() | | c() + * | | | + * .------------------------------. | | .-------------------------------. + * | StateValRemIdentityRetryWait | | | | StateHandshakeInitMessageWait | + * |------------------------------|<----------' '------>|-------------------------------| + * '------------------------------' '-------------------------------' + * SHM_MSG_RECEIVED | + * e() | + * v + * .----------------------------------------. + * VALIDATION_PENDING_RETRY | state_beginHandshakeReply | + * f() |----------------------------------------| + * .-------------------------| fsm_begin_handshake_reply() | + * | | - dispatch VALIDATION_PENDING_RETRY | + * v | - dispatch VALIDATION_OK | + * .-----------------------. 100ms '----------------------------------------' + * | state_beginHsReplyWait | h() ^ VALIDATION_OK | + * |-----------------------|-----------------------' g() | + * '-----------------------' v + * .-. + * '-' + */ +static dds_security_fsm_transition HandshakeTransistions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state + {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait}, + {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait}, + {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, + {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &state_beginHandshakeReply}, + {&state_beginHandshakeReply, VALIDATION_PENDING_RETRY, f, &state_beginHsReplyWait}, + {&state_beginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram + {&state_beginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &state_beginHandshakeReply} +}; +static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]); + + +/* Example State Machine properties and methods */ +typedef enum { + eventX, eventY, eventZ, +} test_events; + +static struct dds_security_fsm *fsm_test; +static uint32_t visited_test = 0; +static int do_stuff_counter = 0; +static int do_other_stuff_counter = 0; + +DO_SIMPLE(do_start, test, 0) +DO_SIMPLE(do_restart, test, 1) +DO_SIMPLE(do_event_stuff, test, 4) + +static void do_stuff(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + printf("Transition %s - %d\n", __FUNCTION__, do_stuff_counter); + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 2; + ddsrt_mutex_unlock (&g_lock); + if (do_stuff_counter < 2) + dds_security_fsm_dispatch(fsm, eventZ, false); + else if (do_stuff_counter == 2) + dds_security_fsm_dispatch(fsm, eventY, false); + ++do_stuff_counter; +} + +static void do_other_stuff(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + printf("Transition %s - %d\n", __FUNCTION__, do_other_stuff_counter); + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 3; + ddsrt_mutex_unlock (&g_lock); + if (do_other_stuff_counter == 0) + dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); + else if (do_other_stuff_counter == 1) + dds_security_fsm_dispatch(fsm, eventY, false); + else if (do_other_stuff_counter == 2) + dds_security_fsm_dispatch(fsm, eventX, false); + ++do_other_stuff_counter; +} + +static dds_security_fsm_state state_a = {do_stuff, 0}; +static dds_security_fsm_state state_b = {do_stuff, 100000000}; +static dds_security_fsm_state state_c = {NULL, 0}; +static dds_security_fsm_state state_d = {do_other_stuff, 0}; + +static dds_security_fsm_transition Transitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, do_start, &state_a}, // NULL state is the start state + {&state_a, eventZ, NULL, &state_b}, + {&state_a, eventY, do_other_stuff, &state_c}, + {&state_b, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram + {&state_b, eventZ, do_restart, &state_a}, + {&state_c, DDS_SECURITY_FSM_EVENT_AUTO, do_event_stuff, &state_d}, + {&state_d, eventY, do_event_stuff, &state_d}, + {&state_d, eventX, do_stuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram +}; +static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]); + + +/* Timeout State Machine properties and methods */ +typedef enum { + event_to_timeout, event_to_interrupt, event_to_end, +} timeout_events; + +struct fsm_timeout_arg { + int id; +}; + +static struct dds_security_fsm *fsm_timeout; +static uint32_t visited_timeout = 0; +static uint32_t correct_fsm_timeout = 0; +static uint32_t correct_arg_timeout = 0; +static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; + +DO_SIMPLE(do_interrupt, timeout, 0) +DO_SIMPLE(timeout_cb2, timeout, 3) + +static void do_timeout(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + printf("Transition >>>> %s\n", __FUNCTION__); + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 1; + ddsrt_mutex_unlock (&g_lock); + printf("Transition <<<< %s\n", __FUNCTION__); + dds_security_fsm_dispatch(fsm, event_to_timeout, false); +} + +static void timeout_cb(struct dds_security_fsm *fsm, void *arg) +{ + struct fsm_timeout_arg *farg = arg; + printf("timeout_cb\n"); + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 2; + if (farg != NULL) + correct_arg_timeout = farg->id == FSM_AUTH_ARG ? 1 : 0; + correct_fsm_timeout = fsm == fsm_timeout ? 1 : 0; + ddsrt_mutex_unlock (&g_lock); +} + +static dds_security_fsm_state state_initial = {do_timeout, 0}; +static dds_security_fsm_state state_wait_timeout = {NULL, DDS_SECS(4)}; +static dds_security_fsm_state state_interrupt = {do_interrupt, 0}; + +static const dds_security_fsm_transition timeout_transitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_initial}, // NULL state is the start state + {&state_initial, event_to_timeout, NULL, &state_wait_timeout}, + {&state_wait_timeout, DDS_SECURITY_FSM_EVENT_TIMEOUT, NULL, &state_interrupt}, + {&state_wait_timeout, event_to_interrupt, NULL, &state_interrupt}, + {&state_interrupt, event_to_end, NULL, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t timeout_transitionsSize = sizeof(timeout_transitions)/sizeof(timeout_transitions[0]); + +/* Parallel Timeout State Machines properties and methods */ +static struct dds_security_fsm *fsm_timeout1; +static struct dds_security_fsm *fsm_timeout2; +static struct dds_security_fsm *fsm_timeout3; + +static dds_time_t time0 = 0; +static dds_time_t time1 = 0; +static dds_time_t time2 = 0; +static dds_time_t time3 = 0; + +static void state_par_time1(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time1 = dds_time(); +} + +static void state_par_time2(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time2 = dds_time(); +} + +static void state_par_time3(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time3 = dds_time(); +} + +static dds_security_fsm_state state_par_timeout1 = {NULL, DDS_SECS(1)}; +static dds_security_fsm_state state_par_timeout2 = {NULL, DDS_SECS(2)}; +static dds_security_fsm_state state_par_timeout3 = {NULL, DDS_SECS(1)}; + +static dds_security_fsm_transition parallel_timeout_transitions_1[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout1}, // NULL state is the startfsm_control_thread state + {&state_par_timeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time1, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_1 = sizeof(parallel_timeout_transitions_1) / sizeof(parallel_timeout_transitions_1[0]); + +static dds_security_fsm_transition parallel_timeout_transitions_2[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout2}, // NULL state is the start state + {&state_par_timeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time2, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_2 = sizeof(parallel_timeout_transitions_2) / sizeof(parallel_timeout_transitions_2[0]); + +static dds_security_fsm_transition parallel_timeout_transitions_3[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout3}, // NULL state is the start state + {&state_par_timeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time3, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_3 = sizeof(parallel_timeout_transitions_3) / sizeof(parallel_timeout_transitions_3[0]); + +static void fsm_control_init(void) +{ + struct dds_entity *e; + g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + ddsrt_mutex_init(&g_lock); + dds_return_t rc = dds_entity_pin(g_participant, &e); + CU_ASSERT_FATAL(rc == 0); + g_fsm_control = dds_security_fsm_control_create(&e->m_domain->gv); + CU_ASSERT_FATAL(g_fsm_control != NULL); + dds_entity_unpin(e); + rc = dds_security_fsm_control_start(g_fsm_control, NULL); + CU_ASSERT_EQUAL_FATAL(rc, 0); +} + +static void fsm_control_fini(void) +{ + dds_security_fsm_control_stop(g_fsm_control); + dds_security_fsm_control_free(g_fsm_control); + ddsrt_mutex_destroy (&g_lock); + dds_delete(g_participant); +} + +CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) +{ + /* Test single running state machine. Check creation of a single State Machine */ + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg); + CU_ASSERT_FATAL(fsm_auth != NULL) + + /* set a delay that doesn't expire. Should be terminate when fsm is freed. */ + dds_security_fsm_set_timeout(fsm_auth, timeout_cb, DDS_SECS(30)); + dds_security_fsm_start(fsm_auth); + + int n = 100; + while (dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT(n > 0); + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); + + n = 100; + while (dds_security_fsm_current_state(fsm_auth) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT(n > 0); + + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_auth == 0xff); + ddsrt_mutex_unlock (&g_lock); + + /* Check correct callback parameter passing (from fsm to user defined methods) */ + CU_ASSERT(correct_arg && correct_fsm); + dds_security_fsm_free(fsm_auth); + + /* Check whether timeout callback has NOT been invoked */ + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_timeout == 0); + ddsrt_mutex_unlock (&g_lock); +} + +/* Test multiple (2) running state machines */ +CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini) +{ + validate_remote_identity_first = 0; + begin_handshake_reply_first = 0; + visited_auth = 0; + visited_test = 0; + + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL); + CU_ASSERT_FATAL(fsm_auth != NULL); + + fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL); + CU_ASSERT_FATAL(fsm_test != NULL); + + dds_security_fsm_start(fsm_auth); + dds_security_fsm_start(fsm_test); + + /* Check the results of multiple running State Machines */ + int n = 100; /* 10 sec */ + while (dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + n = 100; /* 10 sec */ + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); + while (dds_security_fsm_current_state(fsm_auth) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + // not all bits are set since we're running the state machine a second time + ddsrt_mutex_lock (&g_lock); + CU_ASSERT_FATAL(visited_auth == 0x55); + ddsrt_mutex_unlock (&g_lock); + + /* Wait for the last state to occur */ + n = 100; /* 10 sec */ + while (dds_security_fsm_current_state(fsm_test) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_test == 0x1f); + ddsrt_mutex_unlock (&g_lock); + + dds_security_fsm_free(fsm_auth); + dds_security_fsm_free(fsm_test); + +} + +/** + * Check creation of State Machine for timeout purposes + */ +CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + /* Test timeout monitoring of state machines */ + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout != NULL); + dds_security_fsm_set_timeout(fsm_timeout, timeout_cb, DDS_SECS(1)); + dds_security_fsm_start(fsm_timeout); + + int n = 100; /* 10 sec */ + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0x7 && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + CU_ASSERT(n > 0); + CU_ASSERT(visited_timeout == 0x7); + CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); +} + +/* Check the double global timeout */ +CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout != NULL); + + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout2 != NULL); + + dds_security_fsm_set_timeout(fsm_timeout, timeout_cb, DDS_SECS(1)); + dds_security_fsm_set_timeout(fsm_timeout2, timeout_cb2, DDS_SECS(2)); + dds_security_fsm_start(fsm_timeout); + dds_security_fsm_start(fsm_timeout2); + int n = 100; + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0xf && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + CU_ASSERT(visited_timeout == 0xf); + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); + dds_security_fsm_free(fsm_timeout2); +} + +/* Check parallel state timeouts */ +CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + + fsm_timeout1 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_1, parallel_timeout_transitionsSize_1, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout1 != NULL); + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_2, parallel_timeout_transitionsSize_2, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout2 != NULL); + fsm_timeout3 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_3, parallel_timeout_transitionsSize_3, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout3 != NULL); + + time0 = dds_time(); + dds_security_fsm_start(fsm_timeout1); + dds_security_fsm_start(fsm_timeout2); + dds_security_fsm_start(fsm_timeout3); + + int n = 300; + while (((dds_security_fsm_current_state(fsm_timeout1) == NULL) + || (dds_security_fsm_current_state(fsm_timeout2) == NULL) + || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && n-- > 0) + { + dds_sleepfor(DDS_MSECS(100)); + } + while (((dds_security_fsm_current_state(fsm_timeout1) != NULL) + || (dds_security_fsm_current_state(fsm_timeout2) != NULL) + || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && n-- > 0) + { + dds_sleepfor(DDS_MSECS(100)); + } + + dds_duration_t delta1 = time1 - time0; + dds_duration_t delta2 = time2 - time0; + dds_duration_t delta3 = time3 - time0; + printf("time0 %"PRId64"\n", time0); + printf("time1 %"PRId64", delta1 %"PRId64"\n", time1, delta1); + printf("time2 %"PRId64", delta2 %"PRId64"\n", time2, delta2); + printf("time3 %"PRId64", delta3 %"PRId64"\n", time3, delta3); + CU_ASSERT(delta1 > DDS_MSECS(750)); + CU_ASSERT(delta1 < DDS_MSECS(1250)); + CU_ASSERT(delta2 > DDS_MSECS(1750)); + CU_ASSERT(delta2 < DDS_MSECS(2250)); + CU_ASSERT(delta3 > DDS_MSECS(750)); + CU_ASSERT(delta3 < DDS_MSECS(1250)); + + dds_security_fsm_free(fsm_timeout1); + dds_security_fsm_free(fsm_timeout2); + dds_security_fsm_free(fsm_timeout3); +} + +/* Delete with event timeout */ +CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT (fsm_timeout != NULL) + visited_timeout = 0; + dds_security_fsm_start(fsm_timeout); + + int n = 100; + ddsrt_mutex_lock (&g_lock); + while (visited_timeout == 0 && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); +} + diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 2eb52fc..0408bb9 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -35,9 +35,12 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" - " finest" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " + " config" " " " " " " @@ -68,30 +71,27 @@ static dds_entity_t g_part2_participant = 0; static void handshake_init(void) { - /* Domains for pub and sub use a different domain id, but the portgain setting - * in configuration is 0, so that both domains will map to the same port number. - * This allows to create two domains in a single test process. */ - char *conf_part1 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART1); - char *conf_part2 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART2); - g_part1_domain = dds_create_domain(DDS_DOMAINID_PART1, conf_part1); - g_part2_domain = dds_create_domain(DDS_DOMAINID_PART2, conf_part2); - dds_free(conf_part1); - dds_free(conf_part2); + char *conf_part1 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART1); + char *conf_part2 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART2); + g_part1_domain = dds_create_domain (DDS_DOMAINID_PART1, conf_part1); + g_part2_domain = dds_create_domain (DDS_DOMAINID_PART2, conf_part2); + dds_free (conf_part1); + dds_free (conf_part2); - CU_ASSERT_FATAL((g_part1_participant = dds_create_participant(DDS_DOMAINID_PART1, NULL, NULL)) > 0); - CU_ASSERT_FATAL((g_part2_participant = dds_create_participant(DDS_DOMAINID_PART2, NULL, NULL)) > 0); + CU_ASSERT_FATAL ((g_part1_participant = dds_create_participant (DDS_DOMAINID_PART1, NULL, NULL)) > 0); + CU_ASSERT_FATAL ((g_part2_participant = dds_create_participant (DDS_DOMAINID_PART2, NULL, NULL)) > 0); } static void handshake_fini(void) { - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_domain), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_domain), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_domain), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_domain), DDS_RETCODE_OK); } CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini) { - validate_handshake(DDS_DOMAINID_PART1, false, NULL, false, NULL); - validate_handshake(DDS_DOMAINID_PART2, false, NULL, false, NULL); + validate_handshake (DDS_DOMAINID_PART1, false, NULL, false, NULL); + validate_handshake (DDS_DOMAINID_PART2, false, NULL, false, NULL); } diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 9270a57..978aa62 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -51,8 +51,11 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " " " " " " " @@ -219,12 +222,12 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s { NULL, NULL, 0 } }; - char *conf_pub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + char *conf_pub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_PUB, conf_pub, domain_config, n_pub_domains, n_pub_participants, g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher); dds_free (conf_pub); - char *conf_sub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + char *conf_sub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_SUB, conf_sub, domain_config, n_sub_domains, n_sub_participants, g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber); dds_free (conf_sub); diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c deleted file mode 100644 index 666a641..0000000 --- a/src/security/core/tests/tc_fsm.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/ddsrt/sync.h" -#include "dds/ddsrt/misc.h" - -#include "CUnit/CUnit.h" -#include "CUnit/Test.h" -#include "dds/dds.h" -#include "dds__types.h" -#include "dds__entity.h" -#include "dds/security/core/dds_security_fsm.h" - -#define CHECK_BIT(var, pos) ((var) & (1<<(pos))) - -#define FSM_AUTH_ARG 10 - -#define DB_TC_PRINT_DEBUG (true) - -static dds_entity_t g_participant = 0; -static ddsrt_mutex_t g_lock; -static struct dds_security_fsm_control *g_fsm_control = NULL; -static const dds_duration_t msec100 = DDS_MSECS(100); - -//static int fsm_arg = FSM_AUTH_ARG; - -#define DO_SIMPLE(name, var, bit) static void name(struct dds_security_fsm *fsm, void *arg) { \ - DDSRT_UNUSED_ARG(fsm); \ - DDSRT_UNUSED_ARG(arg); \ - if (DB_TC_PRINT_DEBUG) \ - printf("Transition %s\n", __FUNCTION__); \ - ddsrt_mutex_lock(&g_lock); \ - visited_##var |= 1u << (bit); \ - ddsrt_mutex_unlock(&g_lock); \ -} - - -/********************************************************************** - * Authentication State Machine properties and methods - **********************************************************************/ - -typedef enum { - VALIDATION_PENDING_RETRY, - VALIDATION_FAILED, - VALIDATION_OK, - VALIDATION_OK_FINAL_MESSAGE, - VALIDATION_PENDING_HANDSHAKE_MESSAGE, - VALIDATION_PENDING_HANDSHAKE_REQUEST, - PluginReturn_MAX -} PluginReturn; - -static struct dds_security_fsm *fsm_auth; -static uint32_t visited_auth = 0; -static uint32_t correct_fsm = 0; -static uint32_t correct_arg = 0; -static int validate_remote_identity_first = 1; -static int begin_handshake_reply_first = 1; - - -static PluginReturn validate_remote_identity(void) -{ - if (DB_TC_PRINT_DEBUG) { - printf("validate_remote_identity - %d\n", validate_remote_identity_first); - } - if (validate_remote_identity_first) { - validate_remote_identity_first = 0; - return VALIDATION_PENDING_RETRY; - } - return VALIDATION_PENDING_HANDSHAKE_MESSAGE; -} - -static PluginReturn begin_handshake_reply(void) -{ - if (DB_TC_PRINT_DEBUG) { - printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); - } - if (begin_handshake_reply_first) { - begin_handshake_reply_first = 0; - return VALIDATION_PENDING_RETRY; - } - return VALIDATION_OK_FINAL_MESSAGE; -} - -static PluginReturn get_shared_secret(void) -{ - return VALIDATION_OK; -} - -/* State actions. */ -static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) -{ - PluginReturn ret; - - DDSRT_UNUSED_ARG(arg); - - ret = validate_remote_identity(); - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); - } - - dds_security_fsm_dispatch(fsm, (int32_t) ret, false); -} - -static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) -{ - PluginReturn ret; - - DDSRT_UNUSED_ARG(arg); - - ret = begin_handshake_reply(); - if (ret == VALIDATION_OK_FINAL_MESSAGE) { - ret = get_shared_secret(); - } - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); - } - - dds_security_fsm_dispatch(fsm, (int32_t) ret, false); -} - -/* A few states from the handshake state-machine. */ -static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0}; -static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; -static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; -static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0}; -static dds_security_fsm_state StateBeginHsReplyWait = {NULL, 100000000}; - -static void a(struct dds_security_fsm *fsm, void *arg) -{ - int *fsm_arg; - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - } - - ddsrt_mutex_lock (&g_lock); - if (arg != NULL) { - fsm_arg = (int *) arg; - - if (*fsm_arg == FSM_AUTH_ARG) { - correct_arg = 1; - } else { - correct_arg = 0; - } - } - - if (fsm == fsm_auth) { - correct_fsm = 1; - } else { - correct_fsm = 0; - } - visited_auth |= 1u << 0; - ddsrt_mutex_unlock (&g_lock); -} - -DO_SIMPLE(b, auth, 1) -DO_SIMPLE(c, auth, 2) -DO_SIMPLE(d, auth, 3) -DO_SIMPLE(e, auth, 4) -DO_SIMPLE(f, auth, 5) -DO_SIMPLE(g, auth, 6) -DO_SIMPLE(h, auth, 7) - -#define SHM_MSG_RECEIVED (PluginReturn_MAX + 1) - -/* - * .--. - * |##|--------------------------------------. - * '--' a() v - * .----------------------------------------------------. - * | StateValidateRemoteIdentity | - * |----------------------------------------------------| - * .------>| fsm_validate_remote_identity() | - * | | - dispatch VALIDATION_PENDING_RETRY | - * 100ms| | - dispatch VALIDATION_PENDING_HANDSHAKE_MESSAGE | - * d() | '----------------------------------------------------' - * | VALIDATION_PENDING_RETRY| | VALIDATION_PENDING_HANDSHAKE_MESSAGE - * | b() | | c() - * | | | - * .------------------------------. | | .-------------------------------. - * | StateValRemIdentityRetryWait | | | | StateHandshakeInitMessageWait | - * |------------------------------|<----------' '------>|-------------------------------| - * '------------------------------' '-------------------------------' - * SHM_MSG_RECEIVED | - * e() | - * v - * .----------------------------------------. - * VALIDATION_PENDING_RETRY | StateBeginHandshakeReply | - * f() |----------------------------------------| - * .-------------------------| fsm_begin_handshake_reply() | - * | | - dispatch VALIDATION_PENDING_RETRY | - * v | - dispatch VALIDATION_OK | - * .-----------------------. 100ms '----------------------------------------' - * | StateBeginHsReplyWait | h() ^ VALIDATION_OK | - * |-----------------------|-----------------------' g() | - * '-----------------------' v - * .-. - * '-' - */ -static dds_security_fsm_transition HandshakeTransistions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state - {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait}, - {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait}, - {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, - {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &StateBeginHandshakeReply}, - {&StateBeginHandshakeReply, VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait}, - {&StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram - {&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &StateBeginHandshakeReply} -}; -static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]); - - -/********************************************************************** - * Example State Machine properties and methods - **********************************************************************/ - -typedef enum { - eventX, eventY, eventZ, -} test_events; - -static struct dds_security_fsm *fsm_test; -static uint32_t visited_test = 0; -static int do_stuff_counter = 0; -static int do_other_stuff_counter = 0; - -DO_SIMPLE(doStart, test, 0) -DO_SIMPLE(doRestart, test, 1) -DO_SIMPLE(doEventStuff, test, 4) - -static void doStuff(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition %s - %d\n", __FUNCTION__, do_stuff_counter); - } - ddsrt_mutex_lock (&g_lock); - visited_test |= 1u << 2; - ddsrt_mutex_unlock (&g_lock); - - if (do_stuff_counter < 2) { - dds_security_fsm_dispatch(fsm, eventZ, false); - } else if (do_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventY, false); - } - ++do_stuff_counter; -} - -static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition %s - %d\n", __FUNCTION__, do_other_stuff_counter); - } - ddsrt_mutex_lock (&g_lock); - visited_test |= 1u << 3; - ddsrt_mutex_unlock (&g_lock); - - if (do_other_stuff_counter == 0) { - dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); - } - - if (do_other_stuff_counter == 1) { - dds_security_fsm_dispatch(fsm, eventY, false); - } else if (do_other_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventX, false); - } - ++do_other_stuff_counter; -} - -static dds_security_fsm_state StateA = {doStuff, 0}; -static dds_security_fsm_state StateB = {doStuff, 100000000}; -static dds_security_fsm_state StateC = {NULL, 0}; -static dds_security_fsm_state StateD = {doOtherStuff, 0}; - -static dds_security_fsm_transition Transitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state - {&StateA, eventZ, NULL, &StateB}, - {&StateA, eventY, doOtherStuff, &StateC}, - {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram - {&StateB, eventZ, doRestart, &StateA}, - {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, doEventStuff, &StateD}, - {&StateD, eventY, doEventStuff, &StateD}, - {&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram -}; -static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]); - - -/********************************************************************** - * Timeout State Machine properties and methods - **********************************************************************/ - -typedef enum { - eventToTimeout, eventToInterupt, eventToEnd, -} timeout_events; - -struct fsm_timeout_arg { - int id; -}; - -static struct dds_security_fsm *fsm_timeout; -static uint32_t visited_timeout = 0; -static uint32_t correct_fsm_timeout = 0; -static uint32_t correct_arg_timeout = 0; -static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; - -DO_SIMPLE(doInterrupt, timeout, 0) -DO_SIMPLE(TimeoutCallback2, timeout, 3) - -static void doTimeout(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition >>>> %s\n", __FUNCTION__); - } - ddsrt_mutex_lock (&g_lock); - visited_timeout |= 1u << 1; - ddsrt_mutex_unlock (&g_lock); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition <<<< %s\n", __FUNCTION__); - } - - dds_security_fsm_dispatch(fsm, eventToTimeout, false); -} - -static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) -{ - struct fsm_timeout_arg *farg = arg; - - if (DB_TC_PRINT_DEBUG) { - printf("TimeoutCallback\n"); - } - - ddsrt_mutex_lock (&g_lock); - visited_timeout |= 1u << 2; - - if (farg != NULL) { - if (farg->id == FSM_AUTH_ARG) { - correct_arg_timeout = 1; - } else { - correct_arg_timeout = 0; - } - } - if (fsm == fsm_timeout) { - correct_fsm_timeout = 1; - } else { - correct_fsm_timeout = 0; - } - ddsrt_mutex_unlock (&g_lock); -} - -static dds_security_fsm_state StateInitial = {doTimeout, 0}; -static dds_security_fsm_state StateWaitTimeout = {NULL, DDS_SECS(4)}; -static dds_security_fsm_state StateInterupt = {doInterrupt, 0}; - - -static const dds_security_fsm_transition TimeoutTransitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateInitial}, // NULL state is the start state - {&StateInitial, eventToTimeout, NULL, &StateWaitTimeout}, - {&StateWaitTimeout, DDS_SECURITY_FSM_EVENT_TIMEOUT, NULL, &StateInterupt}, - {&StateWaitTimeout, eventToInterupt, NULL, &StateInterupt}, - {&StateInterupt, eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t TimeoutTransitionsSize = sizeof(TimeoutTransitions)/sizeof(TimeoutTransitions[0]); - - -/********************************************************************** - * Parallel Timeout State Machines properties and methods - **********************************************************************/ - -static struct dds_security_fsm *fsm_timeout1; -static struct dds_security_fsm *fsm_timeout2; -static struct dds_security_fsm *fsm_timeout3; - -static dds_time_t time0 = 0; -static dds_time_t time1 = 0; -static dds_time_t time2 = 0; -static dds_time_t time3 = 0; - -static void StateParTime1(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time1 = dds_time(); -} - -static void StateParTime2(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time2 = dds_time(); -} - -static void StateParTime3(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time3 = dds_time(); -} - -static dds_security_fsm_state StateParTimeout1 = {NULL, DDS_SECS(1)}; -static dds_security_fsm_state StateParTimeout2 = {NULL, DDS_SECS(2)}; -static dds_security_fsm_state StateParTimeout3 = {NULL, DDS_SECS(1)}; - -static dds_security_fsm_transition ParallelTimeoutTransitions_1[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout1}, // NULL state is the startfsm_control_thread state - {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_1 = sizeof(ParallelTimeoutTransitions_1) / sizeof(ParallelTimeoutTransitions_1[0]); - -static dds_security_fsm_transition ParallelTimeoutTransitions_2[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout2}, // NULL state is the start state - {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_2 = sizeof(ParallelTimeoutTransitions_2) / sizeof(ParallelTimeoutTransitions_2[0]); - -static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout3}, // NULL state is the start state - {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_3 = sizeof(ParallelTimeoutTransitions_3) / sizeof(ParallelTimeoutTransitions_3[0]); - -static void fsm_control_init(void) -{ - dds_return_t rc; - struct dds_entity *e; - - g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(g_participant > 0); - - ddsrt_mutex_init (&g_lock); - - rc = dds_entity_pin(g_participant, &e); - CU_ASSERT_FATAL(rc == 0); - - g_fsm_control = dds_security_fsm_control_create (&e->m_domain->gv); - CU_ASSERT_FATAL (g_fsm_control != NULL); - - dds_entity_unpin (e); - - rc = dds_security_fsm_control_start (g_fsm_control, NULL); - CU_ASSERT_FATAL(rc == 0); -} - -static void fsm_control_fini(void) -{ - dds_security_fsm_control_stop(g_fsm_control); - dds_security_fsm_control_free(g_fsm_control); - ddsrt_mutex_destroy (&g_lock); - - dds_delete(g_participant); -} - -CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay30 = DDS_SECS(30); - int timeout; - - /* - * Test single running state machine - * Check creation of a single State Machine - */ - fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg); - CU_ASSERT_FATAL(fsm_auth != NULL) - - // set a delay that doesn't expire. Should be terminate when fsm is freed. - dds_security_fsm_set_timeout(fsm_auth, TimeoutCallback, delay30); - dds_security_fsm_start(fsm_auth); - - /** - * Check the result of one running State Machine - */ - - // Wait for the last state to occur - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { - dds_sleepfor(msec100); - timeout--; - } - CU_ASSERT(timeout > 0); - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); - - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { - dds_sleepfor(msec100); - timeout--; - } - CU_ASSERT(timeout > 0); - - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_auth == 0xff); - ddsrt_mutex_unlock (&g_lock); - - /* - * "Check correct callback parameter passing (from fsm to user defined methods) "); - */ - CU_ASSERT(correct_arg && correct_fsm); - dds_security_fsm_free(fsm_auth); - - /* Check whether timeout callback has NOT been invoked */ - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_timeout == 0); - ddsrt_mutex_unlock (&g_lock); -} - -/* - * Test multiple (2) running state machines - */ -CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini) -{ - int timeout; - - /*Check creation of multiple (2) State Machines*/ - validate_remote_identity_first = 0; - begin_handshake_reply_first = 0; - visited_auth = 0; - visited_test = 0; - - fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL); - CU_ASSERT_FATAL(fsm_auth != NULL); - - fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL); - CU_ASSERT_FATAL(fsm_test != NULL); - - dds_security_fsm_start(fsm_auth); - dds_security_fsm_start(fsm_test); - - /* Check the results of multiple running State Machines */ - - /* Wait for the last state to occur */ - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - timeout = 100; /* 10 sec */ - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); - while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - // not all bits are set since we're running the state machine a second time - ddsrt_mutex_lock (&g_lock); - CU_ASSERT_FATAL(visited_auth == 0x55); - ddsrt_mutex_unlock (&g_lock); - - /* Wait for the last state to occur */ - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_test == 0x1f); - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_auth); - dds_security_fsm_free(fsm_test); - -} - -/** - * Check creation of State Machine for timeout purposes - */ -CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay1 = DDS_SECS(1); - int timeout; - - visited_timeout = 0; - - /* - * Test timeout monitoring of state machines - */ - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout != NULL); - - dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); - dds_security_fsm_start(fsm_timeout); - - /*Check the result of the running State Machine for timeout purposes*/ - - // Wait for the last state to occur - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while (visited_timeout != 0x7 && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - CU_ASSERT(timeout > 0); - CU_ASSERT(visited_timeout == 0x7); - CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_timeout); -} - -/** - * Check the double global timeout - */ -CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay1 = DDS_SECS(1); - dds_time_t delay2 = DDS_SECS(2); - int timeout; - - visited_timeout = 0; - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout != NULL); - - fsm_timeout2 = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout2 != NULL); - - dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); - dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2); - dds_security_fsm_start(fsm_timeout); - dds_security_fsm_start(fsm_timeout2); - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while (visited_timeout != 0xf && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - CU_ASSERT(visited_timeout == 0xf); - ddsrt_mutex_unlock (&g_lock); - dds_security_fsm_free(fsm_timeout); - dds_security_fsm_free(fsm_timeout2); -} - -/** - * Check parallel state timeouts - */ -CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_duration_t delta1; - dds_duration_t delta2; - dds_duration_t delta3; - int timeout; - - visited_timeout = 0; - - fsm_timeout1 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_1, ParallelTimeoutTransitionsSize_1, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout1 != NULL); - - fsm_timeout2 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_2, ParallelTimeoutTransitionsSize_2, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout2 != NULL); - - fsm_timeout3 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_3, ParallelTimeoutTransitionsSize_3, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout3 != NULL); - - time0 = dds_time(); - dds_security_fsm_start(fsm_timeout1); - dds_security_fsm_start(fsm_timeout2); - dds_security_fsm_start(fsm_timeout3); - - /* Wait for both to end. */ - timeout = 300; /* 10 sec */ - /* First, they have to be started. */ - while (((dds_security_fsm_current_state(fsm_timeout1) == NULL) - || (dds_security_fsm_current_state(fsm_timeout2) == NULL) - || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - - /* Then, they have to have ended. */ - while (((dds_security_fsm_current_state(fsm_timeout1) != NULL) - || (dds_security_fsm_current_state(fsm_timeout2) != NULL) - || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - - /* - * There should be about 1 second difference between all times: - * time1 = time0 + 1 - * time2 = time0 + 2 - * time3 = time0 + 1 - */ - delta1 = time1 - time0; - delta2 = time2 - time0; - delta3 = time3 - time0; - printf("Time0 %" PRId64 "\n", time0); - printf("Time1 %" PRId64 "\n", time1); - printf("Time2 %" PRId64 "\n", time2); - printf("Time3 %" PRId64 "\n", time3); - printf("Delta1 %" PRId64 "\n", delta1); - printf("Delta2 %" PRId64 "\n", delta2); - printf("Delta3 %" PRId64 "\n", delta3); - CU_ASSERT(delta1 > 750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta1 < 1250 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta2 > 1750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta2 < 2250 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta3 > 750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta3 < 1250 * DDS_NSECS_IN_MSEC); - - dds_security_fsm_free(fsm_timeout1); - dds_security_fsm_free(fsm_timeout2); - dds_security_fsm_free(fsm_timeout3); - -} - -/** - * Delete with event timeout - */ -CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - int timeout; - - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT (fsm_timeout != NULL) - - visited_timeout = 0; - dds_security_fsm_start(fsm_timeout); - - /* Wait until we're in the timeout function. */ - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while ((visited_timeout == 0) && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_timeout); -} - diff --git a/src/security/core/tests/timed_cb.c b/src/security/core/tests/timed_cb.c new file mode 100644 index 0000000..6b01a9e --- /dev/null +++ b/src/security/core/tests/timed_cb.c @@ -0,0 +1,374 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include "CUnit/Test.h" + +#include "dds/security/core/dds_security_timed_cb.h" +#include "dds/ddsrt/misc.h" + +#define SEQ_SIZE (16) + +typedef struct +{ + struct dds_security_timed_dispatcher_t *d; + dds_security_timed_cb_kind kind; + void *listener; + void *arg; + dds_time_t time; +} test_sequence_data; + +static int g_sequence_idx = 0; +static test_sequence_data g_sequence_array[SEQ_SIZE]; + +static void simple_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + *((bool *)arg) = !(*((bool *)arg)); +} + +static int g_order_callback_idx = 0; +static void *g_order_callback[2] = {(void *)NULL, (void *)NULL}; +static void order_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + g_order_callback[g_order_callback_idx] = arg; + g_order_callback_idx++; +} + +static void test_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + if (g_sequence_idx < SEQ_SIZE) + { + g_sequence_array[g_sequence_idx].d = d; + g_sequence_array[g_sequence_idx].arg = arg; + g_sequence_array[g_sequence_idx].kind = kind; + g_sequence_array[g_sequence_idx].listener = listener; + g_sequence_array[g_sequence_idx].time = dds_time(); + } + g_sequence_idx++; +} + +CU_Test(ddssec_timed_cb, simple_test) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t future = dds_time() + DDS_SECS(2); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, simple_order) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_time_t future = dds_time() + DDS_MSECS(20), future2 = future; + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future, (void *)1); + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future2, (void *)2); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)&g_order_callback); + dds_sleepfor(DDS_MSECS(10)); + dds_security_timed_dispatcher_free(tcb, d1); + CU_ASSERT_EQUAL_FATAL(g_order_callback[0], (void *)1); + CU_ASSERT_EQUAL_FATAL(g_order_callback[1], (void *)2); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_enabled_and_disabled) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t future = dds_time() + DDS_SECS(2); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + CU_ASSERT_FALSE(test_var); + dds_security_timed_dispatcher_disable(tcb, d1); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_FALSE(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, simple_test_with_future) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t now = dds_time(), future = now + DDS_SECS(2), far_future = now + DDS_SECS(10); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void *)&test_var); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t now = dds_time(), future = now + DDS_SECS(2), far_future = now + DDS_SECS(10); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + struct dds_security_timed_dispatcher_t *d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void *)NULL); + dds_security_timed_dispatcher_free(tcb, d2); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void *)&test_var); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_not_enabled_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + struct dds_security_timed_dispatcher_t *d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + dds_security_timed_dispatcher_free(tcb, d2); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_create_dispatcher) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + struct dds_security_timed_dispatcher_t *d2 = NULL; + struct dds_security_timed_dispatcher_t *d3 = NULL; + struct dds_security_timed_dispatcher_t *d4 = NULL; + struct dds_security_timed_dispatcher_t *d5 = NULL; + + dds_time_t now = dds_time(); + dds_time_t past = now - DDS_SECS(1); + dds_time_t present = now + DDS_SECS(1); + dds_time_t future = present + DDS_SECS(1); + dds_time_t future2 = future + DDS_SECS(10); + + d1 = dds_security_timed_dispatcher_new(tcb); + d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + + /* The last argument is a sequence number in which + the callbacks are expected to be called. */ + dds_security_timed_dispatcher_add(tcb, d1, test_callback, present, (void *)1); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, past, (void *)0); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, present, (void *)2); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future, (void *)7); + + d3 = dds_security_timed_dispatcher_new(tcb); + d4 = dds_security_timed_dispatcher_new(tcb); + d5 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d3); + CU_ASSERT_PTR_NOT_NULL_FATAL(d4); + CU_ASSERT_PTR_NOT_NULL_FATAL(d5); + + /* The sleeps are added to get the timing between 'present' and 'past' callbacks right. */ + dds_sleepfor(DDS_MSECS(600)); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void *)d2); + dds_security_timed_dispatcher_enable(tcb, d3, (void *)NULL); + /* Specifically not enabling d4 and d5. */ + dds_sleepfor(DDS_MSECS(600)); + + /* The last argument is a sequence number in which the callbacks are expected to be called. */ + dds_security_timed_dispatcher_add(tcb, d4, test_callback, past, (void *)99); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, future, (void *)8); + dds_security_timed_dispatcher_add(tcb, d3, test_callback, future2, (void *)9); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, past, (void *)3); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future2, (void *)10); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, present, (void *)4); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, present, (void *)5); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future, (void *)6); + dds_security_timed_dispatcher_add(tcb, d3, test_callback, future2, (void *)11); + + int idx; + int n = 200; + + /* Wait for the callbacks to have been triggered. Ignore the ones in the far future. */ + while (g_sequence_idx < 8 && n-- > 0) + dds_sleepfor(DDS_MSECS(10)); + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; idx < g_sequence_idx && idx < SEQ_SIZE; idx++) + { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + void *expected_l; + + if (seq == 1 || seq == 6 || seq == 3 || seq == 10 || seq == 4 || seq == 7) + { + expected_d = d1; + expected_l = NULL; + } + else if (seq == 0 || seq == 2 || seq == 8 || seq == 5) + { + expected_d = d2; + expected_l = d2; + } + else if (seq == 9) + { + expected_d = d3; + expected_l = NULL; + } + else if (seq == 99) + { + expected_d = d4; + expected_l = NULL; + CU_FAIL_FATAL("Unexpected callback on a disabled dispatcher"); + } + else + { + expected_d = NULL; + expected_l = NULL; + CU_FAIL_FATAL(sprintf("Unknown sequence idx received %d", seq)); + } + + if (seq != idx) + { + /* 6 and 7 order may be mixed since the order is not defined for same time stamp */ + if (!((seq == 6 && idx == 7) || (seq == 7 && idx == 6))) + { + CU_FAIL_FATAL(sprintf("Unexpected sequence ordering %d vs %d\n", seq, idx)); + } + } + if (seq > 8) + { + CU_FAIL_FATAL(sprintf("Unexpected sequence idx %d of the far future", seq)); + } + if (idx > 8) + { + CU_FAIL_FATAL(sprintf("Too many callbacks %d", idx)); + } + + /* Callback contents checks. */ + if (expected_d != NULL) + { + if (g_sequence_array[idx].d != expected_d) + { + CU_FAIL_FATAL(sprintf("Unexpected dispatcher %p vs %p\n", g_sequence_array[idx].d, expected_d)); + } + if (g_sequence_array[idx].listener != expected_l) + { + CU_FAIL_FATAL(sprintf("Unexpected listener %p vs %p", g_sequence_array[idx].listener, expected_l)); + } + } + + /* Callback kind check. */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) + { + CU_FAIL_FATAL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + } + } + if (g_sequence_idx < 8) + { + CU_FAIL_FATAL(sprintf("Received %d callbacks, while 9 are expected", g_sequence_idx + 1)); + } + + /* Reset callback index to catch the deletion ones. */ + g_sequence_idx = 0; + + /* Check if deleting succeeds with dispatchers in different states */ + if (d1) + dds_security_timed_dispatcher_free(tcb, d1); + if (d2) + dds_security_timed_dispatcher_free(tcb, d2); + if (d3) + dds_security_timed_dispatcher_free(tcb, d3); + if (d4) + dds_security_timed_dispatcher_free(tcb, d4); + if (d5) + dds_security_timed_dispatcher_free(tcb, d5); + + /* Wait for the callbacks to have been triggered. Ignore the ones in the far future. */ + n = 200; + while (g_sequence_idx < 4 && n-- > 0) + dds_sleepfor(DDS_MSECS(10)); + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) + { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + if (seq == 99) + expected_d = d4; + else if (seq == 9 || seq == 11) + expected_d = d3; + else if (seq == 10) + expected_d = d1; + else + { + expected_d = NULL; + CU_FAIL_FATAL(sprintf("Unexpected sequence idx received %d", seq)); + } + if (idx > 4) + { + CU_FAIL_FATAL(sprintf("Too many callbacks %d", idx)); + } + + /* Callback contents checks. */ + if (expected_d != NULL) + { + if (g_sequence_array[idx].d != expected_d) + { + CU_FAIL_FATAL(sprintf("Unexpected dispatcher %p vs %p", g_sequence_array[idx].d, expected_d)); + } + if (g_sequence_array[idx].listener != NULL) + { + CU_FAIL_FATAL(sprintf("Unexpected listener %p vs NULL", g_sequence_array[idx].listener)); + } + } + + /* Callback kind check. */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_DELETE) + { + CU_FAIL_FATAL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + } + } + if (g_sequence_idx < 4) + { + CU_FAIL_FATAL(sprintf("Received %d callbacks, while 3 are expected", g_sequence_idx + 1)); + } + + dds_security_timed_cb_free(tcb); +}