| /* 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_BADUSERACCESSDENIED); |
| |
| retval = UA_Client_writeBrowseNameAttribute(client, nodeReadWriteInt, &browseName); |
| ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); |
| |
| UA_QualifiedName browseNameChangedRead; |
| retval = UA_Client_readBrowseNameAttribute(client, nodeReadWriteInt, &browseNameChangedRead); |
| ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); |
| |
| ck_assert_int_eq(browseName.namespaceIndex, browseNameChangedRead.namespaceIndex); |
| ck_assert(UA_String_equal(&browseName.name, &browseNameChangedRead.name)); |
| |
| UA_QualifiedName_deleteMembers(&browseNameChangedRead); |
| |
| } |
| 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; |
| } |