| Index: base/message_pump_glib_unittest.cc
 | 
| diff --git a/base/message_pump_glib_unittest.cc b/base/message_pump_glib_unittest.cc
 | 
| deleted file mode 100644
 | 
| index be11c2f50e4e5e248ea6117e4d49f2092b1e2f6f..0000000000000000000000000000000000000000
 | 
| --- a/base/message_pump_glib_unittest.cc
 | 
| +++ /dev/null
 | 
| @@ -1,580 +0,0 @@
 | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#include "base/message_pump_glib.h"
 | 
| -
 | 
| -#include <glib.h>
 | 
| -#include <math.h>
 | 
| -
 | 
| -#include <algorithm>
 | 
| -#include <vector>
 | 
| -
 | 
| -#include "base/bind.h"
 | 
| -#include "base/bind_helpers.h"
 | 
| -#include "base/callback.h"
 | 
| -#include "base/memory/ref_counted.h"
 | 
| -#include "base/message_loop.h"
 | 
| -#include "base/run_loop.h"
 | 
| -#include "base/threading/thread.h"
 | 
| -#include "testing/gtest/include/gtest/gtest.h"
 | 
| -
 | 
| -#if defined(TOOLKIT_GTK)
 | 
| -#include <gtk/gtk.h>
 | 
| -#endif
 | 
| -
 | 
