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.
5 #include "base/callback_registry.h"
7 #include "base/basictypes.h"
9 #include "base/bind_helpers.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "testing/gtest/include/gtest/gtest.h"
18 Listener() : total_(0), scaler_(1) {}
19 explicit Listener(int scaler
) : total_(0), scaler_(scaler
) {}
20 void IncrementTotal() { total_
++; }
21 void IncrementByMultipleOfScaler(const int& x
) { total_
+= x
* scaler_
; }
27 DISALLOW_COPY_AND_ASSIGN(Listener
);
32 Remover() : total_(0) {}
33 void IncrementTotalAndRemove() {
35 removal_subscription_
.reset();
37 void SetSubscriptionToRemove(
38 scoped_ptr
<CallbackRegistry
<void>::Subscription
> sub
) {
39 removal_subscription_
= sub
.Pass();
45 scoped_ptr
<CallbackRegistry
<void>::Subscription
> removal_subscription_
;
46 DISALLOW_COPY_AND_ASSIGN(Remover
);
51 explicit Adder(CallbackRegistry
<void>* cb_reg
)
59 cb_reg_
->Add(Bind(&Adder::IncrementTotal
, Unretained(this)));
62 void IncrementTotal() { total_
++; }
68 CallbackRegistry
<void>* cb_reg_
;
69 scoped_ptr
<CallbackRegistry
<void>::Subscription
> subscription_
;
70 DISALLOW_COPY_AND_ASSIGN(Adder
);
73 // Sanity check that closures added to the list will be run, and those removed
74 // from the list will not be run.
75 TEST(CallbackRegistryTest
, BasicTest
) {
76 CallbackRegistry
<void> cb_reg
;
79 scoped_ptr
<CallbackRegistry
<void>::Subscription
> a_subscription
=
80 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&a
)));
81 scoped_ptr
<CallbackRegistry
<void>::Subscription
> b_subscription
=
82 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&b
)));
84 EXPECT_TRUE(a_subscription
.get());
85 EXPECT_TRUE(b_subscription
.get());
89 EXPECT_EQ(1, a
.total_
);
90 EXPECT_EQ(1, b
.total_
);
92 b_subscription
.reset();
94 scoped_ptr
<CallbackRegistry
<void>::Subscription
> c_subscription
=
95 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&c
)));
99 EXPECT_EQ(2, a
.total_
);
100 EXPECT_EQ(1, b
.total_
);
101 EXPECT_EQ(1, c
.total_
);
103 a_subscription
.reset();
104 b_subscription
.reset();
105 c_subscription
.reset();
108 // Sanity check that callbacks with details added to the list will be run, with
109 // the correct details, and those removed from the list will not be run.
110 TEST(CallbackRegistryTest
, BasicTestWithParams
) {
111 CallbackRegistry
<int> cb_reg
;
112 Listener
a(1), b(-1), c(1);
114 scoped_ptr
<CallbackRegistry
<int>::Subscription
> a_subscription
=
115 cb_reg
.Add(Bind(&Listener::IncrementByMultipleOfScaler
, Unretained(&a
)));
116 scoped_ptr
<CallbackRegistry
<int>::Subscription
> b_subscription
=
117 cb_reg
.Add(Bind(&Listener::IncrementByMultipleOfScaler
, Unretained(&b
)));
119 EXPECT_TRUE(a_subscription
.get());
120 EXPECT_TRUE(b_subscription
.get());
124 EXPECT_EQ(10, a
.total_
);
125 EXPECT_EQ(-10, b
.total_
);
127 b_subscription
.reset();
129 scoped_ptr
<CallbackRegistry
<int>::Subscription
> c_subscription
=
130 cb_reg
.Add(Bind(&Listener::IncrementByMultipleOfScaler
, Unretained(&c
)));
134 EXPECT_EQ(20, a
.total_
);
135 EXPECT_EQ(-10, b
.total_
);
136 EXPECT_EQ(10, c
.total_
);
138 a_subscription
.reset();
139 b_subscription
.reset();
140 c_subscription
.reset();
143 // Test the a callback can remove itself or a different callback from the list
144 // during iteration without invalidating the iterator.
145 TEST(CallbackRegistryTest
, RemoveCallbacksDuringIteration
) {
146 CallbackRegistry
<void> cb_reg
;
148 Remover remover_1
, remover_2
;
150 scoped_ptr
<CallbackRegistry
<void>::Subscription
> remover_1_subscription
=
151 cb_reg
.Add(Bind(&Remover::IncrementTotalAndRemove
,
152 Unretained(&remover_1
)));
153 scoped_ptr
<CallbackRegistry
<void>::Subscription
> remover_2_subscription
=
154 cb_reg
.Add(Bind(&Remover::IncrementTotalAndRemove
,
155 Unretained(&remover_2
)));
156 scoped_ptr
<CallbackRegistry
<void>::Subscription
> a_subscription
=
157 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&a
)));
158 scoped_ptr
<CallbackRegistry
<void>::Subscription
> b_subscription
=
159 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&b
)));
161 // |remover_1| will remove itself.
162 remover_1
.SetSubscriptionToRemove(remover_1_subscription
.Pass());
163 // |remover_2| will remove a.
164 remover_2
.SetSubscriptionToRemove(a_subscription
.Pass());
168 // |remover_1| runs once (and removes itself), |remover_2| runs once (and
169 // removes a), |a| never runs, and |b| runs once.
170 EXPECT_EQ(1, remover_1
.total_
);
171 EXPECT_EQ(1, remover_2
.total_
);
172 EXPECT_EQ(0, a
.total_
);
173 EXPECT_EQ(1, b
.total_
);
177 // Only |remover_2| and |b| run this time.
178 EXPECT_EQ(1, remover_1
.total_
);
179 EXPECT_EQ(2, remover_2
.total_
);
180 EXPECT_EQ(0, a
.total_
);
181 EXPECT_EQ(2, b
.total_
);
184 // Test that a callback can add another callback to the list durning iteration
185 // without invalidating the iterator. The newly added callback should be run on
186 // the current iteration as will all other callbacks in the list.
187 TEST(CallbackRegistryTest
, AddCallbacksDuringIteration
) {
188 CallbackRegistry
<void> cb_reg
;
191 scoped_ptr
<CallbackRegistry
<void>::Subscription
> a_subscription
=
192 cb_reg
.Add(Bind(&Adder::AddCallback
, Unretained(&a
)));
193 scoped_ptr
<CallbackRegistry
<void>::Subscription
> b_subscription
=
194 cb_reg
.Add(Bind(&Listener::IncrementTotal
, Unretained(&b
)));
198 EXPECT_EQ(1, a
.total_
);
199 EXPECT_EQ(1, b
.total_
);
200 EXPECT_TRUE(a
.added_
);
204 EXPECT_EQ(2, a
.total_
);
205 EXPECT_EQ(2, b
.total_
);
208 // Sanity check: notifying an empty list is a no-op.
209 TEST(CallbackRegistryTest
, EmptyList
) {
210 CallbackRegistry
<void> cb_reg
;