Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: base/callback_list_unittest.cc

Issue 22877038: Add a CallbackRegistry class to base/ to manage callbacks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use CallbackListBase Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« base/callback_list.h ('K') | « base/callback_list.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/callback_list.h"
6
7 #include <vector>
8
9 #include "base/compiler_specific.h"
10 #include "base/memory/weak_ptr.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace base {
14 namespace {
15
16 typedef base::Callback<void(void)> TestCallback;
17 typedef CallbackList TestCallbackList;
18
19 typedef base::Callback<void(const int&)> OneParamCallback;
20 typedef CallbackListWithDetails<int> TestCallbackListWithParam;
21
22 class Listener {
23 public:
24 explicit Listener() : total(0), scaler_(1) {}
25 Listener(int scaler) : total(0), scaler_(scaler) {}
26 virtual ~Listener() {}
27 virtual void OnEvent() {
28 total++;
29 }
30 virtual void OnEventWithParam(const int& x) {
31 total += x * scaler_;
32 }
33 int total;
34 private:
35 int scaler_;
36 };
37
38 class Remover : public Listener {
39 public:
40 explicit Remover() : removal_cb_(base::Closure()) {}
41 virtual ~Remover() {}
42 virtual void OnEvent() OVERRIDE {
43 Listener::OnEvent();
44 removal_cb_.Run();
45 }
46 virtual void SetCallback(const base::Closure& cb) {
47 removal_cb_ = cb;
48 }
49
50 private:
51 base::Closure removal_cb_;
52 };
53
54 class Adder : public Listener {
55 public:
56 explicit Adder(TestCallbackList* cb_list)
57 : added(false),
58 cb_list_(cb_list) {}
59 virtual ~Adder() {}
60 virtual void OnAddedEvent() {
61 if (!added) {
62 added = true;
63 cb_list_->RegisterCallback(
64 base::Bind(&Adder::OnEvent, base::Unretained(this)));
65 }
66 }
67 bool added;
68
69 private:
70 TestCallbackList* cb_list_;
71 };
72
73 class Clearer : public Listener {
74 public:
75 explicit Clearer(TestCallbackList* cb_list)
76 : added(false),
77 cb_list_(cb_list) {}
78 virtual ~Clearer() {}
79 virtual void OnClearAndAddEvent() {
80 cb_list_->Clear();
81 cb_list_->RegisterCallback(
82 base::Bind(&Clearer::OnEvent, base::Unretained(this)));
83 added = true;
84 }
85 bool added;
86
87 private:
88 TestCallbackList* cb_list_;
89 };
90
91 class ListDestructor {
92 public:
93 explicit ListDestructor(TestCallbackList* cb_list)
94 : cb_list_(cb_list) {}
95 virtual ~ListDestructor() {}
96 virtual void OnEvent() {
97 cb_list_->Clear();
98 delete cb_list_;
99 }
100
101 private:
102 TestCallbackList* cb_list_;
103 };
104
105 TEST(CallbackListTest, BasicTest) {
106 TestCallbackList cb_list;
107 Listener a, b, c;
108 TestCallback a_cb = base::Bind(&Listener::OnEvent, base::Unretained(&a));
109 TestCallback b_cb = base::Bind(&Listener::OnEvent, base::Unretained(&b));
110
111 base::Closure remove_a = cb_list.RegisterCallback(a_cb);
112
113 base::Closure remove_b = cb_list.RegisterCallback(b_cb);;
114
115 EXPECT_FALSE(remove_a.is_null());
116 EXPECT_FALSE(remove_b.is_null());
117
118 cb_list.Run();
119
120 EXPECT_EQ(1, a.total);
121 EXPECT_EQ(1, b.total);
122
123 remove_b.Run();
124
125 base::Closure remove_c = cb_list.RegisterCallback(
126 base::Bind(&Listener::OnEvent, base::Unretained(&c)));
127
128 cb_list.Run();
129
130 EXPECT_EQ(2, a.total);
131 EXPECT_EQ(1, b.total);
132 EXPECT_EQ(1, c.total);
133
134 remove_a.Run();
135 remove_b.Run();
136 remove_c.Run();
137
138 EXPECT_FALSE(cb_list.might_have_callbacks());
139 }
140
141 TEST(CallbackListTest, BasicTestWithParams) {
142 TestCallbackListWithParam cb_list;
143 Listener a(1), b(-1), c(1);
144 OneParamCallback a_cb =
145 base::Bind(&Listener::OnEventWithParam, base::Unretained(&a));
146
147 OneParamCallback b_cb =
148 base::Bind(&Listener::OnEventWithParam, base::Unretained(&b));
149
150 base::Closure remove_a = cb_list.RegisterCallback(a_cb);
151
152 base::Closure remove_b = cb_list.RegisterCallback(b_cb);
153
154 EXPECT_FALSE(remove_a.is_null());
155 EXPECT_FALSE(remove_b.is_null());
156
157 cb_list.Run(10);
158
159 EXPECT_EQ(10, a.total);
160 EXPECT_EQ(-10, b.total);
161
162 remove_b.Run();
163
164 base::Closure remove_c = cb_list.RegisterCallback(
165 base::Bind(&Listener::OnEventWithParam, base::Unretained(&c)));
166
167 cb_list.Run(10);
168
169 EXPECT_EQ(20, a.total);
170 EXPECT_EQ(-10, b.total);
171 EXPECT_EQ(10, c.total);
172
173 remove_a.Run();
174 remove_b.Run();
175 remove_c.Run();
176
177 EXPECT_FALSE(cb_list.might_have_callbacks());
178 }
179
180 TEST(CallbackListTest, RemoveCallbacksDuringIteration) {
181 TestCallbackList cb_list;
182 Listener a, b;
183 Remover remover_1, remover_2;
184
185 base::Closure remover_1_cb = cb_list.RegisterCallback(
186 base::Bind(&Remover::OnEvent, base::Unretained(&remover_1)));
187 base::Closure remover_2_cb = cb_list.RegisterCallback(
188 base::Bind(&Remover::OnEvent, base::Unretained(&remover_2)));
189 base::Closure a_cb = cb_list.RegisterCallback(
190 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
191 base::Closure b_cb = cb_list.RegisterCallback(
192 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
193
194 // |remover_1| will remove itself.
195 remover_1.SetCallback(remover_1_cb);
196 // |remover_2| will remove a.
197 remover_2.SetCallback(a_cb);
198
199 cb_list.Run();
200
201 // |remover_1| runs once (and removes itself), |remover_2| runs once (and
202 // removes a), |a| never runs, and |b| runs once.
203 EXPECT_EQ(1, remover_1.total);
204 EXPECT_EQ(1, remover_2.total);
205 EXPECT_EQ(0, a.total);
206 EXPECT_EQ(1, b.total);
207
208 cb_list.Run();
209
210 // Only |remover_2| and |b| run this time.
211 EXPECT_EQ(1, remover_1.total);
212 EXPECT_EQ(2, remover_2.total);
213 EXPECT_EQ(0, a.total);
214 EXPECT_EQ(2, b.total);
215
216 EXPECT_TRUE(cb_list.might_have_callbacks());
217
218 remover_2_cb.Run();
219 b_cb.Run();
220
221 EXPECT_FALSE(cb_list.might_have_callbacks());
222 }
223
224 TEST(CallbackListTest, AddCallbacksDuringIteration) {
225 TestCallbackList cb_list;
226 Adder a(&cb_list);
227 Listener b;
228 cb_list.RegisterCallback(
229 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
230 cb_list.RegisterCallback(
231 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
232
233 cb_list.Run();
234
235 EXPECT_EQ(1, a.total);
236 EXPECT_EQ(1, b.total);
237 EXPECT_TRUE(a.added);
238
239 cb_list.Run();
240
241 EXPECT_EQ(2, a.total);
242 EXPECT_EQ(2, b.total);
243
244 cb_list.Clear();
245 }
246
247 TEST(CallbackListTest, AddCallbacksDuringIteration_Existing) {
248 TestCallbackList cb_list(TestCallbackList::NOTIFY_EXISTING_ONLY);
249 Adder a(&cb_list);
250 Listener b;
251 cb_list.RegisterCallback(
252 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
253 cb_list.RegisterCallback(
254 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
255
256 cb_list.Run();
257
258 EXPECT_EQ(0, a.total);
259 EXPECT_EQ(1, b.total);
260 EXPECT_TRUE(a.added);
261
262 cb_list.Run();
263
264 EXPECT_EQ(1, a.total);
265 EXPECT_EQ(2, b.total);
266
267 cb_list.Clear();
268 }
269
270 TEST(CallbackListTest, AddAndRemoveCallbacksDuringIteration_Existing) {
271 TestCallbackList cb_list(TestCallbackList::NOTIFY_EXISTING_ONLY);
272 Adder a(&cb_list);
273 Remover b;
274 Listener c;
275
276 base::Closure c_cb = cb_list.RegisterCallback(
277 base::Bind(&Listener::OnEvent, base::Unretained(&c)));
278
279 // |b| removes |c|.
280 b.SetCallback(c_cb);
281 cb_list.RegisterCallback(
282 base::Bind(&Remover::OnEvent, base::Unretained(&b)));
283
284 // |a| adds a new callback.
285 base::Closure a_cb = cb_list.RegisterCallback(
286 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
287
288 cb_list.Run();
289
290 // |c| ran once, new callback should have been added but not yet run.
291 EXPECT_EQ(1, c.total);
292 EXPECT_EQ(0, a.total);
293 EXPECT_TRUE(a.added);
294
295 cb_list.Run();
296
297 // Now it should have been run.
298 EXPECT_EQ(1, c.total);
299 EXPECT_EQ(1, a.total);
300
301 cb_list.Clear();
302 }
303
304 TEST(CallbackListTest, ClearCallbacksDuringIteration) {
305 TestCallbackList cb_list;
306 Clearer a(&cb_list);
307 Listener b;
308 cb_list.RegisterCallback(
309 base::Bind(&Clearer::OnClearAndAddEvent, base::Unretained(&a)));
310 cb_list.RegisterCallback(
311 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
312
313 cb_list.Run();
314
315 EXPECT_EQ(1, a.total);
316 EXPECT_EQ(0, b.total);
317 EXPECT_TRUE(a.added);
318
319 cb_list.Clear();
320 }
321
322 TEST(CallbackListTest, IteratorOutlivesList) {
323 TestCallbackList* cb_list = new TestCallbackList();
324 ListDestructor destructor(cb_list);
325 cb_list->RegisterCallback(
326 base::Bind(&ListDestructor::OnEvent, base::Unretained(&destructor)));
327 Listener a;
328 cb_list->RegisterCallback(
329 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
330
331 cb_list->Run();
332
333 // |a| never gets called, as |cb_list| got deleted first.
334 EXPECT_EQ(0, a.total);
335 }
336
337 } // namespace
338 } // namespace base
OLDNEW
« base/callback_list.h ('K') | « base/callback_list.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698