| -namespace base {
 | 
| -namespace {
 | 
| -
 | 
| -// This class injects dummy "events" into the GLib loop. When "handled" these
 | 
| -// events can run tasks. This is intended to mock gtk events (the corresponding
 | 
| -// GLib source runs at the same priority).
 | 
| -class EventInjector {
 | 
| - public:
 | 
| -  EventInjector() : processed_events_(0) {
 | 
| -    source_ = static_cast<Source*>(g_source_new(&SourceFuncs, sizeof(Source)));
 | 
| -    source_->injector = this;
 | 
| -    g_source_attach(source_, NULL);
 | 
| -    g_source_set_can_recurse(source_, TRUE);
 | 
| -  }
 | 
| -
 | 
| -  ~EventInjector() {
 | 
| -    g_source_destroy(source_);
 | 
| -    g_source_unref(source_);
 | 
| -  }
 | 
| -
 | 
| -  int HandlePrepare() {
 | 
| -    // If the queue is empty, block.
 | 
| -    if (events_.empty())
 | 
| -      return -1;
 | 
| -    base::TimeDelta delta = events_[0].time - base::Time::NowFromSystemTime();
 | 
| -    return std::max(0, static_cast<int>(ceil(delta.InMillisecondsF())));
 | 
| -  }
 | 
| -
 | 
| -  bool HandleCheck() {
 | 
| -    if (events_.empty())
 | 
| -      return false;
 | 
| -    return events_[0].time <= base::Time::NowFromSystemTime();
 | 
| -  }
 | 
| -
 | 
| -  void HandleDispatch() {
 | 
| -    if (events_.empty())
 | 
| -      return;
 | 
| -    Event event = events_[0];
 | 
| -    events_.erase(events_.begin());
 | 
| -    ++processed_events_;
 | 
| -    if (!event.callback.is_null())
 | 
| -      event.callback.Run();
 | 
| -    else if (!event.task.is_null())
 | 
| -      event.task.Run();
 | 
| -  }
 | 
| -
 | 
| -  // Adds an event to the queue. When "handled", executes |callback|.
 | 
| -  // delay_ms is relative to the last event if any, or to Now() otherwise.
 | 
| -  void AddEvent(int delay_ms, const base::Closure& callback) {
 | 
| -    AddEventHelper(delay_ms, callback, base::Closure());
 | 
| -  }
 | 
| -
 | 
| -  void AddDummyEvent(int delay_ms) {
 | 
| -    AddEventHelper(delay_ms, base::Closure(), base::Closure());
 | 
| -  }
 | 
| -
 | 
| -  void AddEventAsTask(int delay_ms, const base::Closure& task) {
 | 
| -    AddEventHelper(delay_ms, base::Closure(), task);
 | 
| -  }
 | 
| -
 | 
| -  void Reset() {
 | 
| -    processed_events_ = 0;
 | 
| -    events_.clear();
 | 
| -  }
 | 
| -
 | 
| -  int processed_events() const { return processed_events_; }
 | 
| -
 | 
| - private:
 | 
| -  struct Event {
 | 
| -    base::Time time;
 | 
| -    base::Closure callback;
 | 
| -    base::Closure task;
 | 
| -  };
 | 
| -
 | 
| -  struct Source : public GSource {
 | 
| -    EventInjector* injector;
 | 
| -  };
 | 
| -
 | 
| -  void AddEventHelper(
 | 
| -      int delay_ms, const base::Closure& callback, const base::Closure& task) {
 | 
| -    base::Time last_time;
 | 
| -    if (!events_.empty())
 | 
| -      last_time = (events_.end()-1)->time;
 | 
| -    else
 | 
| -      last_time = base::Time::NowFromSystemTime();
 | 
| -
 | 
| -    base::Time future = last_time + base::TimeDelta::FromMilliseconds(delay_ms);
 | 
| -    EventInjector::Event event = {future, callback, task};
 | 
| -    events_.push_back(event);
 | 
| -  }
 | 
| -
 | 
| -  static gboolean Prepare(GSource* source, gint* timeout_ms) {
 | 
| -    *timeout_ms = static_cast<Source*>(source)->injector->HandlePrepare();
 | 
| -    return FALSE;
 | 
| -  }
 | 
| -
 | 
| -  static gboolean Check(GSource* source) {
 | 
| -    return static_cast<Source*>(source)->injector->HandleCheck();
 | 
| -  }
 | 
| -
 | 
| -  static gboolean Dispatch(GSource* source,
 | 
| -                           GSourceFunc unused_func,
 | 
| -                           gpointer unused_data) {
 | 
| -    static_cast<Source*>(source)->injector->HandleDispatch();
 | 
| -    return TRUE;
 | 
| -  }
 | 
| -
 | 
| -  Source* source_;
 | 
| -  std::vector<Event> events_;
 | 
| -  int processed_events_;
 | 
| -  static GSourceFuncs SourceFuncs;
 | 
| -  DISALLOW_COPY_AND_ASSIGN(EventInjector);
 | 
| -};
 | 
| -
 | 
| -GSourceFuncs EventInjector::SourceFuncs = {
 | 
| -  EventInjector::Prepare,
 | 
| -  EventInjector::Check,
 | 
| -  EventInjector::Dispatch,
 | 
| -  NULL
 | 
| -};
 | 
| -
 | 
| -void IncrementInt(int *value) {
 | 
| -  ++*value;
 | 
| -}
 | 
| -
 | 
| -// Checks how many events have been processed by the injector.
 | 
| -void ExpectProcessedEvents(EventInjector* injector, int count) {
 | 
| -  EXPECT_EQ(injector->processed_events(), count);
 | 
| -}
 | 
| -
 | 
| -// Posts a task on the current message loop.
 | 
| -void PostMessageLoopTask(const tracked_objects::Location& from_here,
 | 
| -                         const base::Closure& task) {
 | 
| -  MessageLoop::current()->PostTask(from_here, task);
 | 
| -}
 | 
| -
 | 
| -// Test fixture.
 | 
| -class MessagePumpGLibTest : public testing::Test {
 | 
| - public:
 | 
| -  MessagePumpGLibTest() : loop_(NULL), injector_(NULL) { }
 | 
| -
 | 
| -  // Overridden from testing::Test:
 | 
| -  virtual void SetUp() OVERRIDE {
 | 
| -    loop_ = new MessageLoop(MessageLoop::TYPE_UI);
 | 
| -    injector_ = new EventInjector();
 | 
| -  }
 | 
| -  virtual void TearDown() OVERRIDE {
 | 
| -    delete injector_;
 | 
| -    injector_ = NULL;
 | 
| -    delete loop_;
 | 
| -    loop_ = NULL;
 | 
| -  }
 | 
| -
 | 
| -  MessageLoop* loop() const { return loop_; }
 | 
| -  EventInjector* injector() const { return injector_; }
 | 
| -
 | 
| - private:
 | 
| -  MessageLoop* loop_;
 | 
| -  EventInjector* injector_;
 | 
| -  DISALLOW_COPY_AND_ASSIGN(MessagePumpGLibTest);
 | 
| -};
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestQuit) {
 | 
| -  // Checks that Quit works and that the basic infrastructure is working.
 | 
| -
 | 
| -  // Quit from a task
 | 
| -  RunLoop().RunUntilIdle();
 | 
| -  EXPECT_EQ(0, injector()->processed_events());
 | 
| -
 | 
| -  injector()->Reset();
 | 
| -  // Quit from an event
 | 
| -  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
 | 
| -  loop()->Run();
 | 
| -  EXPECT_EQ(1, injector()->processed_events());
 | 
| -}
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) {
 | 
| -  // Checks that tasks posted by events are executed before the next event if
 | 
| -  // the posted task queue is empty.
 | 
| -  // MessageLoop doesn't make strong guarantees that it is the case, but the
 | 
| -  // current implementation ensures it and the tests below rely on it.
 | 
| -  // If changes cause this test to fail, it is reasonable to change it, but
 | 
| -  // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be
 | 
| -  // changed accordingly, otherwise they can become flaky.
 | 
| -  injector()->AddEventAsTask(0, base::Bind(&base::DoNothing));
 | 
| -  base::Closure check_task =
 | 
| -      base::Bind(&ExpectProcessedEvents, base::Unretained(injector()), 2);
 | 
| -  base::Closure posted_task =
 | 
| -      base::Bind(&PostMessageLoopTask, FROM_HERE, check_task);
 | 
| -  injector()->AddEventAsTask(0, posted_task);
 | 
| -  injector()->AddEventAsTask(0, base::Bind(&base::DoNothing));
 | 
| -  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
 | 
| -  loop()->Run();
 | 
| -  EXPECT_EQ(4, injector()->processed_events());
 | 
| -
 | 
| -  injector()->Reset();
 | 
| -  injector()->AddEventAsTask(0, base::Bind(&base::DoNothing));
 | 
| -  check_task =
 | 
| -      base::Bind(&ExpectProcessedEvents, base::Unretained(injector()), 2);
 | 
| -  posted_task = base::Bind(&PostMessageLoopTask, FROM_HERE, check_task);
 | 
| -  injector()->AddEventAsTask(0, posted_task);
 | 
| -  injector()->AddEventAsTask(10, base::Bind(&base::DoNothing));
 | 
| -  injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
 | 
| -  loop()->Run();
 | 
| -  EXPECT_EQ(4, injector()->processed_events());
 | 
| -}
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) {
 | 
| -  int task_count = 0;
 | 
| -  // Tests that we process tasks while waiting for new events.
 | 
| -  // The event queue is empty at first.
 | 
| -  for (int i = 0; i < 10; ++i) {
 | 
| -    loop()->PostTask(FROM_HERE, base::Bind(&IncrementInt, &task_count));
 | 
| -  }
 | 
| -  // After all the previous tasks have executed, enqueue an event that will
 | 
| -  // quit.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&EventInjector::AddEvent, base::Unretained(injector()), 0,
 | 
| -                 MessageLoop::QuitWhenIdleClosure()));
 | 
