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);
+}