Bläddra i källkod

ArrayDimension constraints are only upper bounds (fix #2325)

Julius Pfrommer 6 år sedan
förälder
incheckning
acd2f4a6bf

+ 3 - 2
src/server/ua_services_attribute.c

@@ -741,9 +741,10 @@ compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
     if(testArrayDimensionsSize != constraintArrayDimensionsSize)
         return false;
 
-    /* Dimension lengths must match; zero in the constraint is a wildcard */
+    /* Dimension lengths must not be larger than the constraint. Zero in the
+     * constraint indicates a wildcard. */
     for(size_t i = 0; i < constraintArrayDimensionsSize; ++i) {
-        if(constraintArrayDimensions[i] != testArrayDimensions[i] &&
+        if(constraintArrayDimensions[i] < testArrayDimensions[i] &&
            constraintArrayDimensions[i] != 0)
             return false;
     }

+ 15 - 10
tests/client/check_client_highlevel.c

@@ -2,9 +2,6 @@
  * 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 <stdio.h>
-#include <stdlib.h>
-
 #include "ua_server.h"
 #include "ua_client.h"
 #include "ua_config_default.h"
@@ -372,7 +369,8 @@ START_TEST(Node_AddReadWriteNodes) {
                                          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);
+                                         UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE),
+                                         attr, &nodeReadWriteUnitTest);
         ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
     }
 
@@ -885,15 +883,22 @@ START_TEST(Node_ReadWrite_ArrayDimensions) {
     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
-    UA_UInt32 arrayDimsNew[] = {3};
+    // 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 3 as the value
-    UA_Double vec[3] = {0.0, 0.0, 0.0};
-    UA_Variant value;
-    UA_Variant_setArray(&value, vec, 3, &UA_TYPES[UA_TYPES_DOUBLE]);
+    // 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);
 
@@ -905,7 +910,7 @@ START_TEST(Node_ReadWrite_ArrayDimensions) {
                                                     &arrayDimsReadSize, &arrayDimsRead);
     ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
     ck_assert_int_eq(arrayDimsReadSize, 1);
-    ck_assert_int_eq(arrayDimsRead[0], 3);
+    ck_assert_int_eq(arrayDimsRead[0], 1);
     UA_Array_delete(arrayDimsRead, arrayDimsReadSize, &UA_TYPES[UA_TYPES_UINT32]);
 }
 END_TEST

+ 65 - 7
tests/server/check_services_nodemanagement.c

@@ -58,7 +58,10 @@ START_TEST(AddVariableNode) {
     ck_assert_int_eq(UA_STATUSCODE_GOOD, res);
 } END_TEST
 
