1 /*
2 * Copyright 2020 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include <string>
11 #include <type_traits>
12
13 #include "api/function_view.h"
14 #include "rtc_base/callback_list.h"
15 #include "test/gtest.h"
16
17 namespace webrtc {
18 namespace {
19
TEST(CallbackList,NoReceiverSingleMessageTest)20 TEST(CallbackList, NoReceiverSingleMessageTest) {
21 CallbackList<std::string> c;
22
23 c.Send("message");
24 }
25
TEST(CallbackList,MultipleParameterMessageTest)26 TEST(CallbackList, MultipleParameterMessageTest) {
27 CallbackList<const std::string&, std::string, std::string&&, int, int*,
28 std::string&>
29 c;
30 std::string str = "messege";
31 int i = 10;
32
33 c.Send(str, "message1", "message0", 123, &i, str);
34 }
35
TEST(CallbackList,NoParameterMessageTest)36 TEST(CallbackList, NoParameterMessageTest) {
37 CallbackList<> c;
38
39 c.Send();
40 }
41
TEST(CallbackList,ReferenceTest)42 TEST(CallbackList, ReferenceTest) {
43 CallbackList<int&> c;
44 int index = 1;
45
46 c.AddReceiver([](int& index) { index++; });
47 c.Send(index);
48
49 EXPECT_EQ(index, 2);
50 }
51
52 enum State {
53 kNew,
54 kChecking,
55 };
56
TEST(CallbackList,SingleEnumValueTest)57 TEST(CallbackList, SingleEnumValueTest) {
58 CallbackList<State> c;
59 State s1 = kNew;
60 int index = 0;
61
62 c.AddReceiver([&index](State s) { index++; });
63 c.Send(s1);
64
65 EXPECT_EQ(index, 1);
66 }
67
TEST(CallbackList,SingleEnumReferenceTest)68 TEST(CallbackList, SingleEnumReferenceTest) {
69 CallbackList<State&> c;
70 State s = kNew;
71
72 c.AddReceiver([](State& s) { s = kChecking; });
73 c.Send(s);
74
75 EXPECT_EQ(s, kChecking);
76 }
77
TEST(CallbackList,ConstReferenceTest)78 TEST(CallbackList, ConstReferenceTest) {
79 CallbackList<int&> c;
80 int i = 0;
81 int index = 1;
82
83 c.AddReceiver([&i](const int& index) { i = index; });
84 c.Send(index);
85
86 EXPECT_EQ(i, 1);
87 }
88
TEST(CallbackList,PointerTest)89 TEST(CallbackList, PointerTest) {
90 CallbackList<int*> c;
91 int index = 1;
92
93 c.AddReceiver([](int* index) { (*index)++; });
94 c.Send(&index);
95
96 EXPECT_EQ(index, 2);
97 }
98
TEST(CallbackList,CallByValue)99 TEST(CallbackList, CallByValue) {
100 CallbackList<int> c;
101 int x = 17;
102
103 c.AddReceiver([&x](int n) { x += n; });
104 int y = 89;
105 c.Send(y);
106
107 EXPECT_EQ(x, 106);
108 }
109
PlusOne(int & a)110 void PlusOne(int& a) {
111 a++;
112 }
113
TEST(CallbackList,FunctionPtrTest)114 TEST(CallbackList, FunctionPtrTest) {
115 CallbackList<int&> c;
116 int index = 1;
117
118 c.AddReceiver(PlusOne);
119 c.Send(index);
120
121 EXPECT_EQ(index, 2);
122 }
123
124 struct LargeNonTrivial {
125 int a[17];
126
127 LargeNonTrivial() = default;
LargeNonTrivialwebrtc::__anond648e92a0111::LargeNonTrivial128 LargeNonTrivial(LargeNonTrivial&& m) {}
129 ~LargeNonTrivial() = default;
130
operator ()webrtc::__anond648e92a0111::LargeNonTrivial131 void operator()(int& b) { b = 1; }
132 };
133
TEST(CallbackList,LargeNonTrivialTest)134 TEST(CallbackList, LargeNonTrivialTest) {
135 CallbackList<int&> c;
136 int i = 0;
137 static_assert(sizeof(LargeNonTrivial) > UntypedFunction::kInlineStorageSize,
138 "");
139 c.AddReceiver(LargeNonTrivial());
140 c.Send(i);
141
142 EXPECT_EQ(i, 1);
143 }
144
145 struct LargeTrivial {
146 int a[17];
operator ()webrtc::__anond648e92a0111::LargeTrivial147 void operator()(int& x) { x = 1; }
148 };
149
TEST(CallbackList,LargeTrivial)150 TEST(CallbackList, LargeTrivial) {
151 CallbackList<int&> c;
152 LargeTrivial lt;
153 int i = 0;
154
155 static_assert(sizeof(lt) > UntypedFunction::kInlineStorageSize, "");
156 c.AddReceiver(lt);
157 c.Send(i);
158
159 EXPECT_EQ(i, 1);
160 }
161
162 struct OnlyNonTriviallyConstructible {
163 OnlyNonTriviallyConstructible() = default;
OnlyNonTriviallyConstructiblewebrtc::__anond648e92a0111::OnlyNonTriviallyConstructible164 OnlyNonTriviallyConstructible(OnlyNonTriviallyConstructible&& m) {}
165
operator ()webrtc::__anond648e92a0111::OnlyNonTriviallyConstructible166 void operator()(int& a) { a = 1; }
167 };
168
TEST(CallbackList,OnlyNonTriviallyMoveConstructible)169 TEST(CallbackList, OnlyNonTriviallyMoveConstructible) {
170 CallbackList<int&> c;
171 int i = 0;
172
173 c.AddReceiver(OnlyNonTriviallyConstructible());
174 c.Send(i);
175
176 EXPECT_EQ(i, 1);
177 }
178
TEST(CallbackList,MultipleReceiverSendTest)179 TEST(CallbackList, MultipleReceiverSendTest) {
180 CallbackList<int&> c;
181 std::function<void(int&)> plus = PlusOne;
182 int index = 1;
183
184 c.AddReceiver(plus);
185 c.AddReceiver([](int& i) { i--; });
186 c.AddReceiver(plus);
187 c.AddReceiver(plus);
188 c.Send(index);
189 c.Send(index);
190
191 EXPECT_EQ(index, 5);
192 }
193
194 class A {
195 public:
increment(int & i) const196 void increment(int& i) const { i++; }
197 };
198
TEST(CallbackList,MemberFunctionTest)199 TEST(CallbackList, MemberFunctionTest) {
200 CallbackList<int&> c;
201 A a;
202 int index = 1;
203
204 c.AddReceiver([&a](int& i) { a.increment(i); });
205 c.Send(index);
206
207 EXPECT_EQ(index, 2);
208 }
209
210 // todo(glahiru): Add a test case to catch some error for Karl's first fix
211
TEST(CallbackList,RemoveOneReceiver)212 TEST(CallbackList, RemoveOneReceiver) {
213 int removal_tag[2];
214 CallbackList<> c;
215 int accumulator = 0;
216 c.AddReceiver([&accumulator] { accumulator += 1; });
217 c.AddReceiver(&removal_tag[0], [&accumulator] { accumulator += 10; });
218 c.AddReceiver(&removal_tag[1], [&accumulator] { accumulator += 100; });
219 c.Send();
220 EXPECT_EQ(accumulator, 111);
221 c.RemoveReceivers(&removal_tag[0]);
222 c.Send();
223 EXPECT_EQ(accumulator, 212);
224 }
225
TEST(CallbackList,RemoveZeroReceivers)226 TEST(CallbackList, RemoveZeroReceivers) {
227 int removal_tag[3];
228 CallbackList<> c;
229 int accumulator = 0;
230 c.AddReceiver([&accumulator] { accumulator += 1; });
231 c.AddReceiver(&removal_tag[0], [&accumulator] { accumulator += 10; });
232 c.AddReceiver(&removal_tag[1], [&accumulator] { accumulator += 100; });
233 c.Send();
234 EXPECT_EQ(accumulator, 111);
235 c.RemoveReceivers(&removal_tag[2]);
236 c.Send();
237 EXPECT_EQ(accumulator, 222);
238 }
239
TEST(CallbackList,RemoveManyReceivers)240 TEST(CallbackList, RemoveManyReceivers) {
241 int removal_tag;
242 CallbackList<> c;
243 int accumulator = 0;
244 c.AddReceiver([&accumulator] { accumulator += 1; });
245 c.AddReceiver(&removal_tag, [&accumulator] { accumulator += 10; });
246 c.AddReceiver([&accumulator] { accumulator += 100; });
247 c.AddReceiver(&removal_tag, [&accumulator] { accumulator += 1000; });
248 c.Send();
249 EXPECT_EQ(accumulator, 1111);
250 c.RemoveReceivers(&removal_tag);
251 c.Send();
252 EXPECT_EQ(accumulator, 1212);
253 }
254
TEST(CallbackList,RemoveFromSend)255 TEST(CallbackList, RemoveFromSend) {
256 int removal_tag = 0;
257 CallbackList<> c;
258 c.AddReceiver(&removal_tag, [&] {
259 c.RemoveReceivers(&removal_tag);
260 // Do after RemoveReceivers to make sure the lambda is still valid.
261 ++removal_tag;
262 });
263 c.Send();
264 c.Send();
265 EXPECT_EQ(removal_tag, 1);
266 }
267
268 } // namespace
269 } // namespace webrtc
270