Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/test/core/command/FunctorTest.cc @ 10983

Last change on this file since 10983 was 10983, checked in by landauf, 8 years ago

added a bunch of unit tests for Functor

  • Property svn:eol-style set to native
File size: 33.9 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
74        struct CallableStruct
75        {
76            public:
77                int operator()()
78                {
79                    return 1;
80                }
81        };
82    }
83
84
85    ///////////////////////////////////////////////////////////////
86    ////////////////////// Functor (general) //////////////////////
87    ///////////////////////////////////////////////////////////////
88
89    TEST_F(FunctorTest, HasCorrectType)
90    {
91        FunctorMemberPtr<DestroyableClass> functor1 = createFunctor(&DestroyableClass::method0);
92        FunctorStaticPtr functor2 = createFunctor(&DestroyableClass::staticmethod0);
93        EXPECT_EQ(Functor::Type::Member, functor1->getType());
94        EXPECT_EQ(Functor::Type::Static, functor2->getType());
95    }
96
97    TEST_F(FunctorTest, ReturnsCorrectParamCount)
98    {
99        EXPECT_EQ(0, createFunctor(&DestroyableClass::method0)->getParamCount());
100        EXPECT_EQ(1, createFunctor(&DestroyableClass::method1)->getParamCount());
101        EXPECT_EQ(2, createFunctor(&DestroyableClass::method2)->getParamCount());
102        EXPECT_EQ(3, createFunctor(&DestroyableClass::method3)->getParamCount());
103        EXPECT_EQ(4, createFunctor(&DestroyableClass::method4)->getParamCount());
104        EXPECT_EQ(5, createFunctor(&DestroyableClass::method5)->getParamCount());
105    }
106
107    TEST_F(FunctorTest, HasReturnValue)
108    {
109        EXPECT_FALSE(createFunctor(&DestroyableClass::method0)->hasReturnvalue());
110        EXPECT_TRUE(createFunctor(&DestroyableClass::method1)->hasReturnvalue());
111        EXPECT_TRUE(createFunctor(&DestroyableClass::method2)->hasReturnvalue());
112        EXPECT_TRUE(createFunctor(&DestroyableClass::method3)->hasReturnvalue());
113        EXPECT_TRUE(createFunctor(&DestroyableClass::method4)->hasReturnvalue());
114        EXPECT_TRUE(createFunctor(&DestroyableClass::method5)->hasReturnvalue());
115    }
116
117    TEST_F(FunctorTest, GetTypenameParam)
118    {
119        FunctorPtr functor = createFunctor(&DestroyableClass::method5);
120        EXPECT_EQ("int",     functor->getTypenameParam(0));
121        EXPECT_EQ("float",   functor->getTypenameParam(1));
122        EXPECT_EQ("bool",    functor->getTypenameParam(2));
123        EXPECT_EQ("string",  functor->getTypenameParam(3));
124        EXPECT_EQ("Vector3", functor->getTypenameParam(4));
125        EXPECT_EQ("",        functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
126    }
127
128    TEST_F(FunctorTest, TypenameParamIsAlwaysVoidForFunctionWithoutParams)
129    {
130        FunctorPtr functor = createFunctor(&DestroyableClass::method0);
131        EXPECT_EQ("void", functor->getTypenameParam(0));
132        EXPECT_EQ("void", functor->getTypenameParam(1));
133        EXPECT_EQ("void", functor->getTypenameParam(2));
134        EXPECT_EQ("void", functor->getTypenameParam(3));
135        EXPECT_EQ("void", functor->getTypenameParam(4));
136        EXPECT_EQ("",     functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
137    }
138
139    TEST_F(FunctorTest, GetTypenameReturnvalue)
140    {
141        EXPECT_EQ("void",    createFunctor(&DestroyableClass::method0)->getTypenameReturnvalue());
142        EXPECT_EQ("int",     createFunctor(&DestroyableClass::method1)->getTypenameReturnvalue());
143        EXPECT_EQ("float",   createFunctor(&DestroyableClass::method2)->getTypenameReturnvalue());
144        EXPECT_EQ("bool",    createFunctor(&DestroyableClass::method3)->getTypenameReturnvalue());
145        EXPECT_EQ("string",  createFunctor(&DestroyableClass::method4)->getTypenameReturnvalue());
146        EXPECT_EQ("Vector3", createFunctor(&DestroyableClass::method5)->getTypenameReturnvalue());
147    }
148
149    TEST_F(FunctorTest, GetFullIdentifier)
150    {
151        // static
152        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getFullIdentifier());
153        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getFullIdentifier());
154        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getFullIdentifier());
155        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getFullIdentifier());
156        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getFullIdentifier());
157        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getFullIdentifier());
158
159        // member
160        EXPECT_EQ(typeid(       void(DestroyableClass::*)()),                                                     createFunctor(&DestroyableClass::method0)->getFullIdentifier());
161        EXPECT_EQ(typeid(        int(DestroyableClass::*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getFullIdentifier());
162        EXPECT_EQ(typeid(      float(DestroyableClass::*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getFullIdentifier());
163        EXPECT_EQ(typeid(       bool(DestroyableClass::*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getFullIdentifier());
164        EXPECT_EQ(typeid(std::string(DestroyableClass::*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getFullIdentifier());
165        EXPECT_EQ(typeid(    Vector3(DestroyableClass::*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getFullIdentifier());
166    }
167
168    TEST_F(FunctorTest, GetHeaderIdentifier)
169    {
170        // static
171        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier());
172        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier());
173        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier());
174        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier());
175        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier());
176        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier());
177
178        // member
179        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::method0)->getHeaderIdentifier());
180        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getHeaderIdentifier());
181        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getHeaderIdentifier());
182        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getHeaderIdentifier());
183        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getHeaderIdentifier());
184        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier());
185    }
186
187    TEST_F(FunctorTest, GetHeaderIdentifierFor2Params)
188    {
189        // static
190        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier(2));
191        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier(2));
192        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier(2));
193        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier(2));
194        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier(2));
195        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier(2));
196
197        // member
198        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::method0)->getHeaderIdentifier(2));
199        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::method1)->getHeaderIdentifier(2));
200        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::method2)->getHeaderIdentifier(2));
201        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::method3)->getHeaderIdentifier(2));
202        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::method4)->getHeaderIdentifier(2));
203        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier(2));
204    }
205
206    TEST_F(FunctorTest, GetHeaderIdentifierForNParams)
207    {
208        // static
209        FunctorStaticPtr functorStatic = createFunctor(&DestroyableClass::staticmethod5);
210        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorStatic->getHeaderIdentifier(0));
211        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorStatic->getHeaderIdentifier(1));
212        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorStatic->getHeaderIdentifier(2));
213        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorStatic->getHeaderIdentifier(3));
214        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorStatic->getHeaderIdentifier(4));
215        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(5));
216        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(6));
217
218        // member
219        FunctorMemberPtr<DestroyableClass> functorMember = createFunctor(&DestroyableClass::method5);
220        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorMember->getHeaderIdentifier(0));
221        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorMember->getHeaderIdentifier(1));
222        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorMember->getHeaderIdentifier(2));
223        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorMember->getHeaderIdentifier(3));
224        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorMember->getHeaderIdentifier(4));
225        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(5));
226        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(6));
227    }
228
229    TEST_F(FunctorTest, CanClone)
230    {
231        FunctorPtr functor = createFunctor(&f4a);
232        FunctorPtr clone = functor->clone();
233        EXPECT_NE(nullptr, clone.get());
234    }
235
236    TEST_F(FunctorTest, ClonedFunctorCanBeCalled)
237    {
238        FunctorPtr functor = createFunctor(&f4a);
239        FunctorPtr clone = functor->clone();
240
241        EXPECT_EQ(8, (*functor)(4).get<int>());
242        EXPECT_EQ(8, (*clone)(4).get<int>());
243    }
244
245    TEST_F(FunctorTest, ClonedFunctorKeepsFunction)
246    {
247        FunctorPtr functor = createFunctor(&f4a);
248        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
249
250        FunctorPtr clone = functor->clone();
251        FunctorPointer<int(*)(int)>* clonePointer = static_cast<FunctorPointer<int(*)(int)>*>(clone.get());
252
253        EXPECT_EQ(&f4a, pointer->getFunction());
254        EXPECT_EQ(&f4a, clonePointer->getFunction());
255    }
256
257    TEST_F(FunctorTest, ClonedFunctorKeepsObject)
258    {
259        DestroyableClass object;
260        FunctorPtr functor = createFunctor(&DestroyableClass::method0, &object);
261        FunctorPtr clone = functor->clone();
262
263        EXPECT_EQ(&object, functor->getRawObjectPointer());
264        EXPECT_EQ(&object, clone->getRawObjectPointer());
265    }
266
267    // TODO: test fails... fix or delete clone()
268//    TEST_F(FunctorTest, ClonedFunctorKeepsSafeMode)
269//    {
270//        DestroyableClass* object = new DestroyableClass();
271//        FunctorPtr functor = createFunctor(&DestroyableClass::method0, object);
272//        functor->setSafeMode(true);
273//        FunctorPtr clone = functor->clone();
274//
275//        EXPECT_EQ(object, functor->getRawObjectPointer());
276//        EXPECT_EQ(object, clone->getRawObjectPointer());
277//        object->destroy();
278//        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
279//        EXPECT_EQ(nullptr, clone->getRawObjectPointer());
280//
281//    }
282
283    TEST_F(FunctorTest, CanEvaluateArgument)
284    {
285        FunctorPtr functor = createFunctor(&f4a);
286        MultiType value("5");
287        EXPECT_FALSE(value.isType<int>());
288        EXPECT_TRUE(value.isType<std::string>());
289        functor->evaluateArgument(0, value);
290        EXPECT_TRUE(value.isType<int>());
291        EXPECT_FALSE(value.isType<std::string>());
292    }
293
294    TEST_F(FunctorTest, CanGetAndSetFunctionPointer)
295    {
296        FunctorPtr functor = createFunctor(&f4a);
297        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
298
299        EXPECT_EQ(6, (*functor)(3).get<int>()); // 3*2 = 6
300        EXPECT_EQ(&f4a, pointer->getFunction());
301
302        pointer->setFunction(&f4b);
303
304        EXPECT_EQ(9, (*functor)(3).get<int>()); // 3*3 = 9
305        EXPECT_EQ(&f4b, pointer->getFunction());
306    }
307
308    TEST_F(FunctorTest, ReturnsValue)
309    {
310        DestroyableClass object;
311        {
312            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
313            int result = (*functor)(&object, 13);
314            EXPECT_EQ(13, result);
315        }
316        {
317            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
318            float result = (*functor)(&object, 0, 111.11);
319            EXPECT_FLOAT_EQ(111.11, result);
320        }
321        {
322            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
323            bool result = (*functor)(&object, 0, 0, true);
324            EXPECT_EQ(true, result);
325        }
326        {
327            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
328            std::string result = (*functor)(&object, 0, 0, false, "test");
329            EXPECT_EQ("test", result);
330        }
331        {
332            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
333            Vector3 result = (*functor)(&object, 0, 0, false, "", Vector3(3, 2, 1));
334            EXPECT_EQ(Vector3(3, 2, 1), result);
335        }
336    }
337
338
339    ///////////////////////////////////////////////////////////
340    ////////////////////// FunctorMember //////////////////////
341    ///////////////////////////////////////////////////////////
342
343    TEST_F(FunctorTest, FunctorMember_CanSetObject)
344    {
345        DestroyableClass object;
346
347        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
348        EXPECT_EQ(nullptr, functor->getObject());
349        functor->setObject(&object);
350        EXPECT_EQ(&object, functor->getObject());
351        functor->setObject(nullptr);
352        EXPECT_EQ(nullptr, functor->getObject());
353    }
354
355    TEST_F(FunctorTest, FunctorMember_CanSetObjectInConstructor)
356    {
357        DestroyableClass object;
358
359        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &object);
360        EXPECT_EQ(&object, functor->getObject());
361        functor->setObject(nullptr);
362        EXPECT_EQ(nullptr, functor->getObject());
363    }
364
365    TEST_F(FunctorTest, FunctorMember_CanSetRawObjectPointer)
366    {
367        DestroyableClass object;
368
369        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
370        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
371        functor->setRawObjectPointer(&object);
372        EXPECT_EQ(&object, functor->getRawObjectPointer());
373        functor->setRawObjectPointer(nullptr);
374        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
375    }
376
377    TEST_F(FunctorTest, FunctorMember_RawObjectPointerAndObjectAreEqual)
378    {
379        DestroyableClass object1;
380        DestroyableClass object2;
381
382        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
383        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
384        EXPECT_EQ(nullptr, functor->getObject());
385        functor->setObject(&object1);
386        EXPECT_EQ(&object1, functor->getRawObjectPointer());
387        EXPECT_EQ(&object1, functor->getObject());
388        functor->setObject(&object2);
389        EXPECT_EQ(&object2, functor->getRawObjectPointer());
390        EXPECT_EQ(&object2, functor->getObject());
391    }
392
393    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_SetObjectThenActivateSafeMode)
394    {
395        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
396        {
397            DestroyableClass object;
398            functor->setObject(&object);
399            functor->setSafeMode(true);
400            EXPECT_EQ(&object, functor->getObject());
401        }
402        EXPECT_EQ(nullptr, functor->getObject());
403    }
404
405    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_ActivateSafeModeThenSetObject)
406    {
407        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
408        {
409            DestroyableClass object;
410            functor->setSafeMode(true);
411            functor->setObject(&object);
412            EXPECT_EQ(&object, functor->getObject());
413        }
414        EXPECT_EQ(nullptr, functor->getObject());
415    }
416
417    TEST_F(FunctorTest, FunctorMember_SafeModeCanBeDisabledAfterObjectWasSet)
418    {
419        DestroyableClass* ptr;
420        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
421        {
422            DestroyableClass object;
423            functor->setSafeMode(true);
424            functor->setObject(&object);
425            functor->setSafeMode(false);
426            ptr = &object; // remember the pointer
427            EXPECT_EQ(ptr, functor->getObject());
428        }
429        EXPECT_EQ(ptr, functor->getObject());
430    }
431
432    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_CanChangeObject)
433    {
434        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
435        DestroyableClass* object1 = new DestroyableClass();
436        DestroyableClass* object2 = new DestroyableClass();
437        functor->setSafeMode(true);
438
439        functor->setObject(object1);
440        EXPECT_EQ(object1, functor->getObject());
441        functor->setObject(object2);
442        EXPECT_EQ(object2, functor->getObject());
443        object1->destroy();
444        EXPECT_EQ(object2, functor->getObject());
445        object2->destroy();
446        EXPECT_EQ(nullptr, functor->getObject());
447    }
448
449    TEST_F(FunctorTest, FunctorMember_CanDestroyFunctorWhenObjectInSafeModeStillExists)
450    {
451        DestroyableClass object;
452        {
453            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
454            functor->setSafeMode(true);
455            functor->setObject(&object);
456            EXPECT_EQ(&object, functor->getObject());
457        } // functor is destroyed here
458    }
459
460    TEST_F(FunctorTest, FunctorMember_SafeModeDoesntDoAnythingWithObjectsNotInheritedFromDestroyable)
461    {
462        NonDestroyableClass* ptr;
463        FunctorMemberPtr<NonDestroyableClass> functor = createFunctor(&NonDestroyableClass::method);
464        {
465            NonDestroyableClass object;
466            functor->setSafeMode(true);
467            functor->setObject(&object);
468            ptr = &object; // remember the pointer
469            EXPECT_EQ(ptr, functor->getObject());
470        }
471        EXPECT_EQ(ptr, functor->getObject()); // pointer is still set because safe mode doesn't work on NonDestroyableClass
472    }
473
474    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInCall)
475    {
476        MockDestroyableClass mock;
477        {
478            EXPECT_CALL(mock, method0());
479            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
480            (*functor)(&mock);
481        }
482        {
483            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
484            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
485            (*functor)(&mock, 13);
486        }
487        {
488            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
489            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
490            (*functor)(&mock, 13, 111.11);
491        }
492        {
493            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
494            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
495            (*functor)(&mock, 13, 111.11, true);
496        }
497        {
498            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
499            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
500            (*functor)(&mock, 13, 111.11, true, "test");
501        }
502        {
503            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
504            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
505            (*functor)(&mock, 13, 111.11, true, "test", Vector3(3, 2, 1));
506        }
507    }
508
509    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInConstructor)
510    {
511        MockDestroyableClass mock;
512        {
513            EXPECT_CALL(mock, method0());
514            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &mock);
515            (*functor)();
516        }
517        {
518            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
519            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1, &mock);
520            (*functor)(13);
521        }
522        {
523            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
524            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2, &mock);
525            (*functor)(13, 111.11);
526        }
527        {
528            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
529            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3, &mock);
530            (*functor)(13, 111.11, true);
531        }
532        {
533            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
534            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4, &mock);
535            (*functor)(13, 111.11, true, "test");
536        }
537        {
538            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
539            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5, &mock);
540            (*functor)(13, 111.11, true, "test", Vector3(3, 2, 1));
541        }
542    }
543
544    TEST_F(FunctorTest, FunctorMember_ReturnsZeroIfCalledWithoutObject)
545    {
546        DestroyableClass object;
547        {
548            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
549            int resultWithObject = (*functor)(&object, 13);
550            int resultWithoutObject = (*functor)(13);
551            EXPECT_EQ(13, resultWithObject);
552            EXPECT_EQ(0, resultWithoutObject);
553        }
554    }
555
556
557    ///////////////////////////////////////////////////////////
558    ////////////////////// FunctorStatic //////////////////////
559    ///////////////////////////////////////////////////////////
560
561    TEST_F(FunctorTest, FunctorStatic_CanCall)
562    {
563        MockDestroyableClass mock;
564        DestroyableClass::staticinstance = &mock;
565
566        {
567            EXPECT_CALL(mock, method0());
568            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
569            (*functor)();
570        }
571        {
572            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
573            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod1);
574            (*functor)(13);
575        }
576        {
577            EXPECT_CALL(mock, method2(13, 111.11)).WillOnce(::testing::Return(0.0));
578            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod2);
579            (*functor)(13, 111.11);
580        }
581        {
582            EXPECT_CALL(mock, method3(13, 111.11, true)).WillOnce(::testing::Return(false));
583            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod3);
584            (*functor)(13, 111.11, true);
585        }
586        {
587            EXPECT_CALL(mock, method4(13, 111.11, true, "test")).WillOnce(::testing::Return(""));
588            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod4);
589            (*functor)(13, 111.11, true, "test");
590        }
591        {
592            EXPECT_CALL(mock, method5(13, 111.11, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
593            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod5);
594            (*functor)(13, 111.11, true, "test", Vector3(3, 2, 1));
595        }
596    }
597
598    TEST_F(FunctorTest, FunctorStatic_CanCallWithObject)
599    {
600        MockDestroyableClass mock;
601        DestroyableClass::staticinstance = &mock;
602
603        {
604            EXPECT_CALL(mock, method0());
605            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
606            (*functor)(&mock); // object is ignored
607        }
608    }
609
610    TEST_F(FunctorTest, FunctorStatic_CanCallWithNull)
611    {
612        MockDestroyableClass mock;
613        DestroyableClass::staticinstance = &mock;
614
615        {
616            EXPECT_CALL(mock, method0());
617            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
618            (*functor)(nullptr); // pointer is ignored
619        }
620    }
621
622    TEST_F(FunctorTest, FunctorStatic_RawObjectPointerIsAlwaysNull)
623    {
624        DestroyableClass object;
625
626        FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
627        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
628        functor->setRawObjectPointer(&object);
629        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
630        functor->setRawObjectPointer(nullptr);
631        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
632    }
633
634    ////////////////////////////// Various tests //////////////////////////////
635
636    TEST_F(FunctorTest, canCompareHeaderIdentifiers)
637    {
638        FunctorPtr fp1 = createFunctor(&f1);
639        FunctorPtr fp2 = createFunctor(&f2);
640        FunctorPtr fp3 = createFunctor(&f3);
641        ASSERT_STREQ(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(1).name());
642        ASSERT_STREQ(fp1->getHeaderIdentifier(2).name(), fp2->getHeaderIdentifier(2).name());
643        ASSERT_STRNE(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(2).name());
644        ASSERT_STRNE(fp1->getHeaderIdentifier(10).name(), fp2->getHeaderIdentifier(10).name());
645        ASSERT_STRNE(fp2->getHeaderIdentifier(2).name(), fp3->getHeaderIdentifier(2).name());
646        ASSERT_STRNE(fp1->getHeaderIdentifier().name(), fp2->getHeaderIdentifier().name());
647        ASSERT_STRNE(fp2->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
648    }
649
650    TEST_F(FunctorTest, canCompareTypenames)
651    {
652        FunctorPtr fp1 = createFunctor(&f1);
653        FunctorPtr fp2 = createFunctor(&f2);
654        FunctorPtr fp3 = createFunctor(&f3);
655        ASSERT_EQ(fp1->getTypenameReturnvalue(), fp2->getTypenameReturnvalue());
656        ASSERT_EQ(fp1->getTypenameParam(0), fp3->getTypenameParam(0));
657        ASSERT_EQ("void", fp1->getTypenameReturnvalue());
658        ASSERT_EQ("int", fp3->getTypenameReturnvalue());
659        ASSERT_EQ("int", fp2->getTypenameParam(0));
660        ASSERT_EQ("double", fp3->getTypenameParam(2));
661        ASSERT_EQ("", fp3->getTypenameParam(6));
662    }
663
664    TEST_F(FunctorTest, testGetParamCountAndHasReturnValue)
665    {
666        FunctorPtr fp1 = createFunctor(&f1);
667        FunctorPtr fp2 = createFunctor(&f2);
668        FunctorPtr fp3 = createFunctor(&f3);
669        ASSERT_EQ(3, fp2->getParamCount());
670        ASSERT_NE(fp1->getParamCount(), fp3->getParamCount());
671        ASSERT_FALSE(fp2->hasReturnvalue());
672        ASSERT_TRUE(fp3->hasReturnvalue());
673    }
674
675    TEST_F(FunctorTest, canEvaluateArgument)
676    {
677        FunctorPtr fp1 = createFunctor(&f1);
678        MultiType mttype = "2";
679        fp1->evaluateArgument(0, mttype);
680        ASSERT_TRUE(mttype.isType<int>());
681        ASSERT_EQ(2, mttype.get<int>());
682        fp1->evaluateArgument(1, mttype);
683        ASSERT_TRUE(mttype.isType<double>());
684        ASSERT_EQ(2.0, mttype.get<double>());
685        mttype.reset();
686        fp1->evaluateArgument(5, mttype);
687        ASSERT_TRUE(mttype.null());
688    }
689
690    TEST_F(FunctorTest, canUseCallables)
691    {
692        int a = 0;
693        FunctorPtr fp1 = createFunctor(CallableStruct{});
694        FunctorPtr fp2 = createFunctor([](bool val) { return val; });
695        FunctorPtr fp3 = createFunctor([&a]() {return a++; });
696        FunctorPtr fp4 = createFunctor([a]() {return a; });
697        ASSERT_EQ(1, (*fp1)().get<int>());
698        ASSERT_EQ(true, (*fp2)(true).get<bool>());
699        ASSERT_EQ(0, (*fp3)().get<int>());
700        ASSERT_EQ(1, a);
701        ASSERT_EQ(0, (*fp4)().get<int>());
702        ASSERT_STREQ(fp1->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
703    }
704
705    TEST_F(FunctorTest, SafeModeWorks)
706    {
707        DestroyableClass* testclass = new DestroyableClass();
708        DestroyableClass* testclass2 = new DestroyableClass();
709        FunctorPtr fp1 = createFunctor(&DestroyableClass::method0, testclass);
710        fp1->setSafeMode(true);
711        FunctorPtr fp2 = createFunctor(&DestroyableClass::method0, testclass);
712        fp2->setSafeMode(true);
713        FunctorPtr fp3 = createFunctor(&DestroyableClass::method0, testclass);
714        fp2->setRawObjectPointer(testclass2);
715
716        ASSERT_NE(nullptr, fp1->getRawObjectPointer());
717        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
718        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
719        testclass->destroy();
720        ASSERT_EQ(nullptr, fp1->getRawObjectPointer());
721        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
722        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
723
724        fp3->setRawObjectPointer(testclass2);
725        fp3->setSafeMode(true);
726        fp2->setSafeMode(false);
727        testclass2->destroy();
728        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
729        ASSERT_EQ(nullptr, fp3->getRawObjectPointer());
730    }
731}
Note: See TracBrowser for help on using the repository browser.