[Orxonox-commit 6326] r10983 - code/branches/cpp11_v2/test/core/command

landauf at orxonox.net landauf at orxonox.net
Sun Dec 27 23:17:13 CET 2015


Author: landauf
Date: 2015-12-27 23:17:12 +0100 (Sun, 27 Dec 2015)
New Revision: 10983

Modified:
   code/branches/cpp11_v2/test/core/command/FunctorTest.cc
Log:
added a bunch of unit tests for Functor

Modified: code/branches/cpp11_v2/test/core/command/FunctorTest.cc
===================================================================
--- code/branches/cpp11_v2/test/core/command/FunctorTest.cc	2015-12-27 22:07:37 UTC (rev 10982)
+++ code/branches/cpp11_v2/test/core/command/FunctorTest.cc	2015-12-27 22:17:12 UTC (rev 10983)
@@ -1,4 +1,6 @@
 #include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <functional>
 #include "core/command/Functor.h"
 
 namespace orxonox
@@ -20,33 +22,617 @@
 
         class DestroyableClass : public Destroyable
         {
-	        public:
-	            void method() {};
+            public:
+                virtual void        method0() { return; }
+                virtual int         method1(int arg1) { return arg1; }
+                virtual float       method2(int arg1, float arg2) { return arg2; }
+                virtual bool        method3(int arg1, float arg2, bool arg3) { return arg3; }
+                virtual std::string method4(int arg1, float arg2, bool arg3, const std::string& arg4) { return arg4; }
+                virtual Vector3     method5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5) { return arg5; }
+
+                static void        staticmethod0()
+                    { return staticinstance->method0(); }
+                static int         staticmethod1(int arg1)
+                    { return staticinstance->method1(arg1); }
+                static float       staticmethod2(int arg1, float arg2)
+                    { return staticinstance->method2(arg1, arg2); }
+                static bool        staticmethod3(int arg1, float arg2, bool arg3)
+                    { return staticinstance->method3(arg1, arg2, arg3); }
+                static std::string staticmethod4(int arg1, float arg2, bool arg3, const std::string& arg4)
+                    { return staticinstance->method4(arg1, arg2, arg3, arg4); }
+                static Vector3     staticmethod5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5)
+                    { return staticinstance->method5(arg1, arg2, arg3, arg4, arg5); }
+
+                static DestroyableClass* staticinstance;
         };
 
