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 |