xref: /aosp_15_r20/external/webrtc/rtc_base/callback_list_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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