OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/mac/libdispatch_task_runner.h" | 5 #include "base/mac/libdispatch_task_runner.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/mac/bind_objc_block.h" | 8 #include "base/mac/bind_objc_block.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
12 | 12 |
13 class LibDispatchTaskRunnerTest : public testing::Test { | 13 class LibDispatchTaskRunnerTest : public testing::Test { |
14 public: | 14 public: |
15 virtual void SetUp() OVERRIDE { | 15 virtual void SetUp() OVERRIDE { |
16 task_runner_ = new base::mac::LibDispatchTaskRunner( | 16 task_runner_ = new base::mac::LibDispatchTaskRunner( |
17 "org.chromium.LibDispatchTaskRunnerTest"); | 17 "org.chromium.LibDispatchTaskRunnerTest"); |
18 } | 18 } |
19 | 19 |
20 // DispatchLastTask is used to run the main test thread's MessageLoop until | 20 // DispatchLastTask is used to run the main test thread's MessageLoop until |
21 // all non-delayed tasks are run on the LibDispatchTaskRunner. | 21 // all non-delayed tasks are run on the LibDispatchTaskRunner. |
22 void DispatchLastTask() { | 22 void DispatchLastTask() { |
23 dispatch_async(task_runner_->GetDispatchQueue(), ^{ | 23 dispatch_async(task_runner_->GetDispatchQueue(), ^{ |
24 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 24 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
25 }); | 25 }); |
26 message_loop_.Run(); | 26 message_loop_.Run(); |
| 27 task_runner_->Shutdown(); |
27 } | 28 } |
28 | 29 |
29 // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares | 30 // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares |
30 // them against the recorded values. | 31 // them against the recorded values. |
31 void VerifyTaskOrder(const char* const expectations[], | 32 void VerifyTaskOrder(const char* const expectations[], |
32 size_t num_expectations) { | 33 size_t num_expectations) { |
33 size_t actual_size = task_order_.size(); | 34 size_t actual_size = task_order_.size(); |
34 | 35 |
35 for (size_t i = 0; i < num_expectations; ++i) { | 36 for (size_t i = 0; i < num_expectations; ++i) { |
36 if (i >= actual_size) { | 37 if (i >= actual_size) { |
37 EXPECT_LT(i, actual_size) << "Expected " << expectations[i]; | 38 EXPECT_LE(i, actual_size) << "Expected " << expectations[i]; |
38 continue; | 39 continue; |
39 } | 40 } |
40 | 41 |
41 EXPECT_EQ(expectations[i], task_order_[i]); | 42 EXPECT_EQ(expectations[i], task_order_[i]); |
42 } | 43 } |
43 | 44 |
44 if (actual_size > num_expectations) { | 45 if (actual_size > num_expectations) { |
45 EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:"; | 46 EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:"; |
46 for (size_t i = num_expectations; i < actual_size; ++i) { | 47 for (size_t i = num_expectations; i < actual_size; ++i) { |
47 EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")"; | 48 EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")"; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 })); | 120 })); |
120 DispatchLastTask(); | 121 DispatchLastTask(); |
121 | 122 |
122 const char* const expectations[] = { | 123 const char* const expectations[] = { |
123 "BEGIN MessageLoop = 0x0", | 124 "BEGIN MessageLoop = 0x0", |
124 "END MessageLoop = 0x0" | 125 "END MessageLoop = 0x0" |
125 }; | 126 }; |
126 VerifyTaskOrder(expectations, arraysize(expectations)); | 127 VerifyTaskOrder(expectations, arraysize(expectations)); |
127 } | 128 } |
128 | 129 |
129 // This test is flaky, see http://crbug.com/165117. | 130 TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) { |
130 TEST_F(LibDispatchTaskRunnerTest, FLAKY_DispatchAndPostTasks) { | |
131 dispatch_async(task_runner_->GetDispatchQueue(), ^{ | 131 dispatch_async(task_runner_->GetDispatchQueue(), ^{ |
132 TaskOrderMarker marker(this, "First Block"); | 132 TaskOrderMarker marker(this, "First Block"); |
133 task_runner_->PostTask(FROM_HERE, | |
134 BoundRecordTaskOrder(this, "Second Task")); | |
135 }); | 133 }); |
136 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task")); | 134 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task")); |
137 dispatch_async(task_runner_->GetDispatchQueue(), ^{ | 135 dispatch_async(task_runner_->GetDispatchQueue(), ^{ |
138 TaskOrderMarker marker(this, "Second Block"); | 136 TaskOrderMarker marker(this, "Second Block"); |
139 }); | 137 }); |
| 138 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second Task")); |
140 DispatchLastTask(); | 139 DispatchLastTask(); |
141 | 140 |
142 const char* const expectations[] = { | 141 const char* const expectations[] = { |
143 "BEGIN First Block", | 142 "BEGIN First Block", |
144 "END First Block", | 143 "END First Block", |
145 "BEGIN First Task", | 144 "BEGIN First Task", |
146 "END First Task", | 145 "END First Task", |
147 "BEGIN Second Block", | 146 "BEGIN Second Block", |
148 "END Second Block", | 147 "END Second Block", |
149 "BEGIN Second Task", | 148 "BEGIN Second Task", |
150 "END Second Task", | 149 "END Second Task", |
151 }; | 150 }; |
152 VerifyTaskOrder(expectations, arraysize(expectations)); | 151 VerifyTaskOrder(expectations, arraysize(expectations)); |
153 } | 152 } |
154 | 153 |
155 // This test is flaky, see http://crbug.com/165118. | 154 TEST_F(LibDispatchTaskRunnerTest, NonNestable) { |
156 TEST_F(LibDispatchTaskRunnerTest, FLAKY_NonNestable) { | |
157 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ | 155 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ |
158 TaskOrderMarker marker(this, "First"); | 156 TaskOrderMarker marker(this, "First"); |
159 task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{ | 157 task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{ |
160 TaskOrderMarker marker(this, "Third NonNestable"); | 158 TaskOrderMarker marker(this, "Second NonNestable"); |
| 159 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
161 })); | 160 })); |
162 })); | 161 })); |
163 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); | 162 message_loop_.Run(); |
164 DispatchLastTask(); | 163 task_runner_->Shutdown(); |
165 | 164 |
166 const char* const expectations[] = { | 165 const char* const expectations[] = { |
167 "BEGIN First", | 166 "BEGIN First", |
168 "END First", | 167 "END First", |
169 "BEGIN Second", | 168 "BEGIN Second NonNestable", |
170 "END Second", | 169 "END Second NonNestable" |
171 "BEGIN Third NonNestable", | |
172 "END Third NonNestable" | |
173 }; | 170 }; |
174 VerifyTaskOrder(expectations, arraysize(expectations)); | 171 VerifyTaskOrder(expectations, arraysize(expectations)); |
175 } | 172 } |
176 | 173 |
177 TEST_F(LibDispatchTaskRunnerTest, PostDelayed) { | 174 TEST_F(LibDispatchTaskRunnerTest, PostDelayed) { |
178 base::TimeTicks post_time; | 175 base::TimeTicks post_time; |
179 __block base::TimeTicks run_time; | 176 __block base::TimeTicks run_time; |
180 const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50); | 177 const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50); |
181 | 178 |
182 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First")); | 179 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First")); |
183 post_time = base::TimeTicks::Now(); | 180 post_time = base::TimeTicks::Now(); |
184 task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{ | 181 task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{ |
185 TaskOrderMarker marker(this, "Timed"); | 182 TaskOrderMarker marker(this, "Timed"); |
186 run_time = base::TimeTicks::Now(); | 183 run_time = base::TimeTicks::Now(); |
187 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 184 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
188 }), delta); | 185 }), delta); |
189 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); | 186 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); |
190 message_loop_.Run(); | 187 message_loop_.Run(); |
| 188 task_runner_->Shutdown(); |
191 | 189 |
192 const char* const expectations[] = { | 190 const char* const expectations[] = { |
193 "BEGIN First", | 191 "BEGIN First", |
194 "END First", | 192 "END First", |
195 "BEGIN Second", | 193 "BEGIN Second", |
196 "END Second", | 194 "END Second", |
197 "BEGIN Timed", | 195 "BEGIN Timed", |
198 "END Timed", | 196 "END Timed", |
199 }; | 197 }; |
200 VerifyTaskOrder(expectations, arraysize(expectations)); | 198 VerifyTaskOrder(expectations, arraysize(expectations)); |
201 | 199 |
202 EXPECT_GE(run_time, post_time + delta); | 200 EXPECT_GE(run_time, post_time + delta); |
203 } | 201 } |
| 202 |
| 203 TEST_F(LibDispatchTaskRunnerTest, PostAfterShutdown) { |
| 204 EXPECT_TRUE(task_runner_->PostTask(FROM_HERE, |
| 205 BoundRecordTaskOrder(this, "First"))); |
| 206 EXPECT_TRUE(task_runner_->PostTask(FROM_HERE, |
| 207 BoundRecordTaskOrder(this, "Second"))); |
| 208 task_runner_->Shutdown(); |
| 209 EXPECT_FALSE(task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ |
| 210 TaskOrderMarker marker(this, "Not Run"); |
| 211 ADD_FAILURE() << "Should not run a task after Shutdown"; |
| 212 }))); |
| 213 |
| 214 const char* const expectations[] = { |
| 215 "BEGIN First", |
| 216 "END First", |
| 217 "BEGIN Second", |
| 218 "END Second" |
| 219 }; |
| 220 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 221 } |
OLD | NEW |