[Orxonox-commit 5703] r10363 - in code/branches/core7: src/libraries/core/class test/core test/core/class

landauf at orxonox.net landauf at orxonox.net
Mon Apr 13 23:15:05 CEST 2015


Author: landauf
Date: 2015-04-13 23:15:04 +0200 (Mon, 13 Apr 2015)
New Revision: 10363

Added:
   code/branches/core7/test/core/class/IdentifierNestedClassHierarchyTest.cc
Modified:
   code/branches/core7/src/libraries/core/class/Identifier.cc
   code/branches/core7/src/libraries/core/class/Identifier.h
   code/branches/core7/src/libraries/core/class/IdentifierManager.cc
   code/branches/core7/test/core/CMakeLists.txt
Log:
bugfix: class hierarchy wrongly considered the classes of nested members as base classes of the surrounding class. this is now fixed by using RTTI (i.e. dynamic_cast). also added some tests.

Modified: code/branches/core7/src/libraries/core/class/Identifier.cc
===================================================================
--- code/branches/core7/src/libraries/core/class/Identifier.cc	2015-04-12 21:07:14 UTC (rev 10362)
+++ code/branches/core7/src/libraries/core/class/Identifier.cc	2015-04-13 21:15:04 UTC (rev 10363)
@@ -143,9 +143,10 @@
 
     /**
      * @brief Initializes the parents of this Identifier while creating the class hierarchy.
-     * @param identifiers All identifiers that were used to create an instance of this class (including this identifier itself)
+     * @param instance The instance that was used to determine the class hierarchy of this identifier.
+     * @param identifiers All identifiers that were used to create the instance of this class (including this identifier itself)
      */
-    void Identifier::initializeParents(const std::set<const Identifier*>& identifiers)
+    void Identifier::initializeParents(Identifiable* instance, const std::set<const Identifier*>& identifiers)
     {
         if (!IdentifierManager::getInstance().isCreatingHierarchy())
         {
@@ -153,8 +154,11 @@
             return;
         }
 
+        // Add all identifiers which are real parents (dynamic_cast is possible) and that are not equal to THIS identifier.
+        // Checking for dynamic_cast is necessary because some classes may have other classes as nested members. This means that the Identifiers of the nested
+        // classes are also added to the set of potential parents. The only way to distinguish them is to use RTTI (i.e. dynamic_cast).
         for (std::set<const Identifier*>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it)
-            if (*it != this)
+            if (*it != this && (*it)->canDynamicCastObjectToIdentifierClass(instance))
                 this->parents_.insert(*it);
     }
 

Modified: code/branches/core7/src/libraries/core/class/Identifier.h
===================================================================
--- code/branches/core7/src/libraries/core/class/Identifier.h	2015-04-12 21:07:14 UTC (rev 10362)
+++ code/branches/core7/src/libraries/core/class/Identifier.h	2015-04-13 21:15:04 UTC (rev 10363)
@@ -147,7 +147,7 @@
             /////////////////////////////
             Identifier& inheritsFrom(Identifier* directParent);
 
-            void initializeParents(const std::set<const Identifier*>& identifiers);
+            void initializeParents(Identifiable* instance, const std::set<const Identifier*>& identifiers);
             void initializeDirectParentsOfAbstractClass();
             void finishInitialization();
 
@@ -222,7 +222,7 @@
             void addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container);
             XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
 
-            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) = 0;
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
 
         protected:
             virtual void createSuperFunctionCaller() const = 0;
@@ -289,7 +289,7 @@
             virtual const std::string& getTypeidName()
                 { return this->typeidName_; }
 
-            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object)
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const
                 { return dynamic_cast<T*>(object) != 0; }
 
         private:

Modified: code/branches/core7/src/libraries/core/class/IdentifierManager.cc
===================================================================
--- code/branches/core7/src/libraries/core/class/IdentifierManager.cc	2015-04-12 21:07:14 UTC (rev 10362)
+++ code/branches/core7/src/libraries/core/class/IdentifierManager.cc	2015-04-13 21:15:04 UTC (rev 10363)
@@ -121,9 +121,10 @@
                     Identifiable* temp = it->second->fabricate(&temporaryContext);
                     if (temp->getIdentifier() != it->second)
                         orxout(internal_error) << "Newly created object of type " << it->second->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
+
+                    it->second->initializeParents(temp, this->identifiersOfNewObject_);
+
                     delete temp;
-
-                    it->second->initializeParents(this->identifiersOfNewObject_);
                 }
                 else
                     it->second->initializeDirectParentsOfAbstractClass();

Modified: code/branches/core7/test/core/CMakeLists.txt
===================================================================
--- code/branches/core7/test/core/CMakeLists.txt	2015-04-12 21:07:14 UTC (rev 10362)
+++ code/branches/core7/test/core/CMakeLists.txt	2015-04-13 21:15:04 UTC (rev 10363)
@@ -11,6 +11,7 @@
     class/IdentifierTest.cc
     class/IdentifierClassHierarchyTest.cc
     class/IdentifierSimpleClassHierarchyTest.cc
+    class/IdentifierNestedClassHierarchyTest.cc
     class/IdentifierExternalClassHierarchyTest.cc
     class/OrxonoxClassTest.cc
     class/OrxonoxInterfaceTest.cc