| -  loop()->Run();
 | 
| -  ASSERT_EQ(10, task_count);
 | 
| -  EXPECT_EQ(1, injector()->processed_events());
 | 
| -
 | 
| -  // Tests that we process delayed tasks while waiting for new events.
 | 
| -  injector()->Reset();
 | 
| -  task_count = 0;
 | 
| -  for (int i = 0; i < 10; ++i) {
 | 
| -    loop()->PostDelayedTask(
 | 
| -        FROM_HERE,
 | 
| -        base::Bind(&IncrementInt, &task_count),
 | 
| -        base::TimeDelta::FromMilliseconds(10*i));
 | 
| -  }
 | 
| -  // After all the previous tasks have executed, enqueue an event that will
 | 
| -  // quit.
 | 
| -  // This relies on the fact that delayed tasks are executed in delay order.
 | 
| -  // That is verified in message_loop_unittest.cc.
 | 
| -  loop()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&EventInjector::AddEvent, base::Unretained(injector()), 10,
 | 
| -                 MessageLoop::QuitWhenIdleClosure()),
 | 
| -      base::TimeDelta::FromMilliseconds(150));
 | 
| -  loop()->Run();
 | 
| -  ASSERT_EQ(10, task_count);
 | 
| -  EXPECT_EQ(1, injector()->processed_events());
 | 
