Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / base / mac / libdispatch_task_runner_unittest.cc
blob49b0c9ae9d7d1f3db3b66d782e97dfdaeb244be1
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
3 // found in the LICENSE file.
5 #include "base/mac/libdispatch_task_runner.h"
7 #include "base/bind.h"
8 #include "base/mac/bind_objc_block.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/stringprintf.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 class LibDispatchTaskRunnerTest : public testing::Test {
14 public:
15 void SetUp() override {
16 task_runner_ = new base::mac::LibDispatchTaskRunner(
17 "org.chromium.LibDispatchTaskRunnerTest");
20 // DispatchLastTask is used to run the main test thread's MessageLoop until
21 // all non-delayed tasks are run on the LibDispatchTaskRunner.
22 void DispatchLastTask() {
23 dispatch_async(task_runner_->GetDispatchQueue(), ^{
24 message_loop_.PostTask(FROM_HERE,
25 base::MessageLoop::QuitWhenIdleClosure());
26 });
27 message_loop_.Run();
28 task_runner_->Shutdown();
31 // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares
32 // them against the recorded values.
33 void VerifyTaskOrder(const char* const expectations[],
34 size_t num_expectations) {
35 size_t actual_size = task_order_.size();
37 for (size_t i = 0; i < num_expectations; ++i) {
38 if (i >= actual_size) {
39 EXPECT_LE(i, actual_size) << "Expected " << expectations[i];
40 continue;
43 EXPECT_EQ(expectations[i], task_order_[i]);
46 if (actual_size > num_expectations) {
47 EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:";
48 for (size_t i = num_expectations; i < actual_size; ++i) {
49 EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")";
54 // The message loop for the test main thread.
55 base::MessageLoop message_loop_;
57 // The task runner under test.
58 scoped_refptr<base::mac::LibDispatchTaskRunner> task_runner_;
60 // Vector that records data from TaskOrderMarker.
61 std::vector<std::string> task_order_;
64 // Scoper that records the beginning and end of a running task.
65 class TaskOrderMarker {
66 public:
67 TaskOrderMarker(LibDispatchTaskRunnerTest* test, const std::string& name)
68 : test_(test),
69 name_(name) {
70 test->task_order_.push_back(std::string("BEGIN ") + name);
72 ~TaskOrderMarker() {
73 test_->task_order_.push_back(std::string("END ") + name_);
76 private:
77 LibDispatchTaskRunnerTest* test_;
78 std::string name_;
81 void RecordTaskOrder(LibDispatchTaskRunnerTest* test, const std::string& name) {
82 TaskOrderMarker marker(test, name);
85 // Returns a closure that records the task order.
86 base::Closure BoundRecordTaskOrder(LibDispatchTaskRunnerTest* test,
87 const std::string& name) {
88 return base::Bind(&RecordTaskOrder, base::Unretained(test), name);
91 TEST_F(LibDispatchTaskRunnerTest, PostTask) {
92 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Basic Task"));
93 DispatchLastTask();
94 const char* const expectations[] = {
95 "BEGIN Basic Task",
96 "END Basic Task"
98 VerifyTaskOrder(expectations, arraysize(expectations));
101 TEST_F(LibDispatchTaskRunnerTest, PostTaskWithinTask) {
102 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
103 TaskOrderMarker marker(this, "Outer");
104 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Inner"));
105 }));
106 DispatchLastTask();
108 const char* const expectations[] = {
109 "BEGIN Outer",
110 "END Outer",
111 "BEGIN Inner",
112 "END Inner"
114 VerifyTaskOrder(expectations, arraysize(expectations));
117 TEST_F(LibDispatchTaskRunnerTest, NoMessageLoop) {
118 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
119 TaskOrderMarker marker(this,
120 base::StringPrintf("MessageLoop = %p", base::MessageLoop::current()));
121 }));
122 DispatchLastTask();
124 const char* const expectations[] = {
125 "BEGIN MessageLoop = 0x0",
126 "END MessageLoop = 0x0"
128 VerifyTaskOrder(expectations, arraysize(expectations));
131 TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) {
132 dispatch_async(task_runner_->GetDispatchQueue(), ^{
133 TaskOrderMarker marker(this, "First Block");
135 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task"));
136 dispatch_async(task_runner_->GetDispatchQueue(), ^{
137 TaskOrderMarker marker(this, "Second Block");
139 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second Task"));
140 DispatchLastTask();
142 const char* const expectations[] = {
143 "BEGIN First Block",
144 "END First Block",
145 "BEGIN First Task",
146 "END First Task",
147 "BEGIN Second Block",
148 "END Second Block",
149 "BEGIN Second Task",
150 "END Second Task",
152 VerifyTaskOrder(expectations, arraysize(expectations));
155 TEST_F(LibDispatchTaskRunnerTest, NonNestable) {
156 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
157 TaskOrderMarker marker(this, "First");
158 task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{
159 TaskOrderMarker marker(this, "Second NonNestable");
160 message_loop_.PostTask(FROM_HERE,
161 base::MessageLoop::QuitWhenIdleClosure());
162 }));
163 }));
164 message_loop_.Run();
165 task_runner_->Shutdown();
167 const char* const expectations[] = {
168 "BEGIN First",
169 "END First",
170 "BEGIN Second NonNestable",
171 "END Second NonNestable"
173 VerifyTaskOrder(expectations, arraysize(expectations));
176 TEST_F(LibDispatchTaskRunnerTest, PostDelayed) {
177 base::TimeTicks post_time;
178 __block base::TimeTicks run_time;
179 const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50);
181 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First"));
182 post_time = base::TimeTicks::Now();
183 task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{
184 TaskOrderMarker marker(this, "Timed");
185 run_time = base::TimeTicks::Now();
186 message_loop_.PostTask(FROM_HERE,
187 base::MessageLoop::QuitWhenIdleClosure());
188 }), delta);
189 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second"));
190 message_loop_.Run();
191 task_runner_->Shutdown();
193 const char* const expectations[] = {
194 "BEGIN First",
195 "END First",
196 "BEGIN Second",
197 "END Second",
198 "BEGIN Timed",
199 "END Timed",
201 VerifyTaskOrder(expectations, arraysize(expectations));
203 EXPECT_GE(run_time, post_time + delta);
206 TEST_F(LibDispatchTaskRunnerTest, PostAfterShutdown) {
207 EXPECT_TRUE(task_runner_->PostTask(FROM_HERE,
208 BoundRecordTaskOrder(this, "First")));
209 EXPECT_TRUE(task_runner_->PostTask(FROM_HERE,
210 BoundRecordTaskOrder(this, "Second")));
211 task_runner_->Shutdown();
212 EXPECT_FALSE(task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
213 TaskOrderMarker marker(this, "Not Run");
214 ADD_FAILURE() << "Should not run a task after Shutdown";
215 })));
217 const char* const expectations[] = {
218 "BEGIN First",
219 "END First",
220 "BEGIN Second",
221 "END Second"
223 VerifyTaskOrder(expectations, arraysize(expectations));