Chromium Code Reviews| 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 "base/synchronization/lock.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 class LibDispatchTaskRunnerTest : public testing::Test { | |
| 15 public: | |
| 16 virtual void SetUp() OVERRIDE { | |
| 17 task_runner_ = new base::mac::LibDispatchTaskRunner( | |
| 18 "org.chromium.LibDispatchTaskRunnerTest"); | |
| 19 } | |
| 20 | |
| 21 // DispatchLastTask is used to run the main test thread's MessageLoop until | |
| 22 // all non-delayed tasks are run on the LibDispatchTaskRunner. | |
| 23 void DispatchLastTask() { | |
| 24 dispatch_async(task_runner_->GetDispatchQueue(), ^{ | |
| 25 (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
| 26 }); | |
| 27 message_loop_.Run(); | |
| 28 } | |
| 29 | |
| 30 // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares | |
| 31 // them against the recorded values. | |
| 32 void VerifyTaskOrder(const char* expectations[], size_t num_expectations) { | |
|
Mark Mentovai
2012/12/06 22:11:45
I would make this conster, because I’d want the ac
Robert Sesek
2012/12/06 22:18:05
Done.
| |
| 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* expectations[] = { | |
| 93 "BEGIN Basic Task", | |
| 94 "END Basic Task" | |
| 95 }; | |
| 96 VerifyTaskOrder(expectations, arraysize(expectations)); | |
| 97 } | |
| 98 | |
| 99 TEST_F(LibDispatchTaskRunnerTest, PostTaskNested) { | |
| 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* 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* 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* 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* 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); | |
|
Mark Mentovai
2012/12/06 22:11:45
These tests with timers are always so shady, but w
| |
| 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* 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 |