| -}
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) {
 | 
| -  // Tests that we process events while waiting for work.
 | 
| -  // The event queue is empty at first.
 | 
| -  for (int i = 0; i < 10; ++i) {
 | 
| -    injector()->AddDummyEvent(0);
 | 
| -  }
 | 
| -  // After all the events have been processed, post a task that will check that
 | 
| -  // the events have been processed (note: the task executes after the event
 | 
| -  // that posted it has been handled, so we expect 11 at that point).
 | 
| -  base::Closure check_task =
 | 
| -      base::Bind(&ExpectProcessedEvents, base::Unretained(injector()), 11);
 | 
| -  base::Closure posted_task =
 | 
| -      base::Bind(&PostMessageLoopTask, FROM_HERE, check_task);
 | 
| -  injector()->AddEventAsTask(10, posted_task);
 | 
| -
 | 
| -  // And then quit (relies on the condition tested by TestEventTaskInterleave).
 | 
| -  injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure());
 | 
| -  loop()->Run();
 | 
| -
 | 
| -  EXPECT_EQ(12, injector()->processed_events());
 | 
| -}
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -// This class is a helper for the concurrent events / posted tasks test below.
 | 
| -// It will quit the main loop once enough tasks and events have been processed,
 | 
| -// while making sure there is always work to do and events in the queue.
 | 
| -class ConcurrentHelper : public base::RefCounted<ConcurrentHelper>  {
 | 
| - public:
 | 
| -  explicit ConcurrentHelper(EventInjector* injector)
 | 
| -      : injector_(injector),
 | 
| -        event_count_(kStartingEventCount),
 | 
| -        task_count_(kStartingTaskCount) {
 | 
| -  }
 | 
| -
 | 
| -  void FromTask() {
 | 
| -    if (task_count_ > 0) {
 | 
| -      --task_count_;
 | 
| -    }
 | 
| -    if (task_count_ == 0 && event_count_ == 0) {
 | 
| -        MessageLoop::current()->QuitWhenIdle();
 | 
| -    } else {
 | 
| -      MessageLoop::current()->PostTask(
 | 
| -          FROM_HERE, base::Bind(&ConcurrentHelper::FromTask, this));
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  void FromEvent() {
 | 
| -    if (event_count_ > 0) {
 | 
| -      --event_count_;
 | 
| -    }
 | 
| -    if (task_count_ == 0 && event_count_ == 0) {
 | 
| -        MessageLoop::current()->QuitWhenIdle();
 | 
| -    } else {
 | 
| -      injector_->AddEventAsTask(
 | 
| -          0, base::Bind(&ConcurrentHelper::FromEvent, this));
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  int event_count() const { return event_count_; }
 | 
| -  int task_count() const { return task_count_; }
 | 
| -
 | 
| - private:
 | 
| -  friend class base::RefCounted<ConcurrentHelper>;
 | 
| -
 | 
| -  ~ConcurrentHelper() {}
 | 
| -
 | 
| -  static const int kStartingEventCount = 20;
 | 
| -  static const int kStartingTaskCount = 20;
 | 
| -
 | 
| -  EventInjector* injector_;
 | 
| -  int event_count_;
 | 
| -  int task_count_;
 | 
| -};
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestConcurrentEventPostedTask) {
 | 
| -  // Tests that posted tasks don't starve events, nor the opposite.
 | 
| -  // We use the helper class above. We keep both event and posted task queues
 | 
| -  // full, the helper verifies that both tasks and events get processed.
 | 
| -  // If that is not the case, either event_count_ or task_count_ will not get
 | 
| -  // to 0, and MessageLoop::QuitWhenIdle() will never be called.
 | 
| -  scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector());
 | 
| -
 | 
| -  // Add 2 events to the queue to make sure it is always full (when we remove
 | 
| -  // the event before processing it).
 | 
| -  injector()->AddEventAsTask(
 | 
| -      0, base::Bind(&ConcurrentHelper::FromEvent, helper.get()));
 | 
| -  injector()->AddEventAsTask(
 | 
| -      0, base::Bind(&ConcurrentHelper::FromEvent, helper.get()));
 | 
| -
 | 
| -  // Similarly post 2 tasks.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&ConcurrentHelper::FromTask, helper.get()));
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&ConcurrentHelper::FromTask, helper.get()));
 | 
| -
 | 
| -  loop()->Run();
 | 
| -  EXPECT_EQ(0, helper->event_count());
 | 
| -  EXPECT_EQ(0, helper->task_count());
 | 
| -}
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -void AddEventsAndDrainGLib(EventInjector* injector) {
 | 
| -  // Add a couple of dummy events
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  // Then add an event that will quit the main loop.
 | 
| -  injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
 | 
| -
 | 
| -  // Post a couple of dummy tasks
 | 
| -  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&base::DoNothing));
 | 
