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
29namespace de
30{
31
32static 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
106static 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
186namespace
187{
188
189class RefCount
190{
191public:
192	RefCount (void)
193		: m_count(DE_NULL)
194	{
195	}
196
197	RefCount (int* count)
198		: m_count(count)
199	{
200		*m_count += 1;
201	}
202
203	RefCount (const RefCount& other)
204		: m_count(other.m_count)
205	{
206		if (m_count)
207			*m_count += 1;
208	}
209
210	~RefCount (void)
211	{
212		if (m_count)
213			*m_count -= 1;
214	}
215
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
232private:
233	int* m_count;
234};
235
236} // anonymous
237
238static 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
270static 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
343void PoolArray_selfTest (void)
344{
345	intArrayTest();
346	alignedIntArrayTest();
347	sideEffectTest();
348	iteratorTest();
349}
350
351} // de
352