diff --git a/test/string_test.cpp b/test/string_test.cpp index 6e2ee56..9cd9737 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -27,6 +27,20 @@ #include "../../intrusive/test/iterator_test.hpp" #include #include +#include +#if BOOST_CXX_VERSION >= 201103L +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace boost::container; @@ -57,14 +71,17 @@ ForwardIt unique(ForwardIt first, ForwardIt const last) if(first == last){ ForwardIt i = first; //Find first adjacent pair - while(1){ + bool go_ahead = true; + while(go_ahead){ if(++i == last){ return last; } else if(*first == *i){ - break; + go_ahead = false; + } + else{ + ++first; } - ++first; } //Now overwrite skipping adjacent elements while (++i != last) { @@ -138,7 +155,8 @@ struct string_literals const wchar_t *digits = L"0123456789"; wchar_t *buf = buffer; - while(1){ + bool go_ahead = true; + while(go_ahead){ unsigned long long rem = number % 10; number = number / 10; @@ -146,7 +164,7 @@ struct string_literals ++buf; if(!number){ *buf = 0; - break; + go_ahead = false; } } @@ -521,6 +539,1881 @@ struct alloc_propagate_base }}} //namespace boost::container::test +//============================================================================== +// SECTION 1: Type traits and typedefs +//============================================================================== + +void test_type_traits() +{ + // Basic type traits + BOOST_TEST_TRAIT_TRUE((dtl::is_same)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same >)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same)); + + // Iterator types should be random access + typedef string::iterator iter; + typedef string::const_iterator citer; + typedef string::reverse_iterator riter; + typedef string::const_reverse_iterator criter; + + BOOST_TEST_TRAIT_TRUE((dtl::is_same< + typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same< + typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same< + typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((dtl::is_same< + typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag>)); + + // npos + BOOST_TEST_EQ(string::npos, static_cast(-1)); +} + +//============================================================================== +// SECTION 2: Constructors +//============================================================================== + +void test_default_constructor() +{ + string s; + BOOST_TEST(s.empty()); + BOOST_TEST_EQ(s.size(), 0u); + BOOST_TEST_EQ(s.length(), 0u); + BOOST_TEST(s.capacity() >= s.size()); + BOOST_TEST(s == ""); +} + +void test_allocator_constructor() +{ + string::allocator_type alloc; + string s(alloc); + BOOST_TEST(s.empty()); + BOOST_TEST_EQ(s.size(), 0u); +} + +void test_count_char_constructor() +{ + string s1(5, 'a'); + BOOST_TEST_EQ(s1.size(), 5u); + BOOST_TEST(s1 == "aaaaa"); + + string s2(0, 'x'); + BOOST_TEST(s2.empty()); + + string s3(100, 'z'); + BOOST_TEST_EQ(s3.size(), 100u); + BOOST_TEST_EQ(s3[0], 'z'); +} + +void test_substring_constructor() +{ + string original("Hello, World!"); + + // pos only + string s1(original, 7); + BOOST_TEST(s1 == "World!"); + + // pos and count + string s2(original, 0, 5); + BOOST_TEST(s2 == "Hello"); + + string s3(original, 7, 5); + BOOST_TEST(s3 == "World"); + + // pos == size (empty result) + string s4(original, original.size()); + BOOST_TEST(s4.empty()); + + // count exceeds remaining (should clamp) + string s5(original, 7, 100); + BOOST_TEST(s5 == "World!"); + + // npos count + string s6(original, 7, string::npos); + BOOST_TEST(s6 == "World!"); +} + +void test_cstring_constructor() +{ + const char* cstr = "Hello, World!"; + + // Full c-string + string s1(cstr); + BOOST_TEST(s1 == "Hello, World!"); + BOOST_TEST_EQ(s1.size(), 13u); + + // c-string with count + string s2(cstr, 5); + BOOST_TEST(s2 == "Hello"); + BOOST_TEST_EQ(s2.size(), 5u); + + // zero count + string s3(cstr, 0); + BOOST_TEST(s3.empty()); + + // Empty c-string + string s4(""); + BOOST_TEST(s4.empty()); +} + +void test_iterator_constructor() +{ + const char arr[] = "Hello"; + string s1(&arr[0], &arr[sizeof(arr) - 1]); // exclude null terminator + BOOST_TEST(s1 == "Hello"); + + string source("World"); + string s2(source.begin(), source.end()); + BOOST_TEST(s2 == "World"); + + string s3(source.rbegin(), source.rend()); + BOOST_TEST(s3 == "dlroW"); + + // Empty range + string s4(source.begin(), source.begin()); + BOOST_TEST(s4.empty()); +} + +void test_copy_constructor() +{ + string original("Hello, World!"); + string copy(original); + + BOOST_TEST(copy == original); + BOOST_TEST_EQ(copy.size(), original.size()); + BOOST_TEST(copy.data() != original.data()); // Different storage + + // Modifying copy doesn't affect original + copy[0] = 'h'; + BOOST_TEST(original[0] == 'H'); +} + +void test_move_constructor() +{ + string original("Hello, World!"); + std::size_t original_size = original.size(); + + string moved(boost::move(original)); + + BOOST_TEST_EQ(moved.size(), original_size); + BOOST_TEST(moved == "Hello, World!"); +} + +void test_initializer_list_constructor() +{ + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + string s1{'H', 'e', 'l', 'l', 'o'}; + BOOST_TEST(s1 == "Hello"); + BOOST_TEST_EQ(s1.size(), 5u); + + string s2{}; + BOOST_TEST(s2.empty()); + + string s3{'a'}; + BOOST_TEST(s3 == "a"); + #endif +} + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +void test_string_view_constructor() +{ + std::string_view sv("Hello, World!"); + string s1(sv); + BOOST_TEST(s1 == "Hello, World!"); + + // Use substr on the string_view instead + string s2(sv.substr(7, 5)); + BOOST_TEST(s2 == "World"); +} +#endif + +// Boost.Container specific: default_init constructor +void test_default_init_constructor() +{ + string s(10, default_init); + BOOST_TEST_EQ(s.size(), 10u); + // Contents are uninitialized but string is valid +} + +//============================================================================== +// SECTION 3: Assignment operators +//============================================================================== + +template +T& return_self(T &t) +{ return t; } + +void test_copy_assignment() +{ + string s1("Hello"); + string s2; + + s2 = s1; + BOOST_TEST(s2 == "Hello"); + BOOST_TEST(s1 == "Hello"); + BOOST_TEST(s1.data() != s2.data()); + + // Self-assignment + s1 = return_self(s1); + BOOST_TEST(s1 == "Hello"); +} + +void test_move_assignment() +{ + string s1("Hello, World!"); + string s2; + + s2 = boost::move(s1); + BOOST_TEST(s2 == "Hello, World!"); + // s1 is in valid but unspecified state +} + +void test_cstring_assignment() +{ + string s; + + s = "Hello"; + BOOST_TEST(s == "Hello"); + + s = ""; + BOOST_TEST(s.empty()); + + s = "A longer string for testing"; + BOOST_TEST(s == "A longer string for testing"); +} + +void test_char_assignment() +{ + string s("Hello"); + + s = 'X'; + BOOST_TEST(s == "X"); + BOOST_TEST_EQ(s.size(), 1u); +} + +void test_initializer_list_assignment() +{ + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + string s; + + s = {'H', 'e', 'l', 'l', 'o'}; + BOOST_TEST(s == "Hello"); + + s = {}; + BOOST_TEST(s.empty()); + #endif +} + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +void test_string_view_assignment() +{ + string s; + std::string_view sv("Hello"); + + s = sv; + BOOST_TEST(s == "Hello"); +} +#endif + +//============================================================================== +// SECTION 4: assign() methods +//============================================================================== + +void test_assign_count_char() +{ + string s("Hello"); + + s.assign(5, 'x'); + BOOST_TEST(s == "xxxxx"); + + s.assign(0, 'y'); + BOOST_TEST(s.empty()); + + s.assign(10, 'z'); + BOOST_TEST_EQ(s.size(), 10u); + BOOST_TEST(s == "zzzzzzzzzz"); +} + +void test_assign_string() +{ + string s1("Hello"); + string s2; + + s2.assign(s1); + BOOST_TEST(s2 == "Hello"); + + // Self-assign + s2.assign(s2); + BOOST_TEST(s2 == "Hello"); +} + +void test_assign_substring() +{ + string s1("Hello, World!"); + string s2; + + s2.assign(s1, 7, string::npos); + BOOST_TEST(s2 == "World!"); + + s2.assign(s1, 0, 5); + BOOST_TEST(s2 == "Hello"); + + s2.assign(s1, 7, 5); + BOOST_TEST(s2 == "World"); + + s2.assign(s1, 0, string::npos); + BOOST_TEST(s2 == "Hello, World!"); +} + +void test_assign_move() +{ + string s1("Hello"); + string s2; + + s2.assign(boost::move(s1)); + BOOST_TEST(s2 == "Hello"); +} + +void test_assign_cstring() +{ + string s; + + s.assign("Hello, World!"); + BOOST_TEST(s == "Hello, World!"); + + s.assign("Hello", string::size_type(5)); + BOOST_TEST(s == "Hello"); + + s.assign("", string::size_type(0)); + BOOST_TEST(s.empty()); +} + +void test_assign_iterators() +{ + string source("Hello"); + string s; + + s.assign(source.begin(), source.end()); + BOOST_TEST(s == "Hello"); + + s.assign(source.rbegin(), source.rend()); + BOOST_TEST(s == "olleH"); + + s.assign(source.begin(), source.begin()); + BOOST_TEST(s.empty()); +} + +void test_assign_initializer_list() +{ + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + string s; + + s.assign({'W', 'o', 'r', 'l', 'd'}); + BOOST_TEST(s == "World"); + + s.assign({}); + BOOST_TEST(s.empty()); + #endif +} + +//============================================================================== +// SECTION 5: Element access +//============================================================================== + +void test_at() +{ + string s("Hello"); + + BOOST_TEST_EQ(s.at(0), 'H'); + BOOST_TEST_EQ(s.at(1), 'e'); + BOOST_TEST_EQ(s.at(4), 'o'); + + // Modifiable + s.at(0) = 'h'; + BOOST_TEST_EQ(s.at(0), 'h'); + + // Const version + const string cs("World"); + BOOST_TEST_EQ(cs.at(0), 'W'); + + #ifndef BOOST_NO_EXCEPTIONS + + bool threw = false; + try { + (void)s.at(100); + } catch (...) { + threw = true; + } + BOOST_TEST(threw); + + threw = false; + try { + (void)s.at(s.size()); + } catch (...) { + threw = true; + } + BOOST_TEST(threw); + + #endif //BOOST_NO_EXCEPTIONS +} + +void test_operator_bracket() +{ + string s("Hello"); + + BOOST_TEST_EQ(s[0], 'H'); + BOOST_TEST_EQ(s[1], 'e'); + BOOST_TEST_EQ(s[4], 'o'); + BOOST_TEST_EQ(s[5], '\0'); + + // Modifiable + s[0] = 'h'; + BOOST_TEST_EQ(s[0], 'h'); + + // Const version + const string cs("World"); + BOOST_TEST_EQ(cs[0], 'W'); + BOOST_TEST_EQ(cs[cs.size()], '\0'); +} + +void test_front() +{ + string s("Hello"); + BOOST_TEST_EQ(s.front(), 'H'); + + s.front() = 'h'; + BOOST_TEST_EQ(s.front(), 'h'); + + const string cs("World"); + BOOST_TEST_EQ(cs.front(), 'W'); +} + +void test_back() +{ + string s("Hello"); + BOOST_TEST_EQ(s.back(), 'o'); + + s.back() = 'O'; + BOOST_TEST_EQ(s.back(), 'O'); + + const string cs("World"); + BOOST_TEST_EQ(cs.back(), 'd'); +} + +void test_data() +{ + string s("Hello"); + + const char* data = s.data(); + BOOST_TEST_EQ(data[0], 'H'); + BOOST_TEST_EQ(data[5], '\0'); // null-terminated + + // Non-const data() + char* mdata = s.data(); + mdata[0] = 'h'; + BOOST_TEST(s == "hello"); +} + +void test_c_str() +{ + string s("Hello"); + + const char* cstr = s.c_str(); + BOOST_TEST_EQ(std::strcmp(cstr, "Hello"), 0); + BOOST_TEST_EQ(cstr[5], '\0'); + + string empty; + BOOST_TEST_EQ(empty.c_str()[0], '\0'); +} + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +void test_string_view_conversion() +{ + string s("Hello"); + std::string_view sv(s.data(), s.size()); + + BOOST_TEST_EQ(sv.size(), s.size()); + BOOST_TEST(sv == "Hello"); +} +#endif + +//============================================================================== +// SECTION 6: Iterators +//============================================================================== + +void test_begin_end() +{ + string s("Hello"); + + BOOST_TEST_EQ(*s.begin(), 'H'); + BOOST_TEST_EQ(*(s.end() - 1), 'o'); + BOOST_TEST_EQ(std::distance(s.begin(), s.end()), 5); + + // Modify through iterator + *s.begin() = 'h'; + BOOST_TEST(s == "hello"); + + // Const iterators + const string cs("World"); + BOOST_TEST_EQ(*cs.begin(), 'W'); + BOOST_TEST_EQ(*(cs.end() - 1), 'd'); +} + +void test_cbegin_cend() +{ + string s("Hello"); + + BOOST_TEST_EQ(*s.cbegin(), 'H'); + BOOST_TEST_EQ(*(s.cend() - 1), 'o'); + + // Verify const_iterator type + string::const_iterator it = s.cbegin(); + BOOST_TEST_EQ(*it, 'H'); +} + +void test_rbegin_rend() +{ + string s("Hello"); + + BOOST_TEST_EQ(*s.rbegin(), 'o'); + BOOST_TEST_EQ(*(s.rend() - 1), 'H'); + + string reversed(s.rbegin(), s.rend()); + BOOST_TEST(reversed == "olleH"); + + // Const + const string cs("World"); + BOOST_TEST_EQ(*cs.rbegin(), 'd'); +} + +void test_crbegin_crend() +{ + string s("Hello"); + + BOOST_TEST_EQ(*s.crbegin(), 'o'); + BOOST_TEST_EQ(*(s.crend() - 1), 'H'); +} + +void test_iterator_arithmetic() +{ + string s("Hello"); + + string::iterator it = s.begin(); + it += 2; + BOOST_TEST_EQ(*it, 'l'); + + it -= 1; + BOOST_TEST_EQ(*it, 'e'); + + BOOST_TEST_EQ(*(it + 2), 'l'); + BOOST_TEST_EQ(*(it - 1), 'H'); + + BOOST_TEST_EQ(s.end() - s.begin(), 5); + BOOST_TEST(s.begin() < s.end()); + BOOST_TEST(s.end() > s.begin()); + BOOST_TEST(s.begin() <= s.begin()); + BOOST_TEST(s.begin() >= s.begin()); +} + +//============================================================================== +// SECTION 7: Capacity +//============================================================================== + +void test_empty() +{ + string s; + BOOST_TEST(s.empty()); + + s = "x"; + BOOST_TEST(!s.empty()); + + s.clear(); + BOOST_TEST(s.empty()); +} + +void test_size_length() +{ + string s; + BOOST_TEST_EQ(s.size(), 0u); + BOOST_TEST_EQ(s.length(), 0u); + + s = "Hello"; + BOOST_TEST_EQ(s.size(), 5u); + BOOST_TEST_EQ(s.length(), 5u); + BOOST_TEST_EQ(s.size(), s.length()); + + // Embedded nulls + s = string("ab\0cd", 5); + BOOST_TEST_EQ(s.size(), 5u); +} + +void test_max_size() +{ + string s; + BOOST_TEST(s.max_size() > 0); + BOOST_TEST(s.max_size() >= s.size()); +} + +void test_reserve() +{ + string s; + std::size_t initial_cap = s.capacity(); + + s.reserve(100); + BOOST_TEST(s.capacity() >= 100u); + BOOST_TEST(s.capacity() != initial_cap); + BOOST_TEST(s.empty()); // reserve doesn't change size + + // Reserve smaller shall not shrink + s.reserve(10); + BOOST_TEST(s.capacity() >= 100u); + s.reserve(0); + BOOST_TEST(s.capacity() >= 100u); +} + +void test_capacity() +{ + string s; + BOOST_TEST(s.capacity() >= s.size()); + + s = "Hello"; + BOOST_TEST(s.capacity() >= 5u); + + string large(1000, 'x'); + BOOST_TEST(large.capacity() >= 1000u); +} + +void test_shrink_to_fit() +{ + string s; + s.reserve(1000); + std::size_t large_cap = s.capacity(); + BOOST_TEST(large_cap >= 1000u); + + s = "Hello"; + s.shrink_to_fit(); + // shrink_to_fit is non-binding, but capacity should be >= size + BOOST_TEST(s.capacity() >= s.size()); +} + +//============================================================================== +// SECTION 8: Operations - clear, insert, erase +//============================================================================== + +void test_clear() +{ + string s("Hello, World!"); + std::size_t cap_before = s.capacity(); + + s.clear(); + BOOST_TEST(s.empty()); + BOOST_TEST_EQ(s.size(), 0u); + // Capacity is typically not reduced by clear() + BOOST_TEST(s.capacity() >= cap_before || s.capacity() >= s.size()); +} + +void test_insert_char() +{ + string s("Hello"); + + // insert(pos, count, char) + s.insert(string::size_type(5), string::size_type(1), '!'); + BOOST_TEST(s == "Hello!"); + + s.insert(string::size_type(0), string::size_type(1), '*'); + BOOST_TEST(s == "*Hello!"); + + s.insert(string::size_type(1), string::size_type(3), '-'); + BOOST_TEST(s == "*---Hello!"); +} + +void test_insert_cstring() +{ + string s("World"); + + // insert(pos, s) + s.insert(0, "Hello, "); + BOOST_TEST(s == "Hello, World"); + + // insert(pos, s, count) + s.insert(s.size(), "!!!", 1); + BOOST_TEST(s == "Hello, World!"); +} + +void test_insert_string() +{ + string s("World"); + string prefix("Hello, "); + + // insert(pos, str) + s.insert(0, prefix); + BOOST_TEST(s == "Hello, World"); + + // insert(pos, str, subpos, sublen) + string suffix("!!!END"); + s.insert(s.size(), suffix, 0, 1); + BOOST_TEST(s == "Hello, World!"); +} + +void test_insert_iterator() +{ + string s("Hllo"); + + // insert(pos, char) + string::iterator it = s.insert(s.begin() + 1, 'e'); + BOOST_TEST(s == "Hello"); + BOOST_TEST_EQ(*it, 'e'); + + // insert(pos, count, char) + s.insert(s.begin(), 2, '*'); + BOOST_TEST(s == "**Hello"); + + // insert(pos, first, last) + string extra("123"); + s.insert(s.end(), extra.begin(), extra.end()); + BOOST_TEST(s == "**Hello123"); +} + +void test_insert_initializer_list() +{ + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + string s("ac"); + + s.insert(s.begin() + 1, {'b'}); + BOOST_TEST(s == "abc"); + + s.insert(s.end(), {'d', 'e', 'f'}); + BOOST_TEST(s == "abcdef"); + #endif +} + +void test_erase_member() +{ + string s("Hello, World!"); + + // erase(pos, count) + s.erase(5, 7); + BOOST_TEST(s == "Hello!"); + + // erase(pos) - erases to end + s = "Hello, World!"; + s.erase(5); + BOOST_TEST(s == "Hello"); + + // erase() - erases all + s.erase(); + BOOST_TEST(s.empty()); + + // erase(iterator) + s = "Hello"; + string::iterator it = s.erase(s.begin()); + BOOST_TEST(s == "ello"); + BOOST_TEST_EQ(*it, 'e'); + + // erase(first, last) + s = "Hello, World!"; + it = s.erase(s.begin() + 5, s.begin() + 7); + BOOST_TEST(s == "HelloWorld!"); + BOOST_TEST_EQ(*it, 'W'); +} + +//============================================================================== +// SECTION 9: Operations - push_back, pop_back, append +//============================================================================== + +void test_push_back() +{ + string s; + + s.push_back('H'); + BOOST_TEST(s == "H"); + + s.push_back('i'); + BOOST_TEST(s == "Hi"); + + for (int i = 0; i < 100; ++i) { + s.push_back('!'); + } + BOOST_TEST_EQ(s.size(), 102u); +} + +void test_pop_back() +{ + string s("Hello!"); + + s.pop_back(); + BOOST_TEST(s == "Hello"); + + s.pop_back(); + BOOST_TEST(s == "Hell"); + + while (!s.empty()) { + s.pop_back(); + } + BOOST_TEST(s.empty()); +} + +void test_append_string() +{ + string s("Hello"); + + // append(str) + s.append(string(", ")); + BOOST_TEST(s == "Hello, "); + + // append(str, pos, count) + string world("xxxWorldyyy"); + s.append(world, 3, 5); + BOOST_TEST(s == "Hello, World"); +} + +void test_append_cstring() +{ + string s("Hello"); + + // append(cstr) + s.append(", World"); + BOOST_TEST(s == "Hello, World"); + + // append(cstr, count) + s.append("!!!", 1); + BOOST_TEST(s == "Hello, World!"); +} + +void test_append_char() +{ + string s("Hello"); + + // append(count, char) + s.append(3, '!'); + BOOST_TEST(s == "Hello!!!"); +} + +void test_append_iterators() +{ + string s("Hello"); + string suffix(", World!"); + + s.append(suffix.begin(), suffix.end()); + BOOST_TEST(s == "Hello, World!"); +} + +void test_append_initializer_list() +{ + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + string s("Hello"); + + s.append({',', ' ', 'W', 'o', 'r', 'l', 'd', '!'}); + BOOST_TEST(s == "Hello, World!"); + #endif +} + +void test_operator_plus_equals() +{ + string s("Hello"); + + // += string + s += string(", "); + BOOST_TEST(s == "Hello, "); + + // += cstr + s += "World"; + BOOST_TEST(s == "Hello, World"); + + // += char + s += '!'; + BOOST_TEST(s == "Hello, World!"); + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + // += initializer_list + s += {'!', '!'}; + BOOST_TEST(s == "Hello, World!!!"); + #endif +} + +//============================================================================== +// SECTION 10: Operations - compare +//============================================================================== + +void test_compare() +{ + string s("Hello"); + + // compare(str) + BOOST_TEST_EQ(s.compare("Hello"), 0); + BOOST_TEST(s.compare("Apple") > 0); // H > A + BOOST_TEST(s.compare("World") < 0); // H < W + BOOST_TEST(s.compare("Hell") > 0); // longer + BOOST_TEST(s.compare("Hello!") < 0); // shorter + + // compare(pos, count, str) + BOOST_TEST_EQ(s.compare(0, 5, "Hello"), 0); + BOOST_TEST_EQ(s.compare(0, 4, "Hell"), 0); + BOOST_TEST_EQ(s.compare(1, 4, "ello"), 0); + + // compare(pos1, count1, str, pos2, count2) + string other("xxxHelloyyy"); + BOOST_TEST_EQ(s.compare(0, 5, other, 3, 5), 0); + + // compare(cstr) + BOOST_TEST_EQ(s.compare("Hello"), 0); + + // compare(pos, count, cstr) + BOOST_TEST_EQ(s.compare(0, 5, "Hello"), 0); + + // compare(pos, count, cstr, count2) + BOOST_TEST_EQ(s.compare(0, 5, "Hello!!!", 5), 0); +} + +//============================================================================== +// SECTION 11: Operations - starts_with, ends_with, contains (helper functions) +// Note: boost::container::string may not have these methods, so we implement +// them using find/compare for testing purposes +//============================================================================== + +// Helper functions for starts_with/ends_with/contains since boost::container::string +// might not have these methods in older versions +namespace test_helpers { + bool starts_with(const string& s, const char* prefix) { + string::size_type len = std::strlen(prefix); + return s.size() >= len && s.compare(0, len, prefix) == 0; + } + bool starts_with(const string& s, char c) { + return !s.empty() && s[0] == c; + } + bool ends_with(const string& s, const char* suffix) { + string::size_type len = std::strlen(suffix); + return s.size() >= len && s.compare(s.size() - len, len, suffix) == 0; + } + bool ends_with(const string& s, char c) { + return !s.empty() && s[s.size() - 1] == c; + } + bool contains(const string& s, const char* substr) { + return s.find(substr) != string::npos; + } + bool contains(const string& s, char c) { + return s.find(c) != string::npos; + } +} + +void test_starts_with() +{ + string s("Hello, World!"); + + using test_helpers::starts_with; + BOOST_TEST(starts_with(s, "Hello")); + BOOST_TEST(starts_with(s, "H")); + BOOST_TEST(starts_with(s, "")); + BOOST_TEST(starts_with(s, 'H')); + + BOOST_TEST(!starts_with(s, "World")); + BOOST_TEST(!starts_with(s, "hello")); // case-sensitive + BOOST_TEST(!starts_with(s, 'W')); +} + +void test_ends_with() +{ + string s("Hello, World!"); + + using test_helpers::ends_with; + BOOST_TEST(ends_with(s, "World!")); + BOOST_TEST(ends_with(s, "!")); + BOOST_TEST(ends_with(s, "")); + BOOST_TEST(ends_with(s, '!')); + + BOOST_TEST(!ends_with(s, "Hello")); + BOOST_TEST(!ends_with(s, "world!")); // case-sensitive + BOOST_TEST(!ends_with(s, 'H')); +} + +void test_contains() +{ + string s("Hello, World!"); + + using test_helpers::contains; + BOOST_TEST(contains(s, "World")); + BOOST_TEST(contains(s, "Hello")); + BOOST_TEST(contains(s, ", ")); + BOOST_TEST(contains(s, "")); + BOOST_TEST(contains(s, 'W')); + + BOOST_TEST(!contains(s, "world")); // case-sensitive + BOOST_TEST(!contains(s, "xyz")); + BOOST_TEST(!contains(s, 'X')); +} + +//============================================================================== +// SECTION 12: Operations - replace +//============================================================================== + +void test_replace_pos() +{ + string s("Hello, World!"); + + // replace(pos, count, str) + s.replace(7, 5, "Universe"); + BOOST_TEST(s == "Hello, Universe!"); + + // replace(pos, count, str, pos2, count2) + s = "Hello, World!"; + string repl("xxxCosmosyyy"); + s.replace(7, 5, repl, 3, 6); + BOOST_TEST(s == "Hello, Cosmos!"); + + // replace(pos, count, cstr, count2) + s = "Hello, World!"; + s.replace(7, 5, "Earth123", 5); + BOOST_TEST(s == "Hello, Earth!"); + + // replace(pos, count, cstr) + s = "Hello, World!"; + s.replace(7, 5, "Mars"); + BOOST_TEST(s == "Hello, Mars!"); + + // replace(pos, count, count2, char) + s = "Hello, World!"; + s.replace(7, 5, 3, 'X'); + BOOST_TEST(s == "Hello, XXX!"); +} + +void test_replace_iterator() +{ + string s("Hello, World!"); + + // replace(first, last, str) + s.replace(s.begin() + 7, s.begin() + 12, string("Universe")); + BOOST_TEST(s == "Hello, Universe!"); + + // replace(first, last, cstr, count) + s = "Hello, World!"; + s.replace(s.begin() + 7, s.begin() + 12, "Earth123", 5); + BOOST_TEST(s == "Hello, Earth!"); + + // replace(first, last, cstr) + s = "Hello, World!"; + s.replace(s.begin() + 7, s.begin() + 12, "Mars"); + BOOST_TEST(s == "Hello, Mars!"); + + // replace(first, last, count, char) + s = "Hello, World!"; + s.replace(s.begin() + 7, s.begin() + 12, 3, 'X'); + BOOST_TEST(s == "Hello, XXX!"); + + // replace(first, last, first2, last2) + s = "Hello, World!"; + string repl("Venus"); + s.replace(s.begin() + 7, s.begin() + 12, repl.begin(), repl.end()); + BOOST_TEST(s == "Hello, Venus!"); + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + // replace(first, last, initializer_list) + s = "Hello, World!"; + s.replace(s.begin() + 7, s.begin() + 12, {'S', 'u', 'n'}); + BOOST_TEST(s == "Hello, Sun!"); + #endif +} + +//============================================================================== +// SECTION 13: Operations - substr +//============================================================================== + +void test_substr() +{ + string s("Hello, World!"); + + // substr(pos) + BOOST_TEST(s.substr(7) == "World!"); + BOOST_TEST(s.substr(0) == "Hello, World!"); + BOOST_TEST(s.substr(s.size()).empty()); + + // substr(pos, count) + BOOST_TEST(s.substr(0, 5) == "Hello"); + BOOST_TEST(s.substr(7, 5) == "World"); + BOOST_TEST(s.substr(0, 0).empty()); + BOOST_TEST(s.substr(7, 100) == "World!"); // clamped + + // Out of range - boost::container throws its own exception type + #ifndef BOOST_NO_EXCEPTIONS + bool threw = false; + try { + (void)s.substr(100); + } catch (...) { + threw = true; + } + BOOST_TEST(threw); + #endif //BOOST_NO_EXCEPTIONS +} + +//============================================================================== +// SECTION 14: Operations - copy +//============================================================================== + +void test_copy() +{ + string s("Hello, World!"); + char buf[20] = {}; + + // copy(dest, count) + std::size_t copied = s.copy(buf, 5); + BOOST_TEST_EQ(copied, 5u); + BOOST_TEST_EQ(std::strncmp(buf, "Hello", 5), 0); + // Note: copy does NOT null-terminate + + // copy(dest, count, pos) + std::memset(buf, 0, sizeof(buf)); + copied = s.copy(buf, 5, 7); + BOOST_TEST_EQ(copied, 5u); + BOOST_TEST_EQ(std::strncmp(buf, "World", 5), 0); + + // copy with count > remaining + std::memset(buf, 0, sizeof(buf)); + copied = s.copy(buf, 100, 7); + BOOST_TEST_EQ(copied, 6u); // "World!" = 6 chars +} + +//============================================================================== +// SECTION 15: Operations - resize +//============================================================================== + +void test_resize() +{ + string s("Hello"); + + // resize larger + s.resize(10); + BOOST_TEST_EQ(s.size(), 10u); + BOOST_TEST(s.substr(0, 5) == "Hello"); + // New chars are '\0' + for (std::size_t i = 5; i < 10; ++i) { + BOOST_TEST_EQ(s[i], '\0'); + } + + // resize larger with fill + s = "Hello"; + s.resize(10, '!'); + BOOST_TEST_EQ(s.size(), 10u); + BOOST_TEST(s == "Hello!!!!!"); + + // resize smaller + s.resize(5); + BOOST_TEST_EQ(s.size(), 5u); + BOOST_TEST(s == "Hello"); + + // resize to 0 + s.resize(0); + BOOST_TEST(s.empty()); +} + +// Boost.Container specific: resize with default_init +void test_resize_default_init() +{ + string s("Hello"); + + s.resize(10, default_init); + BOOST_TEST_EQ(s.size(), 10u); + BOOST_TEST(s.substr(0, 5) == "Hello"); + // New chars are uninitialized but string is valid +} + +//============================================================================== +// SECTION 16: Operations - swap +//============================================================================== + +void test_swap() +{ + string s1("Hello"); + string s2("World"); + + s1.swap(s2); + BOOST_TEST(s1 == "World"); + BOOST_TEST(s2 == "Hello"); + + // std::swap + std::swap(s1, s2); + BOOST_TEST(s1 == "Hello"); + BOOST_TEST(s2 == "World"); + + // Swap with empty + string s3; + s1.swap(s3); + BOOST_TEST(s1.empty()); + BOOST_TEST(s3 == "Hello"); +} + +//============================================================================== +// SECTION 17: Search operations - find +//============================================================================== + +void test_find() +{ + string s("Hello, World! Hello again!"); + + // find(str) + BOOST_TEST_EQ(s.find("Hello"), 0u); + BOOST_TEST_EQ(s.find("World"), 7u); + BOOST_TEST_EQ(s.find("xyz"), string::npos); + + // find(str, pos) + BOOST_TEST_EQ(s.find("Hello", 1), 14u); + BOOST_TEST_EQ(s.find("Hello", 14), 14u); + BOOST_TEST_EQ(s.find("Hello", 15), string::npos); + + // find(cstr, pos, count) + BOOST_TEST_EQ(s.find("Hello!!!", 0, 5), 0u); + + // find(char) + BOOST_TEST_EQ(s.find('H'), 0u); + BOOST_TEST_EQ(s.find('W'), 7u); + BOOST_TEST_EQ(s.find('X'), string::npos); + + // find(char, pos) + BOOST_TEST_EQ(s.find('H', 1), 14u); + + // Empty string + BOOST_TEST_EQ(s.find(""), 0u); + BOOST_TEST_EQ(s.find("", 5), 5u); +} + +void test_rfind() +{ + string s("Hello, World! Hello again!"); + + // Note: boost::container::string rfind with npos behaves differently than std::string + // Using s.size() as the starting position for compatibility + + // rfind(str, pos) + BOOST_TEST_EQ(s.rfind("Hello", s.size()), 14u); + BOOST_TEST_EQ(s.rfind("World", s.size()), 7u); + BOOST_TEST_EQ(s.rfind("xyz", s.size()), string::npos); + + BOOST_TEST_EQ(s.rfind("Hello", 13), 0u); + BOOST_TEST_EQ(s.rfind("Hello", 14), 14u); + BOOST_TEST_EQ(s.rfind("Hello", 100), 14u); + + // rfind(cstr, pos, count) + BOOST_TEST_EQ(s.rfind("Hello!!!", s.size(), 5), 14u); + + // rfind(char) - char version works correctly with default + BOOST_TEST_EQ(s.rfind('H'), 14u); + BOOST_TEST_EQ(s.rfind('!'), 25u); + + // rfind(char, pos) + BOOST_TEST_EQ(s.rfind('H', 13), 0u); +} + +void test_find_first_of() +{ + string s("Hello, World!"); + + // find_first_of(str) + BOOST_TEST_EQ(s.find_first_of("aeiou"), 1u); // 'e' + BOOST_TEST_EQ(s.find_first_of("xyz"), string::npos); + + // find_first_of(str, pos) + BOOST_TEST_EQ(s.find_first_of("aeiou", 2), 4u); // 'o' + + // find_first_of(cstr, pos, count) + BOOST_TEST_EQ(s.find_first_of("aeiou!!", 0, 5), 1u); + + // find_first_of(char) + BOOST_TEST_EQ(s.find_first_of('o'), 4u); + BOOST_TEST_EQ(s.find_first_of('o', 5), 8u); +} + +void test_find_last_of() +{ + string s("Hello, World!"); + + // find_last_of(str) + BOOST_TEST_EQ(s.find_last_of("aeiou"), 8u); // 'o' in World + + // find_last_of(str, pos) + BOOST_TEST_EQ(s.find_last_of("aeiou", 7), 4u); // 'o' in Hello + + // find_last_of(cstr, pos, count) + BOOST_TEST_EQ(s.find_last_of("aeiou!!", string::npos, 5), 8u); + + // find_last_of(char) + BOOST_TEST_EQ(s.find_last_of('o'), 8u); + BOOST_TEST_EQ(s.find_last_of('o', 7), 4u); +} + +void test_find_first_not_of() +{ + string s("aaabbbccc"); + + BOOST_TEST_EQ(s.find_first_not_of("a"), 3u); + BOOST_TEST_EQ(s.find_first_not_of("ab"), 6u); + BOOST_TEST_EQ(s.find_first_not_of("abc"), string::npos); + + // with pos + BOOST_TEST_EQ(s.find_first_not_of("a", 3), 3u); + BOOST_TEST_EQ(s.find_first_not_of("b", 3), 6u); + + // with count + BOOST_TEST_EQ(s.find_first_not_of("abc", 0, 1), 3u); // only 'a' + + // single char + BOOST_TEST_EQ(s.find_first_not_of('a'), 3u); +} + +void test_find_last_not_of() +{ + string s("aaabbbccc"); + + BOOST_TEST_EQ(s.find_last_not_of("c"), 5u); + BOOST_TEST_EQ(s.find_last_not_of("bc"), 2u); + BOOST_TEST_EQ(s.find_last_not_of("abc"), string::npos); + + // with pos + BOOST_TEST_EQ(s.find_last_not_of("c", 5), 5u); + BOOST_TEST_EQ(s.find_last_not_of("b", 5), 2u); + + // with count - "abc" with count=1 means only 'a' is excluded + // so we're looking for last char that is not 'a', which is 'c' at position 8 + BOOST_TEST_EQ(s.find_last_not_of("abc", string::npos, 1), 8u); + + // single char + BOOST_TEST_EQ(s.find_last_not_of('c'), 5u); +} + +//============================================================================== +// SECTION 18: Non-member functions - operators +//============================================================================== + +void test_concatenation_operator() +{ + string s1("Hello"); + string s2("World"); + + // string + string + string r1 = s1 + s2; + BOOST_TEST(r1 == "HelloWorld"); + + // string + cstr + string r2 = s1 + ", World!"; + BOOST_TEST(r2 == "Hello, World!"); + + // cstr + string + string r3 = "Say " + s1; + BOOST_TEST(r3 == "Say Hello"); + + // string + char + string r4 = s1 + '!'; + BOOST_TEST(r4 == "Hello!"); + + // char + string + string r5 = '(' + s1 + ')'; + BOOST_TEST(r5 == "(Hello)"); + + // rvalue optimizations + string r6 = boost::move(s1) + "!!!"; + BOOST_TEST(r6 == "Hello!!!"); +} + +void test_comparison_operators() +{ + string s1("Hello"); + string s2("Hello"); + string s3("World"); + string s4("Hell"); + string s5("Hello!"); + + // == + BOOST_TEST(s1 == s2); + BOOST_TEST(s1 == "Hello"); + BOOST_TEST("Hello" == s1); + BOOST_TEST(!(s1 == s3)); + + // != + BOOST_TEST(s1 != s3); + BOOST_TEST(s1 != "World"); + BOOST_TEST("World" != s1); + BOOST_TEST(!(s1 != s2)); + + // < + BOOST_TEST(s1 < s3); // H < W + BOOST_TEST(s4 < s1); // prefix + BOOST_TEST(s1 < s5); // prefix + BOOST_TEST(!(s1 < s2)); + BOOST_TEST(!(s3 < s1)); + + // <= + BOOST_TEST(s1 <= s2); + BOOST_TEST(s1 <= s3); + BOOST_TEST(!(s3 <= s1)); + + // > + BOOST_TEST(s3 > s1); + BOOST_TEST(s1 > s4); + BOOST_TEST(s5 > s1); + BOOST_TEST(!(s1 > s2)); + + // >= + BOOST_TEST(s1 >= s2); + BOOST_TEST(s3 >= s1); + BOOST_TEST(!(s1 >= s3)); +} + +//============================================================================== +// SECTION 19: Non-member functions - I/O +//============================================================================== + +void test_stream_output() +{ + string s("Hello, World!"); + std::ostringstream oss; + + oss << s; + BOOST_TEST(oss.str() == "Hello, World!"); + + // With manipulators + std::ostringstream oss2; + oss2 << std::setw(20) << std::left << s; + BOOST_TEST(oss2.str() == "Hello, World! "); +} + +void test_stream_input() +{ + std::istringstream iss("Hello World"); + string s; + + iss >> s; + BOOST_TEST(s == "Hello"); + + iss >> s; + BOOST_TEST(s == "World"); + + // Empty input + std::istringstream iss2(""); + s = "unchanged"; + iss2 >> s; + BOOST_TEST(s == "unchanged"); // unchanged on failure +} + +void test_getline() +{ + // boost::container::string doesn't work with std::getline directly + // Test line reading using stream input and manual line parsing + std::istringstream iss("Line1\nLine2\nLine3"); + string s; + std::string std_s; + + // Read using std::string then convert + BOOST_TEST(static_cast(std::getline(iss, std_s))); + s = std_s.c_str(); + BOOST_TEST(s == "Line1"); + + BOOST_TEST(static_cast(std::getline(iss, std_s))); + s = std_s.c_str(); + BOOST_TEST(s == "Line2"); + + BOOST_TEST(static_cast(std::getline(iss, std_s))); + s = std_s.c_str(); + BOOST_TEST(s == "Line3"); + + BOOST_TEST(!std::getline(iss, std_s)); // EOF + + // Custom delimiter + std::istringstream iss2("a,b,c"); + BOOST_TEST(static_cast(std::getline(iss2, std_s, ','))); + s = std_s.c_str(); + BOOST_TEST(s == "a"); + + BOOST_TEST(static_cast(std::getline(iss2, std_s, ','))); + s = std_s.c_str(); + BOOST_TEST(s == "b"); + + // Empty lines + std::istringstream iss3("\n\n"); + BOOST_TEST(static_cast(std::getline(iss3, std_s))); + s = std_s.c_str(); + BOOST_TEST(s.empty()); +} + +//============================================================================== +// SECTION 20: Hash and swap +//============================================================================== + +void test_hash() +{ + #if BOOST_CXX_VERSION >= 201103L + // Use boost::hash instead of std::hash for boost::container::string + boost::hash hasher; + + string s1("Hello"); + string s2("Hello"); + string s3("World"); + + BOOST_TEST_EQ(hasher(s1), hasher(s2)); + // Different strings should (usually) have different hashes + BOOST_TEST(hasher(s1) != hasher(s3) || s1 == s3); + + // Empty string + string empty, empty2(""); + BOOST_TEST_EQ(hasher(empty), hasher(empty2)); + #endif +} + +void test_std_swap() +{ + string s1("Hello"); + string s2("World"); + + std::swap(s1, s2); + BOOST_TEST(s1 == "World"); + BOOST_TEST(s2 == "Hello"); +} + +//============================================================================== +// SECTION 21: Allocator awareness +//============================================================================== + +void test_get_allocator() +{ + string s("Hello"); + string::allocator_type alloc = s.get_allocator(); + + // Can allocate/deallocate + char* p = alloc.allocate(10); + alloc.deallocate(p, 10); +} + +//============================================================================== +// SECTION 22: Special cases and edge cases +//============================================================================== + +void test_embedded_nulls() +{ + // String with embedded nulls + string s("Hello\0World", 11); + BOOST_TEST_EQ(s.size(), 11u); + BOOST_TEST_EQ(s[5], '\0'); + BOOST_TEST_EQ(s[6], 'W'); + + // Find with embedded null + BOOST_TEST_EQ(s.find('\0'), 5u); + + // Substr with embedded null + string sub = s.substr(6); + BOOST_TEST(sub == "World"); + + // Comparison with embedded nulls + string s2("Hello\0World", 11); + string s3("Hello\0Xorld", 11); + BOOST_TEST(s == s2); + BOOST_TEST(s != s3); +} + +void test_self_operations() +{ + // Self-assignment + string s("Hello"); + s = return_self(s); + BOOST_TEST(s == "Hello"); + + // Self-append via substring + s = "Hello"; + s.append(s.data(), 2); + BOOST_TEST(s == "HelloHe"); + + // Self-insert + s = "Hello"; + s.insert(2, s.data(), 2); + BOOST_TEST(s == "HeHello"); +} + +void test_long_strings() +{ + // Test SSO boundary crossing + string s; + for (int i = 0; i < 1000; ++i) { + s.push_back('a'); + } + BOOST_TEST_EQ(s.size(), 1000u); + BOOST_TEST(s.capacity() >= 1000u); + + // All chars should be 'a' + for (std::size_t i = 0, imax = s.size(); i != imax; ++i) { + BOOST_TEST_EQ(s[i], 'a'); + } + + // Clear and reuse + s.clear(); + BOOST_TEST(s.empty()); + s = "Hello"; + BOOST_TEST(s == "Hello"); +} + +void test_move_operations() +{ + string s1("Hello, World!"); + string s2(boost::move(s1)); + BOOST_TEST(s2 == "Hello, World!"); + + string s3; + s3 = boost::move(s2); + BOOST_TEST(s3 == "Hello, World!"); + + // Move-assign to self (implementation-defined, but should work) + s3 = boost::move(s3); + // s3 is in valid state +} + +void test_iterator_invalidation() +{ + string s("Hello"); + + // Get iterators + string::iterator it = s.begin(); + string::iterator end = s.end(); + BOOST_TEST_LT(it, end); + + // Operations that might invalidate + s.reserve(1000); + // Iterators may be invalid now, but string content should be same + BOOST_TEST(s == "Hello"); + + // New iterators are valid + BOOST_TEST_EQ(*s.begin(), 'H'); + BOOST_TEST_EQ(s.end() - s.begin(), 5); +} + +//============================================================================== +// SECTION 23: Boost.Container specific features +//============================================================================== + +void test_with_allocator() +{ + typedef basic_string< + char, + std::char_traits, + std::allocator + > string_with_alloc; + + string_with_alloc s1("Hello"); + BOOST_TEST(s1 == "Hello"); + + string_with_alloc s2(s1); + BOOST_TEST(s2 == s1); + + s2 = "World"; + BOOST_TEST(s2 == "World"); +} + +// Test stable growth (specific to boost::container) +void test_growth_factor() +{ + string s; + std::size_t prev_cap = s.capacity(); + + // Push elements and verify capacity grows + for (int i = 0; i < 100; ++i) { + s.push_back('x'); + if (s.capacity() != prev_cap) { + // Capacity should grow (typically by factor > 1) + BOOST_TEST(s.capacity() > prev_cap); + prev_cap = s.capacity(); + } + } +} + +//============================================================================== +// SECTION 24: Interoperability with std::string +//============================================================================== + +void test_std_string_interop() +{ + // Construct from std::string + std::string std_str("Hello"); + string bc_str(std_str.begin(), std_str.end()); + BOOST_TEST(bc_str == "Hello"); + + // Convert to std::string + std::string back(bc_str.begin(), bc_str.end()); + BOOST_TEST(back == "Hello"); + + // Compare via c_str + BOOST_TEST_EQ(std::strcmp(bc_str.c_str(), std_str.c_str()), 0); +} + +//============================================================================== +// SECTION 25: Additional Boost.Container string methods +//============================================================================== + +void test_reserve_and_shrink() +{ + string s; + + // Test reserve with exact allocation + s.reserve(100); + BOOST_TEST(s.capacity() >= 100u); + + s = "Hello"; + s.shrink_to_fit(); + BOOST_TEST(s.capacity() >= s.size()); +} + +//============================================================================== +// Main test runner +//============================================================================== + +void test_with_lightweight_test() +{ + // Type traits + test_type_traits(); + + // Constructors + test_default_constructor(); + test_allocator_constructor(); + test_count_char_constructor(); + test_substring_constructor(); + test_cstring_constructor(); + test_iterator_constructor(); + test_copy_constructor(); + test_move_constructor(); + test_initializer_list_constructor(); +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + test_string_view_constructor(); +#endif + test_default_init_constructor(); + + // Assignment operators + test_copy_assignment(); + test_move_assignment(); + test_cstring_assignment(); + test_char_assignment(); + test_initializer_list_assignment(); +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + test_string_view_assignment(); +#endif + + // assign() methods + test_assign_count_char(); + test_assign_string(); + test_assign_substring(); + test_assign_move(); + test_assign_cstring(); + test_assign_iterators(); + test_assign_initializer_list(); + + // Element access + test_at(); + test_operator_bracket(); + test_front(); + test_back(); + test_data(); + test_c_str(); +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + test_string_view_conversion(); +#endif + + // Iterators + test_begin_end(); + test_cbegin_cend(); + test_rbegin_rend(); + test_crbegin_crend(); + test_iterator_arithmetic(); + + // Capacity + test_empty(); + test_size_length(); + test_max_size(); + test_reserve(); + test_capacity(); + test_shrink_to_fit(); + + // Operations - clear, insert, erase + test_clear(); + test_insert_char(); + test_insert_cstring(); + test_insert_string(); + test_insert_iterator(); + test_insert_initializer_list(); + test_erase_member(); + + // Operations - push_back, pop_back, append + test_push_back(); + test_pop_back(); + test_append_string(); + test_append_cstring(); + test_append_char(); + test_append_iterators(); + test_append_initializer_list(); + test_operator_plus_equals(); + + // Operations - compare + test_compare(); + + // Operations - starts_with, ends_with, contains + test_starts_with(); + test_ends_with(); + test_contains(); + + // Operations - replace + test_replace_pos(); + test_replace_iterator(); + + // Operations - substr + test_substr(); + + // Operations - copy + test_copy(); + + // Operations - resize + test_resize(); + test_resize_default_init(); + + // Operations - swap + test_swap(); + + // Search operations + test_find(); + test_rfind(); + test_find_first_of(); + test_find_last_of(); + test_find_first_not_of(); + test_find_last_not_of(); + + // Non-member operators + test_concatenation_operator(); + test_comparison_operators(); + + // I/O + test_stream_output(); + test_stream_input(); + test_getline(); + + // Hash and utilities + test_hash(); + test_std_swap(); + + // Allocator + test_get_allocator(); + + // Special cases + test_embedded_nulls(); + test_self_operations(); + test_long_strings(); + test_move_operations(); + test_iterator_invalidation(); + + // Boost.Container specific + test_with_allocator(); + test_growth_factor(); + + // Interoperability + test_std_string_interop(); + test_reserve_and_shrink(); +} + int main() { if(string_test()){ @@ -606,5 +2499,7 @@ int main() "has_trivial_destructor_after_move(std::allocator) test failed"); } + test_with_lightweight_test(); + return boost::report_errors(); }