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

Unified Diff: components/scheduler/promises/single_thread_promise_executor_unittest.cc

Issue 1401553002: NOT INTENDED FOR LANDING: A promises demo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Support for rejectatble promises! Created 4 years, 8 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: components/scheduler/promises/single_thread_promise_executor_unittest.cc
diff --git a/components/scheduler/promises/single_thread_promise_executor_unittest.cc b/components/scheduler/promises/single_thread_promise_executor_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..62cbe00c315aeb321eaf73b0d21069a13050e090
--- /dev/null
+++ b/components/scheduler/promises/single_thread_promise_executor_unittest.cc
@@ -0,0 +1,934 @@
+// Copyright 2016 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 "components/scheduler/promises/single_thread_promise_executor.h"
+
+#include "base/test/simple_test_tick_clock.h"
+#include "cc/test/ordered_simple_task_runner.h"
+#include "components/scheduler/base/task_queue_manager.h"
+#include "components/scheduler/base/test_time_source.h"
+#include "components/scheduler/child/scheduler_tqm_delegate_for_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::ElementsAre;
+using testing::WhenSorted;
+
+namespace promise {
+
+class SingleThreadPromiseExecutorTest : public testing::Test {
+ public:
+ SingleThreadPromiseExecutorTest() {}
+ ~SingleThreadPromiseExecutorTest() override {}
+
+ void SetUp() override {
+ clock_.reset(new base::SimpleTestTickClock());
+ clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
+
+ test_time_source_.reset(new scheduler::TestTimeSource(clock_.get()));
+ mock_task_runner_ = make_scoped_refptr(
+ new cc::OrderedSimpleTaskRunner(clock_.get(), false));
+ main_task_runner_ = scheduler::SchedulerTqmDelegateForTest::Create(
+ mock_task_runner_,
+ make_scoped_ptr(new scheduler::TestTimeSource(clock_.get())));
+ manager_ = make_scoped_ptr(new scheduler::TaskQueueManager(
+ main_task_runner_, "test.scheduler", "test.scheduler",
+ "test.scheduler.debug"));
+ task_runner_ =
+ manager_->NewTaskQueue(scheduler::TaskQueue::Spec("task_runner"));
+ promise_executor_.reset(
+ new internal::SingleThreadPromiseExecutor(task_runner_));
+ }
+
+ scoped_ptr<base::SimpleTestTickClock> clock_;
+ scoped_ptr<scheduler::TestTimeSource> test_time_source_;
+ scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ scoped_refptr<scheduler::SchedulerTqmDelegate> main_task_runner_;
+ scoped_ptr<scheduler::TaskQueueManager> manager_;
+ scoped_refptr<scheduler::TaskQueue> task_runner_;
+ scoped_ptr<internal::SingleThreadPromiseExecutor> promise_executor_;
+};
+
+namespace {
+bool ReturnTrue() {
+ return true;
+}
+
+int ReturnOne() {
+ return 1;
+}
+
+int ReturnTwo() {
+ return 2;
+}
+
+int ReturnTen() {
+ return 10;
+}
+
+int Add(int i, int j) {
+ return i + j;
+}
+
+int CondTimesThree(int i, bool do_smth) {
+ if (do_smth)
+ return i * 3;
+ return i;
+}
+
+int ReturnZero() {
+ return 0;
+}
+
+void RecordParam(int* out, int in) {
+ *out = in;
+}
+
+Promise<int> Choose(Promise<int> p1, Promise<int> p2, int i) {
+ return i ? p1 : p2;
+}
+
+void RecordOrder(int value, std::vector<int>* out_result) {
+ out_result->push_back(value);
+}
+
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, NonVoidPromise) {
+ Promise<int> promise(promise::Create(base::Bind(&ReturnOne)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AssignPromise) {
+ Promise<int> promise = promise::Create(base::Bind(&ReturnOne));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, Then) {
+ Promise<int> promise(
+ promise::Create(base::Bind(&ReturnOne)).Then(base::Bind(&Add, 1)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AssignThen) {
+ Promise<int> promise =
+ promise::Create(base::Bind(&ReturnOne)).Then(base::Bind(&Add, 1));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ThenVoid) {
+ int value = 0;
+ Promise<void> promise(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&RecordParam, &value)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, value);
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, VoidThenVoid) {
+ int value = 0;
+ int value2 = 0;
+ Promise<void> promise(promise::Create(base::Bind(&RecordParam, &value, 1))
+ .Then(base::Bind(&RecordParam, &value2, 2)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, value);
+ EXPECT_EQ(2, value2);
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, VoidThenInt) {
+ int value = 0;
+ Promise<int> promise(promise::Create(base::Bind(&RecordParam, &value, 2))
+ .Then(base::Bind(&ReturnOne)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, value);
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ThenChaining) {
+ Promise<int> promise(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Add, 1))
+ .Then(base::Bind(&Add, 1))
+ .Then(base::Bind(&Add, 1)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(4, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, PromiseReuse) {
+ Promise<int> promise10(promise::Create(base::Bind(&ReturnTen)));
+ Promise<int> promise11(promise10.Then(base::Bind(&Add, 1)));
+ Promise<int> promise12(promise10.Then(base::Bind(&Add, 2)));
+ Promise<int> promise13(promise10.Then(base::Bind(&Add, 3)));
+ Promise<int> promise14(promise10.Then(base::Bind(&Add, 4)));
+
+ promise_executor_->StartResolve(promise11);
+ promise_executor_->StartResolve(promise12);
+ promise_executor_->StartResolve(promise13);
+ promise_executor_->StartResolve(promise14);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, PromiseReuseResolvedPromise_TypeOne) {
+ Promise<int> promise10(promise::Create(10));
+ Promise<int> promise11(promise10.Then(base::Bind(&Add, 1)));
+ Promise<int> promise12(promise10.Then(base::Bind(&Add, 2)));
+ Promise<int> promise13(promise10.Then(base::Bind(&Add, 3)));
+ Promise<int> promise14(promise10.Then(base::Bind(&Add, 4)));
+
+ promise_executor_->StartResolve(promise11);
+ promise_executor_->StartResolve(promise12);
+ promise_executor_->StartResolve(promise13);
+ promise_executor_->StartResolve(promise14);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, PromiseReuseResolvedPromise_TypeTwo) {
+ Promise<int> promise10(promise::Create(10));
+ Promise<int> promise11(promise10.Then(base::Bind(&Add, 1)));
+ Promise<int> promise12(promise10.Then(base::Bind(&Add, 2)));
+ Promise<int> promise13(promise10.Then(base::Bind(&Add, 3)));
+ Promise<int> promise14(promise10.Then(base::Bind(&Add, 4)));
+
+ promise_executor_->StartResolve(promise10);
+ mock_task_runner_->RunUntilIdle();
+
+ promise_executor_->StartResolve(promise11);
+ promise_executor_->StartResolve(promise12);
+ promise_executor_->StartResolve(promise13);
+ promise_executor_->StartResolve(promise14);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AllThen) {
+ Promise<int> promise(promise::All(promise::Create(base::Bind(&ReturnOne)),
+ promise::Create(base::Bind(&ReturnTrue)))
+ .Then(base::Bind(&CondTimesThree)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AssignAllThen) {
+ Promise<int> promise = promise::All(promise::Create(base::Bind(&ReturnOne)),
+ promise::Create(base::Bind(&ReturnTrue)))
+ .Then(base::Bind(&CondTimesThree));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, EagerTasksExecutedFirst) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order))
+ .Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order))
+ .Then(base::Bind(&RecordOrder, 4, &run_order)));
+
+ Promise<void> promiseB(
+ promise::Create(base::Bind(&RecordOrder, 10, &run_order))
+ .Then(base::Bind(&RecordOrder, 11, &run_order))
+ .Then(base::Bind(&RecordOrder, 12, &run_order))
+ .Then(base::Bind(&RecordOrder, 13, &run_order))
+ .Then(base::Bind(&RecordOrder, 14, &run_order)));
+
+ promiseB.SetEager(true);
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(10, 11, 12, 13, 14, 0, 1, 2, 3, 4));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, DynamicChangingOfEagerness) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order))
+ .Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order))
+ .Then(base::Bind(&RecordOrder, 4, &run_order)));
+
+ Promise<void> promiseB(
+ promise::Create(base::Bind(&RecordOrder, 10, &run_order))
+ .Then(base::Bind(&RecordOrder, 11, &run_order))
+ .Then(base::Bind(&RecordOrder, 12, &run_order))
+ .Then(base::Bind(&RecordOrder, 13, &run_order))
+ .Then(base::Bind(&RecordOrder, 14, &run_order)));
+
+ promiseB.SetEager(true);
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+
+ promise_executor_->ResolveOnePromise();
+
+ promiseB.SetEager(false);
+ promiseA.SetEager(true);
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(10, 0, 1, 2, 3, 4, 11, 12, 13, 14));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, MultipleThens) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order)));
+
+ Promise<void> promiseB(promiseA.Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order)));
+
+ Promise<void> promiseC(promiseA.Then(base::Bind(&RecordOrder, 4, &run_order))
+ .Then(base::Bind(&RecordOrder, 5, &run_order)));
+
+ promise_executor_->StartResolve(promiseB);
+ promise_executor_->StartResolve(promiseC);
+ mock_task_runner_->RunUntilIdle();
+
+ // The interleaving of promiseB and promiseC execution is undefined.
+ EXPECT_THAT(run_order, WhenSorted(ElementsAre(0, 1, 2, 3, 4, 5)));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, Cancel) {
+ std::vector<int> run_order;
+
+ Promise<void> promise(
+ promise::Create(base::Bind(&RecordOrder, 1, &run_order)));
+
+ promise_executor_->StartResolve(promise);
+ promise.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(run_order.empty());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, CancelChainOfTasks) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order))
+ .Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order))
+ .Then(base::Bind(&RecordOrder, 4, &run_order)));
+
+ Promise<void> promiseB(
+ promise::Create(base::Bind(&RecordOrder, 10, &run_order))
+ .Then(base::Bind(&RecordOrder, 11, &run_order))
+ .Then(base::Bind(&RecordOrder, 12, &run_order))
+ .Then(base::Bind(&RecordOrder, 13, &run_order))
+ .Then(base::Bind(&RecordOrder, 14, &run_order)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+
+ promiseB.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, CancelOneBranch) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order)));
+
+ Promise<void> promiseB(promiseA.Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order)));
+
+ Promise<void> promiseC(promiseA.Then(base::Bind(&RecordOrder, 4, &run_order))
+ .Then(base::Bind(&RecordOrder, 5, &run_order)));
+
+ promise_executor_->StartResolve(promiseB);
+ promise_executor_->StartResolve(promiseC);
+
+ promiseB.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, CancelAndReresolve) {
+ std::vector<int> run_order;
+
+ Promise<void> promise(
+ promise::Create(base::Bind(&RecordOrder, 1, &run_order)));
+
+ promise_executor_->StartResolve(promise);
+ promise.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(run_order.empty());
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(1));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, CancelChainOfTasksAndReresolve) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order))
+ .Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order))
+ .Then(base::Bind(&RecordOrder, 4, &run_order)));
+
+ Promise<void> promiseB(
+ promise::Create(base::Bind(&RecordOrder, 10, &run_order))
+ .Then(base::Bind(&RecordOrder, 11, &run_order))
+ .Then(base::Bind(&RecordOrder, 12, &run_order))
+ .Then(base::Bind(&RecordOrder, 13, &run_order))
+ .Then(base::Bind(&RecordOrder, 14, &run_order)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+
+ promiseB.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4, 10, 11, 12, 13, 14));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, CancelOneBranchAndReresolve) {
+ std::vector<int> run_order;
+
+ Promise<void> promiseA(
+ promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&RecordOrder, 1, &run_order)));
+
+ Promise<void> promiseB(promiseA.Then(base::Bind(&RecordOrder, 2, &run_order))
+ .Then(base::Bind(&RecordOrder, 3, &run_order)));
+
+ Promise<void> promiseC(promiseA.Then(base::Bind(&RecordOrder, 4, &run_order))
+ .Then(base::Bind(&RecordOrder, 5, &run_order)));
+
+ promise_executor_->StartResolve(promiseB);
+ promise_executor_->StartResolve(promiseC);
+
+ promiseB.Cancel();
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5));
+
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5, 2, 3));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, Choose) {
+ Promise<int> promise_two(promise::Create(base::Bind(&ReturnTwo)));
+ Promise<int> promise_ten(promise::Create(base::Bind(&ReturnTen)));
+ Promise<int> promiseA(
+ promise::Create(base::Bind(&ReturnZero))
+ .Then(base::Bind(&Choose, promise_two, promise_ten)));
+
+ Promise<int> promiseB(
+ promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Choose, promise_two, promise_ten)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(10, promiseA.GetResolved());
+ EXPECT_EQ(2, promiseB.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ChooseAndAddOne) {
+ Promise<int> promise_two(promise::Create(base::Bind(&ReturnTwo)));
+ Promise<int> promise_ten(promise::Create(base::Bind(&ReturnTen)));
+ Promise<int> promiseA(promise::Create(base::Bind(&ReturnZero))
+ .Then(base::Bind(&Choose, promise_two, promise_ten))
+ .Then(base::Bind(&Add, 1)));
+
+ Promise<int> promiseB(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Choose, promise_two, promise_ten))
+ .Then(base::Bind(&Add, 1)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(11, promiseA.GetResolved());
+ EXPECT_EQ(3, promiseB.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ChooseResolved) {
+ Promise<int> promise_two(promise::Create(2));
+ Promise<int> promise_ten(promise::Create(10));
+ Promise<int> promiseA(
+ promise::Create(base::Bind(&ReturnZero))
+ .Then(base::Bind(&Choose, promise_two, promise_ten)));
+
+ Promise<int> promiseB(
+ promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Choose, promise_two, promise_ten)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(10, promiseA.GetResolved());
+ EXPECT_EQ(2, promiseB.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ChooseResolvedAndAddOne) {
+ Promise<int> promise_two(promise::Create<int>(2));
+ Promise<int> promise_ten(promise::Create<int>(10));
+ Promise<int> promiseA(promise::Create(base::Bind(&ReturnZero))
+ .Then(base::Bind(&Choose, promise_two, promise_ten))
+ .Then(base::Bind(&Add, 1)));
+
+ Promise<int> promiseB(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Choose, promise_two, promise_ten))
+ .Then(base::Bind(&Add, 1)));
+
+ promise_executor_->StartResolve(promiseA);
+ promise_executor_->StartResolve(promiseB);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(11, promiseA.GetResolved());
+ EXPECT_EQ(3, promiseB.GetResolved());
+}
+
+namespace {
+class BlockingResolveFixture {
+ public:
+ void Root() { run_order_.push_back("Root"); }
+
+ void L() { run_order_.push_back("L"); }
+
+ void LL() { run_order_.push_back("LL"); }
+
+ void LR() { run_order_.push_back("LR"); }
+
+ void R() { run_order_.push_back("R"); }
+
+ void RL() { run_order_.push_back("RL"); }
+
+ void RR() { run_order_.push_back("RL"); }
+
+ std::vector<std::string> run_order_;
+};
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, BlockingResolve) {
+ BlockingResolveFixture fixture;
+
+ Promise<void> promise_l(
+ promise::All(promise::Create(base::Bind(&BlockingResolveFixture::LL,
+ base::Unretained(&fixture))),
+ promise::Create(base::Bind(&BlockingResolveFixture::LR,
+ base::Unretained(&fixture))))
+ .Then(base::Bind(&BlockingResolveFixture::L,
+ base::Unretained(&fixture))));
+
+ Promise<void> blocking_promise(promise::Create<void>());
+
+ Promise<void> promise_r(
+ promise::All(promise::Create(base::Bind(&BlockingResolveFixture::RL,
+ base::Unretained(&fixture))),
+ promise::Create(base::Bind(&BlockingResolveFixture::RR,
+ base::Unretained(&fixture))),
+ blocking_promise)
+ .Then(base::Bind(&BlockingResolveFixture::R,
+ base::Unretained(&fixture))));
+
+ Promise<void> promise_root(promise::All(promise_l, promise_r)
+ .Then(base::Bind(&BlockingResolveFixture::Root,
+ base::Unretained(&fixture))));
+
+ promise_executor_->StartResolve(promise_root);
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_THAT(fixture.run_order_,
+ WhenSorted(ElementsAre(std::string("L"), std::string("LL"),
+ std::string("LR"), std::string("RL"),
+ std::string("RL"))));
+
+ fixture.run_order_.clear();
+ blocking_promise.Resolve();
+ mock_task_runner_->RunUntilIdle();
+ EXPECT_THAT(fixture.run_order_,
+ ElementsAre(std::string("R"), std::string("Root")));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyIntToInt) {
+ Promise<int> promiseA(promise::Create<int>());
+ Promise<int> promiseB(promise::Create<int>());
+ Promise<int> promiseC(promise::Create<int>());
+ Promise<int> promiseD(promise::Create<int>());
+
+ Promise<int> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&Add, 1)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseB.Resolve(10);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyIntToVoid) {
+ Promise<int> promiseA(promise::Create<int>());
+ Promise<int> promiseB(promise::Create<int>());
+ Promise<int> promiseC(promise::Create<int>());
+
+ int chosen = 0;
+ Promise<void> promise(promise::Race(promiseA, promiseB, promiseC)
+ .Then(base::Bind(&RecordParam, &chosen)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseB.Resolve(10);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(10, chosen);
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyAllVoid) {
+ Promise<void> promiseA(promise::Create<void>());
+ Promise<void> promiseB(promise::Create<void>());
+ Promise<void> promiseC(promise::Create<void>());
+
+ int chosen = 0;
+ Promise<void> promise(promise::Race(promiseA, promiseB, promiseC)
+ .Then(base::Bind(&RecordParam, &chosen, 1)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseB.Resolve();
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(1, chosen);
+}
+
+namespace {
+Promise<int> ReturnAPromise(int value) {
+ return promise::Create(value + 1);
+}
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyIntToIntPromise) {
+ Promise<int> promiseA(promise::Create<int>());
+ Promise<int> promiseB(promise::Create<int>());
+ Promise<int> promiseC(promise::Create<int>());
+ Promise<int> promiseD(promise::Create<int>());
+
+ Promise<int> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&ReturnAPromise)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseD.Resolve(10);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, FirstPromiseRegisteredWins) {
+ Promise<int> promiseA(promise::Create<int>());
+ Promise<int> promiseB(promise::Create<int>());
+ Promise<int> promiseC(promise::Create<int>());
+ Promise<int> promiseD(promise::Create<int>());
+
+ Promise<int> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&ReturnAPromise)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseD.Resolve(0);
+ promiseC.Resolve(10);
+ promiseB.Resolve(100);
+ promiseA.Resolve(1000);
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(1001, promise.GetResolved());
+}
+
+namespace {
+Promise<void> ReturnAVoidPromise(int* out_value, int value) {
+ return promise::Create(base::Bind(&RecordParam, out_value, value));
+}
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyIntToVoidPromise) {
+ Promise<int> promiseA(promise::Create<int>());
+ Promise<int> promiseB(promise::Create<int>());
+ Promise<int> promiseC(promise::Create<int>());
+ Promise<int> promiseD(promise::Create<int>());
+
+ int value = 0;
+ Promise<void> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&ReturnAVoidPromise, &value)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseD.Resolve(15);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(15, value);
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyVoidToIntPromise) {
+ Promise<void> promiseA(promise::Create<void>());
+ Promise<void> promiseB(promise::Create<void>());
+ Promise<void> promiseC(promise::Create<void>());
+ Promise<void> promiseD(promise::Create<void>());
+
+ Promise<int> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&ReturnAPromise, 8)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseD.Resolve();
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(9, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, AnyVoidToVoidPromise) {
+ Promise<void> promiseA(promise::Create<void>());
+ Promise<void> promiseB(promise::Create<void>());
+ Promise<void> promiseC(promise::Create<void>());
+ Promise<void> promiseD(promise::Create<void>());
+
+ int value;
+ Promise<void> promise(promise::Race(promiseA, promiseB, promiseC, promiseD)
+ .Then(base::Bind(&ReturnAVoidPromise, &value, 8)));
+
+ promise_executor_->StartResolve(promise);
+
+ promiseD.Resolve();
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(8, value);
+}
+
+namespace {
+Promise<void> GenerateNewTask(std::vector<int>* out_result) {
+ out_result->push_back(1);
+
+ return promise::Create(base::Bind(&RecordOrder, 2, out_result))
+ .Then(base::Bind(&RecordOrder, 3, out_result));
+}
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, NewPromiseFromWithinPromise) {
+ std::vector<int> run_order;
+
+ Promise<void> promise(promise::Create(base::Bind(&RecordOrder, 0, &run_order))
+ .Then(base::Bind(&GenerateNewTask, &run_order))
+ .Then(base::Bind(&RecordOrder, 4, &run_order)));
+
+ promise_executor_->StartResolve(promise);
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ResolvePromiseWithAPromise) {
+ Promise<int> promise(promise::Create<int>());
+
+ promise.Resolve(promise::Create(base::Bind(&ReturnTen)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(10, promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, ResolvePromiseWithAVoidPromise) {
+ Promise<void> promise(promise::Create<void>());
+
+ int value = 0;
+ promise.Resolve(promise::Create(base::Bind(&RecordParam, &value, 5)));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(5, value);
+}
+
+namespace {
+class MoveOnlyType {
+ public:
+ MoveOnlyType() {}
+ MoveOnlyType(MoveOnlyType&& other) {}
+
+ void operator=(MoveOnlyType&& other) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MoveOnlyType);
+};
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_ResolvedPromise_ViaMove) {
+ MoveOnlyType src;
+ Promise<MoveOnlyType> promise = promise::Create(std::move(src));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest,
+ MoveOnlyType_ResolvedPromise_Constructed) {
+ Promise<MoveOnlyType> promise = promise::Create(MoveOnlyType());
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_ManuallyResolved) {
+ Promise<MoveOnlyType> promise = promise::Create<MoveOnlyType>();
+
+ MoveOnlyType src;
+ promise.Resolve(std::move(src));
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+MoveOnlyType ReturnMoveOnlyType() {
+ return MoveOnlyType();
+}
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_ReturnedFromClosure) {
+ Promise<MoveOnlyType> promise =
+ promise::Create(base::Bind(&ReturnMoveOnlyType));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+void TakeMoveOnlyType(MoveOnlyType type) {
+ MoveOnlyType dest = std::move(type);
+}
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_PassedToThenClosure) {
+ Promise<void> promise = promise::Create(base::Bind(&ReturnMoveOnlyType))
+ .Then(base::Bind(&TakeMoveOnlyType));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+}
+
+namespace {
+MoveOnlyType PassMoveOnlyType(MoveOnlyType type) {
+ return type;
+}
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest,
+ MoveOnlyType_PassedToAndReturnedFromThenClosure) {
+ Promise<MoveOnlyType> promise =
+ promise::Create(base::Bind(&ReturnMoveOnlyType))
+ .Then(base::Bind(&PassMoveOnlyType));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_AnyThen) {
+ Promise<MoveOnlyType> promise =
+ promise::Race(promise::Create(base::Bind(&ReturnMoveOnlyType)),
+ promise::Create(base::Bind(&ReturnMoveOnlyType)),
+ promise::Create(base::Bind(&ReturnMoveOnlyType)))
+ .Then(base::Bind(&PassMoveOnlyType));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+MoveOnlyType PassFirstMoveOnlyType(MoveOnlyType type,
+ MoveOnlyType type2,
+ MoveOnlyType type3) {
+ return type;
+}
+} // namespace
+
+TEST_F(SingleThreadPromiseExecutorTest, MoveOnlyType_AllThen) {
+ Promise<MoveOnlyType> promise =
+ promise::All(promise::Create(base::Bind(&ReturnMoveOnlyType)),
+ promise::Create(base::Bind(&ReturnMoveOnlyType)),
+ promise::Create(base::Bind(&ReturnMoveOnlyType)))
+ .Then(base::Bind(&PassFirstMoveOnlyType));
+
+ promise_executor_->StartResolve(promise);
+ mock_task_runner_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+} // namespace promise
« no previous file with comments | « components/scheduler/promises/single_thread_promise_executor.cc ('k') | components/scheduler/promises/template_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698