| -  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&base::DoNothing));
 | 
| -
 | 
| -  // Drain the events
 | 
| -  while (g_main_context_pending(NULL)) {
 | 
| -    g_main_context_iteration(NULL, FALSE);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestDrainingGLib) {
 | 
| -  // Tests that draining events using GLib works.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&AddEventsAndDrainGLib, base::Unretained(injector())));
 | 
| -  loop()->Run();
 | 
| -
 | 
| -  EXPECT_EQ(3, injector()->processed_events());
 | 
| -}
 | 
| -
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -#if defined(TOOLKIT_GTK)
 | 
| -void AddEventsAndDrainGtk(EventInjector* injector) {
 | 
| -  // Add a couple of dummy events
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  // Then add an event that will quit the main loop.
 | 
| -  injector->AddEvent(0, MessageLoop::QuitWhenIdleClosure());
 | 
| -
 | 
| -  // Post a couple of dummy tasks
 | 
| -  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&base::DoNothing));
 | 
| -  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&base::DoNothing));
 | 
| -
 | 
| -  // Drain the events
 | 
| -  while (gtk_events_pending()) {
 | 
| -    gtk_main_iteration();
 | 
| -  }
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -#if defined(TOOLKIT_GTK)
 | 
| -TEST_F(MessagePumpGLibTest, TestDrainingGtk) {
 | 
| -  // Tests that draining events using Gtk works.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&AddEventsAndDrainGtk, base::Unretained(injector())));
 | 
| -  loop()->Run();
 | 
| -
 | 
| -  EXPECT_EQ(3, injector()->processed_events());
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -// Helper class that lets us run the GLib message loop.
 | 
| -class GLibLoopRunner : public base::RefCounted<GLibLoopRunner> {
 | 
| - public:
 | 
| -  GLibLoopRunner() : quit_(false) { }
 | 
| -
 | 
| -  void RunGLib() {
 | 
| -    while (!quit_) {
 | 
| -      g_main_context_iteration(NULL, TRUE);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  void RunLoop() {
 | 
| -#if defined(TOOLKIT_GTK)
 | 
| -    while (!quit_) {
 | 
| -      gtk_main_iteration();
 | 
| -    }
 | 
| -#else
 | 
| -    while (!quit_) {
 | 
| -      g_main_context_iteration(NULL, TRUE);
 | 
| -    }
 | 
| -#endif
 | 
| -  }
 | 
| -
 | 
| -  void Quit() {
 | 
| -    quit_ = true;
 | 
| -  }
 | 
| -
 | 
| -  void Reset() {
 | 
| -    quit_ = false;
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  friend class base::RefCounted<GLibLoopRunner>;
 | 
| -
 | 
| -  ~GLibLoopRunner() {}
 | 
| -
 | 
| -  bool quit_;
 | 
| -};
 | 
| -
 | 
| -void TestGLibLoopInternal(EventInjector* injector) {
 | 
| -  // Allow tasks to be processed from 'native' event loops.
 | 
| -  MessageLoop::current()->SetNestableTasksAllowed(true);
 | 
| -  scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
 | 
| -
 | 
| -  int task_count = 0;
 | 
| -  // Add a couple of dummy events
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  // Post a couple of dummy tasks
 | 
| -  MessageLoop::current()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&IncrementInt, &task_count));
 | 
| -  MessageLoop::current()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&IncrementInt, &task_count));
 | 
| -  // Delayed events
 | 
| -  injector->AddDummyEvent(10);
 | 
| -  injector->AddDummyEvent(10);
 | 
| -  // Delayed work
 | 
| -  MessageLoop::current()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&IncrementInt, &task_count),
 | 
