mirror of
https://github.com/open62541/open62541.git
synced 2026-10-18 13:42:32 +08:00
918f2cfd4b
Fix misspellings found with codespell across headers, sources, examples, tests and the documentation, including "propably" in the nodeset compiler docs. Identifiers, companion spec names and generated code are left untouched.
479 lines
22 KiB
C
479 lines
22 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/server_config_default.h>
|
|
|
|
#include "server/ua_server_internal.h"
|
|
#include "test_helpers.h"
|
|
|
|
#include <check.h>
|
|
#include <stdlib.h>
|
|
|
|
UA_Server *server = NULL;
|
|
UA_UInt32 valueToBeInherited = 42;
|
|
|
|
static void setup(void) {
|
|
server = UA_Server_newForUnitTest();
|
|
ck_assert(server != NULL);
|
|
UA_Server_run_startup(server);
|
|
}
|
|
|
|
static void teardown(void) {
|
|
UA_Server_run_shutdown(server);
|
|
UA_Server_delete(server);
|
|
}
|
|
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
/* finds the NodeId of a StateNumber child of a given node id */
|
|
static void
|
|
findChildId(UA_NodeId parentNode, UA_NodeId referenceType,
|
|
const UA_QualifiedName targetName, UA_NodeId *result) {
|
|
UA_RelativePathElement rpe;
|
|
UA_RelativePathElement_init(&rpe);
|
|
rpe.referenceTypeId = referenceType;
|
|
rpe.isInverse = false;
|
|
rpe.includeSubtypes = false;
|
|
rpe.targetName = targetName;
|
|
|
|
UA_BrowsePath bp;
|
|
UA_BrowsePath_init(&bp);
|
|
bp.startingNode = parentNode;
|
|
bp.relativePath.elementsSize = 1;
|
|
bp.relativePath.elements = &rpe; //clion complains but is ok
|
|
|
|
UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp);
|
|
ck_assert_uint_eq(bpr.statusCode, UA_STATUSCODE_GOOD);
|
|
|
|
ck_assert(bpr.targetsSize > 0);
|
|
|
|
UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, result);
|
|
UA_BrowsePathResult_clear(&bpr);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
START_TEST(Nodes_createCustomBrowseNameObjectType)
|
|
{
|
|
/* Create a custom object type "CustomBrowseNameType" which has a
|
|
* "DefaultInstanceBrowseName" property. */
|
|
|
|
/* create new object type node which has a subcomponent of the type StateType */
|
|
UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("", "CustomBrowseNameType");
|
|
otAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_StatusCode retval = UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 7010),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
UA_QUALIFIEDNAME(1, "CustomBrowseNameType"),
|
|
otAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
// Now add a property "DefaultInstanceBrowseName"
|
|
UA_VariableAttributes attr = UA_VariableAttributes_default;
|
|
attr.minimumSamplingInterval = 0.000000;
|
|
attr.userAccessLevel = 1;
|
|
attr.accessLevel = 1;
|
|
attr.valueRank = UA_VALUERANK_ANY;
|
|
attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_QUALIFIEDNAME);
|
|
UA_QualifiedName defaultInstanceBrowseName = UA_QUALIFIEDNAME(1, "MyCustomBrowseName");
|
|
UA_Variant_setScalar(&attr.value, &defaultInstanceBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
|
|
attr.displayName = UA_LOCALIZEDTEXT("", "DefaultInstanceBrowseName");
|
|
attr.description = UA_LOCALIZEDTEXT("", "");
|
|
attr.writeMask = 0;
|
|
attr.userWriteMask = 0;
|
|
retval = UA_Server_addVariableNode(server,
|
|
UA_NODEID_NUMERIC(1, 7011),
|
|
UA_NODEID_NUMERIC(1, 7010),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
|
|
UA_QUALIFIEDNAME(0, "DefaultInstanceBrowseName"),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE),
|
|
attr,
|
|
NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
} END_TEST
|
|
|
|
|
|
|
|
START_TEST(Nodes_checkDefaultInstanceBrowseName) {
|
|
/* create an object/instance of the CustomDemoType.
|
|
* This should fail if we do not specify a browse name.
|
|
* CustomDemoType does not have a DefaultInstanceBrowseName
|
|
* */
|
|
UA_ObjectAttributes oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "DemoCustomBrowseNameFail");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_QualifiedName nullName;
|
|
UA_QualifiedName_init(&nullName);
|
|
UA_StatusCode retval =
|
|
UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 7020),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
nullName, UA_NODEID_NUMERIC(1, 6010),
|
|
oAttr2, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_BADBROWSENAMEINVALID);
|
|
|
|
/* create an object/instance of the CustomBrowseNameType and set the default browse name */
|
|
oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "DemoCustomBrowseName");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_QualifiedName_init(&nullName);
|
|
retval =
|
|
UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 7021),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
nullName, UA_NODEID_NUMERIC(1, 7010),
|
|
oAttr2, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
UA_QualifiedName receivedBrowseName;
|
|
UA_QualifiedName_init(&receivedBrowseName);
|
|
|
|
UA_QualifiedName defaultInstanceBrowseName = UA_QUALIFIEDNAME(1, "MyCustomBrowseName");
|
|
|
|
retval = UA_Server_readBrowseName(server, UA_NODEID_NUMERIC(1, 7021), &receivedBrowseName);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
ck_assert(UA_QualifiedName_equal(&receivedBrowseName, &defaultInstanceBrowseName) == true);
|
|
UA_QualifiedName_clear(&receivedBrowseName);
|
|
|
|
/* create an object/instance of the CustomBrowseNameType and set a custom browse name */
|
|
oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "DemoCustomBrowseName");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_QualifiedName overriddenBrowseName = UA_QUALIFIEDNAME(1, "MyOverriddenBrowseName");
|
|
retval =
|
|
UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 7022),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
overriddenBrowseName, UA_NODEID_NUMERIC(1, 7010),
|
|
oAttr2, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
UA_QualifiedName_init(&receivedBrowseName);
|
|
|
|
retval = UA_Server_readBrowseName(server, UA_NODEID_NUMERIC(1, 7022), &receivedBrowseName);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
ck_assert(UA_QualifiedName_equal(&receivedBrowseName, &overriddenBrowseName) == true);
|
|
UA_QualifiedName_clear(&receivedBrowseName);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(Nodes_createCustomStateType) {
|
|
// Create a type "CustomStateType" with a variable "CustomStateNumber" as property
|
|
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
|
|
|
UA_ObjectTypeAttributes attrObject = UA_ObjectTypeAttributes_default;
|
|
attrObject.displayName = UA_LOCALIZEDTEXT("", "CustomStateType");
|
|
attrObject.description = UA_LOCALIZEDTEXT("", "");
|
|
attrObject.writeMask = 0;
|
|
attrObject.userWriteMask = 0;
|
|
retval = UA_Server_addObjectTypeNode(server,
|
|
UA_NODEID_NUMERIC(1, 6000),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
UA_QUALIFIEDNAME(1, "CustomStateType"),
|
|
attrObject,
|
|
NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
// Now add a property "StateNumber"
|
|
UA_VariableAttributes attr = UA_VariableAttributes_default;
|
|
attr.minimumSamplingInterval = 0.000000;
|
|
attr.userAccessLevel = 1;
|
|
attr.accessLevel = 1;
|
|
attr.valueRank = UA_VALUERANK_ANY;
|
|
attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_UINT32);
|
|
UA_UInt32 val = 0;
|
|
UA_Variant_setScalar(&attr.value, &val, &UA_TYPES[UA_TYPES_UINT32]);
|
|
attr.displayName = UA_LOCALIZEDTEXT("", "CustomStateNumber");
|
|
attr.description = UA_LOCALIZEDTEXT("", "");
|
|
attr.writeMask = 0;
|
|
attr.userWriteMask = 0;
|
|
retval = UA_Server_addVariableNode(server,
|
|
UA_NODEID_NUMERIC(1, 6001),
|
|
UA_NODEID_NUMERIC(1, 6000),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
|
|
UA_QUALIFIEDNAME(1, "CustomStateNumber"),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE),
|
|
attr,
|
|
NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
/* Minimal nodeset does not contain the modelling rule mandatory */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 6001),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY),
|
|
true);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
#endif
|
|
}
|
|
END_TEST
|
|
|
|
|
|
START_TEST(Nodes_createCustomObjectType) {
|
|
/* Create a custom object type "CustomDemoType" which has a
|
|
* "CustomStateType" component */
|
|
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
|
|
|
/* create new object type node which has a subcomponent of the type StateType */
|
|
UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("", "CustomDemoType");
|
|
otAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
retval = UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 6010),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
UA_QUALIFIEDNAME(1, "CustomDemoType"),
|
|
otAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
|
|
oAttr.displayName = UA_LOCALIZEDTEXT("", "State");
|
|
oAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
retval = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 6011), UA_NODEID_NUMERIC(1, 6010),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "State"),
|
|
UA_NODEID_NUMERIC(1, 6000),
|
|
oAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
/* Minimal nodeset does not contain the modelling rule mandatory */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
/* modelling rule is mandatory so it will be inherited for the object
|
|
* created from CustomDemoType */
|
|
retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 6011),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY),
|
|
true);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
|
|
/* assign a default value to the attribute "StateNumber" inside the state
|
|
* attribute (part of the MyDemoType) */
|
|
UA_Variant stateNum;
|
|
UA_Variant_init(&stateNum);
|
|
UA_Variant_setScalar(&stateNum, &valueToBeInherited, &UA_TYPES[UA_TYPES_UINT32]);
|
|
UA_NodeId childID;
|
|
findChildId(UA_NODEID_NUMERIC(1, 6011), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
|
|
UA_QUALIFIEDNAME(1, "CustomStateNumber"), &childID);
|
|
ck_assert(!UA_NodeId_isNull(&childID));
|
|
|
|
retval = UA_Server_writeValue(server, childID, stateNum);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
#endif
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(Nodes_createInheritedObject) {
|
|
/* create an object/instance of the demo type */
|
|
UA_ObjectAttributes oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "Demo");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_StatusCode retval =
|
|
UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 6020),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(1, 6010),
|
|
oAttr2, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(Nodes_checkInheritedValue) {
|
|
/* Minimal nodeset does not contain the modelling rule mandatory, therefore there is no CustomStateNumber */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
UA_NodeId childState;
|
|
findChildId(UA_NODEID_NUMERIC(1, 6020),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "State"), &childState);
|
|
ck_assert(!UA_NodeId_isNull(&childState));
|
|
|
|
UA_NodeId childNumber;
|
|
findChildId(childState, UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
|
|
UA_QUALIFIEDNAME(1, "CustomStateNumber"), &childNumber);
|
|
ck_assert(!UA_NodeId_isNull(&childNumber));
|
|
|
|
UA_ReadValueId rvi;
|
|
UA_ReadValueId_init(&rvi);
|
|
rvi.nodeId = childNumber;
|
|
rvi.attributeId = UA_ATTRIBUTEID_VALUE;
|
|
UA_DataValue inheritedValue = UA_Server_read(server, &rvi, UA_TIMESTAMPSTORETURN_BOTH);
|
|
ck_assert(inheritedValue.value.type == &UA_TYPES[UA_TYPES_UINT32]);
|
|
UA_UInt32 *value = (UA_UInt32 *) inheritedValue.value.data;
|
|
ck_assert_int_eq(*value, valueToBeInherited);
|
|
|
|
/* Write a specific timestamp */
|
|
UA_WriteValue wValue;
|
|
UA_WriteValue_init(&wValue);
|
|
wValue.value = inheritedValue;
|
|
wValue.value.hasSourceTimestamp = true;
|
|
wValue.value.sourceTimestamp = 1337;
|
|
wValue.nodeId = childNumber;
|
|
wValue.attributeId = UA_ATTRIBUTEID_VALUE;
|
|
UA_StatusCode retval = UA_Server_write(server, &wValue);
|
|
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
/* Read the timestamp back out */
|
|
UA_DataValue resp = UA_Server_read(server, &rvi, UA_TIMESTAMPSTORETURN_BOTH);
|
|
ck_assert(resp.hasSourceTimestamp);
|
|
ck_assert_int_eq(resp.sourceTimestamp, 1337);
|
|
|
|
UA_DataValue_clear(&resp);
|
|
UA_DataValue_clear(&inheritedValue);
|
|
#endif
|
|
}
|
|
END_TEST
|
|
|
|
|
|
|
|
START_TEST(Nodes_createCustomInterfaceType) {
|
|
/* Minimal nodeset does not have the Interface definitions */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
/* Create a custom interface type */
|
|
|
|
UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("", "ILocationType");
|
|
otAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_StatusCode retval = UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 8000),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEINTERFACETYPE),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
UA_QUALIFIEDNAME(1, "ILocationType"),
|
|
otAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
|
|
oAttr.displayName = UA_LOCALIZEDTEXT("", "InterfaceChild");
|
|
oAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
retval = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 8001), UA_NODEID_NUMERIC(1, 8000),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "InterfaceChild"),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
oAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 8001),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
|
|
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY),
|
|
true);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
|
|
/* create an object type which has the interface */
|
|
otAttr = UA_ObjectTypeAttributes_default;
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("", "ObjectWithLocation");
|
|
otAttr.description = UA_LOCALIZEDTEXT("", "");
|
|
retval = UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 8002),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
|
|
UA_QUALIFIEDNAME(1, "ObjectWithLocation"),
|
|
otAttr, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 8002), UA_NODEID_NUMERIC(0, UA_NS0ID_HASINTERFACE), UA_EXPANDEDNODEID_NUMERIC(1, 8000), true);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
#endif
|
|
}
|
|
END_TEST
|
|
|
|
|
|
|
|
START_TEST(Nodes_createObjectWithInterfaceOnType) {
|
|
|
|
/* Minimal nodeset does not have the Interface definitions */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
/* create an object/instance of the demo type */
|
|
UA_ObjectAttributes oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "ObjectInstanceOfInterface");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_StatusCode retval =
|
|
UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 8020),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "ObjectInstanceOfInterface"), UA_NODEID_NUMERIC(1, 8002),
|
|
oAttr2, NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
|
|
/* Check that object has inherited the interface children */
|
|
|
|
UA_NodeId childId;
|
|
findChildId(UA_NODEID_NUMERIC(1, 8020),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "InterfaceChild"), &childId);
|
|
ck_assert(!UA_NodeId_isNull(&childId));
|
|
#endif
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(Nodes_createObjectWithInterfaceOnObject) {
|
|
|
|
/* Minimal nodeset does not have the Interface definitions */
|
|
#ifdef UA_GENERATED_NAMESPACE_ZERO
|
|
/* create an object of base object type */
|
|
UA_ObjectAttributes oAttr2 = UA_ObjectAttributes_default;
|
|
oAttr2.displayName = UA_LOCALIZEDTEXT("", "ObjectInstanceWithInterface");
|
|
oAttr2.description = UA_LOCALIZEDTEXT("", "");
|
|
UA_StatusCode retval =
|
|
UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT, UA_NODEID_NUMERIC(1, 8021),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "ObjectInstanceWithInterface"),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
|
|
(const UA_NodeAttributes*)&oAttr2,&UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
|
|
NULL, NULL);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
/* Add HasInterface to object */
|
|
retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 8021), UA_NODEID_NUMERIC(0, UA_NS0ID_HASINTERFACE), UA_EXPANDEDNODEID_NUMERIC(1, 8000), true);
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
|
|
/* Finish object node creation */
|
|
retval = UA_Server_addNode_finish(server,UA_NODEID_NUMERIC(1, 8021));
|
|
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
|
|
|
|
|
/* Check that object has inherited the interface children */
|
|
UA_NodeId childId;
|
|
findChildId(UA_NODEID_NUMERIC(1, 8021),
|
|
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
|
|
UA_QUALIFIEDNAME(1, "InterfaceChild"), &childId);
|
|
ck_assert(!UA_NodeId_isNull(&childId));
|
|
#endif
|
|
}
|
|
END_TEST
|
|
|
|
static Suite *testSuite_Client(void) {
|
|
Suite *s = suite_create("Node inheritance");
|
|
TCase *tc_inherit_subtype = tcase_create("Inherit subtype value");
|
|
tcase_add_unchecked_fixture(tc_inherit_subtype, setup, teardown);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_createCustomStateType);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_createCustomObjectType);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_createInheritedObject);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_checkInheritedValue);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_createCustomBrowseNameObjectType);
|
|
tcase_add_test(tc_inherit_subtype, Nodes_checkDefaultInstanceBrowseName);
|
|
suite_add_tcase(s, tc_inherit_subtype);
|
|
TCase *tc_interface_addin = tcase_create("Interfaces and Addins");
|
|
tcase_add_unchecked_fixture(tc_interface_addin, setup, teardown);
|
|
tcase_add_test(tc_interface_addin, Nodes_createCustomInterfaceType);
|
|
tcase_add_test(tc_interface_addin, Nodes_createObjectWithInterfaceOnType);
|
|
tcase_add_test(tc_interface_addin, Nodes_createObjectWithInterfaceOnObject);
|
|
suite_add_tcase(s, tc_interface_addin);
|
|
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;
|
|
}
|