summaryrefslogtreecommitdiffstats
path: root/base/mac/libdispatch_task_runner_unittest.cc
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-07 07:47:15 +0000
committerrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-07 07:47:15 +0000
commit3bb6472100f89924f9fb6a4f794a06539e3bfc35 (patch)
treeec1554f7c4c143f531e03e1a4235ddfc886a7ccd /base/mac/libdispatch_task_runner_unittest.cc
parentc9d09c8f002e08550ec4df3f8f854b6721db6b16 (diff)
downloadchromium_src-3bb6472100f89924f9fb6a4f794a06539e3bfc35.zip
chromium_src-3bb6472100f89924f9fb6a4f794a06539e3bfc35.tar.gz
chromium_src-3bb6472100f89924f9fb6a4f794a06539e3bfc35.tar.bz2
Create LibDispatchTaskRunner, a SingleThreadTaskRunner that is backed by a libdispatch queue.
This task runner is meant to be used when an object needs to live on a single thread but needs to both post tasks and receive callbacks via a dispatch queue. BUG=158170 TEST=Covered by new unit test. Review URL: https://chromiumcodereview.appspot.com/11464009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171718 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/mac/libdispatch_task_runner_unittest.cc')
-rw-r--r--base/mac/libdispatch_task_runner_unittest.cc201
1 files changed, 201 insertions, 0 deletions
diff --git a/base/mac/libdispatch_task_runner_unittest.cc b/base/mac/libdispatch_task_runner_unittest.cc
new file mode 100644
index 0000000..e939e49
--- /dev/null
+++ b/base/mac/libdispatch_task_runner_unittest.cc
@@ -0,0 +1,201 @@
+// 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/mac/libdispatch_task_runner.h"
+
+#include "base/bind.h"
+#include "base/mac/bind_objc_block.h"
+#include "base/message_loop.h"
+#include "base/stringprintf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class LibDispatchTaskRunnerTest : public testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ task_runner_ = new base::mac::LibDispatchTaskRunner(
+ "org.chromium.LibDispatchTaskRunnerTest");
+ }
+
+ // DispatchLastTask is used to run the main test thread's MessageLoop until
+ // all non-delayed tasks are run on the LibDispatchTaskRunner.
+ void DispatchLastTask() {
+ dispatch_async(task_runner_->GetDispatchQueue(), ^{
+ (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+ });
+ message_loop_.Run();
+ }
+
+ // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares
+ // them against the recorded values.
+ void VerifyTaskOrder(const char* const expectations[],
+ size_t num_expectations) {
+ size_t actual_size = task_order_.size();
+
+ for (size_t i = 0; i < num_expectations; ++i) {
+ if (i >= actual_size) {
+ EXPECT_LT(i, actual_size) << "Expected " << expectations[i];
+ continue;
+ }
+
+ EXPECT_EQ(expectations[i], task_order_[i]);
+ }
+
+ if (actual_size > num_expectations) {
+ EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:";
+ for (size_t i = num_expectations; i < actual_size; ++i) {
+ EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")";
+ }
+ }
+ }
+
+ // The message loop for the test main thread.
+ MessageLoop message_loop_;
+
+ // The task runner under test.
+ scoped_refptr<base::mac::LibDispatchTaskRunner> task_runner_;
+
+ // Vector that records data from TaskOrderMarker.
+ std::vector<std::string> task_order_;
+};
+
+// Scoper that records the beginning and end of a running task.
+class TaskOrderMarker {
+ public:
+ TaskOrderMarker(LibDispatchTaskRunnerTest* test, const std::string& name)
+ : test_(test),
+ name_(name) {
+ test->task_order_.push_back(std::string("BEGIN ") + name);
+ }
+ ~TaskOrderMarker() {
+ test_->task_order_.push_back(std::string("END ") + name_);
+ }
+
+ private:
+ LibDispatchTaskRunnerTest* test_;
+ std::string name_;
+};
+
+void RecordTaskOrder(LibDispatchTaskRunnerTest* test, const std::string& name) {
+ TaskOrderMarker marker(test, name);
+}
+
+// Returns a closure that records the task order.
+base::Closure BoundRecordTaskOrder(LibDispatchTaskRunnerTest* test,
+ const std::string& name) {
+ return base::Bind(&RecordTaskOrder, base::Unretained(test), name);
+}
+
+TEST_F(LibDispatchTaskRunnerTest, PostTask) {
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Basic Task"));
+ DispatchLastTask();
+ const char* const expectations[] = {
+ "BEGIN Basic Task",
+ "END Basic Task"
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+}
+
+TEST_F(LibDispatchTaskRunnerTest, PostTaskWithinTask) {
+ task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
+ TaskOrderMarker marker(this, "Outer");
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Inner"));
+ }));
+ DispatchLastTask();
+
+ const char* const expectations[] = {
+ "BEGIN Outer",
+ "END Outer",
+ "BEGIN Inner",
+ "END Inner"
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+}
+
+TEST_F(LibDispatchTaskRunnerTest, NoMessageLoop) {
+ task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
+ TaskOrderMarker marker(this,
+ base::StringPrintf("MessageLoop = %p", MessageLoop::current()));
+ }));
+ DispatchLastTask();
+
+ const char* const expectations[] = {
+ "BEGIN MessageLoop = 0x0",
+ "END MessageLoop = 0x0"
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+}
+
+TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) {
+ dispatch_async(task_runner_->GetDispatchQueue(), ^{
+ TaskOrderMarker marker(this, "First Block");
+ task_runner_->PostTask(FROM_HERE,
+ BoundRecordTaskOrder(this, "Second Task"));
+ });
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task"));
+ dispatch_async(task_runner_->GetDispatchQueue(), ^{
+ TaskOrderMarker marker(this, "Second Block");
+ });
+ DispatchLastTask();
+
+ const char* const expectations[] = {
+ "BEGIN First Block",
+ "END First Block",
+ "BEGIN First Task",
+ "END First Task",
+ "BEGIN Second Block",
+ "END Second Block",
+ "BEGIN Second Task",
+ "END Second Task",
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+}
+
+TEST_F(LibDispatchTaskRunnerTest, NonNestable) {
+ task_runner_->PostTask(FROM_HERE, base::BindBlock(^{
+ TaskOrderMarker marker(this, "First");
+ task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{
+ TaskOrderMarker marker(this, "Third NonNestable");
+ }));
+ }));
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second"));
+ DispatchLastTask();
+
+ const char* const expectations[] = {
+ "BEGIN First",
+ "END First",
+ "BEGIN Second",
+ "END Second",
+ "BEGIN Third NonNestable",
+ "END Third NonNestable"
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+}
+
+TEST_F(LibDispatchTaskRunnerTest, PostDelayed) {
+ base::TimeTicks post_time;
+ __block base::TimeTicks run_time;
+ const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50);
+
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First"));
+ post_time = base::TimeTicks::Now();
+ task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{
+ TaskOrderMarker marker(this, "Timed");
+ run_time = base::TimeTicks::Now();
+ (&message_loop_)->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+ }), delta);
+ task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second"));
+ message_loop_.Run();
+
+ const char* const expectations[] = {
+ "BEGIN First",
+ "END First",
+ "BEGIN Second",
+ "END Second",
+ "BEGIN Timed",
+ "END Timed",
+ };
+ VerifyTaskOrder(expectations, arraysize(expectations));
+
+ EXPECT_GE(run_time, post_time + delta);
+}