1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_TEST_BIND_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_TEST_BIND_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <string_view> 9*6777b538SAndroid Build Coastguard Worker #include <type_traits> 10*6777b538SAndroid Build Coastguard Worker #include <utility> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h" 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker namespace base { 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker class Location; 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker namespace internal { 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker template <typename Signature, typename R, typename F, typename... Args> 21*6777b538SAndroid Build Coastguard Worker static constexpr bool kHasConstCallOperator = false; 22*6777b538SAndroid Build Coastguard Worker template <typename R, typename F, typename... Args> 23*6777b538SAndroid Build Coastguard Worker static constexpr bool 24*6777b538SAndroid Build Coastguard Worker kHasConstCallOperator<R (F::*)(Args...) const, R, F, Args...> = true; 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker // Implementation of `BindLambdaForTesting()`, which checks preconditions before 27*6777b538SAndroid Build Coastguard Worker // handing off to `Bind{Once,Repeating}()`. 28*6777b538SAndroid Build Coastguard Worker template <typename Lambda, 29*6777b538SAndroid Build Coastguard Worker typename = ExtractCallableRunType<std::decay_t<Lambda>>> 30*6777b538SAndroid Build Coastguard Worker struct BindLambdaForTestingHelper; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker template <typename Lambda, typename R, typename... Args> 33*6777b538SAndroid Build Coastguard Worker struct BindLambdaForTestingHelper<Lambda, R(Args...)> { 34*6777b538SAndroid Build Coastguard Worker private: 35*6777b538SAndroid Build Coastguard Worker using F = std::decay_t<Lambda>; 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Worker // For context on this "templated struct with a lambda that asserts" pattern, 38*6777b538SAndroid Build Coastguard Worker // see comments in `Invoker<>`. 39*6777b538SAndroid Build Coastguard Worker template <bool v = std::is_rvalue_reference_v<Lambda&&> && 40*6777b538SAndroid Build Coastguard Worker !std::is_const_v<std::remove_reference_t<Lambda>>> 41*6777b538SAndroid Build Coastguard Worker struct IsNonConstRvalueRef { 42*6777b538SAndroid Build Coastguard Worker static constexpr bool value = [] { 43*6777b538SAndroid Build Coastguard Worker static_assert( 44*6777b538SAndroid Build Coastguard Worker v, 45*6777b538SAndroid Build Coastguard Worker "BindLambdaForTesting() requires non-const rvalue for mutable lambda " 46*6777b538SAndroid Build Coastguard Worker "binding, i.e. base::BindLambdaForTesting(std::move(lambda))."); 47*6777b538SAndroid Build Coastguard Worker return v; 48*6777b538SAndroid Build Coastguard Worker }(); 49*6777b538SAndroid Build Coastguard Worker }; 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker static R Run(const F& f, Args... args) { 52*6777b538SAndroid Build Coastguard Worker return f(std::forward<Args>(args)...); 53*6777b538SAndroid Build Coastguard Worker } 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker static R RunOnce(F&& f, Args... args) { 56*6777b538SAndroid Build Coastguard Worker return f(std::forward<Args>(args)...); 57*6777b538SAndroid Build Coastguard Worker } 58*6777b538SAndroid Build Coastguard Worker 59*6777b538SAndroid Build Coastguard Worker public: 60*6777b538SAndroid Build Coastguard Worker static auto BindLambdaForTesting(Lambda&& lambda) { 61*6777b538SAndroid Build Coastguard Worker if constexpr (kHasConstCallOperator<decltype(&F::operator()), R, F, 62*6777b538SAndroid Build Coastguard Worker Args...>) { 63*6777b538SAndroid Build Coastguard Worker // If WTF::BindRepeating is available, and a callback argument is in WTF, 64*6777b538SAndroid Build Coastguard Worker // then this call is ambiguous without the full namespace path. 65*6777b538SAndroid Build Coastguard Worker return ::base::BindRepeating(&Run, std::forward<Lambda>(lambda)); 66*6777b538SAndroid Build Coastguard Worker } else if constexpr (IsNonConstRvalueRef<>::value) { 67*6777b538SAndroid Build Coastguard Worker // Since a mutable lambda potentially can invalidate its state after being 68*6777b538SAndroid Build Coastguard Worker // run once, this method returns a `OnceCallback` instead of a 69*6777b538SAndroid Build Coastguard Worker // `RepeatingCallback`. 70*6777b538SAndroid Build Coastguard Worker return BindOnce(&RunOnce, std::move(lambda)); 71*6777b538SAndroid Build Coastguard Worker } 72*6777b538SAndroid Build Coastguard Worker } 73*6777b538SAndroid Build Coastguard Worker }; 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker } // namespace internal 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker // A variant of `Bind{Once,Repeating}()` that can bind capturing lambdas for 78*6777b538SAndroid Build Coastguard Worker // testing. This doesn't support extra arguments binding as the lambda itself 79*6777b538SAndroid Build Coastguard Worker // can do. 80*6777b538SAndroid Build Coastguard Worker template <typename Lambda> 81*6777b538SAndroid Build Coastguard Worker auto BindLambdaForTesting(Lambda&& lambda) { 82*6777b538SAndroid Build Coastguard Worker return internal::BindLambdaForTestingHelper<Lambda>::BindLambdaForTesting( 83*6777b538SAndroid Build Coastguard Worker std::forward<Lambda>(lambda)); 84*6777b538SAndroid Build Coastguard Worker } 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker // Returns a closure that fails on destruction if it hasn't been run. 87*6777b538SAndroid Build Coastguard Worker OnceClosure MakeExpectedRunClosure( 88*6777b538SAndroid Build Coastguard Worker const Location& location, 89*6777b538SAndroid Build Coastguard Worker std::string_view message = std::string_view()); 90*6777b538SAndroid Build Coastguard Worker RepeatingClosure MakeExpectedRunAtLeastOnceClosure( 91*6777b538SAndroid Build Coastguard Worker const Location& location, 92*6777b538SAndroid Build Coastguard Worker std::string_view message = std::string_view()); 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // Returns a closure that fails the test if run. 95*6777b538SAndroid Build Coastguard Worker RepeatingClosure MakeExpectedNotRunClosure( 96*6777b538SAndroid Build Coastguard Worker const Location& location, 97*6777b538SAndroid Build Coastguard Worker std::string_view message = std::string_view()); 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker } // namespace base 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker #endif // BASE_TEST_BIND_H_ 102