1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #include "fcp/base/unique_value.h"
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include <utility>
20*14675a02SAndroid Build Coastguard Worker
21*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
22*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
23*14675a02SAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
24*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
25*14675a02SAndroid Build Coastguard Worker
26*14675a02SAndroid Build Coastguard Worker namespace fcp {
27*14675a02SAndroid Build Coastguard Worker
28*14675a02SAndroid Build Coastguard Worker using ::testing::Eq;
29*14675a02SAndroid Build Coastguard Worker
30*14675a02SAndroid Build Coastguard Worker struct ValueBox {
31*14675a02SAndroid Build Coastguard Worker bool destructed = false;
32*14675a02SAndroid Build Coastguard Worker int value = 0;
33*14675a02SAndroid Build Coastguard Worker };
34*14675a02SAndroid Build Coastguard Worker
35*14675a02SAndroid Build Coastguard Worker class TracedValue {
36*14675a02SAndroid Build Coastguard Worker public:
TracedValue(int value)37*14675a02SAndroid Build Coastguard Worker explicit TracedValue(int value) : local_value_(0), box_(nullptr) {
38*14675a02SAndroid Build Coastguard Worker UpdateValue(value);
39*14675a02SAndroid Build Coastguard Worker }
40*14675a02SAndroid Build Coastguard Worker
AttachToBox(ValueBox * box)41*14675a02SAndroid Build Coastguard Worker void AttachToBox(ValueBox* box) {
42*14675a02SAndroid Build Coastguard Worker FCP_CHECK(box_ == nullptr);
43*14675a02SAndroid Build Coastguard Worker box_ = box;
44*14675a02SAndroid Build Coastguard Worker UpdateValue(local_value_);
45*14675a02SAndroid Build Coastguard Worker }
46*14675a02SAndroid Build Coastguard Worker
TracedValue(TracedValue const & other)47*14675a02SAndroid Build Coastguard Worker TracedValue(TracedValue const& other) : local_value_(0), box_(nullptr) {
48*14675a02SAndroid Build Coastguard Worker UpdateValue(other.value());
49*14675a02SAndroid Build Coastguard Worker }
50*14675a02SAndroid Build Coastguard Worker
operator =(TracedValue const & other)51*14675a02SAndroid Build Coastguard Worker TracedValue& operator=(TracedValue const& other) {
52*14675a02SAndroid Build Coastguard Worker UpdateValue(other.value());
53*14675a02SAndroid Build Coastguard Worker return *this;
54*14675a02SAndroid Build Coastguard Worker }
55*14675a02SAndroid Build Coastguard Worker
~TracedValue()56*14675a02SAndroid Build Coastguard Worker ~TracedValue() {
57*14675a02SAndroid Build Coastguard Worker if (box_) {
58*14675a02SAndroid Build Coastguard Worker box_->destructed = true;
59*14675a02SAndroid Build Coastguard Worker }
60*14675a02SAndroid Build Coastguard Worker }
61*14675a02SAndroid Build Coastguard Worker
value() const62*14675a02SAndroid Build Coastguard Worker int value() const { return local_value_; }
63*14675a02SAndroid Build Coastguard Worker
64*14675a02SAndroid Build Coastguard Worker private:
UpdateValue(int value)65*14675a02SAndroid Build Coastguard Worker void UpdateValue(int value) {
66*14675a02SAndroid Build Coastguard Worker local_value_ = value;
67*14675a02SAndroid Build Coastguard Worker if (box_) {
68*14675a02SAndroid Build Coastguard Worker box_->destructed = false;
69*14675a02SAndroid Build Coastguard Worker box_->value = value;
70*14675a02SAndroid Build Coastguard Worker }
71*14675a02SAndroid Build Coastguard Worker }
72*14675a02SAndroid Build Coastguard Worker
73*14675a02SAndroid Build Coastguard Worker int local_value_;
74*14675a02SAndroid Build Coastguard Worker ValueBox* box_;
75*14675a02SAndroid Build Coastguard Worker };
76*14675a02SAndroid Build Coastguard Worker
TEST(UniqueValueTest,MoveToInnerScope)77*14675a02SAndroid Build Coastguard Worker TEST(UniqueValueTest, MoveToInnerScope) {
78*14675a02SAndroid Build Coastguard Worker ValueBox box_a{};
79*14675a02SAndroid Build Coastguard Worker ValueBox box_b{};
80*14675a02SAndroid Build Coastguard Worker
81*14675a02SAndroid Build Coastguard Worker {
82*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> a = MakeUniqueValue<TracedValue>(123);
83*14675a02SAndroid Build Coastguard Worker a->AttachToBox(&box_a);
84*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
85*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(123));
86*14675a02SAndroid Build Coastguard Worker
87*14675a02SAndroid Build Coastguard Worker {
88*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> b = MakeUniqueValue<TracedValue>(456);
89*14675a02SAndroid Build Coastguard Worker b->AttachToBox(&box_b);
90*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(false));
91*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.value, Eq(456));
92*14675a02SAndroid Build Coastguard Worker
93*14675a02SAndroid Build Coastguard Worker b = std::move(a);
94*14675a02SAndroid Build Coastguard Worker
95*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
96*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(false));
97*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.value, Eq(123));
98*14675a02SAndroid Build Coastguard Worker }
99*14675a02SAndroid Build Coastguard Worker
100*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
101*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(true));
102*14675a02SAndroid Build Coastguard Worker }
103*14675a02SAndroid Build Coastguard Worker }
104*14675a02SAndroid Build Coastguard Worker
TEST(UniqueValueTest,MoveToOuterScope)105*14675a02SAndroid Build Coastguard Worker TEST(UniqueValueTest, MoveToOuterScope) {
106*14675a02SAndroid Build Coastguard Worker ValueBox box_a{};
107*14675a02SAndroid Build Coastguard Worker ValueBox box_b{};
108*14675a02SAndroid Build Coastguard Worker
109*14675a02SAndroid Build Coastguard Worker {
110*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> a = MakeUniqueValue<TracedValue>(123);
111*14675a02SAndroid Build Coastguard Worker a->AttachToBox(&box_a);
112*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
113*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(123));
114*14675a02SAndroid Build Coastguard Worker
115*14675a02SAndroid Build Coastguard Worker {
116*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> b = MakeUniqueValue<TracedValue>(456);
117*14675a02SAndroid Build Coastguard Worker b->AttachToBox(&box_b);
118*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(false));
119*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.value, Eq(456));
120*14675a02SAndroid Build Coastguard Worker
121*14675a02SAndroid Build Coastguard Worker a = std::move(b);
122*14675a02SAndroid Build Coastguard Worker
123*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
124*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(456));
125*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(true));
126*14675a02SAndroid Build Coastguard Worker }
127*14675a02SAndroid Build Coastguard Worker
128*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
129*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(456));
130*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(true));
131*14675a02SAndroid Build Coastguard Worker }
132*14675a02SAndroid Build Coastguard Worker
133*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
134*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(true));
135*14675a02SAndroid Build Coastguard Worker }
136*14675a02SAndroid Build Coastguard Worker
TEST(UniqueValueTest,Emplace)137*14675a02SAndroid Build Coastguard Worker TEST(UniqueValueTest, Emplace) {
138*14675a02SAndroid Build Coastguard Worker ValueBox box_a{};
139*14675a02SAndroid Build Coastguard Worker ValueBox box_b{};
140*14675a02SAndroid Build Coastguard Worker {
141*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> v{std::nullopt};
142*14675a02SAndroid Build Coastguard Worker v.Emplace(123);
143*14675a02SAndroid Build Coastguard Worker v->AttachToBox(&box_a);
144*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
145*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(123));
146*14675a02SAndroid Build Coastguard Worker v.Emplace(321);
147*14675a02SAndroid Build Coastguard Worker v->AttachToBox(&box_b);
148*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
149*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.destructed, Eq(false));
150*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_b.value, Eq(321));
151*14675a02SAndroid Build Coastguard Worker }
152*14675a02SAndroid Build Coastguard Worker }
153*14675a02SAndroid Build Coastguard Worker
TEST(UniqueValueTest,Reset)154*14675a02SAndroid Build Coastguard Worker TEST(UniqueValueTest, Reset) {
155*14675a02SAndroid Build Coastguard Worker ValueBox box_a{};
156*14675a02SAndroid Build Coastguard Worker UniqueValue<TracedValue> v = MakeUniqueValue<TracedValue>(123);
157*14675a02SAndroid Build Coastguard Worker v.Emplace(123);
158*14675a02SAndroid Build Coastguard Worker v->AttachToBox(&box_a);
159*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(false));
160*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.value, Eq(123));
161*14675a02SAndroid Build Coastguard Worker v.Reset();
162*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
163*14675a02SAndroid Build Coastguard Worker v.Reset();
164*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(box_a.destructed, Eq(true));
165*14675a02SAndroid Build Coastguard Worker }
166*14675a02SAndroid Build Coastguard Worker
167*14675a02SAndroid Build Coastguard Worker } // namespace fcp
168