Added: code/branches/core7/test/core/class/IdentifierNestedClassHierarchyTest.cc
===================================================================
--- code/branches/core7/test/core/class/IdentifierNestedClassHierarchyTest.cc	                        (rev 0)
+++ code/branches/core7/test/core/class/IdentifierNestedClassHierarchyTest.cc	2015-04-13 21:15:04 UTC (rev 10363)
@@ -0,0 +1,346 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    // Tests the class hierarchy with classes that contain other classes as members.
+    //
+    //                    +------ Nested1         +------ Class1_notNested
+    //                    +------ Nested2         +------ Class2_oneNested
+    // OrxonoxClass <-----+------ BaseClass <-----+------ Class3_twoNested <----------- Class3_Child
+    //                                            +------ Class4_class1Nested
+    //                                            +------ Class5_class2Nested
+    //                                            +------ Class6_class3Nested <-------- Class6_Child
+
+    namespace
+    {
+        class Nested1 : public OrxonoxClass
+        {
+            public:
+                Nested1() { RegisterObject(Nested1); }
+        };
+
+        class Nested2 : public OrxonoxClass
+        {
+            public:
+                Nested2() { RegisterObject(Nested2); }
+        };
+
+        class BaseClass : public OrxonoxClass
+        {
+            public:
+                BaseClass() { RegisterObject(BaseClass); }
+        };
+
+        class Class1_notNested : public BaseClass
+        {
+            public:
+                Class1_notNested() { RegisterObject(Class1_notNested); }
+        };
+
+        class Class2_oneNested : public BaseClass
+        {
+            public:
+                Class2_oneNested() { RegisterObject(Class2_oneNested); }
+                Nested1 nested1_;
+        };
+
+        class Class3_twoNested : public BaseClass
+        {
+            public:
+                Class3_twoNested() { RegisterObject(Class3_twoNested); }
+                Nested1 nested1_;
+                Nested2 nested2_;
+        };
+
+        class Class4_class1Nested : public BaseClass
+        {
+            public:
+                Class4_class1Nested() { RegisterObject(Class4_class1Nested); }
+                Class1_notNested nested_;
+        };
+
+        class Class5_class2Nested : public BaseClass
+        {
+            public:
+                Class5_class2Nested() { RegisterObject(Class5_class2Nested); }
+                Class2_oneNested nested_;
+        };
+
+        class Class6_class3Nested : public BaseClass
+        {
+            public:
+                Class6_class3Nested() { RegisterObject(Class6_class3Nested); }
+                Class3_twoNested nested_;
+        };
+
+        class Class3_Child : public Class3_twoNested
+        {
+            public:
+                Class3_Child() { RegisterObject(Class3_Child); }
+        };
+
+        class Class6_Child : public Class6_class3Nested
+        {
+            public:
+                Class6_Child() { RegisterObject(Class6_Child); }
+        };
+
+        // Fixture
+        class IdentifierNestedClassHierarchyTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp()
+                {
+                    registerClass("Context", new ClassFactoryWithContext<Context>());
+                    registerClass("Listable", new ClassFactoryWithContext<Listable>());
+                    registerClass("Configurable", new ClassFactoryNoArgs<Configurable>());
+                    registerClass("OrxonoxClass", new ClassFactoryNoArgs<OrxonoxClass>());
+                    registerClass("Nested1", new ClassFactoryNoArgs<Nested1>());
+                    registerClass("Nested2", new ClassFactoryNoArgs<Nested2>());
+                    registerClass("BaseClass", new ClassFactoryNoArgs<BaseClass>());
+                    registerClass("Class1_notNested", new ClassFactoryNoArgs<Class1_notNested>());
+                    registerClass("Class2_oneNested", new ClassFactoryNoArgs<Class2_oneNested>());
+                    registerClass("Class3_twoNested", new ClassFactoryNoArgs<Class3_twoNested>());
+                    registerClass("Class4_class1Nested", new ClassFactoryNoArgs<Class4_class1Nested>());
+                    registerClass("Class5_class2Nested", new ClassFactoryNoArgs<Class5_class2Nested>());
+                    registerClass("Class6_class3Nested", new ClassFactoryNoArgs<Class6_class3Nested>());
+                    registerClass("Class3_Child", new ClassFactoryNoArgs<Class3_Child>());
+                    registerClass("Class6_Child", new ClassFactoryNoArgs<Class6_Child>());
+
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown()
+                {
+                    IdentifierManager::getInstance().destroyAllIdentifiers();
+                }
+        };
+
+        bool contains(const std::set<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return identifiers.find(identifier) != identifiers.end();
+        }
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestNested1)
+    {
+        Identifier* identifier = Class(Nested1);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestNested2)
+    {
+        Identifier* identifier = Class(Nested2);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestBaseClass)
+    {
+        Identifier* identifier = Class(BaseClass);
+
+        EXPECT_EQ(6u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class1_notNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2_oneNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3_twoNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class4_class1Nested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class5_class2Nested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class6_class3Nested)));
+
+        EXPECT_EQ(8u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class1_notNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2_oneNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_twoNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class4_class1Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class5_class2Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_class3Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_Child)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass1_notNested)
+    {
+        Identifier* identifier = Class(Class1_notNested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass2_oneNested)
+    {
+        Identifier* identifier = Class(Class2_oneNested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass3_twoNested)
+    {
+        Identifier* identifier = Class(Class3_twoNested);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3_Child)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass4_class1Nested)
+    {
+        Identifier* identifier = Class(Class4_class1Nested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass5_class2Nested)
+    {
+        Identifier* identifier = Class(Class5_class2Nested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass6_class3Nested)
+    {
+        Identifier* identifier = Class(Class6_class3Nested);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass3_Child)
+    {
+        Identifier* identifier = Class(Class3_Child);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Class3_twoNested)));
+
+        EXPECT_EQ(6u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Class3_twoNested)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass6_Child)
+    {
+        Identifier* identifier = Class(Class6_Child);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Class6_class3Nested)));
+
+        EXPECT_EQ(6u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Class6_class3Nested)));
+    }
+}




More information about the Orxonox-commit mailing list