//////////////////////////////////////////////////////////////////////////////// // flex_string // Copyright (c) 2001 by Andrei Alexandrescu // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author makes no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// // $Id$ #ifdef _MSC_VER #pragma warning (disable : 4786) // Get rid of browser information too long names #ifdef _DEBUG #pragma warning (disable : 4786) #endif #endif #include #include #ifndef __MWERKS__ //#define NO_ALLOCATOR_REBIND //#define NO_ITERATOR_TRAITS #endif #include #include #include #include #include #include #include #include #include namespace StringsToTest { typedef flex_string< char, std::char_traits, std::allocator, SimpleStringStorage > > my_string_SimpleStorage; typedef flex_string< char, std::char_traits, std::allocator, AllocatorStringStorage > > my_string_AllocatorStorage; typedef flex_string< char, std::char_traits, mallocator, AllocatorStringStorage > > my_string_MallocatorStorage; typedef flex_string< char, std::char_traits, std::allocator, VectorStringStorage > > my_string_VectorStorage; typedef flex_string< char, std::char_traits, std::allocator, SmallStringOpt >, 31> > my_string_SmallStringSimple; typedef flex_string< char, std::char_traits, std::allocator, SmallStringOpt >, 23> > my_string_SmallStringVector; typedef flex_string< char, std::char_traits, std::allocator, CowStringOpt > > > my_string_CowSimple; typedef flex_string< char, std::char_traits, std::allocator, CowStringOpt > > > my_string_CowAllocator; } template Integral2 random(Integral1 low, Integral2 up) { Integral2 low2(low); assert(up >= low2); if (low2 == up) return low; Integral2 x = Integral2(low2 + (rand() * (up - low2)) / RAND_MAX); assert(x >= low2 && x <= up); return x; } template String RandomString(size_t maxSize) { String result(random(0, maxSize), '\0'); size_t i = 0; for (; i != result.size(); ++i) { result[i] = random('a', 'z'); } return result; } template String Num2String(Integral value) { typedef typename String::value_type CharType; std::basic_ostringstream, std::allocator > stream; stream << value; return stream.str().c_str(); } template std::list RandomList(typename String::size_type maxSize) { std::list lst(random(0, maxSize)); std::list::iterator i = lst.begin(); for (; i != lst.end(); ++i) { *i = random('a', 'z'); } return lst; } namespace Tests { template struct MaxString { static const typename String::size_type value = 1050; }; template String default_constructor(String &) { // 21.3.1 return String(); } template String copy_constructor(String & test) { // 21.3.1 String s(test); return s; } template String copy_constructor_with_size_and_range(String & test) { // 21.3.1 const typename String::size_type pos = random(0, test.size()); String s(test, pos, random(0, test.size() - pos)); return s; } template String constructor_with_cstr_and_size(String & test) { // 21.3.1 const typename String::size_type pos = random(0, test.size()), n = random(0, test.size() - pos); String s(test.c_str() + pos, n); return s; } template String constructor_with_cstr(String & test) { // 21.3.1 const typename String::size_type pos = random(0, test.size()); String s(test.c_str() + pos); return s; } template String assignment(String & test) { // 21.3.1 String s(random(0, 1000), '\0'); typename String::size_type i = 0; for (; i != s.size(); ++i) { s[i] = random('a', 'z'); } test = s; return test; } template String assignment_with_cstr(String & test) { // 21.3.1 String s(random(0, 1000), '\0'); typename String::size_type i = 0; for (; i != s.size(); ++i) { s[i] = random('a', 'z'); } test = s.c_str(); return test; } template String assignment_aliased(String & test) { // 21.3.1 const size_t pos = random(0, test.size()); test = test.c_str() + pos; return test; } template String assignment_non_aliased(String & test) { // 21.3.1 const size_t pos = random(0, test.size()); test = String(test.c_str() + pos); return test; } template String assignment_from_char(String & test) { // 21.3.1 test = random('a', 'z'); return test; } template String iterators_call(String & test) { // 21.3.2 String result; result += Num2String(test.end() - test.begin()) + " -- "; result += Num2String(test.rend() - test.rbegin()) + " -- "; return result; } template String iterators_equality(String & test) { // 21.3.2 String result; result += Num2String(test.size()) + " -- "; if(0 != test.size()) { result += Num2String(test.begin() != test.end()) + " -- "; result += Num2String(test.rbegin() != test.rend()) + " -- "; } else { result += Num2String(test.begin() == test.end()) + " -- "; result += Num2String(test.rbegin() == test.rend()) + " -- "; } return result; } template String capacity(String & test) { // 21.3.2 String result; result += Num2String(test.size()) + " -- "; result += Num2String(test.length()) + " -- "; test.max_size(); test.capacity(); result += test; return result; } template String capacity_values(String & test) { // 21.3.2 String result; result += Num2String(test.size() == test.length()) + " -- "; result += Num2String(test.capacity() >= test.size()) + " -- "; result += Num2String(test.max_size() >= test.size()) + " -- "; result += Num2String(test.max_size() >= test.capacity()) + " -- "; return result; } template String resize(String & test) { test.resize(random(0, test.size()), random('a', 'z')); return test; } template String resize_with_1_argument(String & test) { test.resize(random(0, test.size())); return test; } template String reserve(String & test) { test.reserve(random(0, 1000)); return test; } template String clear(String & test) { test.clear(); return test; } template String empty1(String & test) { if (test.empty()) test = "empty"; else test = "not empty"; return test; } template String empty2(String & test) { const char* kEmptyString = "empty"; const char* kNonEmptyString = "not empty"; if (test.empty()) test = String(kEmptyString, kEmptyString + strlen(kEmptyString)); else test = String(kNonEmptyString, kNonEmptyString + strlen(kNonEmptyString)); return test; } template String element_access(String & test) { // 21.3.4 if(!test.empty()) { test[random(0, test.size() - 1)]; test.at(random(0, test.size() - 1)); } return test; } template String operator_plus_equal(String & test) { test += RandomString(MaxString::value); return test; } template String operator_plus_equal_aliasing(String & test) { test += test; return test; } template String operator_plus_equal_with_cstr(String & test) { // 21.3.5 test += RandomString(MaxString::value).c_str(); return test; } template String operator_plus_equal_no_aliasing(String & test) { // 21.3.5 test += String(test.c_str() + random(0, test.size())); return test; } template String operator_plus_equal_aliasing_cstr(String & test) { // 21.3.5 test += test.c_str() + random(0, test.size()); return test; } template String operator_plus_equal_char(String & test) { // 21.3.5 test += random('a', 'z'); return test; } template String append_string(String & test) { // 21.3.5 test.append(RandomString(MaxString::value)); return test; } template String append_string_start_range(String & test) { // 21.3.5 String s(RandomString(MaxString::value)); test.append(s, random(0, s.size()), random(0, MaxString::value)); return test; } template String append_cstr_size(String & test) { // 21.3.5 String s = RandomString(MaxString::value); test.append(s.c_str(), random(0, s.size())); return test; } template String append_cstr(String & test) { // 21.3.5 test.append(RandomString(MaxString::value).c_str()); return test; } template String append_iterators(String & test) { // 21.3.5 test.append(random(0, MaxString::value), random('a', 'z')); std::list lst(RandomList(MaxString::value)); test.append(lst.begin(), lst.end()); return test; } template String push_back_char(String & test) { // 21.3.5 test.push_back(random('a', 'z')); return test; } template String assign_string(String & test) { // 21.3.5 test.assign(RandomString(MaxString::value)); return test; } template String assign_string_start_size(String & test) { // 21.3.5 String str = RandomString(MaxString::value); test.assign(str, random(0, str.size()), random(0, MaxString::value)); return test; } template String assign_cstr_size(String & test) { // 21.3.5 String str = RandomString(MaxString::value); test.assign(str.c_str(), random(0, str.size())); return test; } template String assign_cstr(String & test) { // 21.3.5 test.assign(RandomString(MaxString::value).c_str()); return test; } template String assign_number_char(String & test) { // 21.3.5 test.assign(random(0, MaxString::value), random('a', 'z')); return test; } template String assign_iterators(String & test) { // 21.3.5 std::list lst(RandomList(MaxString::value)); test.assign(lst.begin(), lst.end()); return test; } template String insert_position_string(String & test) { // 21.3.5 test.insert(random(0, test.size()), RandomString(MaxString::value)); return test; } template String insert_position_string_start_end(String & test) { // 21.3.5 String str = RandomString(MaxString::value); test.insert(random(0, test.size()), str, random(0, str.size()), random(0, MaxString::value)); return test; } template String insert_position_cstr_size(String & test) { // 21.3.5 String str = RandomString(MaxString::value); test.insert(random(0, test.size()), str.c_str(), random(0, str.size())); return test; } template String insert_position_cstr(String & test) { // 21.3.5 test.insert(random(0, test.size()), RandomString(MaxString::value).c_str()); return test; } template String insert_position_number_char(String & test) { // 21.3.5 test.insert(random(0, test.size()), random(0, MaxString::value), random('a', 'z')); return test; } template String insert_iterator_char(String & test) { // 21.3.5 test.insert(test.begin() + random(0, test.size()), random('a', 'z')); return test; } template String insert_iterator_iterator_range(String & test) { // 21.3.5 std::list lst(RandomList(MaxString::value)); test.insert(test.begin() + random(0, test.size()), lst.begin(), lst.end()); return test; } template String erase_position_position(String & test) { // 21.3.5 test.erase(random(0, test.size()), random(0, MaxString::value)); return test; } template String erase_iterator(String & test) { // 21.3.5 if(!test.empty()) test.erase(test.begin() + random(0, test.size())); return test; } template String erase_iterator_iterator(String & test) { // 21.3.5 const typename String::iterator i = test.begin() + random(0, test.size()); test.erase(i, i + random(0, size_t(test.end() - i))); return test; } template String replace_start_end_copyself(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, random(0, test.size() - pos), String(test)); return test; } template String replace_start_end_self(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, random(0, test.size() - pos), test); return test; } template String replace_start_end_string(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, pos + random(0, test.size() - pos), RandomString(MaxString::value)); return test; } template String replace_start_end_selfcopy_start_end(String & test) { // 21.3.5 const typename String::size_type pos1 = random(0, test.size()), pos2 = random(0, test.size()); test.replace(pos1, pos1 + random(0, test.size() - pos1), String(test), pos2, pos2 + random(0, test.size() - pos2)); return test; } template String replace_start_end_self_start_end(String & test) { // 21.3.5 const typename String::size_type pos1 = random(0, test.size()), pos2 = random(0, test.size()); test.replace(pos1, pos1 + random(0, test.size() - pos1), test, pos2, pos2 + random(0, test.size() - pos2)); return test; } template String replace_start_end_string_start_end(String & test) { // 21.3.5 const typename String::size_type pos1 = random(0, test.size()); String str = RandomString(MaxString::value); const typename String::size_type pos2 = random(0, str.size()); test.replace(pos1, pos1 + random(0, test.size() - pos1), str, pos2, pos2 + random(0, str.size() - pos2)); return test; } template String replace_start_end_selfcopycstr_size(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, random(0, test.size() - pos), String(test).c_str(), test.size()); return test; } template String replace_start_end_selfcstr_size(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, random(0, test.size() - pos), test.c_str(), test.size()); return test; } template String replace_start_end_stringcstr_size(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); String str = RandomString(MaxString::value); test.replace(pos, pos + random(0, test.size() - pos), str.c_str(), str.size()); return test; } template String replace_start_end_stringcstr(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); String str = RandomString(MaxString::value); test.replace(pos, pos + random(0, test.size() - pos), str.c_str()); return test; } template String replace_start_end_number_char(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace(pos, random(0, test.size() - pos), random(0, MaxString::value), random('a', 'z')); return test; } template String replace_iterator_iterator_selfcopy(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace( test.begin() + pos, test.begin() + pos + random(0, test.size() - pos), String(test)); return test; } template String replace_iterator_iterator_self(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace( test.begin() + pos, test.begin() + pos + random(0, test.size() - pos), test); return test; } template String replace_iterator_iterator_selfcopycstr_size(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace( test.begin() + pos, test.begin() + pos + random(0, test.size() - pos), String(test).c_str(), test.size() - random(0, test.size())); return test; } template String replace_iterator_iterator_selfcstr_size(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace( test.begin() + pos, test.begin() + pos + random(0, test.size() - pos), test.c_str(), test.size() - random(0, test.size())); return test; } template String replace_iterator_iterator_stringcstr(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()), n = random(0, test.size() - pos); typename String::iterator b = test.begin(); const String str = RandomString(MaxString::value); const typename String::value_type* s = str.c_str(); test.replace( b + pos, b + pos + n, s); return test; } template String replace_iterator_iterator_number_char(String & test) { // 21.3.5 const typename String::size_type pos = random(0, test.size()); test.replace( test.begin() + pos, test.begin() + pos + random(0, test.size() - pos), random(0, MaxString::value), random('a', 'z')); return test; } template String copy_pointer_size_position(String & test) { // 21.3.5 std::vector vec(random(1, MaxString::value)); test.copy( &vec[0], vec.size(), random(0, test.size())); return test; } template String member_swap(String & test) { // 21.3.5 RandomString(MaxString::value).swap(test); return test; } template String member_swap2(String & test) { // 21.3.5 String s(RandomString(MaxString::value)); s.swap(test); return s; } template String swap(String & test) { using std::swap; String s(RandomString(MaxString::value)); swap(test, s); return test; } template String swap2(String & test) { using std::swap; String s(RandomString(MaxString::value)); swap(test, s); return s; } template String cstr_data_getallocator(String & test) { // 21.3.6 String result; result += Num2String(test.c_str() == test.data()) + " -- "; result += Num2String(test.get_allocator() == RandomString(MaxString::value).get_allocator()) + " -- "; return result; } template String find_string_index(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.find(str, random(0, test.size()))); return test; } template String find_stringcstr_index_length(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.find(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String find_stringcstr_index(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.find(str.c_str(), random(0, test.size()))); return test; } template String find_char_index(String & test) { // 21.3.6 test = Num2String(test.find( random('a', 'z'), random(0, test.size()))); return test; } template String find_overflow(String & test) { // This tests bug 2536490. test = String(); String result; // Validate that find with a single character doesn't overflow. result += Num2String(test.find('6')); result += " -- "; test = "12345"; result += Num2String(test.find('6')); result += " -- "; test = "123456"; result += Num2String(test.find('6')); result += " -- "; test = "12345"; result += Num2String(test.find('6')); result += " -- "; // Validate that find with multiple characters doesn't overflow. test = "12345"; result += Num2String(test.find("123")); result += " -- "; test = "12345"; result += Num2String(test.find("12345")); result += " -- "; test = "12345"; result += Num2String(test.find("345")); result += " -- "; test = "123456"; result += Num2String(test.find("456")); result += " -- "; test = "12345"; result += Num2String(test.find("456")); result += " -- "; return result; } template String rfind_overflow(String & test) { test = String(); String result; // Validate that rfind with a single character doesn't overflow. result += Num2String(test.rfind('6')); result += " -- "; test = "12345"; result += Num2String(test.rfind('6')); result += " -- "; test = "123456"; result += Num2String(test.rfind('6')); result += " -- "; test = "12345"; result += Num2String(test.rfind('6')); result += " -- "; // Validate that rfind with multiple characters doesn't overflow. test = "12345"; result += Num2String(test.rfind("123")); result += " -- "; test = "12345"; result += Num2String(test.rfind("12345")); result += " -- "; test = "12345"; result += Num2String(test.rfind("345")); result += " -- "; test = "123456"; result += Num2String(test.rfind("456")); result += " -- "; test = "12345"; result += Num2String(test.rfind("456")); result += " -- "; return result; } template String rfind_string_index(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.rfind(str, random(0, test.size()))); return test; } template String rfind_stringcstr_index_length(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.rfind(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String rfind_stringcstr_index(String & test) { // 21.3.6 String str = test.substr( random(0, test.size()), random(0, test.size())); test = Num2String(test.rfind(str.c_str(), random(0, test.size()))); return test; } template String rfind_char_index(String & test) { // 21.3.6 test = Num2String(test.rfind( random('a', 'z'), random(0, test.size()))); return test; } template String find_first_of_string_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_of(str, random(0, test.size()))); return test; } template String find_first_of_stringcstr_index_length(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_of(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String find_first_of_stringcstr_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_of(str.c_str(), random(0, test.size()))); return test; } template String find_first_of_char_index(String & test) { // 21.3.6 test = Num2String(test.find_first_of( random('a', 'z'), random(0, test.size()))); return test; } template String find_last_of_string_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_of(str, random(0, test.size()))); return test; } template String find_last_of_stringcstr_index_length(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_of(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String find_last_of_stringcstr_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_of(str.c_str(), random(0, test.size()))); return test; } template String find_last_of_char_index(String & test) { // 21.3.6 test = Num2String(test.find_last_of( random('a', 'z'), random(0, test.size()))); return test; } template String find_first_not_of_string_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_not_of(str, random(0, test.size()))); return test; } template String find_first_not_of_stringcstr_index_length(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_not_of(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String find_first_not_of_stringcstr_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_first_not_of(str.c_str(), random(0, test.size()))); return test; } template String find_first_not_of_char_index(String & test) { // 21.3.6 test = Num2String(test.find_first_not_of( random('a', 'z'), random(0, test.size()))); return test; } template String find_last_not_of_string_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_not_of(str, random(0, test.size()))); return test; } template String find_last_not_of_stringcstr_index_length(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_not_of(str.c_str(), random(0, test.size()), random(0, str.size()))); return test; } template String find_last_not_of_stringcstr_index(String & test) { // 21.3.6 String str = RandomString(MaxString::value); test = Num2String(test.find_last_not_of(str.c_str(), random(0, test.size()))); return test; } template String find_last_not_of_char_index(String & test) { // 21.3.6 test = Num2String(test.find_last_not_of( random('a', 'z'), random(0, test.size()))); return test; } template String substr_index_length(String & test) { // 21.3.6 test = test.substr(random(0, test.size()), random(0, test.size())); return test; } template String compare_selfcopy(String & test) { int tristate = test.compare(String(test)); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_string(String & test) { int tristate = test.compare(RandomString(MaxString::value)); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_index_length_selfcopy(String & test) { int tristate = test.compare( random(0, test.size()), random(0, test.size()), String(test)); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_index_length_string(String & test) { int tristate = test.compare( random(0, test.size()), random(0, test.size()), RandomString(MaxString::value)); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_index_length_selfcopy_index_length(String & test) { String str = test; int tristate = test.compare( random(0, test.size()), random(0, test.size()), str, random(0, str.size()), random(0, str.size())); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_index_length_string_index_length(String & test) { String str = RandomString(MaxString::value); int tristate = test.compare( random(0, test.size()), random(0, test.size()), str, random(0, str.size()), random(0, str.size())); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_stringcstr(String & test) { int tristate = test.compare( RandomString(MaxString::value).c_str()); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String compare_index_length_stringcstr_length(String & test) { String str = RandomString(MaxString::value); int tristate = test.compare( random(0, test.size()), random(0, test.size()), str.c_str(), random(0, str.size())); if (tristate > 0) tristate = 1; else if (tristate < 0) tristate = 2; test = Num2String(tristate); return test; } template String operator_plus(String & test) { test = RandomString(MaxString::value) + RandomString(MaxString::value); return test; } template String operator_plus_lhs_cstr(String & test) { test = RandomString(MaxString::value).c_str() + RandomString(MaxString::value); return test; } template String operator_plus_lhs_char(String & test) { test = typename String::value_type(random('a', 'z')) + RandomString(MaxString::value); return test; } template String operator_plus_rhs_cstr(String & test) { test = RandomString(MaxString::value) + RandomString(MaxString::value).c_str(); return test; } template String operator_plus_rhs_char(String & test) { test = RandomString(MaxString::value) + typename String::value_type(random('a', 'z')); return test; } } template class TestFunctions { public: typedef String (*TestFunction)(String &); TestFunctions() { using namespace Tests; #define ADD_TEST(test) (testFunctions.push_back(std::make_pair((#test), (test)))) ADD_TEST(default_constructor); ADD_TEST(copy_constructor); ADD_TEST(copy_constructor_with_size_and_range); ADD_TEST(constructor_with_cstr_and_size); ADD_TEST(constructor_with_cstr); ADD_TEST(assignment); ADD_TEST(assignment_with_cstr); ADD_TEST(assignment_aliased); ADD_TEST(assignment_non_aliased); ADD_TEST(assignment_from_char); ADD_TEST(iterators_call); ADD_TEST(iterators_equality); ADD_TEST(capacity); ADD_TEST(capacity_values); ADD_TEST(resize); ADD_TEST(resize_with_1_argument); ADD_TEST(reserve); ADD_TEST(clear); ADD_TEST(empty1); ADD_TEST(empty2); ADD_TEST(element_access); ADD_TEST(operator_plus_equal); ADD_TEST(operator_plus_equal_aliasing); ADD_TEST(operator_plus_equal_with_cstr); ADD_TEST(operator_plus_equal_no_aliasing); ADD_TEST(operator_plus_equal_aliasing_cstr); ADD_TEST(operator_plus_equal_char); ADD_TEST(append_string); ADD_TEST(append_string_start_range); ADD_TEST(append_cstr_size); ADD_TEST(append_cstr); ADD_TEST(append_iterators); ADD_TEST(push_back_char); ADD_TEST(assign_string); ADD_TEST(assign_string_start_size); ADD_TEST(assign_cstr_size); ADD_TEST(assign_cstr); ADD_TEST(assign_number_char); ADD_TEST(assign_iterators); ADD_TEST(insert_position_string); ADD_TEST(insert_position_string_start_end); ADD_TEST(insert_position_cstr_size); ADD_TEST(insert_position_cstr); ADD_TEST(insert_position_number_char); ADD_TEST(insert_iterator_char); ADD_TEST(insert_iterator_iterator_range); ADD_TEST(erase_position_position); ADD_TEST(erase_iterator); ADD_TEST(erase_iterator_iterator); ADD_TEST(replace_start_end_copyself); ADD_TEST(replace_start_end_self); ADD_TEST(replace_start_end_string); ADD_TEST(replace_start_end_selfcopy_start_end); ADD_TEST(replace_start_end_self_start_end); ADD_TEST(replace_start_end_string_start_end); ADD_TEST(replace_start_end_selfcopycstr_size); ADD_TEST(replace_start_end_selfcstr_size); ADD_TEST(replace_start_end_stringcstr_size); ADD_TEST(replace_start_end_stringcstr); ADD_TEST(replace_start_end_number_char); ADD_TEST(replace_iterator_iterator_selfcopy); ADD_TEST(replace_iterator_iterator_self); ADD_TEST(replace_iterator_iterator_selfcopycstr_size); ADD_TEST(replace_iterator_iterator_selfcstr_size); ADD_TEST(replace_iterator_iterator_stringcstr); ADD_TEST(replace_iterator_iterator_number_char); ADD_TEST(copy_pointer_size_position); ADD_TEST(member_swap); ADD_TEST(member_swap2); ADD_TEST(swap); ADD_TEST(swap2); ADD_TEST(cstr_data_getallocator); ADD_TEST(find_string_index); ADD_TEST(find_stringcstr_index_length); ADD_TEST(find_stringcstr_index); ADD_TEST(find_char_index); ADD_TEST(find_overflow); ADD_TEST(rfind_overflow); ADD_TEST(rfind_string_index); ADD_TEST(rfind_stringcstr_index_length); ADD_TEST(rfind_stringcstr_index); ADD_TEST(rfind_char_index); ADD_TEST(find_first_of_string_index); ADD_TEST(find_first_of_stringcstr_index_length); ADD_TEST(find_first_of_stringcstr_index); ADD_TEST(find_first_of_char_index); ADD_TEST(find_last_of_string_index); ADD_TEST(find_last_of_stringcstr_index_length); ADD_TEST(find_last_of_stringcstr_index); ADD_TEST(find_last_of_char_index); ADD_TEST(find_first_not_of_string_index); ADD_TEST(find_first_not_of_stringcstr_index_length); ADD_TEST(find_first_not_of_stringcstr_index); ADD_TEST(find_first_not_of_char_index); ADD_TEST(find_last_not_of_string_index); ADD_TEST(find_last_not_of_stringcstr_index_length); ADD_TEST(find_last_not_of_stringcstr_index); ADD_TEST(find_last_not_of_char_index); ADD_TEST(substr_index_length); ADD_TEST(compare_selfcopy); ADD_TEST(compare_string); ADD_TEST(compare_index_length_selfcopy); ADD_TEST(compare_index_length_string); ADD_TEST(compare_index_length_selfcopy_index_length); ADD_TEST(compare_index_length_string_index_length); ADD_TEST(compare_stringcstr); ADD_TEST(compare_index_length_stringcstr_length); ADD_TEST(operator_plus); ADD_TEST(operator_plus_lhs_cstr); ADD_TEST(operator_plus_lhs_char); ADD_TEST(operator_plus_rhs_cstr); ADD_TEST(operator_plus_rhs_char); } ~TestFunctions() { testFunctions.clear(); } size_t getNumberInTestRange(size_t number) const { return number % testFunctions.size(); } TestFunction getTest(size_t number) const { return testFunctions.at(getNumberInTestRange(number)).second; } const char * getTestName(size_t number) const { return testFunctions.at(getNumberInTestRange(number)).first; } private: std::vector > testFunctions; TestFunctions(const TestFunctions &); TestFunctions & operator=(const TestFunctions &); }; template String Test(size_t count, const TestFunctions & testFunctions) { String test(RandomString(Tests::MaxString::value)); String result(testFunctions.getTest(count)(test)); return result; } template void checkResults(const std::string & reference, const String & tested, const TestFunctions & testFunctions, unsigned int seedForThisIteration, size_t count) { if( (tested.size() != reference.size()) || (std::string(tested.data(), tested.size()) != reference) ) { std::cout << "\n\nTest #" << testFunctions.getNumberInTestRange(count) << " \"" << testFunctions.getTestName(count) << "\" failed for string type \"" << typeid(String).name() << "\":\n" << "seed for this iteration = " << seedForThisIteration << "\n" << "reference.size() = " << reference.size() << "\n" << "tested.size() = " << tested.size() << "\n" << "reference data = {" << reference << "}\n" << "tested data = {" << tested << "}\n\n"; } } void Compare() { size_t count = 0; using namespace StringsToTest; TestFunctions testFunctions_std; TestFunctions testFunctions_SimpleStorage; TestFunctions testFunctions_AllocatorStorage; TestFunctions testFunctions_MallocatorStorage; TestFunctions testFunctions_VectorStorage; TestFunctions testFunctions_SmallStringSimple; TestFunctions testFunctions_SmallStringVector; TestFunctions testFunctions_CowSimple; TestFunctions testFunctions_CowAllocator; for (;;) { std::cout << ++count << '\r'; const unsigned int seedForThisIteration = rand(); srand(seedForThisIteration); const std::string reference(Test(count, testFunctions_std)); { srand(seedForThisIteration); const my_string_SimpleStorage tested(Test(count, testFunctions_SimpleStorage)); checkResults(reference, tested, testFunctions_SimpleStorage, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_AllocatorStorage tested(Test(count, testFunctions_AllocatorStorage)); checkResults(reference, tested, testFunctions_AllocatorStorage, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_MallocatorStorage tested(Test(count, testFunctions_MallocatorStorage)); checkResults(reference, tested, testFunctions_MallocatorStorage, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_VectorStorage tested = Test(count, testFunctions_VectorStorage); checkResults(reference, tested, testFunctions_VectorStorage, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_SmallStringSimple tested(Test(count, testFunctions_SmallStringSimple)); checkResults(reference, tested, testFunctions_SmallStringSimple, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_SmallStringVector tested(Test(count, testFunctions_SmallStringVector)); checkResults(reference, tested, testFunctions_SmallStringVector, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_CowSimple tested(Test(count, testFunctions_CowSimple)); checkResults(reference, tested, testFunctions_CowSimple, seedForThisIteration, count); } { srand(seedForThisIteration); const my_string_CowAllocator tested(Test(count, testFunctions_CowAllocator)); checkResults(reference, tested, testFunctions_CowAllocator, seedForThisIteration, count); } } } int main() { const time_t initialSeed(time(0)); srand(unsigned(initialSeed)); std::cout << "initial seed = " << initialSeed << "\n\n"; Compare(); return 0; }