Index: content/child/scheduler/webthread_impl_for_worker_scheduler_unittest.cc |
diff --git a/content/child/scheduler/webthread_impl_for_worker_scheduler_unittest.cc b/content/child/scheduler/webthread_impl_for_worker_scheduler_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b03749a620889fa3aee22c64e41726ff6e3f6cba |
--- /dev/null |
+++ b/content/child/scheduler/webthread_impl_for_worker_scheduler_unittest.cc |
@@ -0,0 +1,170 @@ |
+// Copyright 2015 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/child/scheduler/webthread_impl_for_worker_scheduler.h" |
+ |
+#include "base/synchronization/waitable_event.h" |
+#include "content/child/scheduler/worker_scheduler_impl.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/WebKit/public/platform/WebTraceLocation.h" |
+ |
+using testing::_; |
+using testing::AnyOf; |
+using testing::ElementsAre; |
+using testing::Invoke; |
+ |
+namespace content { |
+namespace { |
+ |
+class NopTask : public blink::WebThread::Task { |
+ public: |
+ ~NopTask() override {} |
+ |
+ void run() {} |
+}; |
+ |
+class MockTask : public blink::WebThread::Task { |
+ public: |
+ ~MockTask() override {} |
+ |
+ MOCK_METHOD0(run, void()); |
+}; |
+ |
+class MockIdleTask : public blink::WebThread::IdleTask { |
+ public: |
+ ~MockIdleTask() override {} |
+ |
+ MOCK_METHOD1(run, void(double deadline)); |
+}; |
+ |
+class TestObserver : public blink::WebThread::TaskObserver { |
+ public: |
+ explicit TestObserver(std::string* calls) : calls_(calls) {} |
+ |
+ ~TestObserver() override {} |
+ |
+ void willProcessTask() override { calls_->append(" willProcessTask"); } |
+ |
+ void didProcessTask() override { calls_->append(" didProcessTask"); } |
+ |
+ private: |
+ std::string* calls_; // NOT OWNED |
+}; |
+ |
+class TestTask : public blink::WebThread::Task { |
+ public: |
+ explicit TestTask(std::string* calls) : calls_(calls) {} |
+ |
+ ~TestTask() override {} |
+ |
+ void run() override { calls_->append(" run"); } |
+ |
+ private: |
+ std::string* calls_; // NOT OWNED |
+}; |
+ |
+void addTaskObserver(WebThreadImplForWorkerScheduler* thread, |
+ TestObserver* observer) { |
+ thread->addTaskObserver(observer); |
+} |
+ |
+void removeTaskObserver(WebThreadImplForWorkerScheduler* thread, |
+ TestObserver* observer) { |
+ thread->removeTaskObserver(observer); |
+} |
+ |
+} // namespace |
+ |
+class WebThreadImplForWorkerSchedulerTest : public testing::Test { |
+ public: |
+ WebThreadImplForWorkerSchedulerTest() {} |
+ |
+ ~WebThreadImplForWorkerSchedulerTest() override {} |
+ |
+ void SetUp() override { |
+ thread_.reset(new WebThreadImplForWorkerScheduler("test thread")); |
+ } |
+ |
+ void RunOnWorkerThread(const tracked_objects::Location& from_here, |
+ const base::Closure& task) { |
+ base::WaitableEvent completion(false, false); |
+ thread_->TaskRunner()->PostTask( |
+ from_here, |
+ base::Bind(&WebThreadImplForWorkerSchedulerTest::RunOnWorkerThreadTask, |
+ base::Unretained(this), task, &completion)); |
+ completion.Wait(); |
+ } |
+ |
+ protected: |
+ void RunOnWorkerThreadTask(const base::Closure& task, |
+ base::WaitableEvent* completion) { |
+ task.Run(); |
+ completion->Signal(); |
+ } |
+ |
+ scoped_ptr<WebThreadImplForWorkerScheduler> thread_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebThreadImplForWorkerSchedulerTest); |
+}; |
+ |
+TEST_F(WebThreadImplForWorkerSchedulerTest, TestDefaultTask) { |
+ scoped_ptr<MockTask> task(new MockTask()); |
+ base::WaitableEvent completion(false, false); |
+ |
+ EXPECT_CALL(*task, run()); |
+ ON_CALL(*task, run()) |
+ .WillByDefault(Invoke([&completion]() { completion.Signal(); })); |
+ |
+ thread_->postTask(blink::WebTraceLocation(), task.release()); |
+ completion.Wait(); |
+} |
+ |
+TEST_F(WebThreadImplForWorkerSchedulerTest, |
+ TestTaskExecutedBeforeThreadDeletion) { |
+ scoped_ptr<MockTask> task(new MockTask()); |
+ base::WaitableEvent completion(false, false); |
+ |
+ EXPECT_CALL(*task, run()); |
+ ON_CALL(*task, run()) |
+ .WillByDefault(Invoke([&completion]() { completion.Signal(); })); |
+ |
+ thread_->postTask(blink::WebTraceLocation(), task.release()); |
+ thread_.reset(); |
+} |
+ |
+TEST_F(WebThreadImplForWorkerSchedulerTest, TestIdleTask) { |
+ scoped_ptr<MockIdleTask> task(new MockIdleTask()); |
+ base::WaitableEvent completion(false, false); |
+ |
+ EXPECT_CALL(*task, run(_)); |
+ ON_CALL(*task, run(_)) |
+ .WillByDefault(Invoke([&completion](double) { completion.Signal(); })); |
+ |
+ thread_->postIdleTask(blink::WebTraceLocation(), task.release()); |
+ // We need to post a wakeup task or idle work will never happen. |
+ thread_->postDelayedTask(blink::WebTraceLocation(), new NopTask(), 50ul); |
+ |
+ completion.Wait(); |
+} |
+ |
+TEST_F(WebThreadImplForWorkerSchedulerTest, TestTaskObserver) { |
+ std::string calls; |
+ TestObserver observer(&calls); |
+ |
+ RunOnWorkerThread(FROM_HERE, |
+ base::Bind(&addTaskObserver, thread_.get(), &observer)); |
+ thread_->postTask(blink::WebTraceLocation(), new TestTask(&calls)); |
+ RunOnWorkerThread(FROM_HERE, |
+ base::Bind(&removeTaskObserver, thread_.get(), &observer)); |
+ |
+ // We need to be careful what we test here. We want to make sure the |
+ // observers are un in the expected order before and after the task. |
+ // Sometimes we get an internal scheduler task running before or after |
+ // TestTask as well. This is not a bug, and we need to make sure the test |
+ // doesn't fail when that happens. |
+ EXPECT_THAT(calls, testing::HasSubstr("willProcessTask run didProcessTask")); |
+} |
+ |
+} // namespace content |