170 lines · cpp
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-exception6//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 with42 // 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(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(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(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(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(C5);98 EXPECT_EQ(Tmp(), 15);99}100 101TEST(UniqueFunctionTest, MoveOnly) {102 struct SmallCallable {103 std::unique_ptr<int> A = std::make_unique<int>(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(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 all136 // 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* copy151 // 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