OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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/bind.h" | |
6 #include "base/bind_helpers.h" | |
7 #include "base/cancelable_callback.h" | |
willchan no longer on Chromium
2011/11/24 00:44:30
goes first
James Hawkins
2011/11/24 02:47:48
I read (on either c-style or chromium-dev) that th
awong
2011/11/24 02:56:53
Will has caught me on this previously, but it does
| |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/message_loop.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 | |
12 namespace base { | |
13 namespace { | |
14 | |
15 class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> { | |
16 private: | |
17 friend class RefCountedThreadSafe<TestRefCounted>; | |
18 ~TestRefCounted() {}; | |
19 }; | |
20 | |
21 void Increment(int* count) { (*count)++; } | |
22 void IncrementBy(int* count, int n) { (*count) += n; } | |
23 void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {} | |
24 | |
25 // Cancel(). | |
26 // - Callback can be run multiple times. | |
27 // - After Cancel(), Run() completes but has no effect. | |
28 TEST(CancelableCallbackTest, Cancel) { | |
29 int count = 0; | |
30 CancelableCallback cancelable( | |
31 base::Bind(Increment, base::Unretained(&count))); | |
32 | |
33 base::Closure callback = cancelable.callback(); | |
34 callback.Run(); | |
35 EXPECT_EQ(1, count); | |
36 | |
37 callback.Run(); | |
38 EXPECT_EQ(2, count); | |
39 | |
40 cancelable.Cancel(); | |
41 callback.Run(); | |
42 EXPECT_EQ(2, count); | |
43 } | |
44 | |
45 // Cancel() called multiple times. | |
46 // - Cancel() cancels all copies of the wrapped callback. | |
47 TEST(CancelableCallbackTest, MultipleCancel) { | |
48 int count = 0; | |
49 CancelableCallback cancelable( | |
50 base::Bind(Increment, base::Unretained(&count))); | |
willchan no longer on Chromium
2011/11/24 00:44:30
I always forget, doesn't Increment need & before i
awong
2011/11/24 01:00:03
I had thought it did, but I have again learned tha
James Hawkins
2011/11/24 02:47:48
Hmm, I was really sure I've seen this fail to comp
awong
2011/11/24 02:56:53
I *know* I went through and fixed a bunch that fai
| |
51 | |
52 base::Closure callback1 = cancelable.callback(); | |
53 cancelable.Cancel(); | |
54 | |
55 callback1.Run(); | |
56 EXPECT_EQ(0, count); | |
57 | |
58 base::Closure callback2 = cancelable.callback(); | |
59 callback2.Run(); | |
60 EXPECT_EQ(0, count); | |
61 | |
62 // Cancel() should have no effect, but callback() is still runnable. | |
63 base::Closure callback3 = cancelable.callback(); | |
64 cancelable.Cancel(); | |
65 callback3.Run(); | |
66 EXPECT_EQ(0, count); | |
67 } | |
68 | |
69 // CancelableCallback destroyed before callback is run. | |
70 // - Destruction of CancelableCallback cancels outstanding callbacks. | |
71 TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { | |
72 int count = 0; | |
73 base::Closure callback; | |
74 | |
75 { | |
76 CancelableCallback cancelable( | |
77 base::Bind(Increment, base::Unretained(&count))); | |
78 | |
79 callback = cancelable.callback(); | |
80 callback.Run(); | |
81 EXPECT_EQ(1, count); | |
82 } | |
83 | |
84 callback.Run(); | |
85 EXPECT_EQ(1, count); | |
86 } | |
87 | |
88 // Cancel() called on bound closure with a RefCounted parameter. | |
89 // - Cancel drops wrapped callback (and, implicitly, its bound arguments). | |
90 TEST(CancelableCallbackTest, CancelDropsCallback) { | |
91 scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted; | |
92 EXPECT_TRUE(ref_counted->HasOneRef()); | |
93 | |
94 CancelableCallback cancelable(base::Bind(RefCountedParam, ref_counted)); | |
95 EXPECT_FALSE(cancelable.IsCancelled()); | |
96 EXPECT_TRUE(ref_counted.get()); | |
97 EXPECT_FALSE(ref_counted->HasOneRef()); | |
98 | |
99 // There is only one reference to |ref_counted| after the Cancel(). | |
100 cancelable.Cancel(); | |
101 EXPECT_TRUE(cancelable.IsCancelled()); | |
102 EXPECT_TRUE(ref_counted.get()); | |
103 EXPECT_TRUE(ref_counted->HasOneRef()); | |
104 } | |
105 | |
106 // Reset(). | |
107 // - Reset() replaces the existing wrapped callback with a new callback. | |
108 // - Reset() deactivates outstanding callbacks. | |
109 TEST(CancelableCallbackTest, Reset) { | |
110 int count = 0; | |
111 CancelableCallback cancelable( | |
112 base::Bind(Increment, base::Unretained(&count))); | |
113 | |
114 base::Closure callback = cancelable.callback(); | |
115 callback.Run(); | |
116 EXPECT_EQ(1, count); | |
117 | |
118 callback.Run(); | |
119 EXPECT_EQ(2, count); | |
120 | |
121 cancelable.Reset( | |
122 base::Bind(IncrementBy, base::Unretained(&count), 3)); | |
123 EXPECT_FALSE(cancelable.IsCancelled()); | |
124 | |
125 // The stale copy of the cancelable callback is non-null. | |
126 ASSERT_FALSE(callback.is_null()); | |
127 | |
128 // The stale copy of the cancelable callback is no longer active. | |
129 callback.Run(); | |
130 EXPECT_EQ(2, count); | |
131 | |
132 base::Closure callback2 = cancelable.callback(); | |
133 ASSERT_FALSE(callback2.is_null()); | |
134 | |
135 callback2.Run(); | |
136 EXPECT_EQ(5, count); | |
137 } | |
138 | |
139 // IsCanceled(). | |
140 // - Cancel() transforms the CancelableCallback into a cancelled state. | |
141 TEST(CancelableCallbackTest, IsNull) { | |
142 CancelableCallback cancelable; | |
143 EXPECT_TRUE(cancelable.IsCancelled()); | |
144 | |
145 int count = 0; | |
146 cancelable.Reset(base::Bind(Increment, | |
147 base::Unretained(&count))); | |
148 EXPECT_FALSE(cancelable.IsCancelled()); | |
149 | |
150 cancelable.Cancel(); | |
151 EXPECT_TRUE(cancelable.IsCancelled()); | |
152 } | |
153 | |
154 // CancelableCallback posted to a MessageLoop with PostTask. | |
155 // - Callbacks posted to a MessageLoop can be cancelled. | |
156 TEST(CancelableCallbackTest, PostTask) { | |
157 MessageLoop loop(MessageLoop::TYPE_DEFAULT); | |
158 | |
159 int count = 0; | |
160 CancelableCallback cancelable(base::Bind(Increment, | |
161 base::Unretained(&count))); | |
162 | |
163 MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); | |
164 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
165 MessageLoop::current()->Run(); | |
166 | |
167 EXPECT_EQ(1, count); | |
168 | |
169 MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); | |
170 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
171 | |
172 // Cancel before running the message loop. | |
173 cancelable.Cancel(); | |
174 MessageLoop::current()->Run(); | |
175 | |
176 // Callback never ran due to cancellation; count is the same. | |
177 EXPECT_EQ(1, count); | |
178 } | |
179 | |
180 } // namespace | |
181 } // namespace base | |
OLD | NEW |