1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cstring>
18
19 #include "gtest/gtest.h"
20
21 #include "chre/util/unique_ptr.h"
22
23 using chre::MakeUnique;
24 using chre::MakeUniqueArray;
25 using chre::MakeUniqueZeroFill;
26 using chre::UniquePtr;
27 using chre::util::internal::is_unbounded_array_v;
28
29 struct Value {
ValueValue30 Value(int value) : value(value) {
31 constructionCounter++;
32 }
33
~ValueValue34 ~Value() {
35 constructionCounter--;
36 }
37
operator =Value38 Value &operator=(Value &&other) {
39 value = other.value;
40 return *this;
41 }
42
43 int value;
44 static int constructionCounter;
45 };
46
47 int Value::constructionCounter = 0;
48
TEST(UniquePtr,NullInit)49 TEST(UniquePtr, NullInit) {
50 // Put something on the stack to help catch uninitialized memory errors
51 {
52 UniquePtr<int> p1 = MakeUnique<int>();
53 // Verify that the typical null checks are implemented correctly
54 ASSERT_FALSE(p1.isNull());
55 EXPECT_TRUE(p1);
56 EXPECT_NE(p1, nullptr);
57 }
58 {
59 UniquePtr<int> p1;
60 EXPECT_FALSE(p1);
61 EXPECT_TRUE(p1.isNull());
62 EXPECT_EQ(p1, nullptr);
63 }
64 UniquePtr<int> p2(nullptr);
65 EXPECT_TRUE(p2.isNull());
66 }
67
TEST(UniquePtr,Construct)68 TEST(UniquePtr, Construct) {
69 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
70 ASSERT_TRUE(myInt);
71 EXPECT_EQ(myInt.get()->value, 0xcafe);
72 EXPECT_EQ(myInt->value, 0xcafe);
73 EXPECT_EQ((*myInt).value, 0xcafe);
74
75 int *realInt = chre::memoryAlloc<int>();
76 ASSERT_NE(realInt, nullptr);
77 UniquePtr<int> wrapped(realInt);
78 ASSERT_TRUE(realInt);
79 }
80
81 struct BigArray {
82 int x[2048];
83 };
84
85 // Check the is_unbounded_array_v backport used in memoryAllocArray to help
86 // constrain usage of MakeUniqueArray to only the proper type category
87 static_assert(is_unbounded_array_v<int> == false &&
88 is_unbounded_array_v<char[2]> == false &&
89 is_unbounded_array_v<char[]> == true,
90 "is_unbounded_array_v implemented incorrectly");
91
TEST(UniquePtr,MakeUniqueArray)92 TEST(UniquePtr, MakeUniqueArray) {
93 // For these tests, we are just allocating and writing to the array - the main
94 // thing we are looking for is that the allocation is of an appropriate size,
95 // which should be checked when running this test with sanitizers enabled
96 {
97 constexpr size_t kSize = 32;
98 UniquePtr<char[]> ptr = MakeUniqueArray<char[]>(kSize);
99 ASSERT_FALSE(ptr.isNull());
100 std::memset(ptr.get(), 0x98, kSize);
101 ptr[0] = 0x11;
102 EXPECT_EQ(*ptr.get(), 0x11);
103 }
104 {
105 constexpr size_t kSize = 4;
106 auto ptr = MakeUniqueArray<BigArray[]>(kSize);
107 ASSERT_FALSE(ptr.isNull());
108 std::memset(ptr.get(), 0x37, sizeof(BigArray) * kSize);
109 }
110 }
111
TEST(UniquePtr,MakeUniqueZeroFill)112 TEST(UniquePtr, MakeUniqueZeroFill) {
113 BigArray baseline = {};
114 auto myArray = MakeUniqueZeroFill<BigArray>();
115 ASSERT_FALSE(myArray.isNull());
116 // Note that this doesn't actually test things properly, because we don't
117 // guarantee that malloc is not already giving us zeroed out memory. To
118 // properly do it, we could inject the allocator, but this function is simple
119 // enough that it's not really worth the effort.
120 EXPECT_EQ(std::memcmp(&baseline, myArray.get(), sizeof(baseline)), 0);
121 }
122
TEST(UniquePtr,MoveConstruct)123 TEST(UniquePtr, MoveConstruct) {
124 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
125 ASSERT_FALSE(myInt.isNull());
126 Value *value = myInt.get();
127
128 UniquePtr<Value> moved(std::move(myInt));
129 EXPECT_EQ(moved.get(), value);
130 EXPECT_EQ(myInt.get(), nullptr);
131 }
132
TEST(UniquePtr,Move)133 TEST(UniquePtr, Move) {
134 Value::constructionCounter = 0;
135
136 {
137 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
138 ASSERT_FALSE(myInt.isNull());
139 EXPECT_EQ(Value::constructionCounter, 1);
140
141 UniquePtr<Value> myMovedInt = MakeUnique<Value>(0);
142 ASSERT_FALSE(myMovedInt.isNull());
143 EXPECT_EQ(Value::constructionCounter, 2);
144 myMovedInt = std::move(myInt);
145 ASSERT_FALSE(myMovedInt.isNull());
146 ASSERT_TRUE(myInt.isNull());
147 EXPECT_EQ(myMovedInt.get()->value, 0xcafe);
148 }
149
150 EXPECT_EQ(Value::constructionCounter, 0);
151 }
152
TEST(UniquePtr,Release)153 TEST(UniquePtr, Release) {
154 Value::constructionCounter = 0;
155
156 Value *value1, *value2;
157 {
158 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
159 ASSERT_FALSE(myInt.isNull());
160 EXPECT_EQ(Value::constructionCounter, 1);
161 value1 = myInt.get();
162 EXPECT_NE(value1, nullptr);
163 value2 = myInt.release();
164 EXPECT_EQ(value1, value2);
165 EXPECT_EQ(myInt.get(), nullptr);
166 EXPECT_TRUE(myInt.isNull());
167 }
168
169 EXPECT_EQ(Value::constructionCounter, 1);
170 EXPECT_EQ(value2->value, 0xcafe);
171 value2->~Value();
172 chre::memoryFree(value2);
173 }
174
TEST(UniquePtr,Reset)175 TEST(UniquePtr, Reset) {
176 Value::constructionCounter = 0;
177
178 {
179 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
180 EXPECT_EQ(myInt.get()->value, 0xcafe);
181 EXPECT_EQ(Value::constructionCounter, 1);
182 myInt.reset(nullptr);
183 EXPECT_EQ(myInt.get(), nullptr);
184 EXPECT_EQ(Value::constructionCounter, 0);
185
186 myInt = MakeUnique<Value>(0xcafe);
187 UniquePtr<Value> myInt2 = MakeUnique<Value>(0xface);
188 EXPECT_EQ(Value::constructionCounter, 2);
189 myInt.reset(myInt2.release());
190 EXPECT_EQ(Value::constructionCounter, 1);
191 EXPECT_EQ(myInt.get()->value, 0xface);
192 EXPECT_EQ(myInt2.get(), nullptr);
193
194 myInt.reset();
195 EXPECT_EQ(myInt.get(), nullptr);
196 }
197
198 EXPECT_EQ(Value::constructionCounter, 0);
199 }
200
TEST(UniquePtr,EqualityOperator)201 TEST(UniquePtr, EqualityOperator) {
202 Value::constructionCounter = 0;
203
204 {
205 UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe);
206 EXPECT_TRUE(myInt != nullptr);
207
208 myInt.reset();
209 EXPECT_TRUE(myInt == nullptr);
210 }
211
212 EXPECT_EQ(Value::constructionCounter, 0);
213 }
214
TEST(UniquePtr,OverAlignedTest)215 TEST(UniquePtr, OverAlignedTest) {
216 // Explicitly overaligned structure larger than std::max_align_t.
217 struct alignas(32) OverAlignedStruct {
218 uint32_t x[32];
219 };
220 static_assert(alignof(OverAlignedStruct) > alignof(std::max_align_t));
221
222 UniquePtr<OverAlignedStruct> ptr = MakeUnique<OverAlignedStruct>();
223 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr.get()) % alignof(OverAlignedStruct),
224 0);
225 }
226