1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/Portability.h>
18 
19 #include <folly/CancellationToken.h>
20 #include <folly/experimental/coro/Baton.h>
21 #include <folly/experimental/coro/RustAdaptors.h>
22 #include <folly/experimental/coro/Sleep.h>
23 #include <folly/portability/GTest.h>
24 #include <folly/synchronization/Baton.h>
25 
26 #include <chrono>
27 
28 #if FOLLY_HAS_COROUTINES
29 
30 template <typename T>
getPollFuture(folly::coro::PollFuture<T> future)31 T getPollFuture(folly::coro::PollFuture<T> future) {
32   while (true) {
33     folly::Baton<> b;
34     auto poll = future.poll([&] { b.post(); });
35     if (poll) {
36       return std::move(poll).value();
37     }
38     b.wait();
39   }
40 }
41 
42 template <typename T>
getNextPollStream(folly::coro::PollStream<T> & stream)43 folly::Optional<T> getNextPollStream(folly::coro::PollStream<T>& stream) {
44   while (true) {
45     folly::Baton<> b;
46     auto poll = stream.poll([&] { b.post(); });
47     if (poll) {
48       return std::move(poll).value();
49     }
50     b.wait();
51   }
52 }
53 
task42()54 folly::coro::Task<int> task42() {
55   co_await folly::coro::sleep(std::chrono::milliseconds{10});
56   co_await folly::coro::sleep(std::chrono::milliseconds{10});
57   co_return 42;
58 }
59 
TEST(RustAdaptorsTest,PollFuture)60 TEST(RustAdaptorsTest, PollFuture) {
61   EXPECT_EQ(42, getPollFuture(folly::coro::PollFuture<int>(task42())));
62 }
63 
TEST(RustAdaptorsTest,PollFutureSemiFuture)64 TEST(RustAdaptorsTest, PollFutureSemiFuture) {
65   EXPECT_EQ(42, getPollFuture(folly::coro::PollFuture<int>(task42().semi())));
66 }
67 
stream123()68 folly::coro::AsyncGenerator<int> stream123() {
69   co_await folly::coro::sleep(std::chrono::milliseconds{10});
70   co_await folly::coro::sleep(std::chrono::milliseconds{10});
71   co_yield 1;
72   co_await folly::coro::sleep(std::chrono::milliseconds{10});
73   co_yield 2;
74   co_await folly::coro::sleep(std::chrono::milliseconds{10});
75   co_await folly::coro::sleep(std::chrono::milliseconds{10});
76   co_yield 3;
77 }
78 
TEST(RustAdaptorsTest,PollStream)79 TEST(RustAdaptorsTest, PollStream) {
80   auto stream = folly::coro::PollStream<int>(stream123());
81   EXPECT_EQ(1, getNextPollStream(stream).value());
82   EXPECT_EQ(2, getNextPollStream(stream).value());
83   EXPECT_EQ(3, getNextPollStream(stream).value());
84   EXPECT_FALSE(getNextPollStream(stream).hasValue());
85 }
86 
cancellationTask(bool & done)87 folly::coro::Task<void> cancellationTask(bool& done) {
88   folly::coro::Baton b;
89   folly::CancellationCallback cb(
90       co_await folly::coro::co_current_cancellation_token, [&] { b.post(); });
91   co_await b;
92   done = true;
93 }
94 
TEST(RustAdaptorsTest,PollFutureCancellation)95 TEST(RustAdaptorsTest, PollFutureCancellation) {
96   bool done{false};
97   {
98     auto future = folly::coro::PollFuture<void>(cancellationTask(done));
99     EXPECT_EQ(folly::none, future.poll([] {}));
100     EXPECT_FALSE(done);
101   }
102   EXPECT_TRUE(done);
103 }
104 
cancellationStream(bool & done)105 folly::coro::AsyncGenerator<int> cancellationStream(bool& done) {
106   co_yield 1;
107   co_yield 2;
108   co_await cancellationTask(done);
109 }
110 
TEST(RustAdaptorsTest,PollStreamCancellation)111 TEST(RustAdaptorsTest, PollStreamCancellation) {
112   bool done{false};
113   {
114     auto stream = folly::coro::PollStream<int>(cancellationStream(done));
115     EXPECT_EQ(1, getNextPollStream(stream).value());
116     EXPECT_EQ(2, getNextPollStream(stream).value());
117     EXPECT_EQ(folly::none, stream.poll([] {}));
118     EXPECT_FALSE(done);
119   }
120   EXPECT_TRUE(done);
121 }
122 
123 #endif
124