Prechádzať zdrojové kódy

make more unit tests work

Julius Pfrommer 7 rokov pred
rodič
commit
6d51c75cce

+ 48 - 35
src/server/ua_services_attribute.c

@@ -503,6 +503,7 @@ UA_Variant_matchVariableDefinition(UA_Server *server, const UA_NodeId *variableD
     case -1: /* the value is a scalar */
         if(!UA_Variant_isScalar(value))
             return UA_STATUSCODE_BADTYPEMISMATCH;
+        break;
     case 0: /* the value is an array with one or more dimensions */
         if(UA_Variant_isScalar(value))
             return UA_STATUSCODE_BADTYPEMISMATCH;
@@ -545,14 +546,11 @@ UA_VariableNode_setDataType(UA_Server *server, UA_VariableNode *node,
         return UA_STATUSCODE_BADTYPEMISMATCH;
 
     /* Does the new type match the constraints of the variabletype? */
-    const UA_NodeId *vtDataType = &vt->dataType;
     UA_NodeId subtypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     UA_Boolean found = false;
     UA_StatusCode retval = isNodeInTree(server->nodestore, dataType,
-                                        vtDataType, &subtypeId, 1, &found);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-    if(!found)
+                                        &vt->dataType, &subtypeId, 1, &found);
+    if(retval != UA_STATUSCODE_GOOD || !found)
         return UA_STATUSCODE_BADTYPEMISMATCH;
 
     /* Check if the current value would match the new type */
@@ -641,12 +639,14 @@ UA_VariableNode_setArrayDimensions(UA_Server *server, UA_VariableNode *node,
             return UA_STATUSCODE_BADTYPEMISMATCH;
         break;
     case 0: /* the value is an array with one or more dimensions */
-        if(arrayDimensionsSize == 0)
-            return UA_STATUSCODE_BADTYPEMISMATCH;
+        /* no arraydimensions => array of dimension 1 */
         break;
     default: /* >= 1: the value is an array with the specified number of dimensions */
         if(node->valueRank < 0)
             return UA_STATUSCODE_BADTYPEMISMATCH;
+        if(arrayDimensionsSize == 0 && node->valueRank == 1)
+            /* no arraydimensions => array of dimension 1 */
+            break;
         if(arrayDimensionsSize != (size_t)node->valueRank)
             return UA_STATUSCODE_BADTYPEMISMATCH;
     }
@@ -717,9 +717,14 @@ UA_VariableNode_setValue(UA_Server *server, UA_VariableNode *node,
 
     /* write the value */
     if(node->valueSource == UA_VALUESOURCE_DATA) {
-        if(!rangeptr)
+        if(!rangeptr) {
+            UA_Variant old_value = node->value.data.value.value;
             retval = UA_DataValue_copy(&editableValue, &node->value.data.value);
-        else {
+            if(retval == UA_STATUSCODE_GOOD)
+                UA_Variant_deleteMembers(&old_value);
+            else
+                node->value.data.value.value = old_value; 
+        } else {
             if(!node->value.data.value.hasValue || !editableValue.hasValue) {
                 retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
                 goto cleanup;
@@ -745,8 +750,11 @@ UA_VariableNode_setValue(UA_Server *server, UA_VariableNode *node,
                                               &node->value.data.value.value, rangeptr);
     } else {
         /* TODO: Don't make a copy of the node in the multithreaded case */
-        retval = node->value.dataSource.write(node->value.dataSource.handle, node->nodeId,
-                                              &value->value, rangeptr);
+        if(node->value.dataSource.write)
+            retval = node->value.dataSource.write(node->value.dataSource.handle, node->nodeId,
+                                                  &value->value, rangeptr);
+        else
+            retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
     }
 
  cleanup:
@@ -777,7 +785,7 @@ writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
     return UA_STATUSCODE_GOOD;
 }
 
-#define CHECK_DATATYPE(EXP_DT)                                          \
+#define CHECK_DATATYPE_SCALAR(EXP_DT)                                   \
     if(!wvalue->value.hasValue ||                                       \
        &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type ||      \
        !UA_Variant_isScalar(&wvalue->value.value)) {                    \
@@ -785,6 +793,14 @@ writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
         break;                                                          \
     }
 
+#define CHECK_DATATYPE_ARRAY(EXP_DT)                                    \
+    if(!wvalue->value.hasValue ||                                       \
+       &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type ||      \
+       UA_Variant_isScalar(&wvalue->value.value)) {                     \
+        retval = UA_STATUSCODE_BADTYPEMISMATCH;                         \
+        break;                                                          \
+    }
+
 #define CHECK_NODECLASS_WRITE(CLASS)                                    \
     if((node->nodeClass & (CLASS)) == 0) {                              \
         retval = UA_STATUSCODE_BADNODECLASSINVALID;                     \
@@ -803,54 +819,54 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
     switch(wvalue->attributeId) {
     case UA_ATTRIBUTEID_NODEID:
     case UA_ATTRIBUTEID_NODECLASS:
-        retval = UA_STATUSCODE_BADNOTWRITABLE;
+        retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
         break;
     case UA_ATTRIBUTEID_BROWSENAME:
-        CHECK_DATATYPE(QUALIFIEDNAME);
+        CHECK_DATATYPE_SCALAR(QUALIFIEDNAME);
         UA_QualifiedName_deleteMembers(&node->browseName);
         UA_QualifiedName_copy(value, &node->browseName);
         break;
     case UA_ATTRIBUTEID_DISPLAYNAME:
-        CHECK_DATATYPE(LOCALIZEDTEXT);
+        CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
         UA_LocalizedText_deleteMembers(&node->displayName);
         UA_LocalizedText_copy(value, &node->displayName);
         break;
     case UA_ATTRIBUTEID_DESCRIPTION:
-        CHECK_DATATYPE(LOCALIZEDTEXT);
+        CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
         UA_LocalizedText_deleteMembers(&node->description);
         UA_LocalizedText_copy(value, &node->description);
         break;
     case UA_ATTRIBUTEID_WRITEMASK:
-        CHECK_DATATYPE(UINT32);
+        CHECK_DATATYPE_SCALAR(UINT32);
         node->writeMask = *(const UA_UInt32*)value;
         break;
     case UA_ATTRIBUTEID_USERWRITEMASK:
-        CHECK_DATATYPE(UINT32);
+        CHECK_DATATYPE_SCALAR(UINT32);
         node->userWriteMask = *(const UA_UInt32*)value;
         break;
     case UA_ATTRIBUTEID_ISABSTRACT:
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         retval = writeIsAbstractAttribute(node, *(const UA_Boolean*)value);
         break;
     case UA_ATTRIBUTEID_SYMMETRIC:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         ((UA_ReferenceTypeNode*)node)->symmetric = *(const UA_Boolean*)value;
         break;
     case UA_ATTRIBUTEID_INVERSENAME:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
-        CHECK_DATATYPE(LOCALIZEDTEXT);
+        CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
         UA_LocalizedText_deleteMembers(&((UA_ReferenceTypeNode*)node)->inverseName);
         UA_LocalizedText_copy(value, &((UA_ReferenceTypeNode*)node)->inverseName);
         break;
     case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW);
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         ((UA_ViewNode*)node)->containsNoLoops = *(const UA_Boolean*)value;
         break;
     case UA_ATTRIBUTEID_EVENTNOTIFIER:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
-        CHECK_DATATYPE(BYTE);
+        CHECK_DATATYPE_SCALAR(BYTE);
         ((UA_ViewNode*)node)->eventNotifier = *(const UA_Byte*)value;
         break;
     case UA_ATTRIBUTEID_VALUE:
@@ -860,7 +876,7 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
         break;
     case UA_ATTRIBUTEID_DATATYPE: {
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        CHECK_DATATYPE(NODEID);
+        CHECK_DATATYPE_SCALAR(NODEID);
         const UA_VariableTypeNode *vt = getVariableNodeType(server, (UA_VariableNode*)node);
         if(vt)
             retval = UA_VariableNode_setDataType(server, (UA_VariableNode*)node,
@@ -870,7 +886,7 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
         break; }
     case UA_ATTRIBUTEID_VALUERANK: {
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        CHECK_DATATYPE(INT32);
+        CHECK_DATATYPE_SCALAR(INT32);
         const UA_VariableTypeNode *vt = getVariableNodeType(server, (UA_VariableNode*)node);
         if(vt)
             retval = UA_VariableNode_setValueRank(server, (UA_VariableNode*)node,
@@ -880,8 +896,7 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
         break; }
     case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        CHECK_DATATYPE(UINT32);
-        if(!UA_Variant_isScalar(&wvalue->value.value)) {
+        CHECK_DATATYPE_ARRAY(UINT32); {
             const UA_VariableTypeNode *vt = getVariableNodeType(server, (UA_VariableNode*)node);
             if(vt)
                 retval = UA_VariableNode_setArrayDimensions(server, (UA_VariableNode*)node,
@@ -889,38 +904,36 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
                                                             wvalue->value.value.data);
             else
                 retval = UA_STATUSCODE_BADINTERNALERROR;
-        } else {
-            retval = UA_STATUSCODE_BADTYPEMISMATCH;
         }
         break;
     case UA_ATTRIBUTEID_ACCESSLEVEL:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
-        CHECK_DATATYPE(BYTE);
+        CHECK_DATATYPE_SCALAR(BYTE);
         ((UA_VariableNode*)node)->accessLevel = *(const UA_Byte*)value;
         break;
     case UA_ATTRIBUTEID_USERACCESSLEVEL:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
-        CHECK_DATATYPE(BYTE);
+        CHECK_DATATYPE_SCALAR(BYTE);
         ((UA_VariableNode*)node)->userAccessLevel = *(const UA_Byte*)value;
         break;
     case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
-        CHECK_DATATYPE(DOUBLE);
+        CHECK_DATATYPE_SCALAR(DOUBLE);
         ((UA_VariableNode*)node)->minimumSamplingInterval = *(const UA_Double*)value;
         break;
     case UA_ATTRIBUTEID_HISTORIZING:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         ((UA_VariableNode*)node)->historizing = *(const UA_Boolean*)value;
         break;
     case UA_ATTRIBUTEID_EXECUTABLE:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         ((UA_MethodNode*)node)->executable = *(const UA_Boolean*)value;
         break;
     case UA_ATTRIBUTEID_USEREXECUTABLE:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
-        CHECK_DATATYPE(BOOLEAN);
+        CHECK_DATATYPE_SCALAR(BOOLEAN);
         ((UA_MethodNode*)node)->userExecutable = *(const UA_Boolean*)value;
         break;
     default:

+ 26 - 33
src/server/ua_services_nodemanagement.c

@@ -495,21 +495,17 @@ copyCommonVariableAttributes(UA_Server *server, UA_VariableNode *node,
     
     /* Set the constraints */
     UA_StatusCode retval;
-    if(!UA_NodeId_isNull(&attr->dataType)) {
+    if(!UA_NodeId_isNull(&attr->dataType))
         retval  = UA_VariableNode_setDataType(server, node, vt, &attr->dataType);
-    } else {
+    else
         /* workaround common error where the datatype is left as NA_NODEID_NULL */
-        if(attr->value.type)
-            retval = UA_VariableNode_setDataType(server, node, vt, &attr->value.type->typeId);
-        else
-            retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; 
-    }
+        retval = UA_VariableNode_setDataType(server, node, vt, &vt->dataType);
 
     if(attr->valueRank != 0 || !UA_Variant_isScalar(&attr->value))
         retval |= UA_VariableNode_setValueRank(server, node, vt, attr->valueRank);
     else
         /* workaround common error where the valuerank is left as 0 */
-        retval |= UA_VariableNode_setValueRank(server, node, vt, -2);
+        retval |= UA_VariableNode_setValueRank(server, node, vt, vt->valueRank);
         
     retval |= UA_VariableNode_setArrayDimensions(server, node, vt,
                                                  attr->arrayDimensionsSize,
@@ -751,41 +747,38 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requested
                                     const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
                                     const UA_VariableAttributes attr, const UA_DataSource dataSource,
                                     UA_NodeId *outNewNodeId) {
-    /* replace null type with basedatavariabletype */
-    UA_NodeId basevartype = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
-    const UA_NodeId *type = &typeDefinition;
-    if(UA_NodeId_isNull(&typeDefinition))
-        type = &basevartype;
-
-    /* get the datatype node */
-    const UA_VariableTypeNode *vt = (const UA_VariableTypeNode*)UA_NodeStore_get(server->nodestore, type);
-    if(!vt || vt->nodeClass != UA_NODECLASS_VARIABLETYPE)
-        return UA_STATUSCODE_BADTYPEMISMATCH;
-
-    /* create the new node */
+    /* Create the new node */
     UA_VariableNode *node = UA_NodeStore_newVariableNode();
     if(!node)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
-    /* Copy content */
+    /* Read the current value (to do typechecking) */
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    UA_VariableAttributes editAttr = attr;
+    UA_DataValue value;
+    UA_DataValue_init(&value);
+    if(dataSource.read)
+        retval = dataSource.read(dataSource.handle, requestedNewNodeId,
+                                 false, NULL, &value);
+    else
+        retval = UA_STATUSCODE_BADTYPEMISMATCH;
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+    editAttr.value = value.value;
+
+    /* Copy attributes into node */
     UA_AddNodesItem item;
     UA_AddNodesItem_init(&item);
     item.requestedNewNodeId.nodeId = requestedNewNodeId;
     item.browseName = browseName;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)node, &item, (const UA_NodeAttributes*)&attr);
-
-    node->accessLevel = attr.accessLevel;
-    node->userAccessLevel = attr.userAccessLevel;
-    node->historizing = attr.historizing;
-    node->minimumSamplingInterval = attr.minimumSamplingInterval;
-    retval  = UA_VariableNode_setDataType(server, node, vt, &attr.dataType);
-    retval |= UA_VariableNode_setValueRank(server, node, vt, attr.valueRank);
-    retval |= UA_VariableNode_setArrayDimensions(server, node, vt,
-                                                 attr.arrayDimensionsSize,
-                                                 attr.arrayDimensions);
+    item.typeDefinition.nodeId = typeDefinition;
+    item.parentNodeId.nodeId = parentNodeId;
+    retval |= copyStandardAttributes((UA_Node*)node, &item, (const UA_NodeAttributes*)&editAttr);
+    retval |= copyCommonVariableAttributes(server, node, &item, &editAttr);
+    UA_DataValue_deleteMembers(&node->value.data.value);
     node->valueSource = UA_VALUESOURCE_DATASOURCE;
     node->value.dataSource = dataSource;
-
+    UA_DataValue_deleteMembers(&value);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_NodeStore_deleteNode((UA_Node*)node);
         return retval;

+ 26 - 15
tests/check_services_attributes.c

@@ -23,8 +23,18 @@ readCPUTemperature_broken(void *handle, const UA_NodeId nodeid, UA_Boolean sourc
   return UA_STATUSCODE_GOOD;
 }
 
-static UA_Server* makeTestSequence(void) {
-    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+static UA_StatusCode
+readCPUTemperature(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp,
+                   const UA_NumericRange *range, UA_DataValue *dataValue) {
+    UA_Float temp = 20.5f;
+    UA_Variant_setScalarCopy(&dataValue->value, &temp, &UA_TYPES[UA_TYPES_FLOAT]);
+    dataValue->hasValue = true;
+    return UA_STATUSCODE_GOOD;
+}
+
+static UA_Server *
+makeTestSequence(void) {
+    UA_Server * server = UA_Server_new(UA_ServerConfig_standard);
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
 
     /* VariableNode */
@@ -46,8 +56,8 @@ static UA_Server* makeTestSequence(void) {
 
     /* DataSource VariableNode */
     UA_VariableAttributes_init(&vattr);
-    UA_DataSource temperatureDataSource = (UA_DataSource) {
-                                           .handle = NULL, .read = NULL, .write = NULL};
+    UA_DataSource temperatureDataSource =
+        (UA_DataSource) {.handle = NULL, .read = readCPUTemperature, .write = NULL};
     vattr.description = UA_LOCALIZEDTEXT("en_US","temperature");
     vattr.displayName = UA_LOCALIZEDTEXT("en_US","temperature");
     retval = UA_Server_addDataSourceVariableNode(server, UA_NODEID_STRING(1, "cpu.temperature"),
@@ -58,8 +68,8 @@ static UA_Server* makeTestSequence(void) {
     ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
 
     /* DataSource Variable returning no value */
-    UA_DataSource temperatureDataSource1 = (UA_DataSource) {
-                                            .handle = NULL, .read = readCPUTemperature_broken, .write = NULL};
+    UA_DataSource temperatureDataSource1 =
+        (UA_DataSource) {.handle = NULL, .read = readCPUTemperature_broken, .write = NULL};
     vattr.description = UA_LOCALIZEDTEXT("en_US","temperature1");
     vattr.displayName = UA_LOCALIZEDTEXT("en_US","temperature1");
     retval = UA_Server_addDataSourceVariableNode(server, UA_NODEID_STRING(1, "cpu.temperature1"),
@@ -119,7 +129,7 @@ static UA_Server* makeTestSequence(void) {
     retval = UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_METHODNODE),
                                      UA_NODEID_NUMERIC(0, 3),
                                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-                                     UA_QUALIFIEDNAME_ALLOC(0, "Methodtest"), ma,
+                                     UA_QUALIFIEDNAME(0, "Methodtest"), ma,
                                      NULL, NULL, 0, NULL, 0, NULL, NULL);
     ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
 #endif
@@ -647,7 +657,7 @@ START_TEST(ReadSingleDataSourceAttributeValueWithoutTimestamp) {
     rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "cpu.temperature");
     rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
     Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER, &rReq.nodesToRead[0], &resp);
-    ck_assert_int_eq(UA_STATUSCODE_BADINTERNALERROR, resp.status);
+    ck_assert_int_eq(UA_STATUSCODE_GOOD, resp.status);
     UA_Server_delete(server);
     UA_ReadRequest_deleteMembers(&rReq);
     UA_DataValue_deleteMembers(&resp);
@@ -664,7 +674,8 @@ START_TEST(ReadSingleDataSourceAttributeDataTypeWithoutTimestamp) {
     rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "cpu.temperature");
     rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_DATATYPE;
     Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER, &rReq.nodesToRead[0], &resp);
-    ck_assert_int_eq(UA_STATUSCODE_BADINTERNALERROR, resp.status);
+    ck_assert_int_eq(UA_STATUSCODE_GOOD, resp.status);
+    ck_assert_int_eq(resp.hasServerTimestamp, false);
     UA_Server_delete(server);
     UA_ReadRequest_deleteMembers(&rReq);
     UA_DataValue_deleteMembers(&resp);
@@ -681,7 +692,7 @@ START_TEST (ReadSingleDataSourceAttributeArrayDimensionsWithoutTimestamp) {
     rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "cpu.temperature");
     rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
     Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER, &rReq.nodesToRead[0], &resp);
-    ck_assert_int_eq(UA_STATUSCODE_BADINTERNALERROR, resp.status);
+    ck_assert_int_eq(UA_STATUSCODE_GOOD, resp.status);
     UA_Server_delete(server);
     UA_ReadRequest_deleteMembers(&rReq);
     UA_DataValue_deleteMembers(&resp);
@@ -899,7 +910,7 @@ START_TEST(WriteSingleAttributeDataType) {
     wValue.value.hasValue = true;
     UA_Variant_setScalar(&wValue.value.value, &typeId, &UA_TYPES[UA_TYPES_NODEID]);
     UA_StatusCode retval = Service_Write_single(server, &adminSession, &wValue);
-    ck_assert_int_eq(retval, UA_STATUSCODE_BADWRITENOTSUPPORTED);
+    ck_assert_int_eq(retval, UA_STATUSCODE_BADTYPEMISMATCH);
     UA_Server_delete(server);
 } END_TEST
 
@@ -914,7 +925,7 @@ START_TEST(WriteSingleAttributeValueRank) {
     wValue.value.hasValue = true;
     UA_StatusCode retval = Service_Write_single(server, &adminSession, &wValue);
     // Returns attributeInvalid, since variant/value may be writable
-    ck_assert_int_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
     UA_Server_delete(server);
 } END_TEST
 
@@ -922,14 +933,14 @@ START_TEST(WriteSingleAttributeArrayDimensions) {
     UA_Server *server = makeTestSequence();
     UA_WriteValue wValue;
     UA_WriteValue_init(&wValue);
-    UA_Int32 testValue[] = {-1,-1,-1};
-    UA_Variant_setArray(&wValue.value.value, &testValue, 3, &UA_TYPES[UA_TYPES_INT32]);
+    UA_UInt32 testValue[] = {1,1,1};
+    UA_Variant_setArray(&wValue.value.value, &testValue, 3, &UA_TYPES[UA_TYPES_UINT32]);
     wValue.nodeId = UA_NODEID_STRING(1, "the.answer");
     wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
     wValue.value.hasValue = true;
     UA_StatusCode retval = Service_Write_single(server, &adminSession, &wValue);
     // Returns attributeInvalid, since variant/value may be writable
-    ck_assert_int_eq(retval, UA_STATUSCODE_BADATTRIBUTEIDINVALID);
+    ck_assert_int_eq(retval, UA_STATUSCODE_BADTYPEMISMATCH);
     UA_Server_delete(server);
 } END_TEST
 

+ 1 - 1
tests/check_types_builtin.c

@@ -1323,7 +1323,7 @@ START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
     srcArray[2] = UA_STRING_ALLOC("opc ua");
 
     UA_UInt32 *dimensions;
-    dimensions = UA_malloc(sizeof(UA_Int32));
+    dimensions = UA_malloc(sizeof(UA_UInt32));
     dimensions[0] = 3;
 
     UA_Variant value, copiedValue;