| -      base::TimeDelta::FromMilliseconds(30));
 | 
| -  MessageLoop::current()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&GLibLoopRunner::Quit, runner.get()),
 | 
| -      base::TimeDelta::FromMilliseconds(40));
 | 
| -
 | 
| -  // Run a nested, straight GLib message loop.
 | 
| -  runner->RunGLib();
 | 
| -
 | 
| -  ASSERT_EQ(3, task_count);
 | 
| -  EXPECT_EQ(4, injector->processed_events());
 | 
| -  MessageLoop::current()->QuitWhenIdle();
 | 
| -}
 | 
| -
 | 
| -void TestGtkLoopInternal(EventInjector* injector) {
 | 
| -  // Allow tasks to be processed from 'native' event loops.
 | 
| -  MessageLoop::current()->SetNestableTasksAllowed(true);
 | 
| -  scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
 | 
| -
 | 
| -  int task_count = 0;
 | 
| -  // Add a couple of dummy events
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  injector->AddDummyEvent(0);
 | 
| -  // Post a couple of dummy tasks
 | 
| -  MessageLoop::current()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&IncrementInt, &task_count));
 | 
| -  MessageLoop::current()->PostTask(
 | 
| -      FROM_HERE, base::Bind(&IncrementInt, &task_count));
 | 
| -  // Delayed events
 | 
| -  injector->AddDummyEvent(10);
 | 
| -  injector->AddDummyEvent(10);
 | 
| -  // Delayed work
 | 
| -  MessageLoop::current()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&IncrementInt, &task_count),
 | 
| -      base::TimeDelta::FromMilliseconds(30));
 | 
| -  MessageLoop::current()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&GLibLoopRunner::Quit, runner.get()),
 | 
| -      base::TimeDelta::FromMilliseconds(40));
 | 
| -
 | 
| -  // Run a nested, straight Gtk message loop.
 | 
| -  runner->RunLoop();
 | 
| -
 | 
| -  ASSERT_EQ(3, task_count);
 | 
| -  EXPECT_EQ(4, injector->processed_events());
 | 
| -  MessageLoop::current()->QuitWhenIdle();
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestGLibLoop) {
 | 
| -  // Tests that events and posted tasks are correctly executed if the message
 | 
| -  // loop is not run by MessageLoop::Run() but by a straight GLib loop.
 | 
| -  // Note that in this case we don't make strong guarantees about niceness
 | 
| -  // between events and posted tasks.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&TestGLibLoopInternal, base::Unretained(injector())));
 | 
| -  loop()->Run();
 | 
| -}
 | 
| -
 | 
| -TEST_F(MessagePumpGLibTest, TestGtkLoop) {
 | 
| -  // Tests that events and posted tasks are correctly executed if the message
 | 
| -  // loop is not run by MessageLoop::Run() but by a straight Gtk loop.
 | 
| -  // Note that in this case we don't make strong guarantees about niceness
 | 
| -  // between events and posted tasks.
 | 
| -  loop()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&TestGtkLoopInternal, base::Unretained(injector())));
 | 
| -  loop()->Run();
 | 
| -}
 | 
| -
 | 
| -}  // namespace base
 | 
| 
 |