-        void f1(int, double)
+        DestroyableClass* DestroyableClass::staticinstance = nullptr;
+
+        class MockDestroyableClass : public DestroyableClass
         {
+            public:
+                MOCK_METHOD0(method0, void());
+                MOCK_METHOD1(method1, int(int));
+                MOCK_METHOD2(method2, float(int, float));
+                MOCK_METHOD3(method3, bool(int, float, bool));
+                MOCK_METHOD4(method4, std::string(int, float, bool, const std::string&));
+                MOCK_METHOD5(method5, Vector3(int, float, bool, const std::string&, const Vector3&));
+        };
+
+        class NonDestroyableClass
+        {
+            public:
+                void method() {}
+        };
+
+        void f1(int, double) {}
+        void f2(int, double, double) {}
+        int f3(int, double, double) { return 0; }
+        int f4a(int arg) { return arg*2; }
+        int f4b(int arg) { return arg*3; }
+
+        struct CallableStruct
+        {
+            public:
+                int operator()()
+                {
+                    return 1;
+                }
+        };
+    }
+
+
+    ///////////////////////////////////////////////////////////////
+    ////////////////////// Functor (general) //////////////////////
+    ///////////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, HasCorrectType)
+    {
+        FunctorMemberPtr<DestroyableClass> functor1 = createFunctor(&DestroyableClass::method0);
+        FunctorStaticPtr functor2 = createFunctor(&DestroyableClass::staticmethod0);
+        EXPECT_EQ(Functor::Type::Member, functor1->getType());
+        EXPECT_EQ(Functor::Type::Static, functor2->getType());
+    }
+
+    TEST_F(FunctorTest, ReturnsCorrectParamCount)
+    {
+        EXPECT_EQ(0, createFunctor(&DestroyableClass::method0)->getParamCount());
+        EXPECT_EQ(1, createFunctor(&DestroyableClass::method1)->getParamCount());
+        EXPECT_EQ(2, createFunctor(&DestroyableClass::method2)->getParamCount());
+        EXPECT_EQ(3, createFunctor(&DestroyableClass::method3)->getParamCount());
+        EXPECT_EQ(4, createFunctor(&DestroyableClass::method4)->getParamCount());
+        EXPECT_EQ(5, createFunctor(&DestroyableClass::method5)->getParamCount());
+    }
+
+    TEST_F(FunctorTest, HasReturnValue)
+    {
+        EXPECT_FALSE(createFunctor(&DestroyableClass::method0)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method1)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method2)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method3)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method4)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method5)->hasReturnvalue());
+    }
+
+    TEST_F(FunctorTest, GetTypenameParam)
+    {
+        FunctorPtr functor = createFunctor(&DestroyableClass::method5);
+        EXPECT_EQ("int",     functor->getTypenameParam(0));
+        EXPECT_EQ("float",   functor->getTypenameParam(1));
+        EXPECT_EQ("bool",    functor->getTypenameParam(2));
+        EXPECT_EQ("string",  functor->getTypenameParam(3));
+        EXPECT_EQ("Vector3", functor->getTypenameParam(4));
+        EXPECT_EQ("",        functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
+    }
+
+    TEST_F(FunctorTest, TypenameParamIsAlwaysVoidForFunctionWithoutParams)
+    {
+        FunctorPtr functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ("void", functor->getTypenameParam(0));
+        EXPECT_EQ("void", functor->getTypenameParam(1));
+        EXPECT_EQ("void", functor->getTypenameParam(2));
+        EXPECT_EQ("void", functor->getTypenameParam(3));
+        EXPECT_EQ("void", functor->getTypenameParam(4));
+        EXPECT_EQ("",     functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
+    }
+
+    TEST_F(FunctorTest, GetTypenameReturnvalue)
+    {
+        EXPECT_EQ("void",    createFunctor(&DestroyableClass::method0)->getTypenameReturnvalue());
+        EXPECT_EQ("int",     createFunctor(&DestroyableClass::method1)->getTypenameReturnvalue());
+        EXPECT_EQ("float",   createFunctor(&DestroyableClass::method2)->getTypenameReturnvalue());
+        EXPECT_EQ("bool",    createFunctor(&DestroyableClass::method3)->getTypenameReturnvalue());
+        EXPECT_EQ("string",  createFunctor(&DestroyableClass::method4)->getTypenameReturnvalue());
+        EXPECT_EQ("Vector3", createFunctor(&DestroyableClass::method5)->getTypenameReturnvalue());
+    }
+
+    TEST_F(FunctorTest, GetFullIdentifier)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getFullIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getFullIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getFullIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getFullIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getFullIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getFullIdentifier());
+
+        // member
+        EXPECT_EQ(typeid(       void(DestroyableClass::*)()),                                                     createFunctor(&DestroyableClass::method0)->getFullIdentifier());
+        EXPECT_EQ(typeid(        int(DestroyableClass::*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getFullIdentifier());
+        EXPECT_EQ(typeid(      float(DestroyableClass::*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getFullIdentifier());
+        EXPECT_EQ(typeid(       bool(DestroyableClass::*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getFullIdentifier());
+        EXPECT_EQ(typeid(std::string(DestroyableClass::*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getFullIdentifier());
+        EXPECT_EQ(typeid(    Vector3(DestroyableClass::*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getFullIdentifier());
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifier)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier());
+
+        // member
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::method0)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier());
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifierFor2Params)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier(2));
+
+        // member
+        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::method0)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::method1)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::method2)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::method3)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::method4)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier(2));
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifierForNParams)
+    {
+        // static
+        FunctorStaticPtr functorStatic = createFunctor(&DestroyableClass::staticmethod5);
+        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorStatic->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorStatic->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorStatic->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorStatic->getHeaderIdentifier(3));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorStatic->getHeaderIdentifier(4));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(5));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(6));
+
+        // member
+        FunctorMemberPtr<DestroyableClass> functorMember = createFunctor(&DestroyableClass::method5);
+        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorMember->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorMember->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorMember->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorMember->getHeaderIdentifier(3));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorMember->getHeaderIdentifier(4));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(5));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(6));
+    }
+
+    TEST_F(FunctorTest, CanClone)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPtr clone = functor->clone();
+        EXPECT_NE(nullptr, clone.get());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorCanBeCalled)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPtr clone = functor->clone();
+
+        EXPECT_EQ(8, (*functor)(4).get<int>());
+        EXPECT_EQ(8, (*clone)(4).get<int>());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorKeepsFunction)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
+
+        FunctorPtr clone = functor->clone();
+        FunctorPointer<int(*)(int)>* clonePointer = static_cast<FunctorPointer<int(*)(int)>*>(clone.get());
+
+        EXPECT_EQ(&f4a, pointer->getFunction());
+        EXPECT_EQ(&f4a, clonePointer->getFunction());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorKeepsObject)
+    {
+        DestroyableClass object;
+        FunctorPtr functor = createFunctor(&DestroyableClass::method0, &object);
+        FunctorPtr clone = functor->clone();
+
+        EXPECT_EQ(&object, functor->getRawObjectPointer());
+        EXPECT_EQ(&object, clone->getRawObjectPointer());
+    }
+
+    // TODO: test fails... fix or delete clone()
+//    TEST_F(FunctorTest, ClonedFunctorKeepsSafeMode)
+//    {
+//        DestroyableClass* object = new DestroyableClass();
+//        FunctorPtr functor = createFunctor(&DestroyableClass::method0, object);
+//        functor->setSafeMode(true);
+//        FunctorPtr clone = functor->clone();
+//
+//        EXPECT_EQ(object, functor->getRawObjectPointer());
+//        EXPECT_EQ(object, clone->getRawObjectPointer());
+//        object->destroy();
+//        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+//        EXPECT_EQ(nullptr, clone->getRawObjectPointer());
+//
+//    }
+
+    TEST_F(FunctorTest, CanEvaluateArgument)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        MultiType value("5");
+        EXPECT_FALSE(value.isType<int>());
+        EXPECT_TRUE(value.isType<std::string>());
+        functor->evaluateArgument(0, value);
+        EXPECT_TRUE(value.isType<int>());
+        EXPECT_FALSE(value.isType<std::string>());
+    }
+
+    TEST_F(FunctorTest, CanGetAndSetFunctionPointer)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
+
+        EXPECT_EQ(6, (*functor)(3).get<int>()); // 3*2 = 6
+        EXPECT_EQ(&f4a, pointer->getFunction());
+
+        pointer->setFunction(&f4b);
+
+        EXPECT_EQ(9, (*functor)(3).get<int>()); // 3*3 = 9
+        EXPECT_EQ(&f4b, pointer->getFunction());
+    }
+
+    TEST_F(FunctorTest, ReturnsValue)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            int result = (*functor)(&object, 13);
+            EXPECT_EQ(13, result);
         }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
