Skip to content

Commit

Permalink
Promises: Add TakeResolveValueForTesting & TakeRejectValueForTesting
Browse files Browse the repository at this point in the history
These helpers will be useful to cutdown promise related test boilerplate.

Bug: 906125
Change-Id: Ia4bec95c4be7d2600cb12b630a7f81885ccbfb05
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1641284
Commit-Queue: Alex Clarke <alexclarke@chromium.org>
Reviewed-by: Gabriel Charette <gab@chromium.org>
Reviewed-by: François Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#667938}
  • Loading branch information
Alex Clarke authored and Commit Bot committed Jun 11, 2019
1 parent d280191 commit 6fa9ce2
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
42 changes: 42 additions & 0 deletions base/task/promise/promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef BASE_TASK_PROMISE_PROMISE_H_
#define BASE_TASK_PROMISE_PROMISE_H_

#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/task/promise/all_container_executor.h"
#include "base/task/promise/all_tuple_executor.h"
Expand Down Expand Up @@ -72,6 +73,47 @@ class Promise {
return abstract_promise_->IsCanceled();
}

// Waits until the promise has settled and if resolved it returns the resolved
// value.
template <typename T = ResolveType,
std::enable_if_t<!std::is_reference<T>::value &&
!std::is_void<T>::value>* = nullptr>
T TakeResolveValueForTesting() {
static_assert(!std::is_same<NoResolve, T>::value,
"A NoResolve promise can't resolve.");
if (!abstract_promise_->IsSettled()) {
RunLoop run_loop;
FinallyHere(FROM_HERE, run_loop.QuitClosure());
run_loop.Run();
}
DCHECK(abstract_promise_->IsResolved())
<< "Can't take resolved value, promise wasn't resolved.";
return std::move(
unique_any_cast<Resolved<T>>(&abstract_promise_->TakeValue().value())
->value);
}

// Waits until the promise has settled and if rejected it returns the rejected
// value.
template <typename T = RejectType,
std::enable_if_t<!std::is_reference<T>::value &&
!std::is_void<T>::value>* = nullptr>
T TakeRejectValueForTesting() {
static_assert(!std::is_same<NoReject, T>::value,
"A NoReject promise can't reject.");
if (!abstract_promise_->IsSettled()) {
RunLoop run_loop;
FinallyHere(FROM_HERE, run_loop.QuitClosure());
run_loop.Run();
}
abstract_promise_->IgnoreUncaughtCatchForTesting();
DCHECK(abstract_promise_->IsRejected())
<< "Can't take rejected value, promise wasn't rejected.";
return std::move(
unique_any_cast<Rejected<T>>(&abstract_promise_->TakeValue().value())
->value);
}

bool IsResolvedForTesting() const {
DCHECK(abstract_promise_);
return abstract_promise_->IsResolved();
Expand Down
60 changes: 60 additions & 0 deletions base/task/promise/promise_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2057,4 +2057,64 @@ TEST_F(PromiseTest, AllVoidContainerMultipleRejectsAfterExecute) {
mpr4.Reject();
}

TEST_F(PromiseTest, TakeResolveValueForTesting) {
ManualPromiseResolver<void> p1(FROM_HERE);

Promise<int> p2 =
p1.promise().ThenHere(FROM_HERE, BindOnce([]() { return 123; }));

p1.Resolve();

EXPECT_EQ(123, p2.TakeResolveValueForTesting());
}

TEST_F(PromiseTest, TakeResolveValueForTestingMoveOnlyType) {
ManualPromiseResolver<void> p1(FROM_HERE);

Promise<std::unique_ptr<int>> p2 = p1.promise().ThenHere(
FROM_HERE, BindOnce([]() { return std::make_unique<int>(123); }));

p1.Resolve();

EXPECT_EQ(123, *p2.TakeResolveValueForTesting());
}

TEST_F(PromiseTest, TakeResolveValueForTestingNotResolved) {
ManualPromiseResolver<int, int> p1(FROM_HERE,
RejectPolicy::kCatchNotRequired);

p1.Reject(123);

EXPECT_DCHECK_DEATH({ p1.promise().TakeResolveValueForTesting(); });
}

TEST_F(PromiseTest, TakeRejectedValueForTesting) {
ManualPromiseResolver<void, void> p1(FROM_HERE);

Promise<int, int> p2 = p1.promise().ThenHere(
FROM_HERE, BindOnce([]() { return Resolved<int>(123); }),
BindOnce([]() { return Rejected<int>(456); }));

p1.Reject();

EXPECT_EQ(456, p2.TakeRejectValueForTesting());
}

TEST_F(PromiseTest, TakeRejectedValueForTestingMoveOnlyType) {
ManualPromiseResolver<void, std::unique_ptr<int>> p1(FROM_HERE);

p1.Reject(std::make_unique<int>(456));

EXPECT_EQ(456, *p1.promise().TakeRejectValueForTesting());
}

TEST_F(PromiseTest, TakeRejectedValueForTestingNotRejected) {
ManualPromiseResolver<int, int> p1(FROM_HERE,
RejectPolicy::kCatchNotRequired);

p1.Resolve(123);

EXPECT_DCHECK_DEATH({ p1.promise().TakeRejectValueForTesting(); });
}

} // namespace base

0 comments on commit 6fa9ce2

Please sign in to comment.