diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2021-04-08 16:43:58 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2021-04-08 16:43:58 +0200 |
commit | a3c405074db4c53e9da042a8772135fb9bf6caa2 (patch) | |
tree | 3417be8827d1eed95a415e7ee68dbc4263085405 /EASTL/test/source/TestFixedHash.cpp | |
parent | ac1b72946c226eb3cd4f3f0b8f13a8330142ebe8 (diff) | |
parent | e59cf7b09e7388d369e8d2bf73501cde79c28708 (diff) |
Merge commit 'e59cf7b09e7388d369e8d2bf73501cde79c28708' as 'EASTL'
Diffstat (limited to 'EASTL/test/source/TestFixedHash.cpp')
-rw-r--r-- | EASTL/test/source/TestFixedHash.cpp | 744 |
1 files changed, 744 insertions, 0 deletions
diff --git a/EASTL/test/source/TestFixedHash.cpp b/EASTL/test/source/TestFixedHash.cpp new file mode 100644 index 0000000..d7e20d0 --- /dev/null +++ b/EASTL/test/source/TestFixedHash.cpp @@ -0,0 +1,744 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) Electronic Arts Inc. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + + +#include <EABase/eabase.h> +#include "EASTLTest.h" +#include "TestMap.h" +#include "TestSet.h" +#include <EASTL/fixed_hash_set.h> +#include <EASTL/fixed_hash_map.h> +#include <EASTL/fixed_vector.h> + + + + +using namespace eastl; + + +struct A +{ + int mX; + A(int x = 999) : mX(x) {} +}; + +inline bool operator==(const A& a1, const A& a2) + { return a1.mX == a2.mX; } + + + +namespace eastl +{ + template <> + struct hash<A> + { + size_t operator()(const A& a) const + { return static_cast<size_t>(a.mX); } + }; +} + + +/////////////////////////////////////////////////////////////////////////////// +// For test of user-reported crash. +// +struct MemoryEntry +{ + size_t mSize; + void* mGroup; +}; +/////////////////////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////////////////////// +// For test of bug reported by Dave Wall, May 14, 2008. +// +struct InstanceRenderData +{ + static const uint32_t kDataCount = 10; // Bug only occurs with this value. + + uint32_t mPad[kDataCount]; + + InstanceRenderData() + { + memset(mPad, 0, sizeof(mPad)); + } + + bool operator==(const InstanceRenderData &rhs) const + { + for(uint32_t index = 0; index < kDataCount; index++) + { + if(mPad[index] != rhs.mPad[index]) + { + return false; + } + } + + return true; + } +}; + +namespace eastl +{ + template <> + struct hash<const InstanceRenderData> + { + size_t operator()(InstanceRenderData val) const + { + return val.mPad[0]; + } + }; + + template <> + struct hash<InstanceRenderData> + { + size_t operator()(InstanceRenderData val) const + { + return val.mPad[0]; + } + }; +} +/////////////////////////////////////////////////////////////////////////////// + + + +// Template instantations. +// These tell the compiler to compile all the functions for the given class. +template class eastl::fixed_hash_set<int, 1, 2>; +template class eastl::fixed_hash_map<int, int, 1, 2>; +template class eastl::fixed_hash_multiset<int, 1, 2>; +template class eastl::fixed_hash_multimap<int, int, 1, 2>; + +template class eastl::fixed_hash_set<A, 1, 2>; +template class eastl::fixed_hash_map<A, A, 1, 2>; +template class eastl::fixed_hash_multiset<A, 1, 2>; +template class eastl::fixed_hash_multimap<A, A, 1, 2>; + +template class eastl::fixed_hash_set<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>; +template class eastl::fixed_hash_map<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>; +template class eastl::fixed_hash_multiset<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>; +template class eastl::fixed_hash_multimap<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>; + +template class eastl::fixed_hash_set<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>; +template class eastl::fixed_hash_map<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>; +template class eastl::fixed_hash_multiset<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>; +template class eastl::fixed_hash_multimap<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>; + +// Custom allocator +template class eastl::fixed_hash_set<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>; +template class eastl::fixed_hash_map<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>; +template class eastl::fixed_hash_multiset<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>; +template class eastl::fixed_hash_multimap<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>; + +template class eastl::fixed_hash_set<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>; +template class eastl::fixed_hash_map<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>; +template class eastl::fixed_hash_multiset<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>; +template class eastl::fixed_hash_multimap<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>; + + + +template<typename FixedHashMap, int ELEMENT_MAX, int ITERATION_MAX> +int TestFixedHashMapClearBuckets() +{ + int nErrorCount = 0; + + FixedHashMap fixedHashMap; + const auto nPreClearBucketCount = fixedHashMap.bucket_count(); + + for (int j = 0; j < ITERATION_MAX; j++) + { + // add elements and ensure container is valid + for (int i = 0; i < int(nPreClearBucketCount); i++) + fixedHashMap.emplace(i, i); + VERIFY(fixedHashMap.validate()); + + // ensure contents are expected values + for (int i = 0; i < int(nPreClearBucketCount); i++) + { + auto iter = fixedHashMap.find(i); + + VERIFY(iter != fixedHashMap.end()); + VERIFY(iter->second == i); + } + + // validate container after its cleared its nodes and buckets + fixedHashMap.clear(true); + VERIFY(fixedHashMap.validate()); + VERIFY(fixedHashMap.size() == 0); + VERIFY(fixedHashMap.bucket_count() == nPreClearBucketCount); + } + + return nErrorCount; +} + + +EA_DISABLE_VC_WARNING(6262) +int TestFixedHash() +{ + int nErrorCount = 0; + + { // fixed_hash_map + { + // Test version *without* pool overflow. + typedef eastl::fixed_hash_map<int, int, 100, 100, false> FixedHashMapFalse; + FixedHashMapFalse fixedHashMap; + + fixedHashMap[0] = 0; + fixedHashMap.insert(FixedHashMapFalse::value_type(0, 0)); + + VERIFY(fixedHashMap.max_size() == 100); + VERIFY(fixedHashMap.size() == 1); + + fixedHashMap.clear(); + VERIFY(fixedHashMap.size() == 0); + + for(int i = 0; i < 100; i++) + fixedHashMap.insert(FixedHashMapFalse::value_type(i, i)); + VERIFY(fixedHashMap.size() == 100); + + // Verify that we allocated enough space for exactly N items. + // It's possible that due to alignments, there might be room for N + 1. + FixedHashMapFalse::allocator_type& allocator = fixedHashMap.get_allocator(); + void* pResult = allocator.allocate(sizeof(FixedHashMapFalse::node_type)); + if(pResult) + { + pResult = allocator.allocate(sizeof(FixedHashMapFalse::node_type)); + VERIFY(pResult == NULL); + } + + fixedHashMap.clear(true); + VERIFY(fixedHashMap.validate()); + VERIFY(fixedHashMap.size() == 0); + VERIFY(fixedHashMap.bucket_count() == fixedHashMap.rehash_policy().GetPrevBucketCount(100)); + } + + { + // Test version *with* pool overflow. + typedef eastl::fixed_hash_map<int, int, 100, 100, true> FixedHashMapTrue; + FixedHashMapTrue fixedHashMap; + + fixedHashMap[0] = 0; + fixedHashMap.insert(FixedHashMapTrue::value_type(0, 0)); + + VERIFY(fixedHashMap.max_size() == 100); + VERIFY(fixedHashMap.size() == 1); + + fixedHashMap.clear(); + VERIFY(fixedHashMap.size() == 0); + + for(int i = 0; i < 100; i++) + fixedHashMap.insert(FixedHashMapTrue::value_type(i, i)); + VERIFY(fixedHashMap.size() == 100); + + FixedHashMapTrue::allocator_type& allocator = fixedHashMap.get_allocator(); + void* pResult = allocator.allocate(sizeof(FixedHashMapTrue::node_type)); + VERIFY(pResult != NULL); + allocator.deallocate(pResult, sizeof(FixedHashMapTrue::node_type)); + + fixedHashMap.clear(true); + VERIFY(fixedHashMap.validate()); + VERIFY(fixedHashMap.size() == 0); + VERIFY(fixedHashMap.bucket_count() == fixedHashMap.rehash_policy().GetPrevBucketCount(100)); + + // get_overflow_allocator / set_overflow_allocator + // This is a weak test which should be improved. + EASTLAllocatorType a = fixedHashMap.get_allocator().get_overflow_allocator(); + fixedHashMap.get_allocator().set_overflow_allocator(a); + } + + // Test that fixed_hash_map (with and without overflow enabled) is usable after the node and bucket array has + // been cleared. + { + constexpr const int ITERATION_MAX = 5; + constexpr const int ELEMENT_MAX = 100; + constexpr const int ELEMENT_OVERFLOW_MAX = ELEMENT_MAX * 2; + + TestFixedHashMapClearBuckets<eastl::fixed_hash_map<int, int, ELEMENT_MAX, ELEMENT_MAX, false>, ELEMENT_MAX, ITERATION_MAX>(); + TestFixedHashMapClearBuckets<eastl::fixed_hash_map<int, int, ELEMENT_MAX, ELEMENT_MAX, true>, ELEMENT_OVERFLOW_MAX, ITERATION_MAX>(); + TestFixedHashMapClearBuckets<eastl::fixed_hash_multimap<int, int, ELEMENT_MAX, ELEMENT_MAX, false>, ELEMENT_MAX, ITERATION_MAX>(); + TestFixedHashMapClearBuckets<eastl::fixed_hash_multimap<int, int, ELEMENT_MAX, ELEMENT_MAX, true>, ELEMENT_OVERFLOW_MAX, ITERATION_MAX>(); + } + + { + // Test fixed_hash_map *with* overflow and ensure the underlying hashtable rehashes. + typedef eastl::fixed_hash_map<unsigned int, unsigned int, 512, 513, true, eastl::hash<unsigned int>, eastl::equal_to<unsigned int>, false, MallocAllocator> FixedHashMap; + + FixedHashMap fixedHashMap; + auto old_bucket_count = fixedHashMap.bucket_count(); + auto old_load_factor = fixedHashMap.load_factor(); + + for (int i = 0; i < 1000; i++) + fixedHashMap.insert(i); + + auto new_bucket_count = fixedHashMap.bucket_count(); + auto new_load_factor = fixedHashMap.load_factor(); + + VERIFY(new_bucket_count != old_bucket_count); + VERIFY(new_bucket_count > old_bucket_count); + VERIFY(new_load_factor != old_load_factor); + VERIFY(fixedHashMap.get_overflow_allocator().mAllocCountAll != 0); + } + + { + // Test version with overflow and alignment requirements. + typedef fixed_hash_map<Align64, int, 1, 2, true> FixedHashMapWithAlignment; + typedef fixed_hash_multimap<Align64, int, 1, 2, true> FixedHashMultiMapWithAlignment; + typedef fixed_hash_set<Align64, 1, 2, true> FixedHashSetWithAlignment; + typedef fixed_hash_multiset<Align64, 1, 2, true> FixedHashMultiSetWithAlignment; + + FixedHashMapWithAlignment fhm; + FixedHashMultiMapWithAlignment fhmm; + FixedHashSetWithAlignment fhs; + FixedHashMultiSetWithAlignment fhms; + + Align64 a; a.mX = 1; + Align64 b; b.mX = 2; + Align64 c; c.mX = 3; + Align64 d; d.mX = 4; + Align64 e; e.mX = 5; + + fhm.insert(a); + fhm.insert(b); + fhm.insert(c); + fhm.insert(d); + fhm.insert(e); + for (FixedHashMapWithAlignment::const_iterator it = fhm.begin(); it != fhm.end(); ++it) + { + const Align64* ptr = &((*it).first); + EATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0); + } + fhmm.insert(a); + fhmm.insert(b); + fhmm.insert(c); + fhmm.insert(d); + fhmm.insert(e); + for (FixedHashMultiMapWithAlignment::const_iterator it = fhmm.begin(); it != fhmm.end(); ++it) + { + const Align64* ptr = &((*it).first); + EATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0); + } + fhs.insert(a); + fhs.insert(b); + fhs.insert(c); + fhs.insert(d); + fhs.insert(e); + for (FixedHashSetWithAlignment::const_iterator it = fhs.begin(); it != fhs.end(); ++it) + { + const Align64* ptr = &(*it); + EATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0); + } + fhms.insert(a); + fhms.insert(b); + fhms.insert(c); + fhms.insert(d); + fhms.insert(e); + for (FixedHashMultiSetWithAlignment::const_iterator it = fhms.begin(); it != fhms.end(); ++it) + { + const Align64* ptr = &(*it); + EATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0); + } + } + + { + typedef eastl::fixed_hash_map<int, A, 100, 100> FixedHashMap; + FixedHashMap fixedHashMap; + + fixedHashMap[0] = A(); + fixedHashMap.insert(FixedHashMap::value_type(0, A())); + + VERIFY(fixedHashMap.size() == 1); + } + + { + typedef eastl::fixed_hash_map<A, int, 100, 100> FixedHashMap; + FixedHashMap fixedHashMap; + + fixedHashMap[A()] = 0; + fixedHashMap.insert(FixedHashMap::value_type(A(), 0)); + + VERIFY(fixedHashMap.size() == 1); + } + + // explicitly instantiate some templated member functions + { + typedef eastl::fixed_hash_map<int, int, 100, 100, true> FixedHashMapTrue; + FixedHashMapTrue::value_type testValues[] = { eastl::make_pair(0, 0), eastl::make_pair(1,1) }; + FixedHashMapTrue fixedHashMap(testValues, testValues + EAArrayCount(testValues)); + VERIFY(fixedHashMap.size() == 2); + } + } + + + { // fixed_hash_multimap + { + typedef eastl::fixed_hash_multimap<int, int, 100, 100> FixedHashMultiMap; + FixedHashMultiMap fixedHashMultiMap; + + fixedHashMultiMap.insert(FixedHashMultiMap::value_type(0, 0)); + fixedHashMultiMap.insert(FixedHashMultiMap::value_type(0, 0)); + + VERIFY(fixedHashMultiMap.max_size() == 100); + VERIFY(fixedHashMultiMap.size() == 2); + } + + // explicitly instantiate some templated member functions + { + typedef eastl::fixed_hash_multimap<int, int, 100, 100, true> FixedHashMultiMap; + FixedHashMultiMap::value_type testValues[] = { eastl::make_pair(0, 0), eastl::make_pair(1,1) }; + FixedHashMultiMap fixedHashMultiMap(testValues, testValues + EAArrayCount(testValues)); + VERIFY(fixedHashMultiMap.size() == 2); + } + } + + + { // fixed_hash_set + { + typedef eastl::fixed_hash_set<int, 100, 100> FixedHashSet; + FixedHashSet fixedHashSet; + + fixedHashSet.insert(0); + fixedHashSet.insert(0); + VERIFY(fixedHashSet.size() == 1); + + fixedHashSet.clear(); + VERIFY(fixedHashSet.size() == 0); + + for(int i = 0; i < 100; i++) + fixedHashSet.insert(i); + + VERIFY(fixedHashSet.max_size() == 100); + VERIFY(fixedHashSet.size() == 100); + + fixedHashSet.clear(true); + VERIFY(fixedHashSet.validate()); + VERIFY(fixedHashSet.size() == 0); + VERIFY(fixedHashSet.bucket_count() == 1); + } + + { + typedef eastl::fixed_hash_set<A, 100, 100> FixedHashSet; + FixedHashSet fixedHashSet; + + fixedHashSet.insert(A()); + fixedHashSet.insert(A()); + + VERIFY(fixedHashSet.max_size() == 100); + VERIFY(fixedHashSet.size() == 1); + } + + // explicitly instantiate some templated member functions + { + typedef eastl::fixed_hash_set<A, 100, 100> FixedHashSet; + FixedHashSet::value_type testValues[] = { 0, 1 }; + FixedHashSet fixedHashSet(testValues, testValues + EAArrayCount(testValues)); + VERIFY(fixedHashSet.size() == 2); + } + } + + + { // fixed_hash_multiset + { + typedef eastl::fixed_hash_multiset<int, 100, 100> FixedHashMultiSet; + FixedHashMultiSet fixedHashMultiSet; + + fixedHashMultiSet.insert(0); + fixedHashMultiSet.insert(0); + + VERIFY(fixedHashMultiSet.size() == 2); + } + + + // explicitly instantiate some templated member functions + { + typedef eastl::fixed_hash_multiset<A, 100, 100> FixedHashMultiSet; + FixedHashMultiSet::value_type testValues[] = { 0, 1 }; + FixedHashMultiSet fixedHashMultiSet(testValues, testValues + EAArrayCount(testValues)); + VERIFY(fixedHashMultiSet.size() == 2); + } + } + + + { // Tests of various bucketCount values. + { + typedef eastl::fixed_hash_set<int, 1, 2> FixedHashSet; + FixedHashSet fixedHashSet; + + fixedHashSet.insert(0); + + VERIFY(fixedHashSet.size() == 1); + } + + { + typedef eastl::fixed_hash_set<int, 2, 2> FixedHashSet; + FixedHashSet fixedHashSet; + + fixedHashSet.insert(0); + fixedHashSet.insert(1); + + VERIFY(fixedHashSet.size() == 2); + } + + { + typedef eastl::fixed_hash_set<int, 11, 11> FixedHashSet; // 11 is one of the hashtable prime numbers. + FixedHashSet fixedHashSet; + + for(int i = 0; i < 11; i++) + fixedHashSet.insert(i); + + VERIFY(fixedHashSet.size() == 11); + } + + + { + typedef eastl::fixed_hash_set<int, 11, 11> FixedHashSet; // 11 is one of the hashtable prime numbers. + FixedHashSet fixedHashSet; + + VERIFY(fixedHashSet.validate()); + VERIFY(fixedHashSet.size() == 0); + + // Clear a newly constructed, already empty container. + fixedHashSet.clear(true); + VERIFY(fixedHashSet.validate()); + VERIFY(fixedHashSet.size() == 0); + VERIFY(fixedHashSet.bucket_count() == 1); + + for(int i = 0; i < 11; i++) + fixedHashSet.insert(i); + VERIFY(fixedHashSet.size() == 11); + VERIFY(fixedHashSet.bucket_count() > 1); + + fixedHashSet.clear(true); + VERIFY(fixedHashSet.validate()); + VERIFY(fixedHashSet.size() == 0); + VERIFY(fixedHashSet.bucket_count() == 1); + + for(int i = 0; i < 11; i++) + fixedHashSet.insert(i); + VERIFY(fixedHashSet.size() == 11); + } + } + + { // Test of user-reported crash. + + // MemoryAddressToGroupMap is a container used by one team to associate debug + // information with memory allocations. A crash due to corruption of the + // fixed size node pool was reported on consoles (no crash on PC platform). + const eastl_size_t kMemoryAddressMapNodeCount = 500000; + + typedef eastl::fixed_hash_map< + const void*, // Key + MemoryEntry, // Value + kMemoryAddressMapNodeCount, // Node Count + kMemoryAddressMapNodeCount + 1, // Bucket Count + true, // Enable Overflow + eastl::hash<const void*>, // Hash + eastl::equal_to<const void*>, // Predicate + false, // Cache Hash Code + eastl::allocator // Allocator + > MemoryAddressToGroupMap; + + MemoryAddressToGroupMap* pMap = new MemoryAddressToGroupMap; + EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed()); + + // We simulate the usage of MemoryAddressToGroupMap via simulated alloc/free actions. + for(eastl_size_t i = 0; i < kMemoryAddressMapNodeCount * 2; i++) + { + void* const p = (void*)(uintptr_t)rng.RandLimit(kMemoryAddressMapNodeCount); + + if(pMap->find(p) == pMap->end()) + (*pMap)[p] = MemoryEntry(); + else + pMap->erase(p); + } + + delete pMap; + } + + + { // Test of bug reported by Dave Wall, May 14, 2008. + const size_t kNumBuckets = 10; // Bug only occurred with kNumBuckets == 10 or 11. + + typedef eastl::fixed_hash_map<const InstanceRenderData, uint32_t, kNumBuckets, kNumBuckets + 1, false> Map; + + Map map; + InstanceRenderData renderData; + + uint32_t count = (uint32_t)kNumBuckets; + + while(count--) + { + renderData.mPad[0] = count; + map.insert(Map::value_type(renderData, count)); + } + + } + + { + // Test construction of a container with an overflow allocator constructor argument. + MallocAllocator overflowAllocator; + void* p = overflowAllocator.allocate(1); + + typedef eastl::fixed_hash_map<int, int, 64, 100, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator> Container; + Container c(overflowAllocator); + + for(int i = 0; i < 65; i++) + c.insert(Container::value_type(i, i)); + + VERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65. + overflowAllocator.deallocate(p, 1); + } + + + { + // C++11 emplace and related functionality + nErrorCount += TestMapCpp11<eastl::fixed_hash_map<int, TestObject, 2, 7, true> >(); // Exercize a low-capacity fixed-size container. + nErrorCount += TestMapCpp11<eastl::fixed_hash_map<int, TestObject, 32, 7, true> >(); + + nErrorCount += TestMapCpp11NonCopyable<eastl::fixed_hash_map<int, NonCopyable, 2, 7, true>>(); + + nErrorCount += TestSetCpp11<eastl::fixed_hash_set<TestObject, 2, 7, true> >(); + nErrorCount += TestSetCpp11<eastl::fixed_hash_set<TestObject, 32, 7, true> >(); + + nErrorCount += TestMultimapCpp11<eastl::fixed_hash_multimap<int, TestObject, 2, 7, true> >(); + nErrorCount += TestMultimapCpp11<eastl::fixed_hash_multimap<int, TestObject, 32, 7, true> >(); + + nErrorCount += TestMultisetCpp11<eastl::fixed_hash_multiset<TestObject, 2, 7, true> >(); + nErrorCount += TestMultisetCpp11<eastl::fixed_hash_multiset<TestObject, 32, 7, true> >(); + } + + { + // C++17 try_emplace and related functionality + nErrorCount += TestMapCpp17<eastl::fixed_hash_map<int, TestObject, 2, 7, true>>(); + nErrorCount += TestMapCpp17<eastl::fixed_hash_map<int, TestObject, 32, 7, true> >(); + } + + { + // void reserve(size_type nElementCount); + + // test with overflow enabled. + nErrorCount += HashContainerReserveTest<fixed_hash_set<int, 16>>()(); + nErrorCount += HashContainerReserveTest<fixed_hash_multiset<int, 16>>()(); + nErrorCount += HashContainerReserveTest<fixed_hash_map<int, int, 16>>()(); + nErrorCount += HashContainerReserveTest<fixed_hash_multimap<int, int, 16>>()(); + + // API prevents testing fixed size hash container reservation without overflow enabled. + // + // nErrorCount += HashContainerReserveTest<fixed_hash_set<int, 400, 401, false>>()(); + // nErrorCount += HashContainerReserveTest<fixed_hash_multiset<int, 400, 401, false>>()(); + // nErrorCount += HashContainerReserveTest<fixed_hash_map<int, int, 400, 401, false>>()(); + // nErrorCount += HashContainerReserveTest<fixed_hash_multimap<int, int, 9000, 9001, false>>()(); + } + + { + // initializer_list support. + // fixed_hash_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR) + // this_type& operator=(std::initializer_list<value_type> ilist); + // void insert(std::initializer_list<value_type> ilist); + fixed_hash_set<int, 11> intHashSet = { 12, 13, 14 }; + EATEST_VERIFY(intHashSet.size() == 3); + EATEST_VERIFY(intHashSet.find(12) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(13) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(14) != intHashSet.end()); + + intHashSet = { 22, 23, 24 }; + EATEST_VERIFY(intHashSet.size() == 3); + EATEST_VERIFY(intHashSet.find(22) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(23) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(24) != intHashSet.end()); + + intHashSet.insert({ 42, 43, 44 }); + EATEST_VERIFY(intHashSet.size() == 6); + EATEST_VERIFY(intHashSet.find(42) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(43) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(44) != intHashSet.end()); + + // hash_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR) + // this_type& operator=(std::initializer_list<value_type> ilist); + // void insert(std::initializer_list<value_type> ilist); + fixed_hash_map<int, double, 11> intHashMap = { {12,12.0}, {13,13.0}, {14,14.0} }; + EATEST_VERIFY(intHashMap.size() == 3); + EATEST_VERIFY(intHashMap.find(12) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(13) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(14) != intHashMap.end()); + + intHashMap = { {22,22.0}, {23,23.0}, {24,24.0} }; + EATEST_VERIFY(intHashMap.size() == 3); + EATEST_VERIFY(intHashMap.find(22) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(23) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(24) != intHashMap.end()); + + intHashMap.insert({ {42,42.0}, {43,43.0}, {44,44.0} }); + EATEST_VERIFY(intHashMap.size() == 6); + EATEST_VERIFY(intHashMap.find(42) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(43) != intHashMap.end()); + EATEST_VERIFY(intHashMap.find(44) != intHashMap.end()); + } + + { + constexpr int ELEM_MAX = 10; + typedef eastl::fixed_hash_map<int, int, ELEM_MAX, ELEM_MAX, false> FixedHashMapFalse; + FixedHashMapFalse fixedHashMap; + VERIFY(fixedHashMap.size() == 0); + + for (int i = 0; i < ELEM_MAX; i++) + fixedHashMap.insert(FixedHashMapFalse::value_type(i, i)); + + VERIFY(fixedHashMap.validate()); + VERIFY(fixedHashMap.size() == ELEM_MAX); + + // Verify insert requests of nodes already in the container don't attempt to allocate memory. + // Because the fixed_hash_map is full any attempt to allocate memory will generate an OOM error. + { + auto result = fixedHashMap.insert(FixedHashMapFalse::value_type(0, 0)); + VERIFY(result.second == false); + } + + { + auto result = fixedHashMap.insert(fixedHashMap.begin(), FixedHashMapFalse::value_type(0, 0)); + VERIFY(result->first == 0); + VERIFY(result->second == 0); + } + + { + FixedHashMapFalse::value_type value(0, 0); + auto result = fixedHashMap.insert(eastl::move(value)); + VERIFY(result.second == false); + } + { + FixedHashMapFalse::value_type value(0, 0); + auto result = fixedHashMap.insert(fixedHashMap.begin(), eastl::move(value)); + VERIFY(result->first == 0); + VERIFY(result->second == 0); + } + + { + FixedHashMapFalse::value_type value(0, 0); + auto result = fixedHashMap.insert(value); + VERIFY(result.second == false); + } + + { + auto result = fixedHashMap.insert(eastl::make_pair(0, 0)); + VERIFY(result.second == false); + } + + { + // OOM, fixed allocator memory is exhausted so it can't create a node for insertation testing + // auto result = fixedHashMap.emplace(0, 0); + // VERIFY(result.second == false); + } + } + + return nErrorCount; +} +EA_RESTORE_VC_WARNING() + + + + + + + + + |