xref: /aosp_15_r20/external/pigweed/pw_function/function_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_function/function.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_compilation_testing/negative_compilation.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_polyfill/language_feature_macros.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
20*61c4878aSAndroid Build Coastguard Worker 
21*61c4878aSAndroid Build Coastguard Worker namespace pw {
22*61c4878aSAndroid Build Coastguard Worker namespace {
23*61c4878aSAndroid Build Coastguard Worker 
24*61c4878aSAndroid Build Coastguard Worker #if PW_NC_TEST(CannotInstantiateWithNonFunction)
25*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("must be instantiated with a function type");
26*61c4878aSAndroid Build Coastguard Worker 
27*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] Function<int> function_pointer;
28*61c4878aSAndroid Build Coastguard Worker 
29*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotInstantiateWithFunctionPointer1)
30*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("must be instantiated with a function type");
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] Function<void (*)()> function_pointer;
33*61c4878aSAndroid Build Coastguard Worker 
34*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotInstantiateWithFunctionPointer2)
35*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("must be instantiated with a function type");
36*61c4878aSAndroid Build Coastguard Worker 
37*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] void SomeFunction(int);
38*61c4878aSAndroid Build Coastguard Worker 
39*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] Function<decltype(&SomeFunction)> function_pointer;
40*61c4878aSAndroid Build Coastguard Worker 
41*61c4878aSAndroid Build Coastguard Worker #elif PW_NC_TEST(CannotInstantiateWithFunctionReference)
42*61c4878aSAndroid Build Coastguard Worker PW_NC_EXPECT("must be instantiated with a function type");
43*61c4878aSAndroid Build Coastguard Worker 
44*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] Function<void (&)()> function_pointer;
45*61c4878aSAndroid Build Coastguard Worker 
46*61c4878aSAndroid Build Coastguard Worker #endif  // PW_NC_TEST
47*61c4878aSAndroid Build Coastguard Worker 
48*61c4878aSAndroid Build Coastguard Worker // Ensure that Function can be constant initialized.
49*61c4878aSAndroid Build Coastguard Worker [[maybe_unused]] PW_CONSTINIT Function<void()> can_be_constant_initialized;
50*61c4878aSAndroid Build Coastguard Worker 
Multiply(int a,int b)51*61c4878aSAndroid Build Coastguard Worker int Multiply(int a, int b) { return a * b; }
52*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,OperatorCall)53*61c4878aSAndroid Build Coastguard Worker TEST(Function, OperatorCall) {
54*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> multiply(Multiply);
55*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(multiply(3, 7), 21);
56*61c4878aSAndroid Build Coastguard Worker }
57*61c4878aSAndroid Build Coastguard Worker 
CallbackAdd(int a,int b,pw::Function<void (int sum)> callback)58*61c4878aSAndroid Build Coastguard Worker void CallbackAdd(int a, int b, pw::Function<void(int sum)> callback) {
59*61c4878aSAndroid Build Coastguard Worker   callback(a + b);
60*61c4878aSAndroid Build Coastguard Worker }
61*61c4878aSAndroid Build Coastguard Worker 
InlineCallbackAdd(int a,int b,pw::InlineFunction<void (int sum)> callback)62*61c4878aSAndroid Build Coastguard Worker void InlineCallbackAdd(int a,
63*61c4878aSAndroid Build Coastguard Worker                        int b,
64*61c4878aSAndroid Build Coastguard Worker                        pw::InlineFunction<void(int sum)> callback) {
65*61c4878aSAndroid Build Coastguard Worker   callback(a + b);
66*61c4878aSAndroid Build Coastguard Worker }
67*61c4878aSAndroid Build Coastguard Worker 
68*61c4878aSAndroid Build Coastguard Worker int add_result = -1;
69*61c4878aSAndroid Build Coastguard Worker 
free_add_callback(int sum)70*61c4878aSAndroid Build Coastguard Worker void free_add_callback(int sum) { add_result = sum; }
71*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,ConstructInPlace_FreeFunction)72*61c4878aSAndroid Build Coastguard Worker TEST(Function, ConstructInPlace_FreeFunction) {
73*61c4878aSAndroid Build Coastguard Worker   add_result = -1;
74*61c4878aSAndroid Build Coastguard Worker   CallbackAdd(25, 17, free_add_callback);
75*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(add_result, 42);
76*61c4878aSAndroid Build Coastguard Worker }
77*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,ConstructInPlace_NonCapturingLambda)78*61c4878aSAndroid Build Coastguard Worker TEST(Function, ConstructInPlace_NonCapturingLambda) {
79*61c4878aSAndroid Build Coastguard Worker   add_result = -1;
80*61c4878aSAndroid Build Coastguard Worker   CallbackAdd(25, 18, [](int sum) { add_result = sum; });
81*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(add_result, 43);
82*61c4878aSAndroid Build Coastguard Worker }
83*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,ConstructInPlace_CapturingLambda)84*61c4878aSAndroid Build Coastguard Worker TEST(Function, ConstructInPlace_CapturingLambda) {
85*61c4878aSAndroid Build Coastguard Worker   int result = -1;
86*61c4878aSAndroid Build Coastguard Worker   CallbackAdd(25, 19, [&](int sum) { result = sum; });
87*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result, 44);
88*61c4878aSAndroid Build Coastguard Worker }
89*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,ConstructInPlace_FreeFunction)90*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, ConstructInPlace_FreeFunction) {
91*61c4878aSAndroid Build Coastguard Worker   add_result = -1;
92*61c4878aSAndroid Build Coastguard Worker   InlineCallbackAdd(25, 17, free_add_callback);
93*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(add_result, 42);
94*61c4878aSAndroid Build Coastguard Worker }
95*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,ConstructInPlace_NonCapturingLambda)96*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, ConstructInPlace_NonCapturingLambda) {
97*61c4878aSAndroid Build Coastguard Worker   add_result = -1;
98*61c4878aSAndroid Build Coastguard Worker   InlineCallbackAdd(25, 18, [](int sum) { add_result = sum; });
99*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(add_result, 43);
100*61c4878aSAndroid Build Coastguard Worker }
101*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,ConstructInPlace_CapturingLambda)102*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, ConstructInPlace_CapturingLambda) {
103*61c4878aSAndroid Build Coastguard Worker   int result = -1;
104*61c4878aSAndroid Build Coastguard Worker   InlineCallbackAdd(25, 19, [&](int sum) { result = sum; });
105*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result, 44);
106*61c4878aSAndroid Build Coastguard Worker }
107*61c4878aSAndroid Build Coastguard Worker 
108*61c4878aSAndroid Build Coastguard Worker class CallableObject {
109*61c4878aSAndroid Build Coastguard Worker  public:
CallableObject(int * result)110*61c4878aSAndroid Build Coastguard Worker   CallableObject(int* result) : result_(result) {}
111*61c4878aSAndroid Build Coastguard Worker 
112*61c4878aSAndroid Build Coastguard Worker   CallableObject(CallableObject&& other) = default;
113*61c4878aSAndroid Build Coastguard Worker   CallableObject& operator=(CallableObject&& other) = default;
114*61c4878aSAndroid Build Coastguard Worker 
operator ()(int sum)115*61c4878aSAndroid Build Coastguard Worker   void operator()(int sum) { *result_ = sum; }
116*61c4878aSAndroid Build Coastguard Worker 
117*61c4878aSAndroid Build Coastguard Worker  private:
118*61c4878aSAndroid Build Coastguard Worker   int* result_;
119*61c4878aSAndroid Build Coastguard Worker };
120*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,ConstructInPlace_CallableObject)121*61c4878aSAndroid Build Coastguard Worker TEST(Function, ConstructInPlace_CallableObject) {
122*61c4878aSAndroid Build Coastguard Worker   int result = -1;
123*61c4878aSAndroid Build Coastguard Worker   CallbackAdd(25, 20, CallableObject(&result));
124*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result, 45);
125*61c4878aSAndroid Build Coastguard Worker }
126*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,ConstructInPlace_CallableObject)127*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, ConstructInPlace_CallableObject) {
128*61c4878aSAndroid Build Coastguard Worker   int result = -1;
129*61c4878aSAndroid Build Coastguard Worker   InlineCallbackAdd(25, 20, CallableObject(&result));
130*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result, 45);
131*61c4878aSAndroid Build Coastguard Worker }
132*61c4878aSAndroid Build Coastguard Worker 
133*61c4878aSAndroid Build Coastguard Worker class MemberFunctionTest : public ::testing::Test {
134*61c4878aSAndroid Build Coastguard Worker  protected:
MemberFunctionTest()135*61c4878aSAndroid Build Coastguard Worker   MemberFunctionTest() : result_(-1) {}
136*61c4878aSAndroid Build Coastguard Worker 
set_result(int result)137*61c4878aSAndroid Build Coastguard Worker   void set_result(int result) { result_ = result; }
138*61c4878aSAndroid Build Coastguard Worker 
139*61c4878aSAndroid Build Coastguard Worker   int result_;
140*61c4878aSAndroid Build Coastguard Worker };
141*61c4878aSAndroid Build Coastguard Worker 
TEST_F(MemberFunctionTest,ConstructInPlace_Lambda)142*61c4878aSAndroid Build Coastguard Worker TEST_F(MemberFunctionTest, ConstructInPlace_Lambda) {
143*61c4878aSAndroid Build Coastguard Worker   CallbackAdd(25, 21, [this](int sum) { set_result(sum); });
144*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result_, 46);
145*61c4878aSAndroid Build Coastguard Worker }
146*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Null_OperatorBool)147*61c4878aSAndroid Build Coastguard Worker TEST(Function, Null_OperatorBool) {
148*61c4878aSAndroid Build Coastguard Worker   Closure implicit_null;
149*61c4878aSAndroid Build Coastguard Worker   Closure explicit_null(nullptr);
150*61c4878aSAndroid Build Coastguard Worker   Closure assigned_null = nullptr;
151*61c4878aSAndroid Build Coastguard Worker   Closure not_null([]() {});
152*61c4878aSAndroid Build Coastguard Worker 
153*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(bool(implicit_null));
154*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(bool(explicit_null));
155*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(bool(assigned_null));
156*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(bool(not_null));
157*61c4878aSAndroid Build Coastguard Worker 
158*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(!implicit_null);
159*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(!explicit_null);
160*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(!assigned_null);
161*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(!not_null);
162*61c4878aSAndroid Build Coastguard Worker }
163*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Null_OperatorEquals)164*61c4878aSAndroid Build Coastguard Worker TEST(Function, Null_OperatorEquals) {
165*61c4878aSAndroid Build Coastguard Worker   Closure implicit_null;
166*61c4878aSAndroid Build Coastguard Worker   Closure explicit_null(nullptr);
167*61c4878aSAndroid Build Coastguard Worker   Closure assigned_null = nullptr;
168*61c4878aSAndroid Build Coastguard Worker   Closure not_null([]() {});
169*61c4878aSAndroid Build Coastguard Worker 
170*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(implicit_null == nullptr);
171*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(explicit_null == nullptr);
172*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(assigned_null == nullptr);
173*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(not_null != nullptr);
174*61c4878aSAndroid Build Coastguard Worker 
175*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(implicit_null != nullptr);
176*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(explicit_null != nullptr);
177*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(assigned_null != nullptr);
178*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(not_null == nullptr);
179*61c4878aSAndroid Build Coastguard Worker }
180*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Null_Set)181*61c4878aSAndroid Build Coastguard Worker TEST(Function, Null_Set) {
182*61c4878aSAndroid Build Coastguard Worker   Closure function = []() {};
183*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(function, nullptr);
184*61c4878aSAndroid Build Coastguard Worker   function = nullptr;
185*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(function, nullptr);
186*61c4878aSAndroid Build Coastguard Worker }
187*61c4878aSAndroid Build Coastguard Worker 
DoNothing()188*61c4878aSAndroid Build Coastguard Worker void DoNothing() {}
189*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Null_FunctionPointer)190*61c4878aSAndroid Build Coastguard Worker TEST(Function, Null_FunctionPointer) {
191*61c4878aSAndroid Build Coastguard Worker   void (*ptr)() = DoNothing;
192*61c4878aSAndroid Build Coastguard Worker   Closure not_null(ptr);
193*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(not_null, nullptr);
194*61c4878aSAndroid Build Coastguard Worker   ptr = nullptr;
195*61c4878aSAndroid Build Coastguard Worker   Closure is_null(ptr);
196*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(is_null, nullptr);
197*61c4878aSAndroid Build Coastguard Worker }
198*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Move_Null)199*61c4878aSAndroid Build Coastguard Worker TEST(Function, Move_Null) {
200*61c4878aSAndroid Build Coastguard Worker   Closure moved;
201*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
202*61c4878aSAndroid Build Coastguard Worker   Closure function(std::move(moved));
203*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(function, nullptr);
204*61c4878aSAndroid Build Coastguard Worker 
205*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
206*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
207*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
208*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
209*61c4878aSAndroid Build Coastguard Worker }
210*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,MoveAssign_Null)211*61c4878aSAndroid Build Coastguard Worker TEST(Function, MoveAssign_Null) {
212*61c4878aSAndroid Build Coastguard Worker   Closure moved;
213*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
214*61c4878aSAndroid Build Coastguard Worker   Closure function = std::move(moved);
215*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(function, nullptr);
216*61c4878aSAndroid Build Coastguard Worker 
217*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
218*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
219*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
220*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
221*61c4878aSAndroid Build Coastguard Worker }
222*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Move_Inline)223*61c4878aSAndroid Build Coastguard Worker TEST(Function, Move_Inline) {
224*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> moved(Multiply);
225*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(moved, nullptr);
226*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> multiply(std::move(moved));
227*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(multiply(3, 3), 9);
228*61c4878aSAndroid Build Coastguard Worker 
229*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
230*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
231*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
232*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
233*61c4878aSAndroid Build Coastguard Worker }
234*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,Move_InlineFunctionToFunction)235*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, Move_InlineFunctionToFunction) {
236*61c4878aSAndroid Build Coastguard Worker   InlineFunction<int(int, int)> moved(Multiply);
237*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(moved, nullptr);
238*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> multiply(std::move(moved));
239*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(multiply(3, 3), 9);
240*61c4878aSAndroid Build Coastguard Worker 
241*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
242*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
243*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
244*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
245*61c4878aSAndroid Build Coastguard Worker }
246*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,MoveAssign_Inline)247*61c4878aSAndroid Build Coastguard Worker TEST(Function, MoveAssign_Inline) {
248*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> moved(Multiply);
249*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(moved, nullptr);
250*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> multiply = std::move(moved);
251*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(multiply(3, 3), 9);
252*61c4878aSAndroid Build Coastguard Worker 
253*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
254*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
255*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
256*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
257*61c4878aSAndroid Build Coastguard Worker }
258*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,MoveAssign_InlineFunctionToFunction)259*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, MoveAssign_InlineFunctionToFunction) {
260*61c4878aSAndroid Build Coastguard Worker   InlineFunction<int(int, int)> moved(Multiply);
261*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(moved, nullptr);
262*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> multiply = std::move(moved);
263*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(multiply(3, 3), 9);
264*61c4878aSAndroid Build Coastguard Worker 
265*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
266*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
267*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
268*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
269*61c4878aSAndroid Build Coastguard Worker }
270*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,MoveAssign_Callable)271*61c4878aSAndroid Build Coastguard Worker TEST(Function, MoveAssign_Callable) {
272*61c4878aSAndroid Build Coastguard Worker   Function<int(int, int)> operation = Multiply;
273*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(operation(3, 3), 9);
274*61c4878aSAndroid Build Coastguard Worker   operation = [](int a, int b) -> int { return a + b; };
275*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(operation(3, 3), 6);
276*61c4878aSAndroid Build Coastguard Worker }
277*61c4878aSAndroid Build Coastguard Worker 
TEST(InlineFunction,MoveAssign_Callable)278*61c4878aSAndroid Build Coastguard Worker TEST(InlineFunction, MoveAssign_Callable) {
279*61c4878aSAndroid Build Coastguard Worker   InlineFunction<int(int, int)> operation = Multiply;
280*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(operation(3, 3), 9);
281*61c4878aSAndroid Build Coastguard Worker   operation = [](int a, int b) -> int { return a + b; };
282*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(operation(3, 3), 6);
283*61c4878aSAndroid Build Coastguard Worker }
284*61c4878aSAndroid Build Coastguard Worker 
285*61c4878aSAndroid Build Coastguard Worker class MoveTracker {
286*61c4878aSAndroid Build Coastguard Worker  public:
MoveTracker()287*61c4878aSAndroid Build Coastguard Worker   MoveTracker() : move_count_(0) {}
288*61c4878aSAndroid Build Coastguard Worker 
MoveTracker(MoveTracker && other)289*61c4878aSAndroid Build Coastguard Worker   MoveTracker(MoveTracker&& other) : move_count_(other.move_count_ + 1) {}
290*61c4878aSAndroid Build Coastguard Worker   MoveTracker& operator=(MoveTracker&& other) = default;
291*61c4878aSAndroid Build Coastguard Worker 
operator ()() const292*61c4878aSAndroid Build Coastguard Worker   int operator()() const { return move_count_; }
293*61c4878aSAndroid Build Coastguard Worker 
294*61c4878aSAndroid Build Coastguard Worker  private:
295*61c4878aSAndroid Build Coastguard Worker   int move_count_;
296*61c4878aSAndroid Build Coastguard Worker };
297*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Move_CustomObject)298*61c4878aSAndroid Build Coastguard Worker TEST(Function, Move_CustomObject) {
299*61c4878aSAndroid Build Coastguard Worker   Function<int()> moved((MoveTracker()));
300*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved(), 1);
301*61c4878aSAndroid Build Coastguard Worker   Function<int()> tracker(std::move(moved));
302*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(tracker(), 2);
303*61c4878aSAndroid Build Coastguard Worker 
304*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
305*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
306*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
307*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
308*61c4878aSAndroid Build Coastguard Worker }
309*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,MoveAssign_CustomObject)310*61c4878aSAndroid Build Coastguard Worker TEST(Function, MoveAssign_CustomObject) {
311*61c4878aSAndroid Build Coastguard Worker   Function<int()> moved((MoveTracker()));
312*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved(), 1);
313*61c4878aSAndroid Build Coastguard Worker   Function<int()> tracker = std::move(moved);
314*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(tracker(), 2);
315*61c4878aSAndroid Build Coastguard Worker 
316*61c4878aSAndroid Build Coastguard Worker // Ignore use-after-move.
317*61c4878aSAndroid Build Coastguard Worker #ifndef __clang_analyzer__
318*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(moved, nullptr);
319*61c4878aSAndroid Build Coastguard Worker #endif  // __clang_analyzer__
320*61c4878aSAndroid Build Coastguard Worker }
321*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,MoveOnlyType)322*61c4878aSAndroid Build Coastguard Worker TEST(Function, MoveOnlyType) {
323*61c4878aSAndroid Build Coastguard Worker   class MoveOnlyType {
324*61c4878aSAndroid Build Coastguard Worker    public:
325*61c4878aSAndroid Build Coastguard Worker     MoveOnlyType() = default;
326*61c4878aSAndroid Build Coastguard Worker 
327*61c4878aSAndroid Build Coastguard Worker     MoveOnlyType(const MoveOnlyType& other) = delete;
328*61c4878aSAndroid Build Coastguard Worker     MoveOnlyType& operator=(const MoveOnlyType& other) = delete;
329*61c4878aSAndroid Build Coastguard Worker 
330*61c4878aSAndroid Build Coastguard Worker     MoveOnlyType(MoveOnlyType&&) = default;
331*61c4878aSAndroid Build Coastguard Worker     MoveOnlyType& operator=(MoveOnlyType&&) = default;
332*61c4878aSAndroid Build Coastguard Worker 
333*61c4878aSAndroid Build Coastguard Worker     bool ItsWorking() const { return true; }
334*61c4878aSAndroid Build Coastguard Worker   };
335*61c4878aSAndroid Build Coastguard Worker 
336*61c4878aSAndroid Build Coastguard Worker   pw::Function<bool(MoveOnlyType)> function = [](MoveOnlyType value) {
337*61c4878aSAndroid Build Coastguard Worker     return value.ItsWorking();
338*61c4878aSAndroid Build Coastguard Worker   };
339*61c4878aSAndroid Build Coastguard Worker 
340*61c4878aSAndroid Build Coastguard Worker   MoveOnlyType move_only;
341*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(function(std::move(move_only)));
342*61c4878aSAndroid Build Coastguard Worker }
343*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,CallbackCanOnlyBeCalledOnce)344*61c4878aSAndroid Build Coastguard Worker TEST(Function, CallbackCanOnlyBeCalledOnce) {
345*61c4878aSAndroid Build Coastguard Worker   Callback<void()> cb([]() {});
346*61c4878aSAndroid Build Coastguard Worker   cb();
347*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(cb);
348*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(cb, nullptr);
349*61c4878aSAndroid Build Coastguard Worker }
350*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,CallbackDestroysTargetAfterBeingCalled)351*61c4878aSAndroid Build Coastguard Worker TEST(Function, CallbackDestroysTargetAfterBeingCalled) {
352*61c4878aSAndroid Build Coastguard Worker   class MoveOnlyDestructionCounter {
353*61c4878aSAndroid Build Coastguard Worker    public:
354*61c4878aSAndroid Build Coastguard Worker     MoveOnlyDestructionCounter(int* destroyed_count)
355*61c4878aSAndroid Build Coastguard Worker         : destroyed_(destroyed_count) {}
356*61c4878aSAndroid Build Coastguard Worker 
357*61c4878aSAndroid Build Coastguard Worker     MoveOnlyDestructionCounter(const MoveOnlyDestructionCounter& other) =
358*61c4878aSAndroid Build Coastguard Worker         delete;
359*61c4878aSAndroid Build Coastguard Worker     MoveOnlyDestructionCounter& operator=(
360*61c4878aSAndroid Build Coastguard Worker         const MoveOnlyDestructionCounter& other) = delete;
361*61c4878aSAndroid Build Coastguard Worker 
362*61c4878aSAndroid Build Coastguard Worker     MoveOnlyDestructionCounter(MoveOnlyDestructionCounter&& t) {
363*61c4878aSAndroid Build Coastguard Worker       *this = std::move(t);
364*61c4878aSAndroid Build Coastguard Worker     }
365*61c4878aSAndroid Build Coastguard Worker     MoveOnlyDestructionCounter& operator=(MoveOnlyDestructionCounter&& t) {
366*61c4878aSAndroid Build Coastguard Worker       destroyed_ = t.destroyed_;
367*61c4878aSAndroid Build Coastguard Worker       t.destroyed_ = nullptr;
368*61c4878aSAndroid Build Coastguard Worker       return *this;
369*61c4878aSAndroid Build Coastguard Worker     }
370*61c4878aSAndroid Build Coastguard Worker 
371*61c4878aSAndroid Build Coastguard Worker     ~MoveOnlyDestructionCounter() {
372*61c4878aSAndroid Build Coastguard Worker       if (destroyed_) {
373*61c4878aSAndroid Build Coastguard Worker         (*destroyed_)++;
374*61c4878aSAndroid Build Coastguard Worker       }
375*61c4878aSAndroid Build Coastguard Worker     }
376*61c4878aSAndroid Build Coastguard Worker 
377*61c4878aSAndroid Build Coastguard Worker    private:
378*61c4878aSAndroid Build Coastguard Worker     int* destroyed_;
379*61c4878aSAndroid Build Coastguard Worker   };
380*61c4878aSAndroid Build Coastguard Worker 
381*61c4878aSAndroid Build Coastguard Worker   int destroyed_count = 0;
382*61c4878aSAndroid Build Coastguard Worker   MoveOnlyDestructionCounter destruction_counter(&destroyed_count);
383*61c4878aSAndroid Build Coastguard Worker   Callback<void()> cb = [counter = std::move(destruction_counter)]() {};
384*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(destroyed_count, 0);
385*61c4878aSAndroid Build Coastguard Worker   cb();
386*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(destroyed_count, 1);
387*61c4878aSAndroid Build Coastguard Worker }
388*61c4878aSAndroid Build Coastguard Worker 
389*61c4878aSAndroid Build Coastguard Worker }  // namespace
390*61c4878aSAndroid Build Coastguard Worker }  // namespace pw
391*61c4878aSAndroid Build Coastguard Worker 
392*61c4878aSAndroid Build Coastguard Worker namespace obscure_different_namespace_which_should_never_collide {
393*61c4878aSAndroid Build Coastguard Worker namespace {
394*61c4878aSAndroid Build Coastguard Worker 
TEST(Function,Null_OperatorEquals_DifferentNamespace)395*61c4878aSAndroid Build Coastguard Worker TEST(Function, Null_OperatorEquals_DifferentNamespace) {
396*61c4878aSAndroid Build Coastguard Worker   pw::Closure implicit_null;
397*61c4878aSAndroid Build Coastguard Worker   pw::Closure explicit_null(nullptr);
398*61c4878aSAndroid Build Coastguard Worker   pw::Closure assigned_null = nullptr;
399*61c4878aSAndroid Build Coastguard Worker   pw::Closure not_null([]() {});
400*61c4878aSAndroid Build Coastguard Worker 
401*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(implicit_null == nullptr);
402*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(explicit_null == nullptr);
403*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(assigned_null == nullptr);
404*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(not_null != nullptr);
405*61c4878aSAndroid Build Coastguard Worker 
406*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(implicit_null != nullptr);
407*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(explicit_null != nullptr);
408*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(assigned_null != nullptr);
409*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(not_null == nullptr);
410*61c4878aSAndroid Build Coastguard Worker }
411*61c4878aSAndroid Build Coastguard Worker 
412*61c4878aSAndroid Build Coastguard Worker }  // namespace
413*61c4878aSAndroid Build Coastguard Worker }  // namespace obscure_different_namespace_which_should_never_collide
414