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: 27 ~DestructorTestingObject() { 28 if (valueToFlipWhenDestruct != nullptr) { 29 *valueToFlipWhenDestruct = !*valueToFlipWhenDestruct; 30 } 31 } 32 33 void setValueToFlipWhenDestruct(bool *value) { 34 valueToFlipWhenDestruct = value; 35 } 36 37 private: 38 bool *valueToFlipWhenDestruct = nullptr; 39 }; 40 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 50 TEST(Optional, NoValueByDefault) { 51 Optional<int> myInt; 52 EXPECT_FALSE(myInt.has_value()); 53 } 54 55 TEST(Optional, NonDefaultValueByDefault) { 56 Optional<int> myInt(0x1337); 57 EXPECT_TRUE(myInt.has_value()); 58 EXPECT_EQ(*myInt, 0x1337); 59 } 60 61 TEST(Optional, NonDefaultMovedValueByDefault) { 62 Optional<int> myInt(std::move(0x1337)); 63 EXPECT_TRUE(myInt.has_value()); 64 EXPECT_EQ(*myInt, 0x1337); 65 } 66 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 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 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 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 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 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; 125 MovableButNonCopyable(int value) : mValue(value) {} 126 MovableButNonCopyable(MovableButNonCopyable &&other) { 127 mValue = other.mValue; 128 other.mValue = kInvalidValue; 129 } 130 131 MovableButNonCopyable &operator=(MovableButNonCopyable &&other) { 132 assert(mMagic == kConstructedMagic); 133 mValue = other.mValue; 134 other.mValue = kInvalidValue; 135 return *this; 136 } 137 138 ~MovableButNonCopyable() { 139 mMagic = kUninitializedMagic; 140 mValue = kUninitializedMagic; 141 } 142 143 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 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