Files
bacnet_stack/test/ports/win32/bsc_event/src/main.c
T

215 lines
5.4 KiB
C

/**
* @file
* @brief test of BACnet/SC event interface
* @author Steve Karg <skarg@users.sourceforge.net>
* @author Kirill Neznamov <kirill.neznamov@dsr-corporation.com>
* @author Mikhail Antropov <michail.antropov@dsr-corporation.com>
* @author Ondřej Hruška <ondra@ondrovo.com>
* @author Patrick Grimm <patrick@lunatiki.de>
* @date 2020
* @copyright SPDX-License-Identifier: MIT
*/
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <zephyr/ztest.h>
#include <bacnet/datalink/bsc/bsc-event.h>
typedef enum {
STAGE_NONE,
STAGE_WAIT_1,
STAGE_WAIT_2,
STAGE_TIMEDWAIT_TIMEOUT,
STAGE_TIMEDWAIT_OK,
} TEST_STAGE;
static TEST_STAGE test_stage = STAGE_NONE;
#define TIMEOUT_CHILD 400
#define TIMEOUT_MIN 200
#define TIMEOUT_MAX 600
#define TIMEOUT_SLEEP 2
#define WAITTIME_MIN (TIMEOUT_SLEEP * 1000 - 100)
#define WAITTIME_MAX (TIMEOUT_SLEEP * 1000 + 100)
#define MULTIPLE_WAIT_THREADS_NUM 50
DWORD WINAPI child_func(LPVOID lpParam)
{
BSC_EVENT *event = (BSC_EVENT *)lpParam;
zassert_not_null(event, NULL);
while (test_stage != STAGE_WAIT_1) {
Sleep(1);
}
bsc_event_signal(event);
while (test_stage != STAGE_WAIT_2) {
Sleep(1);
}
bsc_event_signal(event);
while (test_stage != STAGE_TIMEDWAIT_TIMEOUT) {
Sleep(1);
}
Sleep(TIMEOUT_CHILD);
bsc_event_signal(event);
while (test_stage != STAGE_TIMEDWAIT_OK) {
Sleep(1);
}
Sleep(TIMEOUT_CHILD);
bsc_event_signal(event);
return 0;
}
static void test_bsc_event1(void)
{
BSC_EVENT *event;
HANDLE thread;
DWORD threadID;
bool b;
ULONGLONG time1;
ULONGLONG time2;
ULONGLONG timediff;
test_stage = STAGE_NONE;
event = bsc_event_init();
zassert_not_null(event, NULL);
// run child and wait when child running
thread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)child_func, event,
0, // default creation flags
&threadID); // receive thread identifier
zassert_not_null(thread, NULL);
test_stage = STAGE_WAIT_1;
bsc_event_wait(event);
test_stage = STAGE_WAIT_2;
bsc_event_wait(event);
test_stage = STAGE_TIMEDWAIT_TIMEOUT;
b = bsc_event_timedwait(event, TIMEOUT_MIN);
zassert_false(b, NULL);
test_stage = STAGE_TIMEDWAIT_OK;
b = bsc_event_timedwait(event, TIMEOUT_MAX);
zassert_true(b, NULL);
time1 = GetTickCount64();
bsc_wait(TIMEOUT_SLEEP);
time2 = GetTickCount64();
timediff = time2 - time1;
zassert_true(timediff >= TIMEOUT_SLEEP * 1000, NULL);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
bsc_event_deinit(event);
}
DWORD WINAPI thread_func(LPVOID lpParam)
{
BSC_EVENT *event = (BSC_EVENT *)lpParam;
zassert_not_null(event, NULL);
bsc_event_wait(event);
return 0;
}
static void test_bsc_event2(void)
{
int i;
BSC_EVENT *event;
DWORD tid[MULTIPLE_WAIT_THREADS_NUM];
HANDLE thread[MULTIPLE_WAIT_THREADS_NUM];
event = bsc_event_init();
zassert_not_null(event, NULL);
for (i = 0; i < MULTIPLE_WAIT_THREADS_NUM; i++) {
thread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)thread_func, event,
0, // default creation flags
&tid[i]); // receive thread identifier
zassert_not_null(thread[i], NULL);
}
bsc_wait(1);
bsc_event_signal(event);
for (i = 0; i < MULTIPLE_WAIT_THREADS_NUM; i++) {
WaitForSingleObject(thread[i], INFINITE);
CloseHandle(thread[i]);
}
bsc_event_deinit(event);
}
typedef struct {
BSC_EVENT *event;
BOOL result;
} test_param_t;
DWORD WINAPI thread_func2(LPVOID lpParam)
{
test_param_t *p = (test_param_t *)lpParam;
zassert_not_null(p->event, NULL);
// use some big timeout value, 24 hours seems to be enough
p->result = bsc_event_timedwait(p->event, 24 * 60 * 60 * 1000);
return 0;
}
static void test_bsc_event3(void)
{
int i;
BSC_EVENT *event;
DWORD tid[MULTIPLE_WAIT_THREADS_NUM];
HANDLE thread[MULTIPLE_WAIT_THREADS_NUM];
test_param_t results[MULTIPLE_WAIT_THREADS_NUM];
event = bsc_event_init();
zassert_not_null(event, NULL);
for (i = 0; i < MULTIPLE_WAIT_THREADS_NUM; i++) {
results[i].event = event;
results[i].result = FALSE;
thread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)thread_func2, &results[i],
0, // default creation flags
&tid[i]); // receive thread identifier
zassert_not_null(thread[i], NULL);
}
bsc_wait(1);
bsc_event_signal(event);
for (i = 0; i < MULTIPLE_WAIT_THREADS_NUM; i++) {
WaitForSingleObject(thread[i], INFINITE);
CloseHandle(thread[i]);
}
for (i = 0; i < MULTIPLE_WAIT_THREADS_NUM; i++) {
zassert_equal(results[i].result == true, true, NULL);
}
bsc_event_deinit(event);
}
void test_main(void)
{
ztest_test_suite(bsc_event_test1, ztest_unit_test(test_bsc_event1));
ztest_test_suite(bsc_event_test2, ztest_unit_test(test_bsc_event2));
ztest_test_suite(bsc_event_test3, ztest_unit_test(test_bsc_event3));
ztest_run_test_suite(bsc_event_test1);
ztest_run_test_suite(bsc_event_test2);
ztest_run_test_suite(bsc_event_test3);
}