OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "base/mac/libdispatch_task_runner.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/mac/bind_objc_block.h" |
| 9 #include "base/message_loop.h" |
| 10 #include "base/stringprintf.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 class LibDispatchTaskRunnerTest : public testing::Test { |
| 14 public: |
| 15 virtual void SetUp() OVERRIDE { |
| 16 task_runner_ = new base::mac::LibDispatchTaskRunner( |
| 17 "org.chromium.LibDispatchTaskRunnerTest"); |
| 18 } |
| 19 |
| 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, MessageLoop::QuitClosure()); |
| 25 }); |
| 26 message_loop_.Run(); |
| 27 } |
| 28 |
| 29 // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares |
| 30 // them against the recorded values. |
| 31 void VerifyTaskOrder(const char* const expectations[], |
| 32 size_t num_expectations) { |
| 33 size_t actual_size = task_order_.size(); |
| 34 |
| 35 for (size_t i = 0; i < num_expectations; ++i) { |
| 36 if (i >= actual_size) { |
| 37 EXPECT_LT(i, actual_size) << "Expected " << expectations[i]; |
| 38 continue; |
| 39 } |
| 40 |
| 41 EXPECT_EQ(expectations[i], task_order_[i]); |
| 42 } |
| 43 |
| 44 if (actual_size > num_expectations) { |
| 45 EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:"; |
| 46 for (size_t i = num_expectations; i < actual_size; ++i) { |
| 47 EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")"; |
| 48 } |
| 49 } |
| 50 } |
| 51 |
| 52 // The message loop for the test main thread. |
| 53 MessageLoop message_loop_; |
| 54 |
| 55 // The task runner under test. |
| 56 scoped_refptr<base::mac::LibDispatchTaskRunner> task_runner_; |
| 57 |
| 58 // Vector that records data from TaskOrderMarker. |
| 59 std::vector<std::string> task_order_; |
| 60 }; |
| 61 |
| 62 // Scoper that records the beginning and end of a running task. |
| 63 class TaskOrderMarker { |
| 64 public: |
| 65 TaskOrderMarker(LibDispatchTaskRunnerTest* test, const std::string& name) |
| 66 : test_(test), |
| 67 name_(name) { |
| 68 test->task_order_.push_back(std::string("BEGIN ") + name); |
| 69 } |
| 70 ~TaskOrderMarker() { |
| 71 test_->task_order_.push_back(std::string("END ") + name_); |
| 72 } |
| 73 |
| 74 private: |
| 75 LibDispatchTaskRunnerTest* test_; |
| 76 std::string name_; |
| 77 }; |
| 78 |
| 79 void RecordTaskOrder(LibDispatchTaskRunnerTest* test, const std::string& name) { |
| 80 TaskOrderMarker marker(test, name); |
| 81 } |
| 82 |
| 83 // Returns a closure that records the task order. |
| 84 base::Closure BoundRecordTaskOrder(LibDispatchTaskRunnerTest* test, |
| 85 const std::string& name) { |
| 86 return base::Bind(&RecordTaskOrder, base::Unretained(test), name); |
| 87 } |
| 88 |
| 89 TEST_F(LibDispatchTaskRunnerTest, PostTask) { |
| 90 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Basic Task")); |
| 91 DispatchLastTask(); |
| 92 const char* const expectations[] = { |
| 93 "BEGIN Basic Task", |
| 94 "END Basic Task" |
| 95 }; |
| 96 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 97 } |
| 98 |
| 99 TEST_F(LibDispatchTaskRunnerTest, PostTaskWithinTask) { |
| 100 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ |
| 101 TaskOrderMarker marker(this, "Outer"); |
| 102 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Inner")); |
| 103 })); |
| 104 DispatchLastTask(); |
| 105 |
| 106 const char* const expectations[] = { |
| 107 "BEGIN Outer", |
| 108 "END Outer", |
| 109 "BEGIN Inner", |
| 110 "END Inner" |
| 111 }; |
| 112 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 113 } |
| 114 |
| 115 TEST_F(LibDispatchTaskRunnerTest, NoMessageLoop) { |
| 116 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ |
| 117 TaskOrderMarker marker(this, |
| 118 base::StringPrintf("MessageLoop = %p", MessageLoop::current())); |
| 119 })); |
| 120 DispatchLastTask(); |
| 121 |
| 122 const char* const expectations[] = { |
| 123 "BEGIN MessageLoop = 0x0", |
| 124 "END MessageLoop = 0x0" |
| 125 }; |
| 126 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 127 } |
| 128 |
| 129 TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) { |
| 130 dispatch_async(task_runner_->GetDispatchQueue(), ^{ |
| 131 TaskOrderMarker marker(this, "First Block"); |
| 132 task_runner_->PostTask(FROM_HERE, |
| 133 BoundRecordTaskOrder(this, "Second Task")); |
| 134 }); |
| 135 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task")); |
| 136 dispatch_async(task_runner_->GetDispatchQueue(), ^{ |
| 137 TaskOrderMarker marker(this, "Second Block"); |
| 138 }); |
| 139 DispatchLastTask(); |
| 140 |
| 141 const char* const expectations[] = { |
| 142 "BEGIN First Block", |
| 143 "END First Block", |
| 144 "BEGIN First Task", |
| 145 "END First Task", |
| 146 "BEGIN Second Block", |
| 147 "END Second Block", |
| 148 "BEGIN Second Task", |
| 149 "END Second Task", |
| 150 }; |
| 151 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 152 } |
| 153 |
| 154 TEST_F(LibDispatchTaskRunnerTest, NonNestable) { |
| 155 task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ |
| 156 TaskOrderMarker marker(this, "First"); |
| 157 task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{ |
| 158 TaskOrderMarker marker(this, "Third NonNestable"); |
| 159 })); |
| 160 })); |
| 161 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); |
| 162 DispatchLastTask(); |
| 163 |
| 164 const char* const expectations[] = { |
| 165 "BEGIN First", |
| 166 "END First", |
| 167 "BEGIN Second", |
| 168 "END Second", |
| 169 "BEGIN Third NonNestable", |
| 170 "END Third NonNestable" |
| 171 }; |
| 172 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 173 } |
| 174 |
| 175 TEST_F(LibDispatchTaskRunnerTest, PostDelayed) { |
| 176 base::TimeTicks post_time; |
| 177 __block base::TimeTicks run_time; |
| 178 const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50); |
| 179 |
| 180 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First")); |
| 181 post_time = base::TimeTicks::Now(); |
| 182 task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{ |
| 183 TaskOrderMarker marker(this, "Timed"); |
| 184 run_time = base::TimeTicks::Now(); |
| 185 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
| 186 }), delta); |
| 187 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); |
| 188 message_loop_.Run(); |
| 189 |
| 190 const char* const expectations[] = { |
| 191 "BEGIN First", |
| 192 "END First", |
| 193 "BEGIN Second", |
| 194 "END Second", |
| 195 "BEGIN Timed", |
| 196 "END Timed", |
| 197 }; |
| 198 VerifyTaskOrder(expectations, arraysize(expectations)); |
| 199 |
| 200 EXPECT_GE(run_time, post_time + delta); |
| 201 } |
OLD | NEW |