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