Browse Source

fix(server): Delete node when replaceNode is not successful

Ubuntu 5 years ago
parent
commit
7f3271d405
2 changed files with 76 additions and 1 deletions
  1. 3 1
      plugins/ua_nodestore_default.c
  2. 73 0
      tests/server/check_server_callbacks.c

+ 3 - 1
plugins/ua_nodestore_default.c

@@ -244,8 +244,10 @@ UA_StatusCode
 UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node) {
     /* Find the node */
     const UA_Node *oldNode = UA_Nodestore_getNode(nsCtx, &node->nodeId);
-    if(!oldNode)
+    if(!oldNode) {
+        deleteEntry(container_of(node, NodeEntry, nodeId));
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
+    }
 
     /* Test if the copy is current */
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);

+ 73 - 0
tests/server/check_server_callbacks.c

@@ -17,6 +17,7 @@ UA_Boolean running;
 UA_ServerNetworkLayer nl;
 UA_NodeId temperatureNodeId = {1, UA_NODEIDTYPE_NUMERIC, {1001}};
 UA_Int32 temperature;
+UA_Boolean deleteNodeWhileWriting;
 THREAD_HANDLE server_thread;
 
 static void
@@ -95,6 +96,8 @@ writeTemperature(UA_Server *tmpServer,
                  const UA_NodeId *nodeId, void *nodeContext,
                  const UA_NumericRange *range, const UA_DataValue *data) {
     temperature = *(UA_Int32 *) data->value.data;
+    if (deleteNodeWhileWriting)
+        UA_Server_deleteNode(server, temperatureNodeId, true);
     return UA_STATUSCODE_GOOD;
 }
 
@@ -197,12 +200,82 @@ START_TEST(client_readMultipleAttributes) {
     }
 END_TEST
 
+START_TEST(client_writeValueCallbackAttribute) {
+        UA_Client *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);
+
+        UA_Variant *val = UA_Variant_new();
+        UA_Int32 value = 77;
+        UA_Variant_setScalarCopy(val, &value, &UA_TYPES[UA_TYPES_INT32]);
+        retval = UA_Client_writeValueAttribute(client, temperatureNodeId, val);
+
+#ifdef UA_ENABLE_IMMUTABLE_NODES
+        ck_assert_uint_eq(retval, UA_STATUSCODE_BADNODEIDUNKNOWN);
+#else
+        ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
+#endif
+        UA_Variant_delete(val);
+
+        UA_Client_disconnect(client);
+        UA_Client_delete(client);
+    }
+END_TEST
+
+START_TEST(client_writeMultipleAttributes) {
+        UA_Client *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);
+
+        UA_Int32 value1 = 23;
+        UA_WriteRequest wReq;
+        UA_WriteRequest_init(&wReq);
+        UA_LocalizedText string = UA_LOCALIZEDTEXT("en-US", "Temperature");
+        UA_WriteValue wv[2];
+        UA_WriteValue_init(&wv[0]);
+        UA_WriteValue_init(&wv[1]);
+        wReq.nodesToWrite = wv;
+        wReq.nodesToWriteSize = 2;
+        wReq.nodesToWrite[0].nodeId = temperatureNodeId;
+        wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_DISPLAYNAME;
+        wReq.nodesToWrite[0].value.hasValue = true;
+        wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
+        wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE;
+        wReq.nodesToWrite[0].value.value.data = &string;
+
+        wReq.nodesToWrite[1].nodeId = temperatureNodeId;
+        wReq.nodesToWrite[1].attributeId = UA_ATTRIBUTEID_VALUE;
+        wReq.nodesToWrite[1].value.hasValue = true;
+        wReq.nodesToWrite[1].value.value.type = &UA_TYPES[UA_TYPES_INT32];
+        wReq.nodesToWrite[1].value.value.storageType = UA_VARIANT_DATA_NODELETE;
+        wReq.nodesToWrite[1].value.value.data = &value1;
+
+
+        UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
+
+        ck_assert_uint_eq(wResp.responseHeader.serviceResult,UA_STATUSCODE_GOOD);
+        ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
+
+        UA_WriteResponse_clear(&wResp);
+        UA_Client_disconnect(client);
+        UA_Client_delete(client);
+    }
+END_TEST
+
 static Suite* testSuite_immutableNodes(void) {
     Suite *s = suite_create("Immutable Nodes");
     TCase *valueCallback = tcase_create("ValueCallback");
+
+    deleteNodeWhileWriting = UA_FALSE;
     tcase_add_checked_fixture(valueCallback, setup, teardown);
     tcase_add_test(valueCallback, client_readValueCallbackAttribute);
     tcase_add_test(valueCallback, client_readMultipleAttributes);
+
+    deleteNodeWhileWriting = UA_TRUE;
+    tcase_add_test(valueCallback, client_writeValueCallbackAttribute);
+    tcase_add_test(valueCallback, client_writeMultipleAttributes);
     suite_add_tcase(s,valueCallback);
     return s;
 }