1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 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 #include "base/functional/function_ref.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <concepts>
10*6777b538SAndroid Build Coastguard Worker #include <optional>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
13*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
14*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/functional/function_ref.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker namespace {
19*6777b538SAndroid Build Coastguard Worker
Func(float)20*6777b538SAndroid Build Coastguard Worker char Func(float) {
21*6777b538SAndroid Build Coastguard Worker return 'a';
22*6777b538SAndroid Build Coastguard Worker }
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker } // namespace
25*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,Lambda)26*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, Lambda) {
27*6777b538SAndroid Build Coastguard Worker auto add = [](int a, int b) { return a + b; };
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker {
30*6777b538SAndroid Build Coastguard Worker const FunctionRef<int(int, int)> ref = add;
31*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(19, ref(17, 2));
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker {
35*6777b538SAndroid Build Coastguard Worker const auto add_const = add;
36*6777b538SAndroid Build Coastguard Worker const FunctionRef<int(int, int)> ref = add_const;
37*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(19, ref(17, 2));
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker }
40*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,CapturingLambda)41*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, CapturingLambda) {
42*6777b538SAndroid Build Coastguard Worker int x = 3;
43*6777b538SAndroid Build Coastguard Worker const auto lambda = [&x] { return x; };
44*6777b538SAndroid Build Coastguard Worker FunctionRef<int()> ref = lambda;
45*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(3, ref());
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,FunctionPtr)48*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, FunctionPtr) {
49*6777b538SAndroid Build Coastguard Worker [](FunctionRef<char(float)> ref) { EXPECT_EQ('a', ref(1.0)); }(&Func);
50*6777b538SAndroid Build Coastguard Worker const FunctionRef<char(float)> ref = +[](float) { return 'a'; };
51*6777b538SAndroid Build Coastguard Worker EXPECT_EQ('a', ref(1.0f));
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,Functor)54*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, Functor) {
55*6777b538SAndroid Build Coastguard Worker struct S {
56*6777b538SAndroid Build Coastguard Worker int operator()(int x) const { return x; }
57*6777b538SAndroid Build Coastguard Worker };
58*6777b538SAndroid Build Coastguard Worker const S s;
59*6777b538SAndroid Build Coastguard Worker const FunctionRef<int(int)> ref = s;
60*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(17, ref(17));
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,Method)63*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, Method) {
64*6777b538SAndroid Build Coastguard Worker struct S {
65*6777b538SAndroid Build Coastguard Worker int Method() const { return value; }
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker const int value;
68*6777b538SAndroid Build Coastguard Worker };
69*6777b538SAndroid Build Coastguard Worker const S s(25);
70*6777b538SAndroid Build Coastguard Worker [&s](FunctionRef<int(const S*)> ref) { EXPECT_EQ(25, ref(&s)); }(&S::Method);
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker // If we construct from another `FunctionRef`, that should work fine, even if
74*6777b538SAndroid Build Coastguard Worker // the input is destroyed before we call the output. In other words, we should
75*6777b538SAndroid Build Coastguard Worker // reference the underlying callable, not the `FunctionRef`.
76*6777b538SAndroid Build Coastguard Worker //
77*6777b538SAndroid Build Coastguard Worker // We construct in a `noinline` function to maximize the chance that ASAN
78*6777b538SAndroid Build Coastguard Worker // notices the use-after-free if we get this wrong.
ConstructFromLValue(std::optional<FunctionRef<int ()>> & ref)79*6777b538SAndroid Build Coastguard Worker NOINLINE void ConstructFromLValue(std::optional<FunctionRef<int()>>& ref) {
80*6777b538SAndroid Build Coastguard Worker const auto return_17 = [] { return 17; };
81*6777b538SAndroid Build Coastguard Worker FunctionRef<int()> other = return_17;
82*6777b538SAndroid Build Coastguard Worker ref.emplace(other);
83*6777b538SAndroid Build Coastguard Worker }
ConstructFromConstLValue(std::optional<FunctionRef<int ()>> & ref)84*6777b538SAndroid Build Coastguard Worker NOINLINE void ConstructFromConstLValue(std::optional<FunctionRef<int()>>& ref) {
85*6777b538SAndroid Build Coastguard Worker const auto return_17 = [] { return 17; };
86*6777b538SAndroid Build Coastguard Worker const FunctionRef<int()> other = return_17;
87*6777b538SAndroid Build Coastguard Worker ref.emplace(other);
88*6777b538SAndroid Build Coastguard Worker }
ConstructFromRValue(std::optional<FunctionRef<int ()>> & ref)89*6777b538SAndroid Build Coastguard Worker NOINLINE void ConstructFromRValue(std::optional<FunctionRef<int()>>& ref) {
90*6777b538SAndroid Build Coastguard Worker const auto return_17 = [] { return 17; };
91*6777b538SAndroid Build Coastguard Worker using Ref = FunctionRef<int()>;
92*6777b538SAndroid Build Coastguard Worker ref.emplace(Ref(return_17));
93*6777b538SAndroid Build Coastguard Worker }
ConstructFromConstRValue(std::optional<FunctionRef<int ()>> & ref)94*6777b538SAndroid Build Coastguard Worker NOINLINE void ConstructFromConstRValue(std::optional<FunctionRef<int()>>& ref) {
95*6777b538SAndroid Build Coastguard Worker const auto return_17 = [] { return 17; };
96*6777b538SAndroid Build Coastguard Worker using Ref = const FunctionRef<int()>;
97*6777b538SAndroid Build Coastguard Worker ref.emplace(Ref(return_17));
98*6777b538SAndroid Build Coastguard Worker }
TEST(FunctionRef,ConstructionFromOtherFunctionRefObjects)99*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, ConstructionFromOtherFunctionRefObjects) {
100*6777b538SAndroid Build Coastguard Worker using Ref = FunctionRef<int()>;
101*6777b538SAndroid Build Coastguard Worker std::optional<Ref> ref;
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker ConstructFromLValue(ref);
104*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(17, (*ref)());
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker ConstructFromConstLValue(ref);
107*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(17, (*ref)());
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker ConstructFromRValue(ref);
110*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(17, (*ref)());
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker ConstructFromConstRValue(ref);
113*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(17, (*ref)());
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker // It shouldn't be possible to construct from `FunctionRef` objects with
116*6777b538SAndroid Build Coastguard Worker // differing signatures, even if they are compatible with `int()`.
117*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, FunctionRef<void()>>);
118*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, FunctionRef<int(int)>>);
119*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, FunctionRef<int64_t()>>);
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker // Check again with various qualifiers.
122*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, const FunctionRef<void()>>);
123*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, FunctionRef<void()>&>);
124*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, FunctionRef<void()>&&>);
125*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, const FunctionRef<void()>&>);
126*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<Ref, const FunctionRef<void()>&&>);
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker // `FunctionRef` allows functors with convertible return types to be adapted.
TEST(FunctionRef,ConvertibleReturnTypes)130*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, ConvertibleReturnTypes) {
131*6777b538SAndroid Build Coastguard Worker {
132*6777b538SAndroid Build Coastguard Worker const auto lambda = [] { return true; };
133*6777b538SAndroid Build Coastguard Worker const FunctionRef<int()> ref = lambda;
134*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, ref());
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker {
138*6777b538SAndroid Build Coastguard Worker class Base {};
139*6777b538SAndroid Build Coastguard Worker class Derived : public Base {};
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker const auto lambda = []() -> Derived* { return nullptr; };
142*6777b538SAndroid Build Coastguard Worker const FunctionRef<const Base*()> ref = lambda;
143*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(nullptr, ref());
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,ConstructionFromInexactMatches)147*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, ConstructionFromInexactMatches) {
148*6777b538SAndroid Build Coastguard Worker // Lambda.
149*6777b538SAndroid Build Coastguard Worker const auto lambda = [](int32_t x) { return x; };
150*6777b538SAndroid Build Coastguard Worker
151*6777b538SAndroid Build Coastguard Worker // Capturing lambda.
152*6777b538SAndroid Build Coastguard Worker const auto capturing_lambda = [&](int32_t x) { return lambda(x); };
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker // Function pointer.
155*6777b538SAndroid Build Coastguard Worker int32_t (*const function_ptr)(int32_t) = +lambda;
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker // Functor.
158*6777b538SAndroid Build Coastguard Worker struct Functor {
159*6777b538SAndroid Build Coastguard Worker int32_t operator()(int32_t x) const { return x; }
160*6777b538SAndroid Build Coastguard Worker };
161*6777b538SAndroid Build Coastguard Worker const Functor functor;
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker // Method.
164*6777b538SAndroid Build Coastguard Worker struct Obj {
165*6777b538SAndroid Build Coastguard Worker int32_t Method(int32_t x) const { return x; }
166*6777b538SAndroid Build Coastguard Worker };
167*6777b538SAndroid Build Coastguard Worker int32_t (Obj::*const method)(int32_t) const = &Obj::Method;
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Worker // Each of the objects above should work for a `FunctionRef` with a
170*6777b538SAndroid Build Coastguard Worker // convertible return type. In this case, they all return `int32_t`, which
171*6777b538SAndroid Build Coastguard Worker // should be seamlessly convertible to `int64_t` below.
172*6777b538SAndroid Build Coastguard Worker static_assert(
173*6777b538SAndroid Build Coastguard Worker std::constructible_from<FunctionRef<int64_t(int32_t)>, decltype(lambda)>);
174*6777b538SAndroid Build Coastguard Worker static_assert(std::constructible_from<FunctionRef<int64_t(int32_t)>,
175*6777b538SAndroid Build Coastguard Worker decltype(capturing_lambda)>);
176*6777b538SAndroid Build Coastguard Worker static_assert(std::constructible_from<FunctionRef<int64_t(int32_t)>,
177*6777b538SAndroid Build Coastguard Worker decltype(function_ptr)>);
178*6777b538SAndroid Build Coastguard Worker static_assert(std::constructible_from<FunctionRef<int64_t(int32_t)>,
179*6777b538SAndroid Build Coastguard Worker decltype(functor)>);
180*6777b538SAndroid Build Coastguard Worker static_assert(
181*6777b538SAndroid Build Coastguard Worker std::constructible_from<FunctionRef<int64_t(const Obj*, int32_t)>,
182*6777b538SAndroid Build Coastguard Worker decltype(method)>);
183*6777b538SAndroid Build Coastguard Worker
184*6777b538SAndroid Build Coastguard Worker // It shouldn't be possible to construct a `FunctionRef` from any of the
185*6777b538SAndroid Build Coastguard Worker // objects above if we discard the return value.
186*6777b538SAndroid Build Coastguard Worker static_assert(
187*6777b538SAndroid Build Coastguard Worker !std::constructible_from<FunctionRef<void(int32_t)>, decltype(lambda)>);
188*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<FunctionRef<void(int32_t)>,
189*6777b538SAndroid Build Coastguard Worker decltype(capturing_lambda)>);
190*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<FunctionRef<void(int32_t)>,
191*6777b538SAndroid Build Coastguard Worker decltype(function_ptr)>);
192*6777b538SAndroid Build Coastguard Worker static_assert(
193*6777b538SAndroid Build Coastguard Worker !std::constructible_from<FunctionRef<void(int32_t)>, decltype(functor)>);
194*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<FunctionRef<void(const Obj*, int32_t)>,
195*6777b538SAndroid Build Coastguard Worker decltype(method)>);
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker // It shouldn't be possible to construct a `FunctionRef` from a pointer to a
198*6777b538SAndroid Build Coastguard Worker // functor, even with a compatible signature.
199*6777b538SAndroid Build Coastguard Worker static_assert(!std::constructible_from<FunctionRef<int32_t(int32_t)>,
200*6777b538SAndroid Build Coastguard Worker decltype(&functor)>);
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
TEST(FunctionRef,ConstructionFromAbslFunctionRef)203*6777b538SAndroid Build Coastguard Worker TEST(FunctionRef, ConstructionFromAbslFunctionRef) {
204*6777b538SAndroid Build Coastguard Worker // It shouldn't be possible to construct a `FunctionRef` from an
205*6777b538SAndroid Build Coastguard Worker // `absl::FunctionRef`, whether the signatures are compatible or not.
206*6777b538SAndroid Build Coastguard Worker using Ref = FunctionRef<int(int)>;
207*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, absl::FunctionRef<void()>>);
208*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, absl::FunctionRef<void(int)>>);
209*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, absl::FunctionRef<int(int)>>);
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker // Check again with various qualifiers.
212*6777b538SAndroid Build Coastguard Worker using AbslRef = absl::FunctionRef<int(int)>;
213*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, const AbslRef>);
214*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, AbslRef&>);
215*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, AbslRef&&>);
216*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, const AbslRef&>);
217*6777b538SAndroid Build Coastguard Worker static_assert(!std::is_constructible_v<Ref, const AbslRef&&>);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker } // namespace base
221