1 /*-------------------------------------------------------------------------
2  * drawElements C++ Base Library
3  * -----------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Array template backed by memory pool.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "dePoolArray.hpp"
25 
26 #include <algorithm>
27 #include <vector>
28 
29 namespace de
30 {
31 
intArrayTest(void)32 static void intArrayTest (void)
33 {
34 	MemPool				pool;
35 	PoolArray<int>		arr		(&pool);
36 	PoolArray<deUint16>	arr16	(&pool);
37 	int					i;
38 
39 	/* Test pushBack(). */
40 	for (i = 0; i < 5000; i++)
41 	{
42 		/* Dummy alloc to try to break alignments. */
43 		pool.alloc(1);
44 
45 		arr.pushBack(i);
46 		arr16.pushBack((deInt16)i);
47 	}
48 
49 	DE_TEST_ASSERT(arr.size() == 5000);
50 	DE_TEST_ASSERT(arr16.size() == 5000);
51 	for (i = 0; i < 5000; i++)
52 	{
53 		DE_TEST_ASSERT(arr[i] == i);
54 		DE_TEST_ASSERT(arr16[i] == i);
55 	}
56 
57 	/* Test popBack(). */
58 	for (i = 0; i < 1000; i++)
59 	{
60 		DE_TEST_ASSERT(arr.popBack() == (4999 - i));
61 		DE_TEST_ASSERT(arr16.popBack() == (4999 - i));
62 	}
63 
64 	DE_TEST_ASSERT(arr.size() == 4000);
65 	DE_TEST_ASSERT(arr16.size() == 4000);
66 	for (i = 0; i < 4000; i++)
67 	{
68 		DE_TEST_ASSERT(arr[i] == i);
69 		DE_TEST_ASSERT(arr16[i] == i);
70 	}
71 
72 	/* Test resize(). */
73 	arr.resize(1000);
74 	arr16.resize(1000);
75 	for (i = 1000; i < 5000; i++)
76 	{
77 		arr.pushBack(i);
78 		arr16.pushBack((deInt16)i);
79 	}
80 
81 	DE_TEST_ASSERT(arr.size() == 5000);
82 	DE_TEST_ASSERT(arr16.size() == 5000);
83 	for (i = 0; i < 5000; i++)
84 	{
85 		DE_TEST_ASSERT(arr[i] == i);
86 		DE_TEST_ASSERT(arr16[i] == i);
87 	}
88 
89 	/* Test set() and pushBack() with reserve(). */
90 	PoolArray<int> arr2(&pool);
91 	arr2.resize(1500);
92 	arr2.reserve(2000);
93 	for (i = 0; i < 1500; i++)
94 		arr2[i] = i;
95 	for (; i < 5000; i++)
96 		arr2.pushBack(i);
97 
98 	DE_TEST_ASSERT(arr2.size() == 5000);
99 	for (i = 0; i < 5000; i++)
100 	{
101 		int val = arr2[i];
102 		DE_TEST_ASSERT(val == i);
103 	}
104 }
105 
alignedIntArrayTest(void)106 static void alignedIntArrayTest (void)
107 {
108 	MemPool					pool;
109 	PoolArray<int, 16>		arr		(&pool);
110 	PoolArray<deUint16,	8>	arr16	(&pool);
111 	int						i;
112 
113 	/* Test pushBack(). */
114 	for (i = 0; i < 5000; i++)
115 	{
116 		/* Dummy alloc to try to break alignments. */
117 		pool.alloc(1);
118 
119 		arr.pushBack(i);
120 		arr16.pushBack((deInt16)i);
121 	}
122 
123 	DE_TEST_ASSERT(arr.size() == 5000);
124 	DE_TEST_ASSERT(arr16.size() == 5000);
125 	for (i = 0; i < 5000; i++)
126 	{
127 		DE_TEST_ASSERT(arr[i] == i);
128 		DE_TEST_ASSERT(arr16[i] == i);
129 	}
130 
131 	/* Test popBack(). */
132 	for (i = 0; i < 1000; i++)
133 	{
134 		DE_TEST_ASSERT(arr.popBack() == (4999 - i));
135 		DE_TEST_ASSERT(arr16.popBack() == (4999 - i));
136 	}
137 
138 	DE_TEST_ASSERT(arr.size() == 4000);
139 	DE_TEST_ASSERT(arr16.size() == 4000);
140 	for (i = 0; i < 4000; i++)
141 	{
142 		DE_TEST_ASSERT(arr[i] == i);
143 		DE_TEST_ASSERT(arr16[i] == i);
144 	}
145 
146 	/* Test resize(). */
147 	arr.resize(1000);
148 	arr16.resize(1000);
149 	for (i = 1000; i < 5000; i++)
150 	{
151 		arr.pushBack(i);
152 		arr16.pushBack((deInt16)i);
153 	}
154 
155 	DE_TEST_ASSERT(arr.size() == 5000);
156 	DE_TEST_ASSERT(arr16.size() == 5000);
157 	for (i = 0; i < 5000; i++)
158 	{
159 		DE_TEST_ASSERT(arr[i] == i);
160 		DE_TEST_ASSERT(arr16[i] == i);
161 	}
162 
163 	arr.resize(0);
164 	arr.resize(100, -123);
165 	DE_TEST_ASSERT(arr.size() == 100);
166 	for (i = 0; i < 100; i++)
167 		DE_TEST_ASSERT(arr[i] == -123);
168 
169 	/* Test set() and pushBack() with reserve(). */
170 	PoolArray<int, 32> arr2(&pool);
171 	arr2.resize(1500);
172 	arr2.reserve(2000);
173 	for (i = 0; i < 1500; i++)
174 		arr2[i] = i;
175 	for (; i < 5000; i++)
176 		arr2.pushBack(i);
177 
178 	DE_TEST_ASSERT(arr2.size() == 5000);
179 	for (i = 0; i < 5000; i++)
180 	{
181 		int val = arr2[i];
182 		DE_TEST_ASSERT(val == i);
183 	}
184 }
185 
186 namespace
187 {
188 
189 class RefCount
190 {
191 public:
RefCount(void)192 	RefCount (void)
193 		: m_count(DE_NULL)
194 	{
195 	}
196 
RefCount(int * count)197 	RefCount (int* count)
198 		: m_count(count)
199 	{
200 		*m_count += 1;
201 	}
202 
RefCount(const RefCount & other)203 	RefCount (const RefCount& other)
204 		: m_count(other.m_count)
205 	{
206 		if (m_count)
207 			*m_count += 1;
208 	}
209 
~RefCount(void)210 	~RefCount (void)
211 	{
212 		if (m_count)
213 			*m_count -= 1;
214 	}
215 
operator =(const RefCount & other)216 	RefCount& operator= (const RefCount& other)
217 	{
218 		if (this == &other)
219 			return *this;
220 
221 		if (m_count)
222 			*m_count -= 1;
223 
224 		m_count = other.m_count;
225 
226 		if (m_count)
227 			*m_count += 1;
228 
229 		return *this;
230 	}
231 
232 private:
233 	int* m_count;
234 };
235 
236 } // anonymous
237 
sideEffectTest(void)238 static void sideEffectTest (void)
239 {
240 	MemPool				pool;
241 	PoolArray<RefCount>	arr		(&pool);
242 	int					count	= 0;
243 	RefCount			counter	(&count);
244 
245 	DE_TEST_ASSERT(count == 1);
246 
247 	for (int i = 0; i < 127; i++)
248 		arr.pushBack(counter);
249 
250 	DE_TEST_ASSERT(count == 128);
251 
252 	for (int i = 0; i < 10; i++)
253 		arr.popBack();
254 
255 	DE_TEST_ASSERT(count == 118);
256 
257 	arr.resize(150);
258 	DE_TEST_ASSERT(count == 118);
259 
260 	arr.resize(18);
261 	DE_TEST_ASSERT(count == 19);
262 
263 	arr.resize(19);
264 	DE_TEST_ASSERT(count == 19);
265 
266 	arr.clear();
267 	DE_TEST_ASSERT(count == 1);
268 }
269 
iteratorTest(void)270 static void iteratorTest (void)
271 {
272 	MemPool			pool;
273 	PoolArray<int>	arr		(&pool);
274 
275 	for (int ndx = 0; ndx < 128; ndx++)
276 		arr.pushBack(ndx);
277 
278 	// ConstIterator
279 	{
280 		const PoolArray<int>& cRef = arr;
281 		int ndx = 0;
282 		for (PoolArray<int>::ConstIterator iter = cRef.begin(); iter != cRef.end(); iter++, ndx++)
283 		{
284 			DE_TEST_ASSERT(*iter == ndx);
285 		}
286 
287 		// Cast & interop with non-const array.
288 		ndx = 0;
289 		for (PoolArray<int>::ConstIterator iter = arr.begin(); iter != arr.end(); iter++, ndx++)
290 		{
291 			DE_TEST_ASSERT(*iter == ndx);
292 		}
293 	}
294 
295 	// Arithmetics.
296 	DE_TEST_ASSERT(arr.end()-arr.begin() == 128);
297 	DE_TEST_ASSERT(*(arr.begin()+3) == 3);
298 	DE_TEST_ASSERT(arr.begin()[4] == 4);
299 
300 	// Relational
301 	DE_TEST_ASSERT(arr.begin() != arr.begin()+1);
302 	DE_TEST_ASSERT(arr.begin() == arr.begin());
303 	DE_TEST_ASSERT(arr.begin() != arr.end());
304 	DE_TEST_ASSERT(arr.begin() < arr.end());
305 	DE_TEST_ASSERT(arr.begin() < arr.begin()+1);
306 	DE_TEST_ASSERT(arr.begin() <= arr.begin());
307 	DE_TEST_ASSERT(arr.end() > arr.begin());
308 	DE_TEST_ASSERT(arr.begin() >= arr.begin());
309 
310 	// Compatibility with stl.
311 	DE_TEST_ASSERT(std::distance(arr.begin(), arr.end()) == 128);
312 
313 	std::vector<int> vecCopy(arr.size());
314 	std::copy(arr.begin(), arr.end(), vecCopy.begin());
315 	for (int ndx = 0; ndx < (int)vecCopy.size(); ndx++)
316 		DE_TEST_ASSERT(vecCopy[ndx] == ndx);
317 
318 	std::fill(arr.begin(), arr.end(), -1);
319 	for (int ndx = 0; ndx < (int)arr.size(); ndx++)
320 		DE_TEST_ASSERT(arr[ndx] == -1);
321 
322 	std::copy(vecCopy.begin(), vecCopy.end(), arr.begin());
323 	for (int ndx = 0; ndx < (int)arr.size(); ndx++)
324 		DE_TEST_ASSERT(arr[ndx] == ndx);
325 
326 	// Iterator
327 	{
328 		int ndx = 0;
329 		for (PoolArray<int>::Iterator iter = arr.begin(); iter != arr.end(); iter++, ndx++)
330 		{
331 			DE_TEST_ASSERT(*iter == ndx);
332 			if (ndx == 4)
333 				*iter = 0;
334 			else if (ndx == 7)
335 				*(iter-1) = 1;
336 		}
337 	}
338 
339 	DE_TEST_ASSERT(arr[4] == 0);
340 	DE_TEST_ASSERT(arr[6] == 1);
341 }
342 
PoolArray_selfTest(void)343 void PoolArray_selfTest (void)
344 {
345 	intArrayTest();
346 	alignedIntArrayTest();
347 	sideEffectTest();
348 	iteratorTest();
349 }
350 
351 } // de
352