+            float result = (*functor)(&object, 0, 111.11);
+            EXPECT_FLOAT_EQ(111.11, result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
+            bool result = (*functor)(&object, 0, 0, true);
+            EXPECT_EQ(true, result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
+            std::string result = (*functor)(&object, 0, 0, false, "test");
+            EXPECT_EQ("test", result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
+            Vector3 result = (*functor)(&object, 0, 0, false, "", Vector3(3, 2, 1));
+            EXPECT_EQ(Vector3(3, 2, 1), result);
+        }
+    }
 
-        void f2(int, double, double)
+
+    ///////////////////////////////////////////////////////////
+    ////////////////////// FunctorMember //////////////////////
+    ///////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, FunctorMember_CanSetObject)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getObject());
+        functor->setObject(&object);
+        EXPECT_EQ(&object, functor->getObject());
+        functor->setObject(nullptr);
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanSetObjectInConstructor)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &object);
+        EXPECT_EQ(&object, functor->getObject());
+        functor->setObject(nullptr);
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanSetRawObjectPointer)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(&object);
+        EXPECT_EQ(&object, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(nullptr);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_RawObjectPointerAndObjectAreEqual)
+    {
+        DestroyableClass object1;
+        DestroyableClass object2;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        EXPECT_EQ(nullptr, functor->getObject());
+        functor->setObject(&object1);
+        EXPECT_EQ(&object1, functor->getRawObjectPointer());
+        EXPECT_EQ(&object1, functor->getObject());
+        functor->setObject(&object2);
+        EXPECT_EQ(&object2, functor->getRawObjectPointer());
+        EXPECT_EQ(&object2, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_SetObjectThenActivateSafeMode)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
         {
+            DestroyableClass object;
+            functor->setObject(&object);
+            functor->setSafeMode(true);
+            EXPECT_EQ(&object, functor->getObject());
         }
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
 
-        int f3(int, double, double)
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_ActivateSafeModeThenSetObject)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
         {
-            return 0;
+            DestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            EXPECT_EQ(&object, functor->getObject());
         }
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
 
