OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_loop/message_pump_glib.h" | 5 #include "base/message_loop/message_pump_glib.h" |
6 | 6 |
7 #include <glib.h> | 7 #include <glib.h> |
8 #include <math.h> | 8 #include <math.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/run_loop.h" | 19 #include "base/run_loop.h" |
| 20 #include "base/single_thread_task_runner.h" |
20 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
21 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
23 | 24 |
24 namespace base { | 25 namespace base { |
25 namespace { | 26 namespace { |
26 | 27 |
27 // This class injects dummy "events" into the GLib loop. When "handled" these | 28 // This class injects dummy "events" into the GLib loop. When "handled" these |
28 // events can run tasks. This is intended to mock gtk events (the corresponding | 29 // events can run tasks. This is intended to mock gtk events (the corresponding |
29 // GLib source runs at the same priority). | 30 // GLib source runs at the same priority). |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 TEST_F(MessagePumpGLibTest, TestQuit) { | 189 TEST_F(MessagePumpGLibTest, TestQuit) { |
189 // Checks that Quit works and that the basic infrastructure is working. | 190 // Checks that Quit works and that the basic infrastructure is working. |
190 | 191 |
191 // Quit from a task | 192 // Quit from a task |
192 RunLoop().RunUntilIdle(); | 193 RunLoop().RunUntilIdle(); |
193 EXPECT_EQ(0, injector()->processed_events()); | 194 EXPECT_EQ(0, injector()->processed_events()); |
194 | 195 |
195 injector()->Reset(); | 196 injector()->Reset(); |
196 // Quit from an event | 197 // Quit from an event |
197 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 198 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
198 loop()->Run(); | 199 RunLoop().Run(); |
199 EXPECT_EQ(1, injector()->processed_events()); | 200 EXPECT_EQ(1, injector()->processed_events()); |
200 } | 201 } |
201 | 202 |
202 TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) { | 203 TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) { |
203 // Checks that tasks posted by events are executed before the next event if | 204 // Checks that tasks posted by events are executed before the next event if |
204 // the posted task queue is empty. | 205 // the posted task queue is empty. |
205 // MessageLoop doesn't make strong guarantees that it is the case, but the | 206 // MessageLoop doesn't make strong guarantees that it is the case, but the |
206 // current implementation ensures it and the tests below rely on it. | 207 // current implementation ensures it and the tests below rely on it. |
207 // If changes cause this test to fail, it is reasonable to change it, but | 208 // If changes cause this test to fail, it is reasonable to change it, but |
208 // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be | 209 // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be |
209 // changed accordingly, otherwise they can become flaky. | 210 // changed accordingly, otherwise they can become flaky. |
210 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 211 injector()->AddEventAsTask(0, Bind(&DoNothing)); |
211 Closure check_task = | 212 Closure check_task = |
212 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); | 213 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); |
213 Closure posted_task = | 214 Closure posted_task = |
214 Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 215 Bind(&PostMessageLoopTask, FROM_HERE, check_task); |
215 injector()->AddEventAsTask(0, posted_task); | 216 injector()->AddEventAsTask(0, posted_task); |
216 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 217 injector()->AddEventAsTask(0, Bind(&DoNothing)); |
217 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 218 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
218 loop()->Run(); | 219 RunLoop().Run(); |
219 EXPECT_EQ(4, injector()->processed_events()); | 220 EXPECT_EQ(4, injector()->processed_events()); |
220 | 221 |
221 injector()->Reset(); | 222 injector()->Reset(); |
222 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 223 injector()->AddEventAsTask(0, Bind(&DoNothing)); |
223 check_task = | 224 check_task = |
224 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); | 225 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); |
225 posted_task = Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 226 posted_task = Bind(&PostMessageLoopTask, FROM_HERE, check_task); |
226 injector()->AddEventAsTask(0, posted_task); | 227 injector()->AddEventAsTask(0, posted_task); |
227 injector()->AddEventAsTask(10, Bind(&DoNothing)); | 228 injector()->AddEventAsTask(10, Bind(&DoNothing)); |
228 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 229 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
229 loop()->Run(); | 230 RunLoop().Run(); |
230 EXPECT_EQ(4, injector()->processed_events()); | 231 EXPECT_EQ(4, injector()->processed_events()); |
231 } | 232 } |
232 | 233 |
233 TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) { | 234 TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) { |
234 int task_count = 0; | 235 int task_count = 0; |
235 // Tests that we process tasks while waiting for new events. | 236 // Tests that we process tasks while waiting for new events. |
236 // The event queue is empty at first. | 237 // The event queue is empty at first. |
237 for (int i = 0; i < 10; ++i) { | 238 for (int i = 0; i < 10; ++i) { |
238 loop()->PostTask(FROM_HERE, Bind(&IncrementInt, &task_count)); | 239 loop()->task_runner()->PostTask(FROM_HERE, |
| 240 Bind(&IncrementInt, &task_count)); |
239 } | 241 } |
240 // After all the previous tasks have executed, enqueue an event that will | 242 // After all the previous tasks have executed, enqueue an event that will |
241 // quit. | 243 // quit. |
242 loop()->PostTask( | 244 loop()->task_runner()->PostTask( |
243 FROM_HERE, | 245 FROM_HERE, Bind(&EventInjector::AddEvent, Unretained(injector()), 0, |
244 Bind(&EventInjector::AddEvent, Unretained(injector()), 0, | 246 MessageLoop::QuitWhenIdleClosure())); |
245 MessageLoop::QuitWhenIdleClosure())); | 247 RunLoop().Run(); |
246 loop()->Run(); | |
247 ASSERT_EQ(10, task_count); | 248 ASSERT_EQ(10, task_count); |
248 EXPECT_EQ(1, injector()->processed_events()); | 249 EXPECT_EQ(1, injector()->processed_events()); |
249 | 250 |
250 // Tests that we process delayed tasks while waiting for new events. | 251 // Tests that we process delayed tasks while waiting for new events. |
251 injector()->Reset(); | 252 injector()->Reset(); |
252 task_count = 0; | 253 task_count = 0; |
253 for (int i = 0; i < 10; ++i) { | 254 for (int i = 0; i < 10; ++i) { |
254 loop()->PostDelayedTask( | 255 loop()->task_runner()->PostDelayedTask(FROM_HERE, |
255 FROM_HERE, | 256 Bind(&IncrementInt, &task_count), |
256 Bind(&IncrementInt, &task_count), | 257 TimeDelta::FromMilliseconds(10 * i)); |
257 TimeDelta::FromMilliseconds(10*i)); | |
258 } | 258 } |
259 // After all the previous tasks have executed, enqueue an event that will | 259 // After all the previous tasks have executed, enqueue an event that will |
260 // quit. | 260 // quit. |
261 // This relies on the fact that delayed tasks are executed in delay order. | 261 // This relies on the fact that delayed tasks are executed in delay order. |
262 // That is verified in message_loop_unittest.cc. | 262 // That is verified in message_loop_unittest.cc. |
263 loop()->PostDelayedTask( | 263 loop()->task_runner()->PostDelayedTask( |
264 FROM_HERE, | 264 FROM_HERE, Bind(&EventInjector::AddEvent, Unretained(injector()), 10, |
265 Bind(&EventInjector::AddEvent, Unretained(injector()), 10, | 265 MessageLoop::QuitWhenIdleClosure()), |
266 MessageLoop::QuitWhenIdleClosure()), | |
267 TimeDelta::FromMilliseconds(150)); | 266 TimeDelta::FromMilliseconds(150)); |
268 loop()->Run(); | 267 RunLoop().Run(); |
269 ASSERT_EQ(10, task_count); | 268 ASSERT_EQ(10, task_count); |
270 EXPECT_EQ(1, injector()->processed_events()); | 269 EXPECT_EQ(1, injector()->processed_events()); |
271 } | 270 } |
272 | 271 |
273 TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) { | 272 TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) { |
274 // Tests that we process events while waiting for work. | 273 // Tests that we process events while waiting for work. |
275 // The event queue is empty at first. | 274 // The event queue is empty at first. |
276 for (int i = 0; i < 10; ++i) { | 275 for (int i = 0; i < 10; ++i) { |
277 injector()->AddDummyEvent(0); | 276 injector()->AddDummyEvent(0); |
278 } | 277 } |
279 // After all the events have been processed, post a task that will check that | 278 // After all the events have been processed, post a task that will check that |
280 // the events have been processed (note: the task executes after the event | 279 // the events have been processed (note: the task executes after the event |
281 // that posted it has been handled, so we expect 11 at that point). | 280 // that posted it has been handled, so we expect 11 at that point). |
282 Closure check_task = | 281 Closure check_task = |
283 Bind(&ExpectProcessedEvents, Unretained(injector()), 11); | 282 Bind(&ExpectProcessedEvents, Unretained(injector()), 11); |
284 Closure posted_task = | 283 Closure posted_task = |
285 Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 284 Bind(&PostMessageLoopTask, FROM_HERE, check_task); |
286 injector()->AddEventAsTask(10, posted_task); | 285 injector()->AddEventAsTask(10, posted_task); |
287 | 286 |
288 // And then quit (relies on the condition tested by TestEventTaskInterleave). | 287 // And then quit (relies on the condition tested by TestEventTaskInterleave). |
289 injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure()); | 288 injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure()); |
290 loop()->Run(); | 289 RunLoop().Run(); |
291 | 290 |
292 EXPECT_EQ(12, injector()->processed_events()); | 291 EXPECT_EQ(12, injector()->processed_events()); |
293 } | 292 } |
294 | 293 |
295 namespace { | 294 namespace { |
296 | 295 |
297 // This class is a helper for the concurrent events / posted tasks test below. | 296 // This class is a helper for the concurrent events / posted tasks test below. |
298 // It will quit the main loop once enough tasks and events have been processed, | 297 // It will quit the main loop once enough tasks and events have been processed, |
299 // while making sure there is always work to do and events in the queue. | 298 // while making sure there is always work to do and events in the queue. |
300 class ConcurrentHelper : public RefCounted<ConcurrentHelper> { | 299 class ConcurrentHelper : public RefCounted<ConcurrentHelper> { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector()); | 355 scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector()); |
357 | 356 |
358 // Add 2 events to the queue to make sure it is always full (when we remove | 357 // Add 2 events to the queue to make sure it is always full (when we remove |
359 // the event before processing it). | 358 // the event before processing it). |
360 injector()->AddEventAsTask( | 359 injector()->AddEventAsTask( |
361 0, Bind(&ConcurrentHelper::FromEvent, helper.get())); | 360 0, Bind(&ConcurrentHelper::FromEvent, helper.get())); |
362 injector()->AddEventAsTask( | 361 injector()->AddEventAsTask( |
363 0, Bind(&ConcurrentHelper::FromEvent, helper.get())); | 362 0, Bind(&ConcurrentHelper::FromEvent, helper.get())); |
364 | 363 |
365 // Similarly post 2 tasks. | 364 // Similarly post 2 tasks. |
366 loop()->PostTask( | 365 loop()->task_runner()->PostTask( |
367 FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get())); | 366 FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get())); |
368 loop()->PostTask( | 367 loop()->task_runner()->PostTask( |
369 FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get())); | 368 FROM_HERE, Bind(&ConcurrentHelper::FromTask, helper.get())); |
370 | 369 |
371 loop()->Run(); | 370 RunLoop().Run(); |
372 EXPECT_EQ(0, helper->event_count()); | 371 EXPECT_EQ(0, helper->event_count()); |
373 EXPECT_EQ(0, helper->task_count()); | 372 EXPECT_EQ(0, helper->task_count()); |
374 } | 373 } |
375 | 374 |
376 namespace { | 375 namespace { |
377 | 376 |
378 void AddEventsAndDrainGLib(EventInjector* injector) { | 377 void AddEventsAndDrainGLib(EventInjector* injector) { |
379 // Add a couple of dummy events | 378 // Add a couple of dummy events |
380 injector->AddDummyEvent(0); | 379 injector->AddDummyEvent(0); |
381 injector->AddDummyEvent(0); | 380 injector->AddDummyEvent(0); |
382 // Then add an event that will quit the main loop. | 381 // Then add an event that will quit the main loop. |
383 injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 382 injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
384 | 383 |
385 // Post a couple of dummy tasks | 384 // Post a couple of dummy tasks |
386 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&DoNothing)); | 385 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&DoNothing)); |
387 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&DoNothing)); | 386 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&DoNothing)); |
388 | 387 |
389 // Drain the events | 388 // Drain the events |
390 while (g_main_context_pending(NULL)) { | 389 while (g_main_context_pending(NULL)) { |
391 g_main_context_iteration(NULL, FALSE); | 390 g_main_context_iteration(NULL, FALSE); |
392 } | 391 } |
393 } | 392 } |
394 | 393 |
395 } // namespace | 394 } // namespace |
396 | 395 |
397 TEST_F(MessagePumpGLibTest, TestDrainingGLib) { | 396 TEST_F(MessagePumpGLibTest, TestDrainingGLib) { |
398 // Tests that draining events using GLib works. | 397 // Tests that draining events using GLib works. |
399 loop()->PostTask( | 398 loop()->task_runner()->PostTask( |
400 FROM_HERE, | 399 FROM_HERE, Bind(&AddEventsAndDrainGLib, Unretained(injector()))); |
401 Bind(&AddEventsAndDrainGLib, Unretained(injector()))); | 400 RunLoop().Run(); |
402 loop()->Run(); | |
403 | 401 |
404 EXPECT_EQ(3, injector()->processed_events()); | 402 EXPECT_EQ(3, injector()->processed_events()); |
405 } | 403 } |
406 | 404 |
407 namespace { | 405 namespace { |
408 | 406 |
409 // Helper class that lets us run the GLib message loop. | 407 // Helper class that lets us run the GLib message loop. |
410 class GLibLoopRunner : public RefCounted<GLibLoopRunner> { | 408 class GLibLoopRunner : public RefCounted<GLibLoopRunner> { |
411 public: | 409 public: |
412 GLibLoopRunner() : quit_(false) { } | 410 GLibLoopRunner() : quit_(false) { } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 MessageLoop::current()->QuitWhenIdle(); | 503 MessageLoop::current()->QuitWhenIdle(); |
506 } | 504 } |
507 | 505 |
508 } // namespace | 506 } // namespace |
509 | 507 |
510 TEST_F(MessagePumpGLibTest, TestGLibLoop) { | 508 TEST_F(MessagePumpGLibTest, TestGLibLoop) { |
511 // Tests that events and posted tasks are correctly executed if the message | 509 // Tests that events and posted tasks are correctly executed if the message |
512 // loop is not run by MessageLoop::Run() but by a straight GLib loop. | 510 // loop is not run by MessageLoop::Run() but by a straight GLib loop. |
513 // Note that in this case we don't make strong guarantees about niceness | 511 // Note that in this case we don't make strong guarantees about niceness |
514 // between events and posted tasks. | 512 // between events and posted tasks. |
515 loop()->PostTask( | 513 loop()->task_runner()->PostTask( |
516 FROM_HERE, | 514 FROM_HERE, Bind(&TestGLibLoopInternal, Unretained(injector()))); |
517 Bind(&TestGLibLoopInternal, Unretained(injector()))); | 515 RunLoop().Run(); |
518 loop()->Run(); | |
519 } | 516 } |
520 | 517 |
521 TEST_F(MessagePumpGLibTest, TestGtkLoop) { | 518 TEST_F(MessagePumpGLibTest, TestGtkLoop) { |
522 // Tests that events and posted tasks are correctly executed if the message | 519 // Tests that events and posted tasks are correctly executed if the message |
523 // loop is not run by MessageLoop::Run() but by a straight Gtk loop. | 520 // loop is not run by MessageLoop::Run() but by a straight Gtk loop. |
524 // Note that in this case we don't make strong guarantees about niceness | 521 // Note that in this case we don't make strong guarantees about niceness |
525 // between events and posted tasks. | 522 // between events and posted tasks. |
526 loop()->PostTask( | 523 loop()->task_runner()->PostTask( |
527 FROM_HERE, | 524 FROM_HERE, Bind(&TestGtkLoopInternal, Unretained(injector()))); |
528 Bind(&TestGtkLoopInternal, Unretained(injector()))); | 525 RunLoop().Run(); |
529 loop()->Run(); | |
530 } | 526 } |
531 | 527 |
532 } // namespace base | 528 } // namespace base |
OLD | NEW |