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

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: Remove the macro, template on details type 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(const NoDetail&)> TestCallback;
17 typedef CallbackList<NoDetail> TestCallbackList;
18
19 typedef base::Callback<void(const int&)> OneParamCallback;
20 typedef CallbackList<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(const NoDetail& detail) {
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(const NoDetail& detail) OVERRIDE {
43 Listener::OnEvent(detail);
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(const NoDetail& detail) {
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(const NoDetail& detail) {
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(const NoDetail& detail) {
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 EXPECT_TRUE(cb_list.HasCallback(a_cb));
114 EXPECT_FALSE(cb_list.HasCallback(b_cb));
115
116 base::Closure remove_b = cb_list.RegisterCallback(b_cb);
117 EXPECT_TRUE(cb_list.HasCallback(b_cb));
118
119 EXPECT_FALSE(remove_a.is_null());
120 EXPECT_FALSE(remove_b.is_null());
121
122 cb_list.Run(NoDetail());
123
124 EXPECT_EQ(1, a.total);
125 EXPECT_EQ(1, b.total);
126
127 remove_b.Run();
128
129 base::Closure remove_c = cb_list.RegisterCallback(
130 base::Bind(&Listener::OnEvent, base::Unretained(&c)));
131
132 cb_list.Run(NoDetail());
133
134 EXPECT_EQ(2, a.total);
135 EXPECT_EQ(1, b.total);
136 EXPECT_EQ(1, c.total);
137
138 remove_a.Run();
139 remove_b.Run();
140 remove_c.Run();
141
142 EXPECT_FALSE(cb_list.might_have_callbacks());
143 }
144
145 TEST(CallbackListTest, BasicTestWithParams) {
146 TestCallbackListWithParam cb_list;
147 Listener a(1), b(-1), c(1);
148 OneParamCallback a_cb =
149 base::Bind(&Listener::OnEventWithParam, base::Unretained(&a));
150
151 OneParamCallback b_cb =
152 base::Bind(&Listener::OnEventWithParam, base::Unretained(&b));
153
154 base::Closure remove_a = cb_list.RegisterCallback(a_cb);
155
156 EXPECT_TRUE(cb_list.HasCallback(a_cb));
157 EXPECT_FALSE(cb_list.HasCallback(b_cb));
158
159 base::Closure remove_b = cb_list.RegisterCallback(b_cb);
160 EXPECT_TRUE(cb_list.HasCallback(b_cb));
161
162 EXPECT_FALSE(remove_a.is_null());
163 EXPECT_FALSE(remove_b.is_null());
164
165 cb_list.Run(10);
166
167 EXPECT_EQ(10, a.total);
168 EXPECT_EQ(-10, b.total);
169
170 remove_b.Run();
171
172 base::Closure remove_c = cb_list.RegisterCallback(
173 base::Bind(&Listener::OnEventWithParam, base::Unretained(&c)));
174
175 cb_list.Run(10);
176
177 EXPECT_EQ(20, a.total);
178 EXPECT_EQ(-10, b.total);
179 EXPECT_EQ(10, c.total);
180
181 remove_a.Run();
182 remove_b.Run();
183 remove_c.Run();
184
185 EXPECT_FALSE(cb_list.might_have_callbacks());
186 }
187
188 TEST(CallbackListTest, RemoveCallbacksDuringIteration) {
189 TestCallbackList cb_list;
190 Listener a, b;
191 Remover remover_1, remover_2;
192
193 base::Closure remover_1_cb = cb_list.RegisterCallback(
194 base::Bind(&Remover::OnEvent, base::Unretained(&remover_1)));
195 base::Closure remover_2_cb = cb_list.RegisterCallback(
196 base::Bind(&Remover::OnEvent, base::Unretained(&remover_2)));
197 base::Closure a_cb = cb_list.RegisterCallback(
198 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
199 base::Closure b_cb = cb_list.RegisterCallback(
200 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
201
202 // |remover_1| will remove itself.
203 remover_1.SetCallback(remover_1_cb);
204 // |remover_2| will remove a.
205 remover_2.SetCallback(a_cb);
206
207 cb_list.Run(NoDetail());
208
209 // |remover_1| runs once (and removes itself), |remover_2| runs once (and
210 // removes a), |a| never runs, and |b| runs once.
211 EXPECT_EQ(1, remover_1.total);
212 EXPECT_EQ(1, remover_2.total);
213 EXPECT_EQ(0, a.total);
214 EXPECT_EQ(1, b.total);
215
216 cb_list.Run(NoDetail());
217
218 // Only |remover_2| and |b| run this time.
219 EXPECT_EQ(1, remover_1.total);
220 EXPECT_EQ(2, remover_2.total);
221 EXPECT_EQ(0, a.total);
222 EXPECT_EQ(2, b.total);
223
224 EXPECT_TRUE(cb_list.might_have_callbacks());
225
226 remover_2_cb.Run();
227 b_cb.Run();
228
229 EXPECT_FALSE(cb_list.might_have_callbacks());
230 }
231
232 TEST(CallbackListTest, AddCallbacksDuringIteration) {
233 TestCallbackList cb_list;
234 Adder a(&cb_list);
235 Listener b;
236 cb_list.RegisterCallback(
237 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
238 cb_list.RegisterCallback(
239 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
240
241 cb_list.Run(NoDetail());
242
243 EXPECT_EQ(1, a.total);
244 EXPECT_EQ(1, b.total);
245 EXPECT_TRUE(a.added);
246
247 cb_list.Run(NoDetail());
248
249 EXPECT_EQ(2, a.total);
250 EXPECT_EQ(2, b.total);
251
252 cb_list.Clear();
253 }
254
255 TEST(CallbackListTest, AddCallbacksDuringIteration_Existing) {
256 TestCallbackList cb_list(TestCallbackList::NOTIFY_EXISTING_ONLY);
257 Adder a(&cb_list);
258 Listener b;
259 cb_list.RegisterCallback(
260 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
261 cb_list.RegisterCallback(
262 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
263
264 cb_list.Run(NoDetail());
265
266 EXPECT_EQ(0, a.total);
267 EXPECT_EQ(1, b.total);
268 EXPECT_TRUE(a.added);
269
270 cb_list.Run(NoDetail());
271
272 EXPECT_EQ(1, a.total);
273 EXPECT_EQ(2, b.total);
274
275 cb_list.Clear();
276 }
277
278 TEST(CallbackListTest, AddAndRemoveCallbacksDuringIteration_Existing) {
279 TestCallbackList cb_list(TestCallbackList::NOTIFY_EXISTING_ONLY);
280 Adder a(&cb_list);
281 Remover b;
282 Listener c;
283
284 base::Closure c_cb = cb_list.RegisterCallback(
285 base::Bind(&Listener::OnEvent, base::Unretained(&c)));
286
287 // |b| removes |c|.
288 b.SetCallback(c_cb);
289 cb_list.RegisterCallback(
290 base::Bind(&Remover::OnEvent, base::Unretained(&b)));
291
292 // |a| adds a new callback.
293 base::Closure a_cb = cb_list.RegisterCallback(
294 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
295
296 cb_list.Run(NoDetail());
297
298 // |c| ran once, new callback should have been added but not yet run.
299 EXPECT_EQ(1, c.total);
300 EXPECT_EQ(0, a.total);
301 EXPECT_TRUE(a.added);
302
303 cb_list.Run(NoDetail());
304
305 // Now it should have been run.
306 EXPECT_EQ(1, c.total);
307 EXPECT_EQ(1, a.total);
308
309 cb_list.Clear();
310 }
311
312 TEST(CallbackListTest, ClearCallbacksDuringIteration) {
313 TestCallbackList cb_list;
314 Clearer a(&cb_list);
315 Listener b;
316 cb_list.RegisterCallback(
317 base::Bind(&Clearer::OnClearAndAddEvent, base::Unretained(&a)));
318 cb_list.RegisterCallback(
319 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
320
321 cb_list.Run(NoDetail());
322
323 EXPECT_EQ(1, a.total);
324 EXPECT_EQ(0, b.total);
325 EXPECT_TRUE(a.added);
326
327 cb_list.Clear();
328 }
329
330 TEST(CallbackListTest, IteratorOutlivesList) {
331 TestCallbackList* cb_list = new TestCallbackList();
332 ListDestructor destructor(cb_list);
333 cb_list->RegisterCallback(
334 base::Bind(&ListDestructor::OnEvent, base::Unretained(&destructor)));
335 Listener a;
336 cb_list->RegisterCallback(
337 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
338
339 cb_list->Run(NoDetail());
340
341 // |a| never gets called, as |cb_list| got deleted first.
342 EXPECT_EQ(0, a.total);
343 }
344
345 } // namespace
346 } // 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