xref: /aosp_15_r20/external/libgav1/tests/utils_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2020 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include "tests/utils.h"
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #include <cstddef>
18*09537850SAkhilesh Sanikop #include <cstdint>
19*09537850SAkhilesh Sanikop #include <memory>
20*09537850SAkhilesh Sanikop #include <new>
21*09537850SAkhilesh Sanikop 
22*09537850SAkhilesh Sanikop #include "absl/base/config.h"
23*09537850SAkhilesh Sanikop #include "gtest/gtest.h"
24*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
25*09537850SAkhilesh Sanikop 
26*09537850SAkhilesh Sanikop #ifdef ABSL_HAVE_EXCEPTIONS
27*09537850SAkhilesh Sanikop #include <exception>
28*09537850SAkhilesh Sanikop #endif
29*09537850SAkhilesh Sanikop 
30*09537850SAkhilesh Sanikop namespace libgav1 {
31*09537850SAkhilesh Sanikop namespace test_utils {
32*09537850SAkhilesh Sanikop namespace {
33*09537850SAkhilesh Sanikop 
34*09537850SAkhilesh Sanikop constexpr size_t kMaxAllocableSize = 0x40000000;
35*09537850SAkhilesh Sanikop 
36*09537850SAkhilesh Sanikop // Has a trivial default constructor that performs no action.
37*09537850SAkhilesh Sanikop struct SmallMaxAligned : public MaxAlignedAllocable {
38*09537850SAkhilesh Sanikop   alignas(kMaxAlignment) uint8_t x;
39*09537850SAkhilesh Sanikop };
40*09537850SAkhilesh Sanikop 
41*09537850SAkhilesh Sanikop // Has a nontrivial default constructor that initializes the data member.
42*09537850SAkhilesh Sanikop struct SmallMaxAlignedNontrivialConstructor : public MaxAlignedAllocable {
43*09537850SAkhilesh Sanikop   alignas(kMaxAlignment) uint8_t x = 0;
44*09537850SAkhilesh Sanikop };
45*09537850SAkhilesh Sanikop 
46*09537850SAkhilesh Sanikop // Has a trivial default constructor that performs no action.
47*09537850SAkhilesh Sanikop struct HugeMaxAligned : public MaxAlignedAllocable {
48*09537850SAkhilesh Sanikop   alignas(kMaxAlignment) uint8_t x[kMaxAllocableSize + 1];
49*09537850SAkhilesh Sanikop };
50*09537850SAkhilesh Sanikop 
51*09537850SAkhilesh Sanikop // Has a nontrivial default constructor that initializes the data member.
52*09537850SAkhilesh Sanikop struct HugeMaxAlignedNontrivialConstructor : public MaxAlignedAllocable {
53*09537850SAkhilesh Sanikop   alignas(kMaxAlignment) uint8_t x[kMaxAllocableSize + 1] = {};
54*09537850SAkhilesh Sanikop };
55*09537850SAkhilesh Sanikop 
56*09537850SAkhilesh Sanikop #ifdef ABSL_HAVE_EXCEPTIONS
57*09537850SAkhilesh Sanikop struct MaxAlignedThrowingConstructor : public MaxAlignedAllocable {
MaxAlignedThrowingConstructorlibgav1::test_utils::__anon81aa64620111::MaxAlignedThrowingConstructor58*09537850SAkhilesh Sanikop   MaxAlignedThrowingConstructor() { throw std::exception(); }
59*09537850SAkhilesh Sanikop 
60*09537850SAkhilesh Sanikop   uint8_t x;
61*09537850SAkhilesh Sanikop };
62*09537850SAkhilesh Sanikop #endif
63*09537850SAkhilesh Sanikop 
TEST(TestUtilsTest,TestMaxAlignedAllocable)64*09537850SAkhilesh Sanikop TEST(TestUtilsTest, TestMaxAlignedAllocable) {
65*09537850SAkhilesh Sanikop   {
66*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new (std::nothrow) is called.
67*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAligned> small(new (std::nothrow) SmallMaxAligned);
68*09537850SAkhilesh Sanikop     EXPECT_NE(small, nullptr);
69*09537850SAkhilesh Sanikop     // Note this check doesn't guarantee conformance as a suitably aligned
70*09537850SAkhilesh Sanikop     // address may be returned from any allocator.
71*09537850SAkhilesh Sanikop     EXPECT_EQ(reinterpret_cast<uintptr_t>(small.get()) & (kMaxAlignment - 1),
72*09537850SAkhilesh Sanikop               0);
73*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete is called.
74*09537850SAkhilesh Sanikop   }
75*09537850SAkhilesh Sanikop 
76*09537850SAkhilesh Sanikop   {
77*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new is called.
78*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAligned> small(new SmallMaxAligned);
79*09537850SAkhilesh Sanikop     EXPECT_NE(small, nullptr);
80*09537850SAkhilesh Sanikop     // Note this check doesn't guarantee conformance as a suitably aligned
81*09537850SAkhilesh Sanikop     // address may be returned from any allocator.
82*09537850SAkhilesh Sanikop     EXPECT_EQ(reinterpret_cast<uintptr_t>(small.get()) & (kMaxAlignment - 1),
83*09537850SAkhilesh Sanikop               0);
84*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete is called.
85*09537850SAkhilesh Sanikop   }
86*09537850SAkhilesh Sanikop 
87*09537850SAkhilesh Sanikop   {
88*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] (std::nothrow) is called.
89*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAligned[]> small_array_of_smalls(
90*09537850SAkhilesh Sanikop         new (std::nothrow) SmallMaxAligned[10]);
91*09537850SAkhilesh Sanikop     EXPECT_NE(small_array_of_smalls, nullptr);
92*09537850SAkhilesh Sanikop     EXPECT_EQ(reinterpret_cast<uintptr_t>(small_array_of_smalls.get()) &
93*09537850SAkhilesh Sanikop                   (kMaxAlignment - 1),
94*09537850SAkhilesh Sanikop               0);
95*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete[] is called.
96*09537850SAkhilesh Sanikop   }
97*09537850SAkhilesh Sanikop 
98*09537850SAkhilesh Sanikop   {
99*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] is called.
100*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAligned[]> small_array_of_smalls(
101*09537850SAkhilesh Sanikop         new SmallMaxAligned[10]);
102*09537850SAkhilesh Sanikop     EXPECT_NE(small_array_of_smalls, nullptr);
103*09537850SAkhilesh Sanikop     EXPECT_EQ(reinterpret_cast<uintptr_t>(small_array_of_smalls.get()) &
104*09537850SAkhilesh Sanikop                   (kMaxAlignment - 1),
105*09537850SAkhilesh Sanikop               0);
106*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete[] is called.
107*09537850SAkhilesh Sanikop   }
108*09537850SAkhilesh Sanikop 
109*09537850SAkhilesh Sanikop   {
110*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new (std::nothrow) is called.
111*09537850SAkhilesh Sanikop     std::unique_ptr<HugeMaxAligned> huge(new (std::nothrow) HugeMaxAligned);
112*09537850SAkhilesh Sanikop     EXPECT_EQ(huge, nullptr);
113*09537850SAkhilesh Sanikop   }
114*09537850SAkhilesh Sanikop 
115*09537850SAkhilesh Sanikop   {
116*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] (std::nothrow) is called.
117*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAligned[]> huge_array_of_smalls(
118*09537850SAkhilesh Sanikop         new (std::nothrow)
119*09537850SAkhilesh Sanikop             SmallMaxAligned[kMaxAllocableSize / sizeof(SmallMaxAligned) + 1]);
120*09537850SAkhilesh Sanikop     EXPECT_EQ(huge_array_of_smalls, nullptr);
121*09537850SAkhilesh Sanikop   }
122*09537850SAkhilesh Sanikop 
123*09537850SAkhilesh Sanikop #ifdef ABSL_HAVE_EXCEPTIONS
124*09537850SAkhilesh Sanikop   try {
125*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new (std::nothrow) is called.
126*09537850SAkhilesh Sanikop     // The constructor throws an exception.
127*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete (std::nothrow) is called.
128*09537850SAkhilesh Sanikop     auto* always = new (std::nothrow) MaxAlignedThrowingConstructor;
129*09537850SAkhilesh Sanikop     static_cast<void>(always);
130*09537850SAkhilesh Sanikop   } catch (...) {
131*09537850SAkhilesh Sanikop   }
132*09537850SAkhilesh Sanikop 
133*09537850SAkhilesh Sanikop   try {
134*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new is called.
135*09537850SAkhilesh Sanikop     // The constructor throws an exception.
136*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete is called.
137*09537850SAkhilesh Sanikop     auto* always = new MaxAlignedThrowingConstructor;
138*09537850SAkhilesh Sanikop     static_cast<void>(always);
139*09537850SAkhilesh Sanikop   } catch (...) {
140*09537850SAkhilesh Sanikop   }
141*09537850SAkhilesh Sanikop 
142*09537850SAkhilesh Sanikop   try {
143*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] (std::nothrow) is called.
144*09537850SAkhilesh Sanikop     // The constructor throws an exception.
145*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete[] (std::nothrow) is called.
146*09537850SAkhilesh Sanikop     auto* always = new (std::nothrow) MaxAlignedThrowingConstructor[2];
147*09537850SAkhilesh Sanikop     static_cast<void>(always);
148*09537850SAkhilesh Sanikop   } catch (...) {
149*09537850SAkhilesh Sanikop   }
150*09537850SAkhilesh Sanikop 
151*09537850SAkhilesh Sanikop   try {
152*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] is called.
153*09537850SAkhilesh Sanikop     // The constructor throws an exception.
154*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator delete[] is called.
155*09537850SAkhilesh Sanikop     auto* always = new MaxAlignedThrowingConstructor[2];
156*09537850SAkhilesh Sanikop     static_cast<void>(always);
157*09537850SAkhilesh Sanikop   } catch (...) {
158*09537850SAkhilesh Sanikop   }
159*09537850SAkhilesh Sanikop 
160*09537850SAkhilesh Sanikop   // Note these calls are only safe with exceptions enabled as if the throwing
161*09537850SAkhilesh Sanikop   // operator new returns the object is expected to be valid. In this case an
162*09537850SAkhilesh Sanikop   // attempt to invoke the object's constructor on a nullptr may be made which
163*09537850SAkhilesh Sanikop   // is undefined behavior.
164*09537850SAkhilesh Sanikop   try {
165*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new is called.
166*09537850SAkhilesh Sanikop     std::unique_ptr<HugeMaxAlignedNontrivialConstructor> huge(
167*09537850SAkhilesh Sanikop         new HugeMaxAlignedNontrivialConstructor);
168*09537850SAkhilesh Sanikop     ADD_FAILURE() << "huge allocation should fail.";
169*09537850SAkhilesh Sanikop   } catch (...) {
170*09537850SAkhilesh Sanikop     SUCCEED();
171*09537850SAkhilesh Sanikop   }
172*09537850SAkhilesh Sanikop 
173*09537850SAkhilesh Sanikop   try {
174*09537850SAkhilesh Sanikop     // MaxAlignedAllocable::operator new[] is called.
175*09537850SAkhilesh Sanikop     std::unique_ptr<SmallMaxAlignedNontrivialConstructor[]>
176*09537850SAkhilesh Sanikop         huge_array_of_smalls(
177*09537850SAkhilesh Sanikop             new SmallMaxAlignedNontrivialConstructor
178*09537850SAkhilesh Sanikop                 [kMaxAllocableSize /
179*09537850SAkhilesh Sanikop                      sizeof(SmallMaxAlignedNontrivialConstructor) +
180*09537850SAkhilesh Sanikop                  1]);
181*09537850SAkhilesh Sanikop     ADD_FAILURE() << "huge_array_of_smalls allocation should fail.";
182*09537850SAkhilesh Sanikop   } catch (...) {
183*09537850SAkhilesh Sanikop     SUCCEED();
184*09537850SAkhilesh Sanikop   }
185*09537850SAkhilesh Sanikop #endif  // ABSL_HAVE_EXCEPTIONS
186*09537850SAkhilesh Sanikop }
187*09537850SAkhilesh Sanikop 
188*09537850SAkhilesh Sanikop }  // namespace
189*09537850SAkhilesh Sanikop }  // namespace test_utils
190*09537850SAkhilesh Sanikop }  // namespace libgav1
191