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 <dennis.potman@adlinktech.com>
This commit is contained in:
parent
ea10dbd8e1
commit
e7f5ae354c
9 changed files with 990 additions and 1333 deletions
|
@ -62,8 +62,8 @@ function(add_wrapper libname linklibs)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
set(security_core_test_sources
|
set(security_core_test_sources
|
||||||
"tc_fsm.c"
|
"fsm.c"
|
||||||
"dds_security_core.c"
|
"timed_cb.c"
|
||||||
"security_utils.c"
|
"security_utils.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,8 +102,6 @@ target_include_directories(
|
||||||
|
|
||||||
set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc")
|
set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc")
|
||||||
set(plugin_wrapper_lib_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
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")
|
configure_file("common/config_env.h.in" "common/config_env.h")
|
||||||
|
|
||||||
target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests)
|
target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "dds/version.h"
|
#include "dds/version.h"
|
||||||
#include "dds/ddsrt/cdtors.h"
|
#include "dds/ddsrt/cdtors.h"
|
||||||
#include "dds/ddsrt/environ.h"
|
#include "dds/ddsrt/environ.h"
|
||||||
|
#include "dds/ddsrt/process.h"
|
||||||
#include "dds/ddsrt/heap.h"
|
#include "dds/ddsrt/heap.h"
|
||||||
#include "dds/ddsrt/string.h"
|
#include "dds/ddsrt/string.h"
|
||||||
#include "dds/ddsi/q_config.h"
|
#include "dds/ddsi/q_config.h"
|
||||||
|
@ -36,8 +37,11 @@
|
||||||
|
|
||||||
static const char *config =
|
static const char *config =
|
||||||
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
||||||
"<Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
|
|
||||||
"<Domain id=\"any\">"
|
"<Domain id=\"any\">"
|
||||||
|
" <Discovery>"
|
||||||
|
" <ExternalDomainId>0</ExternalDomainId>"
|
||||||
|
" <Tag>\\${CYCLONEDDS_PID}</Tag>"
|
||||||
|
" </Discovery>"
|
||||||
" <Tracing><Verbosity>config</></>"
|
" <Tracing><Verbosity>config</></>"
|
||||||
" <DDSSecurity>"
|
" <DDSSecurity>"
|
||||||
" <Authentication>"
|
" <Authentication>"
|
||||||
|
@ -87,8 +91,8 @@ static void authentication_init(bool different_ca, const char * trusted_ca_dir,
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1);
|
char *conf1 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars1);
|
||||||
char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2);
|
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_vars1), 0);
|
||||||
CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0);
|
CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0);
|
||||||
g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1);
|
g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef CONFIG_ENV_H
|
#ifndef CONFIG_ENV_H
|
||||||
#define 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 COMMON_ETC_DIR "@common_etc_dir@"
|
||||||
#define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@"
|
#define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@"
|
||||||
#define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@"
|
#define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@"
|
||||||
|
|
|
@ -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 <stdio.h>
|
|
||||||
#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);
|
|
||||||
}
|
|
581
src/security/core/tests/fsm.c
Normal file
581
src/security/core/tests/fsm.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -35,9 +35,12 @@
|
||||||
|
|
||||||
static const char *config =
|
static const char *config =
|
||||||
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
||||||
"<Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
|
|
||||||
"<Domain id=\"any\">"
|
"<Domain id=\"any\">"
|
||||||
" <Tracing><Verbosity>finest</></>"
|
" <Discovery>"
|
||||||
|
" <ExternalDomainId>0</ExternalDomainId>"
|
||||||
|
" <Tag>\\${CYCLONEDDS_PID}</Tag>"
|
||||||
|
" </Discovery>"
|
||||||
|
" <Tracing><Verbosity>config</></>"
|
||||||
" <DDSSecurity>"
|
" <DDSSecurity>"
|
||||||
" <Authentication>"
|
" <Authentication>"
|
||||||
" <Library finalizeFunction=\"finalize_test_authentication_wrapped\" initFunction=\"init_test_authentication_wrapped\" path=\"" WRAPPERLIB_PATH("dds_security_authentication_wrapper") "\"/>"
|
" <Library finalizeFunction=\"finalize_test_authentication_wrapped\" initFunction=\"init_test_authentication_wrapped\" path=\"" WRAPPERLIB_PATH("dds_security_authentication_wrapper") "\"/>"
|
||||||
|
@ -68,30 +71,27 @@ static dds_entity_t g_part2_participant = 0;
|
||||||
|
|
||||||
static void handshake_init(void)
|
static void handshake_init(void)
|
||||||
{
|
{
|
||||||
/* Domains for pub and sub use a different domain id, but the portgain setting
|
char *conf_part1 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART1);
|
||||||
* in configuration is 0, so that both domains will map to the same port number.
|
char *conf_part2 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART2);
|
||||||
* This allows to create two domains in a single test process. */
|
g_part1_domain = dds_create_domain (DDS_DOMAINID_PART1, conf_part1);
|
||||||
char *conf_part1 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART1);
|
g_part2_domain = dds_create_domain (DDS_DOMAINID_PART2, conf_part2);
|
||||||
char *conf_part2 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART2);
|
dds_free (conf_part1);
|
||||||
g_part1_domain = dds_create_domain(DDS_DOMAINID_PART1, conf_part1);
|
dds_free (conf_part2);
|
||||||
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_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_part2_participant = dds_create_participant (DDS_DOMAINID_PART2, NULL, NULL)) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handshake_fini(void)
|
static void handshake_fini(void)
|
||||||
{
|
{
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_participant), 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_part2_participant), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_domain), 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_part2_domain), DDS_RETCODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini)
|
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_PART1, false, NULL, false, NULL);
|
||||||
validate_handshake(DDS_DOMAINID_PART2, false, NULL, false, NULL);
|
validate_handshake (DDS_DOMAINID_PART2, false, NULL, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,11 @@
|
||||||
|
|
||||||
static const char *config =
|
static const char *config =
|
||||||
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
|
||||||
"<Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
|
|
||||||
"<Domain id=\"any\">"
|
"<Domain id=\"any\">"
|
||||||
|
" <Discovery>"
|
||||||
|
" <ExternalDomainId>0</ExternalDomainId>"
|
||||||
|
" <Tag>\\${CYCLONEDDS_PID}</Tag>"
|
||||||
|
" </Discovery>"
|
||||||
" <DDSSecurity>"
|
" <DDSSecurity>"
|
||||||
" <Authentication>"
|
" <Authentication>"
|
||||||
" <Library finalizeFunction=\"finalize_authentication\" initFunction=\"init_authentication\" />"
|
" <Library finalizeFunction=\"finalize_authentication\" initFunction=\"init_authentication\" />"
|
||||||
|
@ -219,12 +222,12 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s
|
||||||
{ NULL, NULL, 0 }
|
{ 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,
|
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);
|
g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher);
|
||||||
dds_free (conf_pub);
|
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,
|
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);
|
g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber);
|
||||||
dds_free (conf_sub);
|
dds_free (conf_sub);
|
||||||
|
|
|
@ -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 <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
374
src/security/core/tests/timed_cb.c
Normal file
374
src/security/core/tests/timed_cb.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#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);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue