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