xref: /aosp_15_r20/external/cronet/base/test/repeating_test_future_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/test/repeating_test_future.h"
6 
7 #include "base/task/single_thread_task_runner.h"
8 #include "base/test/bind.h"
9 #include "base/test/gtest_util.h"
10 #include "base/test/task_environment.h"
11 #include "testing/gtest/include/gtest/gtest-spi.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base::test {
15 
16 namespace {
17 
18 struct MoveOnlyValue {
19  public:
20   MoveOnlyValue() = default;
MoveOnlyValuebase::test::__anon8ae5ce050111::MoveOnlyValue21   explicit MoveOnlyValue(std::string data) : data(std::move(data)) {}
22   MoveOnlyValue(const MoveOnlyValue&) = delete;
23   auto& operator=(const MoveOnlyValue&) = delete;
24   MoveOnlyValue(MoveOnlyValue&&) = default;
25   MoveOnlyValue& operator=(MoveOnlyValue&&) = default;
26   ~MoveOnlyValue() = default;
27 
28   std::string data;
29 };
30 
31 }  // namespace
32 
33 class RepeatingTestFutureTest : public ::testing::Test {
34  public:
35   RepeatingTestFutureTest() = default;
36   RepeatingTestFutureTest(const RepeatingTestFutureTest&) = delete;
37   RepeatingTestFutureTest& operator=(const RepeatingTestFutureTest&) = delete;
38   ~RepeatingTestFutureTest() override = default;
39 
RunLater(OnceClosure callable)40   void RunLater(OnceClosure callable) {
41     SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
42                                                           std::move(callable));
43   }
44 
45  private:
46   test::SingleThreadTaskEnvironment environment_;
47 };
48 
TEST_F(RepeatingTestFutureTest,ShouldBeEmptyInitially)49 TEST_F(RepeatingTestFutureTest, ShouldBeEmptyInitially) {
50   RepeatingTestFuture<std::string> future;
51 
52   EXPECT_TRUE(future.IsEmpty());
53 }
54 
TEST_F(RepeatingTestFutureTest,ShouldNotBeEmptyAfterAddingAValue)55 TEST_F(RepeatingTestFutureTest, ShouldNotBeEmptyAfterAddingAValue) {
56   RepeatingTestFuture<std::string> future;
57 
58   future.AddValue("a value");
59 
60   EXPECT_FALSE(future.IsEmpty());
61 }
62 
TEST_F(RepeatingTestFutureTest,ShouldBeEmptyAfterTakingTheOnlyElement)63 TEST_F(RepeatingTestFutureTest, ShouldBeEmptyAfterTakingTheOnlyElement) {
64   RepeatingTestFuture<std::string> future;
65 
66   future.AddValue("a value");
67   future.Take();
68 
69   EXPECT_TRUE(future.IsEmpty());
70 }
71 
TEST_F(RepeatingTestFutureTest,ShouldNotBeEmptyIfTakingOneElementFromAfutureWith2Elements)72 TEST_F(RepeatingTestFutureTest,
73        ShouldNotBeEmptyIfTakingOneElementFromAfutureWith2Elements) {
74   RepeatingTestFuture<std::string> future;
75 
76   future.AddValue("first value");
77   future.AddValue("second value");
78   future.Take();
79 
80   EXPECT_FALSE(future.IsEmpty());
81 }
82 
TEST_F(RepeatingTestFutureTest,ShouldTakeElementsFiFo)83 TEST_F(RepeatingTestFutureTest, ShouldTakeElementsFiFo) {
84   RepeatingTestFuture<std::string> future;
85 
86   future.AddValue("first value");
87   future.AddValue("second value");
88 
89   EXPECT_EQ(future.Take(), "first value");
90   EXPECT_EQ(future.Take(), "second value");
91 }
92 
TEST_F(RepeatingTestFutureTest,WaitShouldBlockUntilElementArrives)93 TEST_F(RepeatingTestFutureTest, WaitShouldBlockUntilElementArrives) {
94   RepeatingTestFuture<std::string> future;
95 
96   RunLater(BindLambdaForTesting([&future]() { future.AddValue("a value"); }));
97   EXPECT_TRUE(future.IsEmpty());
98 
99   EXPECT_TRUE(future.Wait());
100 
101   EXPECT_FALSE(future.IsEmpty());
102 }
103 
TEST_F(RepeatingTestFutureTest,WaitShouldReturnTrueWhenValueArrives)104 TEST_F(RepeatingTestFutureTest, WaitShouldReturnTrueWhenValueArrives) {
105   RepeatingTestFuture<std::string> future;
106 
107   RunLater(BindLambdaForTesting([&future]() { future.AddValue("a value"); }));
108 
109   EXPECT_TRUE(future.Wait());
110 
111   EXPECT_FALSE(future.IsEmpty());
112 }
113 
TEST_F(RepeatingTestFutureTest,WaitShouldReturnTrueImmediatelyWhenValueIsAlreadyPresent)114 TEST_F(RepeatingTestFutureTest,
115        WaitShouldReturnTrueImmediatelyWhenValueIsAlreadyPresent) {
116   RepeatingTestFuture<std::string> future;
117 
118   future.AddValue("value already present");
119 
120   EXPECT_TRUE(future.Wait());
121 }
122 
TEST_F(RepeatingTestFutureTest,WaitShouldReturnFalseIfTimeoutHappens)123 TEST_F(RepeatingTestFutureTest, WaitShouldReturnFalseIfTimeoutHappens) {
124   test::ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
125 
126   // `ScopedRunLoopTimeout` will automatically fail the test when a timeout
127   // happens, so we use EXPECT_NONFATAL_FAILURE to handle this failure.
128   // EXPECT_NONFATAL_FAILURE only works on static objects.
129   static bool success;
130   static RepeatingTestFuture<std::string> future;
131 
132   EXPECT_NONFATAL_FAILURE({ success = future.Wait(); }, "timed out");
133 
134   EXPECT_FALSE(success);
135 }
136 
TEST_F(RepeatingTestFutureTest,TakeShouldBlockUntilAnElementArrives)137 TEST_F(RepeatingTestFutureTest, TakeShouldBlockUntilAnElementArrives) {
138   RepeatingTestFuture<std::string> future;
139 
140   RunLater(BindLambdaForTesting(
141       [&future]() { future.AddValue("value pushed delayed"); }));
142 
143   EXPECT_EQ(future.Take(), "value pushed delayed");
144 }
145 
TEST_F(RepeatingTestFutureTest,TakeShouldDcheckIfTimeoutHappens)146 TEST_F(RepeatingTestFutureTest, TakeShouldDcheckIfTimeoutHappens) {
147   test::ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
148 
149   RepeatingTestFuture<std::string> future;
150 
151   EXPECT_DCHECK_DEATH_WITH(future.Take(), "timed out");
152 }
153 
TEST_F(RepeatingTestFutureTest,TakeShouldWorkWithMoveOnlyValue)154 TEST_F(RepeatingTestFutureTest, TakeShouldWorkWithMoveOnlyValue) {
155   RepeatingTestFuture<MoveOnlyValue> future;
156 
157   RunLater(BindLambdaForTesting(
158       [&future]() { future.AddValue(MoveOnlyValue("move only value")); }));
159 
160   MoveOnlyValue result = future.Take();
161 
162   EXPECT_EQ(result.data, "move only value");
163 }
164 
TEST_F(RepeatingTestFutureTest,ShouldStoreValuePassedToCallback)165 TEST_F(RepeatingTestFutureTest, ShouldStoreValuePassedToCallback) {
166   RepeatingTestFuture<std::string> future;
167 
168   RunLater(BindOnce(future.GetCallback(), "value"));
169 
170   EXPECT_EQ("value", future.Take());
171 }
172 
TEST_F(RepeatingTestFutureTest,ShouldAllowInvokingCallbackMultipleTimes)173 TEST_F(RepeatingTestFutureTest, ShouldAllowInvokingCallbackMultipleTimes) {
174   RepeatingTestFuture<std::string> future;
175 
176   RunLater(BindLambdaForTesting([callback = future.GetCallback()]() {
177     callback.Run("first value");
178     callback.Run("second value");
179     callback.Run("third value");
180   }));
181 
182   EXPECT_EQ("first value", future.Take());
183   EXPECT_EQ("second value", future.Take());
184   EXPECT_EQ("third value", future.Take());
185 }
186 
TEST_F(RepeatingTestFutureTest,ShouldAllowReferenceArgumentsForCallback)187 TEST_F(RepeatingTestFutureTest, ShouldAllowReferenceArgumentsForCallback) {
188   RepeatingTestFuture<std::string> future;
189 
190   RepeatingCallback<void(const std::string&)> callback =
191       future.GetCallback<const std::string&>();
192   RunLater(BindOnce(std::move(callback), "expected value"));
193 
194   EXPECT_EQ("expected value", future.Take());
195 }
196 
TEST_F(RepeatingTestFutureTest,ShouldStoreMultipleValuesInATuple)197 TEST_F(RepeatingTestFutureTest, ShouldStoreMultipleValuesInATuple) {
198   const int expected_int_value = 5;
199   const std::string expected_string_value = "value";
200 
201   RepeatingTestFuture<int, std::string> future;
202 
203   RunLater(BindLambdaForTesting(
204       [&]() { future.AddValue(expected_int_value, expected_string_value); }));
205 
206   std::tuple<int, std::string> actual = future.Take();
207   EXPECT_EQ(expected_int_value, std::get<0>(actual));
208   EXPECT_EQ(expected_string_value, std::get<1>(actual));
209 }
210 
TEST_F(RepeatingTestFutureTest,ShouldAllowCallbackWithMultipleValues)211 TEST_F(RepeatingTestFutureTest, ShouldAllowCallbackWithMultipleValues) {
212   const int expected_int_value = 5;
213   const std::string expected_string_value = "value";
214 
215   RepeatingTestFuture<int, std::string> future;
216 
217   RunLater(BindOnce(future.GetCallback(), expected_int_value,
218                     expected_string_value));
219 
220   std::tuple<int, std::string> actual = future.Take();
221   EXPECT_EQ(expected_int_value, std::get<0>(actual));
222   EXPECT_EQ(expected_string_value, std::get<1>(actual));
223 }
224 
TEST_F(RepeatingTestFutureTest,ShouldAllowCallbackWithMultipleReferenceValues)225 TEST_F(RepeatingTestFutureTest,
226        ShouldAllowCallbackWithMultipleReferenceValues) {
227   const int expected_int_value = 5;
228   const std::string expected_string_value = "value";
229 
230   RepeatingTestFuture<int, std::string> future;
231 
232   RepeatingCallback<void(const int&, std::string)> callback =
233       future.GetCallback<const int&, std::string>();
234   RunLater(
235       BindOnce(std::move(callback), expected_int_value, expected_string_value));
236 
237   std::tuple<int, std::string> actual = future.Take();
238   EXPECT_EQ(expected_int_value, std::get<0>(actual));
239   EXPECT_EQ(expected_string_value, std::get<1>(actual));
240 }
241 
TEST_F(RepeatingTestFutureTest,ShouldSupportCvRefType)242 TEST_F(RepeatingTestFutureTest, ShouldSupportCvRefType) {
243   std::string expected_value = "value";
244   RepeatingTestFuture<const std::string&> future;
245 
246   base::OnceCallback<void(const std::string&)> callback = future.GetCallback();
247   std::move(callback).Run(expected_value);
248 
249   std::string actual = future.Take();
250   EXPECT_EQ(expected_value, actual);
251 }
252 
TEST_F(RepeatingTestFutureTest,ShouldSupportMultipleCvRefType)253 TEST_F(RepeatingTestFutureTest, ShouldSupportMultipleCvRefType) {
254   const int expected_first_value = 5;
255   std::string expected_second_value = "value";
256   const long expected_third_value = 10;
257   RepeatingTestFuture<const int, std::string&, const long&> future;
258 
259   base::OnceCallback<void(const int, std::string&, const long&)> callback =
260       future.GetCallback();
261   std::move(callback).Run(expected_first_value, expected_second_value,
262                           expected_third_value);
263 
264   std::tuple<int, std::string, long> take_result = future.Take();
265   EXPECT_EQ(expected_first_value, std::get<0>(take_result));
266   EXPECT_EQ(expected_second_value, std::get<1>(take_result));
267   EXPECT_EQ(expected_third_value, std::get<2>(take_result));
268 }
269 
270 }  // namespace base::test
271