1 #include "gtest/gtest.h"
2 
3 #include <functional>
4 #include <memory>
5 
6 #include <QCoreApplication>
7 #include <QPointer>
8 #include <QSharedPointer>
9 #include <QSignalSpy>
10 
11 #include "config.h"
12 #include "core/closure.h"
13 #include "test_utils.h"
14 
TEST(ClosureTest,ClosureInvokesReceiver)15 TEST(ClosureTest, ClosureInvokesReceiver) {
16   TestQObject sender;
17   TestQObject receiver;
18   _detail::ClosureBase* closure = NewClosure(
19       &sender, SIGNAL(Emitted()),
20       &receiver, SLOT(Invoke()));
21   EXPECT_EQ(0, receiver.invoked());
22   sender.Emit();
23   EXPECT_EQ(1, receiver.invoked());
24 }
25 
TEST(ClosureTest,ClosureDeletesSelf)26 TEST(ClosureTest, ClosureDeletesSelf) {
27   TestQObject sender;
28   TestQObject receiver;
29   _detail::ClosureBase* closure = NewClosure(
30       &sender, SIGNAL(Emitted()),
31       &receiver, SLOT(Invoke()));
32   _detail::ObjectHelper* helper = closure->helper();
33   QSignalSpy spy(helper, SIGNAL(destroyed()));
34   EXPECT_EQ(0, receiver.invoked());
35   sender.Emit();
36   EXPECT_EQ(1, receiver.invoked());
37 
38   EXPECT_EQ(0, spy.count());
39   QEventLoop loop;
40   QObject::connect(helper, SIGNAL(destroyed()), &loop, SLOT(quit()));
41   loop.exec();
42   EXPECT_EQ(1, spy.count());
43 }
44 
TEST(ClosureTest,ClosureDoesNotCrashWithSharedPointerSender)45 TEST(ClosureTest, ClosureDoesNotCrashWithSharedPointerSender) {
46   TestQObject receiver;
47   TestQObject* sender;
48   std::unique_ptr<QSignalSpy> spy;
49   QPointer<_detail::ObjectHelper> closure;
50   {
51     QSharedPointer<TestQObject> sender_shared(new TestQObject);
52     sender = sender_shared.data();
53     closure = QPointer<_detail::ObjectHelper>(NewClosure(
54         sender_shared, SIGNAL(Emitted()),
55         &receiver, SLOT(Invoke()))->helper());
56     spy.reset(new QSignalSpy(sender, SIGNAL(destroyed())));
57   }
58   ASSERT_EQ(0, receiver.invoked());
59   sender->Emit();
60   ASSERT_EQ(1, receiver.invoked());
61 
62   ASSERT_EQ(0, spy->count());
63   QEventLoop loop;
64   QObject::connect(sender, SIGNAL(destroyed()), &loop, SLOT(quit()));
65   loop.exec();
66   ASSERT_EQ(1, spy->count());
67   EXPECT_TRUE(closure.isNull());
68 }
69 
70 namespace {
71 
Foo(bool * called,int question,int * answer)72 void Foo(bool* called, int question, int* answer) {
73   *called = true;
74   *answer = question;
75 }
76 
77 }  // namespace
78 
TEST(ClosureTest,ClosureWorksWithFunctionPointers)79 TEST(ClosureTest, ClosureWorksWithFunctionPointers) {
80   TestQObject sender;
81   bool called = false;
82   int question = 42;
83   int answer = 0;
84   NewClosure(
85       &sender, SIGNAL(Emitted()),
86       &Foo, &called, question, &answer);
87   EXPECT_FALSE(called);
88   sender.Emit();
89   EXPECT_TRUE(called);
90   EXPECT_EQ(question, answer);
91 }
92 
TEST(ClosureTest,ClosureWorksWithStandardFunctions)93 TEST(ClosureTest, ClosureWorksWithStandardFunctions) {
94   TestQObject sender;
95   bool called = false;
96   int question = 42;
97   int answer = 0;
98   std::function<void(bool*,int,int*)> callback(&Foo);
99   NewClosure(
100       &sender, SIGNAL(Emitted()),
101       callback, &called, question, &answer);
102   EXPECT_FALSE(called);
103   sender.Emit();
104   EXPECT_TRUE(called);
105   EXPECT_EQ(question, answer);
106 }
107 
108 namespace {
109 
110 class Bar {
111  public:
Bar(int a)112   explicit Bar(int a) : foo_(a) {}
Foo(int * answer)113   bool Foo(int* answer) {
114     *answer = foo_;
115     return true;
116   }
117 
118  private:
119   int foo_;
120 };
121 
122 }
123 
TEST(ClosureTest,ClosureWorksWithMemberFunctionPointers)124 TEST(ClosureTest, ClosureWorksWithMemberFunctionPointers) {
125   TestQObject sender;
126   Bar receiver(42);
127   int q = 1;
128   NewClosure(
129       &sender, SIGNAL(Emitted()),
130       &receiver, &Bar::Foo, &q);
131   EXPECT_EQ(1, q);
132   sender.Emit();
133   EXPECT_EQ(42, q);
134 }
135 
TEST(ClosureTest,ClosureCallsLambda)136 TEST(ClosureTest, ClosureCallsLambda) {
137   TestQObject sender;
138   bool called = false;
139   NewClosure(
140       &sender, SIGNAL(Emitted()),
141       [&called] () { called = true; });
142   EXPECT_FALSE(called);
143   sender.Emit();
144   EXPECT_TRUE(called);
145 }
146