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 <cassert>
21 
22 #include "chre/util/non_copyable.h"
23 #include "chre/util/optional.h"
24 
25 using chre::Optional;
26 
27 class DestructorTestingObject {
28  public:
~DestructorTestingObject()29   ~DestructorTestingObject() {
30     if (valueToFlipWhenDestruct != nullptr) {
31       *valueToFlipWhenDestruct = !*valueToFlipWhenDestruct;
32     }
33   }
34 
setValueToFlipWhenDestruct(bool * value)35   void setValueToFlipWhenDestruct(bool *value) {
36     valueToFlipWhenDestruct = value;
37   }
38 
39  private:
40   bool *valueToFlipWhenDestruct = nullptr;
41 };
42 
TEST(Optional,ShouldDestructContainedObject)43 TEST(Optional, ShouldDestructContainedObject) {
44   bool destructed = false;
45   {
46     Optional<DestructorTestingObject> object(DestructorTestingObject{});
47     object.value().setValueToFlipWhenDestruct(&destructed);
48   }
49   EXPECT_TRUE(destructed);
50 }
51 
TEST(Optional,NoValueByDefault)52 TEST(Optional, NoValueByDefault) {
53   Optional<int> myInt;
54   EXPECT_FALSE(myInt.has_value());
55 }
56 
TEST(Optional,NonDefaultValueByDefault)57 TEST(Optional, NonDefaultValueByDefault) {
58   Optional<int> myInt(0x1337);
59   EXPECT_TRUE(myInt.has_value());
60   EXPECT_EQ(*myInt, 0x1337);
61 }
62 
TEST(Optional,NonDefaultMovedValueByDefault)63 TEST(Optional, NonDefaultMovedValueByDefault) {
64   Optional<int> myInt(std::move(0x1337));
65   EXPECT_TRUE(myInt.has_value());
66   EXPECT_EQ(*myInt, 0x1337);
67 }
68 
TEST(Optional,CopyConstruct)69 TEST(Optional, CopyConstruct) {
70   Optional<int> myInt(0x1337);
71   Optional<int> myNewInt(myInt);
72   EXPECT_TRUE(myNewInt.has_value());
73   EXPECT_EQ(*myNewInt, 0x1337);
74 }
75 
TEST(Optional,CopyConstructConst)76 TEST(Optional, CopyConstructConst) {
77   const Optional<int> myInt(0x1337);
78   Optional<int> myNewInt(myInt);
79   EXPECT_TRUE(myNewInt.has_value());
80   EXPECT_EQ(*myNewInt, 0x1337);
81 }
82 
TEST(Optional,CopyAssignAndRead)83 TEST(Optional, CopyAssignAndRead) {
84   Optional<int> myInt;
85   EXPECT_FALSE(myInt.has_value());
86   myInt = 0x1337;
87   EXPECT_EQ(*myInt, 0x1337);
88   EXPECT_TRUE(myInt.has_value());
89   myInt.reset();
90   EXPECT_FALSE(myInt.has_value());
91 }
92 
TEST(Optional,MoveAssignAndRead)93 TEST(Optional, MoveAssignAndRead) {
94   Optional<int> myInt;
95   EXPECT_FALSE(myInt.has_value());
96   myInt = std::move(0xcafe);
97   EXPECT_TRUE(myInt.has_value());
98   EXPECT_EQ(*myInt, 0xcafe);
99 }
100 
TEST(Optional,OptionalMoveAssignAndRead)101 TEST(Optional, OptionalMoveAssignAndRead) {
102   Optional<int> myInt(0x1337);
103   Optional<int> myMovedInt;
104   EXPECT_FALSE(myMovedInt.has_value());
105   myMovedInt = std::move(myInt);
106   EXPECT_TRUE(myInt.has_value());
107   EXPECT_TRUE(myMovedInt.has_value());
108   EXPECT_EQ(*myMovedInt, 0x1337);
109 }
110 
TEST(Optional,OptionalCopyAssignAndRead)111 TEST(Optional, OptionalCopyAssignAndRead) {
112   Optional<int> myInt(0x1337);
113   Optional<int> myCopiedInt;
114   EXPECT_FALSE(myCopiedInt.has_value());
115   myCopiedInt = myInt;
116   EXPECT_TRUE(myInt.has_value());
117   EXPECT_TRUE(myCopiedInt.has_value());
118   EXPECT_EQ(*myInt, 0x1337);
119   EXPECT_EQ(*myCopiedInt, 0x1337);
120 }
121 
122 static constexpr int kInvalidValue = -1;
123 
124 class MovableButNonCopyable : public chre::NonCopyable {
125  public:
126   MovableButNonCopyable() = default;
MovableButNonCopyable(int value)127   MovableButNonCopyable(int value) : mValue(value) {}
MovableButNonCopyable(MovableButNonCopyable && other)128   MovableButNonCopyable(MovableButNonCopyable &&other) {
129     mValue = other.mValue;
130     other.mValue = kInvalidValue;
131   }
132 
operator =(MovableButNonCopyable && other)133   MovableButNonCopyable &operator=(MovableButNonCopyable &&other) {
134     assert(mMagic == kConstructedMagic);
135     mValue = other.mValue;
136     other.mValue = kInvalidValue;
137     return *this;
138   }
139 
~MovableButNonCopyable()140   ~MovableButNonCopyable() {
141     mMagic = kUninitializedMagic;
142     mValue = kUninitializedMagic;
143   }
144 
getValue() const145   int getValue() const {
146     return mValue;
147   }
148 
149  private:
150   static constexpr int kConstructedMagic = 0xfeedc0fe;
151   static constexpr int kUninitializedMagic = 0xdeadbeef;
152 
153   int mMagic = kConstructedMagic;
154   int mValue = kInvalidValue;
155 };
156 
TEST(Optional,UninitializedAssignment)157 TEST(Optional, UninitializedAssignment) {
158   constexpr int kValue1 = 0xd00d;
159   constexpr int kValue2 = 0xcafe;
160   MovableButNonCopyable transferee1(kValue1);
161   MovableButNonCopyable transferee2(kValue2);
162 
163   Optional<MovableButNonCopyable> container;
164   EXPECT_FALSE(container.has_value());
165 
166   container = std::move(transferee1);
167   EXPECT_TRUE(container.has_value());
168   EXPECT_EQ(container->getValue(), kValue1);
169   EXPECT_EQ(transferee1.getValue(), kInvalidValue);
170 
171   container.reset();
172   EXPECT_FALSE(container.has_value());
173 
174   container = std::move(transferee2);
175   EXPECT_TRUE(container.has_value());
176   EXPECT_EQ(container->getValue(), kValue2);
177   EXPECT_EQ(transferee2.getValue(), kInvalidValue);
178 }
179 
180 // TODO: should add some tests to cover the possible assignment outcomes between
181 // two Optional instances (e.g. assign one w/o value to one w/value, etc)
182