2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "wtf/Functional.h"
29 #include "wtf/OwnPtr.h"
30 #include "wtf/RefCounted.h"
31 #include <gtest/gtest.h>
35 class UnwrappedClass
{
37 explicit UnwrappedClass(int value
)
42 int value() const { return m_value
; }
50 explicit WrappedClass(int value
)
55 UnwrappedClass
unwrap() const { return UnwrappedClass(m_value
); }
61 // This class must be wrapped in bind() and unwrapped in closure execution.
62 class ClassToBeWrapped
{
63 WTF_MAKE_NONCOPYABLE(ClassToBeWrapped
);
65 explicit ClassToBeWrapped(int value
)
70 WrappedClass
wrap() const { return WrappedClass(m_value
); }
76 template<> struct ParamStorageTraits
<ClassToBeWrapped
> {
77 using StorageType
= WrappedClass
;
78 static StorageType
wrap(const ClassToBeWrapped
& value
) { return value
.wrap(); }
79 static UnwrappedClass
unwrap(const StorageType
& value
) { return value
.unwrap(); }
89 TEST(FunctionalTest
, Basic
)
91 OwnPtr
<Function
<int()>> returnFortyTwoFunction
= bind(returnFortyTwo
);
92 EXPECT_EQ(42, (*returnFortyTwoFunction
)());
95 int multiplyByTwo(int n
)
100 double multiplyByOneAndAHalf(double d
)
105 TEST(FunctionalTest
, UnaryBind
)
107 OwnPtr
<Function
<int()>> multiplyFourByTwoFunction
= bind(multiplyByTwo
, 4);
108 EXPECT_EQ(8, (*multiplyFourByTwoFunction
)());
110 OwnPtr
<Function
<double()>> multiplyByOneAndAHalfFunction
= bind(multiplyByOneAndAHalf
, 3);
111 EXPECT_EQ(4.5, (*multiplyByOneAndAHalfFunction
)());
114 TEST(FunctionalTest
, UnaryPartBind
)
116 OwnPtr
<Function
<int(int)>> multiplyByTwoFunction
= bind
<int>(multiplyByTwo
);
117 EXPECT_EQ(8, (*multiplyByTwoFunction
)(4));
119 OwnPtr
<Function
<double(double)>> multiplyByOneAndAHalfFunction
= bind
<double>(multiplyByOneAndAHalf
);
120 EXPECT_EQ(4.5, (*multiplyByOneAndAHalfFunction
)(3));
123 int multiply(int x
, int y
)
128 int subtract(int x
, int y
)
133 TEST(FunctionalTest
, BinaryBind
)
135 OwnPtr
<Function
<int()>> multiplyFourByTwoFunction
= bind(multiply
, 4, 2);
136 EXPECT_EQ(8, (*multiplyFourByTwoFunction
)());
138 OwnPtr
<Function
<int()>> subtractTwoFromFourFunction
= bind(subtract
, 4, 2);
139 EXPECT_EQ(2, (*subtractTwoFromFourFunction
)());
142 TEST(FunctionalTest
, BinaryPartBind
)
144 OwnPtr
<Function
<int(int)>> multiplyFourFunction
= bind
<int>(multiply
, 4);
145 EXPECT_EQ(8, (*multiplyFourFunction
)(2));
146 OwnPtr
<Function
<int(int, int)>> multiplyFunction
= bind
<int, int>(multiply
);
147 EXPECT_EQ(8, (*multiplyFunction
)(4, 2));
149 OwnPtr
<Function
<int(int)>> subtractFromFourFunction
= bind
<int>(subtract
, 4);
150 EXPECT_EQ(2, (*subtractFromFourFunction
)(2));
151 OwnPtr
<Function
<int(int, int)>> subtractFunction
= bind
<int, int>(subtract
);
152 EXPECT_EQ(2, (*subtractFunction
)(4, 2));
155 void sixArgFunc(int a
, double b
, char c
, int* d
, double* e
, char* f
)
162 void assertArgs(int actualInt
, double actualDouble
, char actualChar
, int expectedInt
, double expectedDouble
, char expectedChar
)
164 EXPECT_EQ(expectedInt
, actualInt
);
165 EXPECT_EQ(expectedDouble
, actualDouble
);
166 EXPECT_EQ(expectedChar
, actualChar
);
169 TEST(FunctionalTest
, MultiPartBind
)
175 OwnPtr
<Function
<void(int, double, char, int*, double*, char*)>> unbound
=
176 bind
<int, double, char, int*, double*, char*>(sixArgFunc
);
177 (*unbound
)(1, 1.5, 'b', &a
, &b
, &c
);
178 assertArgs(a
, b
, c
, 1, 1.5, 'b');
180 OwnPtr
<Function
<void(double, char, int*, double*, char*)>> oneBound
=
181 bind
<double, char, int*, double*, char*>(sixArgFunc
, 2);
182 (*oneBound
)(2.5, 'c', &a
, &b
, &c
);
183 assertArgs(a
, b
, c
, 2, 2.5, 'c');
185 OwnPtr
<Function
<void(char, int*, double*, char*)>> twoBound
=
186 bind
<char, int*, double*, char*>(sixArgFunc
, 3, 3.5);
187 (*twoBound
)('d', &a
, &b
, &c
);
188 assertArgs(a
, b
, c
, 3, 3.5, 'd');
190 OwnPtr
<Function
<void(int*, double*, char*)>> threeBound
=
191 bind
<int*, double*, char*>(sixArgFunc
, 4, 4.5, 'e');
192 (*threeBound
)(&a
, &b
, &c
);
193 assertArgs(a
, b
, c
, 4, 4.5, 'e');
195 OwnPtr
<Function
<void(double*, char*)>> fourBound
=
196 bind
<double*, char*>(sixArgFunc
, 5, 5.5, 'f', &a
);
197 (*fourBound
)(&b
, &c
);
198 assertArgs(a
, b
, c
, 5, 5.5, 'f');
200 OwnPtr
<Function
<void(char*)>> fiveBound
=
201 bind
<char*>(sixArgFunc
, 6, 6.5, 'g', &a
, &b
);
203 assertArgs(a
, b
, c
, 6, 6.5, 'g');
205 OwnPtr
<Function
<void()>> sixBound
=
206 bind(sixArgFunc
, 7, 7.5, 'h', &a
, &b
, &c
);
208 assertArgs(a
, b
, c
, 7, 7.5, 'h');
218 int f() { return m_i
; }
219 int addF(int j
) { return m_i
+ j
; }
225 TEST(FunctionalTest
, MemberFunctionBind
)
228 OwnPtr
<Function
<int()>> function1
= bind(&A::f
, &a
);
229 EXPECT_EQ(10, (*function1
)());
231 OwnPtr
<Function
<int()>> function2
= bind(&A::addF
, &a
, 15);
232 EXPECT_EQ(25, (*function2
)());
235 TEST(FunctionalTest
, MemberFunctionPartBind
)
238 OwnPtr
<Function
<int(class A
*)>> function1
= bind
<class A
*>(&A::f
);
239 EXPECT_EQ(10, (*function1
)(&a
));
241 OwnPtr
<Function
<int(class A
*, int)>> unboundFunction2
=
242 bind
<class A
*, int>(&A::addF
);
243 EXPECT_EQ(25, (*unboundFunction2
)(&a
, 15));
244 OwnPtr
<Function
<int(int)>> objectBoundFunction2
=
245 bind
<int>(&A::addF
, &a
);
246 EXPECT_EQ(25, (*objectBoundFunction2
)(15));
249 class Number
: public RefCounted
<Number
> {
251 static PassRefPtr
<Number
> create(int value
)
253 return adoptRef(new Number(value
));
261 int value() const { return m_value
; }
264 explicit Number(int value
)
272 int multiplyNumberByTwo(Number
* number
)
274 return number
->value() * 2;
277 TEST(FunctionalTest
, RefCountedStorage
)
279 RefPtr
<Number
> five
= Number::create(5);
280 OwnPtr
<Function
<int()>> multiplyFiveByTwoFunction
= bind(multiplyNumberByTwo
, five
);
281 EXPECT_EQ(10, (*multiplyFiveByTwoFunction
)());
283 OwnPtr
<Function
<int()>> multiplyFourByTwoFunction
= bind(multiplyNumberByTwo
, Number::create(4));
284 EXPECT_EQ(8, (*multiplyFourByTwoFunction
)());
286 RefPtr
<Number
> six
= Number::create(6);
287 OwnPtr
<Function
<int()>> multiplySixByTwoFunction
= bind(multiplyNumberByTwo
, six
.release());
289 EXPECT_EQ(12, (*multiplySixByTwoFunction
)());
292 int processUnwrappedClass(const UnwrappedClass
& u
, int v
)
294 return u
.value() * v
;
298 // - ParamStorageTraits's wrap()/unwrap() are called, and
299 // - bind()'s arguments are passed as references to ParamStorageTraits::wrap()
300 // with no additional copies.
301 // This test would fail in compile if something is wrong,
302 // rather than in runtime.
303 TEST(FunctionalTest
, WrapUnwrap
)
305 OwnPtr
<Function
<int()>> function
= bind(processUnwrappedClass
, ClassToBeWrapped(3), 7);
306 EXPECT_EQ(21, (*function
)());
309 TEST(FunctionalTest
, WrapUnwrapInPartialBind
)
311 OwnPtr
<Function
<int(int)>> partiallyBoundFunction
= bind
<int>(processUnwrappedClass
, ClassToBeWrapped(3));
312 EXPECT_EQ(21, (*partiallyBoundFunction
)(7));
315 } // anonymous namespace