1 #include <gtest/gtest.h>
2 
3 #include <pajlada/signals/signal.hpp>
4 #include <vector>
5 
6 using namespace pajlada::Signals;
7 using namespace std;
8 
9 // TODO(pajlada): Make tests that try to put connections/signals in various STL containers
10 
TEST(Signal,SingleConnect)11 TEST(Signal, SingleConnect)
12 {
13     Signal<int> incrementSignal;
14 
15     int a = 0;
16 
17     auto IncrementA = [&a](int incrementBy) {
18         a += incrementBy;  //
19     };
20 
21     EXPECT_EQ(a, 0);
22 
23     incrementSignal.invoke(1);
24 
25     EXPECT_EQ(a, 0);
26 
27     incrementSignal.connect(IncrementA);
28 
29     incrementSignal.invoke(1);
30 
31     EXPECT_EQ(a, 1);
32 
33     incrementSignal.invoke(2);
34 
35     EXPECT_EQ(a, 3);
36 }
37 
TEST(Signal,MultipleConnect)38 TEST(Signal, MultipleConnect)
39 {
40     Signal<int> incrementSignal;
41 
42     int a = 0;
43 
44     auto IncrementA = [&a](int incrementBy) {
45         a += incrementBy;  //
46     };
47 
48     EXPECT_EQ(a, 0);
49 
50     incrementSignal.invoke(1);
51 
52     EXPECT_EQ(a, 0);
53 
54     incrementSignal.connect(IncrementA);
55     incrementSignal.connect(IncrementA);
56 
57     incrementSignal.invoke(1);
58 
59     EXPECT_EQ(a, 2);
60 
61     incrementSignal.invoke(2);
62 
63     EXPECT_EQ(a, 6);
64 }
65 
TEST(Connection,IsConnected)66 TEST(Connection, IsConnected)
67 {
68     Signal<int> incrementSignal;
69     int a = 0;
70     auto IncrementA = [&a](int incrementBy) {
71         a += incrementBy;  //
72     };
73     EXPECT_EQ(a, 0);
74 
75     auto conn = incrementSignal.connect(IncrementA);
76 
77     incrementSignal.invoke(1);
78 
79     EXPECT_EQ(a, 1);
80 
81     EXPECT_TRUE(conn.isConnected());
82     conn.disconnect();
83     EXPECT_FALSE(conn.isConnected());
84     conn.disconnect();
85     EXPECT_FALSE(conn.isConnected());
86 
87     incrementSignal.invoke(1);
88 
89     EXPECT_EQ(a, 1);
90 }
91 
TEST(Connection,Blocking)92 TEST(Connection, Blocking)
93 {
94     Signal<int> incrementSignal;
95     int a = 0;
96     auto IncrementA = [&a](int incrementBy) {
97         a += incrementBy;  //
98     };
99     EXPECT_EQ(a, 0);
100 
101     auto conn = incrementSignal.connect(IncrementA);
102 
103     incrementSignal.invoke(1);
104 
105     EXPECT_EQ(a, 1);
106 
107     EXPECT_FALSE(conn.isBlocked());
108     EXPECT_TRUE(conn.block());
109     EXPECT_TRUE(conn.isBlocked());
110     EXPECT_FALSE(conn.block());
111     EXPECT_TRUE(conn.isBlocked());
112 
113     incrementSignal.invoke(1);
114 
115     EXPECT_EQ(a, 1);
116 
117     EXPECT_TRUE(conn.unblock());
118     EXPECT_FALSE(conn.isBlocked());
119     EXPECT_FALSE(conn.unblock());
120     EXPECT_FALSE(conn.isBlocked());
121 
122     incrementSignal.invoke(2);
123 
124     EXPECT_EQ(a, 3);
125 }
126 
TEST(Connection,BlockDisconnected)127 TEST(Connection, BlockDisconnected)
128 {
129     Signal<int> incrementSignal;
130     int a = 0;
131     auto IncrementA = [&a](int incrementBy) {
132         a += incrementBy;  //
133     };
134     EXPECT_EQ(a, 0);
135 
136     auto conn = incrementSignal.connect(IncrementA);
137 
138     incrementSignal.invoke(1);
139 
140     EXPECT_EQ(a, 1);
141 
142     EXPECT_TRUE(conn.isConnected());
143     conn.disconnect();
144     EXPECT_FALSE(conn.isConnected());
145 
146     incrementSignal.invoke(1);
147 
148     EXPECT_EQ(a, 1);
149 
150     EXPECT_FALSE(conn.isBlocked());
151     EXPECT_FALSE(conn.block());
152     EXPECT_FALSE(conn.isBlocked());
153     EXPECT_FALSE(conn.unblock());
154     EXPECT_FALSE(conn.isBlocked());
155 }
156 
TEST(Connection,Copying)157 TEST(Connection, Copying)
158 {
159     Signal<int> incrementSignal;
160     int a = 0;
161     auto IncrementA = [&a](int incrementBy) {
162         a += incrementBy;  //
163     };
164     EXPECT_EQ(a, 0);
165 
166     auto conn = incrementSignal.connect(IncrementA);
167 
168     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
169     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
170 
171     incrementSignal.invoke(1);
172     EXPECT_EQ(a, 1);
173 
174     // Test copying of connection
175     auto connCopy = conn;
176     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
177     EXPECT_EQ(conn.getSubscriberRefCount().count, 2);
178 
179     incrementSignal.invoke(1);
180     EXPECT_EQ(a, 2);
181 
182     EXPECT_TRUE(connCopy.disconnect());
183 
184     incrementSignal.invoke(1);
185     EXPECT_EQ(a, 3);
186 
187     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
188     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
189 
190     EXPECT_TRUE(conn.disconnect());
191 
192     EXPECT_FALSE(conn.getSubscriberRefCount().connected);
193 
194     incrementSignal.invoke(1);
195     EXPECT_EQ(a, 3);
196 }
197 
TEST(Connection,AssignmentOperatorCopySelf)198 TEST(Connection, AssignmentOperatorCopySelf)
199 {
200     Signal<int> incrementSignal;
201     int a = 0;
202     auto IncrementA = [&a](int incrementBy) {
203         a += incrementBy;  //
204     };
205     EXPECT_EQ(a, 0);
206 
207     auto conn = incrementSignal.connect(IncrementA);
208 
209     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
210     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
211 
212     incrementSignal.invoke(1);
213     EXPECT_EQ(a, 1);
214 
215     // Test copying of connection
216     auto connCopy = conn;
217     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
218     EXPECT_EQ(conn.getSubscriberRefCount().count, 2);
219 
220     incrementSignal.invoke(1);
221     EXPECT_EQ(a, 2);
222 
223     connCopy = connCopy;
224 
225     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
226     EXPECT_EQ(conn.getSubscriberRefCount().count, 2);
227 
228     incrementSignal.invoke(1);
229     EXPECT_EQ(a, 3);
230 
231     EXPECT_TRUE(connCopy.disconnect());
232 
233     incrementSignal.invoke(1);
234     EXPECT_EQ(a, 4);
235 
236     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
237     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
238 
239     EXPECT_TRUE(conn.disconnect());
240 
241     EXPECT_FALSE(conn.getSubscriberRefCount().connected);
242 
243     incrementSignal.invoke(1);
244     EXPECT_EQ(a, 4);
245 }
246 
TEST(Connection,AssignmentOperatorMove)247 TEST(Connection, AssignmentOperatorMove)
248 {
249     Signal<int> incrementSignal;
250     int a = 0;
251     auto IncrementA = [&a](int incrementBy) {
252         a += incrementBy;  //
253     };
254     EXPECT_EQ(a, 0);
255 
256     auto conn = incrementSignal.connect(IncrementA);
257 
258     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
259     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
260 
261     incrementSignal.invoke(1);
262     EXPECT_EQ(a, 1);
263 
264     // Test copying of connection
265     auto yoinkedConn = std::move(conn);
266     EXPECT_FALSE(conn.getSubscriberRefCount().connected);
267     EXPECT_EQ(conn.getSubscriberRefCount().count, 0);
268     EXPECT_TRUE(yoinkedConn.getSubscriberRefCount().connected);
269     EXPECT_EQ(yoinkedConn.getSubscriberRefCount().count, 1);
270 
271     incrementSignal.invoke(1);
272     EXPECT_EQ(a, 2);
273 
274     EXPECT_TRUE(yoinkedConn.disconnect());
275 
276     incrementSignal.invoke(1);
277     EXPECT_EQ(a, 2);
278 }
279 
TEST(Connection,AssignmentOperatorMoveSelf)280 TEST(Connection, AssignmentOperatorMoveSelf)
281 {
282     Signal<int> incrementSignal;
283     int a = 0;
284     auto IncrementA = [&a](int incrementBy) {
285         a += incrementBy;  //
286     };
287     EXPECT_EQ(a, 0);
288 
289     auto conn = incrementSignal.connect(IncrementA);
290 
291     EXPECT_TRUE(conn.getSubscriberRefCount().connected);
292     EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
293 
294     incrementSignal.invoke(1);
295     EXPECT_EQ(a, 1);
296 
297     // Test copying of connection
298     auto yoinkedConn = std::move(conn);
299     EXPECT_FALSE(conn.getSubscriberRefCount().connected);
300     EXPECT_EQ(conn.getSubscriberRefCount().count, 0);
301     EXPECT_TRUE(yoinkedConn.getSubscriberRefCount().connected);
302     EXPECT_EQ(yoinkedConn.getSubscriberRefCount().count, 1);
303 
304     incrementSignal.invoke(1);
305     EXPECT_EQ(a, 2);
306 
307     yoinkedConn = std::move(yoinkedConn);
308 
309     EXPECT_TRUE(yoinkedConn.getSubscriberRefCount().connected);
310     EXPECT_EQ(yoinkedConn.getSubscriberRefCount().count, 1);
311 
312     incrementSignal.invoke(1);
313     EXPECT_EQ(a, 3);
314 
315     EXPECT_TRUE(yoinkedConn.disconnect());
316 
317     incrementSignal.invoke(1);
318     EXPECT_EQ(a, 3);
319 }
320 
TEST(ScopedConnection,MoveConstructorFromBase)321 TEST(ScopedConnection, MoveConstructorFromBase)
322 {
323     Signal<int> incrementSignal;
324     int a = 0;
325     auto IncrementA = [&a](int incrementBy) {
326         a += incrementBy;  //
327     };
328     EXPECT_EQ(a, 0);
329 
330     {
331         ScopedConnection scopedConn(incrementSignal.connect(IncrementA));
332 
333         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
334         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
335 
336         incrementSignal.invoke(1);
337         EXPECT_EQ(a, 1);
338     }
339 
340     incrementSignal.invoke(1);
341     EXPECT_EQ(a, 1);
342 }
343 
TEST(ScopedConnection,ConstructFromImplicitlyMovedConnection)344 TEST(ScopedConnection, ConstructFromImplicitlyMovedConnection)
345 {
346     Signal<int> incrementSignal;
347     int a = 0;
348     auto IncrementA = [&a](int incrementBy) {
349         a += incrementBy;  //
350     };
351     EXPECT_EQ(a, 0);
352 
353     incrementSignal.invoke(1);
354 
355     EXPECT_EQ(a, 0);
356 
357     {
358         ScopedConnection scopedConn(incrementSignal.connect(IncrementA));
359 
360         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
361         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
362 
363         incrementSignal.invoke(1);
364         EXPECT_EQ(a, 1);
365     }
366 
367     incrementSignal.invoke(1);
368     EXPECT_EQ(a, 1);
369 }
370 
TEST(ScopedConnection,ConstructFromCopiedConnection)371 TEST(ScopedConnection, ConstructFromCopiedConnection)
372 {
373     Signal<int> incrementSignal;
374     int a = 0;
375     auto IncrementA = [&a](int incrementBy) {
376         a += incrementBy;  //
377     };
378     EXPECT_EQ(a, 0);
379 
380     {
381         auto conn = incrementSignal.connect(IncrementA);
382 
383         EXPECT_TRUE(conn.getSubscriberRefCount().connected);
384         EXPECT_EQ(conn.getSubscriberRefCount().count, 1);
385 
386         ScopedConnection scopedConn(conn);
387 
388         EXPECT_TRUE(conn.getSubscriberRefCount().connected);
389         EXPECT_EQ(conn.getSubscriberRefCount().count, 2);
390 
391         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
392         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 2);
393 
394         incrementSignal.invoke(1);
395         EXPECT_EQ(a, 1);
396 
397         EXPECT_TRUE(conn.disconnect());
398     }
399 
400     incrementSignal.invoke(1);
401     EXPECT_EQ(a, 1);
402 }
403 
TEST(ScopedConnection,ConstructFromCopiedScopedConnection)404 TEST(ScopedConnection, ConstructFromCopiedScopedConnection)
405 {
406     Signal<int> incrementSignal;
407     int a = 0;
408     auto IncrementA = [&a](int incrementBy) {
409         a += incrementBy;  //
410     };
411     EXPECT_EQ(a, 0);
412 
413     {
414         ScopedConnection scopedConn(incrementSignal.connect(IncrementA));
415 
416         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
417         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
418 
419         ScopedConnection scopedConnCopy(scopedConn);
420 
421         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
422         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 2);
423 
424         EXPECT_TRUE(scopedConnCopy.c().getSubscriberRefCount().connected);
425         EXPECT_EQ(scopedConnCopy.c().getSubscriberRefCount().count, 2);
426 
427         incrementSignal.invoke(1);
428         EXPECT_EQ(a, 1);
429     }
430 
431     incrementSignal.invoke(1);
432     EXPECT_EQ(a, 1);
433 }
434 
TEST(ScopedConnection,STLContainer)435 TEST(ScopedConnection, STLContainer)
436 {
437     Signal<int> incrementSignal;
438     int a = 0;
439     auto IncrementA = [&a](int incrementBy) {
440         a += incrementBy;  //
441     };
442     EXPECT_EQ(a, 0);
443 
444     vector<ScopedConnection> scopedConnections;
445 
446     {
447         ScopedConnection scopedConn(incrementSignal.connect(IncrementA));
448 
449         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
450         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
451 
452         ScopedConnection scopedConnCopy(scopedConn);
453 
454         EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
455         EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 2);
456 
457         ScopedConnection scopedConnMoved(move(scopedConn));
458 
459         EXPECT_TRUE(scopedConnMoved.c().getSubscriberRefCount().connected);
460         EXPECT_EQ(scopedConnMoved.c().getSubscriberRefCount().count, 2);
461 
462         EXPECT_TRUE(scopedConnCopy.c().getSubscriberRefCount().connected);
463         EXPECT_EQ(scopedConnCopy.c().getSubscriberRefCount().count, 2);
464 
465         scopedConnections.emplace_back(move(scopedConnCopy));
466 
467         EXPECT_TRUE(scopedConnMoved.c().getSubscriberRefCount().connected);
468         EXPECT_EQ(scopedConnMoved.c().getSubscriberRefCount().count, 2);
469 
470         scopedConnections.emplace_back(move(scopedConnMoved));
471 
472         EXPECT_TRUE(
473             scopedConnections.front().c().getSubscriberRefCount().connected);
474         EXPECT_EQ(scopedConnections.front().c().getSubscriberRefCount().count,
475                   2);
476 
477         incrementSignal.invoke(1);
478         EXPECT_EQ(a, 1);
479     }
480 
481     incrementSignal.invoke(1);
482     EXPECT_EQ(a, 2);
483 
484     scopedConnections.clear();
485 
486     incrementSignal.invoke(1);
487     EXPECT_EQ(a, 2);
488 }
489 
TEST(ScopedConnection,VectorPushBack)490 TEST(ScopedConnection, VectorPushBack)
491 {
492     Signal<int> incrementSignal;
493     int a = 0;
494     auto IncrementA = [&a](int incrementBy) {
495         a += incrementBy;  //
496     };
497     EXPECT_EQ(a, 0);
498 
499     vector<ScopedConnection> scopedConnections;
500 
501     {
502         scopedConnections.push_back(incrementSignal.connect(IncrementA));
503 
504         incrementSignal.invoke(1);
505         EXPECT_EQ(a, 1);
506     }
507 
508     incrementSignal.invoke(1);
509     EXPECT_EQ(a, 2);
510 
511     scopedConnections.clear();
512 
513     incrementSignal.invoke(1);
514     EXPECT_EQ(a, 2);
515 }
516 
TEST(ScopedConnection,VectorEmplaceBack)517 TEST(ScopedConnection, VectorEmplaceBack)
518 {
519     Signal<int> incrementSignal;
520     int a = 0;
521     auto IncrementA = [&a](int incrementBy) {
522         a += incrementBy;  //
523     };
524     EXPECT_EQ(a, 0);
525 
526     vector<ScopedConnection> scopedConnections;
527 
528     {
529         scopedConnections.emplace_back(incrementSignal.connect(IncrementA));
530 
531         incrementSignal.invoke(1);
532         EXPECT_EQ(a, 1);
533     }
534 
535     incrementSignal.invoke(1);
536     EXPECT_EQ(a, 2);
537 
538     scopedConnections.clear();
539 
540     incrementSignal.invoke(1);
541     EXPECT_EQ(a, 2);
542 }
543 
TEST(ScopedConnection,AssignmentOperatorCopyConnection)544 TEST(ScopedConnection, AssignmentOperatorCopyConnection)
545 {
546     Signal<int> incrementSignal;
547     int a = 0;
548     auto IncrementA = [&a](int incrementBy) {
549         a += incrementBy;  //
550     };
551     EXPECT_EQ(a, 0);
552 
553     // Nothing connected, should not change
554     incrementSignal.invoke(1);
555     EXPECT_EQ(a, 0);
556 
557     {
558         Connection connA = incrementSignal.connect(IncrementA);
559 
560         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
561         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
562 
563         Connection connB = incrementSignal.connect(IncrementA);
564 
565         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
566         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
567 
568         // 2 connections connected
569         incrementSignal.invoke(1);
570         EXPECT_EQ(a, 2);
571 
572         {
573             ScopedConnection scopedConn(connA);
574 
575             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
576             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
577             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
578             EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
579 
580             scopedConn = connB;
581 
582             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
583             EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
584             EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
585             EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 2);
586 
587             scopedConn = connA;
588 
589             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
590             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
591             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
592             EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
593 
594             // 2 connections still connected
595             incrementSignal.invoke(1);
596             EXPECT_EQ(a, 4);
597         }
598 
599         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
600         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
601         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
602         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
603     }
604 }
605 
TEST(ScopedConnection,AssignmentOperatorCopyScopedConnection)606 TEST(ScopedConnection, AssignmentOperatorCopyScopedConnection)
607 {
608     Signal<int> incrementSignal;
609     int a = 0;
610     auto IncrementA = [&a](int incrementBy) {
611         a += incrementBy;  //
612     };
613     EXPECT_EQ(a, 0);
614 
615     // Nothing connected, should not change
616     incrementSignal.invoke(1);
617     EXPECT_EQ(a, 0);
618 
619     {
620         Connection connA = incrementSignal.connect(IncrementA);
621 
622         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
623         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
624 
625         Connection connB = incrementSignal.connect(IncrementA);
626 
627         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
628         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
629 
630         // 2 connections connected
631         incrementSignal.invoke(1);
632         EXPECT_EQ(a, 2);
633 
634         {
635             ScopedConnection scopedConn(connA);
636             ScopedConnection scB(connB);
637 
638             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
639             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
640             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
641             EXPECT_EQ(connB.getSubscriberRefCount().count, 2);
642 
643             scopedConn = scB;
644 
645             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
646             EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
647             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
648             EXPECT_EQ(connB.getSubscriberRefCount().count, 3);
649 
650             // 2 connections still connected
651             incrementSignal.invoke(1);
652             EXPECT_EQ(a, 4);
653         }
654 
655         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
656         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
657         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
658         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
659     }
660 }
661 
TEST(ScopedConnection,AssignmentOperatorMoveScopedConnection)662 TEST(ScopedConnection, AssignmentOperatorMoveScopedConnection)
663 {
664     Signal<int> incrementSignal;
665     int a = 0;
666     auto IncrementA = [&a](int incrementBy) {
667         a += incrementBy;  //
668     };
669     EXPECT_EQ(a, 0);
670 
671     // Nothing connected, should not change
672     incrementSignal.invoke(1);
673     EXPECT_EQ(a, 0);
674 
675     {
676         Connection connA = incrementSignal.connect(IncrementA);
677 
678         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
679         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
680 
681         Connection connB = incrementSignal.connect(IncrementA);
682 
683         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
684         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
685 
686         // 2 connections connected
687         incrementSignal.invoke(1);
688         EXPECT_EQ(a, 2);
689 
690         {
691             ScopedConnection scopedConn(connA);
692             ScopedConnection scB(connB);
693 
694             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
695             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
696             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
697             EXPECT_EQ(connB.getSubscriberRefCount().count, 2);
698 
699             scopedConn = std::move(scB);
700 
701             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
702             EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
703             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
704             EXPECT_EQ(connB.getSubscriberRefCount().count, 2);
705 
706             // 2 connections still connected
707             incrementSignal.invoke(1);
708             EXPECT_EQ(a, 4);
709         }
710 
711         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
712         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
713         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
714         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
715     }
716 }
717 
TEST(ScopedConnection,AssignmentOperatorMoveScopedConnectionSelf)718 TEST(ScopedConnection, AssignmentOperatorMoveScopedConnectionSelf)
719 {
720     Signal<int> incrementSignal;
721     int a = 0;
722     auto IncrementA = [&a](int incrementBy) {
723         a += incrementBy;  //
724     };
725     EXPECT_EQ(a, 0);
726 
727     // Nothing connected, should not change
728     incrementSignal.invoke(1);
729     EXPECT_EQ(a, 0);
730 
731     {
732         Connection connA = incrementSignal.connect(IncrementA);
733 
734         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
735         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
736 
737         Connection connB = incrementSignal.connect(IncrementA);
738 
739         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
740         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
741 
742         // 2 connections connected
743         incrementSignal.invoke(1);
744         EXPECT_EQ(a, 2);
745 
746         {
747             ScopedConnection scopedConn(connA);
748 
749             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
750             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
751             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
752             EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
753 
754             scopedConn = std::move(scopedConn);
755 
756             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
757             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
758             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
759             EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
760 
761             // 2 connections still connected
762             incrementSignal.invoke(1);
763             EXPECT_EQ(a, 4);
764         }
765 
766         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
767         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
768         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
769         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
770     }
771 }
772 
TEST(ScopedConnection,AssignmentOperatorMove)773 TEST(ScopedConnection, AssignmentOperatorMove)
774 {
775     Signal<int> incrementSignal;
776     int a = 0;
777     auto IncrementA = [&a](int incrementBy) {
778         a += incrementBy;  //
779     };
780     EXPECT_EQ(a, 0);
781 
782     // Nothing connected, should not change
783     incrementSignal.invoke(1);
784     EXPECT_EQ(a, 0);
785 
786     {
787         Connection connA = incrementSignal.connect(IncrementA);
788 
789         EXPECT_TRUE(connA.getSubscriberRefCount().connected);
790         EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
791 
792         Connection connB = incrementSignal.connect(IncrementA);
793 
794         EXPECT_TRUE(connB.getSubscriberRefCount().connected);
795         EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
796 
797         // 2 connections connected
798         incrementSignal.invoke(1);
799         EXPECT_EQ(a, 2);
800 
801         {
802             ScopedConnection scopedConn(connA);
803 
804             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
805             EXPECT_EQ(connA.getSubscriberRefCount().count, 2);
806             EXPECT_TRUE(connB.getSubscriberRefCount().connected);
807             EXPECT_EQ(connB.getSubscriberRefCount().count, 1);
808 
809             scopedConn = std::move(connB);
810 
811             // 2 connections still connected
812             incrementSignal.invoke(1);
813             EXPECT_EQ(a, 4);
814 
815             EXPECT_TRUE(connA.getSubscriberRefCount().connected);
816             EXPECT_EQ(connA.getSubscriberRefCount().count, 1);
817             EXPECT_FALSE(connB.getSubscriberRefCount().connected);
818             EXPECT_EQ(connB.getSubscriberRefCount().count, 0);
819             EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
820             EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
821 
822             scopedConn = std::move(connA);
823 
824             // connB is gone now, so only 1 should be connected
825             incrementSignal.invoke(1);
826             EXPECT_EQ(a, 5);
827 
828             EXPECT_FALSE(connA.getSubscriberRefCount().connected);
829             EXPECT_EQ(connA.getSubscriberRefCount().count, 0);
830             EXPECT_FALSE(connB.getSubscriberRefCount().connected);
831             EXPECT_EQ(connB.getSubscriberRefCount().count, 0);
832 
833             EXPECT_TRUE(scopedConn.c().getSubscriberRefCount().connected);
834             EXPECT_EQ(scopedConn.c().getSubscriberRefCount().count, 1);
835         }
836 
837         // connB and connA are gone now, since connA was moved into the scoped connection
838         // so nothing should change
839         incrementSignal.invoke(1);
840         EXPECT_EQ(a, 5);
841 
842         EXPECT_FALSE(connA.getSubscriberRefCount().connected);
843         EXPECT_EQ(connA.getSubscriberRefCount().count, 0);
844         EXPECT_FALSE(connB.getSubscriberRefCount().connected);
845         EXPECT_EQ(connB.getSubscriberRefCount().count, 0);
846     }
847 }
848 
TEST(SelfDisconnectingSignal,MultipleConnects)849 TEST(SelfDisconnectingSignal, MultipleConnects)
850 {
851     NoArgSelfDisconnectingSignal signal;
852 
853     int a = 0;
854     int b = 0;
855 
856     signal.connect([&] {
857         a++;
858         return a == 1;
859     });
860 
861     signal.connect([&] {
862         b++;
863         return b == 2;
864     });
865 
866     signal.invoke();
867 
868     EXPECT_EQ(a, 1);
869     EXPECT_EQ(b, 1);
870 
871     signal.invoke();
872 
873     EXPECT_EQ(a, 1);
874     EXPECT_EQ(b, 2);
875 
876     signal.invoke();
877 
878     EXPECT_EQ(a, 1);
879     EXPECT_EQ(b, 2);
880 }
881