Files
open62541/tests/client/check_client_highlevel.c
Julius Pfrommer 287c5ad69b fix(server): Make the BrowseName of Nodes immutable
The BrowseName is tracked in binary trees in other nodes for fast
lookup. We would have to reinsert the node to all references lists
of other nodes pointing here.
2020-03-29 21:27:39 +02:00

1081 lines
44 KiB
C

/* 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/client_highlevel.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>
#include <check.h>
#include "thread_wrapper.h"
UA_Server *server;
UA_Boolean running;
UA_ServerNetworkLayer nl;
THREAD_HANDLE server_thread;
UA_Client *client;
#define CUSTOM_NS "http://open62541.org/ns/test"
#define CUSTOM_NS_UPPER "http://open62541.org/ns/Test"
THREAD_CALLBACK(serverloop) {
while (running)
UA_Server_run_iterate(server, true);
return 0;
}
static void setup(void) {
running = true;
server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
ck_assert_uint_eq(2, UA_Server_addNamespace(server, CUSTOM_NS));
UA_Server_run_startup(server);
THREAD_CREATE(server_thread, serverloop);
client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
static void teardown(void) {
UA_Client_disconnect(client);
UA_Client_delete(client);
running = false;
THREAD_JOIN(server_thread);
UA_Server_run_shutdown(server);
UA_Server_delete(server);
}
START_TEST(Misc_State) {
UA_ClientState state = UA_Client_getState(client);
ck_assert_uint_eq(state, UA_CLIENTSTATE_SESSION);
}
END_TEST
START_TEST(Misc_NamespaceGetIndex) {
UA_UInt16 idx;
UA_String ns = UA_STRING(CUSTOM_NS);
UA_StatusCode retval = UA_Client_NamespaceGetIndex(client, &ns, &idx);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(idx, 2);
// namespace uri is case sensitive
ns = UA_STRING(CUSTOM_NS_UPPER);
retval = UA_Client_NamespaceGetIndex(client, &ns, &idx);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADNOTFOUND);
} END_TEST
UA_NodeId newReferenceTypeId;
UA_NodeId newObjectTypeId;
UA_NodeId newDataTypeId;
UA_NodeId newVariableTypeId;
UA_NodeId newObjectId;
UA_NodeId newVariableId;
UA_NodeId newMethodId;
UA_NodeId newViewId;
#ifdef UA_ENABLE_NODEMANAGEMENT
START_TEST(Node_Add) {
UA_StatusCode retval;
// Create custom reference type 'HasSubSubType' as child of HasSubtype
{
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some HasSubSubType");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "HasSubSubType");
retval = UA_Client_addReferenceTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "HasSubSubType"), attr,
&newReferenceTypeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// Create TestObjectType SubType within BaseObjectType
{
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some TestObjectType");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "TestObjectType");
retval = UA_Client_addObjectTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "TestObjectType"), attr, &newObjectTypeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
/* Minimal nodeset does not contain UA_NS0ID_INTEGER node */
#ifdef UA_GENERATED_NAMESPACE_ZERO
// Create Int128 DataType within Integer Datatype
{
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some Int128");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int128");
retval = UA_Client_addDataTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_INTEGER),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "Int128"), attr, &newDataTypeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
#endif
// Create PointType VariableType within BaseDataVariableType
{
UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
UA_UInt32 arrayDims[1] = {2};
attr.arrayDimensions = arrayDims;
attr.arrayDimensionsSize = 1;
attr.displayName = UA_LOCALIZEDTEXT("en-US", "PointType");
/* a matching default value is required */
UA_Double zero[2] = {0.0, 0.0};
UA_Variant_setArray(&attr.value, zero, 2, &UA_TYPES[UA_TYPES_INT32]);
retval = UA_Client_addVariableTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "PointType"), attr, &newVariableTypeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Coordinates Object within ObjectsFolder
{
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some Coordinates");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Coordinates");
retval = UA_Client_addObjectNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "Coordinates"),
UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), attr, &newObjectId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Variable 'Top' within Coordinates Object
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Top Coordinate");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Top");
UA_Int32 values[2] = {10, 20};
UA_Variant_setArray(&attr.value, values, 2, &UA_TYPES[UA_TYPES_INT32]);
attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
UA_UInt32 arrayDims[1] = {2};
attr.arrayDimensions = arrayDims;
attr.arrayDimensionsSize = 1;
retval = UA_Client_addVariableNode(client, UA_NODEID_NULL,
newObjectId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
UA_QUALIFIEDNAME(1, "Top"),
newVariableTypeId, attr, &newVariableId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Method 'Dummy' within Coordinates Object.
{
UA_MethodAttributes attr = UA_MethodAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Dummy method");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Dummy");
attr.executable = true;
attr.userExecutable = true;
retval = UA_Client_addMethodNode(client, UA_NODEID_NULL,
newObjectId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
UA_QUALIFIEDNAME(1, "Dummy"),
attr, &newMethodId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create View 'AllTopCoordinates' whithin Views Folder
{
UA_ViewAttributes attr = UA_ViewAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "List of all top coordinates");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "AllTopCoordinates");
retval = UA_Client_addViewNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "AllTopCoordinates"),
attr, &newViewId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
UA_ExpandedNodeId target = UA_EXPANDEDNODEID_NULL;
target.nodeId = newObjectId;
// Add 'Top' to view
retval = UA_Client_addReference(client, newViewId, UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_TRUE, UA_STRING_NULL, target, UA_NODECLASS_VARIABLE);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// Delete 'Top' from view
retval = UA_Client_deleteReference(client, newViewId,
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
true, target, true);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// Delete 'AllTopCoordinates' view
retval = UA_Client_deleteNode(client, newViewId, UA_TRUE);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
END_TEST
unsigned int iteratedNodeCount = 0;
UA_NodeId iteratedNodes[4];
static UA_StatusCode
nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) {
if (isInverse || (referenceTypeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
referenceTypeId.identifier.numeric == UA_NS0ID_HASTYPEDEFINITION))
return UA_STATUSCODE_GOOD;
if (iteratedNodeCount >= 4)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
UA_NodeId_copy(&childId, &iteratedNodes[iteratedNodeCount]);
iteratedNodeCount++;
return UA_STATUSCODE_GOOD;
}
#endif
START_TEST(Node_Browse) {
// Browse node in server folder
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
// normally is set to 0, to get all the nodes, but we want to test browse next
bReq.requestedMaxReferencesPerNode = 1;
bReq.nodesToBrowse = UA_BrowseDescription_new();
bReq.nodesToBrowseSize = 1;
bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL;
UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
ck_assert_uint_eq(bResp.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bResp.resultsSize, 1);
ck_assert_uint_eq(bResp.results[0].statusCode, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bResp.results[0].referencesSize, 1);
/* References might have a different order in generated nodesets */
/* UA_ReferenceDescription *ref = &(bResp.results[0].references[0]); */
/* ck_assert_uint_eq(ref->nodeId.nodeId.identifier.numeric, UA_NS0ID_SERVERTYPE); */
// browse next
UA_BrowseNextRequest bNextReq;
UA_BrowseNextRequest_init(&bNextReq);
// normally is set to 0, to get all the nodes, but we want to test browse next
bNextReq.releaseContinuationPoints = UA_FALSE;
bNextReq.continuationPoints = &bResp.results[0].continuationPoint;
bNextReq.continuationPointsSize = 1;
UA_BrowseNextResponse bNextResp = UA_Client_Service_browseNext(client, bNextReq);
ck_assert_uint_eq(bNextResp.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bNextResp.resultsSize, 1);
ck_assert_uint_eq(bNextResp.results[0].statusCode, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bNextResp.results[0].referencesSize, 1);
/* ref = &(bNextResp.results[0].references[0]); */
/* ck_assert_uint_eq(ref->nodeId.nodeId.identifier.numeric, UA_NS0ID_SERVER_NAMESPACEARRAY); */
UA_BrowseNextResponse_deleteMembers(&bNextResp);
bNextResp = UA_Client_Service_browseNext(client, bNextReq);
ck_assert_uint_eq(bNextResp.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bNextResp.resultsSize, 1);
ck_assert_uint_eq(bNextResp.results[0].statusCode, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bNextResp.results[0].referencesSize, 1);
/* ref = &(bNextResp.results[0].references[0]); */
/* ck_assert_uint_eq(ref->nodeId.nodeId.identifier.numeric, UA_NS0ID_SERVER_SERVERARRAY); */
UA_BrowseNextResponse_deleteMembers(&bNextResp);
// release continuation point. Result is then empty
bNextReq.releaseContinuationPoints = UA_TRUE;
bNextResp = UA_Client_Service_browseNext(client, bNextReq);
UA_BrowseNextResponse_deleteMembers(&bNextResp);
ck_assert_uint_eq(bNextResp.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(bNextResp.resultsSize, 0);
UA_BrowseRequest_deleteMembers(&bReq);
UA_BrowseResponse_deleteMembers(&bResp);
// already deleted by browse request
bNextReq.continuationPoints = NULL;
bNextReq.continuationPointsSize = 0;
UA_BrowseNextRequest_deleteMembers(&bNextReq);
}
END_TEST
START_TEST(Node_Register) {
UA_RegisterNodesRequest req;
UA_RegisterNodesRequest_init(&req);
req.nodesToRegister = UA_NodeId_new();
req.nodesToRegister[0] = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
req.nodesToRegisterSize = 1;
UA_RegisterNodesResponse res = UA_Client_Service_registerNodes(client, req);
ck_assert_uint_eq(res.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(res.registeredNodeIdsSize, 1);
UA_UnregisterNodesRequest reqUn;
UA_UnregisterNodesRequest_init(&reqUn);
reqUn.nodesToUnregister = UA_NodeId_new();
reqUn.nodesToUnregister[0] = res.registeredNodeIds[0];
reqUn.nodesToUnregisterSize = 1;
UA_UnregisterNodesResponse resUn = UA_Client_Service_unregisterNodes(client, reqUn);
ck_assert_uint_eq(resUn.responseHeader.serviceResult, UA_STATUSCODE_GOOD);
UA_UnregisterNodesRequest_deleteMembers(&reqUn);
UA_UnregisterNodesResponse_deleteMembers(&resUn);
UA_RegisterNodesRequest_deleteMembers(&req);
UA_RegisterNodesResponse_deleteMembers(&res);
}
END_TEST
// NodeIds for ReadWrite testing
UA_NodeId nodeReadWriteUnitTest;
UA_NodeId nodeReadWriteArray;
UA_NodeId nodeReadWriteInt;
UA_NodeId nodeReadWriteGeneric;
UA_NodeId nodeReadWriteTestObjectType;
UA_NodeId nodeReadWriteTestHasSubSubType;
UA_NodeId nodeReadWriteView;
UA_NodeId nodeReadWriteMethod;
#ifdef UA_ENABLE_NODEMANAGEMENT
START_TEST(Node_AddReadWriteNodes) {
UA_StatusCode retval;
// Create a folder with two variables for testing
// create Coordinates Object within ObjectsFolder
{
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "UnitTest");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "UnitTest");
retval = UA_Client_addObjectNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "UnitTest"),
UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE),
attr, &nodeReadWriteUnitTest);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Variable 'Top' within UnitTest Object
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Array");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Array");
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
attr.writeMask = UA_WRITEMASK_ARRRAYDIMENSIONS;
UA_Int32 values[2];
values[0] = 10;
values[1] = 20;
UA_Variant_setArray(&attr.value, values, 2, &UA_TYPES[UA_TYPES_INT32]);
attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
UA_UInt32 arrayDims[1] = {2};
attr.arrayDimensions = arrayDims;
attr.arrayDimensionsSize = 1;
retval = UA_Client_addVariableNode(client, UA_NODEID_NULL,
nodeReadWriteUnitTest,
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "Array"),
UA_NODEID_NULL, attr, &nodeReadWriteArray);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Variable 'Int' within UnitTest Object
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Int");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int");
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
attr.writeMask = 0xFFFFFFFF;
UA_Int32 int_value = 5678;
UA_Variant_setScalar(&attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]);
attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
retval = UA_Client_addVariableNode(client, UA_NODEID_NULL,
nodeReadWriteUnitTest,
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "Int"),
UA_NODEID_NULL, attr, &nodeReadWriteInt);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Variable 'Generic' within UnitTest Object
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Generic");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Generic");
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
attr.writeMask = 0xFFFFFFFF;
// generic datatype
attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
retval = UA_Client_addVariableNode(client, UA_NODEID_NULL,
nodeReadWriteUnitTest,
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "Generic"),
UA_NODEID_NULL, attr, &nodeReadWriteGeneric);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create Method 'Dummy' within Coordinates Object.
{
UA_MethodAttributes attr = UA_MethodAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Dummy method");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Dummy");
attr.executable = true;
attr.userExecutable = true;
attr.writeMask = 0xFFFFFFFF;
retval = UA_Client_addMethodNode(client, UA_NODEID_NULL,
nodeReadWriteUnitTest,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
UA_QUALIFIEDNAME(1, "Dummy"),
attr, &nodeReadWriteMethod);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// Create TestObjectType SubType within BaseObjectType
{
UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some TestObjectType");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "TestObjectType");
attr.writeMask = 0xFFFFFFFF;
retval = UA_Client_addObjectTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "TestObjectType"), attr, &nodeReadWriteTestObjectType);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// Create custom reference type 'HasSubSubType' as child of HasSubtype
{
UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "Some HasSubSubType");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "HasSubSubType");
attr.inverseName = UA_LOCALIZEDTEXT("en-US", "HasParentParentType");
attr.writeMask = 0xFFFFFFFF;
retval = UA_Client_addReferenceTypeNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "HasSubSubType"), attr,
&nodeReadWriteTestHasSubSubType);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// create View 'AllTopCoordinates' whithin Views Folder
{
UA_ViewAttributes attr = UA_ViewAttributes_default;
attr.description = UA_LOCALIZEDTEXT("en-US", "List of all top coordinates");
attr.displayName = UA_LOCALIZEDTEXT("en-US", "AllTopCoordinates");
attr.writeMask = 0xFFFFFFFF;
retval = UA_Client_addViewNode(client, UA_NODEID_NULL,
UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "AllTopCoordinates"),
attr, &nodeReadWriteView);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
// iterate over children
retval = UA_Client_forEachChildNodeCall(client, nodeReadWriteUnitTest, nodeIter, NULL);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_NodeId_equal(&nodeReadWriteArray, &iteratedNodes[0]));
ck_assert(UA_NodeId_equal(&nodeReadWriteInt, &iteratedNodes[1]));
}
END_TEST
START_TEST(Node_ReadWrite_Id) {
UA_NodeId newNodeId;
// read to check if node id was changed
UA_StatusCode retval = UA_Client_readNodeIdAttribute(client, nodeReadWriteInt, &newNodeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_NodeId_equal(&newNodeId, &nodeReadWriteInt));
newNodeId.identifier.numeric = 900;
retval = UA_Client_writeNodeIdAttribute(client, nodeReadWriteInt, &newNodeId);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
static void checkNodeClass(UA_Client *clientNc, const UA_NodeId nodeId, const UA_NodeClass expectedClass) {
UA_NodeClass nodeClass = UA_NODECLASS_UNSPECIFIED;
UA_StatusCode retval = UA_Client_readNodeClassAttribute(clientNc, nodeId, &nodeClass);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(nodeClass, expectedClass);
}
START_TEST(Node_ReadWrite_Class) {
checkNodeClass(client, nodeReadWriteInt, UA_NODECLASS_VARIABLE);
checkNodeClass(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), UA_NODECLASS_OBJECT);
/* Minimal nodeset does not contain UA_NS0ID_SERVER_GETMONITOREDITEMS node */
#if defined(UA_ENABLE_METHODCALLS) && defined(UA_GENERATED_NAMESPACE_ZERO)
checkNodeClass(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), UA_NODECLASS_METHOD);
#endif
UA_NodeClass newClass = UA_NODECLASS_METHOD;
UA_StatusCode retval = UA_Client_writeNodeClassAttribute(client, nodeReadWriteInt, &newClass);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
START_TEST(Node_ReadWrite_BrowseName) {
UA_QualifiedName browseName;
UA_StatusCode retval = UA_Client_readBrowseNameAttribute(client, nodeReadWriteInt, &browseName);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_QualifiedName orig = UA_QUALIFIEDNAME(1, "Int");
ck_assert_int_eq(browseName.namespaceIndex, orig.namespaceIndex);
ck_assert(UA_String_equal(&browseName.name, &orig.name));
UA_QualifiedName_deleteMembers(&browseName);
browseName = UA_QUALIFIEDNAME(1,"Int-Changed");
retval = UA_Client_writeBrowseNameAttribute(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), &browseName);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
retval = UA_Client_writeBrowseNameAttribute(client, nodeReadWriteInt, &browseName);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
START_TEST(Node_ReadWrite_DisplayName) {
UA_LocalizedText displayName;
UA_StatusCode retval = UA_Client_readDisplayNameAttribute(client, nodeReadWriteInt, &displayName);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText orig = UA_LOCALIZEDTEXT("en-US", "Int");
ck_assert(UA_String_equal(&displayName.locale, &orig.locale));
ck_assert(UA_String_equal(&displayName.text, &orig.text));
UA_LocalizedText_deleteMembers(&displayName);
UA_LocalizedText newLocale = UA_LOCALIZEDTEXT("en-US", "Int-Changed");
retval = UA_Client_writeDisplayNameAttribute(client, nodeReadWriteInt, &newLocale);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText displayNameChangedRead;
retval = UA_Client_readDisplayNameAttribute(client, nodeReadWriteInt, &displayNameChangedRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_String_equal(&newLocale.locale, &displayNameChangedRead.locale));
ck_assert(UA_String_equal(&newLocale.text, &displayNameChangedRead.text));
UA_LocalizedText_deleteMembers(&displayNameChangedRead);
}
END_TEST
START_TEST(Node_ReadWrite_Description) {
UA_LocalizedText description;
UA_StatusCode retval = UA_Client_readDescriptionAttribute(client, nodeReadWriteInt, &description);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText orig = UA_LOCALIZEDTEXT("en-US", "Int");
ck_assert(UA_String_equal(&description.locale, &orig.locale));
ck_assert(UA_String_equal(&description.text, &orig.text));
UA_LocalizedText_deleteMembers(&description);
UA_LocalizedText newLocale = UA_LOCALIZEDTEXT("en-US", "Int-Changed");
retval = UA_Client_writeDescriptionAttribute(client, nodeReadWriteInt, &newLocale);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText descriptionChangedRead;
retval = UA_Client_readDescriptionAttribute(client, nodeReadWriteInt, &descriptionChangedRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_String_equal(&newLocale.locale, &descriptionChangedRead.locale));
ck_assert(UA_String_equal(&newLocale.text, &descriptionChangedRead.text));
UA_LocalizedText_deleteMembers(&descriptionChangedRead);
}
END_TEST
START_TEST(Node_ReadWrite_WriteMask) {
UA_UInt32 writeMask;
UA_StatusCode retval = UA_Client_readWriteMaskAttribute(client, nodeReadWriteInt, &writeMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(writeMask, 0xFFFFFFFF);
// Disable a random write mask bit
UA_UInt32 newMask = 0xFFFFFFFF & ~UA_WRITEMASK_BROWSENAME;
retval = UA_Client_writeWriteMaskAttribute(client, nodeReadWriteInt, &newMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_UInt32 writeMaskChangedRead;
retval = UA_Client_readWriteMaskAttribute(client, nodeReadWriteInt, &writeMaskChangedRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(writeMaskChangedRead, newMask);
}
END_TEST
START_TEST(Node_ReadWrite_UserWriteMask) {
UA_UInt32 userWriteMask;
UA_StatusCode retval = UA_Client_readUserWriteMaskAttribute(client, nodeReadWriteInt, &userWriteMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(userWriteMask, 0xFFFFFFFF & ~UA_WRITEMASK_BROWSENAME);
// Disable a random write mask bit
UA_UInt32 newMask = 0xFFFFFFFF & ~UA_WRITEMASK_DISPLAYNAME;
retval = UA_Client_writeUserWriteMaskAttribute(client, nodeReadWriteInt, &newMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
START_TEST(Node_ReadWrite_IsAbstract) {
UA_Boolean isAbstract;
UA_StatusCode retval = UA_Client_readIsAbstractAttribute(client, nodeReadWriteInt, &isAbstract);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
retval = UA_Client_readIsAbstractAttribute(client, nodeReadWriteTestObjectType, &isAbstract);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(isAbstract, UA_FALSE);
UA_Boolean newIsAbstract = UA_TRUE;
retval = UA_Client_writeIsAbstractAttribute(client, nodeReadWriteTestObjectType, &newIsAbstract);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readIsAbstractAttribute(client, nodeReadWriteTestObjectType, &isAbstract);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(isAbstract, newIsAbstract);
}
END_TEST
START_TEST(Node_ReadWrite_Symmetric) {
UA_Boolean symmetric;
UA_StatusCode retval = UA_Client_readSymmetricAttribute(client, nodeReadWriteInt, &symmetric);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
retval = UA_Client_readSymmetricAttribute(client, nodeReadWriteTestHasSubSubType, &symmetric);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(symmetric, UA_FALSE);
UA_Boolean newSymmetric = UA_TRUE;
retval = UA_Client_writeSymmetricAttribute(client, nodeReadWriteTestHasSubSubType, &newSymmetric);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readSymmetricAttribute(client, nodeReadWriteTestHasSubSubType, &symmetric);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(symmetric, newSymmetric);
}
END_TEST
START_TEST(Node_ReadWrite_InverseName) {
UA_LocalizedText inverseName;
UA_StatusCode retval = UA_Client_readInverseNameAttribute(client, nodeReadWriteTestHasSubSubType, &inverseName);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText orig = UA_LOCALIZEDTEXT("en-US", "HasParentParentType");
ck_assert(UA_String_equal(&inverseName.locale, &orig.locale));
ck_assert(UA_String_equal(&inverseName.text, &orig.text));
UA_LocalizedText_deleteMembers(&inverseName);
UA_LocalizedText newLocale = UA_LOCALIZEDTEXT("en-US", "HasParentParentType-Changed");
retval = UA_Client_writeInverseNameAttribute(client, nodeReadWriteTestHasSubSubType, &newLocale);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_LocalizedText inverseNameChangedRead;
retval = UA_Client_readInverseNameAttribute(client, nodeReadWriteTestHasSubSubType, &inverseNameChangedRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_String_equal(&newLocale.locale, &inverseNameChangedRead.locale));
ck_assert(UA_String_equal(&newLocale.text, &inverseNameChangedRead.text));
UA_LocalizedText_deleteMembers(&inverseNameChangedRead);
}
END_TEST
START_TEST(Node_ReadWrite_ContainsNoLoops) {
UA_Boolean containsNoLoops;
UA_StatusCode retval = UA_Client_readContainsNoLoopsAttribute(client, nodeReadWriteTestHasSubSubType, &containsNoLoops);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
retval = UA_Client_readContainsNoLoopsAttribute(client, nodeReadWriteView, &containsNoLoops);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(containsNoLoops, UA_FALSE);
UA_Boolean newContainsNoLoops = UA_TRUE;
retval = UA_Client_writeContainsNoLoopsAttribute(client, nodeReadWriteView, &newContainsNoLoops);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readContainsNoLoopsAttribute(client, nodeReadWriteView, &containsNoLoops);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(containsNoLoops, newContainsNoLoops);
}
END_TEST
START_TEST(Node_ReadWrite_EventNotifier) {
UA_Byte eventNotifier = 0;
UA_StatusCode retval = UA_Client_readEventNotifierAttribute(client, nodeReadWriteTestHasSubSubType, &eventNotifier);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
retval = UA_Client_readEventNotifierAttribute(client, nodeReadWriteView, &eventNotifier);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(eventNotifier, 0);
UA_Byte newEventNotifier = 1;
retval = UA_Client_writeEventNotifierAttribute(client, nodeReadWriteView, &newEventNotifier);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readEventNotifierAttribute(client, nodeReadWriteView, &eventNotifier);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(eventNotifier, newEventNotifier);
}
END_TEST
START_TEST(Node_ReadWrite_Value) {
UA_Int32 value = 0;
UA_Variant *val = UA_Variant_new();
UA_StatusCode retval = UA_Client_readValueAttribute(client, nodeReadWriteInt, val);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_Variant_isScalar(val) && val->type == &UA_TYPES[UA_TYPES_INT32]);
value = *(UA_Int32*)val->data;
ck_assert_int_eq(value, 5678);
UA_Variant_delete(val);
/* Write attribute */
value++;
val = UA_Variant_new();
UA_Variant_setScalarCopy(val, &value, &UA_TYPES[UA_TYPES_INT32]);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteInt, val);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_Variant_delete(val);
/* Read again to check value */
val = UA_Variant_new();
retval = UA_Client_readValueAttribute(client, nodeReadWriteInt, val);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_Variant_isScalar(val) && val->type == &UA_TYPES[UA_TYPES_INT32]);
value = *(UA_Int32*)val->data;
ck_assert_int_eq(value, 5679);
UA_Variant_delete(val);
}
END_TEST
START_TEST(Node_ReadWrite_DataType) {
UA_NodeId dataType;
// read to check if node id was changed
UA_StatusCode retval = UA_Client_readDataTypeAttribute(client, nodeReadWriteInt, &dataType);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_NodeId_equal(&dataType, &UA_TYPES[UA_TYPES_INT32].typeId));
UA_NodeId newDataType = UA_TYPES[UA_TYPES_VARIANT].typeId;
retval = UA_Client_writeDataTypeAttribute(client, nodeReadWriteGeneric, &newDataType);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readDataTypeAttribute(client, nodeReadWriteGeneric, &dataType);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_NodeId_equal(&dataType, &newDataType));
}
END_TEST
START_TEST(Node_ReadWrite_ValueRank) {
UA_Int32 valueRank = UA_VALUERANK_ONE_OR_MORE_DIMENSIONS;
UA_StatusCode retval = UA_Client_readValueRankAttribute(client, nodeReadWriteGeneric, &valueRank);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(valueRank, UA_VALUERANK_ANY);
// set the value to a scalar
UA_Double val = 0.0;
UA_Variant value;
UA_Variant_setScalar(&value, &val, &UA_TYPES[UA_TYPES_DOUBLE]);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteGeneric, &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// we want an array
UA_Int32 newValueRank = UA_VALUERANK_ONE_DIMENSION;
// shall fail when the value is not compatible
retval = UA_Client_writeValueRankAttribute(client, nodeReadWriteGeneric, &newValueRank);
ck_assert(retval != UA_STATUSCODE_GOOD);
// set the value to an array
UA_Double vec[3] = {0.0, 0.0, 0.0};
UA_Variant_setArray(&value, vec, 3, &UA_TYPES[UA_TYPES_DOUBLE]);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteGeneric, &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// try again
retval = UA_Client_writeValueRankAttribute(client, nodeReadWriteGeneric, &newValueRank);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readValueRankAttribute(client, nodeReadWriteGeneric, &valueRank);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(valueRank, newValueRank);
// set the value to no array
UA_Variant_init(&value);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteGeneric, &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
}
END_TEST
START_TEST(Node_ReadWrite_ArrayDimensions) {
UA_UInt32 *arrayDimsRead;
size_t arrayDimsReadSize;
UA_StatusCode retval = UA_Client_readArrayDimensionsAttribute(client, nodeReadWriteGeneric,
&arrayDimsReadSize, &arrayDimsRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(arrayDimsReadSize, 0);
// Set a vector of size 1 as the value
UA_Double vec2[2] = {0.0, 0.0};
UA_Variant value;
UA_Variant_setArray(&value, vec2, 2, &UA_TYPES[UA_TYPES_DOUBLE]);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteGeneric, &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// writing the array dimensions shall fail at first
// because the current value is not conformant
UA_UInt32 arrayDimsNew[] = {1};
retval = UA_Client_writeArrayDimensionsAttribute(client, nodeReadWriteGeneric, 1, arrayDimsNew);
ck_assert(retval != UA_STATUSCODE_GOOD);
// Set a vector of size 1 as the value
UA_Double vec1[1] = {0.0};
UA_Variant_setArray(&value, vec1, 1, &UA_TYPES[UA_TYPES_DOUBLE]);
retval = UA_Client_writeValueAttribute(client, nodeReadWriteGeneric, &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
// Now we can set matching array-dimensions
retval = UA_Client_writeArrayDimensionsAttribute(client, nodeReadWriteGeneric, 1, arrayDimsNew);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readArrayDimensionsAttribute(client, nodeReadWriteGeneric,
&arrayDimsReadSize, &arrayDimsRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(arrayDimsReadSize, 1);
ck_assert_int_eq(arrayDimsRead[0], 1);
UA_Array_delete(arrayDimsRead, arrayDimsReadSize, &UA_TYPES[UA_TYPES_UINT32]);
}
END_TEST
START_TEST(Node_ReadWrite_AccessLevel) {
UA_Byte accessLevel;
UA_StatusCode retval = UA_Client_readAccessLevelAttribute(client, nodeReadWriteInt, &accessLevel);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(accessLevel, UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE);
UA_Byte newMask = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD;
retval = UA_Client_writeAccessLevelAttribute(client, nodeReadWriteInt, &newMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
UA_Byte accessLevelChangedRead;
retval = UA_Client_readAccessLevelAttribute(client, nodeReadWriteInt, &accessLevelChangedRead);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(accessLevelChangedRead, newMask);
}
END_TEST
START_TEST(Node_ReadWrite_UserAccessLevel) {
UA_Byte userAccessLevel;
UA_StatusCode retval = UA_Client_readUserAccessLevelAttribute(client, nodeReadWriteInt, &userAccessLevel);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(userAccessLevel, UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD);
UA_Byte newMask = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD;
retval = UA_Client_writeUserAccessLevelAttribute(client, nodeReadWriteInt, &newMask);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
START_TEST(Node_ReadWrite_MinimumSamplingInterval) {
UA_Double minimumSamplingInterval = 0;
UA_StatusCode retval = UA_Client_readMinimumSamplingIntervalAttribute(client, nodeReadWriteGeneric, &minimumSamplingInterval);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(minimumSamplingInterval == 0);
// we want an array
UA_Double newMinimumSamplingInterval = 1;
retval = UA_Client_writeMinimumSamplingIntervalAttribute(client, nodeReadWriteGeneric, &newMinimumSamplingInterval);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readMinimumSamplingIntervalAttribute(client, nodeReadWriteGeneric, &minimumSamplingInterval);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(minimumSamplingInterval == newMinimumSamplingInterval);
}
END_TEST
START_TEST(Node_ReadWrite_Historizing) {
UA_Boolean historizing;
UA_StatusCode retval = UA_Client_readHistorizingAttribute(client, nodeReadWriteInt, &historizing);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(historizing, UA_FALSE);
UA_Boolean newHistorizing = UA_TRUE;
retval = UA_Client_writeHistorizingAttribute(client, nodeReadWriteInt, &newHistorizing);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readHistorizingAttribute(client, nodeReadWriteInt, &historizing);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(historizing, newHistorizing);
}
END_TEST
START_TEST(Node_ReadWrite_Executable) {
UA_Boolean executable;
UA_StatusCode retval = UA_Client_readExecutableAttribute(client, nodeReadWriteMethod, &executable);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(executable, UA_TRUE);
UA_Boolean newExecutable = UA_FALSE;
retval = UA_Client_writeExecutableAttribute(client, nodeReadWriteMethod, &newExecutable);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Client_readExecutableAttribute(client, nodeReadWriteMethod, &executable);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(executable, newExecutable);
}
END_TEST
START_TEST(Node_ReadWrite_UserExecutable) {
UA_Boolean userExecutable;
UA_StatusCode retval = UA_Client_readUserExecutableAttribute(client, nodeReadWriteMethod, &userExecutable);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert_int_eq(userExecutable, UA_FALSE);
UA_Boolean newUserExecutable = UA_TRUE;
retval = UA_Client_writeUserExecutableAttribute(client, nodeReadWriteMethod, &newUserExecutable);
ck_assert_uint_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
}
END_TEST
#endif
static Suite *testSuite_Client(void) {
Suite *s = suite_create("Client Highlevel");
TCase *tc_misc = tcase_create("Client Highlevel Misc");
tcase_add_checked_fixture(tc_misc, setup, teardown);
tcase_add_test(tc_misc, Misc_State);
tcase_add_test(tc_misc, Misc_NamespaceGetIndex);
suite_add_tcase(s, tc_misc);
TCase *tc_nodes = tcase_create("Client Highlevel Node Management");
tcase_add_checked_fixture(tc_nodes, setup, teardown);
#ifdef UA_ENABLE_NODEMANAGEMENT
tcase_add_test(tc_nodes, Node_Add);
#endif
tcase_add_test(tc_nodes, Node_Browse);
tcase_add_test(tc_nodes, Node_Register);
suite_add_tcase(s, tc_nodes);
#ifdef UA_ENABLE_NODEMANAGEMENT
TCase *tc_readwrite = tcase_create("Client Highlevel Read/Write");
tcase_add_unchecked_fixture(tc_readwrite, setup, teardown);
// first add some nodes where we test on
tcase_add_test(tc_readwrite, Node_AddReadWriteNodes);
// Now run all the read write tests
tcase_add_test(tc_readwrite, Node_ReadWrite_Id);
tcase_add_test(tc_readwrite, Node_ReadWrite_Class);
tcase_add_test(tc_readwrite, Node_ReadWrite_BrowseName);
tcase_add_test(tc_readwrite, Node_ReadWrite_DisplayName);
tcase_add_test(tc_readwrite, Node_ReadWrite_Description);
tcase_add_test(tc_readwrite, Node_ReadWrite_WriteMask);
tcase_add_test(tc_readwrite, Node_ReadWrite_UserWriteMask);
tcase_add_test(tc_readwrite, Node_ReadWrite_IsAbstract);
tcase_add_test(tc_readwrite, Node_ReadWrite_Symmetric);
tcase_add_test(tc_readwrite, Node_ReadWrite_InverseName);
tcase_add_test(tc_readwrite, Node_ReadWrite_ContainsNoLoops);
tcase_add_test(tc_readwrite, Node_ReadWrite_EventNotifier);
tcase_add_test(tc_readwrite, Node_ReadWrite_Value);
tcase_add_test(tc_readwrite, Node_ReadWrite_DataType);
tcase_add_test(tc_readwrite, Node_ReadWrite_ValueRank);
tcase_add_test(tc_readwrite, Node_ReadWrite_ArrayDimensions);
tcase_add_test(tc_readwrite, Node_ReadWrite_AccessLevel);
tcase_add_test(tc_readwrite, Node_ReadWrite_UserAccessLevel);
tcase_add_test(tc_readwrite, Node_ReadWrite_MinimumSamplingInterval);
tcase_add_test(tc_readwrite, Node_ReadWrite_Historizing);
tcase_add_test(tc_readwrite, Node_ReadWrite_Executable);
tcase_add_test(tc_readwrite, Node_ReadWrite_UserExecutable);
suite_add_tcase(s, tc_readwrite);
#endif
return s;
}
int main(void) {
Suite *s = testSuite_Client();
SRunner *sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_NORMAL);
int number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}