blob: b77723e7d397d547d72b0159d5f92fae35383f6d [file] [log] [blame]
#ifndef OPEN62541_MT_TESTING_H
#define OPEN62541_MT_TESTING_H
#include <open62541/server_config_default.h>
#define THREAD_CALLBACK_PARAM(name, param) static void * name(void *param)
#define THREAD_CREATE_PARAM(handle, callback, param) pthread_create(&(handle), NULL, callback, (void*) &(param))
typedef struct {
void (*func)(void *param); //function to execute
size_t counter; //index of the iteration
size_t index; // index within workerContext array of global TestContext
size_t upperBound; //number of iterations each thread schould execute func
THREAD_HANDLE handle;
} ThreadContext;
typedef struct {
size_t numberOfWorkers;
ThreadContext *workerContext;
size_t numberofClients;
ThreadContext *clientContext;
UA_Boolean running;
UA_Server *server;
UA_Client **clients;
void (*checkServerNodes)(void);
} TestContext;
TestContext tc;
THREAD_HANDLE server_thread;
THREAD_CALLBACK(serverloop) {
while(tc.running)
UA_Server_run_iterate(tc.server, true);
return 0;
}
static
void teardown(void) {
for (size_t i = 0; i < tc.numberOfWorkers; i++)
THREAD_JOIN(tc.workerContext[i].handle);
for (size_t i = 0; i < tc.numberofClients; i++)
THREAD_JOIN(tc.clientContext[i].handle);
tc.running = false;
THREAD_JOIN(server_thread);
if (tc.checkServerNodes)
tc.checkServerNodes();
UA_Server_run_shutdown(tc.server);
UA_Server_delete(tc.server);
}
THREAD_CALLBACK_PARAM(workerLoop, val) {
ThreadContext tmp = (*(ThreadContext *) val);
for (size_t i = 0; i < tmp.upperBound; i++) {
tmp.counter = i;
tmp.func(&tmp);
}
return NULL;
}
THREAD_CALLBACK_PARAM(clientLoop, val) {
ThreadContext tmp = (*(ThreadContext *) val);
tc.clients[tmp.index] = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(tc.clients[tmp.index]));
UA_StatusCode retval = UA_Client_connect(tc.clients[tmp.index], "opc.tcp://localhost:4840");
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
for(size_t i = 0; i < tmp.upperBound; i++) {
tmp.counter = i;
tmp.func(&tmp);
}
UA_Client_disconnect(tc.clients[tmp.index]);
UA_Client_delete(tc.clients[tmp.index]);
return NULL;
}
static UA_INLINE void
initThreadContext(size_t numberOfWorkers, size_t numberOfClients, void (*checkServerNodes)(void)) {
tc.numberOfWorkers = numberOfWorkers;
tc.numberofClients = numberOfClients;
tc.checkServerNodes = checkServerNodes;
tc.workerContext = (ThreadContext*) UA_calloc(tc.numberOfWorkers, sizeof(ThreadContext));
tc.clients = (UA_Client**) UA_calloc(tc.numberofClients, sizeof(UA_Client*));
tc.clientContext = (ThreadContext*) UA_calloc(tc.numberofClients, sizeof(ThreadContext));
}
static UA_INLINE void
setThreadContext(ThreadContext *workerContext, size_t index, size_t upperBound, void (*func)(void *param)) {
workerContext->index = index;
workerContext->upperBound = upperBound;
workerContext->func = func;
}
static UA_INLINE void
startMultithreading(void) {
for (size_t i = 0; i < tc.numberOfWorkers; i++)
THREAD_CREATE_PARAM(tc.workerContext[i].handle, workerLoop, tc.workerContext[i]);
for (size_t i = 0; i < tc.numberofClients; i++)
THREAD_CREATE_PARAM(tc.clientContext[i].handle, clientLoop, tc.clientContext[i]);
}
#endif //OPEN62541_MT_TESTING_H