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"
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 {
15 virtual 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());
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];
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 {
67 TaskOrderMarker(LibDispatchTaskRunnerTest* test, const std::string& name)
70 test->task_order_.push_back(std::string("BEGIN ") + name);
73 test_->task_order_.push_back(std::string("END ") + name_);
77 LibDispatchTaskRunnerTest* test_;
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"));
94 const char* const expectations[] = {
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"));
108 const char* const expectations[] = {
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()));
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"));
142 const char* const expectations[] = {
147 "BEGIN Second Block",
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());
165 task_runner_->Shutdown();
167 const char* const expectations[] = {
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());
189 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second"));
191 task_runner_->Shutdown();
193 const char* const expectations[] = {
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";
217 const char* const expectations[] = {
223 VerifyTaskOrder(expectations, arraysize(expectations));