Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/PresentationFS18/test/core/command/FunctorTest.cc @ 12012

Last change on this file since 12012 was 11097, checked in by landauf, 9 years ago

fixed build on tardis.

  • Property svn:eol-style set to native
File size: 38.3 KB
Line 
1#include <gtest/gtest.h>
2#include <gmock/gmock.h>
3#include <functional>
4#include "core/command/Functor.h"
5
6namespace orxonox
7{
8    namespace
9    {
10        // Fixture
11        class FunctorTest : public ::testing::Test
12        {
13            public:
14                virtual void SetUp() override
15                {
16                }
17
18                virtual void TearDown() override
19                {
20                }
21        };
22
23        class DestroyableClass : public Destroyable
24        {
25            public:
26                virtual void        method0() { return; }
27                virtual int         method1(int arg1) { return arg1; }
28                virtual float       method2(int arg1, float arg2) { return arg2; }
29                virtual bool        method3(int arg1, float arg2, bool arg3) { return arg3; }
30                virtual std::string method4(int arg1, float arg2, bool arg3, const std::string& arg4) { return arg4; }
31                virtual Vector3     method5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5) { return arg5; }
32
33                static void        staticmethod0()
34                    { return staticinstance->method0(); }
35                static int         staticmethod1(int arg1)
36                    { return staticinstance->method1(arg1); }
37                static float       staticmethod2(int arg1, float arg2)
38                    { return staticinstance->method2(arg1, arg2); }
39                static bool        staticmethod3(int arg1, float arg2, bool arg3)
40                    { return staticinstance->method3(arg1, arg2, arg3); }
41                static std::string staticmethod4(int arg1, float arg2, bool arg3, const std::string& arg4)
42                    { return staticinstance->method4(arg1, arg2, arg3, arg4); }
43                static Vector3     staticmethod5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5)
44                    { return staticinstance->method5(arg1, arg2, arg3, arg4, arg5); }
45
46                static DestroyableClass* staticinstance;
47        };
48
49        DestroyableClass* DestroyableClass::staticinstance = nullptr;
50
51        class MockDestroyableClass : public DestroyableClass
52        {
53            public:
54                MOCK_METHOD0(method0, void());
55                MOCK_METHOD1(method1, int(int));
56                MOCK_METHOD2(method2, float(int, float));
57                MOCK_METHOD3(method3, bool(int, float, bool));
58                MOCK_METHOD4(method4, std::string(int, float, bool, const std::string&));
59                MOCK_METHOD5(method5, Vector3(int, float, bool, const std::string&, const Vector3&));
60        };
61
62        class NonDestroyableClass
63        {
64            public:
65                void method() {}
66        };
67
68        void f1(int, double) {}
69        void f2(int, double, double) {}
70        int f3(int, double, double) { return 0; }
71        int f4a(int arg) { return arg*2; }
72        int f4b(int arg) { return arg*3; }
73        int multiply(int a, int b) { return a*b; }
74
75        struct CallableStruct
76        {
77            public:
78                int operator()()
79                {
80                    return 1;
81                }
82        };
83    }
84
85
86    ///////////////////////////////////////////////////////////////
87    ////////////////////// Functor (general) //////////////////////
88    ///////////////////////////////////////////////////////////////
89
90    TEST_F(FunctorTest, HasCorrectType)
91    {
92        FunctorMemberPtr<DestroyableClass> functor1 = createFunctor(&DestroyableClass::method0);
93        FunctorStaticPtr functor2 = createFunctor(&DestroyableClass::staticmethod0);
94        EXPECT_EQ(Functor::Type::Member, functor1->getType());
95        EXPECT_EQ(Functor::Type::Static, functor2->getType());
96    }
97
98    TEST_F(FunctorTest, ReturnsCorrectParamCount)
99    {
100        EXPECT_EQ(0u, createFunctor(&DestroyableClass::method0)->getParamCount());
101        EXPECT_EQ(1u, createFunctor(&DestroyableClass::method1)->getParamCount());
102        EXPECT_EQ(2u, createFunctor(&DestroyableClass::method2)->getParamCount());
103        EXPECT_EQ(3u, createFunctor(&DestroyableClass::method3)->getParamCount());
104        EXPECT_EQ(4u, createFunctor(&DestroyableClass::method4)->getParamCount());
105        EXPECT_EQ(5u, createFunctor(&DestroyableClass::method5)->getParamCount());
106    }
107
108    TEST_F(FunctorTest, HasReturnValue)
109    {
110        EXPECT_FALSE(createFunctor(&DestroyableClass::method0)->hasReturnvalue());
111        EXPECT_TRUE(createFunctor(&DestroyableClass::method1)->hasReturnvalue());
112        EXPECT_TRUE(createFunctor(&DestroyableClass::method2)->hasReturnvalue());
113        EXPECT_TRUE(createFunctor(&DestroyableClass::method3)->hasReturnvalue());
114        EXPECT_TRUE(createFunctor(&DestroyableClass::method4)->hasReturnvalue());
115        EXPECT_TRUE(createFunctor(&DestroyableClass::method5)->hasReturnvalue());
116    }
117
118    TEST_F(FunctorTest, GetTypenameParam)
119    {
120        FunctorPtr functor = createFunctor(&DestroyableClass::method5);
121        EXPECT_EQ("int",     functor->getTypenameParam(0));
122        EXPECT_EQ("float",   functor->getTypenameParam(1));
123        EXPECT_EQ("bool",    functor->getTypenameParam(2));
124        EXPECT_EQ("string",  functor->getTypenameParam(3));
125        EXPECT_EQ("Vector3", functor->getTypenameParam(4));
126        EXPECT_EQ("",        functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
127    }
128
129    TEST_F(FunctorTest, TypenameParamIsAlwaysVoidForFunctionWithoutParams)
130    {
131        FunctorPtr functor = createFunctor(&DestroyableClass::method0);
132        EXPECT_EQ("void", functor->getTypenameParam(0));
133        EXPECT_EQ("void", functor->getTypenameParam(1));
134        EXPECT_EQ("void", functor->getTypenameParam(2));
135        EXPECT_EQ("void", functor->getTypenameParam(3));
136        EXPECT_EQ("void", functor->getTypenameParam(4));
137        EXPECT_EQ("",     functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
138    }
139
140    TEST_F(FunctorTest, GetTypenameReturnvalue)
141    {
142        EXPECT_EQ("void",    createFunctor(&DestroyableClass::method0)->getTypenameReturnvalue());
143        EXPECT_EQ("int",     createFunctor(&DestroyableClass::method1)->getTypenameReturnvalue());
144        EXPECT_EQ("float",   createFunctor(&DestroyableClass::method2)->getTypenameReturnvalue());
145        EXPECT_EQ("bool",    createFunctor(&DestroyableClass::method3)->getTypenameReturnvalue());
146        EXPECT_EQ("string",  createFunctor(&DestroyableClass::method4)->getTypenameReturnvalue());
147        EXPECT_EQ("Vector3", createFunctor(&DestroyableClass::method5)->getTypenameReturnvalue());
148    }
149
150    TEST_F(FunctorTest, GetFullIdentifier)
151    {
152        // static
153        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getFullIdentifier());
154        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getFullIdentifier());
155        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getFullIdentifier());
156        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getFullIdentifier());
157        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getFullIdentifier());
158        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getFullIdentifier());
159
160        // member
161        EXPECT_EQ(typeid(       void(DestroyableClass::*)()),                                                     createFunctor(&DestroyableClass::method0)->getFullIdentifier());
162        EXPECT_EQ(typeid(        int(DestroyableClass::*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getFullIdentifier());
163        EXPECT_EQ(typeid(      float(DestroyableClass::*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getFullIdentifier());
164        EXPECT_EQ(typeid(       bool(DestroyableClass::*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getFullIdentifier());
165        EXPECT_EQ(typeid(std::string(DestroyableClass::*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getFullIdentifier());
166        EXPECT_EQ(typeid(    Vector3(DestroyableClass::*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getFullIdentifier());
167    }
168
169    TEST_F(FunctorTest, GetHeaderIdentifier)
170    {
171        // static
172        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier());
173        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier());
174        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier());
175        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier());
176        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier());
177        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier());
178
179        // member
180        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::method0)->getHeaderIdentifier());
181        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getHeaderIdentifier());
182        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getHeaderIdentifier());
183        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getHeaderIdentifier());
184        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getHeaderIdentifier());
185        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier());
186    }
187
188    TEST_F(FunctorTest, GetHeaderIdentifierFor2Params)
189    {
190        // static
191        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier(2));
192        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier(2));
193        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier(2));
194        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier(2));
195        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier(2));
196        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier(2));
197
198        // member
199        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::method0)->getHeaderIdentifier(2));
200        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::method1)->getHeaderIdentifier(2));
201        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::method2)->getHeaderIdentifier(2));
202        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::method3)->getHeaderIdentifier(2));
203        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::method4)->getHeaderIdentifier(2));
204        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier(2));
205    }
206
207    TEST_F(FunctorTest, GetHeaderIdentifierForNParams)
208    {
209        // static
210        FunctorStaticPtr functorStatic = createFunctor(&DestroyableClass::staticmethod5);
211        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorStatic->getHeaderIdentifier(0));
212        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorStatic->getHeaderIdentifier(1));
213        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorStatic->getHeaderIdentifier(2));
214        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorStatic->getHeaderIdentifier(3));
215        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorStatic->getHeaderIdentifier(4));
216        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(5));
217        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(6));
218
219        // member
220        FunctorMemberPtr<DestroyableClass> functorMember = createFunctor(&DestroyableClass::method5);
221        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorMember->getHeaderIdentifier(0));
222        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorMember->getHeaderIdentifier(1));
223        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorMember->getHeaderIdentifier(2));
224        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorMember->getHeaderIdentifier(3));
225        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorMember->getHeaderIdentifier(4));
226        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(5));
227        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(6));
228    }
229
230    TEST_F(FunctorTest, CanClone)
231    {
232        FunctorPtr functor = createFunctor(&f4a);
233        FunctorPtr clone = functor->clone();
234        EXPECT_NE(nullptr, clone.get());
235    }
236
237    TEST_F(FunctorTest, ClonedFunctorCanBeCalled)
238    {
239        FunctorPtr functor = createFunctor(&f4a);
240        FunctorPtr clone = functor->clone();
241
242        EXPECT_EQ(8, (*functor)(4).get<int>());
243        EXPECT_EQ(8, (*clone)(4).get<int>());
244    }
245
246    TEST_F(FunctorTest, ClonedFunctorKeepsFunction)
247    {
248        FunctorPtr functor = createFunctor(&f4a);
249        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
250
251        FunctorPtr clone = functor->clone();
252        FunctorPointer<int(*)(int)>* clonePointer = static_cast<FunctorPointer<int(*)(int)>*>(clone.get());
253
254        EXPECT_EQ(&f4a, pointer->getFunction());
255        EXPECT_EQ(&f4a, clonePointer->getFunction());
256    }
257
258    TEST_F(FunctorTest, ClonedFunctorKeepsObject)
259    {
260        DestroyableClass object;
261        FunctorPtr functor = createFunctor(&DestroyableClass::method0, &object);
262        FunctorPtr clone = functor->clone();
263
264        EXPECT_EQ(&object, functor->getRawObjectPointer());
265        EXPECT_EQ(&object, clone->getRawObjectPointer());
266    }
267
268    // TODO: test fails... fix or delete clone()
269//    TEST_F(FunctorTest, ClonedFunctorKeepsSafeMode)
270//    {
271//        DestroyableClass* object = new DestroyableClass();
272//        FunctorPtr functor = createFunctor(&DestroyableClass::method0, object);
273//        functor->setSafeMode(true);
274//        FunctorPtr clone = functor->clone();
275//
276//        EXPECT_EQ(object, functor->getRawObjectPointer());
277//        EXPECT_EQ(object, clone->getRawObjectPointer());
278//        object->destroy();
279//        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
280//        EXPECT_EQ(nullptr, clone->getRawObjectPointer());
281//
282//    }
283
284    TEST_F(FunctorTest, CanEvaluateArgument)
285    {
286        FunctorPtr functor = createFunctor(&f4a);
287        MultiType value("5");
288        EXPECT_FALSE(value.isType<int>());
289        EXPECT_TRUE(value.isType<std::string>());
290        functor->evaluateArgument(0, value);
291        EXPECT_TRUE(value.isType<int>());
292        EXPECT_FALSE(value.isType<std::string>());
293    }
294
295    TEST_F(FunctorTest, CanGetAndSetFunctionPointer)
296    {
297        FunctorPtr functor = createFunctor(&f4a);
298        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
299
300        EXPECT_EQ(6, (*functor)(3).get<int>()); // 3*2 = 6
301        EXPECT_EQ(&f4a, pointer->getFunction());
302
303        pointer->setFunction(&f4b);
304
305        EXPECT_EQ(9, (*functor)(3).get<int>()); // 3*3 = 9
306        EXPECT_EQ(&f4b, pointer->getFunction());
307    }
308
309    TEST_F(FunctorTest, ReturnsValue)
310    {
311        DestroyableClass object;
312        {
313            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
314            int result = (*functor)(&object, 13);
315            EXPECT_EQ(13, result);
316        }
317        {
318            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
319            float result = (*functor)(&object, 0, 111.11f);
320            EXPECT_FLOAT_EQ(111.11f, result);
321        }
322        {
323            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
324            bool result = (*functor)(&object, 0, 0, true);
325            EXPECT_EQ(true, result);
326        }
327        {
328            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
329            std::string result = (*functor)(&object, 0, 0, false, "test");
330            EXPECT_EQ("test", result);
331        }
332        {
333            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
334            Vector3 result = (*functor)(&object, 0, 0, false, "", Vector3(3, 2, 1));
335            EXPECT_EQ(Vector3(3, 2, 1), result);
336        }
337    }
338
339
340    ///////////////////////////////////////////////////////////
341    ////////////////////// FunctorMember //////////////////////
342    ///////////////////////////////////////////////////////////
343
344    TEST_F(FunctorTest, FunctorMember_CanSetObject)
345    {
346        DestroyableClass object;
347
348        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
349        EXPECT_EQ(nullptr, functor->getObject());
350        functor->setObject(&object);
351        EXPECT_EQ(&object, functor->getObject());
352        functor->setObject(nullptr);
353        EXPECT_EQ(nullptr, functor->getObject());
354    }
355
356    TEST_F(FunctorTest, FunctorMember_CanSetObjectInConstructor)
357    {
358        DestroyableClass object;
359
360        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &object);
361        EXPECT_EQ(&object, functor->getObject());
362        functor->setObject(nullptr);
363        EXPECT_EQ(nullptr, functor->getObject());
364    }
365
366    TEST_F(FunctorTest, FunctorMember_CanSetRawObjectPointer)
367    {
368        DestroyableClass object;
369
370        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
371        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
372        functor->setRawObjectPointer(&object);
373        EXPECT_EQ(&object, functor->getRawObjectPointer());
374        functor->setRawObjectPointer(nullptr);
375        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
376    }
377
378    TEST_F(FunctorTest, FunctorMember_RawObjectPointerAndObjectAreEqual)
379    {
380        DestroyableClass object1;
381        DestroyableClass object2;
382
383        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
384        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
385        EXPECT_EQ(nullptr, functor->getObject());
386        functor->setObject(&object1);
387        EXPECT_EQ(&object1, functor->getRawObjectPointer());
388        EXPECT_EQ(&object1, functor->getObject());
389        functor->setObject(&object2);
390        EXPECT_EQ(&object2, functor->getRawObjectPointer());
391        EXPECT_EQ(&object2, functor->getObject());
392    }
393
394    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_SetObjectThenActivateSafeMode)
395    {
396        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
397        {
398            DestroyableClass object;
399            functor->setObject(&object);
400            functor->setSafeMode(true);
401            EXPECT_EQ(&object, functor->getObject());
402        }
403        EXPECT_EQ(nullptr, functor->getObject());
404    }
405
406    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_ActivateSafeModeThenSetObject)
407    {
408        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
409        {
410            DestroyableClass object;
411            functor->setSafeMode(true);
412            functor->setObject(&object);
413            EXPECT_EQ(&object, functor->getObject());
414        }
415        EXPECT_EQ(nullptr, functor->getObject());
416    }
417
418    TEST_F(FunctorTest, FunctorMember_SafeModeCanBeDisabledAfterObjectWasSet)
419    {
420        DestroyableClass* ptr;
421        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
422        {
423            DestroyableClass object;
424            functor->setSafeMode(true);
425            functor->setObject(&object);
426            functor->setSafeMode(false);
427            ptr = &object; // remember the pointer
428            EXPECT_EQ(ptr, functor->getObject());
429        }
430        EXPECT_EQ(ptr, functor->getObject());
431    }
432
433    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_CanChangeObject)
434    {
435        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
436        DestroyableClass* object1 = new DestroyableClass();
437        DestroyableClass* object2 = new DestroyableClass();
438        functor->setSafeMode(true);
439
440        functor->setObject(object1);
441        EXPECT_EQ(object1, functor->getObject());
442        functor->setObject(object2);
443        EXPECT_EQ(object2, functor->getObject());
444        object1->destroy();
445        EXPECT_EQ(object2, functor->getObject());
446        object2->destroy();
447        EXPECT_EQ(nullptr, functor->getObject());
448    }
449
450    TEST_F(FunctorTest, FunctorMember_CanDestroyFunctorWhenObjectInSafeModeStillExists)
451    {
452        DestroyableClass object;
453        {
454            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
455            functor->setSafeMode(true);
456            functor->setObject(&object);
457            EXPECT_EQ(&object, functor->getObject());
458        } // functor is destroyed here
459    }
460
461    TEST_F(FunctorTest, FunctorMember_SafeModeDoesntDoAnythingWithObjectsNotInheritedFromDestroyable)
462    {
463        NonDestroyableClass* ptr;
464        FunctorMemberPtr<NonDestroyableClass> functor = createFunctor(&NonDestroyableClass::method);
465        {
466            NonDestroyableClass object;
467            functor->setSafeMode(true);
468            functor->setObject(&object);
469            ptr = &object; // remember the pointer
470            EXPECT_EQ(ptr, functor->getObject());
471        }
472        EXPECT_EQ(ptr, functor->getObject()); // pointer is still set because safe mode doesn't work on NonDestroyableClass
473    }
474
475    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInCall)
476    {
477        MockDestroyableClass mock;
478        {
479            EXPECT_CALL(mock, method0());
480            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
481            (*functor)(&mock);
482        }
483        {
484            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
485            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
486            (*functor)(&mock, 13);
487        }
488        {
489            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
490            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
491            (*functor)(&mock, 13, 111.11f);
492        }
493        {
494            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
495            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
496            (*functor)(&mock, 13, 111.11f, true);
497        }
498        {
499            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
500            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
501            (*functor)(&mock, 13, 111.11f, true, "test");
502        }
503        {
504            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
505            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
506            (*functor)(&mock, 13, 111.11f, true, "test", Vector3(3, 2, 1));
507        }
508    }
509
510    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInConstructor)
511    {
512        MockDestroyableClass mock;
513        {
514            EXPECT_CALL(mock, method0());
515            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &mock);
516            (*functor)();
517        }
518        {
519            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
520            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1, &mock);
521            (*functor)(13);
522        }
523        {
524            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
525            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2, &mock);
526            (*functor)(13, 111.11f);
527        }
528        {
529            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
530            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3, &mock);
531            (*functor)(13, 111.11f, true);
532        }
533        {
534            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
535            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4, &mock);
536            (*functor)(13, 111.11f, true, "test");
537        }
538        {
539            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
540            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5, &mock);
541            (*functor)(13, 111.11f, true, "test", Vector3(3, 2, 1));
542        }
543    }
544
545    TEST_F(FunctorTest, FunctorMember_ReturnsZeroIfCalledWithoutObject)
546    {
547        DestroyableClass object;
548        {
549            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
550            int resultWithObject = (*functor)(&object, 13);
551            int resultWithoutObject = (*functor)(13);
552            EXPECT_EQ(13, resultWithObject);
553            EXPECT_EQ(0, resultWithoutObject);
554        }
555    }
556
557
558    ///////////////////////////////////////////////////////////
559    ////////////////////// FunctorStatic //////////////////////
560    ///////////////////////////////////////////////////////////
561
562    TEST_F(FunctorTest, FunctorStatic_CanCall)
563    {
564        MockDestroyableClass mock;
565        DestroyableClass::staticinstance = &mock;
566
567        {
568            EXPECT_CALL(mock, method0());
569            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
570            (*functor)();
571        }
572        {
573            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
574            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod1);
575            (*functor)(13);
576        }
577        {
578            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
579            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod2);
580            (*functor)(13, 111.11f);
581        }
582        {
583            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
584            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod3);
585            (*functor)(13, 111.11f, true);
586        }
587        {
588            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
589            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod4);
590            (*functor)(13, 111.11f, true, "test");
591        }
592        {
593            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
594            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod5);
595            (*functor)(13, 111.11f, true, "test", Vector3(3, 2, 1));
596        }
597    }
598
599    TEST_F(FunctorTest, FunctorStatic_CanCallWithObject)
600    {
601        MockDestroyableClass mock;
602        DestroyableClass::staticinstance = &mock;
603
604        {
605            EXPECT_CALL(mock, method0());
606            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
607            (*functor)(&mock); // object is ignored
608        }
609    }
610
611    TEST_F(FunctorTest, FunctorStatic_CanCallWithNull)
612    {
613        MockDestroyableClass mock;
614        DestroyableClass::staticinstance = &mock;
615
616        {
617            EXPECT_CALL(mock, method0());
618            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
619            (*functor)(nullptr); // pointer is ignored
620        }
621    }
622
623    TEST_F(FunctorTest, FunctorStatic_RawObjectPointerIsAlwaysNull)
624    {
625        DestroyableClass object;
626
627        FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
628        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
629        functor->setRawObjectPointer(&object);
630        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
631        functor->setRawObjectPointer(nullptr);
632        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
633    }
634
635    ////////////////////////////// Various tests //////////////////////////////
636
637    TEST_F(FunctorTest, CreateFunctorWithVariousFunctionTypes)
638    {
639        FunctorPtr c1 = createFunctor(&f4a);
640        FunctorPtr c2 = createFunctor(&f4b);
641        FunctorPtr c3 = createFunctor([] (int arg) { return arg*4; });
642        auto lambda = [] (int arg1, int arg2) { return arg1*arg2; };
643        FunctorPtr c4 = createFunctor(lambda);
644
645        std::function<int()> bind0 = std::bind(multiply, 4, 6);
646        std::function<int(int)> bind1 = std::bind(multiply, std::placeholders::_1, 7);
647        std::function<int(int, int)> bind2 = std::bind(multiply, std::placeholders::_1, std::placeholders::_2);
648        std::function<int(int)> function = f4a;
649
650        FunctorPtr c5 = createFunctor(bind0);
651        FunctorPtr c6 = createFunctor(bind1);
652        FunctorPtr c7 = createFunctor(bind2);
653        FunctorPtr c8 = createFunctor(function);
654
655
656        EXPECT_EQ(8,  (*c1)(4).get<int>());
657        EXPECT_EQ(12, (*c2)(4).get<int>());
658        EXPECT_EQ(16, (*c3)(4).get<int>());
659        EXPECT_EQ(20, (*c4)(4, 5).get<int>());
660        EXPECT_EQ(24, (*c5)(4).get<int>());
661        EXPECT_EQ(28, (*c6)(4).get<int>());
662        EXPECT_EQ(32, (*c7)(4, 8).get<int>());
663        EXPECT_EQ(8,  (*c8)(4).get<int>());
664
665        EXPECT_EQ(1u, c1->getParamCount());
666        EXPECT_EQ(1u, c2->getParamCount());
667        EXPECT_EQ(1u, c3->getParamCount());
668        EXPECT_EQ(2u, c4->getParamCount());
669        EXPECT_EQ(0u, c5->getParamCount());
670        EXPECT_EQ(1u, c6->getParamCount());
671        EXPECT_EQ(2u, c7->getParamCount());
672        EXPECT_EQ(1u, c8->getParamCount());
673
674        EXPECT_EQ(typeid(int(*)(int)), c1->getFullIdentifier());
675        EXPECT_EQ(typeid(int(*)(int)), c2->getFullIdentifier());
676        EXPECT_EQ(typeid(int(*)(int)), c3->getFullIdentifier());
677        EXPECT_EQ(typeid(int(*)(int, int)), c4->getFullIdentifier());
678        EXPECT_EQ(typeid(int(*)()), c5->getFullIdentifier());
679        EXPECT_EQ(typeid(int(*)(int)), c6->getFullIdentifier());
680        EXPECT_EQ(typeid(int(*)(int, int)), c7->getFullIdentifier());
681        EXPECT_EQ(typeid(int(*)(int)), c8->getFullIdentifier());
682
683        EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier());
684        EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier());
685        EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier());
686        EXPECT_EQ(typeid(int(*)(int, int)), c4->getHeaderIdentifier());
687        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier());
688        EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier());
689        EXPECT_EQ(typeid(int(*)(int, int)), c7->getHeaderIdentifier());
690        EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier());
691
692        EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier(1));
693        EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier(1));
694        EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier(1));
695        EXPECT_EQ(typeid(int(*)(int)), c4->getHeaderIdentifier(1));
696        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(1));
697        EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier(1));
698        EXPECT_EQ(typeid(int(*)(int)), c7->getHeaderIdentifier(1));
699        EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier(1));
700
701        EXPECT_EQ(typeid(int(*)()), c1->getHeaderIdentifier(0));
702        EXPECT_EQ(typeid(int(*)()), c2->getHeaderIdentifier(0));
703        EXPECT_EQ(typeid(int(*)()), c3->getHeaderIdentifier(0));
704        EXPECT_EQ(typeid(int(*)()), c4->getHeaderIdentifier(0));
705        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(0));
706        EXPECT_EQ(typeid(int(*)()), c6->getHeaderIdentifier(0));
707        EXPECT_EQ(typeid(int(*)()), c7->getHeaderIdentifier(0));
708        EXPECT_EQ(typeid(int(*)()), c8->getHeaderIdentifier(0));
709    }
710
711    TEST_F(FunctorTest, CanCallFunctorWithLambdaWichIsAlreadyOutOfScope)
712    {
713        int var1 = 1;
714        FunctorPtr fp1a = createFunctor([&var1] () { return var1++; });
715        FunctorPtr fp1b = createFunctor([&var1] () { return var1; });
716        FunctorPtr fp2;
717        FunctorPtr fp3;
718
719        {
720            int var2 = 2;
721            fp2 = createFunctor([var2] () { return var2; });
722        }
723        {
724            int var3 = 3;
725            fp3 = createFunctor([var3] () { return var3; });
726        }
727
728        EXPECT_EQ(1, var1);
729        EXPECT_EQ(1, (*fp1a)().get<int>());
730        EXPECT_EQ(2, var1);
731        EXPECT_EQ(2, (*fp1b)().get<int>());
732
733        EXPECT_EQ(2, (*fp2)().get<int>());
734        EXPECT_EQ(3, (*fp3)().get<int>());
735    }
736
737    TEST_F(FunctorTest, canCompareHeaderIdentifiers)
738    {
739        FunctorPtr fp1 = createFunctor(&f1);
740        FunctorPtr fp2 = createFunctor(&f2);
741        FunctorPtr fp3 = createFunctor(&f3);
742        ASSERT_STREQ(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(1).name());
743        ASSERT_STREQ(fp1->getHeaderIdentifier(2).name(), fp2->getHeaderIdentifier(2).name());
744        ASSERT_STRNE(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(2).name());
745        ASSERT_STRNE(fp1->getHeaderIdentifier(10).name(), fp2->getHeaderIdentifier(10).name());
746        ASSERT_STRNE(fp2->getHeaderIdentifier(2).name(), fp3->getHeaderIdentifier(2).name());
747        ASSERT_STRNE(fp1->getHeaderIdentifier().name(), fp2->getHeaderIdentifier().name());
748        ASSERT_STRNE(fp2->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
749    }
750
751    TEST_F(FunctorTest, canCompareTypenames)
752    {
753        FunctorPtr fp1 = createFunctor(&f1);
754        FunctorPtr fp2 = createFunctor(&f2);
755        FunctorPtr fp3 = createFunctor(&f3);
756        ASSERT_EQ(fp1->getTypenameReturnvalue(), fp2->getTypenameReturnvalue());
757        ASSERT_EQ(fp1->getTypenameParam(0), fp3->getTypenameParam(0));
758        ASSERT_EQ("void", fp1->getTypenameReturnvalue());
759        ASSERT_EQ("int", fp3->getTypenameReturnvalue());
760        ASSERT_EQ("int", fp2->getTypenameParam(0));
761        ASSERT_EQ("double", fp3->getTypenameParam(2));
762        ASSERT_EQ("", fp3->getTypenameParam(6));
763    }
764
765    TEST_F(FunctorTest, testGetParamCountAndHasReturnValue)
766    {
767        FunctorPtr fp1 = createFunctor(&f1);
768        FunctorPtr fp2 = createFunctor(&f2);
769        FunctorPtr fp3 = createFunctor(&f3);
770        ASSERT_EQ(3u, fp2->getParamCount());
771        ASSERT_NE(fp1->getParamCount(), fp3->getParamCount());
772        ASSERT_FALSE(fp2->hasReturnvalue());
773        ASSERT_TRUE(fp3->hasReturnvalue());
774    }
775
776    TEST_F(FunctorTest, canEvaluateArgument)
777    {
778        FunctorPtr fp1 = createFunctor(&f1);
779        MultiType mttype = "2";
780        fp1->evaluateArgument(0, mttype);
781        ASSERT_TRUE(mttype.isType<int>());
782        ASSERT_EQ(2, mttype.get<int>());
783        fp1->evaluateArgument(1, mttype);
784        ASSERT_TRUE(mttype.isType<double>());
785        ASSERT_EQ(2.0, mttype.get<double>());
786        mttype.reset();
787        fp1->evaluateArgument(5, mttype);
788        ASSERT_TRUE(mttype.null());
789    }
790
791    TEST_F(FunctorTest, canUseCallables)
792    {
793        int a = 0;
794        FunctorPtr fp1 = createFunctor(CallableStruct{});
795        FunctorPtr fp2 = createFunctor([](bool val) { return val; });
796        FunctorPtr fp3 = createFunctor([&a]() {return a++; });
797        FunctorPtr fp4 = createFunctor([a]() {return a; });
798        ASSERT_EQ(1, (*fp1)().get<int>());
799        ASSERT_EQ(true, (*fp2)(true).get<bool>());
800        ASSERT_EQ(0, (*fp3)().get<int>());
801        ASSERT_EQ(1, a);
802        ASSERT_EQ(0, (*fp4)().get<int>());
803        ASSERT_STREQ(fp1->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
804    }
805
806    TEST_F(FunctorTest, SafeModeWorks)
807    {
808        DestroyableClass* testclass = new DestroyableClass();
809        DestroyableClass* testclass2 = new DestroyableClass();
810        FunctorPtr fp1 = createFunctor(&DestroyableClass::method0, testclass);
811        fp1->setSafeMode(true);
812        FunctorPtr fp2 = createFunctor(&DestroyableClass::method0, testclass);
813        fp2->setSafeMode(true);
814        FunctorPtr fp3 = createFunctor(&DestroyableClass::method0, testclass);
815        fp2->setRawObjectPointer(testclass2);
816
817        ASSERT_NE(nullptr, fp1->getRawObjectPointer());
818        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
819        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
820        testclass->destroy();
821        ASSERT_EQ(nullptr, fp1->getRawObjectPointer());
822        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
823        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
824
825        fp3->setRawObjectPointer(testclass2);
826        fp3->setSafeMode(true);
827        fp2->setSafeMode(false);
828        testclass2->destroy();
829        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
830        ASSERT_EQ(nullptr, fp3->getRawObjectPointer());
831    }
832}
Note: See TracBrowser for help on using the repository browser.