// // OrderedContainersTest.h // // Definition of the OrderedContainersTest class. // // SPDX-License-Identifier: BSL-1.0 // #ifndef OrderedContainersTest_INCLUDED #define OrderedContainersTest_INCLUDED #include "Poco/Foundation.h" #include "CppUnit/TestCase.h" #include "Poco/OrderedMap.h" #include "Poco/OrderedSet.h" #include "ordered_map_util.h" #include #include #ifdef POCO_COMPILER_MSVC #pragma warning(push) #pragma warning(disable : 4244) #pragma warning(disable : 4267) #endif // POCO_COMPILER_MSVC class OrderedContainersTest: public CppUnit::TestCase { public: OrderedContainersTest(const std::string& name); ~OrderedContainersTest(); void testMapInsert(); void testRangeInsert(); void testInsertWithHint(); void testEmplace(); void testTryEmplace(); void testTryEmplace2(); void testTryEmplaceHint(); void testInsertOrAssign(); void testInsertOrAssignHint(); void testInsertAtPosition(); void testTryEmplaceAtPosition(); void testRangeErase(); void testMapEraseLoop(); void testMapInsertEraseInsert(); void testRangeEraseAll(); void testRangeEraseSameIterators(); void testUnorderedErase(); void testCompare(); void testClear(); void testReverseIterator(); void testIteratorArithmetic(); void testIteratorComparators(); void testModifyValue(); void testAssignOperator(); void testMoveConstructor(); void testMoveOperator(); void testReassignMovedObjectMoveConstructor(); void testReassignMovedObjectMoveOperator(); void testCopyConstructorOperator(); void testAt(); void testEqualRange(); void testData(); void testAccessOperator(); void testSwap(); void testFrontBack(); void testNth(); void testHeterogeneousLookups(); void testEmptyMap(); void testPrecalculatedHash(); void testSetInsert(); void testCustomAllocator1(); void setUp(); void tearDown(); static CppUnit::Test* suite(); private: #define testMapFuncFwd(cont, func) { \ func>(); \ func, std::equal_to, \ std::allocator>, \ std::deque>>>(); \ func, std::equal_to, \ std::allocator>, \ std::vector>>>(); \ func>(); \ func>>(); \ } // needs significant CppUnit or test changes, maybe one day ... //func>>(); #define testSetFuncFwd(cont, func) { \ func, \ std::equal_to, \ std::allocator, \ std::deque>>(); \ func, \ std::equal_to, \ std::allocator, \ std::vector>>(); \ func>>(); \ func>(); \ func>>(); \ } template void testMapInsertImpl() { // insert x values, insert them again, check values through find, check order through iterator using key_tt = typename T::key_type; using value_tt = typename T::mapped_type; const std::size_t nb_values = 1000; T map; typename T::iterator it; bool inserted; for(std::size_t i = 0; i < nb_values; i++) { // Avoid sequential values by splitting the values with modulo const std::size_t insert_val = (i%2 == 0) ? i : nb_values + i; std::tie(it, inserted) = map.insert({utils::get_key(insert_val), utils::get_value(insert_val)}); assertEquals(it->first, utils::get_key(insert_val)); assertEquals(it->second, utils::get_value(insert_val)); assertTrue(inserted); } assertEquals(map.size(), nb_values); for(std::size_t i = 0; i < nb_values; i++) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; std::tie(it, inserted) = map.insert({utils::get_key(insert_val), utils::get_value(insert_val + 1)}); assertEquals(it->first, utils::get_key(insert_val)); assertEquals(it->second, utils::get_value(insert_val)); assertTrue(!inserted); } assertEquals(map.size(), nb_values); for(std::size_t i = 0; i < nb_values; i++) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; it = map.find(utils::get_key(insert_val)); assertEquals(it->first, utils::get_key(insert_val)); assertEquals(it->second, utils::get_value(insert_val)); } std::size_t i = 0; for(const auto& key_value: map) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; assertEquals(key_value.first, utils::get_key(insert_val)); assertEquals(key_value.second, utils::get_value(insert_val)); i++; } } template void testMapEraseLoopImpl() { // insert x values, delete all one by one std::size_t nb_values = 1000; T map = utils::get_filled_hash_map(nb_values); T map2 = utils::get_filled_hash_map(nb_values); auto it = map.begin(); // Use second map to check for key after delete as we may not copy the key with move-only types. auto it2 = map2.begin(); while(it != map.end()) { it = map.erase(it); --nb_values; assertEquals(map.count(it2->first), 0); assertEquals(map.size(), nb_values); ++it2; } assertTrue(map.empty()); } template void testMapInsertEraseInsertImpl() { // insert x/2 values, delete x/4 values, insert x/2 values, find each value, check order of values using key_tt = typename T::key_type; using value_tt = typename T:: mapped_type; const std::size_t nb_values = 2000; T map; typename T::iterator it; bool inserted; // Insert nb_values/2 for(std::size_t i = 0; i < nb_values/2; i++) { std::tie(it, inserted) = map.insert({utils::get_key(i), utils::get_value(i)}); assertEquals(it->first, utils::get_key(i)); assertEquals(it->second, utils::get_value(i)); assertTrue(inserted); } assertEquals(map.size(), nb_values/2); // Delete nb_values/4 for(std::size_t i = 0; i < nb_values/2; i++) { if(i%2 == 0) { assertEquals(map.erase(utils::get_key(i)), 1); } } assertEquals(map.size(), nb_values/4); // Insert nb_values/2 for(std::size_t i = nb_values/2; i < nb_values; i++) { std::tie(it, inserted) = map.insert({utils::get_key(i), utils::get_value(i)}); assertEquals(it->first, utils::get_key(i)); assertEquals(it->second, utils::get_value(i)); assertTrue(inserted); } assertEquals(map.size(), nb_values-nb_values/4); // Find for(std::size_t i = 0; i < nb_values; i++) { if(i%2 == 0 && i < nb_values/2) { it = map.find(utils::get_key(i)); assertTrue(it == map.cend()); } else { it = map.find(utils::get_key(i)); assertEquals(it->first, utils::get_key(i)); assertEquals(it->second, utils::get_value(i)); } } // Check order std::size_t i = 1; for(const auto& key_value: map) { if(i < nb_values/2) { assertEquals(key_value.first, utils::get_key(i)); assertEquals(key_value.second, utils::get_value(i)); i = std::min(i+2, nb_values/2); } else { assertEquals(key_value.first, utils::get_key(i)); assertEquals(key_value.second, utils::get_value(i)); i++; } } } template void testSetInsertImpl() { // insert x values, insert them again, check values through find, check order through iterator using key_t = typename T::key_type; const std::size_t nb_values = 1000; T set; typename T::iterator it; bool inserted; for(std::size_t i = 0; i < nb_values; i++) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; std::tie(it, inserted) = set.insert(utils::get_key(insert_val)); assertEquals(*it, utils::get_key(insert_val)); assertTrue(inserted); } assertEquals(set.size(), nb_values); for(std::size_t i = 0; i < nb_values; i++) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; std::tie(it, inserted) = set.insert(utils::get_key(insert_val)); assertEquals(*it, utils::get_key(insert_val)); assertTrue(!inserted); } assertEquals(set.size(), nb_values); for(std::size_t i = 0; i < nb_values; i++) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; it = set.find(utils::get_key(insert_val)); assertEquals(*it, utils::get_key(insert_val)); } std::size_t i = 0; for(const auto& value: set) { const std::size_t insert_val = (i%2 == 0)?i:nb_values + i; assertEquals(value, utils::get_key(insert_val)); i++; } } }; #ifdef POCO_COMPILER_MSVC #pragma warning(pop) #endif // POCO_COMPILER_MSVC #endif // OrderedContainersTest_INCLUDED