1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #include "fcp/base/future.h"
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include <functional>
20*14675a02SAndroid Build Coastguard Worker #include <memory>
21*14675a02SAndroid Build Coastguard Worker #include <thread> // NOLINT(build/c++11)
22*14675a02SAndroid Build Coastguard Worker #include <type_traits>
23*14675a02SAndroid Build Coastguard Worker #include <utility>
24*14675a02SAndroid Build Coastguard Worker
25*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
26*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
27*14675a02SAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
28*14675a02SAndroid Build Coastguard Worker #include "absl/synchronization/barrier.h"
29*14675a02SAndroid Build Coastguard Worker #include "absl/time/time.h"
30*14675a02SAndroid Build Coastguard Worker #include "fcp/base/meta.h"
31*14675a02SAndroid Build Coastguard Worker #include "fcp/base/move_to_lambda.h"
32*14675a02SAndroid Build Coastguard Worker
33*14675a02SAndroid Build Coastguard Worker namespace fcp {
34*14675a02SAndroid Build Coastguard Worker namespace thread {
35*14675a02SAndroid Build Coastguard Worker
36*14675a02SAndroid Build Coastguard Worker using ::testing::Eq;
37*14675a02SAndroid Build Coastguard Worker
38*14675a02SAndroid Build Coastguard Worker // Future::Wait and Future::Take sometimes block. We'd like to test thread
39*14675a02SAndroid Build Coastguard Worker // interleavings where these calls block before being woken up. In the absence
40*14675a02SAndroid Build Coastguard Worker // of instrumentation of the underlying synchronization primitives, we just use
41*14675a02SAndroid Build Coastguard Worker // this arbitrary delay before unblocking operations (the other thread
42*14675a02SAndroid Build Coastguard Worker // "probably" has time to block). Note that the other ordering (Promise::Set
43*14675a02SAndroid Build Coastguard Worker // before Future::Take etc.) is easy to guarantee.
44*14675a02SAndroid Build Coastguard Worker constexpr absl::Duration kArbitraryDelay = absl::Milliseconds(50);
45*14675a02SAndroid Build Coastguard Worker
Delay()46*14675a02SAndroid Build Coastguard Worker void Delay() { absl::SleepFor(kArbitraryDelay); }
47*14675a02SAndroid Build Coastguard Worker
48*14675a02SAndroid Build Coastguard Worker // Freely copyable test value. We put in a 'valid' value and hope to find it
49*14675a02SAndroid Build Coastguard Worker // again.
50*14675a02SAndroid Build Coastguard Worker enum class V { kInvalid, kValid };
51*14675a02SAndroid Build Coastguard Worker
52*14675a02SAndroid Build Coastguard Worker // Move-only test value (we use this for Promise and Future, to make sure they
53*14675a02SAndroid Build Coastguard Worker // are compatible with move-only types - typically the harder case). This
54*14675a02SAndroid Build Coastguard Worker // corresponds to V:
55*14675a02SAndroid Build Coastguard Worker // Value present (not moved) <=> kValid
56*14675a02SAndroid Build Coastguard Worker // Value moved <=> kInvalid
57*14675a02SAndroid Build Coastguard Worker // The TakeV / SetV wrappers below actually do those conversions, since the test
58*14675a02SAndroid Build Coastguard Worker // assertions (e.g. Eq matcher) are difficult to use with move-only types.
59*14675a02SAndroid Build Coastguard Worker using UV = UniqueValue<Unit>;
60*14675a02SAndroid Build Coastguard Worker
61*14675a02SAndroid Build Coastguard Worker static_assert(!std::is_copy_constructible<UV>::value,
62*14675a02SAndroid Build Coastguard Worker "Expected to be move-only");
63*14675a02SAndroid Build Coastguard Worker
TakeV(Future<UV> future)64*14675a02SAndroid Build Coastguard Worker std::optional<V> TakeV(Future<UV> future) {
65*14675a02SAndroid Build Coastguard Worker std::optional<UV> maybe_uv = std::move(future).Take();
66*14675a02SAndroid Build Coastguard Worker if (maybe_uv.has_value()) {
67*14675a02SAndroid Build Coastguard Worker UniqueValue<Unit> uv = *std::move(maybe_uv);
68*14675a02SAndroid Build Coastguard Worker return uv.has_value() ? V::kValid : V::kInvalid;
69*14675a02SAndroid Build Coastguard Worker } else {
70*14675a02SAndroid Build Coastguard Worker return std::nullopt;
71*14675a02SAndroid Build Coastguard Worker }
72*14675a02SAndroid Build Coastguard Worker }
73*14675a02SAndroid Build Coastguard Worker
SetV(Promise<UV> promise)74*14675a02SAndroid Build Coastguard Worker void SetV(Promise<UV> promise) { std::move(promise).Set(UV(Unit{})); }
75*14675a02SAndroid Build Coastguard Worker
MakeBarrier()76*14675a02SAndroid Build Coastguard Worker absl::Barrier MakeBarrier() { return absl::Barrier(2); }
77*14675a02SAndroid Build Coastguard Worker
RunThreads(std::vector<std::function<void ()>> fns)78*14675a02SAndroid Build Coastguard Worker void RunThreads(std::vector<std::function<void()>> fns) {
79*14675a02SAndroid Build Coastguard Worker std::vector<std::thread> threads;
80*14675a02SAndroid Build Coastguard Worker for (auto& fn : fns) {
81*14675a02SAndroid Build Coastguard Worker threads.push_back(std::thread(std::move(fn)));
82*14675a02SAndroid Build Coastguard Worker }
83*14675a02SAndroid Build Coastguard Worker
84*14675a02SAndroid Build Coastguard Worker for (auto& thread : threads) {
85*14675a02SAndroid Build Coastguard Worker thread.join();
86*14675a02SAndroid Build Coastguard Worker }
87*14675a02SAndroid Build Coastguard Worker }
88*14675a02SAndroid Build Coastguard Worker
RunThreadsWithFuture(std::function<void (Promise<UV>)> promise_fn,std::function<void (Future<UV>)> future_fn)89*14675a02SAndroid Build Coastguard Worker void RunThreadsWithFuture(std::function<void(Promise<UV>)> promise_fn,
90*14675a02SAndroid Build Coastguard Worker std::function<void(Future<UV>)> future_fn) {
91*14675a02SAndroid Build Coastguard Worker FuturePair<UV> pair = MakeFuture<UV>();
92*14675a02SAndroid Build Coastguard Worker
93*14675a02SAndroid Build Coastguard Worker MoveToLambdaWrapper<Promise<UV>> promise_capture =
94*14675a02SAndroid Build Coastguard Worker MoveToLambda(std::move(pair.promise));
95*14675a02SAndroid Build Coastguard Worker auto promise_fn_wrapped = [promise_capture, promise_fn]() mutable {
96*14675a02SAndroid Build Coastguard Worker promise_fn(std::move(*promise_capture));
97*14675a02SAndroid Build Coastguard Worker };
98*14675a02SAndroid Build Coastguard Worker
99*14675a02SAndroid Build Coastguard Worker MoveToLambdaWrapper<Future<UV>> future_capture =
100*14675a02SAndroid Build Coastguard Worker MoveToLambda(std::move(pair.future));
101*14675a02SAndroid Build Coastguard Worker auto future_fn_wrapped = [future_capture, future_fn]() mutable {
102*14675a02SAndroid Build Coastguard Worker future_fn(std::move(*future_capture));
103*14675a02SAndroid Build Coastguard Worker };
104*14675a02SAndroid Build Coastguard Worker
105*14675a02SAndroid Build Coastguard Worker RunThreads({std::move(promise_fn_wrapped), std::move(future_fn_wrapped)});
106*14675a02SAndroid Build Coastguard Worker }
107*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,WaitTimeouts)108*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, WaitTimeouts) {
109*14675a02SAndroid Build Coastguard Worker absl::Barrier waited = MakeBarrier();
110*14675a02SAndroid Build Coastguard Worker absl::Barrier set = MakeBarrier();
111*14675a02SAndroid Build Coastguard Worker
112*14675a02SAndroid Build Coastguard Worker auto promise_fn = [&](Promise<UV> promise) {
113*14675a02SAndroid Build Coastguard Worker waited.Block();
114*14675a02SAndroid Build Coastguard Worker SetV(std::move(promise));
115*14675a02SAndroid Build Coastguard Worker set.Block();
116*14675a02SAndroid Build Coastguard Worker };
117*14675a02SAndroid Build Coastguard Worker
118*14675a02SAndroid Build Coastguard Worker auto future_fn = [&](Future<UV> future) {
119*14675a02SAndroid Build Coastguard Worker // Before set: Timeout should elapse
120*14675a02SAndroid Build Coastguard Worker EXPECT_FALSE(future.Wait(absl::Milliseconds(1)))
121*14675a02SAndroid Build Coastguard Worker << "Future shouldn't be ready yet";
122*14675a02SAndroid Build Coastguard Worker waited.Block();
123*14675a02SAndroid Build Coastguard Worker set.Block();
124*14675a02SAndroid Build Coastguard Worker // After set: Zero timeout should be sufficient
125*14675a02SAndroid Build Coastguard Worker EXPECT_TRUE(future.Wait(absl::ZeroDuration()))
126*14675a02SAndroid Build Coastguard Worker << "Future should be ready without waiting";
127*14675a02SAndroid Build Coastguard Worker };
128*14675a02SAndroid Build Coastguard Worker
129*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
130*14675a02SAndroid Build Coastguard Worker }
131*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,TakeAfterSet)132*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, TakeAfterSet) {
133*14675a02SAndroid Build Coastguard Worker absl::Barrier set = MakeBarrier();
134*14675a02SAndroid Build Coastguard Worker
135*14675a02SAndroid Build Coastguard Worker auto promise_fn = [&](Promise<UV> promise) {
136*14675a02SAndroid Build Coastguard Worker SetV(std::move(promise));
137*14675a02SAndroid Build Coastguard Worker set.Block();
138*14675a02SAndroid Build Coastguard Worker };
139*14675a02SAndroid Build Coastguard Worker
140*14675a02SAndroid Build Coastguard Worker auto future_fn = [&](Future<UV> future) {
141*14675a02SAndroid Build Coastguard Worker set.Block();
142*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(TakeV(std::move(future)), Eq(V::kValid));
143*14675a02SAndroid Build Coastguard Worker };
144*14675a02SAndroid Build Coastguard Worker
145*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
146*14675a02SAndroid Build Coastguard Worker }
147*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,TakeProbablyBeforeSet)148*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, TakeProbablyBeforeSet) {
149*14675a02SAndroid Build Coastguard Worker auto promise_fn = [](Promise<UV> promise) {
150*14675a02SAndroid Build Coastguard Worker Delay();
151*14675a02SAndroid Build Coastguard Worker SetV(std::move(promise));
152*14675a02SAndroid Build Coastguard Worker };
153*14675a02SAndroid Build Coastguard Worker
154*14675a02SAndroid Build Coastguard Worker auto future_fn = [](Future<UV> future) {
155*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(TakeV(std::move(future)), Eq(V::kValid));
156*14675a02SAndroid Build Coastguard Worker };
157*14675a02SAndroid Build Coastguard Worker
158*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
159*14675a02SAndroid Build Coastguard Worker }
160*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,AbandonWhileProbablyTaking)161*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, AbandonWhileProbablyTaking) {
162*14675a02SAndroid Build Coastguard Worker auto promise_fn = [](Promise<UV> promise) {
163*14675a02SAndroid Build Coastguard Worker Delay();
164*14675a02SAndroid Build Coastguard Worker { Promise<UV> dies = std::move(promise); }
165*14675a02SAndroid Build Coastguard Worker };
166*14675a02SAndroid Build Coastguard Worker
167*14675a02SAndroid Build Coastguard Worker auto future_fn = [](Future<UV> future) {
168*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(std::move(future).Take(), Eq(std::nullopt));
169*14675a02SAndroid Build Coastguard Worker };
170*14675a02SAndroid Build Coastguard Worker
171*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
172*14675a02SAndroid Build Coastguard Worker }
173*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,SetWhileProbablyWaiting)174*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, SetWhileProbablyWaiting) {
175*14675a02SAndroid Build Coastguard Worker auto promise_fn = [](Promise<UV> promise) {
176*14675a02SAndroid Build Coastguard Worker Delay();
177*14675a02SAndroid Build Coastguard Worker SetV(std::move(promise));
178*14675a02SAndroid Build Coastguard Worker };
179*14675a02SAndroid Build Coastguard Worker
180*14675a02SAndroid Build Coastguard Worker auto future_fn = [](Future<UV> future) {
181*14675a02SAndroid Build Coastguard Worker EXPECT_TRUE(future.Wait(absl::InfiniteDuration()));
182*14675a02SAndroid Build Coastguard Worker };
183*14675a02SAndroid Build Coastguard Worker
184*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
185*14675a02SAndroid Build Coastguard Worker }
186*14675a02SAndroid Build Coastguard Worker
TEST(FutureTest,AbandonWhileProbablyWaiting)187*14675a02SAndroid Build Coastguard Worker TEST(FutureTest, AbandonWhileProbablyWaiting) {
188*14675a02SAndroid Build Coastguard Worker auto promise_fn = [](Promise<UV> promise) {
189*14675a02SAndroid Build Coastguard Worker Delay();
190*14675a02SAndroid Build Coastguard Worker { Promise<UV> dies = std::move(promise); }
191*14675a02SAndroid Build Coastguard Worker };
192*14675a02SAndroid Build Coastguard Worker
193*14675a02SAndroid Build Coastguard Worker auto future_fn = [](Future<UV> future) {
194*14675a02SAndroid Build Coastguard Worker EXPECT_TRUE(future.Wait(absl::InfiniteDuration()));
195*14675a02SAndroid Build Coastguard Worker };
196*14675a02SAndroid Build Coastguard Worker
197*14675a02SAndroid Build Coastguard Worker RunThreadsWithFuture(std::move(promise_fn), std::move(future_fn));
198*14675a02SAndroid Build Coastguard Worker }
199*14675a02SAndroid Build Coastguard Worker
200*14675a02SAndroid Build Coastguard Worker } // namespace thread
201*14675a02SAndroid Build Coastguard Worker } // namespace fcp
202