Files
carbon-lang/common/indirect_value_test.cpp
T
Geoff Romer 6ca6822157 Implement IndirectValue (#588)
Also updates `FieldAccess` to use `IndirectValue`, as an example.
2021-06-24 11:26:28 -07:00

126 lines
3.0 KiB
C++

// 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 <string>
#include "gtest/gtest.h"
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 {
NonMovable(int i) : i(i) {}
NonMovable(NonMovable&&) = delete;
auto operator=(NonMovable&&) -> NonMovable& = delete;
int i;
};
TEST(IndirectValueTest, Create) {
IndirectValue<NonMovable> v =
CreateIndirectValue([] { return NonMovable(42); });
EXPECT_EQ(v->i, 42);
}
const int& GetIntReference() {
static int i = 42;
return i;
}
TEST(IndirectValueTest, CreateWithDecay) {
auto v = CreateIndirectValue(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) : state("move constructed") {
other.state = "move constructed from";
}
TestValue& operator=(const TestValue&) {
state = "copy assigned";
return *this;
}
TestValue& operator=(TestValue&& other) {
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;
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);
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);
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