blob: cf6b78905f5007a194a931e925a604b4a16c81c8 [file] [log] [blame]
mtklein4a9426f2015-03-31 14:24:27 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkFunction.h"
9#include "Test.h"
10
mtklein0d992db2015-05-06 07:40:25 -070011static void test_add_five(skiatest::Reporter* r, SkFunction<int(int)>& f) {
mtklein97312d02015-04-01 08:11:16 -070012 REPORTER_ASSERT(r, f(3) == 8);
mtklein4a9426f2015-03-31 14:24:27 -070013 REPORTER_ASSERT(r, f(4) == 9);
14}
15
mtklein0d992db2015-05-06 07:40:25 -070016static void test_add_five(skiatest::Reporter* r, SkFunction<int(int)>&& f) { test_add_five(r, f); }
17
mtklein4a9426f2015-03-31 14:24:27 -070018static int add_five(int x) { return x + 5; }
19
20struct AddFive {
mtklein0d992db2015-05-06 07:40:25 -070021 int operator()(int x) const { return x + 5; };
mtklein4a9426f2015-03-31 14:24:27 -070022};
23
mtklein0d992db2015-05-06 07:40:25 -070024class MoveOnlyThree : SkNoncopyable {
mtklein03e51612015-04-01 13:08:50 -070025public:
mtklein0d992db2015-05-06 07:40:25 -070026 MoveOnlyThree() {}
27 MoveOnlyThree(MoveOnlyThree&&) {}
28 MoveOnlyThree& operator=(MoveOnlyThree&&) { return *this; }
mtklein03e51612015-04-01 13:08:50 -070029
mtklein0d992db2015-05-06 07:40:25 -070030 int val() { return 3; }
mtklein03e51612015-04-01 13:08:50 -070031};
32
mtklein4a9426f2015-03-31 14:24:27 -070033DEF_TEST(Function, r) {
mtklein0d992db2015-05-06 07:40:25 -070034 // We should be able to turn a function pointer, an explicit functor, or a
35 // lambda into an SkFunction all equally well.
mtklein03e51612015-04-01 13:08:50 -070036 test_add_five(r, &add_five);
37 test_add_five(r, AddFive());
38 test_add_five(r, [](int x) { return x + 5; });
mtklein97312d02015-04-01 08:11:16 -070039
40 // AddFive and the lambda above are both small enough to test small-object optimization.
41 // Now test a lambda that's much too large for the small-object optimization.
42 int a = 1, b = 1, c = 1, d = 1, e = 1;
mtklein03e51612015-04-01 13:08:50 -070043 test_add_five(r, [&](int x) { return x + a + b + c + d + e; });
mtklein74415272015-04-01 11:26:31 -070044
mtklein74415272015-04-01 11:26:31 -070045 // Makes sure we forward arguments when calling SkFunction.
mtklein0d992db2015-05-06 07:40:25 -070046 SkFunction<int(int, MoveOnlyThree&&, int)> f([](int x, MoveOnlyThree&& three, int y) {
47 return x * three.val() + y;
mtkleinb41f0572015-04-01 13:36:23 -070048 });
mtklein0d992db2015-05-06 07:40:25 -070049 REPORTER_ASSERT(r, f(2, MoveOnlyThree(), 4) == 10);
50
51 // SkFunctions can go in containers.
52 SkTArray<SkFunction<int(int)>> add_fivers;
53 add_fivers.push_back(&add_five);
54 add_fivers.push_back(AddFive());
55 add_fivers.push_back([](int x) { return x + 5; });
56 add_fivers.push_back([&](int x) { return x + a + b + c + d + e; });
57 for (auto& f : add_fivers) {
58 test_add_five(r, f);
59 }
60
61 // SkFunctions are assignable.
62 SkFunction<int(int)> empty;
63 empty = [](int x) { return x + 5; };
64 test_add_five(r, empty);
65
66 // This all is silly acrobatics, but it should at least work correctly.
67 SkFunction<int(int)> emptyA, emptyB(emptyA);
68 emptyA = emptyB;
69 emptyA = emptyA;
mtklein74415272015-04-01 11:26:31 -070070}