// Copyright 2017 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_BIND_H_ #define BASE_TEST_BIND_H_ #include #include #include #include "base/functional/bind.h" namespace base { class Location; namespace internal { template static constexpr bool kHasConstCallOperator = false; template static constexpr bool kHasConstCallOperator = true; // Implementation of `BindLambdaForTesting()`, which checks preconditions before // handing off to `Bind{Once,Repeating}()`. template >> struct BindLambdaForTestingHelper; template struct BindLambdaForTestingHelper { private: using F = std::decay_t; // For context on this "templated struct with a lambda that asserts" pattern, // see comments in `Invoker<>`. template && !std::is_const_v>> struct IsNonConstRvalueRef { static constexpr bool value = [] { static_assert( v, "BindLambdaForTesting() requires non-const rvalue for mutable lambda " "binding, i.e. base::BindLambdaForTesting(std::move(lambda))."); return v; }(); }; static R Run(const F& f, Args... args) { return f(std::forward(args)...); } static R RunOnce(F&& f, Args... args) { return f(std::forward(args)...); } public: static auto BindLambdaForTesting(Lambda&& lambda) { if constexpr (kHasConstCallOperator) { // If WTF::BindRepeating is available, and a callback argument is in WTF, // then this call is ambiguous without the full namespace path. return ::base::BindRepeating(&Run, std::forward(lambda)); } else if constexpr (IsNonConstRvalueRef<>::value) { // Since a mutable lambda potentially can invalidate its state after being // run once, this method returns a `OnceCallback` instead of a // `RepeatingCallback`. return BindOnce(&RunOnce, std::move(lambda)); } } }; } // namespace internal // A variant of `Bind{Once,Repeating}()` that can bind capturing lambdas for // testing. This doesn't support extra arguments binding as the lambda itself // can do. template auto BindLambdaForTesting(Lambda&& lambda) { return internal::BindLambdaForTestingHelper::BindLambdaForTesting( std::forward(lambda)); } // Returns a closure that fails on destruction if it hasn't been run. OnceClosure MakeExpectedRunClosure( const Location& location, std::string_view message = std::string_view()); RepeatingClosure MakeExpectedRunAtLeastOnceClosure( const Location& location, std::string_view message = std::string_view()); // Returns a closure that fails the test if run. RepeatingClosure MakeExpectedNotRunClosure( const Location& location, std::string_view message = std::string_view()); } // namespace base #endif // BASE_TEST_BIND_H_