| 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/message_loop.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 class LibDispatchTaskRunnerTest : public testing::Test { | |
| 14 public: | |
| 15 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, | |
| 25 base::MessageLoop::QuitWhenIdleClosure()); | |
| 26 }); | |
| 27 message_loop_.Run(); | |
| 28 task_runner_->Shutdown(); | |
| 29 } | |
| 30 | |
| 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(); | |
| 36 | |
| 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; | |
| 41 } | |
| 42 | |
| 43 EXPECT_EQ(expectations[i], task_order_[i]); | |
| 44 } | |
| 45 | |
| 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 << ")"; | |
| 50 } | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 // The message loop for the test main thread. | |
| 55 base::MessageLoop message_loop_; | |
| 56 | |
| 57 // The task runner under test. | |
| 58 scoped_refptr<base::mac::LibDispatchTaskRunner> task_runner_; | |
| 59 | |
| 60 // Vector that records data from TaskOrderMarker. | |
| 61 std::vector<std::string> task_order_; | |
| 62 }; | |
| 63 | |
| 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); | |
| 71 } | |
| 72 ~TaskOrderMarker() { | |
| 73 test_->task_order_.push_back(std::string("END ") + name_); | |
| 74 } | |
| 75 | |
| 76 private: | |
| 77 LibDispatchTaskRunnerTest* test_; | |
| 78 std::string name_; | |
| 79 }; | |
| 80 | |
| 81 void RecordTaskOrder(LibDispatchTaskRunnerTest* test, const std::string& name) { | |
| 82 TaskOrderMarker marker(test, name); | |
| 83 } | |
| 84 | |
| 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); | |
| 89 } | |
| 90 | |
| 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" | |
| 97 }; | |
| 98 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 99 } | |
| 100 | |
| 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(); | |
| 107 | |
| 108 const char* const expectations[] = { | |
| 109 "BEGIN Outer", | |
| 110 "END Outer", | |
| 111 "BEGIN Inner", | |
| 112 "END Inner" | |
| 113 }; | |
| 114 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 115 } | |
| 116 | |
| 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(); | |
| 123 | |
| 124 const char* const expectations[] = { | |
| 125 "BEGIN MessageLoop = 0x0", | |
| 126 "END MessageLoop = 0x0" | |
| 127 }; | |
| 128 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 129 } | |
| 130 | |
| 131 TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) { | |
| 132 dispatch_async(task_runner_->GetDispatchQueue(), ^{ | |
| 133 TaskOrderMarker marker(this, "First Block"); | |
| 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 task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second Task")); | |
| 140 DispatchLastTask(); | |
| 141 | |
| 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", | |
| 151 }; | |
| 152 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 153 } | |
| 154 | |
| 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(); | |
| 166 | |
| 167 const char* const expectations[] = { | |
| 168 "BEGIN First", | |
| 169 "END First", | |
| 170 "BEGIN Second NonNestable", | |
| 171 "END Second NonNestable" | |
| 172 }; | |
| 173 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 174 } | |
| 175 | |
| 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); | |
| 180 | |
| 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(); | |
| 192 | |
| 193 const char* const expectations[] = { | |
| 194 "BEGIN First", | |
| 195 "END First", | |
| 196 "BEGIN Second", | |
| 197 "END Second", | |
| 198 "BEGIN Timed", | |
| 199 "END Timed", | |
| 200 }; | |
| 201 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 202 | |
| 203 EXPECT_GE(run_time, post_time + delta); | |
| 204 } | |
| 205 | |
| 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 }))); | |
| 216 | |
| 217 const char* const expectations[] = { | |
| 218 "BEGIN First", | |
| 219 "END First", | |
| 220 "BEGIN Second", | |
| 221 "END Second" | |
| 222 }; | |
| 223 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 224 } | |
| OLD | NEW |