forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindirect_value_test.cpp
130 lines (108 loc) · 3.35 KB
/
indirect_value_test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "common/indirect_value.h"
#include <gtest/gtest.h>
#include <string>
namespace Carbon {
namespace {
TEST(IndirectValueTest, ConstAccess) {
const IndirectValue<int> v = 42;
EXPECT_EQ(*v, 42);
EXPECT_EQ(v.GetPointer(), &*v);
}
TEST(IndirectValueTest, MutableAccess) {
IndirectValue<int> v = 42;
EXPECT_EQ(*v, 42);
EXPECT_EQ(v.GetPointer(), &*v);
*v = 0;
EXPECT_EQ(*v, 0);
}
struct NonMovable {
explicit NonMovable(int i) : i(i) {}
NonMovable(NonMovable&&) = delete;
auto operator=(NonMovable&&) -> NonMovable& = delete;
int i;
};
TEST(IndirectValueTest, Create) {
IndirectValue<NonMovable> v =
MakeIndirectValue([] { return NonMovable(42); });
EXPECT_EQ(v->i, 42);
}
auto GetIntReference() -> const int& {
static int i = 42;
return i;
}
TEST(IndirectValueTest, CreateWithDecay) {
auto v = MakeIndirectValue(GetIntReference);
EXPECT_TRUE((std::is_same_v<decltype(v), IndirectValue<int>>));
EXPECT_EQ(*v, 42);
}
// Test double which presents a value-like interface, but tracks which special
// member function (if any) caused it to reach its present value.
struct TestValue {
TestValue() : state("default constructed") {}
TestValue(const TestValue& /*rhs*/) : state("copy constructed") {}
TestValue(TestValue&& other) noexcept : state("move constructed") {
other.state = "move constructed from";
}
auto operator=(const TestValue& /*unused*/) noexcept -> TestValue& {
state = "copy assigned";
return *this;
}
auto operator=(TestValue&& other) noexcept -> TestValue& {
state = "move assigned";
other.state = "move assigned from";
return *this;
}
std::string state;
};
TEST(IndirectValueTest, ConstArrow) {
const IndirectValue<TestValue> v;
EXPECT_EQ(v->state, "default constructed");
}
TEST(IndirectValueTest, MutableArrow) {
IndirectValue<TestValue> v;
EXPECT_EQ(v->state, "default constructed");
v->state = "explicitly set";
EXPECT_EQ(v->state, "explicitly set");
}
TEST(IndirectValueTest, CopyConstruct) {
IndirectValue<TestValue> v1;
// NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
auto v2 = v1;
EXPECT_EQ(v1->state, "default constructed");
EXPECT_EQ(v2->state, "copy constructed");
}
TEST(IndirectValueTest, CopyAssign) {
IndirectValue<TestValue> v1;
IndirectValue<TestValue> v2;
v2 = v1;
EXPECT_EQ(v1->state, "default constructed");
EXPECT_EQ(v2->state, "copy assigned");
}
TEST(IndirectValueTest, MoveConstruct) {
IndirectValue<TestValue> v1;
auto v2 = std::move(v1);
// While not entirely safe, the `v1->state` access tests move behavior.
// NOLINTNEXTLINE(bugprone-use-after-move)
EXPECT_EQ(v1->state, "move constructed from");
EXPECT_EQ(v2->state, "move constructed");
}
TEST(IndirectValueTest, MoveAssign) {
IndirectValue<TestValue> v1;
IndirectValue<TestValue> v2;
v2 = std::move(v1);
// While not entirely safe, the `v1->state` access tests move behavior.
// NOLINTNEXTLINE(bugprone-use-after-move)
EXPECT_EQ(v1->state, "move assigned from");
EXPECT_EQ(v2->state, "move assigned");
}
TEST(IndirectValueTest, IncompleteType) {
struct S {
std::optional<IndirectValue<S>> v;
};
S s = {.v = S{}};
}
} // namespace
} // namespace Carbon