1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
base / test / test_future.h [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TEST_TEST_FUTURE_H_
#define BASE_TEST_TEST_FUTURE_H_
#include <memory>
#include <optional>
#include <tuple>
#include "base/auto_reset.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
#include "base/strings/to_string.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/test_future_internal.h"
#include "base/thread_annotations.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base::test {
// Helper class to test code that returns its result(s) asynchronously through a
// callback:
//
// - Pass the callback provided by `GetCallback()` to the code under test.
// - Wait for the callback to be invoked by calling `Wait(),` or `Get()` to
// access the value(s) passed to the callback.
//
// Example usage:
//
// TEST_F(MyTestFixture, MyTest) {
// TestFuture<ResultType> future;
//
// object_under_test.DoSomethingAsync(future.GetCallback());
//
// const ResultType& actual_result = future.Get();
//
// // When you come here, DoSomethingAsync has finished and
// // `actual_result` contains the result passed to the callback.
// }
//
// Example using `Wait()`:
//
// TEST_F(MyTestFixture, MyWaitTest) {
// TestFuture<ResultType> future;
//
// object_under_test.DoSomethingAsync(future.GetCallback());
//
// // Optional. The Get() call below will also wait until the value
// // arrives, but this explicit call to Wait() can be useful if you want
// // to add extra information.
// ASSERT_TRUE(future.Wait()) << "Detailed error message";
//
// const ResultType& actual_result = future.Get();
// }
//
// `TestFuture` supports both single- and multiple-argument callbacks.
// `TestFuture` provides both index and type based accessors for multi-argument
// callbacks. `Get()` and `Take()` return tuples for multi-argument callbacks.
//
// TestFuture<int, std::string> future;
// future.Get<0>(); // Reads the first argument
// future.Get<int>(); // Also reads the first argument
// future.Get(); // Returns a `const std::tuple<int, std::string>&`
//
// Example for a multi-argument callback:
//
// TEST_F(MyTestFixture, MyTest) {
// TestFuture<int, std::string> future;
//
// object_under_test.DoSomethingAsync(future.GetCallback());
//
// // You can use type based accessors:
// int first_argument = future.Get<int>();
// const std::string& second_argument = future.Get<std::string>();
//
// // or index based accessors:
// int first_argument = future.Get<0>();
// const std::string& second_argument = future.Get<1>();
// }
//
// You can also satisfy a `TestFuture` by calling `SetValue()` from the sequence
// on which the `TestFuture` was created. This is mostly useful when
// implementing an observer:
//
// class MyTestObserver: public MyObserver {
// public:
// // `MyObserver` implementation:
// void ObserveAnInt(int value) override {
// future_.SetValue(value);
// }
//
// int Wait() { return future_.Take(); }
//
// private:
// TestFuture<int> future_;
// };
//
// TEST_F(MyTestFixture, MyTest) {
// MyTestObserver observer;
//
// object_under_test.DoSomethingAsync(observer);
//
// int value_passed_to_observer = observer.Wait();
// };
//
// `GetRepeatingCallback()` allows you to use a single `TestFuture` in code
// that invokes the callback multiple times.
// Your test must take care to consume each value before the next value
// arrives. You can consume the value by calling either `Take()` or `Clear()`.
//
// Example for reusing a `TestFuture`:
//
// TEST_F(MyTestFixture, MyReuseTest) {
// TestFuture<std::string> future;
//
// object_under_test.InstallCallback(future.GetRepeatingCallback());
//
// object_under_test.DoSomething();
// EXPECT_EQ(future.Take(), "expected-first-value");
// // Because we used `Take()` the test future is ready for reuse.
//
// object_under_test.DoSomethingElse();
// EXPECT_EQ(future.Take(), "expected-second-value");
// }
//
// Example for reusing a `TestFuture` using `Get()` + `Clear()`:
//
// TEST_F(MyTestFixture, MyReuseTest) {
// TestFuture<std::string, int> future;
//
// object_under_test.InstallCallback(future.GetRepeatingCallback());
//
// object_under_test.DoSomething();
//
// EXPECT_EQ(future.Get<std::string>(), "expected-first-value");
// EXPECT_EQ(future.Get<int>(), 5);
// // Because we used `Get()`, the test future is not ready for reuse,
// //so we need an explicit `Clear()` call.
// future.Clear();
//
// object_under_test.DoSomethingElse();
// EXPECT_EQ(future.Get<std::string>(), "expected-second-value");
// EXPECT_EQ(future.Get<int>(), 2);
// }
//
// Finally, `TestFuture` also supports no-args callbacks:
//
// Example for no-args callbacks:
//
// TEST_F(MyTestFixture, MyTest) {
// TestFuture<void> signal;
//
// object_under_test.DoSomethingAsync(signal.GetCallback());
//
// EXPECT_TRUE(signal.Wait());
// // When you come here you know the callback was invoked and the async
// // code is ready.
// }
//
// All access to this class and its callbacks must be made from the sequence on
// which the `TestFuture` was constructed.
//
template <typename... Types>
class TestFuture {
public:
using TupleType = std::tuple<std::decay_t<Types>...>;
static_assert(std::tuple_size_v<TupleType> > 0,
"Don't use TestFuture<> but use TestFuture<void> instead");
TestFuture() = default;
TestFuture(const TestFuture&) = delete;
TestFuture& operator=(const TestFuture&) = delete;
~TestFuture() = default;
// Waits for the value to arrive.
//
// Returns true if the value arrived, or false if a timeout happens.
//
// Directly calling Wait() is not required as Get()/Take() will also wait for
// the value to arrive, however you can use a direct call to Wait() to
// improve the error reported:
//
// ASSERT_TRUE(queue.Wait()) << "Detailed error message";
//
[[nodiscard]] bool Wait() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (values_) {
return true;
}
// Wait for the value to arrive.
RunLoop loop;
AutoReset<RepeatingClosure> quit_loop(&ready_signal_, loop.QuitClosure());
loop.Run();
return IsReady();
}
// Returns true if the value has arrived.
bool IsReady() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return values_.has_value();
}
// Waits for the value to arrive, and returns the I-th value.
//
// Will CHECK if a timeout happens.
//
// Example usage:
//
// TestFuture<int, std::string> future;
// int first = future.Get<0>();
// std::string second = future.Get<1>();
//
template <std::size_t I, typename T = TupleType>
requires(internal::IsNonEmptyTuple<T>)
const auto& Get() {
return std::get<I>(GetTuple());
}
// Waits for the value to arrive, and returns the value with the given type.
//
// Will CHECK if a timeout happens.
//
// Example usage:
//
// TestFuture<int, std::string> future;
// int first = future.Get<int>();
// std::string second = future.Get<std::string>();
//
template <typename Type>
const auto& Get() {
return std::get<Type>(GetTuple());
}
// Returns a callback that when invoked will store all the argument values,
// and unblock any waiters. The callback must be invoked on the sequence the
// TestFuture was created on.
//
// Templated so you can specify how you need the arguments to be passed -
// const, reference, .... Defaults to simply `Types...`.
//
// Example usage:
//
// TestFuture<int, std::string> future;
//
// // Without specifying the callback argument types, this returns
// // base::OnceCallback<void(int, std::string)>.
// future.GetCallback();
//
// // By explicitly specifying the callback argument types, this returns
// // base::OnceCallback<void(int, const std::string&)>.
// future.GetCallback<int, const std::string&>();
//
template <typename... CallbackArgumentsTypes>
OnceCallback<void(CallbackArgumentsTypes...)> GetCallback() {
return GetRepeatingCallback<CallbackArgumentsTypes...>();
}
OnceCallback<void(Types...)> GetCallback() { return GetCallback<Types...>(); }
// Returns a repeating callback that when invoked will store all the argument
// values, and unblock any waiters. The callback must be invoked on the
// sequence the TestFuture was created on.
//
// You must take care that the stored value is consumed before the callback
// is invoked a second time. You can consume the value by calling either
// `Take()` or `Clear()`.
//
// Example usage:
//
// TestFuture<std::string> future;
//
// object_under_test.InstallCallback(future.GetRepeatingCallback());
//
// object_under_test.DoSomething();
// EXPECT_EQ(future.Take(), "expected-first-value");
// // Because we used `Take()` the test future is ready for reuse.
//
// object_under_test.DoSomethingElse();
// // We can also use `Get()` + `Clear()` to reuse the callback.
// EXPECT_EQ(future.Get(), "expected-second-value");
// future.Clear();
//
// object_under_test.DoSomethingElse();
// EXPECT_EQ(future.Take(), "expected-third-value");
//
template <typename... CallbackArgumentsTypes>
RepeatingCallback<void(CallbackArgumentsTypes...)> GetRepeatingCallback() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return BindRepeating(
[](WeakPtr<TestFuture<Types...>> future,
CallbackArgumentsTypes... values) {
if (future) {
future->SetValue(std::forward<CallbackArgumentsTypes>(values)...);
}
},
weak_ptr_factory_.GetWeakPtr());
}
RepeatingCallback<void(Types...)> GetRepeatingCallback() {
return GetRepeatingCallback<Types...>();
}
// Returns a callback that can be invoked on any sequence. When invoked it
// will post a task to the sequence the TestFuture was created on, to store
// all the argument values, and unblock any waiters.
//
// Templated so you can specify how you need the arguments to be passed -
// const, reference, .... Defaults to simply `Types...`.
//
// Example usage:
//
// TestFuture<int, std::string> future;
//
// // Without specifying the callback argument types, this returns
// // base::OnceCallback<void(int, std::string)>.
// auto callback = future.GetSequenceBoundCallback();
//
// // By explicitly specifying the callback argument types, this returns
// // base::OnceCallback<void(int, const std::string&)>.
// auto callback =
// future.GetSequenceBoundCallback<int, const std::string&>();
//
// // AsyncOperation invokes `callback` with a result.
// other_task_runner->PostTask(FROM_HERE, base::BindOnce(&AsyncOperation,
// std::move(callback));
//
// future.Wait();
//
template <typename... CallbackArgumentsTypes>
OnceCallback<void(CallbackArgumentsTypes...)> GetSequenceBoundCallback() {
return GetSequenceBoundRepeatingCallback<CallbackArgumentsTypes...>();
}
OnceCallback<void(Types...)> GetSequenceBoundCallback() {
return GetSequenceBoundCallback<Types...>();
}
// Returns a repeating callback that can be invoked on any sequence. When
// invoked it will post a task to the sequence the TestFuture was created on,
// to store all the argument values, and unblock any waiters.
//
// You must take care that the stored value is consumed before the callback
// is invoked a second time. You can consume the value by calling either
// `Take()` or `Clear()`.
//
// Example usage:
//
// base::SequenceBound<Object> object_under_test(other_task_runner);
// TestFuture<std::string> future;
//
// object_under_test.AsyncCall(&Object::InstallCallback,
// future.GetSequenceBoundRepeatingCallback());
//
// object_under_test.AsyncCall(&DoSomething);
// EXPECT_EQ(future.Take(), "expected-first-value");
// // Because we used `Take()` the test future is ready for reuse.
//
// object_under_test.AsyncCall(&DoSomethingElse);
// // We can also use `Get()` + `Clear()` to reuse the callback.
// EXPECT_EQ(future.Get(), "expected-second-value");
// future.Clear();
//
// object_under_test.AsyncCall(&DoSomethingElse);
// EXPECT_EQ(future.Take(), "expected-third-value");
//
template <typename... CallbackArgumentsTypes>
RepeatingCallback<void(CallbackArgumentsTypes...)>
GetSequenceBoundRepeatingCallback() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return BindPostTask(base::SequencedTaskRunner::GetCurrentDefault(),
GetRepeatingCallback<CallbackArgumentsTypes...>());
}
RepeatingCallback<void(Types...)> GetSequenceBoundRepeatingCallback() {
return GetSequenceBoundRepeatingCallback<Types...>();
}
// Sets the value of the future.
// This will unblock any pending Wait() or Get() call.
void SetValue(Types... values) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto new_values = std::make_tuple(std::forward<Types>(values)...);
EXPECT_FALSE(values_.has_value())
<< "Received new value " << ToString(new_values) //
<< " before old value " << ToString(GetTuple())
<< " was consumed through Take() or Clear().";
values_ = std::move(new_values);
ready_signal_.Run();
}
// Clears the future, allowing it to be reused and accept a new value.
//
// All outstanding callbacks issued through `GetCallback()` remain valid.
void Clear() {
if (IsReady()) {
std::ignore = Take();
}
}
//////////////////////////////////////////////////////////////////////////////
// Accessor methods only available if the future holds a single value.
//////////////////////////////////////////////////////////////////////////////
// Waits for the value to arrive, and returns a reference to it.
//
// Will CHECK if a timeout happens.
template <typename T = TupleType>
requires(internal::IsSingleValuedTuple<T>)
[[nodiscard]] const auto& Get() {
return std::get<0>(GetTuple());
}
// Waits for the value to arrive, and returns it.
//
// Will CHECK if a timeout happens.
template <typename T = TupleType>
requires(internal::IsSingleValuedTuple<T>)
[[nodiscard]] auto Take() {
return std::get<0>(TakeTuple());
}
//////////////////////////////////////////////////////////////////////////////
// Accessor methods only available if the future holds multiple values.
//////////////////////////////////////////////////////////////////////////////
// Waits for the values to arrive, and returns a tuple with the values.
//
// Will CHECK if a timeout happens.
template <typename T = TupleType>
requires(internal::IsMultiValuedTuple<T>)
[[nodiscard]] const TupleType& Get() {
return GetTuple();
}
// Waits for the values to arrive, and moves a tuple with the values out.
//
// Will CHECK if a timeout happens.
template <typename T = TupleType>
requires(internal::IsMultiValuedTuple<T>)
[[nodiscard]] TupleType Take() {
return TakeTuple();
}
private:
[[nodiscard]] const TupleType& GetTuple() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool success = Wait();
CHECK(success) << "Waiting for value timed out.";
return values_.value();
}
[[nodiscard]] TupleType TakeTuple() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool success = Wait();
CHECK(success) << "Waiting for value timed out.";
return std::exchange(values_, {}).value();
}
SEQUENCE_CHECKER(sequence_checker_);
base::RepeatingClosure ready_signal_ GUARDED_BY_CONTEXT(sequence_checker_) =
base::DoNothing();
std::optional<TupleType> values_ GUARDED_BY_CONTEXT(sequence_checker_);
WeakPtrFactory<TestFuture<Types...>> weak_ptr_factory_{this};
};
// Specialization so you can use `TestFuture` to wait for a no-args callback.
//
// This specialization offers a subset of the methods provided on the base
// `TestFuture`, as there is no value to be returned.
template <>
class TestFuture<void> {
public:
// Waits until the callback or `SetValue()` is invoked.
//
// Fails your test if a timeout happens, but you can check the return value
// to improve the error reported:
//
// ASSERT_TRUE(future.Wait()) << "Detailed error message";
[[nodiscard]] bool Wait() { return implementation_.Wait(); }
// Same as above, then clears the future, allowing it to be reused and accept
// a new value.
[[nodiscard]] bool WaitAndClear() {
auto result = Wait();
Clear();
return result;
}
// Waits until the callback or `SetValue()` is invoked.
void Get() { std::ignore = implementation_.Get(); }
// Returns true if the callback or `SetValue()` was invoked.
bool IsReady() const { return implementation_.IsReady(); }
// Returns a callback that when invoked will unblock any waiters.
OnceClosure GetCallback() {
return BindOnce(implementation_.GetCallback(), true);
}
// Returns a callback that when invoked will unblock any waiters.
RepeatingClosure GetRepeatingCallback() {
return BindRepeating(implementation_.GetRepeatingCallback(), true);
}
// Returns a callback that when invoked on any sequence will unblock any
// waiters.
OnceClosure GetSequenceBoundCallback() {
return BindOnce(implementation_.GetSequenceBoundCallback(), true);
}
// Returns a callback that when invoked on any sequence will unblock any
// waiters.
RepeatingClosure GetSequenceBoundRepeatingCallback() {
return BindRepeating(implementation_.GetSequenceBoundRepeatingCallback(),
true);
}
// Indicates this `TestFuture` is ready, and unblocks any waiters.
void SetValue() { implementation_.SetValue(true); }
// Clears the future, allowing it to be reused and accept a new value.
//
// All outstanding callbacks issued through `GetCallback()` remain valid.
void Clear() { implementation_.Clear(); }
private:
TestFuture<bool> implementation_;
};
// A gmock action that when invoked will store the argument values and
// unblock any waiters. The action must be invoked on the sequence the
// TestFuture was created on.
//
// Usually the action will be used with `WillOnce()` and only invoked once,
// but if you consume the value with `Take()` or `Clear()` it is safe to
// invoke it again.
//
// Example usage:
// TestFuture<int> future;
//
// EXPECT_CALL(delegate, OnReadComplete)
// .WillOnce(InvokeFuture(future));
//
// object_under_test.Read(buffer, 16);
//
// EXPECT_EQ(future.Take(), 16);
//
//
//
// Implementation note: this is not implemented using the MATCHER_P macro as the
// C++03-compatible way it implements varargs would make this too verbose.
// Instead, it takes advantage of the ability to pass a functor to .WillOnce()
// and .WillRepeatedly().
template <typename... Types>
class InvokeFuture {
public:
// The TestFuture must be an lvalue. Passing an rvalue would make no sense as
// you wouldn't be able to call Take() on it afterwards.
explicit InvokeFuture(TestFuture<Types...>& future)
: callback_(future.GetRepeatingCallback()) {}
// GMock actions must be copyable.
InvokeFuture(const InvokeFuture&) = default;
InvokeFuture& operator=(const InvokeFuture&) = default;
// WillOnce() can take advantage of move constructors.
InvokeFuture(InvokeFuture&&) = default;
InvokeFuture& operator=(InvokeFuture&&) = default;
void operator()(Types... values) {
callback_.Run(std::forward<Types>(values)...);
}
private:
RepeatingCallback<void(Types...)> callback_;
};
// Specialization for TestFuture<void>.
template <>
class InvokeFuture<void> {
public:
explicit InvokeFuture(TestFuture<void>& future)
: closure_(future.GetRepeatingCallback()) {}
InvokeFuture(const InvokeFuture&) = default;
InvokeFuture& operator=(const InvokeFuture&) = default;
InvokeFuture(InvokeFuture&&) = default;
InvokeFuture& operator=(InvokeFuture&&) = default;
void operator()() { closure_.Run(); }
private:
RepeatingClosure closure_;
};
// Deduction guide so the compiler can choose the correct specialisation of
// InvokeFuture.
template <typename... Types>
InvokeFuture(TestFuture<Types...>&) -> InvokeFuture<Types...>;
} // namespace base::test
#endif // BASE_TEST_TEST_FUTURE_H_