1 /////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 /////////////////////////////////////////////////////////////////////////////
4 
5 
6 #include "EASTLTest.h"
7 #include <EASTL/memory.h>
8 #include <EASTL/utility.h>
9 #include <EASTL/vector.h>
10 #include <EAStdC/EAMemory.h>
11 #include <EAStdC/EAAlignment.h>
12 
13 
14 // Regression for user reported operator new problem (12/8/2009):
15 class AssetHandler
16 {
17 public:
operator new(size_t size,const char *,unsigned int)18 	inline static void* operator new(size_t size, const char* /*text*/, unsigned int /*flags*/)
19 	{
20 		return ::operator new(size);
21 	}
operator delete(void * p)22 	inline static void operator delete(void* p)
23 	{
24 		return ::operator delete(p);
25 	}
26 };
27 typedef eastl::vector<AssetHandler> AssetHandlerArray;
28 
29 // Regression test for a default memory fill optimization that defers to memset instead of explicitly
30 // value-initialization each element in a vector individually.  This test ensures that the value of the memset is
31 // consistent with an explicitly value-initialized element (namely when the container holds a scalar value that is
32 // memset to zero).
33 template <typename T>
TestValueInitOptimization()34 int TestValueInitOptimization()
35 {
36 	int nErrorCount = 0;
37 	const int ELEM_COUNT = 100;
38 
39 	{
40 		eastl::vector<T> v1;
41 		eastl::vector<ValueInitOf<T>> v2;
42 
43 		v1.resize(ELEM_COUNT);
44 		v2.resize(ELEM_COUNT);
45 
46 		for (int i = 0; i < ELEM_COUNT; i++)
47 			{ EATEST_VERIFY(v1[i] == v2[i].get()); }
48 	}
49 
50 	{
51 		eastl::vector<T> v1(ELEM_COUNT);
52 		eastl::vector<ValueInitOf<T>> v2(ELEM_COUNT);
53 
54 		for (int i = 0; i < ELEM_COUNT; i++)
55 			{ EATEST_VERIFY(v1[i] == v2[i].get()); }
56 	}
57 
58 	EATEST_VERIFY(nErrorCount == 0);
59 	return nErrorCount;
60 }
61 
62 
63 // LCTestObject
64 //
65 // Helps test the late_constructed utility.
66 // Has an unusual alignment so we can test that aspect of late_constructed.
67 //
68 struct EA_ALIGN(64) LCTestObject
69 {
70 	int             mX;                  //
71 	static int64_t  sTOCount;            // Count of all current existing objects.
72 	static int64_t  sTOCtorCount;        // Count of times any ctor was called.
73 	static int64_t  sTODtorCount;        // Count of times dtor was called.
74 
LCTestObjectLCTestObject75 	explicit LCTestObject(int x = 0)
76 		: mX(x)
77 	{
78 		++sTOCount;
79 		++sTOCtorCount;
80 	}
81 
LCTestObjectLCTestObject82 	LCTestObject(int x0, int x1, int x2)
83 		: mX(x0 + x1 + x2)
84 	{
85 		++sTOCount;
86 		++sTOCtorCount;
87 	}
88 
LCTestObjectLCTestObject89 	LCTestObject(const LCTestObject& testObject)
90 		: mX(testObject.mX)
91 	{
92 		++sTOCount;
93 		++sTOCtorCount;
94 	}
95 
96 	#if !defined(EA_COMPILER_NO_RVALUE_REFERENCES)
LCTestObjectLCTestObject97 		LCTestObject(TestObject&& testObject)
98 			: mX(testObject.mX)
99 		{
100 			++sTOCount;
101 			++sTOCtorCount;
102 		}
103 	#endif
104 
operator =LCTestObject105 	LCTestObject& operator=(const LCTestObject& testObject)
106 	{
107 		mX = testObject.mX;
108 		return *this;
109 	}
110 
111 	#if !defined(EA_COMPILER_NO_RVALUE_REFERENCES)
operator =LCTestObject112 		LCTestObject& operator=(LCTestObject&& testObject)
113 		{
114 			eastl::swap(mX, testObject.mX);
115 			return *this;
116 		}
117 	#endif
118 
~LCTestObjectLCTestObject119 	~LCTestObject()
120 	{
121 		--sTOCount;
122 		++sTODtorCount;
123 	}
124 };
125 
126 int64_t LCTestObject::sTOCount     = 0;
127 int64_t LCTestObject::sTOCtorCount = 0;
128 int64_t LCTestObject::sTODtorCount = 0;
129 
130 
131 eastl::late_constructed<LCTestObject, true>  gLCTestObjectTrue;
132 eastl::late_constructed<LCTestObject, false> gLCTestObjectFalse;
133 
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 // TestMemory
137 //
TestMemory()138 int TestMemory()
139 {
140 	using namespace eastl;
141 
142 	int nErrorCount = 0;
143 
144 	TestObject::Reset();
145 
146 	{
147 		// get_temporary_buffer(ptrdiff_t n, size_t alignment, size_t alignmentOffset, char* pName);
148 
149 		pair<int*, ptrdiff_t> pr1 = get_temporary_buffer<int>(100, 1, 0, EASTL_NAME_VAL("Temp int array"));
150 		memset(pr1.first, 0, 100 * sizeof(int));
151 		return_temporary_buffer(pr1.first);
152 
153 		// Note that
154 		pair<TestObject*, ptrdiff_t> pr2 = get_temporary_buffer<TestObject>(300);
155 		memset(pr2.first, 0, 300 * sizeof(TestObject));
156 		return_temporary_buffer(pr2.first, pr2.second);
157 	}
158 
159 	EATEST_VERIFY(TestObject::IsClear());
160 	TestObject::Reset();
161 
162 
163 	{
164 		LCTestObject* pLCTO;
165 
166 		// Verify alignment requirements.
167 		// We don't verify that gLCTestObjectTrue.get() is aligned for all platforms because some platforms can't do that with global memory.
168 		static_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::value_type>::value == 64, "late_constructed alignment failure.");
169 		static_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::storage_type>::value == 64, "late_constructed alignment failure.");
170 		static_assert(eastl::alignment_of<late_constructed<LCTestObject> >::value >= 64, "late_constructed alignment failure.");
171 
172 
173 		// late_constructed / gLCTestObjectTrue
174 		EATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));
175 		EATEST_VERIFY(!gLCTestObjectTrue.is_constructed());
176 
177 		pLCTO = gLCTestObjectTrue.get(); // This will auto-construct LCTestObject.
178 		EATEST_VERIFY(pLCTO != NULL);
179 		EATEST_VERIFY(gLCTestObjectTrue.is_constructed());
180 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));
181 
182 		gLCTestObjectTrue->mX = 17;
183 		EATEST_VERIFY(gLCTestObjectTrue->mX == 17);
184 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));
185 
186 		gLCTestObjectTrue.destruct();
187 		EATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));
188 		EATEST_VERIFY(!gLCTestObjectTrue.is_constructed());
189 
190 		gLCTestObjectTrue->mX = 18;
191 		EATEST_VERIFY(gLCTestObjectTrue->mX == 18);
192 		EATEST_VERIFY(gLCTestObjectTrue.is_constructed());
193 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));
194 
195 		gLCTestObjectTrue.destruct();
196 		(*gLCTestObjectTrue).mX = 19;
197 		EATEST_VERIFY(gLCTestObjectTrue->mX == 19);
198 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));
199 
200 		gLCTestObjectTrue.destruct();
201 		LCTestObject::sTOCount     = 0;
202 		LCTestObject::sTOCtorCount = 0;
203 		LCTestObject::sTODtorCount = 0;
204 
205 		// late_constructed / gLCTestObjectFalse
206 		EATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));
207 		EATEST_VERIFY(!gLCTestObjectFalse.is_constructed());
208 
209 		pLCTO = gLCTestObjectFalse.get(); // This will not auto-construct LCTestObject.
210 		EATEST_VERIFY(pLCTO == NULL);
211 		EATEST_VERIFY(!gLCTestObjectFalse.is_constructed());
212 		EATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));
213 
214 		gLCTestObjectFalse.construct();
215 		pLCTO = gLCTestObjectFalse.get();
216 		EATEST_VERIFY(pLCTO != NULL);
217 		EATEST_VERIFY(gLCTestObjectFalse.is_constructed());
218 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));
219 
220 		gLCTestObjectFalse->mX = 17;
221 		EATEST_VERIFY(gLCTestObjectFalse->mX == 17);
222 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));
223 
224 		gLCTestObjectFalse.destruct();
225 		EATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));
226 		EATEST_VERIFY(!gLCTestObjectFalse.is_constructed());
227 
228 		gLCTestObjectFalse.construct(14);
229 		EATEST_VERIFY(gLCTestObjectFalse->mX == 14);
230 		gLCTestObjectFalse->mX = 18;
231 		EATEST_VERIFY(gLCTestObjectFalse->mX == 18);
232 		EATEST_VERIFY(gLCTestObjectFalse.is_constructed());
233 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));
234 
235 		gLCTestObjectFalse.destruct();
236 		gLCTestObjectFalse.construct(10, 20, 30);
237 		EATEST_VERIFY(gLCTestObjectFalse->mX == 10+20+30);
238 		(*gLCTestObjectFalse).mX = 19;
239 		EATEST_VERIFY(gLCTestObjectFalse->mX == 19);
240 		EATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));
241 
242 		gLCTestObjectFalse.destruct();
243 	}
244 
245 
246 	// We use the vector container to supply a RandomAccessIterator.
247 	// We use the list container to supply a BidirectionalIterator.
248 	// We use the slist container to supply a ForwardIterator.
249 	// We use our generic_input_iterator adapter to supply an InputIterator.
250 
251 	// eastl::vector<int>  intVector;
252 	// eastl::list<int>    intList;
253 	// eastl::slist<int>   intSlist;
254 
255 	// template <typename ForwardIterator, typename ForwardIteratorDest>
256 	// inline ForwardIteratorDest uninitialized_relocate_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
257 
258 	// template <typename ForwardIterator, typename ForwardIteratorDest>
259 	// inline ForwardIteratorDest uninitialized_relocate_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
260 
261 	// template <typename ForwardIterator, typename ForwardIteratorDest>
262 	// inline ForwardIteratorDest uninitialized_relocate_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
263 
264 	// template <typename ForwardIterator, typename ForwardIteratorDest>
265 	// inline ForwardIteratorDest uninitialized_relocate(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
266 
267 	// This test does little more than verify that the code compiles.
268 	int* pEnd = eastl::uninitialized_relocate_start<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
269 	EATEST_VERIFY(pEnd == NULL);
270 
271 	pEnd = eastl::uninitialized_relocate_commit<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
272 	EATEST_VERIFY(pEnd == NULL);
273 
274 	pEnd = eastl::uninitialized_relocate_abort<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
275 	EATEST_VERIFY(pEnd == NULL);
276 
277 	pEnd = eastl::uninitialized_relocate<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
278 	EATEST_VERIFY(pEnd == NULL);
279 
280 
281 
282 	// template <typename InputIterator, typename ForwardIterator>
283 	// ForwardIterator uninitialized_copy(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);
284 
285 	pEnd = eastl::uninitialized_copy<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
286 	EATEST_VERIFY(pEnd == NULL);
287 
288 
289 
290 	// template <typename First, typename Last, typename Result>
291 	// Result uninitialized_copy_ptr(First first, Last last, Result result)
292 
293 	pEnd = eastl::uninitialized_copy_ptr<int*, int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);
294 	EATEST_VERIFY(pEnd == NULL);
295 
296 
297 
298 	// template <typename ForwardIterator, typename T>
299 	// void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)
300 
301 	eastl::uninitialized_fill<int*, int>((int*)NULL, (int*)NULL, (int)0);
302 
303 
304 
305 	// template <typename T>
306 	// void uninitialized_fill_ptr(T* first, T* last, const T& value)
307 
308 	eastl::uninitialized_fill_ptr<int>((int*)NULL, (int*)NULL, (int)0);
309 
310 
311 
312 	// template <typename ForwardIterator, typename Count, typename T>
313 	// void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)
314 
315 	eastl::uninitialized_fill_n<int*, int, int>((int*)NULL, (int)0, (int)0);
316 
317 
318 
319 	// template <typename T, typename Count>
320 	// void uninitialized_fill_n_ptr(T* first, Count n, const T& value)
321 
322 	eastl::uninitialized_fill_n_ptr<int, int>((int*)NULL, (int)0, (int)0);
323 
324 
325 
326 
327 	// template <typename InputIterator, typename ForwardIterator, typename T>
328 	// void uninitialized_copy_fill(InputIterator first1, InputIterator last1,
329 	//                                 ForwardIterator first2, ForwardIterator last2, const T& value)
330 
331 	eastl::uninitialized_copy_fill<int*, int*, int>((int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL, (int)0);
332 
333 
334 
335 	// template <typename ForwardIterator, typename T, typename InputIterator>
336 	// ForwardIterator uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
337 
338 	eastl::uninitialized_fill_copy<int*, int, int*>((int*)NULL, (int*)NULL, (int)0, (int*)NULL, (int*)NULL);
339 
340 
341 
342 	// template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>
343 	// ForwardIterator uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
344 	//                                         InputIterator2 first2, InputIterator2 last2,
345 	//                                         ForwardIterator result)
346 
347 	eastl::uninitialized_copy_copy<int*, int*, int*>((int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL);
348 
349 	// uninitialized_default_construct
350 	{
351 		TestObject::Reset();
352 		char testCharArray[sizeof(TestObject) * 10];
353 		TestObject* pTestMemory = (TestObject*)(testCharArray);
354 
355 		eastl::uninitialized_default_construct(pTestMemory, pTestMemory + 10);
356 		EATEST_VERIFY(TestObject::sTODefaultCtorCount == 10);
357 	}
358 
359 	// uninitialized_default_construct_n
360 	{
361 		TestObject::Reset();
362 		char testCharArray[sizeof(TestObject) * 10];
363 		TestObject* pTestMemory = (TestObject*)(testCharArray);
364 
365 		auto endIter = eastl::uninitialized_default_construct_n(pTestMemory, 5);
366 		EATEST_VERIFY(TestObject::sTODefaultCtorCount == 5);
367 		EATEST_VERIFY(endIter == (pTestMemory + 5));
368 	}
369 
370 	// uninitialized_value_construct
371 	{
372 		TestObject::Reset();
373 		char testCharArray[sizeof(TestObject) * 10];
374 		TestObject* pTestMemory = (TestObject*)(testCharArray);
375 
376 		eastl::uninitialized_value_construct(pTestMemory, pTestMemory + 10);
377 		EATEST_VERIFY(TestObject::sTODefaultCtorCount == 10);
378 	}
379 
380 	// uninitialized_value_construct_n
381 	{
382 		TestObject::Reset();
383 		char testCharArray[sizeof(TestObject) * 10];
384 		TestObject* pTestMemory = (TestObject*)(testCharArray);
385 
386 		auto endIter = eastl::uninitialized_value_construct_n(pTestMemory, 5);
387 		EATEST_VERIFY(TestObject::sTODefaultCtorCount == 5);
388 		EATEST_VERIFY(endIter == (pTestMemory + 5));
389 	}
390 
391 	// Verify that uninitialized_value_construct does not do any additional initialization besides zero-initialization.
392 	//
393 	/// Value-Initialization:
394 	//   If T is a class, the object is default-initialized (after being zero-initialized if T's default
395 	//   constructor is not user-provided/deleted); otherwise, the object is zero-initialized.
396 	{
397 		struct foo
398 		{
399 			// foo() = default; // intentionally removed to force zero-initialization behavior
400 			char mV;
401 		};
402 
403 		static const int ARRAY_SIZE_IN_BYTES = sizeof(foo) * 10;
404 
405 		char testCharArray[ARRAY_SIZE_IN_BYTES];
406 		EA::StdC::Memfill8(testCharArray, 42, ARRAY_SIZE_IN_BYTES);
407 		foo* pTestMemory = (foo*)testCharArray;
408 
409 		eastl::uninitialized_value_construct(pTestMemory, pTestMemory + 10);
410 
411 		for (int i = 0; i < 10; i++)
412 		{
413 			EATEST_VERIFY(pTestMemory[i].mV == 0); // verify that memory is zero-initialized
414 		}
415 	}
416 
417 	// Verify that uninitialized_default_construct does not do any additional initialization besides the calling of a empty
418 	// constructor.
419 	//
420 	// Default-initialization:
421 	//  If T is a class, the default constructor is called; otherwise, no initialization is done, resulting in
422 	//  indeterminate values.
423 	{
424 		struct foo
425 		{
426 			foo() {}  // default ctor intentionally a no-op
427 			char mV;
428 		};
429 
430 		static const int ARRAY_SIZE_IN_BYTES = sizeof(foo) * 10;
431 
432 		char testCharArray[ARRAY_SIZE_IN_BYTES];
433 		EA::StdC::Memfill8(testCharArray, 42, ARRAY_SIZE_IN_BYTES);
434 		foo* pTestMemory = (foo*)testCharArray;
435 
436 		eastl::uninitialized_default_construct(pTestMemory, pTestMemory + 10);
437 
438 		for (int i = 0; i < 10; i++)
439 		{
440 			EATEST_VERIFY(pTestMemory[i].mV == 42); // verify original memset value is intact
441 		}
442 	}
443 
444 	// template <typename T>
445 	// void destruct(T* p)
446 	{
447 		TestObject::Reset();
448 		uint64_t testObjectMemory[((sizeof(TestObject) / sizeof(uint64_t)) + 1) * 2];
449 
450 		TestObject* pTestObject = new(testObjectMemory) TestObject;
451 		destruct(pTestObject);
452 		EATEST_VERIFY(TestObject::IsClear());
453 	}
454 
455 	// template <typename T>
456 	// void destroy_at(T* p)
457 	{
458 		TestObject::Reset();
459 		uint64_t testObjectMemory[((sizeof(TestObject) / sizeof(uint64_t)) + 1) * 2];
460 		TestObject* pTestObject = new(testObjectMemory) TestObject;
461 		destroy_at(pTestObject);
462 
463 		EATEST_VERIFY(TestObject::IsClear());
464 	}
465 
466 
467 	// template <typename ForwardIterator>
468 	// void destruct(ForwardIterator first, ForwardIterator last)
469 	{
470 		TestObject::Reset();
471 		char testObjectMemory[sizeof(TestObject) * 3];
472 		TestObject* pTestObject = new(testObjectMemory) TestObject[2];
473 		destruct(pTestObject, pTestObject + 2);
474 
475 		EATEST_VERIFY(TestObject::IsClear());
476 	}
477 
478 	// template <typename ForwardIterator>
479 	// void destroy(ForwardIterator first, ForwardIterator last)
480 	{
481 		TestObject::Reset();
482 		char testObjectMemory[sizeof(TestObject) * 3];
483 		TestObject* pTestObject = new(testObjectMemory) TestObject[2];
484 		destroy(pTestObject, pTestObject + 2);
485 
486 		EATEST_VERIFY(TestObject::IsClear());
487 	}
488 
489 	// template <typename ForwardIterator, typename Size>
490 	// void destroy_n(ForwardIterator first, Size n)
491 	{
492 		TestObject::Reset();
493 		char testObjectMemory[sizeof(TestObject) * 3];
494 		TestObject* pTestObject = new (testObjectMemory) TestObject[2];
495 
496 		destroy_n(pTestObject, 1);     // destroy TestObject[0]
497 		destroy_n(pTestObject + 1, 1); // destroy TestObject[1]
498 
499 		EATEST_VERIFY(TestObject::IsClear());
500 	}
501 
502 
503 	{
504 		// Regression for user reported operator new problem (12/8/2009):
505 		eastl::vector<AssetHandler> ahArray;
506 		ahArray.push_back(AssetHandler());
507 	}
508 
509 
510 	// void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
511 	// void* align_advance(size_t alignment, size_t size, void*& ptr, size_t& space);
512 	{
513 		const  size_t kBufferSize = 256;
514 		char   buffer[kBufferSize * 2];
515 		size_t space = sizeof(buffer);
516 		void*  ptr = buffer;
517 		void*  ptrSaved;
518 		void*  ptrAligned;
519 		size_t i;
520 
521 		// First get 256 bytes of space aligned to 256.
522 		// It's a coincidence that we are using eastl::align to set up a buffer for testing eastl::align below.
523 		ptrSaved = eastl::align(256, 256, ptr, space);
524 
525 		// At this point we have 256 bytes of memory aligned on 256 bytes, within buffer.
526 		// We test allocating multiple blocks from this space at various alignments values.
527 		// We also test that the function sets ptr to the next available location after the
528 		// returned allocated block.
529 		EA::StdC::Memset8(buffer, 0x00, sizeof(buffer));
530 		EATEST_VERIFY(EA::StdC::IsAligned(ptr, 256));
531 
532 		// align test
533 		// Try a number of allocation sizes.
534 		for(size_t a = 1; a < 64; a *= 2)
535 		{
536 			// Do multiple sequental allocations from the storage.
537 			for(i = 0, space = 256, ptr = ptrSaved; i < kBufferSize; i += a)
538 			{
539 				ptrAligned = eastl::align(a, a, ptr, space);
540 
541 				EATEST_VERIFY((uintptr_t)ptrAligned == ((uintptr_t)ptrSaved + i));
542 				EATEST_VERIFY(ptr                   == ptrAligned);
543 				EATEST_VERIFY(space                 == (kBufferSize - i));
544 				EATEST_VERIFY(EA::StdC::IsAligned(ptrAligned, a));
545 				EATEST_VERIFY(EA::StdC::Memcheck8(ptrAligned, 0x00, a) == NULL);
546 
547 				ptr    = (char*)ptr + a;
548 				space -= a;
549 				memset(ptrAligned, 0xff, a); // Do this so that next time around we can verify this memory isn't returned.
550 			}
551 
552 			EA::StdC::Memset8(buffer, 0x00, sizeof(buffer));
553 		}
554 
555 		// align_advance test (similar to but not identical to the align test)
556 		// Try a number of allocation sizes.
557 		for(size_t a = 1; a < 64; a *= 2)
558 		{
559 			// Do multiple sequental allocations from the storage.
560 			for(i = 0, space = 256, ptr = ptrSaved; i < kBufferSize; i += a)
561 			{
562 				ptrAligned = eastl::align_advance(a, a, ptr, space, &ptr, &space);
563 
564 				EATEST_VERIFY((uintptr_t)ptrAligned == ((uintptr_t)ptrSaved + i));
565 				EATEST_VERIFY((uintptr_t)ptr        == (uintptr_t)ptrAligned + a);
566 				EATEST_VERIFY(space                 == (kBufferSize - i) - a);
567 				EATEST_VERIFY(EA::StdC::IsAligned(ptrAligned, a));
568 				EATEST_VERIFY(EA::StdC::Memcheck8(ptrAligned, 0x00, a) == NULL);
569 
570 				memset(ptrAligned, 0xff, a); // Do this so that next time around we can verify this memory isn't returned.
571 			}
572 
573 			EA::StdC::Memset8(buffer, 0x00, sizeof(buffer));
574 		}
575 	}
576 
577 	{
578 		// Test that align handles integral overflow correctly and returns NULL.
579 		void*  ptr;
580 		void*  ptrSaved;
581 		size_t space;
582 		void*  pResult;
583 
584 		space    = 64;
585 		ptr      = 0;
586 		ptr      = (char*)ptr - space;
587 		ptrSaved = ptr;
588 		pResult  = eastl::align(1, space + 1, ptr, space);             // Possible alignment, impossible size due to wraparound.
589 		EATEST_VERIFY((pResult == NULL) && (ptr == ptrSaved));
590 
591 		space    = 64;
592 		ptr      = 0;
593 		ptr      = (char*)ptr - space;
594 		ptrSaved = ptr;
595 		pResult  = eastl::align(space * 2, 32, ptr, space);            // Impossible alignment due to wraparound, possible size.
596 		EATEST_VERIFY((pResult == NULL) && (ptr == ptrSaved));
597 	}
598 
599 	{
600 		nErrorCount += TestValueInitOptimization<int>();
601 		nErrorCount += TestValueInitOptimization<char>();
602 		nErrorCount += TestValueInitOptimization<short>();
603 		nErrorCount += TestValueInitOptimization<float>();
604 		nErrorCount += TestValueInitOptimization<double>();
605 		nErrorCount += TestValueInitOptimization<void*>();
606 	}
607 
608 	EATEST_VERIFY(nErrorCount == 0);
609 	return nErrorCount;
610 }
611 
612 
613 
614 
615 
616 
617 
618 
619 
620 
621 
622