1 // Copyright 2022 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 #include "base/functional/function_ref.h"
6
7 #include "testing/gtest/include/gtest/gtest.h"
8
9 namespace base {
10
11 namespace {
12
Moo(float)13 char Moo(float) {
14 return 'a';
15 }
16
17 struct C {
Methodbase::__anondd3e23200111::C18 long Method() { return value; }
19 long value;
20 };
21
22 } // namespace
23
TEST(FunctionRefTest,FreeFunction)24 TEST(FunctionRefTest, FreeFunction) {
25 [](FunctionRef<char(float)> ref) { EXPECT_EQ('a', ref(1.0)); }(&Moo);
26 }
27
TEST(FunctionRefTest,Method)28 TEST(FunctionRefTest, Method) {
29 [](FunctionRef<long(C*)> ref) {
30 C c = {.value = 25L};
31 EXPECT_EQ(25L, ref(&c));
32 }(&C::Method);
33 }
34
TEST(FunctionRefTest,Lambda)35 TEST(FunctionRefTest, Lambda) {
36 int x = 3;
37 auto lambda = [&x]() { return x; };
38 [](FunctionRef<int()> ref) { EXPECT_EQ(3, ref()); }(lambda);
39 }
40
41 // Tests for passing a `base::FunctionRef` as an `absl::FunctionRef`.
TEST(FunctionRefTest,AbslConversion)42 TEST(FunctionRefTest, AbslConversion) {
43 // Matching signatures should work.
44 {
45 bool called = false;
46 auto lambda = [&called](float) {
47 called = true;
48 return 'a';
49 };
50 FunctionRef<char(float)> ref(lambda);
51 [](absl::FunctionRef<char(float)> absl_ref) {
52 absl_ref(1.0);
53 }(ref.ToAbsl());
54 EXPECT_TRUE(called);
55 }
56
57 // `absl::FunctionRef` should be able to adapt "similar enough" signatures.
58 {
59 bool called = false;
60 auto lambda = [&called](float) {
61 called = true;
62 return 'a';
63 };
64 FunctionRef<char(float)> ref(lambda);
65 [](absl::FunctionRef<void(float)> absl_ref) {
66 absl_ref(1.0);
67 }(ref.ToAbsl());
68 EXPECT_TRUE(called);
69 }
70 }
71
72 // base::FunctionRef allows functors with convertible return types to be
73 // adapted.
TEST(FunctionRefTest,ConvertibleReturnTypes)74 TEST(FunctionRefTest, ConvertibleReturnTypes) {
75 // Hopefully this never results in a postmorterm-worthy bug...
76 {
77 auto lambda = []() -> bool { return true; };
78 [](FunctionRef<int()> ref) { EXPECT_EQ(1, ref()); }(lambda);
79 }
80
81 {
82 class Base {};
83 class Derived : public Base {};
84
85 auto lambda = []() -> Derived* { return nullptr; };
86 [](FunctionRef<Base*()> ref) { EXPECT_EQ(nullptr, ref()); }(lambda);
87 }
88 }
89
90 } // namespace base
91