-START_TEST(InstantiateVariableTypeNode) {
+static UA_NodeId pointTypeId;
+
+static void
+addVariableTypeNode(void) {
     UA_VariableTypeAttributes vtAttr = UA_VariableTypeAttributes_default;
     vtAttr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
     vtAttr.valueRank = UA_VALUERANK_ONE_DIMENSION;
@@ -71,7 +74,6 @@ START_TEST(InstantiateVariableTypeNode) {
     UA_Double zero[2] = {0.0, 0.0};
     UA_Variant_setArray(&vtAttr.value, zero, 2, &UA_TYPES[UA_TYPES_DOUBLE]);
 
-    UA_NodeId pointTypeId;
     UA_StatusCode res =
         UA_Server_addVariableTypeNode(server, UA_NODEID_NULL,
                                       UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
@@ -79,8 +81,13 @@ START_TEST(InstantiateVariableTypeNode) {
                                       UA_QUALIFIEDNAME(1, "2DPoint Type"), UA_NODEID_NULL,
                                       vtAttr, NULL, &pointTypeId);
     ck_assert_int_eq(UA_STATUSCODE_GOOD, res);
+}
 
+START_TEST(InstantiateVariableTypeNode) {
+    addVariableTypeNode();
+    
     /* Prepare the node attributes */
+    UA_UInt32 arrayDims[1] = {2};
     UA_VariableAttributes vAttr = UA_VariableAttributes_default;
     vAttr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
     vAttr.valueRank = UA_VALUERANK_ONE_DIMENSION;
@@ -92,11 +99,12 @@ START_TEST(InstantiateVariableTypeNode) {
 
     /* Add the node */
     UA_NodeId pointVariableId;
-    res = UA_Server_addVariableNode(server, UA_NODEID_NULL,
-                                    UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                    UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-                                    UA_QUALIFIEDNAME(1, "2DPoint Type"), pointTypeId,
-                                    vAttr, NULL, &pointVariableId);
+    UA_StatusCode res =
+        UA_Server_addVariableNode(server, UA_NODEID_NULL,
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                                  UA_QUALIFIEDNAME(1, "2DPoint Type"), pointTypeId,
+                                  vAttr, NULL, &pointVariableId);
     ck_assert_int_eq(UA_STATUSCODE_GOOD, res);
 
     /* Was the value instantiated? */
@@ -107,6 +115,54 @@ START_TEST(InstantiateVariableTypeNode) {
     UA_Variant_deleteMembers(&val);
 } END_TEST
 
+START_TEST(InstantiateVariableTypeNodeWrongDims) {
+    addVariableTypeNode();
+    
+    /* Prepare the node attributes */
+    UA_UInt32 arrayDims[1] = {3}; /* This will fail as the dimensions are too big */
+    UA_VariableAttributes vAttr = UA_VariableAttributes_default;
+    vAttr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
+    vAttr.valueRank = UA_VALUERANK_ONE_DIMENSION;
+    vAttr.arrayDimensions = arrayDims;
+    vAttr.arrayDimensionsSize = 1;
+    vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "2DPoint Variable");
+    vAttr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
+    /* vAttr.value is left empty, the server instantiates with the default value */
+
+    /* Add the node */
+    UA_StatusCode res =
+        UA_Server_addVariableNode(server, UA_NODEID_NULL,
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                                  UA_QUALIFIEDNAME(1, "2DPoint Type"), pointTypeId,
+                                  vAttr, NULL, NULL);
+    ck_assert_int_eq(UA_STATUSCODE_BADTYPEMISMATCH, res);
+} END_TEST
+
+START_TEST(InstantiateVariableTypeNodeLessDims) {
+    addVariableTypeNode();
+    
+    /* Prepare the node attributes */
+    UA_UInt32 arrayDims[1] = {1}; /* This will match as the dimension constraints are an upper bound */
+    UA_VariableAttributes vAttr = UA_VariableAttributes_default;
+    vAttr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
+    vAttr.valueRank = UA_VALUERANK_ONE_DIMENSION;
+    vAttr.arrayDimensions = arrayDims;
+    vAttr.arrayDimensionsSize = 1;
+    vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "2DPoint Variable");
+    vAttr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
+    /* vAttr.value is left empty, the server instantiates with the default value */
+
+    /* Add the node */
+    UA_StatusCode res =
+        UA_Server_addVariableNode(server, UA_NODEID_NULL,
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                                  UA_QUALIFIEDNAME(1, "2DPoint Type"), pointTypeId,
+                                  vAttr, NULL, NULL);
+    ck_assert_int_eq(UA_STATUSCODE_BADTYPEMISMATCH, res);
+} END_TEST
+
 START_TEST(AddComplexTypeWithInheritance) {
     /* add a variable node to the address space */
     UA_ObjectAttributes attr = UA_ObjectAttributes_default;
@@ -410,6 +466,8 @@ int main(void) {
     tcase_add_checked_fixture(tc_addnodes, setup, teardown);
     tcase_add_test(tc_addnodes, AddVariableNode);
     tcase_add_test(tc_addnodes, InstantiateVariableTypeNode);
+    tcase_add_test(tc_addnodes, InstantiateVariableTypeNodeWrongDims);
+    tcase_add_test(tc_addnodes, InstantiateVariableTypeNodeLessDims);
     tcase_add_test(tc_addnodes, AddComplexTypeWithInheritance);
     tcase_add_test(tc_addnodes, AddNodeTwiceGivesError);
     tcase_add_test(tc_addnodes, AddObjectWithConstructor);