OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 19 matching lines...) Expand all Loading... |
30 } // namespace | 30 } // namespace |
31 | 31 |
32 TEST(TaskQueueTest, Construct) { | 32 TEST(TaskQueueTest, Construct) { |
33 static const char kQueueName[] = "Construct"; | 33 static const char kQueueName[] = "Construct"; |
34 TaskQueue queue(kQueueName); | 34 TaskQueue queue(kQueueName); |
35 EXPECT_FALSE(queue.IsCurrent()); | 35 EXPECT_FALSE(queue.IsCurrent()); |
36 } | 36 } |
37 | 37 |
38 TEST(TaskQueueTest, PostAndCheckCurrent) { | 38 TEST(TaskQueueTest, PostAndCheckCurrent) { |
39 static const char kQueueName[] = "PostAndCheckCurrent"; | 39 static const char kQueueName[] = "PostAndCheckCurrent"; |
| 40 Event event(false, false); |
40 TaskQueue queue(kQueueName); | 41 TaskQueue queue(kQueueName); |
41 | 42 |
42 // We're not running a task, so there shouldn't be a current queue. | 43 // We're not running a task, so there shouldn't be a current queue. |
43 EXPECT_FALSE(queue.IsCurrent()); | 44 EXPECT_FALSE(queue.IsCurrent()); |
44 EXPECT_FALSE(TaskQueue::Current()); | 45 EXPECT_FALSE(TaskQueue::Current()); |
45 | 46 |
46 Event event(false, false); | |
47 queue.PostTask(Bind(&CheckCurrent, kQueueName, &event, &queue)); | 47 queue.PostTask(Bind(&CheckCurrent, kQueueName, &event, &queue)); |
48 EXPECT_TRUE(event.Wait(1000)); | 48 EXPECT_TRUE(event.Wait(1000)); |
49 } | 49 } |
50 | 50 |
51 TEST(TaskQueueTest, PostCustomTask) { | 51 TEST(TaskQueueTest, PostCustomTask) { |
52 static const char kQueueName[] = "PostCustomImplementation"; | 52 static const char kQueueName[] = "PostCustomImplementation"; |
| 53 Event event(false, false); |
53 TaskQueue queue(kQueueName); | 54 TaskQueue queue(kQueueName); |
54 | 55 |
55 Event event(false, false); | |
56 | |
57 class CustomTask : public QueuedTask { | 56 class CustomTask : public QueuedTask { |
58 public: | 57 public: |
59 explicit CustomTask(Event* event) : event_(event) {} | 58 explicit CustomTask(Event* event) : event_(event) {} |
60 | 59 |
61 private: | 60 private: |
62 bool Run() override { | 61 bool Run() override { |
63 event_->Set(); | 62 event_->Set(); |
64 return false; // Never allows the task to be deleted by the queue. | 63 return false; // Never allows the task to be deleted by the queue. |
65 } | 64 } |
66 | 65 |
67 Event* const event_; | 66 Event* const event_; |
68 } my_task(&event); | 67 } my_task(&event); |
69 | 68 |
70 // Please don't do this in production code! :) | 69 // Please don't do this in production code! :) |
71 queue.PostTask(std::unique_ptr<QueuedTask>(&my_task)); | 70 queue.PostTask(std::unique_ptr<QueuedTask>(&my_task)); |
72 EXPECT_TRUE(event.Wait(1000)); | 71 EXPECT_TRUE(event.Wait(1000)); |
73 } | 72 } |
74 | 73 |
75 TEST(TaskQueueTest, PostLambda) { | 74 TEST(TaskQueueTest, PostLambda) { |
76 static const char kQueueName[] = "PostLambda"; | 75 static const char kQueueName[] = "PostLambda"; |
| 76 Event event(false, false); |
77 TaskQueue queue(kQueueName); | 77 TaskQueue queue(kQueueName); |
78 | 78 |
79 Event event(false, false); | |
80 queue.PostTask([&event]() { event.Set(); }); | 79 queue.PostTask([&event]() { event.Set(); }); |
81 EXPECT_TRUE(event.Wait(1000)); | 80 EXPECT_TRUE(event.Wait(1000)); |
82 } | 81 } |
83 | 82 |
84 TEST(TaskQueueTest, PostFromQueue) { | 83 TEST(TaskQueueTest, PostFromQueue) { |
85 static const char kQueueName[] = "PostFromQueue"; | 84 static const char kQueueName[] = "PostFromQueue"; |
| 85 Event event(false, false); |
86 TaskQueue queue(kQueueName); | 86 TaskQueue queue(kQueueName); |
87 | 87 |
88 Event event(false, false); | |
89 queue.PostTask( | 88 queue.PostTask( |
90 [&event, &queue]() { queue.PostTask([&event]() { event.Set(); }); }); | 89 [&event, &queue]() { queue.PostTask([&event]() { event.Set(); }); }); |
91 EXPECT_TRUE(event.Wait(1000)); | 90 EXPECT_TRUE(event.Wait(1000)); |
92 } | 91 } |
93 | 92 |
94 TEST(TaskQueueTest, PostDelayed) { | 93 TEST(TaskQueueTest, PostDelayed) { |
95 static const char kQueueName[] = "PostDelayed"; | 94 static const char kQueueName[] = "PostDelayed"; |
| 95 Event event(false, false); |
96 TaskQueue queue(kQueueName); | 96 TaskQueue queue(kQueueName); |
97 | 97 |
98 Event event(false, false); | |
99 uint32_t start = Time(); | 98 uint32_t start = Time(); |
100 queue.PostDelayedTask(Bind(&CheckCurrent, kQueueName, &event, &queue), 100); | 99 queue.PostDelayedTask(Bind(&CheckCurrent, kQueueName, &event, &queue), 100); |
101 EXPECT_TRUE(event.Wait(1000)); | 100 EXPECT_TRUE(event.Wait(1000)); |
102 uint32_t end = Time(); | 101 uint32_t end = Time(); |
103 // These tests are a little relaxed due to how "powerful" our test bots can | 102 // These tests are a little relaxed due to how "powerful" our test bots can |
104 // be. Most recently we've seen windows bots fire the callback after 94-99ms, | 103 // be. Most recently we've seen windows bots fire the callback after 94-99ms, |
105 // which is why we have a little bit of leeway backwards as well. | 104 // which is why we have a little bit of leeway backwards as well. |
106 EXPECT_GE(end - start, 90u); | 105 EXPECT_GE(end - start, 90u); |
107 EXPECT_NEAR(end - start, 190u, 100u); // Accept 90-290. | 106 EXPECT_NEAR(end - start, 190u, 100u); // Accept 90-290. |
108 } | 107 } |
(...skipping 19 matching lines...) Expand all Loading... |
128 { | 127 { |
129 TaskQueue queue(kQueueName); | 128 TaskQueue queue(kQueueName); |
130 queue.PostDelayedTask(Bind(&CheckCurrent, kQueueName, &event, &queue), 100); | 129 queue.PostDelayedTask(Bind(&CheckCurrent, kQueueName, &event, &queue), 100); |
131 } | 130 } |
132 EXPECT_FALSE(event.Wait(200)); // Task should not run. | 131 EXPECT_FALSE(event.Wait(200)); // Task should not run. |
133 } | 132 } |
134 | 133 |
135 TEST(TaskQueueTest, PostAndReply) { | 134 TEST(TaskQueueTest, PostAndReply) { |
136 static const char kPostQueue[] = "PostQueue"; | 135 static const char kPostQueue[] = "PostQueue"; |
137 static const char kReplyQueue[] = "ReplyQueue"; | 136 static const char kReplyQueue[] = "ReplyQueue"; |
| 137 Event event(false, false); |
138 TaskQueue post_queue(kPostQueue); | 138 TaskQueue post_queue(kPostQueue); |
139 TaskQueue reply_queue(kReplyQueue); | 139 TaskQueue reply_queue(kReplyQueue); |
140 | 140 |
141 Event event(false, false); | |
142 post_queue.PostTaskAndReply( | 141 post_queue.PostTaskAndReply( |
143 Bind(&CheckCurrent, kPostQueue, nullptr, &post_queue), | 142 Bind(&CheckCurrent, kPostQueue, nullptr, &post_queue), |
144 Bind(&CheckCurrent, kReplyQueue, &event, &reply_queue), &reply_queue); | 143 Bind(&CheckCurrent, kReplyQueue, &event, &reply_queue), &reply_queue); |
145 EXPECT_TRUE(event.Wait(1000)); | 144 EXPECT_TRUE(event.Wait(1000)); |
146 } | 145 } |
147 | 146 |
148 TEST(TaskQueueTest, PostAndReuse) { | 147 TEST(TaskQueueTest, PostAndReuse) { |
149 static const char kPostQueue[] = "PostQueue"; | 148 static const char kPostQueue[] = "PostQueue"; |
150 static const char kReplyQueue[] = "ReplyQueue"; | 149 static const char kReplyQueue[] = "ReplyQueue"; |
| 150 Event event(false, false); |
151 TaskQueue post_queue(kPostQueue); | 151 TaskQueue post_queue(kPostQueue); |
152 TaskQueue reply_queue(kReplyQueue); | 152 TaskQueue reply_queue(kReplyQueue); |
153 | 153 |
154 int call_count = 0; | 154 int call_count = 0; |
155 | 155 |
156 class ReusedTask : public QueuedTask { | 156 class ReusedTask : public QueuedTask { |
157 public: | 157 public: |
158 ReusedTask(int* counter, TaskQueue* reply_queue, Event* event) | 158 ReusedTask(int* counter, TaskQueue* reply_queue, Event* event) |
159 : counter_(counter), reply_queue_(reply_queue), event_(event) { | 159 : counter_(counter), reply_queue_(reply_queue), event_(event) { |
160 EXPECT_EQ(0, *counter_); | 160 EXPECT_EQ(0, *counter_); |
(...skipping 16 matching lines...) Expand all Loading... |
177 event_->Set(); | 177 event_->Set(); |
178 return true; // Indicate that the object should be deleted. | 178 return true; // Indicate that the object should be deleted. |
179 } | 179 } |
180 } | 180 } |
181 | 181 |
182 int* const counter_; | 182 int* const counter_; |
183 TaskQueue* const reply_queue_; | 183 TaskQueue* const reply_queue_; |
184 Event* const event_; | 184 Event* const event_; |
185 }; | 185 }; |
186 | 186 |
187 Event event(false, false); | |
188 std::unique_ptr<QueuedTask> task( | 187 std::unique_ptr<QueuedTask> task( |
189 new ReusedTask(&call_count, &reply_queue, &event)); | 188 new ReusedTask(&call_count, &reply_queue, &event)); |
190 | 189 |
191 post_queue.PostTask(std::move(task)); | 190 post_queue.PostTask(std::move(task)); |
192 EXPECT_TRUE(event.Wait(1000)); | 191 EXPECT_TRUE(event.Wait(1000)); |
193 } | 192 } |
194 | 193 |
195 TEST(TaskQueueTest, PostAndReplyLambda) { | 194 TEST(TaskQueueTest, PostAndReplyLambda) { |
196 static const char kPostQueue[] = "PostQueue"; | 195 static const char kPostQueue[] = "PostQueue"; |
197 static const char kReplyQueue[] = "ReplyQueue"; | 196 static const char kReplyQueue[] = "ReplyQueue"; |
| 197 Event event(false, false); |
198 TaskQueue post_queue(kPostQueue); | 198 TaskQueue post_queue(kPostQueue); |
199 TaskQueue reply_queue(kReplyQueue); | 199 TaskQueue reply_queue(kReplyQueue); |
200 | 200 |
201 Event event(false, false); | |
202 bool my_flag = false; | 201 bool my_flag = false; |
203 post_queue.PostTaskAndReply([&my_flag]() { my_flag = true; }, | 202 post_queue.PostTaskAndReply([&my_flag]() { my_flag = true; }, |
204 [&event]() { event.Set(); }, &reply_queue); | 203 [&event]() { event.Set(); }, &reply_queue); |
205 EXPECT_TRUE(event.Wait(1000)); | 204 EXPECT_TRUE(event.Wait(1000)); |
206 EXPECT_TRUE(my_flag); | 205 EXPECT_TRUE(my_flag); |
207 } | 206 } |
208 | 207 |
| 208 // This test covers a particular bug that we had in the libevent implementation |
| 209 // where we could hit a deadlock while trying to post a reply task to a queue |
| 210 // that was being deleted. The test isn't guaranteed to hit that case but it's |
| 211 // written in a way that makes it likely and by running with --gtest_repeat=1000 |
| 212 // the bug would occur. Alas, now it should be fixed. |
| 213 TEST(TaskQueueTest, PostAndReplyDeadlock) { |
| 214 Event event(false, false); |
| 215 TaskQueue post_queue("PostQueue"); |
| 216 TaskQueue reply_queue("ReplyQueue"); |
| 217 |
| 218 post_queue.PostTaskAndReply([&event]() { event.Set(); }, []() {}, |
| 219 &reply_queue); |
| 220 EXPECT_TRUE(event.Wait(1000)); |
| 221 } |
| 222 |
209 void TestPostTaskAndReply(TaskQueue* work_queue, | 223 void TestPostTaskAndReply(TaskQueue* work_queue, |
210 const char* work_queue_name, | 224 const char* work_queue_name, |
211 Event* event) { | 225 Event* event) { |
212 ASSERT_FALSE(work_queue->IsCurrent()); | 226 ASSERT_FALSE(work_queue->IsCurrent()); |
213 work_queue->PostTaskAndReply( | 227 work_queue->PostTaskAndReply( |
214 Bind(&CheckCurrent, work_queue_name, nullptr, work_queue), | 228 Bind(&CheckCurrent, work_queue_name, nullptr, work_queue), |
215 NewClosure([event]() { event->Set(); })); | 229 NewClosure([event]() { event->Set(); })); |
216 } | 230 } |
217 | 231 |
218 // Does a PostTaskAndReply from within a task to post and reply to the current | 232 // Does a PostTaskAndReply from within a task to post and reply to the current |
219 // queue. All in all there will be 3 tasks posted and run. | 233 // queue. All in all there will be 3 tasks posted and run. |
220 TEST(TaskQueueTest, PostAndReply2) { | 234 TEST(TaskQueueTest, PostAndReply2) { |
221 static const char kQueueName[] = "PostAndReply2"; | 235 static const char kQueueName[] = "PostAndReply2"; |
222 static const char kWorkQueueName[] = "PostAndReply2_Worker"; | 236 static const char kWorkQueueName[] = "PostAndReply2_Worker"; |
| 237 Event event(false, false); |
223 TaskQueue queue(kQueueName); | 238 TaskQueue queue(kQueueName); |
224 TaskQueue work_queue(kWorkQueueName); | 239 TaskQueue work_queue(kWorkQueueName); |
225 | 240 |
226 Event event(false, false); | |
227 queue.PostTask( | 241 queue.PostTask( |
228 Bind(&TestPostTaskAndReply, &work_queue, kWorkQueueName, &event)); | 242 Bind(&TestPostTaskAndReply, &work_queue, kWorkQueueName, &event)); |
229 EXPECT_TRUE(event.Wait(1000)); | 243 EXPECT_TRUE(event.Wait(1000)); |
230 } | 244 } |
231 | 245 |
232 // Tests posting more messages than a queue can queue up. | 246 // Tests posting more messages than a queue can queue up. |
233 // In situations like that, tasks will get dropped. | 247 // In situations like that, tasks will get dropped. |
234 TEST(TaskQueueTest, PostALot) { | 248 TEST(TaskQueueTest, PostALot) { |
235 // To destruct the event after the queue has gone out of scope. | 249 // To destruct the event after the queue has gone out of scope. |
236 Event event(false, false); | 250 Event event(false, false); |
(...skipping 15 matching lines...) Expand all Loading... |
252 queue.PostTask(NewClosure([&tasks_executed]() { ++tasks_executed; }, | 266 queue.PostTask(NewClosure([&tasks_executed]() { ++tasks_executed; }, |
253 [&tasks_cleaned_up]() { ++tasks_cleaned_up; })); | 267 [&tasks_cleaned_up]() { ++tasks_cleaned_up; })); |
254 event.Set(); // Unblock the first task. | 268 event.Set(); // Unblock the first task. |
255 } | 269 } |
256 | 270 |
257 EXPECT_GE(tasks_cleaned_up, tasks_executed); | 271 EXPECT_GE(tasks_cleaned_up, tasks_executed); |
258 EXPECT_EQ(kTaskCount, tasks_cleaned_up); | 272 EXPECT_EQ(kTaskCount, tasks_cleaned_up); |
259 } | 273 } |
260 | 274 |
261 } // namespace rtc | 275 } // namespace rtc |
OLD | NEW |