Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Unified Diff: content/common/startup_task_runner_unittest.cc

Issue 19957002: Run the later parts of startup as UI thread tasks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Run the later parts of startup as UI thread tasks - patch for Yaron's comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/startup_task_runner_unittest.cc
diff --git a/content/common/startup_task_runner_unittest.cc b/content/common/startup_task_runner_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7a9ffc065f4d284083cfb58ba501445679fe8b5b
--- /dev/null
+++ b/content/common/startup_task_runner_unittest.cc
@@ -0,0 +1,200 @@
+// Copyright (c) 2013 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 "content/public/common/startup_task_runner.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/run_loop.h"
+#include "base/task_runner.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+using base::Closure;
+using testing::_;
+using testing::Assign;
+using testing::Invoke;
+using testing::WithArg;
+
+class StartupTaskRunnerTest : public testing::Test {
+ private:
+
+ int last_task_;
+
+ public:
+
+ virtual void SetUp() { last_task_ = 0; }
+
+ void Task1() { last_task_ = 1; }
+
+ void Task2() { last_task_ = 2; }
+
+ int GetLastTask() { return last_task_; }
+};
+
+class MockObserver : public StartupTaskRunner::Observer {
+ public:
+ MOCK_METHOD0(AllStartupTasksRan, void());
+};
+
+// We can't use the real message loop, even if we want to, since doing so on
+// Android requires a complex Java infrastructure. The test would have to built
+// as a content_shell test; but content_shell startup invokes the class we are
+// trying to test.
+//
+// The mocks are not directly in TaskRunnerProxy because reference counted
+// objects seem to confuse the mocking framework
+
+class MockTaskRunner {
+ public:
+ MOCK_METHOD3(
+ PostDelayedTask,
+ bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
+ MOCK_METHOD3(
+ PostNonNestableDelayedTask,
+ bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
+};
+
+class TaskRunnerProxy : public base::SingleThreadTaskRunner {
+ public:
+ TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
+ bool RunsTasksOnCurrentThread() const { return true; }
+ bool PostDelayedTask(const tracked_objects::Location& location,
+ const Closure& closure,
+ base::TimeDelta delta) {
+ return mock_->PostDelayedTask(location, closure, delta);
+ }
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& location,
+ const Closure& closure,
+ base::TimeDelta delta) {
+ return mock_->PostNonNestableDelayedTask(location, closure, delta);
+ }
+
+ private:
+ MockTaskRunner* mock_;
+};
+
+TEST_F(StartupTaskRunnerTest, ImmediateExecution) {
+
+ MockTaskRunner mock_runner;
+ scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
+
+ EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
+ EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
+
+ scoped_refptr<StartupTaskRunner> runner =
+ new StartupTaskRunner(StartupTaskRunner::IMMEDIATE, NULL);
+
+ runner->SetProxy(proxy);
+
+ base::Closure task1 =
+ base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
+ runner->AddTask(task1);
+ EXPECT_EQ(GetLastTask(), 0);
+ base::Closure task2 =
+ base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
+ runner->AddTask(task2);
+
+ // Nothing should run until we tell them to.
+ EXPECT_EQ(GetLastTask(), 0);
+ runner->StartRunningTasks();
+
+ // On an immediate StartupTaskRunner the tasks should now all have run.
+ EXPECT_EQ(GetLastTask(), 2);
+}
+
+TEST_F(StartupTaskRunnerTest, ImmediateExecutionObserved) {
+ MockTaskRunner mock_runner;
+ scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
+
+ MockObserver observer;
+ EXPECT_CALL(observer, AllStartupTasksRan()).Times(1);
+
+ EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
+ EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
+
+ scoped_refptr<StartupTaskRunner> runner =
+ new StartupTaskRunner(StartupTaskRunner::IMMEDIATE, &observer);
+
+ runner->SetProxy(proxy);
+
+ base::Closure task1 =
+ base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
+ runner->AddTask(task1);
+ EXPECT_EQ(GetLastTask(), 0);
+ base::Closure task2 =
+ base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
+ runner->AddTask(task2);
+
+ // Nothing should run until we tell them to.
+ EXPECT_EQ(GetLastTask(), 0);
+ runner->StartRunningTasks();
+
+ // On an immediate StartupTaskRunner the tasks should now all have run.
+ EXPECT_EQ(GetLastTask(), 2);
+}
+
+base::Closure task;
+
+// I couldn't get gMock's SaveArg to compile, hence had to save the argument
+// this way
+bool SaveTaskArg(const Closure& arg) {
+ task = arg;
+ return true;
+}
+
+TEST_F(StartupTaskRunnerTest, IncrementalExecution) {
+
+ MockTaskRunner mock_runner;
+ scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
+
+ bool done = false;
+ ;
+
+ MockObserver observer;
+
+ EXPECT_CALL(observer, AllStartupTasksRan()).WillOnce(Assign(&done, true));
+ EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
+ EXPECT_CALL(
+ mock_runner,
+ PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
+ .Times(3).WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
+
+ scoped_refptr<StartupTaskRunner> runner =
+ new StartupTaskRunner(StartupTaskRunner::INCREMENTAL, &observer);
+
+ runner->SetProxy(proxy);
+
+ base::Closure task1 =
+ base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
+ runner->AddTask(task1);
+ base::Closure task2 =
+ base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
+ runner->AddTask(task2);
+
+ // Nothing should run until we tell them to.
+ EXPECT_EQ(GetLastTask(), 0);
+ runner->StartRunningTasks();
+
+ // No tasks should have run yet, since we the message loop hasn't run.
+ EXPECT_EQ(GetLastTask(), 0);
+
+ // Fake the actual message loop. Each time a task is run a new task should
+ // be added to the queue, hence updating "task". The loop should actually run
+ // three times, the "4" is a backstop.
+ for (int i = 0; i < 4 && !done; i++) {
+ task.Run();
+ if (!done) {
+ EXPECT_EQ(i + 1, GetLastTask());
+ }
+ }
+}
+
+} // namespace
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698