blob: 156c7557995fbc9eef10069813a77fefcf1f70bb [file] [log] [blame]
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <open62541/client.h>
#include <open62541/client_config_default.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>
#include "server/ua_server_internal.h"
#include <check.h>
#include <stdio.h>
#include <stdlib.h>
#include "thread_wrapper.h"
UA_Server *server_translate_browse;
UA_Boolean *running_translate_browse;
THREAD_HANDLE server_thread_translate_browse;
THREAD_CALLBACK(serverloop_register) {
while (*running_translate_browse)
UA_Server_run_iterate(server_translate_browse, true);
return 0;
}
static void setup_server(void) {
// start server
running_translate_browse = UA_Boolean_new();
*running_translate_browse = true;
server_translate_browse = UA_Server_new();
UA_ServerConfig *server_translate_config = UA_Server_getConfig(server_translate_browse);
UA_ServerConfig_setDefault(server_translate_config);
UA_String_deleteMembers(&server_translate_config->applicationDescription.applicationUri);
server_translate_config->applicationDescription.applicationUri =
UA_String_fromChars("urn:open62541.test.server_translate_browse");
UA_Server_run_startup(server_translate_browse);
THREAD_CREATE(server_thread_translate_browse, serverloop_register);
}
static void teardown_server(void) {
*running_translate_browse = false;
THREAD_JOIN(server_thread_translate_browse);
UA_Server_run_shutdown(server_translate_browse);
UA_Boolean_delete(running_translate_browse);
UA_Server_delete(server_translate_browse);
}
static size_t
browseWithMaxResults(UA_Server *server, UA_NodeId nodeId, UA_UInt32 maxResults) {
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.nodeId = nodeId;
bd.resultMask = UA_BROWSERESULTMASK_ALL;
bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
UA_BrowseResult br = UA_Server_browse(server, maxResults, &bd);
ck_assert_int_eq(br.statusCode, UA_STATUSCODE_GOOD);
ck_assert(br.referencesSize > 0);
ck_assert(br.referencesSize <= maxResults);
size_t total = br.referencesSize;
UA_ByteString cp = br.continuationPoint;
br.continuationPoint = UA_BYTESTRING_NULL;
UA_BrowseResult_deleteMembers(&br);
while(cp.length > 0) {
br = UA_Server_browseNext(server, false, &cp);
ck_assert(br.referencesSize > 0);
ck_assert(br.referencesSize <= maxResults);
UA_ByteString_deleteMembers(&cp);
cp = br.continuationPoint;
br.continuationPoint = UA_BYTESTRING_NULL;
total += br.referencesSize;
UA_BrowseResult_deleteMembers(&br);
}
return total;
}
START_TEST(Service_Browse_WithMaxResults) {
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.resultMask = UA_BROWSERESULTMASK_ALL;
bd.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
UA_BrowseResult br = UA_Server_browse(server, 0, &bd);
ck_assert_int_eq(br.statusCode, UA_STATUSCODE_GOOD);
ck_assert(br.referencesSize > 0);
size_t total = br.referencesSize;
UA_BrowseResult_deleteMembers(&br);
for(UA_UInt32 i = 1; i <= total; i++) {
size_t sum_total =
browseWithMaxResults(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), i);
ck_assert_int_eq(total, sum_total);
}
UA_Server_delete(server);
}
END_TEST
START_TEST(Service_Browse_WithBrowseName) {
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
bd.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
UA_BrowseResult br = UA_Server_browse(server, 0, &bd);
ck_assert_int_eq(br.statusCode, UA_STATUSCODE_GOOD);
ck_assert(br.referencesSize > 0);
ck_assert(!UA_String_equal(&br.references[0].browseName.name, &UA_STRING_NULL));
UA_BrowseResult_deleteMembers(&br);
UA_Server_delete(server);
}
END_TEST
START_TEST(Service_Browse_Recursive) {
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
size_t resultSize = 0;
UA_ExpandedNodeId *result = NULL;
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
bd.includeSubtypes = true;
bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
UA_StatusCode retval = UA_Server_browseRecursive(server, &bd, &resultSize, &result);
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(resultSize, 3);
UA_NodeId expected[3];
expected[0] = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
expected[1] = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
expected[2] = UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER);
for(size_t i = 0; i < resultSize; i++) {
ck_assert(UA_NodeId_equal(&expected[i], &result[i].nodeId));
}
UA_Array_delete(result, resultSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
UA_Server_delete(server);
}
END_TEST
START_TEST(Service_TranslateBrowsePathsToNodeIds) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
UA_StatusCode retVal = UA_Client_connect(client, "opc.tcp://localhost:4840");
ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
// Just for testing we want to translate the following path to its corresponding node id
// /Objects/Server/ServerStatus/State
// Equals the following node IDs:
// /85/2253/2256/2259
#define BROWSE_PATHS_SIZE 3
char *paths[BROWSE_PATHS_SIZE] = {"Server", "ServerStatus", "State"};
UA_UInt32 ids[BROWSE_PATHS_SIZE] = {UA_NS0ID_ORGANIZES, UA_NS0ID_HASCOMPONENT, UA_NS0ID_HASCOMPONENT};
UA_BrowsePath browsePath;
UA_BrowsePath_init(&browsePath);
browsePath.startingNode = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
browsePath.relativePath.elements = (UA_RelativePathElement*)UA_Array_new(BROWSE_PATHS_SIZE, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]);
browsePath.relativePath.elementsSize = BROWSE_PATHS_SIZE;
for(size_t i = 0; i < BROWSE_PATHS_SIZE; i++) {
UA_RelativePathElement *elem = &browsePath.relativePath.elements[i];
elem->referenceTypeId = UA_NODEID_NUMERIC(0, ids[i]);
elem->targetName = UA_QUALIFIEDNAME_ALLOC(0, paths[i]);
}
UA_TranslateBrowsePathsToNodeIdsRequest request;
UA_TranslateBrowsePathsToNodeIdsRequest_init(&request);
request.browsePaths = &browsePath;
request.browsePathsSize = 1;
UA_TranslateBrowsePathsToNodeIdsResponse response = UA_Client_Service_translateBrowsePathsToNodeIds(client, request);
ck_assert_int_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_int_eq(response.resultsSize, 1);
ck_assert_int_eq(response.results[0].targetsSize, 1);
ck_assert_int_eq(response.results[0].targets[0].targetId.nodeId.identifierType, UA_NODEIDTYPE_NUMERIC);
ck_assert_int_eq(response.results[0].targets[0].targetId.nodeId.identifier.numeric, UA_NS0ID_SERVER_SERVERSTATUS_STATE);
UA_BrowsePath_deleteMembers(&browsePath);
UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers(&response);
retVal = UA_Client_disconnect(client);
ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
UA_Client_delete(client);
}
END_TEST
START_TEST(BrowseSimplifiedBrowsePath) {
UA_QualifiedName objectsName = UA_QUALIFIEDNAME(0, "Objects");
UA_BrowsePathResult bpr =
UA_Server_browseSimplifiedBrowsePath(server_translate_browse,
UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
1, &objectsName);
ck_assert_int_eq(bpr.targetsSize, 1);
UA_BrowsePathResult_deleteMembers(&bpr);
}
END_TEST
static Suite *testSuite_Service_TranslateBrowsePathsToNodeIds(void) {
Suite *s = suite_create("Service_TranslateBrowsePathsToNodeIds");
TCase *tc_browse = tcase_create("Browse Service");
tcase_add_test(tc_browse, Service_Browse_WithBrowseName);
tcase_add_test(tc_browse, Service_Browse_WithMaxResults);
tcase_add_test(tc_browse, Service_Browse_Recursive);
suite_add_tcase(s, tc_browse);
TCase *tc_translate = tcase_create("TranslateBrowsePathsToNodeIds");
tcase_add_unchecked_fixture(tc_translate, setup_server, teardown_server);
tcase_add_test(tc_translate, Service_TranslateBrowsePathsToNodeIds);
tcase_add_test(tc_translate, BrowseSimplifiedBrowsePath);
suite_add_tcase(s, tc_translate);
return s;
}
int main(void) {
int number_failed = 0;
Suite *s;
SRunner *sr;
s = testSuite_Service_TranslateBrowsePathsToNodeIds();
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_NORMAL);
number_failed += srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}