1//===-- unique_function_test.cpp ------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "unique_function.h"
10#include "gtest/gtest.h"
11
12using namespace orc_rt;
13
14TEST(UniqueFunctionTest, Basic) {
15 unique_function<int(int, int)> Sum = [](int A, int B) { return A + B; };
16 EXPECT_EQ(Sum(1, 2), 3);
17
18 unique_function<int(int, int)> Sum2 = std::move(Sum);
19 EXPECT_EQ(Sum2(1, 2), 3);
20
21 unique_function<int(int, int)> Sum3 = [](int A, int B) { return A + B; };
22 Sum2 = std::move(Sum3);
23 EXPECT_EQ(Sum2(1, 2), 3);
24
25 Sum2 = unique_function<int(int, int)>([](int A, int B) { return A + B; });
26 EXPECT_EQ(Sum2(1, 2), 3);
27
28 // Explicit self-move test.
29 *&Sum2 = std::move(Sum2);
30 EXPECT_EQ(Sum2(1, 2), 3);
31
32 Sum2 = unique_function<int(int, int)>();
33 EXPECT_FALSE(Sum2);
34
35 // Make sure we can forward through l-value reference parameters.
36 unique_function<void(int &)> Inc = [](int &X) { ++X; };
37 int X = 42;
38 Inc(X);
39 EXPECT_EQ(X, 43);
40
41 // Make sure we can forward through r-value reference parameters with
42 // move-only types.
43 unique_function<int(std::unique_ptr<int> &&)> ReadAndDeallocByRef =
44 [](std::unique_ptr<int> &&Ptr) {
45 int V = *Ptr;
46 Ptr.reset();
47 return V;
48 };
49 std::unique_ptr<int> Ptr{new int(13)};
50 EXPECT_EQ(ReadAndDeallocByRef(std::move(Ptr)), 13);
51 EXPECT_FALSE((bool)Ptr);
52
53 // Make sure we can pass a move-only temporary as opposed to a local variable.
54 EXPECT_EQ(ReadAndDeallocByRef(std::unique_ptr<int>(new int(42))), 42);
55
56 // Make sure we can pass a move-only type by-value.
57 unique_function<int(std::unique_ptr<int>)> ReadAndDeallocByVal =
58 [](std::unique_ptr<int> Ptr) {
59 int V = *Ptr;
60 Ptr.reset();
61 return V;
62 };
63 Ptr.reset(new int(13));
64 EXPECT_EQ(ReadAndDeallocByVal(std::move(Ptr)), 13);
65 EXPECT_FALSE((bool)Ptr);
66
67 EXPECT_EQ(ReadAndDeallocByVal(std::unique_ptr<int>(new int(42))), 42);
68}
69
70TEST(UniqueFunctionTest, Captures) {
71 long A = 1, B = 2, C = 3, D = 4, E = 5;
72
73 unique_function<long()> Tmp;
74
75 unique_function<long()> C1 = [A]() { return A; };
76 EXPECT_EQ(C1(), 1);
77 Tmp = std::move(t&: C1);
78 EXPECT_EQ(Tmp(), 1);
79
80 unique_function<long()> C2 = [A, B]() { return A + B; };
81 EXPECT_EQ(C2(), 3);
82 Tmp = std::move(t&: C2);
83 EXPECT_EQ(Tmp(), 3);
84
85 unique_function<long()> C3 = [A, B, C]() { return A + B + C; };
86 EXPECT_EQ(C3(), 6);
87 Tmp = std::move(t&: C3);
88 EXPECT_EQ(Tmp(), 6);
89
90 unique_function<long()> C4 = [A, B, C, D]() { return A + B + C + D; };
91 EXPECT_EQ(C4(), 10);
92 Tmp = std::move(t&: C4);
93 EXPECT_EQ(Tmp(), 10);
94
95 unique_function<long()> C5 = [A, B, C, D, E]() { return A + B + C + D + E; };
96 EXPECT_EQ(C5(), 15);
97 Tmp = std::move(t&: C5);
98 EXPECT_EQ(Tmp(), 15);
99}
100
101TEST(UniqueFunctionTest, MoveOnly) {
102 struct SmallCallable {
103 std::unique_ptr<int> A = std::make_unique<int>(args: 1);
104 int operator()(int B) { return *A + B; }
105 };
106
107 unique_function<int(int)> Small = SmallCallable();
108 EXPECT_EQ(Small(2), 3);
109 unique_function<int(int)> Small2 = std::move(t&: Small);
110 EXPECT_EQ(Small2(2), 3);
111}
112
113TEST(UniqueFunctionTest, CountForwardingCopies) {
114 struct CopyCounter {
115 int &CopyCount;
116
117 CopyCounter(int &CopyCount) : CopyCount(CopyCount) {}
118 CopyCounter(const CopyCounter &Arg) : CopyCount(Arg.CopyCount) {
119 ++CopyCount;
120 }
121 };
122
123 unique_function<void(CopyCounter)> ByValF = [](CopyCounter) {};
124 int CopyCount = 0;
125 ByValF(CopyCounter(CopyCount));
126 EXPECT_EQ(1, CopyCount);
127
128 CopyCount = 0;
129 {
130 CopyCounter Counter{CopyCount};
131 ByValF(Counter);
132 }
133 EXPECT_EQ(2, CopyCount);
134
135 // Check that we don't generate a copy at all when we can bind a reference all
136 // the way down, even if that reference could *in theory* allow copies.
137 unique_function<void(const CopyCounter &)> ByRefF = [](const CopyCounter &) {
138 };
139 CopyCount = 0;
140 ByRefF(CopyCounter(CopyCount));
141 EXPECT_EQ(0, CopyCount);
142
143 CopyCount = 0;
144 {
145 CopyCounter Counter{CopyCount};
146 ByRefF(Counter);
147 }
148 EXPECT_EQ(0, CopyCount);
149
150 // If we use a reference, we can make a stronger guarantee that *no* copy
151 // occurs.
152 struct Uncopyable {
153 Uncopyable() = default;
154 Uncopyable(const Uncopyable &) = delete;
155 };
156 unique_function<void(const Uncopyable &)> UncopyableF =
157 [](const Uncopyable &) {};
158 UncopyableF(Uncopyable());
159 Uncopyable X;
160 UncopyableF(X);
161}
162
163TEST(UniqueFunctionTest, BooleanConversion) {
164 unique_function<void()> D;
165 EXPECT_FALSE(D);
166
167 unique_function<void()> F = []() {};
168 EXPECT_TRUE(F);
169}
170

source code of compiler-rt/lib/orc/tests/unit/unique_function_test.cpp