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

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: Created 7 years, 4 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 (c) 2012 The Chromium Authors. All rights reserved.
Avi (use Gerrit) 2013/08/23 16:51:12 New files get "Copyright 2013".
Cait (Slow) 2013/08/23 18:21:10 Done.
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 "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/threading/platform_thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17 namespace {
18
19 typedef CallbackList<base::Closure> TestCallbackList;
20
21 class Listener {
22 public:
23 explicit Listener() : total(0) {}
24 virtual ~Listener() {}
25 virtual void OnEvent() {
26 total ++;
Avi (use Gerrit) 2013/08/23 16:51:12 No space.
Cait (Slow) 2013/08/23 18:21:10 Done.
27 }
28 int total;
29 };
30
31 class Remover : public Listener {
32 public:
33 explicit Remover() : removal_cb_(base::Closure()) {}
34 virtual ~Remover() {}
35 virtual void OnEvent() OVERRIDE {
36 Listener::OnEvent();
37 removal_cb_.Run();
38 }
39 virtual void SetCallback(const base::Closure& cb) {
40 removal_cb_ = cb;
41 }
42
43 private:
44 base::Closure removal_cb_;
45 };
46
47 class Adder : public Listener {
48 public:
49 explicit Adder(TestCallbackList* cb_list)
50 : added(false),
51 cb_list_(cb_list) {}
52 virtual ~Adder() {}
53 virtual void OnAddedEvent() {
54 if (!added) {
55 added = true;
56 cb_list_->RegisterCallback(
57 base::Bind(&Adder::OnEvent, base::Unretained(this)));
58 }
59 }
60 bool added;
61
62 private:
63 TestCallbackList* cb_list_;
64 };
65
66 class Clearer : public Listener{
Avi (use Gerrit) 2013/08/23 16:51:12 Space before {
Cait (Slow) 2013/08/23 18:21:10 Done.
67 public:
68 explicit Clearer(TestCallbackList* cb_list)
69 : added(false),
70 cb_list_(cb_list) {}
71 virtual ~Clearer() {}
72 virtual void OnClearAndAddEvent() {
73 cb_list_->Clear();
74 cb_list_->RegisterCallback(
75 base::Bind(&Clearer::OnEvent, base::Unretained(this)));
76 added = true;
77 }
78 bool added;
79
80 private:
81 TestCallbackList* cb_list_;
82 };
83
84 class ListDestructor {
85 public:
86 explicit ListDestructor(TestCallbackList* cb_list)
87 : cb_list_(cb_list) {}
88 virtual ~ListDestructor() {}
89 virtual void OnEvent() {
90 delete cb_list_;
91 }
92
93 private:
94 TestCallbackList* cb_list_;
95 };
96
97 TEST(CallbackListTest, BasicTest) {
98 TestCallbackList cb_list;
99 Listener a, b, c;
100 base::Closure a_cb = base::Bind(&Listener::OnEvent, base::Unretained(&a));
101 base::Closure b_cb = base::Bind(&Listener::OnEvent, base::Unretained(&b));
102
103 base::Closure remove_a = cb_list.RegisterCallback(a_cb);
104
105 EXPECT_TRUE(cb_list.HasCallback(a_cb));
106 EXPECT_FALSE(cb_list.HasCallback(b_cb));
107
108 base::Closure remove_b = cb_list.RegisterCallback(b_cb);
109 EXPECT_TRUE(cb_list.HasCallback(b_cb));
110
111 EXPECT_FALSE(remove_a.is_null());
112 EXPECT_FALSE(remove_b.is_null());
113
114 FOR_EACH_CALLBACK(base::Closure, cb_list);
115
116 EXPECT_EQ(1, a.total);
117 EXPECT_EQ(1, b.total);
118
119 remove_b.Run();
120
121 base::Closure remove_c = cb_list.RegisterCallback(
122 base::Bind(&Listener::OnEvent, base::Unretained(&c)));
123
124 FOR_EACH_CALLBACK(base::Closure, cb_list);
125
126 EXPECT_EQ(2, a.total);
127 EXPECT_EQ(1, b.total);
128 EXPECT_EQ(1, c.total);
129
130 remove_a.Run();
131 remove_b.Run();
132 remove_c.Run();
133
134 EXPECT_FALSE(cb_list.might_have_callbacks());
135 }
136
137 TEST(CallbackListTest, RemoveCallbacksDuringIteration) {
138 TestCallbackList cb_list;
139 Listener a, b;
140 Remover remover_1, remover_2;
141
142 base::Closure remover_1_cb = cb_list.RegisterCallback(
143 base::Bind(&Remover::OnEvent, base::Unretained(&remover_1)));
144 base::Closure remover_2_cb = cb_list.RegisterCallback(
145 base::Bind(&Remover::OnEvent, base::Unretained(&remover_2)));
146 base::Closure a_cb = cb_list.RegisterCallback(
147 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
148 base::Closure b_cb = cb_list.RegisterCallback(
149 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
150
151 // |remover_1| will remove itself.
152 remover_1.SetCallback(remover_1_cb);
153 // |remover_2| will remove a.
154 remover_2.SetCallback(a_cb);
155
156 FOR_EACH_CALLBACK(base::Closure, cb_list);
157
158 // |remover_1| runs once (and rms itself), |remover_2| runs once (and removes
Avi (use Gerrit) 2013/08/23 16:51:12 s/rms/removes/
Cait (Slow) 2013/08/23 18:21:10 Done.
159 // a), |a| never runs, and |b| runs once.
160 EXPECT_EQ(1, remover_1.total);
161 EXPECT_EQ(1, remover_2.total);
162 EXPECT_EQ(0, a.total);
163 EXPECT_EQ(1, b.total);
164
165 FOR_EACH_CALLBACK(base::Closure, cb_list);
166
167 // Only |remover_2| and |b| run this time.
168 EXPECT_EQ(1, remover_1.total);
169 EXPECT_EQ(2, remover_2.total);
170 EXPECT_EQ(0, a.total);
171 EXPECT_EQ(2, b.total);
172
173 EXPECT_TRUE(cb_list.might_have_callbacks());
174
175 remover_2_cb.Run();
176 b_cb.Run();
177
178 EXPECT_FALSE(cb_list.might_have_callbacks());
179 }
180
181 TEST(CallbackListTest, AddCallbacksDuringIteration) {
Avi (use Gerrit) 2013/08/23 16:51:12 So we're only supporting the equivalent of NOTIFY_
Cait (Slow) 2013/08/23 18:21:10 Actually, adding support for EXISTING_ONLY was pre
182 TestCallbackList cb_list;
183 Adder a(&cb_list);
184 Listener b;
185 cb_list.RegisterCallback(
186 base::Bind(&Adder::OnAddedEvent, base::Unretained(&a)));
187 cb_list.RegisterCallback(
188 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
189
190 FOR_EACH_CALLBACK(base::Closure, cb_list);
191
192 EXPECT_EQ(1, a.total);
193 EXPECT_EQ(1, b.total);
194 EXPECT_TRUE(a.added);
195
196 FOR_EACH_CALLBACK(base::Closure, cb_list);
197
198 EXPECT_EQ(2, a.total);
199 EXPECT_EQ(2, b.total);
200 }
201
202 TEST(CallbackListTest, ClearCallbacksDuringIteration) {
203 TestCallbackList cb_list;
204 Clearer a(&cb_list);
205 Listener b;
206 cb_list.RegisterCallback(
207 base::Bind(&Clearer::OnClearAndAddEvent, base::Unretained(&a)));
208 cb_list.RegisterCallback(
209 base::Bind(&Listener::OnEvent, base::Unretained(&b)));
210
211 FOR_EACH_CALLBACK(base::Closure, cb_list);
212
213 EXPECT_EQ(1, a.total);
214 EXPECT_EQ(0, b.total);
215 EXPECT_TRUE(a.added);
216 }
217
218 TEST(CallbackListTest, AddNullCallbacks) {
219 TestCallbackList cb_list;
220
221 base::Closure noop = cb_list.RegisterCallback(base::Closure());
222 base::Closure noop2 = cb_list.RegisterCallback(base::Closure());
223
224 // NULL callbacks should not get added.
225 EXPECT_FALSE(cb_list.might_have_callbacks());
226
227 noop.Run();
228 noop2.Run();
229
230 // |noop| and |noop2| should be no-ops.
231 EXPECT_FALSE(cb_list.might_have_callbacks());
232 }
233
234 TEST(CallbackListTest, IteratorOutlivesList) {
235 TestCallbackList* cb_list = new TestCallbackList();
236 ListDestructor destructor(cb_list);
237 cb_list->RegisterCallback(
238 base::Bind(&ListDestructor::OnEvent, base::Unretained(&destructor)));
239 Listener a;
240 cb_list->RegisterCallback(
241 base::Bind(&Listener::OnEvent, base::Unretained(&a)));
242
243 FOR_EACH_CALLBACK(base::Closure, *cb_list);
244
245 // |a| never gets called, as |cb_list| got deleted first.
246 EXPECT_EQ(0, a.total);
247 }
248
249 } // namespace
Avi (use Gerrit) 2013/08/23 16:51:12 What happened to tests of callbacks with parameter
Cait (Slow) 2013/08/23 18:21:10 Done.
250 } // 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