1 
2 /*
3  * Copyright (C) 2016 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "gtest/gtest.h"
19 
20 #include "chre/util/non_copyable.h"
21 #include "chre/util/optional.h"
22 
23 using chre::Optional;
24 
25 class DestructorTestingObject {
26  public:
~DestructorTestingObject()27   ~DestructorTestingObject() {
28     if (valueToFlipWhenDestruct != nullptr) {
29       *valueToFlipWhenDestruct = !*valueToFlipWhenDestruct;
30     }
31   }
32 
setValueToFlipWhenDestruct(bool * value)33   void setValueToFlipWhenDestruct(bool *value) {
34     valueToFlipWhenDestruct = value;
35   }
36 
37  private:
38   bool *valueToFlipWhenDestruct = nullptr;
39 };
40 
TEST(Optional,ShouldDestructContainedObject)41 TEST(Optional, ShouldDestructContainedObject) {
42   bool destructed = false;
43   {
44     Optional<DestructorTestingObject> object(DestructorTestingObject{});
45     object.value().setValueToFlipWhenDestruct(&destructed);
46   }
47   EXPECT_TRUE(destructed);
48 }
49 
TEST(Optional,NoValueByDefault)50 TEST(Optional, NoValueByDefault) {
51   Optional<int> myInt;
52   EXPECT_FALSE(myInt.has_value());
53 }
54 
TEST(Optional,NonDefaultValueByDefault)55 TEST(Optional, NonDefaultValueByDefault) {
56   Optional<int> myInt(0x1337);
57   EXPECT_TRUE(myInt.has_value());
58   EXPECT_EQ(*myInt, 0x1337);
59 }
60 
TEST(Optional,NonDefaultMovedValueByDefault)61 TEST(Optional, NonDefaultMovedValueByDefault) {
62   Optional<int> myInt(std::move(0x1337));
63   EXPECT_TRUE(myInt.has_value());
64   EXPECT_EQ(*myInt, 0x1337);
65 }
66 
TEST(Optional,CopyConstruct)67 TEST(Optional, CopyConstruct) {
68   Optional<int> myInt(0x1337);
69   Optional<int> myNewInt(myInt);
70   EXPECT_TRUE(myNewInt.has_value());
71   EXPECT_EQ(*myNewInt, 0x1337);
72 }
73 
TEST(Optional,CopyConstructConst)74 TEST(Optional, CopyConstructConst) {
75   const Optional<int> myInt(0x1337);
76   Optional<int> myNewInt(myInt);
77   EXPECT_TRUE(myNewInt.has_value());
78   EXPECT_EQ(*myNewInt, 0x1337);
79 }
80 
TEST(Optional,CopyAssignAndRead)81 TEST(Optional, CopyAssignAndRead) {
82   Optional<int> myInt;
83   EXPECT_FALSE(myInt.has_value());
84   myInt = 0x1337;
85   EXPECT_EQ(*myInt, 0x1337);
86   EXPECT_TRUE(myInt.has_value());
87   myInt.reset();
88   EXPECT_FALSE(myInt.has_value());
89 }
90 
TEST(Optional,MoveAssignAndRead)91 TEST(Optional, MoveAssignAndRead) {
92   Optional<int> myInt;
93   EXPECT_FALSE(myInt.has_value());
94   myInt = std::move(0xcafe);
95   EXPECT_TRUE(myInt.has_value());
96   EXPECT_EQ(*myInt, 0xcafe);
97 }
98 
TEST(Optional,OptionalMoveAssignAndRead)99 TEST(Optional, OptionalMoveAssignAndRead) {
100   Optional<int> myInt(0x1337);
101   Optional<int> myMovedInt;
102   EXPECT_FALSE(myMovedInt.has_value());
103   myMovedInt = std::move(myInt);
104   EXPECT_TRUE(myInt.has_value());
105   EXPECT_TRUE(myMovedInt.has_value());
106   EXPECT_EQ(*myMovedInt, 0x1337);
107 }
108 
TEST(Optional,OptionalCopyAssignAndRead)109 TEST(Optional, OptionalCopyAssignAndRead) {
110   Optional<int> myInt(0x1337);
111   Optional<int> myCopiedInt;
112   EXPECT_FALSE(myCopiedInt.has_value());
113   myCopiedInt = myInt;
114   EXPECT_TRUE(myInt.has_value());
115   EXPECT_TRUE(myCopiedInt.has_value());
116   EXPECT_EQ(*myInt, 0x1337);
117   EXPECT_EQ(*myCopiedInt, 0x1337);
118 }
119 
120 static constexpr int kInvalidValue = -1;
121 
122 class MovableButNonCopyable : public chre::NonCopyable {
123  public:
124   MovableButNonCopyable() = default;
MovableButNonCopyable(int value)125   MovableButNonCopyable(int value) : mValue(value) {}
MovableButNonCopyable(MovableButNonCopyable && other)126   MovableButNonCopyable(MovableButNonCopyable&& other) {
127     mValue = other.mValue;
128     other.mValue = kInvalidValue;
129   }
130 
operator =(MovableButNonCopyable && other)131   MovableButNonCopyable& operator=(MovableButNonCopyable&& other) {
132     assert(mMagic == kConstructedMagic);
133     mValue = other.mValue;
134     other.mValue = kInvalidValue;
135     return *this;
136   }
137 
~MovableButNonCopyable()138   ~MovableButNonCopyable() {
139     mMagic = kUninitializedMagic;
140     mValue = kUninitializedMagic;
141   }
142 
getValue() const143   int getValue() const {
144     return mValue;
145   }
146 
147  private:
148   static constexpr int kConstructedMagic = 0xfeedc0fe;
149   static constexpr int kUninitializedMagic = 0xdeadbeef;
150 
151   int mMagic = kConstructedMagic;
152   int mValue = kInvalidValue;
153 };
154 
TEST(Optional,UninitializedAssignment)155 TEST(Optional, UninitializedAssignment) {
156   constexpr int kValue1 = 0xd00d;
157   constexpr int kValue2 = 0xcafe;
158   MovableButNonCopyable transferee1(kValue1);
159   MovableButNonCopyable transferee2(kValue2);
160 
161   Optional<MovableButNonCopyable> container;
162   EXPECT_FALSE(container.has_value());
163 
164   container = std::move(transferee1);
165   EXPECT_TRUE(container.has_value());
166   EXPECT_EQ(container->getValue(), kValue1);
167   EXPECT_EQ(transferee1.getValue(), kInvalidValue);
168 
169   container.reset();
170   EXPECT_FALSE(container.has_value());
171 
172   container = std::move(transferee2);
173   EXPECT_TRUE(container.has_value());
174   EXPECT_EQ(container->getValue(), kValue2);
175   EXPECT_EQ(transferee2.getValue(), kInvalidValue);
176 }
177 
178 // TODO: should add some tests to cover the possible assignment outcomes between
179 // two Optional instances (e.g. assign one w/o value to one w/value, etc)
180