1 /////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 /////////////////////////////////////////////////////////////////////////////
4 
5 
6 #ifndef EASTLTEST_H
7 #define EASTLTEST_H
8 
9 
10 #include <EABase/eabase.h>
11 #include <EATest/EATest.h>
12 
13 EA_DISABLE_ALL_VC_WARNINGS()
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <vector>   // For the STD_STL_TYPE defines below.
18 #if EASTL_EXCEPTIONS_ENABLED
19 	#include <stdexcept>
20 	#include <new>
21 #endif
22 EA_RESTORE_VC_WARNING()
23 
24 
25 int TestAlgorithm();
26 int TestAllocator();
27 int TestAny();
28 int TestArray();
29 int TestBitVector();
30 int TestBitset();
31 int TestCharTraits();
32 int TestChrono();
33 int TestCppCXTypeTraits();
34 int TestDeque();
35 int TestExtra();
36 int TestFixedFunction();
37 int TestFixedHash();
38 int TestFixedList();
39 int TestFixedMap();
40 int TestFixedSList();
41 int TestFixedSet();
42 int TestFixedString();
43 int TestFixedTupleVector();
44 int TestFixedVector();
45 int TestFunctional();
46 int TestHash();
47 int TestHeap();
48 int TestIntrusiveHash();
49 int TestIntrusiveList();
50 int TestIntrusiveSDList();
51 int TestIntrusiveSList();
52 int TestIterator();
53 int TestList();
54 int TestListMap();
55 int TestLruCache();
56 int TestMap();
57 int TestMemory();
58 int TestMeta();
59 int TestNumericLimits();
60 int TestOptional();
61 int TestRandom();
62 int TestRatio();
63 int TestRingBuffer();
64 int TestSList();
65 int TestSegmentedVector();
66 int TestSet();
67 int TestSmartPtr();
68 int TestSort();
69 int TestSpan();
70 int TestSparseMatrix();
71 int TestString();
72 int TestStringHashMap();
73 int TestStringMap();
74 int TestStringView();
75 int TestTuple();
76 int TestTypeTraits();
77 int TestUtility();
78 int TestVariant();
79 int TestVector();
80 int TestVectorMap();
81 int TestVectorSet();
82 int TestTupleVector();
83 
84 
85 // Now enable warnings as desired.
86 #ifdef _MSC_VER
87 	#pragma warning(disable: 4324)      // 'struct_name' : structure was padded due to __declspec(align())
88   //#pragma warning(disable: 4512)      // 'class' : assignment operator could not be generated
89   //#pragma warning(disable: 4100)      // 'identifier' : unreferenced formal parameter
90   //#pragma warning(disable: 4706)      // assignment within conditional expression
91 
92 	#pragma warning(default: 4056)      // Floating-point constant arithmetic generates a result that exceeds the maximum allowable value
93 	#pragma warning(default: 4061)      // The enumerate has no associated handler in a switch statement
94 	#pragma warning(default: 4062)      // The enumerate has no associated handler in a switch statement, and there is no default label
95 	#pragma warning(default: 4191)      // Calling this function through the result pointer may cause your program to crash
96 	#pragma warning(default: 4217)      // Member template functions cannot be used for copy-assignment or copy-construction
97   //#pragma warning(default: 4242)      // 'variable' : conversion from 'type' to 'type', possible loss of data
98 	#pragma warning(default: 4254)      // 'operator' : conversion from 'type1' to 'type2', possible loss of data
99 	#pragma warning(default: 4255)      // 'function' : no function prototype given: converting '()' to '(void)'
100 	#pragma warning(default: 4263)      // 'function' : member function does not override any base class virtual member function
101 	#pragma warning(default: 4264)      // 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden
102 	#pragma warning(default: 4287)      // 'operator' : unsigned/negative constant mismatch
103 	#pragma warning(default: 4289)      // Nonstandard extension used : 'var' : loop control variable declared in the for-loop is used outside the for-loop scope
104 	#pragma warning(default: 4296)      // 'operator' : expression is always false
105 	#pragma warning(default: 4302)      // 'conversion' : truncation from 'type 1' to 'type 2'
106 	#pragma warning(default: 4339)      // 'type' : use of undefined type detected in CLR meta-data - use of this type may lead to a runtime exception
107 	#pragma warning(default: 4347)      // Behavior change: 'function template' is called instead of 'function'
108   //#pragma warning(default: 4514)      // unreferenced inline/local function has been removed
109 	#pragma warning(default: 4529)      // 'member_name' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name
110 	#pragma warning(default: 4545)      // Expression before comma evaluates to a function which is missing an argument list
111 	#pragma warning(default: 4546)      // Function call before comma missing argument list
112 	#pragma warning(default: 4547)      // 'operator' : operator before comma has no effect; expected operator with side-effect
113   //#pragma warning(default: 4548)      // expression before comma has no effect; expected expression with side-effect
114 	#pragma warning(default: 4549)      // 'operator' : operator before comma has no effect; did you intend 'operator'?
115 	#pragma warning(default: 4536)      // 'type name' : type-name exceeds meta-data limit of 'limit' characters
116 	#pragma warning(default: 4555)      // Expression has no effect; expected expression with side-effect
117 	#pragma warning(default: 4557)      // '__assume' contains effect 'effect'
118   //#pragma warning(default: 4619)      // #pragma warning : there is no warning number 'number'
119 	#pragma warning(default: 4623)      // 'derived class' : default constructor could not be generated because a base class default constructor is inaccessible
120 	#pragma warning(default: 4625)      // 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
121 	#pragma warning(default: 4626)      // 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
122 	#pragma warning(default: 4628)      // Digraphs not supported with -Ze. Character sequence 'digraph' not interpreted as alternate token for 'char'
123 	#pragma warning(default: 4640)      // 'instance' : construction of local static object is not thread-safe
124 	#pragma warning(default: 4668)      // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
125 	#pragma warning(default: 4682)      // 'parameter' : no directional parameter attribute specified, defaulting to [in]
126 	#pragma warning(default: 4686)      // 'user-defined type' : possible change in behavior, change in UDT return calling convention
127   //#pragma warning(default: 4710)      // 'function' : function not inlined
128   //#pragma warning(default: 4786)      // 'identifier' : identifier was truncated to 'number' characters in the debug information
129 	#pragma warning(default: 4793)      // Native code generated for function 'function': 'reason'
130   //#pragma warning(default: 4820)      // 'bytes' bytes padding added after member 'member'
131 	#pragma warning(default: 4905)      // Wide string literal cast to 'LPSTR'
132 	#pragma warning(default: 4906)      // String literal cast to 'LPWSTR'
133 	#pragma warning(default: 4917)      // 'declarator' : a GUID cannot only be associated with a class, interface or namespace
134 	#pragma warning(default: 4928)      // Illegal copy-initialization; more than one user-defined conversion has been implicitly applied
135 	#pragma warning(default: 4931)      // We are assuming the type library was built for number-bit pointers
136 	#pragma warning(default: 4946)      // reinterpret_cast used between related classes: 'class1' and 'class2'
137 
138 #endif
139 
140 
141 ///////////////////////////////////////////////////////////////////////////////
142 // EASTL includes
143 //
144 // Intentionally keep these includes below the warning settings specified above.
145 //
146 #include <EASTL/iterator.h>
147 #include <EASTL/algorithm.h>
148 
149 
150 
151 
152 /// EASTL_TestLevel
153 ///
154 /// Defines how extensive our testing is. A low level is for a desktop or
155 /// nightly build in which the test can run quickly but still hit the
156 /// majority of functionality. High level is for heavy testing and internal
157 /// validation which may take numerous hours to run.
158 ///
159 enum EASTL_TestLevel
160 {
161 	kEASTL_TestLevelLow  = 1,   /// ~10 seconds for test completion.
162 	kEASTL_TestLevelHigh = 10   /// Numerous hours for test completion.
163 };
164 
165 extern int gEASTL_TestLevel;
166 
167 
168 
169 /// EASTLTest_CheckMemory
170 ///
171 /// Does a global memory heap validation check. Returns 0 if OK and
172 /// an error count if there is a problem.
173 ///
174 /// Example usage:
175 ///    EASTLTest_CheckMemory();
176 ///
177 int EASTLTest_CheckMemory_Imp(const char* pFile, int nLine);
178 #define EASTLTest_CheckMemory() EASTLTest_CheckMemory_Imp(__FILE__, __LINE__)
179 
180 
181 
182 // EASTLTEST_STD_STL_VER
183 //
184 #if defined(_STLPORT_VERSION)
185 	#define EASTLTEST_STD_STL_VER_STLPORT
186 #elif defined(_RWSTD_VER_STR) || defined(_RWSTD_NAMESPACE_END)
187 	#define EASTLTEST_STD_STL_VER_APACHE
188 #elif defined(_CPPLIB_VER)
189 	#define EASTLTEST_STD_STL_VER_DINKUMWARE
190 #elif defined(__GNUC__) && defined(_CXXCONFIG)
191 	#define EASTLTEST_STD_STL_VER_GCC
192 #else
193 	#define EASTLTEST_STD_STL_VER_UNKNOWN
194 #endif
195 
196 
197 
198 /// StdSTLType
199 ///
200 enum StdSTLType
201 {
202 	kSTLUnknown,    // Unknown type
203 	kSTLPort,       // STLPort. Descendent of the old HP / SGI STL.
204 	kSTLApache,     // Apache stdcxx (previously RogueWave), which is a descendent of the old HP / SGI STL.
205 	kSTLClang,      // Clang native. a.k.a. libc++
206 	kSTLGCC,        // GCC native. a.k.a. libstdc++
207 	kSTLMS,         // Microsoft. Tweaked version of Dinkumware.
208 	kSTLDinkumware  // Generic Dinkumware
209 };
210 
211 StdSTLType GetStdSTLType();
212 
213 
214 
215 
216 /// GetStdSTLName
217 ///
218 /// Returns the name of the std C++ STL available to the current build.
219 /// The returned value will be one of:
220 ///     "STLPort"
221 ///     "GCC"
222 ///     "VC++"
223 //      "Apache" // Previously RogueWave
224 ///
225 const char* GetStdSTLName();
226 
227 
228 /// gEASTLTest_AllocationCount
229 ///
230 extern int gEASTLTest_AllocationCount;
231 extern int gEASTLTest_TotalAllocationCount;
232 
233 
234 
235 // For backwards compatibility:
236 #define EASTLTest_Printf EA::UnitTest::Report
237 #define VERIFY           EATEST_VERIFY
238 
239 
240 ///////////////////////////////////////////////////////////////////////////////
241 /// EASTLTest_Rand
242 ///
243 /// Implements a basic random number generator for EASTL unit tests. It's not
244 /// intended to be a robust random number generator (though it is decent),
245 /// but rather is present so the unit tests can have a portable random number
246 /// generator they can rely on being present.
247 ///
248 /// Example usage:
249 ///    EASTLTest_Rand rng;
250 ///    eastl_size_t   x = rng();                      // Generate value in range of [0, 0xffffffff] (i.e. generate any uint32_t)
251 ///    eastl_ssize_t  y = rng.Rand(1000);             // Generate value in range of [0, 1000)
252 ///    eastl_ssize_t  z = rng.RandRange(-50, +30);    // Generate value in range of [-50, +30)
253 ///
254 /// Example usage in the random_shuffle algorithm:
255 ///    EASTLTest_Rand rng;
256 ///    random_shuffle(first, last, rnd);
257 ///
258 class EASTLTest_Rand
259 {
260 public:
EASTLTest_Rand(eastl_size_t nSeed)261 	EASTLTest_Rand(eastl_size_t nSeed) // The user must supply a seed; we don't provide default values.
262 		: mnSeed(nSeed) { }
263 
Rand()264 	eastl_size_t Rand()
265 	{
266 		// This is not designed to be a high quality random number generator.
267 		if(mnSeed == 0)
268 			mnSeed = UINT64_C(0xfefefefefefefefe); // Can't have a seed of zero.
269 
270 		const uint64_t nResult64A = ((mnSeed     * UINT64_C(6364136223846793005)) + UINT64_C(1442695040888963407));
271 		const uint64_t nResult64B = ((nResult64A * UINT64_C(6364136223846793005)) + UINT64_C(1442695040888963407));
272 
273 		mnSeed = (nResult64A >> 32) ^ nResult64B;
274 
275 		return (eastl_size_t)mnSeed; // For eastl_size_t == uint32_t, this is a chop.
276 	}
277 
operator()278 	eastl_size_t operator()() // Returns a pseudorandom value in range of [0, 0xffffffffffffffff)] (i.e. generate any eastl_size_t)
279 		{ return Rand(); }
280 
operator()281 	eastl_size_t operator()(eastl_size_t n)  // Returns a pseudorandom value in range of [0, n)
282 		{ return RandLimit(n); }
283 
RandLimit(eastl_size_t nLimit)284 	eastl_size_t RandLimit(eastl_size_t nLimit) // Returns a pseudorandom value in range of [0, nLimit)
285 	{
286 		// Can't do the following correct solution because we don't have a portable int128_t to work with.
287 		// We could implement a 128 bit multiply manually. See EAStdC/int128_t.cpp.
288 		// return (eastl_size_t)((Rand() * (uint128_t)nLimit) >> 64);
289 
290 		return (Rand() % nLimit); // This results in an imperfect distribution, especially for the case of nLimit being high relative to eastl_size_t.
291 	}
292 
RandRange(eastl_ssize_t nBegin,eastl_ssize_t nEnd)293 	eastl_ssize_t RandRange(eastl_ssize_t nBegin, eastl_ssize_t nEnd)   // Returns a pseudorandom value in range of [nBegin, nEnd)
294 		{ return nBegin + (eastl_ssize_t)RandLimit((eastl_size_t)(nEnd - nBegin)); }
295 
296 protected:
297 	uint64_t mnSeed;
298 };
299 
300 
301 ///////////////////////////////////////////////////////////////////////////////
302 /// RandGenT
303 ///
304 /// A wrapper for EASTLTest_Rand which generates values of the given integral
305 /// data type. This is mostly useful for clearnly avoiding compiler warnings,
306 /// as we intentionally enable the highest warning levels in these tests.
307 ///
308 template <typename Integer>
309 struct RandGenT
310 {
RandGenTRandGenT311 	RandGenT(eastl_size_t nSeed)
312 		: mRand(nSeed) { }
313 
operatorRandGenT314 	Integer operator()()
315 		{ return (Integer)mRand.Rand(); }
316 
operatorRandGenT317 	Integer operator()(eastl_size_t n)
318 		{ return (Integer)mRand.RandLimit(n); }
319 
320 	EASTLTest_Rand mRand;
321 };
322 
323 
324 
325 ///////////////////////////////////////////////////////////////////////////////
326 /// kMagicValue
327 ///
328 /// Used as a unique integer. We assign this to TestObject in its constructor
329 /// and verify in the TestObject destructor that the value is unchanged.
330 /// This can be used to tell, for example, if an invalid object is being
331 /// destroyed.
332 ///
333 const uint32_t kMagicValue = 0x01f1cbe8;
334 
335 
336 ///////////////////////////////////////////////////////////////////////////////
337 /// TestObject
338 ///
339 /// Implements a generic object that is suitable for use in container tests.
340 /// Note that we choose a very restricted set of functions that are available
341 /// for this class. Do not add any additional functions, as that would
342 /// compromise the intentions of the unit tests.
343 ///
344 struct TestObject
345 {
346 	int             mX;                  // Value for the TestObject.
347 	bool            mbThrowOnCopy;       // Throw an exception of this object is copied, moved, or assigned to another.
348 	int64_t         mId;                 // Unique id for each object, equal to its creation number. This value is not coped from other TestObjects during any operations, including moves.
349 	uint32_t        mMagicValue;         // Used to verify that an instance is valid and that it is not corrupted. It should always be kMagicValue.
350 	static int64_t  sTOCount;            // Count of all current existing TestObjects.
351 	static int64_t  sTOCtorCount;        // Count of times any ctor was called.
352 	static int64_t  sTODtorCount;        // Count of times dtor was called.
353 	static int64_t  sTODefaultCtorCount; // Count of times the default ctor was called.
354 	static int64_t  sTOArgCtorCount;     // Count of times the x0,x1,x2 ctor was called.
355 	static int64_t  sTOCopyCtorCount;    // Count of times copy ctor was called.
356 	static int64_t  sTOMoveCtorCount;    // Count of times move ctor was called.
357 	static int64_t  sTOCopyAssignCount;  // Count of times copy assignment was called.
358 	static int64_t  sTOMoveAssignCount;  // Count of times move assignment was called.
359 	static int      sMagicErrorCount;    // Number of magic number mismatch errors.
360 
361 	explicit TestObject(int x = 0, bool bThrowOnCopy = false)
mXTestObject362 		: mX(x), mbThrowOnCopy(bThrowOnCopy), mMagicValue(kMagicValue)
363 	{
364 		++sTOCount;
365 		++sTOCtorCount;
366 		++sTODefaultCtorCount;
367 		mId = sTOCtorCount;
368 	}
369 
370 	// This constructor exists for the purpose of testing variadiac template arguments, such as with the emplace container functions.
371 	TestObject(int x0, int x1, int x2, bool bThrowOnCopy = false)
372 		: mX(x0 + x1 + x2), mbThrowOnCopy(bThrowOnCopy), mMagicValue(kMagicValue)
373 	{
374 		++sTOCount;
375 		++sTOCtorCount;
376 		++sTOArgCtorCount;
377 		mId = sTOCtorCount;
378 	}
379 
TestObjectTestObject380 	TestObject(const TestObject& testObject)
381 		: mX(testObject.mX), mbThrowOnCopy(testObject.mbThrowOnCopy), mMagicValue(testObject.mMagicValue)
382 	{
383 		++sTOCount;
384 		++sTOCtorCount;
385 		++sTOCopyCtorCount;
386 		mId = sTOCtorCount;
387 		if(mbThrowOnCopy)
388 		{
389 			#if EASTL_EXCEPTIONS_ENABLED
390 				throw "Disallowed TestObject copy";
391 			#endif
392 		}
393 	}
394 
395 	// Due to the nature of TestObject, there isn't much special for us to
396 	// do in our move constructor. A move constructor swaps its contents with
397 	// the other object, whhich is often a default-constructed object.
TestObjectTestObject398 	TestObject(TestObject&& testObject)
399 		: mX(testObject.mX), mbThrowOnCopy(testObject.mbThrowOnCopy), mMagicValue(testObject.mMagicValue)
400 	{
401 		++sTOCount;
402 		++sTOCtorCount;
403 		++sTOMoveCtorCount;
404 		mId = sTOCtorCount;  // testObject keeps its mId, and we assign ours anew.
405 		testObject.mX = 0;   // We are swapping our contents with the TestObject, so give it our "previous" value.
406 		if(mbThrowOnCopy)
407 		{
408 			#if EASTL_EXCEPTIONS_ENABLED
409 				throw "Disallowed TestObject copy";
410 			#endif
411 		}
412 	}
413 
414 	TestObject& operator=(const TestObject& testObject)
415 	{
416 		++sTOCopyAssignCount;
417 
418 		if(&testObject != this)
419 		{
420 			mX = testObject.mX;
421 			// Leave mId alone.
422 			mMagicValue = testObject.mMagicValue;
423 			mbThrowOnCopy = testObject.mbThrowOnCopy;
424 			if(mbThrowOnCopy)
425 			{
426 				#if EASTL_EXCEPTIONS_ENABLED
427 					throw "Disallowed TestObject copy";
428 				#endif
429 			}
430 		}
431 		return *this;
432 	}
433 
434 	TestObject& operator=(TestObject&& testObject)
435 	{
436 		++sTOMoveAssignCount;
437 
438 		if(&testObject != this)
439 		{
440 			eastl::swap(mX, testObject.mX);
441 			// Leave mId alone.
442 			eastl::swap(mMagicValue, testObject.mMagicValue);
443 			eastl::swap(mbThrowOnCopy, testObject.mbThrowOnCopy);
444 
445 			if(mbThrowOnCopy)
446 			{
447 				#if EASTL_EXCEPTIONS_ENABLED
448 					throw "Disallowed TestObject copy";
449 				#endif
450 			}
451 		}
452 		return *this;
453 	}
454 
~TestObjectTestObject455 	~TestObject()
456 	{
457 		if(mMagicValue != kMagicValue)
458 			++sMagicErrorCount;
459 		mMagicValue = 0;
460 		--sTOCount;
461 		++sTODtorCount;
462 	}
463 
ResetTestObject464 	static void Reset()
465 	{
466 		sTOCount            = 0;
467 		sTOCtorCount        = 0;
468 		sTODtorCount        = 0;
469 		sTODefaultCtorCount = 0;
470 		sTOArgCtorCount     = 0;
471 		sTOCopyCtorCount    = 0;
472 		sTOMoveCtorCount    = 0;
473 		sTOCopyAssignCount  = 0;
474 		sTOMoveAssignCount  = 0;
475 		sMagicErrorCount    = 0;
476 	}
477 
IsClearTestObject478 	static bool IsClear() // Returns true if there are no existing TestObjects and the sanity checks related to that test OK.
479 	{
480 		return (sTOCount == 0) && (sTODtorCount == sTOCtorCount) && (sMagicErrorCount == 0);
481 	}
482 };
483 
484 // Operators
485 // We specifically define only == and <, in order to verify that
486 // our containers and algorithms are not mistakenly expecting other
487 // operators for the contained and manipulated classes.
488 inline bool operator==(const TestObject& t1, const TestObject& t2)
489 	{ return t1.mX == t2.mX; }
490 
491 inline bool operator<(const TestObject& t1, const TestObject& t2)
492 	{ return t1.mX < t2.mX; }
493 
494 
495 // TestObject hash
496 // Normally you don't want to put your hash functions in the eastl namespace, as that namespace is owned by EASTL.
497 // However, these are the EASTL unit tests and we can say that they are also owned by EASTL.
498 namespace eastl
499 {
500 	template <>
501 	struct hash<TestObject>
502 	{
503 		size_t operator()(const TestObject& a) const
504 			{ return static_cast<size_t>(a.mX); }
505 	};
506 }
507 
508 
509 // use_mX
510 // Used for printing TestObject contents via the PrintSequence function,
511 // which is defined below. See the PrintSequence function for documentation.
512 // This function is an analog of the eastl::use_self and use_first functions.
513 // We declare this all in one line because the user should never need to
514 // debug usage of this function.
515 template <typename T> struct use_mX { int operator()(const T& t) const { return t.mX; } };
516 
517 
518 
519 ///////////////////////////////////////////////////////////////////////////////
520 // SizedPOD
521 //
522 // Exists for the purpose testing PODs that are larger than built-in types.
523 //
524 template <size_t kSize>
525 struct SizedPOD
526 {
527 	char memory[kSize];
528 };
529 
530 
531 
532 ///////////////////////////////////////////////////////////////////////////////
533 /// ConstType
534 ///
535 /// Used to test const type containers (e.g. vector<const ConstType>).
536 ///
537 class ConstType
538 {
539 public:
540 	ConstType(int value) : mDummy(value) {};
541 	int mDummy;
542 };
543 
544 
545 
546 
547 ///////////////////////////////////////////////////////////////////////////////
548 /// TestObjectHash
549 ///
550 /// Implements a manually specified hash function for TestObjects.
551 ///
552 struct TestObjectHash
553 {
554 	size_t operator()(const TestObject& t) const
555 	{
556 		return (size_t)t.mX;
557 	}
558 };
559 
560 
561 
562 
563 
564 ///////////////////////////////////////////////////////////////////////////////
565 /// Align16
566 ///
567 
568 #if defined(EA_PROCESSOR_ARM)
569 	#define kEASTLTestAlign16 8 //ARM processors can only align to 8
570 #else
571 	#define kEASTLTestAlign16 16
572 #endif
573 
574 
575 EA_PREFIX_ALIGN(kEASTLTestAlign16)
576 struct Align16
577 {
578 	explicit Align16(int x = 0) : mX(x) {}
579 	int mX;
580 } EA_POSTFIX_ALIGN(kEASTLTestAlign16);
581 
582 inline bool operator==(const Align16& a, const Align16& b)
583 	{ return (a.mX == b.mX); }
584 
585 inline bool operator<(const Align16& a, const Align16& b)
586 	{ return (a.mX < b.mX); }
587 
588 
589 
590 ///////////////////////////////////////////////////////////////////////////////
591 /// Align32
592 ///
593 #if defined(EA_PROCESSOR_ARM)
594 	#define kEASTLTestAlign32 8 //ARM processors can only align to 8
595 #elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) < 400) // GCC 2.x, 3.x
596 	#define kEASTLTestAlign32 16 // Some versions of GCC fail to support any alignment beyond 16.
597 #else
598 	#define kEASTLTestAlign32 32
599 #endif
600 
601 EA_PREFIX_ALIGN(kEASTLTestAlign32)
602 struct Align32
603 {
604 	explicit Align32(int x = 0) : mX(x) {}
605 	int mX;
606 } EA_POSTFIX_ALIGN(kEASTLTestAlign32);
607 
608 inline bool operator==(const Align32& a, const Align32& b)
609 	{ return (a.mX == b.mX); }
610 
611 inline bool operator<(const Align32& a, const Align32& b)
612 	{ return (a.mX < b.mX); }
613 
614 
615 
616 ///////////////////////////////////////////////////////////////////////////////
617 /// Align64
618 ///
619 /// Used for testing of alignment.
620 ///
621 #if defined(EA_PROCESSOR_ARM)
622 	#define kEASTLTestAlign64 8
623 #elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) < 400) // GCC 2.x, 3.x
624 	#define kEASTLTestAlign64 16 // Some versions of GCC fail to support any alignment beyond 16.
625 #else
626 	#define kEASTLTestAlign64 64
627 #endif
628 
629 EA_PREFIX_ALIGN(kEASTLTestAlign64)
630 struct Align64
631 {
632 	explicit Align64(int x = 0) : mX(x) {}
633 	int mX;
634 } EA_POSTFIX_ALIGN(kEASTLTestAlign64);
635 
636 inline bool operator==(const Align64& a, const Align64& b)
637 	{ return (a.mX == b.mX); }
638 
639 inline bool operator<(const Align64& a, const Align64& b)
640 	{ return (a.mX < b.mX); }
641 
642 namespace eastl
643 {
644 	template <>
645 	struct hash < Align64 >
646 	{
647 		size_t operator()(const Align64& a) const
648 		{
649 			return static_cast<size_t>(a.mX);
650 		}
651 	};
652 }
653 
654 
655 
656 
657 
658 /// test_use_self
659 ///
660 /// Intentionally avoiding a dependency on eastl::use_self.
661 ///
662 template <typename T>
663 struct test_use_self
664 {
665 	const T& operator()(const T& x) const
666 		{ return x; }
667 };
668 
669 
670 
671 /// GenerateIncrementalIntegers
672 ///
673 /// Used to seed containers with incremental values based on integers.
674 ///
675 /// Example usage:
676 ///     vector<int> v(10, 0);
677 ///     generate(v.begin(), v.end(), GenerateIncrementalIntegers<int>());
678 ///     // v will now have 0, 1, 2, ... 8, 9.
679 ///
680 ///     generate_n(intArray.begin(), 10, GenerateIncrementalIntegers<int>());
681 ///     // v will now have 0, 1, 2, ... 8, 9.
682 ///
683 ///     vector<TestObject> vTO(10, 0);
684 ///     generate(vTO.begin(), vTO.end(), GenerateIncrementalIntegers<TestObject>());
685 ///     // vTO will now have 0, 1, 2, ... 8, 9.
686 ///
687 template <typename T>
688 struct GenerateIncrementalIntegers
689 {
690 	int mX;
691 
692 	GenerateIncrementalIntegers(int x = 0)
693 		: mX(x) { }
694 
695 	void reset(int x = 0)
696 		{ mX = x; }
697 
698 	T operator()()
699 		{ return T(mX++); }
700 };
701 
702 
703 
704 /// SetIncrementalIntegers
705 ///
706 /// Used to seed containers with incremental values based on integers.
707 ///
708 /// Example usage:
709 ///     vector<int> v(10, 0);
710 ///     for_each(v.begin(), v.end(), SetIncrementalIntegers<int>());
711 ///     // v will now have 0, 1, 2, ... 8, 9.
712 ///
713 template <typename T>
714 struct SetIncrementalIntegers
715 {
716 	int mX;
717 
718 	SetIncrementalIntegers(int x = 0)
719 		: mX(x) { }
720 
721 	void reset(int x = 0)
722 		{ mX = x; }
723 
724 	void operator()(T& t)
725 		{ t = T(mX++); }
726 };
727 
728 
729 
730 /// CompareContainers
731 ///
732 /// Does a comparison between the contents of two containers.
733 ///
734 /// Specifically tests for the following properties:
735 ///     empty() is the same for both
736 ///     size() is the same for both
737 ///     iteration through both element by element yields equal values.
738 ///
739 template <typename T1, typename T2, typename ExtractValue1, typename ExtractValue2>
740 int CompareContainers(const T1& t1, const T2& t2, const char* ppName,
741 					  ExtractValue1 ev1 = test_use_self<T1>(), ExtractValue2 ev2 = test_use_self<T2>())
742 {
743 	int nErrorCount = 0;
744 
745 	// Compare emptiness.
746 	VERIFY(t1.empty() == t2.empty());
747 
748 	// Compare sizes.
749 	const size_t nSize1 = t1.size();
750 	const size_t nSize2 = t2.size();
751 
752 	VERIFY(nSize1 == nSize2);
753 	if(nSize1 != nSize2)
754 		EASTLTest_Printf("%s: Container size difference: %u, %u\n", ppName, (unsigned)nSize1, (unsigned)nSize2);
755 
756 	// Compare values.
757 	if(nSize1 == nSize2)
758 	{
759 		// Test iteration
760 		typename T1::const_iterator it1 = t1.begin();
761 		typename T2::const_iterator it2 = t2.begin();
762 
763 		for(unsigned j = 0; it1 != t1.end(); ++it1, ++it2, ++j)
764 		{
765 			const typename T1::value_type& v1 = *it1;
766 			const typename T2::value_type& v2 = *it2;
767 
768 			VERIFY(ev1(v1) == ev2(v2));
769 			if(!(ev1(v1) == ev2(v2)))
770 			{
771 				EASTLTest_Printf("%s: Container iterator difference at index %d\n", ppName, j);
772 				break;
773 			}
774 		}
775 
776 		VERIFY(it1 == t1.end());
777 		VERIFY(it2 == t2.end());
778 	}
779 
780 	return nErrorCount;
781 }
782 
783 
784 
785 
786 
787 /// VerifySequence
788 ///
789 /// Allows the user to specify that a container has a given set of values.
790 ///
791 /// Example usage:
792 ///    vector<int> v;
793 ///    v.push_back(1); v.push_back(3); v.push_back(5);
794 ///    VerifySequence(v.begin(), v.end(), int(), "v.push_back", 1, 3, 5, -1);
795 ///
796 /// Note: The StackValue template argument is a hint to the compiler about what type
797 ///       the passed vararg sequence is.
798 ///
799 template <typename InputIterator, typename StackValue>
800 bool VerifySequence(InputIterator first, InputIterator last, StackValue /*unused*/, const char* pName, ...)
801 {
802 	typedef typename eastl::iterator_traits<InputIterator>::value_type value_type;
803 
804 	int        argIndex = 0;
805 	int        seqIndex = 0;
806 	bool       bReturnValue = true;
807 	StackValue next;
808 
809 	va_list args;
810 	va_start(args, pName);
811 
812 	for( ; first != last; ++first, ++argIndex, ++seqIndex)
813 	{
814 		next = va_arg(args, StackValue);
815 
816 		if((next == StackValue(-1)) || !(value_type(next) == *first))
817 		{
818 			if(pName)
819 				EASTLTest_Printf("[%s] Mismatch at index %d\n", pName, argIndex);
820 			else
821 				EASTLTest_Printf("Mismatch at index %d\n", argIndex);
822 			bReturnValue = false;
823 		}
824 	}
825 
826 	for(; first != last; ++first)
827 		++seqIndex;
828 
829 	if(bReturnValue)
830 	{
831 		next = va_arg(args, StackValue);
832 
833 		if(!(next == StackValue(-1)))
834 		{
835 			do {
836 				++argIndex;
837 				next = va_arg(args, StackValue);
838 			} while(!(next == StackValue(-1)));
839 
840 			if(pName)
841 				EASTLTest_Printf("[%s] Too many elements: expected %d, found %d\n", pName, argIndex, seqIndex);
842 			else
843 				EASTLTest_Printf("Too many elements: expected %d, found %d\n", argIndex, seqIndex);
844 			bReturnValue = false;
845 		}
846 	}
847 
848 	va_end(args);
849 
850 	return bReturnValue;
851 }
852 
853 
854 
855 
856 /// PrintSequence
857 ///
858 /// Allows the user to print a sequence of values.
859 ///
860 /// Example usage:
861 ///    vector<int> v;
862 ///    PrintSequence(v.begin(), v.end(), use_self<int>(), 100, "vector", 1, 3, 5, -1);
863 ///
864 /// Example usage:
865 ///    template <typename T> struct use_mX { int operator()(const T& t) const { return t.mX; } };
866 ///    vector<TestObject> v;
867 ///    PrintSequence(v.begin(), v.end(), use_mX<TestObject>(), 100, "vector", 1, 3, 5, -1);
868 ///
869 template <typename InputIterator, typename ExtractInt>
870 void PrintSequence(InputIterator first, InputIterator last, ExtractInt extractInt, int nMaxCount, const char* pName, ...)
871 {
872 	if(pName)
873 		EASTLTest_Printf("[%s]", pName);
874 
875 	for(int i = 0; (i < nMaxCount) && (first != last); ++i, ++first)
876 	{
877 		EASTLTest_Printf("%d ", (int)extractInt(*first));
878 	}
879 
880 	EASTLTest_Printf("\n");
881 }
882 
883 
884 
885 
886 /// demoted_iterator
887 ///
888 /// Converts an iterator into a demoted category. For example, you can convert
889 /// an iterator of type bidirectional_iterator_tag to forward_iterator_tag.
890 /// The following is a list of iterator types. A demonted iterator can be demoted
891 /// only to a lower iterator category (earlier in the following list):
892 ///     input_iterator_tag
893 ///     forward_iterator_tag
894 ///     bidirectional_iterator_tag
895 ///     random_access_iterator_tag
896 ///     contiguous_iterator_tag
897 ///
898 /// Converts something which can be iterated into a formal input iterator.
899 /// This class is useful for testing functions and algorithms that expect
900 /// InputIterators, which are the lowest and 'weakest' form of iterators.
901 ///
902 /// Key traits of InputIterators:
903 ///    Algorithms on input iterators should never attempt to pass
904 ///    through the same iterator twice. They should be single pass
905 ///    algorithms. value_type T is not required to be an lvalue type.
906 ///
907 /// Example usage:
908 ///     typedef demoted_iterator<int*, eastl::bidirectional_iterator_tag>         PointerAsBidirectionalIterator;
909 ///     typedef demoted_iterator<MyVector::iterator, eastl::forward_iterator_tag> VectorIteratorAsForwardIterator;
910 ///
911 /// Example usage:
912 ///     IntVector v;
913 ///     comb_sort(to_forward_iterator(v.begin()), to_forward_iterator(v.end()));
914 ///
915 template <typename Iterator, typename IteratorCategory>
916 class demoted_iterator
917 {
918 protected:
919 	Iterator mIterator;
920 
921 public:
922 	typedef demoted_iterator<Iterator, IteratorCategory>                 this_type;
923 	typedef Iterator                                                     iterator_type;
924 	typedef IteratorCategory                                             iterator_category;
925 	typedef typename eastl::iterator_traits<Iterator>::value_type        value_type;
926 	typedef typename eastl::iterator_traits<Iterator>::difference_type   difference_type;
927 	typedef typename eastl::iterator_traits<Iterator>::reference         reference;
928 	typedef typename eastl::iterator_traits<Iterator>::pointer           pointer;
929 
930 	demoted_iterator()
931 		: mIterator() { }
932 
933 	explicit demoted_iterator(const Iterator& i)
934 		: mIterator(i) { }
935 
936 	demoted_iterator(const this_type& x)
937 		: mIterator(x.mIterator) { }
938 
939 	this_type& operator=(const Iterator& i)
940 		{ mIterator = i; return *this; }
941 
942 	this_type& operator=(const this_type& x)
943 		{ mIterator = x.mIterator; return *this; }
944 
945 	reference operator*() const
946 		{ return *mIterator; }
947 
948 	pointer operator->() const
949 		{ return mIterator; }
950 
951 	this_type& operator++()
952 		{ ++mIterator; return *this; }
953 
954 	this_type operator++(int)
955 		{ return this_type(mIterator++); }
956 
957 	this_type& operator--()
958 		{ --mIterator; return *this; }
959 
960 	this_type operator--(int)
961 		{ return this_type(mIterator--); }
962 
963 	reference operator[](const difference_type& n) const
964 		{ return mIterator[n]; }
965 
966 	this_type& operator+=(const difference_type& n)
967 		{ mIterator += n; return *this; }
968 
969 	this_type operator+(const difference_type& n) const
970 		{ return this_type(mIterator + n); }
971 
972 	this_type& operator-=(const difference_type& n)
973 		{ mIterator -= n; return *this; }
974 
975 	this_type operator-(const difference_type& n) const
976 		{ return this_type(mIterator - n); }
977 
978 	const iterator_type& base() const
979 		{ return mIterator; }
980 
981 }; // class demoted_iterator
982 
983 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
984 inline bool
985 operator==(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
986 	{ return a.base() == b.base(); }
987 
988 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
989 inline bool
990 operator!=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
991 	{ return !(a == b); }
992 
993 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
994 inline bool
995 operator<(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
996 	{ return a.base() < b.base(); }
997 
998 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
999 inline bool
1000 operator<=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
1001 	{ return !(b < a); }
1002 
1003 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
1004 inline bool
1005 operator>(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
1006 	{ return b < a; }
1007 
1008 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
1009 inline bool
1010 operator>=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
1011 	{ return !(a < b); }
1012 
1013 template<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>
1014 inline demoted_iterator<Iterator1, IteratorCategory1>
1015 operator-(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)
1016 	{ return demoted_iterator<Iterator1, IteratorCategory1>(a.base() - b.base()); }
1017 
1018 template<typename Iterator1, typename IteratorCategory1>
1019 inline demoted_iterator<Iterator1, IteratorCategory1>
1020 operator+(typename demoted_iterator<Iterator1, IteratorCategory1>::difference_type n, const demoted_iterator<Iterator1, IteratorCategory1>& a)
1021 	{ return a + n; }
1022 
1023 
1024 // to_xxx_iterator
1025 //
1026 // Returns a demoted iterator
1027 //
1028 template <typename Iterator>
1029 inline demoted_iterator<Iterator, EASTL_ITC_NS::input_iterator_tag>
1030 to_input_iterator(const Iterator& i)
1031 	{ return demoted_iterator<Iterator, EASTL_ITC_NS::input_iterator_tag>(i); }
1032 
1033 template <typename Iterator>
1034 inline demoted_iterator<Iterator, EASTL_ITC_NS::forward_iterator_tag>
1035 to_forward_iterator(const Iterator& i)
1036 	{ return demoted_iterator<Iterator, EASTL_ITC_NS::forward_iterator_tag>(i); }
1037 
1038 template <typename Iterator>
1039 inline demoted_iterator<Iterator, EASTL_ITC_NS::bidirectional_iterator_tag>
1040 to_bidirectional_iterator(const Iterator& i)
1041 	{ return demoted_iterator<Iterator, EASTL_ITC_NS::bidirectional_iterator_tag>(i); }
1042 
1043 template <typename Iterator>
1044 inline demoted_iterator<Iterator, EASTL_ITC_NS::random_access_iterator_tag>
1045 to_random_access_iterator(const Iterator& i)
1046 	{ return demoted_iterator<Iterator, EASTL_ITC_NS::random_access_iterator_tag>(i); }
1047 
1048 
1049 
1050 
1051 
1052 
1053 ///////////////////////////////////////////////////////////////////////////////
1054 // MallocAllocator
1055 //
1056 // Implements an EASTL allocator that uses malloc/free as opposed to
1057 // new/delete or PPMalloc Malloc/Free. This is useful for testing
1058 // allocator behaviour of code.
1059 //
1060 // Example usage:
1061 //      vector<int, MallocAllocator> intVector;
1062 //
1063 class MallocAllocator
1064 {
1065 public:
1066 	MallocAllocator(const char* = EASTL_NAME_VAL("MallocAllocator"))
1067 		: mAllocCount(0), mFreeCount(0), mAllocVolume(0) {}
1068 
1069 	MallocAllocator(const MallocAllocator& x)
1070 		: mAllocCount(x.mAllocCount), mFreeCount(x.mFreeCount), mAllocVolume(x.mAllocVolume) {}
1071 
1072 	MallocAllocator(const MallocAllocator&, const char*) {}
1073 
1074 	MallocAllocator& operator=(const MallocAllocator& x)
1075 	{
1076 		mAllocCount = x.mAllocCount;
1077 		mFreeCount = x.mFreeCount;
1078 		mAllocVolume = x.mAllocVolume;
1079 		return *this;
1080 	}
1081 
1082 	void* allocate(size_t n, int = 0);
1083 	void* allocate(size_t n, size_t, size_t, int = 0); // We don't support alignment, so you can't use this class where alignment is required.
1084 	void deallocate(void* p, size_t n);
1085 
1086 	const char* get_name() const { return "MallocAllocator"; }
1087 	void set_name(const char*) {}
1088 
1089 	static void reset_all()
1090 	{
1091 		mAllocCountAll = 0;
1092 		mFreeCountAll = 0;
1093 		mAllocVolumeAll = 0;
1094 		mpLastAllocation = NULL;
1095 	}
1096 
1097 public:
1098 	int mAllocCount;
1099 	int mFreeCount;
1100 	size_t mAllocVolume;
1101 
1102 	static int mAllocCountAll;
1103 	static int mFreeCountAll;
1104 	static size_t mAllocVolumeAll;
1105 	static void* mpLastAllocation;
1106 };
1107 
1108 inline bool operator==(const MallocAllocator&, const MallocAllocator&) { return true; }
1109 inline bool operator!=(const MallocAllocator&, const MallocAllocator&) { return false; }
1110 
1111 
1112 ///////////////////////////////////////////////////////////////////////////////
1113 // CustomAllocator
1114 //
1115 // Implements an allocator that works just like eastl::allocator but is defined
1116 // within this test as opposed to within EASTL.
1117 //
1118 // Example usage:
1119 //      vector<int, CustomAllocator> intVector;
1120 //
1121 class CustomAllocator
1122 {
1123 public:
1124 	CustomAllocator(const char* = NULL) {}
1125 	CustomAllocator(const CustomAllocator&) {}
1126 	CustomAllocator(const CustomAllocator&, const char*) {}
1127 	CustomAllocator& operator=(const CustomAllocator&) { return *this; }
1128 
1129 	void* allocate(size_t n, int flags = 0);
1130 	void* allocate(size_t n, size_t, size_t, int flags = 0);
1131 	void deallocate(void* p, size_t n);
1132 
1133 	const char* get_name() const { return "CustomAllocator"; }
1134 	void set_name(const char*) {}
1135 };
1136 
1137 inline bool operator==(const CustomAllocator&, const CustomAllocator&) { return true; }
1138 inline bool operator!=(const CustomAllocator&, const CustomAllocator&) { return false; }
1139 
1140 
1141 ///////////////////////////////////////////////////////////////////////////////
1142 /// UnequalAllocator
1143 ///
1144 /// Acts the same as eastl::allocator, but always compares as unequal to an
1145 /// instance of itself.
1146 ///
1147 class UnequalAllocator
1148 {
1149 public:
1150 	EASTL_ALLOCATOR_EXPLICIT UnequalAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))
1151 	    : mAllocator(pName) {}
1152 
1153 	UnequalAllocator(const UnequalAllocator& x) : mAllocator(x.mAllocator) {}
1154 	UnequalAllocator(const UnequalAllocator& x, const char* pName) : mAllocator(x.mAllocator) { set_name(pName); }
1155 	UnequalAllocator& operator=(const UnequalAllocator& x)
1156 	{
1157 		mAllocator = x.mAllocator;
1158 		return *this;
1159 	}
1160 
1161 	void* allocate(size_t n, int flags = 0) { return mAllocator.allocate(n, flags); }
1162 	void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0) { return mAllocator.allocate(n, alignment, offset, flags); }
1163 	void deallocate(void* p, size_t n) { return mAllocator.deallocate(p, n); }
1164 
1165 	const char* get_name() const { return mAllocator.get_name(); }
1166 	void set_name(const char* pName) { mAllocator.set_name(pName); }
1167 
1168 protected:
1169 	eastl::allocator mAllocator;
1170 };
1171 
1172 inline bool operator==(const UnequalAllocator&, const UnequalAllocator&) { return false; }
1173 inline bool operator!=(const UnequalAllocator&, const UnequalAllocator&) { return true; }
1174 
1175 
1176 ///////////////////////////////////////////////////////////////////////////////
1177 /// CountingAllocator
1178 ///
1179 /// Counts allocation events allowing unit tests to validate assumptions.
1180 ///
1181 class CountingAllocator : public eastl::allocator
1182 {
1183 public:
1184 	using base_type = eastl::allocator;
1185 
1186 	EASTL_ALLOCATOR_EXPLICIT CountingAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))
1187 	    : base_type(pName)
1188 	{
1189 		totalCtorCount++;
1190 		defaultCtorCount++;
1191 	}
1192 
1193 	CountingAllocator(const CountingAllocator& x) : base_type(x)
1194 	{
1195 		totalCtorCount++;
1196 		copyCtorCount++;
1197 	}
1198 
1199 	CountingAllocator(const CountingAllocator& x, const char* pName) : base_type(x)
1200 	{
1201 		totalCtorCount++;
1202 		copyCtorCount++;
1203 		set_name(pName);
1204 	}
1205 
1206 	CountingAllocator& operator=(const CountingAllocator& x)
1207 	{
1208 		base_type::operator=(x);
1209 		assignOpCount++;
1210 		return *this;
1211 	}
1212 
1213 	virtual void* allocate(size_t n, int flags = 0)
1214 	{
1215 		activeAllocCount++;
1216 		totalAllocCount++;
1217 		totalAllocatedMemory += n;
1218 		activeAllocatedMemory += n;
1219 		return base_type::allocate(n, flags);
1220 	}
1221 
1222 	virtual void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)
1223 	{
1224 		activeAllocCount++;
1225 		totalAllocCount++;
1226 		totalAllocatedMemory += n;
1227 		activeAllocatedMemory += n;
1228 		return base_type::allocate(n, alignment, offset, flags);
1229 	}
1230 
1231 	void deallocate(void* p, size_t n)
1232 	{
1233 		activeAllocCount--;
1234 		totalDeallocCount--;
1235 		activeAllocatedMemory -= n;
1236 		return base_type::deallocate(p, n);
1237 	}
1238 
1239 	const char* get_name() const          { return base_type::get_name(); }
1240 	void set_name(const char* pName)      { base_type::set_name(pName); }
1241 
1242 	static auto getTotalAllocationCount()  { return totalAllocCount; }
1243 	static auto getTotalAllocationSize()   { return totalAllocatedMemory; }
1244 	static auto getActiveAllocationSize()  { return activeAllocatedMemory; }
1245 	static auto getActiveAllocationCount() { return activeAllocCount; }
1246 	static auto neverUsed()				   { return totalAllocCount == 0; }
1247 
1248 	static void resetCount()
1249 	{
1250 		activeAllocCount      = 0;
1251 		totalAllocCount       = 0;
1252 		totalDeallocCount     = 0;
1253 		totalCtorCount        = 0;
1254 		defaultCtorCount      = 0;
1255 		copyCtorCount         = 0;
1256 		assignOpCount         = 0;
1257 		totalAllocatedMemory  = 0;
1258 		activeAllocatedMemory = 0;
1259 	}
1260 
1261 	static uint64_t activeAllocCount;
1262 	static uint64_t totalAllocCount;
1263 	static uint64_t totalDeallocCount;
1264 	static uint64_t totalCtorCount;
1265 	static uint64_t defaultCtorCount;
1266 	static uint64_t copyCtorCount;
1267 	static uint64_t assignOpCount;
1268 	static uint64_t totalAllocatedMemory;  // the total amount of memory allocated
1269 	static uint64_t activeAllocatedMemory; // currently allocated memory by allocator
1270 };
1271 
1272 inline bool operator==(const CountingAllocator& rhs, const CountingAllocator& lhs) { return operator==(CountingAllocator::base_type(rhs), CountingAllocator::base_type(lhs)); }
1273 inline bool operator!=(const CountingAllocator& rhs, const CountingAllocator& lhs) { return !(rhs == lhs); }
1274 
1275 
1276 
1277 
1278 ///////////////////////////////////////////////////////////////////////////////
1279 // InstanceAllocator
1280 //
1281 // Implements an allocator which has a instance id that makes it different
1282 // from other InstanceAllocators of a different id. Allocations between
1283 // InstanceAllocators of different ids are incompatible. An allocation done
1284 // by an InstanceAllocator of id=0 cannot be freed by an InstanceAllocator
1285 // of id=1.
1286 //
1287 // Example usage:
1288 //         InstanceAllocator ia0((uint8_t)0);
1289 //         InstanceAllocator ia1((uint8_t)1);
1290 //
1291 //         eastl::list<int, InstanceAllocator> list0(1, ia0);
1292 //         eastl::list<int, InstanceAllocator> list1(1, ia1);
1293 //
1294 //         list0 = list1; // list0 cannot free it's current contents with list1's allocator, and InstanceAllocator's purpose is to detect if it mistakenly does so.
1295 //
1296 class InstanceAllocator
1297 {
1298 public:
1299 	enum
1300 	{
1301 		kMultiplier = 16
1302 	}; // Use 16 because it's the highest currently known platform alignment requirement.
1303 
1304 	InstanceAllocator(const char* = NULL, uint8_t instanceId = 0) : mInstanceId(instanceId) {}
1305 	InstanceAllocator(uint8_t instanceId) : mInstanceId(instanceId) {}
1306 	InstanceAllocator(const InstanceAllocator& x) : mInstanceId(x.mInstanceId) {}
1307 	InstanceAllocator(const InstanceAllocator& x, const char*) : mInstanceId(x.mInstanceId) {}
1308 
1309 	InstanceAllocator& operator=(const InstanceAllocator& x)
1310 	{
1311 		mInstanceId = x.mInstanceId;
1312 		return *this;
1313 	}
1314 
1315 	void* allocate(size_t n, int = 0)
1316 	{ // +1 so that we always have space to write mInstanceId.
1317 		uint8_t* p8 =
1318 		    static_cast<uint8_t*>(malloc(n + (kMultiplier * (mInstanceId + 1)))); // We make allocations between
1319 		                                                                          // different instances incompatible by
1320 		                                                                          // tweaking their return values.
1321 		eastl::fill(p8, p8 + kMultiplier, 0xff);
1322 		EA_ANALYSIS_ASSUME(p8 != NULL);
1323 		*p8 = mInstanceId;
1324 		return p8 + (kMultiplier * (mInstanceId + 1));
1325 	}
1326 
1327 	void* allocate(size_t n, size_t, size_t, int = 0)
1328 	{ // +1 so that we always have space to write mInstanceId.
1329 		uint8_t* p8 =
1330 		    static_cast<uint8_t*>(malloc(n + (kMultiplier * (mInstanceId + 1)))); // We make allocations between
1331 		                                                                          // different instances incompatible by
1332 		                                                                          // tweaking their return values.
1333 		eastl::fill(p8, p8 + kMultiplier, 0xff);
1334 		EA_ANALYSIS_ASSUME(p8 != NULL);
1335 		*p8 = mInstanceId;
1336 		return p8 + (kMultiplier * (mInstanceId + 1));
1337 	}
1338 
1339 	void deallocate(void* p, size_t /*n*/)
1340 	{
1341 		uint8_t* p8 = static_cast<uint8_t*>(p) - (kMultiplier * (mInstanceId + 1));
1342 		EASTL_ASSERT(*p8 == mInstanceId); // mInstanceId must match the id used in allocate(), otherwise the behavior is
1343 		                                  // undefined (probably a heap assert).
1344 		if (*p8 == mInstanceId) // It's possible that *p8 coincidentally matches mInstanceId if p8 is offset into memory
1345 		                        // we don't control.
1346 			free(p8);
1347 		else
1348 			++mMismatchCount;
1349 	}
1350 
1351 	const char* get_name()
1352 	{
1353 		sprintf(mName, "InstanceAllocator %u", mInstanceId);
1354 		return mName;
1355 	}
1356 
1357 	void set_name(const char*) {}
1358 
1359 	static void reset_all() { mMismatchCount = 0; }
1360 
1361 public:
1362 	uint8_t mInstanceId;
1363 	char mName[32];
1364 
1365 	static int mMismatchCount;
1366 };
1367 
1368 inline bool operator==(const InstanceAllocator& a, const InstanceAllocator& b) { return (a.mInstanceId == b.mInstanceId); }
1369 inline bool operator!=(const InstanceAllocator& a, const InstanceAllocator& b) { return (a.mInstanceId != b.mInstanceId); }
1370 
1371 
1372 ///////////////////////////////////////////////////////////////////////////////
1373 // ThrowingAllocator
1374 //
1375 // Implements an EASTL allocator that uses malloc/free as opposed to
1376 // new/delete or PPMalloc Malloc/Free. This is useful for testing
1377 // allocator behaviour of code.
1378 //
1379 // Example usage:
1380 //      vector<int, ThrowingAllocator< false<> > intVector;
1381 //
1382 template <bool initialShouldThrow = true>
1383 class ThrowingAllocator
1384 {
1385 public:
1386 	ThrowingAllocator(const char* = EASTL_NAME_VAL("ThrowingAllocator")) : mbShouldThrow(initialShouldThrow) {}
1387 	ThrowingAllocator(const ThrowingAllocator& x) : mbShouldThrow(x.mbShouldThrow) {}
1388 	ThrowingAllocator(const ThrowingAllocator& x, const char*) : mbShouldThrow(x.mbShouldThrow) {}
1389 
1390 	ThrowingAllocator& operator=(const ThrowingAllocator& x)
1391 	{
1392 		mbShouldThrow = x.mbShouldThrow;
1393 		return *this;
1394 	}
1395 
1396 	void* allocate(size_t n, int = 0)
1397 	{
1398 #if EASTL_EXCEPTIONS_ENABLED
1399 		if (mbShouldThrow)
1400 			throw std::bad_alloc();
1401 #endif
1402 		return malloc(n);
1403 	}
1404 
1405 	void* allocate(size_t n, size_t, size_t, int = 0)
1406 	{
1407 #if EASTL_EXCEPTIONS_ENABLED
1408 		if (mbShouldThrow)
1409 			throw std::bad_alloc();
1410 #endif
1411 		return malloc(n); // We don't support alignment, so you can't use this class where alignment is required.
1412 	}
1413 
1414 	void deallocate(void* p, size_t) { free(p); }
1415 
1416 	const char* get_name() const { return "ThrowingAllocator"; }
1417 	void set_name(const char*) {}
1418 
1419 	void set_should_throw(bool shouldThrow) { mbShouldThrow = shouldThrow; }
1420 	bool get_should_throw() const { return mbShouldThrow; }
1421 
1422 protected:
1423 	bool mbShouldThrow;
1424 };
1425 
1426 template <bool initialShouldThrow>
1427 inline bool operator==(const ThrowingAllocator<initialShouldThrow>&, const ThrowingAllocator<initialShouldThrow>&)
1428 {
1429 	return true;
1430 }
1431 
1432 template <bool initialShouldThrow>
1433 inline bool operator!=(const ThrowingAllocator<initialShouldThrow>&, const ThrowingAllocator<initialShouldThrow>&)
1434 {
1435 	return false;
1436 }
1437 
1438 
1439 ///////////////////////////////////////////////////////////////////////////////
1440 // Helper utility that does a case insensitive string comparsion with two sets of overloads
1441 //
1442 struct TestStrCmpI_2
1443 {
1444 	bool operator()(const char* pCStr, const eastl::string& str) const { return str.comparei(pCStr) == 0; }
1445 	bool operator()(const eastl::string& str, const char* pCStr) const { return str.comparei(pCStr) == 0; }
1446 };
1447 
1448 
1449 ///////////////////////////////////////////////////////////////////////////////
1450 // StompDetectAllocator
1451 //
1452 // An allocator that has sentinal values surrounding its allocator in an
1453 // effort to detected if its internal memory has been stomped.
1454 //
1455 static uint64_t STOMP_MAGIC_V1 = 0x0101DEC1A551F1ED;
1456 static uint64_t STOMP_MAGIC_V2 = 0x12345C1A551F1ED5;
1457 
1458 struct StompDetectAllocator
1459 {
1460 	StompDetectAllocator() { Validate(); }
1461 	~StompDetectAllocator() { Validate(); }
1462 
1463 	StompDetectAllocator(const char*) { Validate(); }
1464 
1465 	void* allocate(size_t n, int = 0) { return mMallocAllocator.allocate(n); }
1466 	void* allocate(size_t n, size_t, size_t, int = 0) { return mMallocAllocator.allocate(n); }
1467 	void deallocate(void* p, size_t n) { mMallocAllocator.deallocate(p, n); }
1468 
1469 	const char* get_name() const { return "FatAllocator"; }
1470 	void set_name(const char*) {}
1471 
1472 	void Validate() const
1473 	{
1474 		EASTL_ASSERT(mSentinal1 == STOMP_MAGIC_V1);
1475 		EASTL_ASSERT(mSentinal2 == STOMP_MAGIC_V2);
1476 	}
1477 
1478 	uint64_t mSentinal1 = STOMP_MAGIC_V1;
1479 	MallocAllocator mMallocAllocator;
1480 	uint64_t mSentinal2 = STOMP_MAGIC_V2;
1481 };
1482 
1483 inline bool operator==(const StompDetectAllocator& a, const StompDetectAllocator& b)
1484 {
1485 	a.Validate();
1486 	b.Validate();
1487 
1488 	return (a.mMallocAllocator == b.mMallocAllocator);
1489 }
1490 
1491 inline bool operator!=(const StompDetectAllocator& a, const StompDetectAllocator& b)
1492 {
1493 	a.Validate();
1494 	b.Validate();
1495 
1496 	return (a.mMallocAllocator != b.mMallocAllocator);
1497 }
1498 
1499 
1500 // Commonly used free-standing functions to test callables
1501 inline int ReturnVal(int param) { return param; }
1502 inline int ReturnZero() { return 0; }
1503 inline int ReturnOne() { return 1; }
1504 
1505 
1506 // ValueInit
1507 template<class T>
1508 struct ValueInitOf
1509 {
1510 	ValueInitOf() : mV() {}
1511 	~ValueInitOf() = default;
1512 
1513 	ValueInitOf(const ValueInitOf&) = default;
1514 	ValueInitOf(ValueInitOf&&) = default;
1515 
1516 	ValueInitOf& operator=(const ValueInitOf&) = default;
1517 	ValueInitOf& operator=(ValueInitOf&&) = default;
1518 
1519 	T get() { return mV; }
1520 
1521 	T mV;
1522 };
1523 
1524 // MoveOnlyType - useful for verifying containers that may hold, e.g., unique_ptrs to make sure move ops are implemented
1525 struct MoveOnlyType
1526 {
1527 	MoveOnlyType() = delete;
1528 	MoveOnlyType(int val) : mVal(val) {}
1529 	MoveOnlyType(const MoveOnlyType&) = delete;
1530 	MoveOnlyType(MoveOnlyType&& x) : mVal(x.mVal) { x.mVal = 0; }
1531 	MoveOnlyType& operator=(const MoveOnlyType&) = delete;
1532 	MoveOnlyType& operator=(MoveOnlyType&& x)
1533 	{
1534 		mVal = x.mVal;
1535 		x.mVal = 0;
1536 		return *this;
1537 	}
1538 	bool operator==(const MoveOnlyType& o) const { return mVal == o.mVal; }
1539 
1540 	int mVal;
1541 };
1542 
1543 // MoveOnlyTypeDefaultCtor - useful for verifying containers that may hold, e.g., unique_ptrs to make sure move ops are implemented
1544 struct MoveOnlyTypeDefaultCtor
1545 {
1546 	MoveOnlyTypeDefaultCtor() = default;
1547 	MoveOnlyTypeDefaultCtor(int val) : mVal(val) {}
1548 	MoveOnlyTypeDefaultCtor(const MoveOnlyTypeDefaultCtor&) = delete;
1549 	MoveOnlyTypeDefaultCtor(MoveOnlyTypeDefaultCtor&& x) : mVal(x.mVal) { x.mVal = 0; }
1550 	MoveOnlyTypeDefaultCtor& operator=(const MoveOnlyTypeDefaultCtor&) = delete;
1551 	MoveOnlyTypeDefaultCtor& operator=(MoveOnlyTypeDefaultCtor&& x)
1552 	{
1553 		mVal = x.mVal;
1554 		x.mVal = 0;
1555 		return *this;
1556 	}
1557 	bool operator==(const MoveOnlyTypeDefaultCtor& o) const { return mVal == o.mVal; }
1558 
1559 	int mVal;
1560 };
1561 
1562 
1563 
1564 //////////////////////////////////////////////////////////////////////////////
1565 // Utility RAII class that sets a new default allocator for the scope
1566 //
1567 struct AutoDefaultAllocator
1568 {
1569 	eastl::allocator* mPrevAllocator = nullptr;
1570 
1571 	AutoDefaultAllocator(eastl::allocator* nextAllocator) { mPrevAllocator = SetDefaultAllocator(nextAllocator); }
1572 	~AutoDefaultAllocator()                               { SetDefaultAllocator(mPrevAllocator); }
1573 };
1574 
1575 
1576 #endif // Header include guard
1577 
1578 
1579 
1580 
1581 
1582 
1583 
1584