xref: /aosp_15_r20/system/chre/util/tests/unique_ptr_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
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