-        struct CallableStruct
+    TEST_F(FunctorTest, FunctorMember_SafeModeCanBeDisabledAfterObjectWasSet)
+    {
+        DestroyableClass* ptr;
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
         {
-	        public:
-	            int operator()()
-	            {
-	                return 1;
-	            }
-        };
+            DestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            functor->setSafeMode(false);
+            ptr = &object; // remember the pointer
+            EXPECT_EQ(ptr, functor->getObject());
+        }
+        EXPECT_EQ(ptr, functor->getObject());
     }
 
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_CanChangeObject)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        DestroyableClass* object1 = new DestroyableClass();
+        DestroyableClass* object2 = new DestroyableClass();
+        functor->setSafeMode(true);
+
+        functor->setObject(object1);
+        EXPECT_EQ(object1, functor->getObject());
+        functor->setObject(object2);
+        EXPECT_EQ(object2, functor->getObject());
+        object1->destroy();
+        EXPECT_EQ(object2, functor->getObject());
+        object2->destroy();
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanDestroyFunctorWhenObjectInSafeModeStillExists)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            EXPECT_EQ(&object, functor->getObject());
+        } // functor is destroyed here
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeDoesntDoAnythingWithObjectsNotInheritedFromDestroyable)
+    {
+        NonDestroyableClass* ptr;
+        FunctorMemberPtr<NonDestroyableClass> functor = createFunctor(&NonDestroyableClass::method);
+        {
+            NonDestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            ptr = &object; // remember the pointer
+            EXPECT_EQ(ptr, functor->getObject());
+        }
+        EXPECT_EQ(ptr, functor->getObject()); // pointer is still set because safe mode doesn't work on NonDestroyableClass
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInCall)
+    {
+        MockDestroyableClass mock;
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+            (*functor)(&mock);
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            (*functor)(&mock, 13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
+            (*functor)(&mock, 13, 111.11);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
+            (*functor)(&mock, 13, 111.11, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
+            (*functor)(&mock, 13, 111.11, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
+            (*functor)(&mock, 13, 111.11, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInConstructor)
+    {
+        MockDestroyableClass mock;
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &mock);
+            (*functor)();
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1, &mock);
+            (*functor)(13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2, &mock);
+            (*functor)(13, 111.11);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3, &mock);
+            (*functor)(13, 111.11, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4, &mock);
+            (*functor)(13, 111.11, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5, &mock);
+            (*functor)(13, 111.11, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorMember_ReturnsZeroIfCalledWithoutObject)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            int resultWithObject = (*functor)(&object, 13);
+            int resultWithoutObject = (*functor)(13);
+            EXPECT_EQ(13, resultWithObject);
+            EXPECT_EQ(0, resultWithoutObject);
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////
+    ////////////////////// FunctorStatic //////////////////////
+    ///////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, FunctorStatic_CanCall)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)();
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod1);
+            (*functor)(13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod2);
+            (*functor)(13, 111.11);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod3);
+            (*functor)(13, 111.11, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod4);
+            (*functor)(13, 111.11, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod5);
+            (*functor)(13, 111.11, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_CanCallWithObject)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)(&mock); // object is ignored
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_CanCallWithNull)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)(nullptr); // pointer is ignored
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_RawObjectPointerIsAlwaysNull)
+    {
+        DestroyableClass object;
+
+        FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(&object);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(nullptr);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+    }
+
+    ////////////////////////////// Various tests //////////////////////////////
+
     TEST_F(FunctorTest, canCompareHeaderIdentifiers)
     {
         FunctorPtr fp1 = createFunctor(&f1);
@@ -120,11 +706,11 @@
     {
         DestroyableClass* testclass = new DestroyableClass();
         DestroyableClass* testclass2 = new DestroyableClass();
-        FunctorPtr fp1 = createFunctor(&DestroyableClass::method, testclass);
+        FunctorPtr fp1 = createFunctor(&DestroyableClass::method0, testclass);
         fp1->setSafeMode(true);
-        FunctorPtr fp2 = createFunctor(&DestroyableClass::method, testclass);
+        FunctorPtr fp2 = createFunctor(&DestroyableClass::method0, testclass);
         fp2->setSafeMode(true);
-        FunctorPtr fp3 = createFunctor(&DestroyableClass::method, testclass);
+        FunctorPtr fp3 = createFunctor(&DestroyableClass::method0, testclass);
         fp2->setRawObjectPointer(testclass2);
 
         ASSERT_NE(nullptr, fp1->getRawObjectPointer());




More information about the Orxonox-commit mailing list