OLD | NEW |
---|---|
(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 | |
OLD | NEW |