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" | |
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 // * Callback can be run multiple times. | |
awong
2011/11/23 23:41:07
Formatting Nit: I've been using a "-" instead of a
James Hawkins
2011/11/24 00:11:15
Done.
| |
26 // * After Cancel(), Run() completes but has no effect. | |
27 TEST(CancelableCallbackTest, Cancel) { | |
28 int count = 0; | |
29 CancelableCallback cancelable( | |
30 base::Bind(Increment, base::Unretained(&count))); | |
31 | |
32 base::Closure callback = cancelable.callback(); | |
33 callback.Run(); | |
34 EXPECT_EQ(1, count); | |
35 | |
36 callback.Run(); | |
37 EXPECT_EQ(2, count); | |
38 | |
39 cancelable.Cancel(); | |
40 callback.Run(); | |
41 EXPECT_EQ(2, count); | |
42 } | |
43 | |
44 // * Cancel() can be called multiple times. | |
45 // * Cancel() cancels all copies of the wrapped callback. | |
46 TEST(CancelableCallbackTest, MultipleCancel) { | |
47 int count = 0; | |
48 CancelableCallback cancelable( | |
49 base::Bind(Increment, base::Unretained(&count))); | |
50 | |
51 base::Closure callback1 = cancelable.callback(); | |
52 cancelable.Cancel(); | |
53 | |
54 callback1.Run(); | |
55 EXPECT_EQ(0, count); | |
56 | |
57 base::Closure callback2 = cancelable.callback(); | |
58 callback2.Run(); | |
59 EXPECT_EQ(0, count); | |
60 | |
61 base::Closure callback3 = cancelable.callback(); | |
62 cancelable.Cancel(); | |
awong
2011/11/23 23:41:07
Add comment saying this Cancel() should have no ef
James Hawkins
2011/11/24 00:11:15
Done.
| |
63 callback3.Run(); | |
64 EXPECT_EQ(0, count); | |
65 } | |
66 | |
67 // * Destruction of CancelableCallback cancels outstanding callbacks. | |
68 TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { | |
69 int count = 0; | |
70 base::Closure callback; | |
71 | |
72 { | |
73 CancelableCallback cancelable( | |
74 base::Bind(Increment, base::Unretained(&count))); | |
75 | |
76 callback = cancelable.callback(); | |
77 callback.Run(); | |
78 EXPECT_EQ(1, count); | |
79 } | |
80 | |
81 callback.Run(); | |
82 EXPECT_EQ(1, count); | |
83 } | |
84 | |
85 // * Cancel drops wrapped callback (and, implicitly, its bound arguments). | |
86 TEST(CancelableCallbackTest, CancelDropsCallback) { | |
87 scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted; | |
88 EXPECT_TRUE(ref_counted->HasOneRef()); | |
89 | |
90 CancelableCallback cancelable(base::Bind(RefCountedParam, ref_counted)); | |
91 EXPECT_FALSE(cancelable.is_null()); | |
92 EXPECT_TRUE(ref_counted.get()); | |
93 EXPECT_FALSE(ref_counted->HasOneRef()); | |
94 | |
95 // There is only one reference to |ref_counted| after the Cancel(). | |
96 cancelable.Cancel(); | |
97 EXPECT_TRUE(cancelable.is_null()); | |
98 EXPECT_TRUE(ref_counted.get()); | |
99 EXPECT_TRUE(ref_counted->HasOneRef()); | |
100 } | |
101 | |
102 // * Reset() replaces the existing wrapped callback with a new callback. | |
103 // * Reset() deactivates outstanding callbacks. | |
104 TEST(CancelableCallbackTest, Reset) { | |
105 int count = 0; | |
106 CancelableCallback cancelable( | |
107 base::Bind(Increment, base::Unretained(&count))); | |
108 | |
109 base::Closure callback = cancelable.callback(); | |
110 callback.Run(); | |
111 EXPECT_EQ(1, count); | |
112 | |
113 callback.Run(); | |
114 EXPECT_EQ(2, count); | |
115 | |
116 cancelable.Reset( | |
117 base::Bind(IncrementBy, base::Unretained(&count), 3)); | |
118 EXPECT_FALSE(cancelable.is_null()); | |
119 | |
120 // The stale copy of the cancelable callback is non-null. | |
121 ASSERT_FALSE(callback.is_null()); | |
122 | |
123 // The stale copy of the cancelable callback is no longer active. | |
124 callback.Run(); | |
125 EXPECT_EQ(2, count); | |
126 | |
127 base::Closure callback2 = cancelable.callback(); | |
128 ASSERT_FALSE(callback2.is_null()); | |
129 | |
130 callback2.Run(); | |
131 EXPECT_EQ(5, count); | |
132 } | |
133 | |
134 // * Cancel() transforms the CancelableCallback into null. | |
135 TEST(CancelableCallbackTest, IsNull) { | |
136 CancelableCallback cancelable; | |
137 EXPECT_TRUE(cancelable.is_null()); | |
138 | |
139 int count = 0; | |
140 cancelable.Reset(base::Bind(Increment, | |
141 base::Unretained(&count))); | |
142 EXPECT_FALSE(cancelable.is_null()); | |
143 | |
144 cancelable.Cancel(); | |
145 EXPECT_TRUE(cancelable.is_null()); | |
146 } | |
147 | |
148 // * Callbacks posted to a MessageLoop can be cancelled. | |
149 TEST(CancelableCallbackTest, PostTask) { | |
150 MessageLoop loop(MessageLoop::TYPE_DEFAULT); | |
151 | |
152 int count = 0; | |
153 CancelableCallback cancelable(base::Bind(Increment, | |
154 base::Unretained(&count))); | |
155 | |
156 MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); | |
157 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
158 MessageLoop::current()->Run(); | |
159 | |
160 EXPECT_EQ(1, count); | |
161 | |
162 MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); | |
163 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
164 | |
165 // Cancel before running the message loop. | |
166 cancelable.Cancel(); | |
167 MessageLoop::current()->Run(); | |
168 | |
169 // Callback never ran due to cancellation; count is the same. | |
170 EXPECT_EQ(1, count); | |
171 } | |
172 | |
173 } // namespace | |
174 } // namespace base | |
OLD | NEW |