1 // Copyright 2017 The Chromium Authors. All rights reserved. 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_BIND_H_ 6 #define BASE_TEST_BIND_H_ 7 8 #include <type_traits> 9 #include <utility> 10 11 #include "base/bind.h" 12 #include "base/strings/string_piece.h" 13 14 namespace base { 15 16 class Location; 17 18 namespace internal { 19 20 template <typename Callable, 21 typename Signature = decltype(&Callable::operator())> 22 struct HasConstCallOperatorImpl : std::false_type {}; 23 24 template <typename Callable, typename R, typename... Args> 25 struct HasConstCallOperatorImpl<Callable, R (Callable::*)(Args...) const> 26 : std::true_type {}; 27 28 template <typename Callable> 29 constexpr bool HasConstCallOperator = 30 HasConstCallOperatorImpl<std::decay_t<Callable>>::value; 31 32 template <typename F, typename Signature> 33 struct BindLambdaHelper; 34 35 template <typename F, typename R, typename... Args> 36 struct BindLambdaHelper<F, R(Args...)> { 37 static R Run(const std::decay_t<F>& f, Args... args) { 38 return f(std::forward<Args>(args)...); 39 } 40 41 static R RunOnce(std::decay_t<F>&& f, Args... args) { 42 return f(std::forward<Args>(args)...); 43 } 44 }; 45 46 } // namespace internal 47 48 // A variant of BindRepeating() that can bind capturing lambdas for testing. 49 // This doesn't support extra arguments binding as the lambda itself can do. 50 template <typename Lambda, 51 std::enable_if_t<internal::HasConstCallOperator<Lambda>>* = nullptr> 52 decltype(auto) BindLambdaForTesting(Lambda&& lambda) { 53 using Signature = internal::ExtractCallableRunType<std::decay_t<Lambda>>; 54 return BindRepeating(&internal::BindLambdaHelper<Lambda, Signature>::Run, 55 std::forward<Lambda>(lambda)); 56 } 57 58 // A variant of BindRepeating() that can bind mutable capturing lambdas for 59 // testing. This doesn't support extra arguments binding as the lambda itself 60 // can do. Since a mutable lambda potentially can invalidate its state after 61 // being run once, this method returns a OnceCallback instead of a 62 // RepeatingCallback. 63 template <typename Lambda, 64 std::enable_if_t<!internal::HasConstCallOperator<Lambda>>* = nullptr> 65 decltype(auto) BindLambdaForTesting(Lambda&& lambda) { 66 static_assert( 67 std::is_rvalue_reference<Lambda&&>() && 68 !std::is_const<std::remove_reference_t<Lambda>>(), 69 "BindLambdaForTesting requires non-const rvalue for mutable lambda " 70 "binding. I.e.: base::BindLambdaForTesting(std::move(lambda))."); 71 using Signature = internal::ExtractCallableRunType<std::decay_t<Lambda>>; 72 return BindOnce(&internal::BindLambdaHelper<Lambda, Signature>::RunOnce, 73 std::move(lambda)); 74 } 75 76 // Returns a closure that fails on destruction if it hasn't been run. 77 OnceClosure MakeExpectedRunClosure(const Location& location, 78 StringPiece message = StringPiece()); 79 RepeatingClosure MakeExpectedRunAtLeastOnceClosure( 80 const Location& location, 81 StringPiece message = StringPiece()); 82 83 // Returns a closure that fails the test if run. 84 RepeatingClosure MakeExpectedNotRunClosure(const Location& location, 85 StringPiece message = StringPiece()); 86 87 } // namespace base 88 89 #endif // BASE_TEST_BIND_H_ 90