cyclonedds/src/security/core/tests/timed_cb.c
Dennis Potman e7f5ae354c 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>
2020-03-05 15:25:16 +01:00

374 lines
13 KiB
C

/*
* 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);
}