Quellcode durchsuchen

simplify calling the destructor and add unit tests for lifecycle management

Julius Pfrommer vor 8 Jahren
Ursprung
Commit
8b1fc29376
2 geänderte Dateien mit 94 neuen und 18 gelöschten Zeilen
  1. 3 17
      src/server/ua_services_nodemanagement.c
  2. 91 1
      tests/check_services_nodemanagement.c

+ 3 - 17
src/server/ua_services_nodemanagement.c

@@ -1165,24 +1165,10 @@ Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
         bd.includeSubtypes = true;
         bd.nodeClassMask = UA_NODECLASS_OBJECTTYPE;
 
-        /* browse type definitions with admin rights */
-        UA_BrowseResult result;
-        UA_BrowseResult_init(&result);
-        Service_Browse_single(server, &adminSession, NULL, &bd, 0, &result);
-        for(size_t i = 0; i < result.referencesSize; ++i) {
-            /* call the destructor */
-            UA_ReferenceDescription *rd = &result.references[i];
-            const UA_ObjectTypeNode *typenode =
-                (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, &rd->nodeId.nodeId);
-            if(!typenode)
-                continue;
-            if(typenode->nodeClass != UA_NODECLASS_OBJECTTYPE || !typenode->lifecycleManagement.destructor)
-                continue;
-
-            /* if there are several types with lifecycle management, call all the destructors */
+        /* Call the destructor from the object type */
+        const UA_ObjectTypeNode *typenode = getObjectNodeType(server, (const UA_ObjectNode*)node);
+        if(typenode && typenode->lifecycleManagement.destructor)
             typenode->lifecycleManagement.destructor(*nodeId, ((const UA_ObjectNode*)node)->instanceHandle);
-        }
-        UA_BrowseResult_deleteMembers(&result);
     }
 
     /* remove references */

+ 91 - 1
tests/check_services_nodemanagement.c

@@ -87,15 +87,105 @@ START_TEST(AddNodeTwiceGivesError) {
     UA_Server_delete(server);
 } END_TEST
 
+static UA_Boolean constructorCalled = false;
+
+static void * objectConstructor(const UA_NodeId instance) {
+    constructorCalled = true;
+    return NULL;
+}
+
+START_TEST(AddObjectWithConstructor) {
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+
+    /* Add an object type */
+    UA_NodeId objecttypeid = UA_NODEID_NUMERIC(0, 13371337);
+    UA_ObjectTypeAttributes attr;
+    UA_ObjectTypeAttributes_init(&attr);
+    attr.displayName = UA_LOCALIZEDTEXT("en_US","my objecttype");
+    UA_StatusCode res = UA_Server_addObjectTypeNode(server, objecttypeid,
+                                                    UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
+                                                    UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
+                                                    UA_QUALIFIEDNAME(0, "myobjecttype"), attr, NULL, NULL);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Add a constructor to the object type */
+    UA_ObjectLifecycleManagement olm = {objectConstructor, NULL};
+    res = UA_Server_setObjectTypeNode_lifecycleManagement(server, objecttypeid, olm);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Add an object of the type */
+    UA_ObjectAttributes attr2;
+    UA_ObjectAttributes_init(&attr2);
+    attr2.displayName = UA_LOCALIZEDTEXT("en_US","my object");
+    res = UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(0, ""),
+                                  objecttypeid, attr2, NULL, NULL);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Verify that the constructor was called */
+    ck_assert_int_eq(constructorCalled, true);
+
+    UA_Server_delete(server);
+} END_TEST
+
+static UA_Boolean destructorCalled = false;
+
+static void objectDestructor(const UA_NodeId instance, void *handle) {
+    destructorCalled = true;
+}
+
+START_TEST(DeleteObjectWithDestructor) {
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+
+    /* Add an object type */
+    UA_NodeId objecttypeid = UA_NODEID_NUMERIC(0, 13371337);
+    UA_ObjectTypeAttributes attr;
+    UA_ObjectTypeAttributes_init(&attr);
+    attr.displayName = UA_LOCALIZEDTEXT("en_US","my objecttype");
+    UA_StatusCode res = UA_Server_addObjectTypeNode(server, objecttypeid,
+                                                    UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
+                                                    UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
+                                                    UA_QUALIFIEDNAME(0, "myobjecttype"), attr, NULL, NULL);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Add a constructor to the object type */
+    UA_ObjectLifecycleManagement olm = {NULL, objectDestructor};
+    res = UA_Server_setObjectTypeNode_lifecycleManagement(server, objecttypeid, olm);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Add an object of the type */
+    UA_NodeId objectid = UA_NODEID_NUMERIC(0, 23372337);
+    UA_ObjectAttributes attr2;
+    UA_ObjectAttributes_init(&attr2);
+    attr2.displayName = UA_LOCALIZEDTEXT("en_US","my object");
+    res = UA_Server_addObjectNode(server, objectid, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(0, ""),
+                                  objecttypeid, attr2, NULL, NULL);
+    ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
+
+    /* Delete the object */
+    UA_Server_deleteNode(server, objectid, true);
+
+    /* Verify that the denstructor was called */
+    ck_assert_int_eq(destructorCalled, true);
+
+    UA_Server_delete(server);
+} END_TEST
+
 static Suite * testSuite_services_nodemanagement(void) {
     Suite *s = suite_create("services_nodemanagement");
 
     TCase *tc_addnodes = tcase_create("addnodes");
     tcase_add_test(tc_addnodes, AddVariableNode);
-        tcase_add_test(tc_addnodes, AddComplexTypeWithInheritance);
+    tcase_add_test(tc_addnodes, AddComplexTypeWithInheritance);
     tcase_add_test(tc_addnodes, AddNodeTwiceGivesError);
+    tcase_add_test(tc_addnodes, AddObjectWithConstructor);
+
+    TCase *tc_deletenodes = tcase_create("deletenodes");
+    tcase_add_test(tc_addnodes, DeleteObjectWithDestructor);
 
     suite_add_tcase(s, tc_addnodes);
+    suite_add_tcase(s, tc_deletenodes);
     return s;
 }