• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_BIND_H_
6 #define BASE_TEST_BIND_H_
7 
8 #include <type_traits>
9 #include <utility>
10 
11 #include "base/functional/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   // If WTF::BindRepeating is available, and a callback argument is in WTF, then
55   // this call is ambiguous without the full namespace path.
56   return ::base::BindRepeating(
57       &internal::BindLambdaHelper<Lambda, Signature>::Run,
58       std::forward<Lambda>(lambda));
59 }
60 
61 // A variant of BindOnce() that can bind mutable capturing lambdas for
62 // testing. This doesn't support extra arguments binding as the lambda itself
63 // can do. Since a mutable lambda potentially can invalidate its state after
64 // being run once, this method returns a OnceCallback instead of a
65 // RepeatingCallback.
66 template <typename Lambda,
67           std::enable_if_t<!internal::HasConstCallOperator<Lambda>>* = nullptr>
68 decltype(auto) BindLambdaForTesting(Lambda&& lambda) {
69   static_assert(
70       std::is_rvalue_reference<Lambda&&>() &&
71           !std::is_const<std::remove_reference_t<Lambda>>(),
72       "BindLambdaForTesting requires non-const rvalue for mutable lambda "
73       "binding. I.e.: base::BindLambdaForTesting(std::move(lambda)).");
74   using Signature = internal::ExtractCallableRunType<std::decay_t<Lambda>>;
75   return BindOnce(&internal::BindLambdaHelper<Lambda, Signature>::RunOnce,
76                   std::move(lambda));
77 }
78 
79 // Returns a closure that fails on destruction if it hasn't been run.
80 OnceClosure MakeExpectedRunClosure(const Location& location,
81                                    StringPiece message = StringPiece());
82 RepeatingClosure MakeExpectedRunAtLeastOnceClosure(
83     const Location& location,
84     StringPiece message = StringPiece());
85 
86 // Returns a closure that fails the test if run.
87 RepeatingClosure MakeExpectedNotRunClosure(const Location& location,
88                                            StringPiece message = StringPiece());
89 
90 }  // namespace base
91 
92 #endif  // BASE_TEST_BIND_H_
93