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

Unified Diff: components/scheduler/promises/promise_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
« no previous file with comments | « components/scheduler/promises/promise_internal.h ('k') | components/scheduler/promises/rejectable.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/scheduler/promises/promise_unittest.cc
diff --git a/components/scheduler/promises/promise_unittest.cc b/components/scheduler/promises/promise_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..af810c69a01d457cb4c9b44a8cd9bc7f81b831b0
--- /dev/null
+++ b/components/scheduler/promises/promise_unittest.cc
@@ -0,0 +1,1198 @@
+// 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 <queue>
+
+#include "base/bind.h"
+#include "components/scheduler/promises/promise_executor.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::ElementsAre;
+using testing::WhenSorted;
+
+namespace promise {
+
+class PromiseTest : public testing::Test {
+ public:
+ PromiseTest() {}
+ ~PromiseTest() override {}
+
+ void SetUp() override { executor_.reset(new internal::PromiseExecutor()); }
+
+ scoped_ptr<internal::PromiseExecutor> 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(PromiseTest, NonVoidPromise) {
+ Promise<int> promise(promise::Create(base::Bind(&ReturnOne)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, AssignPromise) {
+ Promise<int> promise = promise::Create(base::Bind(&ReturnOne));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, Then) {
+ Promise<int> promise(
+ promise::Create(base::Bind(&ReturnOne)).Then(base::Bind(&Add, 1)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(2, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, AssignThen) {
+ Promise<int> promise =
+ promise::Create(base::Bind(&ReturnOne)).Then(base::Bind(&Add, 1));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(2, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, ThenVoid) {
+ int value = 0;
+ Promise<void> promise(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&RecordParam, &value)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(1, value);
+}
+
+TEST_F(PromiseTest, VoidThenVoid) {
+ int value = 0;
+ int value2 = 0;
+ Promise<void> promise(promise::Create(base::Bind(&RecordParam, &value, 1))
+ .Then(base::Bind(&RecordParam, &value2, 2)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(1, value);
+ EXPECT_EQ(2, value2);
+}
+
+TEST_F(PromiseTest, VoidThenInt) {
+ int value = 0;
+ Promise<int> promise(promise::Create(base::Bind(&RecordParam, &value, 2))
+ .Then(base::Bind(&ReturnOne)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(2, value);
+ EXPECT_EQ(1, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, ThenChaining) {
+ Promise<int> promise(promise::Create(base::Bind(&ReturnOne))
+ .Then(base::Bind(&Add, 1))
+ .Then(base::Bind(&Add, 1))
+ .Then(base::Bind(&Add, 1)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(4, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise11);
+ executor_->StartResolve(promise12);
+ executor_->StartResolve(promise13);
+ executor_->StartResolve(promise14);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise11);
+ executor_->StartResolve(promise12);
+ executor_->StartResolve(promise13);
+ executor_->StartResolve(promise14);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise10);
+ executor_->RunUntilIdle();
+
+ executor_->StartResolve(promise11);
+ executor_->StartResolve(promise12);
+ executor_->StartResolve(promise13);
+ executor_->StartResolve(promise14);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise11.GetResolved());
+ EXPECT_EQ(12, promise12.GetResolved());
+ EXPECT_EQ(13, promise13.GetResolved());
+ EXPECT_EQ(14, promise14.GetResolved());
+}
+
+TEST_F(PromiseTest, AllThen) {
+ Promise<int> promise(promise::All(promise::Create(base::Bind(&ReturnOne)),
+ promise::Create(base::Bind(&ReturnTrue)))
+ .Then(base::Bind(&CondTimesThree)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(3, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, AssignAllThen) {
+ Promise<int> promise = promise::All(promise::Create(base::Bind(&ReturnOne)),
+ promise::Create(base::Bind(&ReturnTrue)))
+ .Then(base::Bind(&CondTimesThree));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(3, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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);
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(10, 11, 12, 13, 14, 0, 1, 2, 3, 4));
+}
+
+TEST_F(PromiseTest, 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);
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+
+ executor_->ResolveOnePromise();
+
+ promiseB.SetEager(false);
+ promiseA.SetEager(true);
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(10, 0, 1, 2, 3, 4, 11, 12, 13, 14));
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseB);
+ executor_->StartResolve(promiseC);
+ executor_->RunUntilIdle();
+
+ // The interleaving of promiseB and promiseC execution is undefined.
+ EXPECT_THAT(run_order, WhenSorted(ElementsAre(0, 1, 2, 3, 4, 5)));
+}
+
+TEST_F(PromiseTest, Cancel) {
+ std::vector<int> run_order;
+
+ Promise<void> promise(
+ promise::Create(base::Bind(&RecordOrder, 1, &run_order)));
+
+ executor_->StartResolve(promise);
+ promise.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(run_order.empty());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+
+ promiseB.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseB);
+ executor_->StartResolve(promiseC);
+
+ promiseB.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5));
+}
+
+TEST_F(PromiseTest, CancelAndReresolve) {
+ std::vector<int> run_order;
+
+ Promise<void> promise(
+ promise::Create(base::Bind(&RecordOrder, 1, &run_order)));
+
+ executor_->StartResolve(promise);
+ promise.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(run_order.empty());
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(1));
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+
+ promiseB.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4, 10, 11, 12, 13, 14));
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseB);
+ executor_->StartResolve(promiseC);
+
+ promiseB.Cancel();
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5));
+
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 4, 5, 2, 3));
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(10, promiseA.GetResolved());
+ EXPECT_EQ(2, promiseB.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(11, promiseA.GetResolved());
+ EXPECT_EQ(3, promiseB.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+ executor_->RunUntilIdle();
+ EXPECT_EQ(10, promiseA.GetResolved());
+ EXPECT_EQ(2, promiseB.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promiseA);
+ executor_->StartResolve(promiseB);
+ executor_->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(PromiseTest, 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))));
+
+ executor_->StartResolve(promise_root);
+ executor_->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();
+ executor_->RunUntilIdle();
+ EXPECT_THAT(fixture.run_order_,
+ ElementsAre(std::string("R"), std::string("Root")));
+}
+
+TEST_F(PromiseTest, 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));
+
+ executor_->StartResolve(promise);
+
+ promiseB.Resolve(10);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseB.Resolve(10);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(10, chosen);
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseB.Resolve();
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(1, chosen);
+}
+
+namespace {
+Promise<int> ReturnAPromise(int value) {
+ return promise::Create(value + 1);
+}
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseD.Resolve(10);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(11, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseD.Resolve(0);
+ promiseC.Resolve(10);
+ promiseB.Resolve(100);
+ promiseA.Resolve(1000);
+
+ executor_->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(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseD.Resolve(15);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(15, value);
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseD.Resolve();
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(9, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ promiseD.Resolve();
+ executor_->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(PromiseTest, 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)));
+
+ executor_->StartResolve(promise);
+
+ executor_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
+}
+
+TEST_F(PromiseTest, ResolvePromiseWithAPromise) {
+ Promise<int> promise(promise::Create<int>());
+
+ promise.Resolve(promise::Create(base::Bind(&ReturnTen)));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(10, promise.GetResolved());
+}
+
+TEST_F(PromiseTest, ResolvePromiseWithAVoidPromise) {
+ Promise<void> promise(promise::Create<void>());
+
+ int value = 0;
+ promise.Resolve(promise::Create(base::Bind(&RecordParam, &value, 5)));
+
+ executor_->StartResolve(promise);
+ executor_->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(PromiseTest, MoveOnlyType_ResolvedPromise_ViaMove) {
+ MoveOnlyType src;
+ Promise<MoveOnlyType> promise = promise::Create(std::move(src));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(PromiseTest, MoveOnlyType_ResolvedPromise_Constructed) {
+ Promise<MoveOnlyType> promise = promise::Create(MoveOnlyType());
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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(PromiseTest, MoveOnlyType_ReturnedFromClosure) {
+ Promise<MoveOnlyType> promise =
+ promise::Create(base::Bind(&ReturnMoveOnlyType));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+void TakeMoveOnlyType(MoveOnlyType type) {
+ MoveOnlyType dest = std::move(type);
+}
+} // namespace
+
+TEST_F(PromiseTest, MoveOnlyType_PassedToThenClosure) {
+ Promise<void> promise = promise::Create(base::Bind(&ReturnMoveOnlyType))
+ .Then(base::Bind(&TakeMoveOnlyType));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+}
+
+namespace {
+MoveOnlyType PassMoveOnlyType(MoveOnlyType type) {
+ return type;
+}
+} // namespace
+
+TEST_F(PromiseTest, MoveOnlyType_PassedToAndReturnedFromThenClosure) {
+ Promise<MoveOnlyType> promise =
+ promise::Create(base::Bind(&ReturnMoveOnlyType))
+ .Then(base::Bind(&PassMoveOnlyType));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+TEST_F(PromiseTest, 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));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+MoveOnlyType PassFirstMoveOnlyType(MoveOnlyType type,
+ MoveOnlyType type2,
+ MoveOnlyType type3) {
+ return type;
+}
+} // namespace
+
+TEST_F(PromiseTest, 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));
+
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ MoveOnlyType dest = std::move(promise.GetResolved());
+}
+
+namespace {
+Rejectable<int, bool> ReturnIntResolve() {
+ return Resolve(10);
+}
+
+Rejectable<int, bool> ReturnBoolReject() {
+ return Reject(true);
+}
+} // namespace
+
+TEST_F(PromiseTest, IntBoolRejectable_Resolve) {
+ Rejectable<int, bool> rejectable = ReturnIntResolve();
+
+ EXPECT_TRUE(rejectable.is_resolved());
+ EXPECT_EQ(10, rejectable.resolved());
+}
+
+TEST_F(PromiseTest, IntBoolRejectable_Reject) {
+ Rejectable<int, bool> rejectable = ReturnBoolReject();
+
+ EXPECT_FALSE(rejectable.is_resolved());
+ EXPECT_TRUE(rejectable.reject_reason());
+}
+
+namespace {
+Rejectable<void, void> ReturnVoidResolve() {
+ return Resolve();
+}
+
+Rejectable<void, void> ReturnVoidReject() {
+ return Reject();
+}
+} // namespace
+
+TEST_F(PromiseTest, VoidVoidRejectable_Resolve) {
+ Rejectable<void, void> rejectable = ReturnVoidResolve();
+
+ EXPECT_TRUE(rejectable.is_resolved());
+}
+
+TEST_F(PromiseTest, VoidVoidRejectable_Reject) {
+ Rejectable<void, void> rejectable = ReturnVoidReject();
+
+ EXPECT_FALSE(rejectable.is_resolved());
+}
+
+TEST_F(PromiseTest, RejectablePromise_Resolve) {
+ Promise<Rejectable<int, bool>> promise(
+ promise::Create<Rejectable<int, bool>>());
+
+ promise.Resolve(10);
+
+ EXPECT_TRUE(promise.is_resolved());
+ EXPECT_FALSE(promise.is_rejected());
+ EXPECT_EQ(10, promise.GetResolved().resolved());
+}
+
+TEST_F(PromiseTest, RejectablePromise_Reject) {
+ Promise<Rejectable<int, bool>> promise(
+ promise::Create<Rejectable<int, bool>>());
+
+ promise.Reject(true);
+
+ EXPECT_FALSE(promise.is_resolved());
+ EXPECT_TRUE(promise.is_rejected());
+ EXPECT_TRUE(promise.GetResolved().reject_reason());
+}
+
+namespace {
+Rejectable<int, int> ResolveWithTenFunc() {
+ return Resolve(10);
+}
+
+Rejectable<int, int> RejectWithTwentyFunc() {
+ return Reject(20);
+}
+}
+
+TEST_F(PromiseTest, RejectableFunction_Resolve) {
+ Promise<Rejectable<int, int>> promise(
+ promise::Create(base::Bind(&ResolveWithTenFunc)));
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(promise.is_resolved());
+ EXPECT_FALSE(promise.is_rejected());
+ EXPECT_EQ(10, promise.GetResolved().resolved());
+}
+
+TEST_F(PromiseTest, RejectableFunction_Reject) {
+ Promise<Rejectable<int, int>> promise(
+ promise::Create(base::Bind(&RejectWithTwentyFunc)));
+ executor_->StartResolve(promise);
+ executor_->RunUntilIdle();
+
+ EXPECT_FALSE(promise.is_resolved());
+ EXPECT_TRUE(promise.is_rejected());
+ EXPECT_EQ(20, promise.GetResolved().reject_reason());
+}
+
+TEST_F(PromiseTest, RejectablePromise_ResolveWithPromiseThatResolves) {
+ Promise<Rejectable<int, int>> promise =
+ promise::Create<Rejectable<int, int>>();
+ executor_->StartResolve(promise);
+
+ promise.Resolve(promise::Create(base::Bind(&ResolveWithTenFunc)));
+
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(promise.is_resolved());
+ EXPECT_FALSE(promise.is_rejected());
+ EXPECT_EQ(10, promise.GetResolved().resolved());
+}
+
+TEST_F(PromiseTest, RejectablePromise_ResolveWithPromiseThatRejects) {
+ Promise<Rejectable<int, int>> promise =
+ promise::Create<Rejectable<int, int>>();
+ executor_->StartResolve(promise);
+
+ promise.Resolve(promise::Create(base::Bind(&RejectWithTwentyFunc)));
+
+ executor_->RunUntilIdle();
+
+ EXPECT_FALSE(promise.is_resolved());
+ EXPECT_TRUE(promise.is_rejected());
+ EXPECT_EQ(20, promise.GetResolved().reject_reason());
+}
+
+TEST_F(PromiseTest, RejectablePromise_ResolveWithResolvedPromise) {
+ Promise<Rejectable<int, int>> rejected_promise =
+ promise::Create<Rejectable<int, int>>();
+
+ rejected_promise.Resolve(1337);
+
+ Promise<Rejectable<int, int>> promise =
+ promise::Create<Rejectable<int, int>>();
+ executor_->StartResolve(promise);
+
+ promise.Resolve(rejected_promise);
+
+ EXPECT_TRUE(promise.is_resolved());
+ EXPECT_FALSE(promise.is_rejected());
+ EXPECT_EQ(1337, promise.GetResolved().resolved());
+}
+
+TEST_F(PromiseTest, RejectablePromise_ResolveWithRectedPromise) {
+ Promise<Rejectable<int, int>> rejected_promise =
+ promise::Create<Rejectable<int, int>>();
+
+ rejected_promise.Reject(123);
+
+ Promise<Rejectable<int, int>> promise =
+ promise::Create<Rejectable<int, int>>();
+ executor_->StartResolve(promise);
+
+ promise.Resolve(rejected_promise);
+
+ EXPECT_FALSE(promise.is_resolved());
+ EXPECT_TRUE(promise.is_rejected());
+ EXPECT_EQ(123, promise.GetResolved().reject_reason());
+}
+
+namespace {
+void OnRejectableIntBool(bool* was_rejected,
+ int* resolved_result,
+ bool* reject_reason,
+ Rejectable<int, bool> result) {
+ *was_rejected = result.is_rejected();
+ if (result.is_rejected()) {
+ *reject_reason = result.reject_reason();
+ } else {
+ *resolved_result = result.resolved();
+ }
+}
+}
+
+TEST_F(PromiseTest, RejectablePromise_ThenResolve) {
+ Promise<Rejectable<int, bool>> manually_resolved_promise(
+ promise::Create<Rejectable<int, bool>>());
+
+ bool was_rejected = false;
+ int resolved_result = 0;
+ bool reject_reason = false;
+ Promise<void> promise(manually_resolved_promise.Then(base::Bind(
+ &OnRejectableIntBool, &was_rejected, &resolved_result, &reject_reason)));
+
+ executor_->StartResolve(promise);
+
+ manually_resolved_promise.Resolve(10);
+ executor_->RunUntilIdle();
+
+ EXPECT_FALSE(was_rejected);
+ EXPECT_EQ(10, resolved_result);
+}
+
+TEST_F(PromiseTest, RejectablePromise_ThenReject) {
+ Promise<Rejectable<int, bool>> manually_resolved_promise(
+ promise::Create<Rejectable<int, bool>>());
+
+ bool was_rejected = false;
+ int resolved_result = 0;
+ bool reject_reason = false;
+ Promise<void> promise(manually_resolved_promise.Then(base::Bind(
+ &OnRejectableIntBool, &was_rejected, &resolved_result, &reject_reason)));
+
+ executor_->StartResolve(promise);
+
+ manually_resolved_promise.Reject(true);
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(was_rejected);
+ EXPECT_TRUE(reject_reason);
+}
+
+namespace {
+int GetRejectionReason(Rejectable<void, int> a,
+ Rejectable<void, int> b,
+ Rejectable<void, int> c,
+ Rejectable<void, int> d) {
+ if (a.is_rejected())
+ return a.reject_reason();
+ if (b.is_rejected())
+ return b.reject_reason();
+ if (c.is_rejected())
+ return c.reject_reason();
+ if (d.is_rejected())
+ return d.reject_reason();
+ return -1;
+}
+}
+
+TEST_F(PromiseTest, RejectablePromise_FastFail) {
+ Promise<Rejectable<void, int>> promise1(
+ promise::Create<Rejectable<void, int>>());
+ Promise<Rejectable<void, int>> promise2(
+ promise::Create<Rejectable<void, int>>());
+ Promise<Rejectable<void, int>> promise3(
+ promise::Create<Rejectable<void, int>>());
+ Promise<Rejectable<void, int>> promise4(
+ promise::Create<Rejectable<void, int>>());
+ Promise<int> promise = promise::All(promise1, promise2, promise3, promise4)
+ .Then(base::Bind(&GetRejectionReason));
+
+ executor_->StartResolve(promise);
+
+ promise4.Reject(4);
+ executor_->RunUntilIdle();
+
+ EXPECT_EQ(4, promise.GetResolved());
+}
+
+namespace {
+void OnRejectableIntInt(bool* was_rejected,
+ int* resolved_result,
+ int* reject_reason,
+ Rejectable<int, int> result) {
+ *was_rejected = result.is_rejected();
+ if (result.is_rejected()) {
+ *reject_reason = result.reject_reason();
+ } else {
+ DCHECK(result.is_resolved());
+ *resolved_result = result.resolved();
+ }
+}
+}
+
+TEST_F(PromiseTest, RejectablePromise_Race) {
+ Promise<Rejectable<int, int>> promise1(
+ promise::Create<Rejectable<int, int>>());
+ Promise<Rejectable<int, int>> promise2(
+ promise::Create<Rejectable<int, int>>());
+ Promise<Rejectable<int, int>> promise3(
+ promise::Create<Rejectable<int, int>>());
+ Promise<Rejectable<int, int>> promise4(
+ promise::Create<Rejectable<int, int>>());
+
+ bool was_rejected = false;
+ int resolved_result = 0;
+ int reject_reason = 0;
+ Promise<void> promise =
+ promise::Race(promise1, promise2, promise3, promise4)
+ .Then(base::Bind(&OnRejectableIntInt, &was_rejected, &resolved_result,
+ &reject_reason));
+
+ executor_->StartResolve(promise);
+
+ promise3.Reject(3);
+ executor_->RunUntilIdle();
+
+ EXPECT_TRUE(was_rejected);
+ EXPECT_EQ(3, reject_reason);
+}
+
+} // namespace promise
« no previous file with comments | « components/scheduler/promises/promise_internal.h ('k') | components/scheduler/promises/rejectable.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698