1*09537850SAkhilesh Sanikop // Copyright 2021 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 "src/utils/vector.h"
16*09537850SAkhilesh Sanikop
17*09537850SAkhilesh Sanikop #include <memory>
18*09537850SAkhilesh Sanikop #include <new>
19*09537850SAkhilesh Sanikop #include <utility>
20*09537850SAkhilesh Sanikop
21*09537850SAkhilesh Sanikop #include "gtest/gtest.h"
22*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
23*09537850SAkhilesh Sanikop
24*09537850SAkhilesh Sanikop #if LIBGAV1_MSAN
25*09537850SAkhilesh Sanikop #include <sanitizer/msan_interface.h>
26*09537850SAkhilesh Sanikop #endif
27*09537850SAkhilesh Sanikop
28*09537850SAkhilesh Sanikop namespace libgav1 {
29*09537850SAkhilesh Sanikop namespace {
30*09537850SAkhilesh Sanikop
31*09537850SAkhilesh Sanikop class Foo {
32*09537850SAkhilesh Sanikop public:
33*09537850SAkhilesh Sanikop Foo() = default;
34*09537850SAkhilesh Sanikop
x() const35*09537850SAkhilesh Sanikop int x() const { return x_; }
36*09537850SAkhilesh Sanikop
37*09537850SAkhilesh Sanikop private:
38*09537850SAkhilesh Sanikop int x_ = 38;
39*09537850SAkhilesh Sanikop };
40*09537850SAkhilesh Sanikop
41*09537850SAkhilesh Sanikop class Point {
42*09537850SAkhilesh Sanikop public:
Point(int x,int y)43*09537850SAkhilesh Sanikop Point(int x, int y) : x_(x), y_(y) {}
44*09537850SAkhilesh Sanikop
x() const45*09537850SAkhilesh Sanikop int x() const { return x_; }
y() const46*09537850SAkhilesh Sanikop int y() const { return y_; }
47*09537850SAkhilesh Sanikop
48*09537850SAkhilesh Sanikop private:
49*09537850SAkhilesh Sanikop int x_;
50*09537850SAkhilesh Sanikop int y_;
51*09537850SAkhilesh Sanikop };
52*09537850SAkhilesh Sanikop
TEST(VectorTest,NoCtor)53*09537850SAkhilesh Sanikop TEST(VectorTest, NoCtor) {
54*09537850SAkhilesh Sanikop VectorNoCtor<int> v;
55*09537850SAkhilesh Sanikop EXPECT_TRUE(v.resize(100));
56*09537850SAkhilesh Sanikop Vector<int> w;
57*09537850SAkhilesh Sanikop EXPECT_TRUE(w.resize(100));
58*09537850SAkhilesh Sanikop
59*09537850SAkhilesh Sanikop #if LIBGAV1_MSAN
60*09537850SAkhilesh Sanikop // Use MemorySanitizer to check VectorNoCtor::resize() does not initialize
61*09537850SAkhilesh Sanikop // the memory while Vector::resize() does.
62*09537850SAkhilesh Sanikop //
63*09537850SAkhilesh Sanikop // __msan_test_shadow(const void *x, uptr size) returns the offset of the
64*09537850SAkhilesh Sanikop // first (at least partially) poisoned byte in the range, or -1 if the whole
65*09537850SAkhilesh Sanikop // range is good.
66*09537850SAkhilesh Sanikop for (size_t i = 0; i < 100; ++i) {
67*09537850SAkhilesh Sanikop EXPECT_EQ(__msan_test_shadow(&v[i], sizeof(int)), 0);
68*09537850SAkhilesh Sanikop EXPECT_EQ(__msan_test_shadow(&w[i], sizeof(int)), -1);
69*09537850SAkhilesh Sanikop }
70*09537850SAkhilesh Sanikop #endif
71*09537850SAkhilesh Sanikop }
72*09537850SAkhilesh Sanikop
TEST(VectorTest,Constructor)73*09537850SAkhilesh Sanikop TEST(VectorTest, Constructor) {
74*09537850SAkhilesh Sanikop Vector<Foo> v;
75*09537850SAkhilesh Sanikop EXPECT_TRUE(v.resize(100));
76*09537850SAkhilesh Sanikop for (const Foo& foo : v) {
77*09537850SAkhilesh Sanikop EXPECT_EQ(foo.x(), 38);
78*09537850SAkhilesh Sanikop }
79*09537850SAkhilesh Sanikop }
80*09537850SAkhilesh Sanikop
TEST(VectorTest,PushBack)81*09537850SAkhilesh Sanikop TEST(VectorTest, PushBack) {
82*09537850SAkhilesh Sanikop // Create a vector containing integers
83*09537850SAkhilesh Sanikop Vector<int> v;
84*09537850SAkhilesh Sanikop EXPECT_TRUE(v.reserve(8));
85*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 0);
86*09537850SAkhilesh Sanikop
87*09537850SAkhilesh Sanikop EXPECT_TRUE(v.push_back(25));
88*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 1);
89*09537850SAkhilesh Sanikop EXPECT_EQ(v[0], 25);
90*09537850SAkhilesh Sanikop
91*09537850SAkhilesh Sanikop EXPECT_TRUE(v.push_back(13));
92*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 2);
93*09537850SAkhilesh Sanikop EXPECT_EQ(v[0], 25);
94*09537850SAkhilesh Sanikop EXPECT_EQ(v[1], 13);
95*09537850SAkhilesh Sanikop }
96*09537850SAkhilesh Sanikop
TEST(VectorTest,PushBackUnchecked)97*09537850SAkhilesh Sanikop TEST(VectorTest, PushBackUnchecked) {
98*09537850SAkhilesh Sanikop Vector<std::unique_ptr<Point>> v;
99*09537850SAkhilesh Sanikop EXPECT_TRUE(v.reserve(2));
100*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 0);
101*09537850SAkhilesh Sanikop
102*09537850SAkhilesh Sanikop std::unique_ptr<Point> point(new (std::nothrow) Point(1, 2));
103*09537850SAkhilesh Sanikop EXPECT_NE(point, nullptr);
104*09537850SAkhilesh Sanikop v.push_back_unchecked(std::move(point));
105*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 1);
106*09537850SAkhilesh Sanikop EXPECT_EQ(v[0]->x(), 1);
107*09537850SAkhilesh Sanikop EXPECT_EQ(v[0]->y(), 2);
108*09537850SAkhilesh Sanikop
109*09537850SAkhilesh Sanikop point.reset(new (std::nothrow) Point(3, 4));
110*09537850SAkhilesh Sanikop EXPECT_NE(point, nullptr);
111*09537850SAkhilesh Sanikop v.push_back_unchecked(std::move(point));
112*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 2);
113*09537850SAkhilesh Sanikop EXPECT_EQ(v[0]->x(), 1);
114*09537850SAkhilesh Sanikop EXPECT_EQ(v[0]->y(), 2);
115*09537850SAkhilesh Sanikop EXPECT_EQ(v[1]->x(), 3);
116*09537850SAkhilesh Sanikop EXPECT_EQ(v[1]->y(), 4);
117*09537850SAkhilesh Sanikop }
118*09537850SAkhilesh Sanikop
TEST(VectorTest,EmplaceBack)119*09537850SAkhilesh Sanikop TEST(VectorTest, EmplaceBack) {
120*09537850SAkhilesh Sanikop Vector<Point> v;
121*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 0);
122*09537850SAkhilesh Sanikop
123*09537850SAkhilesh Sanikop EXPECT_TRUE(v.emplace_back(1, 2));
124*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 1);
125*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].x(), 1);
126*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].y(), 2);
127*09537850SAkhilesh Sanikop
128*09537850SAkhilesh Sanikop EXPECT_TRUE(v.emplace_back(3, 4));
129*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 2);
130*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].x(), 1);
131*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].y(), 2);
132*09537850SAkhilesh Sanikop EXPECT_EQ(v[1].x(), 3);
133*09537850SAkhilesh Sanikop EXPECT_EQ(v[1].y(), 4);
134*09537850SAkhilesh Sanikop }
135*09537850SAkhilesh Sanikop
136*09537850SAkhilesh Sanikop // Copy constructor and assignment are deleted, but move constructor and
137*09537850SAkhilesh Sanikop // assignment are OK.
TEST(VectorTest,Move)138*09537850SAkhilesh Sanikop TEST(VectorTest, Move) {
139*09537850SAkhilesh Sanikop Vector<int> ints1;
140*09537850SAkhilesh Sanikop EXPECT_TRUE(ints1.reserve(4));
141*09537850SAkhilesh Sanikop EXPECT_TRUE(ints1.push_back(2));
142*09537850SAkhilesh Sanikop EXPECT_TRUE(ints1.push_back(3));
143*09537850SAkhilesh Sanikop EXPECT_TRUE(ints1.push_back(5));
144*09537850SAkhilesh Sanikop EXPECT_TRUE(ints1.push_back(7));
145*09537850SAkhilesh Sanikop
146*09537850SAkhilesh Sanikop // Move constructor.
147*09537850SAkhilesh Sanikop Vector<int> ints2(std::move(ints1));
148*09537850SAkhilesh Sanikop EXPECT_EQ(ints2.size(), 4);
149*09537850SAkhilesh Sanikop EXPECT_EQ(ints2[0], 2);
150*09537850SAkhilesh Sanikop EXPECT_EQ(ints2[1], 3);
151*09537850SAkhilesh Sanikop EXPECT_EQ(ints2[2], 5);
152*09537850SAkhilesh Sanikop EXPECT_EQ(ints2[3], 7);
153*09537850SAkhilesh Sanikop
154*09537850SAkhilesh Sanikop // Move assignment.
155*09537850SAkhilesh Sanikop Vector<int> ints3;
156*09537850SAkhilesh Sanikop EXPECT_TRUE(ints3.reserve(1));
157*09537850SAkhilesh Sanikop EXPECT_TRUE(ints3.push_back(11));
158*09537850SAkhilesh Sanikop ints3 = std::move(ints2);
159*09537850SAkhilesh Sanikop EXPECT_EQ(ints3.size(), 4);
160*09537850SAkhilesh Sanikop EXPECT_EQ(ints3[0], 2);
161*09537850SAkhilesh Sanikop EXPECT_EQ(ints3[1], 3);
162*09537850SAkhilesh Sanikop EXPECT_EQ(ints3[2], 5);
163*09537850SAkhilesh Sanikop EXPECT_EQ(ints3[3], 7);
164*09537850SAkhilesh Sanikop }
165*09537850SAkhilesh Sanikop
TEST(VectorTest,Erase)166*09537850SAkhilesh Sanikop TEST(VectorTest, Erase) {
167*09537850SAkhilesh Sanikop Vector<int> ints;
168*09537850SAkhilesh Sanikop EXPECT_TRUE(ints.reserve(4));
169*09537850SAkhilesh Sanikop EXPECT_TRUE(ints.push_back(2));
170*09537850SAkhilesh Sanikop EXPECT_TRUE(ints.push_back(3));
171*09537850SAkhilesh Sanikop EXPECT_TRUE(ints.push_back(5));
172*09537850SAkhilesh Sanikop EXPECT_TRUE(ints.push_back(7));
173*09537850SAkhilesh Sanikop
174*09537850SAkhilesh Sanikop EXPECT_EQ(ints.size(), 4);
175*09537850SAkhilesh Sanikop EXPECT_EQ(ints[0], 2);
176*09537850SAkhilesh Sanikop EXPECT_EQ(ints[1], 3);
177*09537850SAkhilesh Sanikop EXPECT_EQ(ints[2], 5);
178*09537850SAkhilesh Sanikop EXPECT_EQ(ints[3], 7);
179*09537850SAkhilesh Sanikop
180*09537850SAkhilesh Sanikop ints.erase(ints.begin());
181*09537850SAkhilesh Sanikop EXPECT_EQ(ints.size(), 3);
182*09537850SAkhilesh Sanikop EXPECT_EQ(ints[0], 3);
183*09537850SAkhilesh Sanikop EXPECT_EQ(ints[1], 5);
184*09537850SAkhilesh Sanikop EXPECT_EQ(ints[2], 7);
185*09537850SAkhilesh Sanikop }
186*09537850SAkhilesh Sanikop
TEST(VectorTest,EraseNonTrivial)187*09537850SAkhilesh Sanikop TEST(VectorTest, EraseNonTrivial) {
188*09537850SAkhilesh Sanikop // A simple class that sets an int value to 0 in the destructor.
189*09537850SAkhilesh Sanikop class Cleaner {
190*09537850SAkhilesh Sanikop public:
191*09537850SAkhilesh Sanikop explicit Cleaner(int* value) : value_(value) {}
192*09537850SAkhilesh Sanikop ~Cleaner() { *value_ = 0; }
193*09537850SAkhilesh Sanikop
194*09537850SAkhilesh Sanikop int value() const { return *value_; }
195*09537850SAkhilesh Sanikop
196*09537850SAkhilesh Sanikop private:
197*09537850SAkhilesh Sanikop int* value_;
198*09537850SAkhilesh Sanikop };
199*09537850SAkhilesh Sanikop int value1 = 100;
200*09537850SAkhilesh Sanikop int value2 = 200;
201*09537850SAkhilesh Sanikop Vector<std::unique_ptr<Cleaner>> v;
202*09537850SAkhilesh Sanikop EXPECT_TRUE(v.reserve(2));
203*09537850SAkhilesh Sanikop EXPECT_EQ(v.capacity(), 2);
204*09537850SAkhilesh Sanikop
205*09537850SAkhilesh Sanikop std::unique_ptr<Cleaner> c(new (std::nothrow) Cleaner(&value1));
206*09537850SAkhilesh Sanikop EXPECT_NE(c, nullptr);
207*09537850SAkhilesh Sanikop EXPECT_TRUE(v.push_back(std::move(c)));
208*09537850SAkhilesh Sanikop c.reset(new (std::nothrow) Cleaner(&value2));
209*09537850SAkhilesh Sanikop EXPECT_NE(c, nullptr);
210*09537850SAkhilesh Sanikop EXPECT_TRUE(v.push_back(std::move(c)));
211*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 2);
212*09537850SAkhilesh Sanikop EXPECT_EQ(value1, 100);
213*09537850SAkhilesh Sanikop EXPECT_EQ(value2, 200);
214*09537850SAkhilesh Sanikop
215*09537850SAkhilesh Sanikop v.erase(v.begin());
216*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 1);
217*09537850SAkhilesh Sanikop EXPECT_EQ(v.capacity(), 2);
218*09537850SAkhilesh Sanikop EXPECT_EQ(value1, 0);
219*09537850SAkhilesh Sanikop EXPECT_EQ(value2, 200);
220*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].get()->value(), value2);
221*09537850SAkhilesh Sanikop
222*09537850SAkhilesh Sanikop EXPECT_TRUE(v.shrink_to_fit());
223*09537850SAkhilesh Sanikop EXPECT_EQ(v.size(), 1);
224*09537850SAkhilesh Sanikop EXPECT_EQ(v.capacity(), 1);
225*09537850SAkhilesh Sanikop EXPECT_EQ(value2, 200);
226*09537850SAkhilesh Sanikop EXPECT_EQ(v[0].get()->value(), value2);
227*09537850SAkhilesh Sanikop
228*09537850SAkhilesh Sanikop v.clear();
229*09537850SAkhilesh Sanikop EXPECT_TRUE(v.empty());
230*09537850SAkhilesh Sanikop EXPECT_EQ(value2, 0);
231*09537850SAkhilesh Sanikop }
232*09537850SAkhilesh Sanikop
233*09537850SAkhilesh Sanikop } // namespace
234*09537850SAkhilesh Sanikop } // namespace libgav1
235