見出し画像

ChatGPT4o に c++ STL のテスターを生成させてみた

ChatGPT4o にc++ STLのテスターを生成させてみました。

対象:
std::vector
std::string
std::shared_ptr<>
std::map<>

STLの大半の機能を網羅的にテストするコードが生成されました。

#include <vector>
#include <map>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <stdexcept>
#include <memory>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sublibc.h>
#include <submath.h>

void testVectorInitialization() {
    std::vector<int> vec;
    _ASSERT(vec.empty(), "Vector should be empty upon initialization");
    _ASSERT(vec.size() == 0, "Vector size should be 0 upon initialization");
    printf("[OK] testVectorInitialization()\n");
}

void testVectorPushBack() {
    std::vector<int> vec;
    vec.push_back(1);
    _ASSERT(vec.size() == 1, "Vector size should be 1 after one push_back");
    _ASSERT(vec[0] == 1, "Vector element should be 1 after push_back(1)");
    printf("[OK] testVectorPushBack()\n");
}

void testVectorAccess() {
    std::vector<int> vec = {1, 2, 3};
    _ASSERT(vec[0] == 1, "First element should be 1");
    _ASSERT(vec[1] == 2, "Second element should be 2");
    _ASSERT(vec[2] == 3, "Third element should be 3");
    printf("[OK] testVectorAccess()\n");
}

void testVectorResize() {
    std::vector<int> vec(5);
    _ASSERT(vec.size() == 5, "Vector size should be 5 after initialization with size 5");
    vec.resize(10);
    _ASSERT(vec.size() == 10, "Vector size should be 10 after resizing to 10");
    printf("[OK] testVectorResize()\n");
}

void testVectorPopBack() {
    std::vector<int> vec = {1, 2, 3};
    vec.pop_back();
    _ASSERT(vec.size() == 2, "Vector size should be 2 after one pop_back");
    _ASSERT(vec[0] == 1, "First element should still be 1");
    _ASSERT(vec[1] == 2, "Second element should still be 2");
    printf("[OK] testVectorPopBack()\n");
}

void testVectorClear() {
    std::vector<int> vec = {1, 2, 3};
    vec.clear();
    _ASSERT(vec.empty(), "Vector should be empty after clear");
    _ASSERT(vec.size() == 0, "Vector size should be 0 after clear");
    printf("[OK] testVectorClear()\n");
}

void testVectorInsert() {
    std::vector<int> vec = {1, 3};
    vec.insert(vec.begin() + 1, 2);
    _ASSERT(vec.size() == 3, "Vector size should be 3 after insert");
    _ASSERT(vec[0] == 1, "First element should be 1");
    _ASSERT(vec[1] == 2, "Second element should be 2");
    _ASSERT(vec[2] == 3, "Third element should be 3");
    printf("[OK] testVectorInsert()\n");
}

void testVectorErase() {
    std::vector<int> vec = {1, 2, 3};
    vec.erase(vec.begin() + 1);
    _ASSERT(vec.size() == 2, "Vector size should be 2 after erase");
    _ASSERT(vec[0] == 1, "First element should be 1");
    _ASSERT(vec[1] == 3, "Second element should be 3");
    printf("[OK] testVectorErase()\n");
}

void testVectorSwap() {
    std::vector<int> vec1 = {1, 2};
    std::vector<int> vec2 = {3, 4, 5};
    vec1.swap(vec2);
    _ASSERT(vec1.size() == 3, "vec1 size should be 3 after swap");
    _ASSERT(vec2.size() == 2, "vec2 size should be 2 after swap");
    _ASSERT(vec1[0] == 3, "vec1's first element should be 3 after swap");
    _ASSERT(vec2[0] == 1, "vec2's first element should be 1 after swap");
    printf("[OK] testVectorSwap()\n");
}

void testVectorCapacity() {
    std::vector<int> vec;
    vec.reserve(10);
    _ASSERT(vec.capacity() == 10, "Vector capacity should be 10 after reserve(10)");
    vec.push_back(1);
    vec.shrink_to_fit();
    _ASSERT(vec.capacity() >= 1, "Vector capacity should be at least 1 after shrink_to_fit");
    printf("[OK] testVectorCapacity()\n");
}

void testVectorEmplace() {
    std::vector<int> vec;
    vec.emplace(vec.begin(), 1);
    _ASSERT(vec.size() == 1, "Vector size should be 1 after emplace");
    _ASSERT(vec[0] == 1, "First element should be 1 after emplace");
    vec.emplace(vec.end(), 2);
    _ASSERT(vec.size() == 2, "Vector size should be 2 after emplacing at end");
    _ASSERT(vec[1] == 2, "Second element should be 2 after emplacing at end");
    printf("[OK] testVectorEmplace()\n");
}

void testVectorFrontBack() {
    std::vector<int> vec = {1, 2, 3};
    _ASSERT(vec.front() == 1, "First element should be 1");
    _ASSERT(vec.back() == 3, "Last element should be 3");
    vec.front() = 0;
    vec.back() = 4;
    _ASSERT(vec.front() == 0, "First element should be 0 after modification");
    _ASSERT(vec.back() == 4, "Last element should be 4 after modification");
    printf("[OK] testVectorFrontBack()\n");
}

void testVectorAssign() {
    std::vector<int> vec;
    vec.assign(5, 10);
    _ASSERT(vec.size() == 5, "Vector size should be 5 after assign");
    _ASSERT(vec[0] == 10, "All elements should be 10 after assign");
    _ASSERT(vec[4] == 10, "All elements should be 10 after assign");
    std::vector<int> vec2;
    vec2.assign(vec.begin(), vec.end());
    _ASSERT(vec2.size() == 5, "Vector size should be 5 after range assign");
    _ASSERT(vec2[0] == 10, "All elements should be 10 after range assign");
    _ASSERT(vec2[4] == 10, "All elements should be 10 after range assign");
    printf("[OK] testVectorAssign()\n");
}

void testVectorData() {
    std::vector<int> vec = {1, 2, 3};
    int* data = vec.data();
    _ASSERT(data[0] == 1, "Data pointer's first element should be 1");
    _ASSERT(data[1] == 2, "Data pointer's second element should be 2");
    _ASSERT(data[2] == 3, "Data pointer's third element should be 3");
    data[0] = 0;
    _ASSERT(vec[0] == 0, "Vector's first element should be 0 after modifying data pointer");
    printf("[OK] testVectorData()\n");
}

void testVectorMove() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = std::move(vec1);
    _ASSERT(vec1.empty(), "vec1 should be empty after move");
    _ASSERT(vec2.size() == 3, "vec2 should have size 3 after move");
    _ASSERT(vec2[0] == 1, "vec2's first element should be 1 after move");
    printf("[OK] testVectorMove()\n");
}

void testVectorEquality() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = {1, 2, 3};
    std::vector<int> vec3 = {1, 2, 4};
    _ASSERT(vec1 == vec2, "vec1 and vec2 should be equal");
    _ASSERT(!(vec1 == vec3), "vec1 and vec3 should not be equal");
    printf("[OK] testVectorEquality()\n");
}

void testVectorInequality() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = {1, 2, 3};
    std::vector<int> vec3 = {1, 2, 4};
    _ASSERT(!(vec1 != vec2), "vec1 and vec2 should not be unequal");
    _ASSERT(vec1 != vec3, "vec1 and vec3 should be unequal");
    printf("[OK] testVectorInequality()\n");
}

void testVectorComparisonOperators() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = {1, 2, 3};
    std::vector<int> vec3 = {1, 2, 4};
    _ASSERT(vec1 <= vec2, "vec1 should be less than or equal to vec2");
    _ASSERT(vec1 < vec3, "vec1 should be less than vec3");
    _ASSERT(vec3 > vec1, "vec3 should be greater than vec1");
    _ASSERT(vec3 >= vec2, "vec3 should be greater than or equal to vec2");
    printf("[OK] testVectorComparisonOperators()\n");
}

void testVectorIterator() {
    std::vector<int> vec = {1, 2, 3};
    std::vector<int>::iterator it = vec.begin();
    _ASSERT(*it == 1, "First element should be 1");
    ++it;
    _ASSERT(*it == 2, "Second element should be 2");
    ++it;
    _ASSERT(*it == 3, "Third element should be 3");
    printf("[OK] testVectorIterator()\n");
}

void testVectorReverseIterator() {
    std::vector<int> vec = {1, 2, 3};
    std::vector<int>::reverse_iterator rit = vec.rbegin();
    _ASSERT(*rit == 3, "First reverse element should be 3");
    ++rit;
    _ASSERT(*rit == 2, "Second reverse element should be 2");
    ++rit;
    _ASSERT(*rit == 1, "Third reverse element should be 1");
    printf("[OK] testVectorReverseIterator()\n");
}

void testVectorCopy() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = vec1;
    _ASSERT(vec1 == vec2, "vec1 and vec2 should be equal after copy");
    vec1[0] = 0;
    _ASSERT(vec1 != vec2, "vec1 and vec2 should not be equal after modifying vec1");
    printf("[OK] testVectorCopy()\n");
}

void testVectorAllocator() {
    std::vector<int> vec;
    std::allocator<int> alloc = vec.get_allocator();
    int* p = alloc.allocate(1);
    std::allocator_traits<std::allocator<int>>::construct(alloc, p, 1);
    _ASSERT(*p == 1, "Allocated and constructed element should be 1");
    std::allocator_traits<std::allocator<int>>::destroy(alloc, p);
    alloc.deallocate(p, 1);
    printf("[OK] testVectorAllocator()\n");
}

void testVectorEmplaceBack() {
    std::vector<int> vec;
    vec.emplace_back(1);
    _ASSERT(vec.size() == 1, "Vector size should be 1 after emplace_back");
    _ASSERT(vec[0] == 1, "First element should be 1 after emplace_back");
    vec.emplace_back(2);
    _ASSERT(vec.size() == 2, "Vector size should be 2 after second emplace_back");
    _ASSERT(vec[1] == 2, "Second element should be 2 after second emplace_back");
    printf("[OK] testVectorEmplaceBack()\n");
}

void testVectorReserve() {
    std::vector<int> vec;
    vec.reserve(10);
    _ASSERT(vec.capacity() == 10, "Vector capacity should be 10 after reserve");
    vec.push_back(1);
    _ASSERT(vec.size() == 1, "Vector size should be 1 after push_back");
    _ASSERT(vec.capacity() == 10, "Vector capacity should remain 10 after push_back");
    printf("[OK] testVectorReserve()\n");
}

void testVectorShrinkToFit() {
    std::vector<int> vec;
    vec.reserve(10);
    vec.push_back(1);
    vec.shrink_to_fit();
    _ASSERT(vec.capacity() >= vec.size(), "Vector capacity should be at least equal to its size after shrink_to_fit");
    printf("[OK] testVectorShrinkToFit()\n");
}

void testVectorAssignRange() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2;
    vec2.assign(vec1.begin(), vec1.end());
    _ASSERT(vec2.size() == vec1.size(), "Vector size should be equal to the assigned range size");
    _ASSERT(vec2 == vec1, "Vector elements should be equal to the assigned range elements");
    printf("[OK] testVectorAssignRange()\n");
}

void testVectorAssignFill() {
    std::vector<int> vec;
    vec.assign(5, 10);
    _ASSERT(vec.size() == 5, "Vector size should be 5 after fill assign");
    _ASSERT(vec[0] == 10, "First element should be 10 after fill assign");
    _ASSERT(vec[4] == 10, "Last element should be 10 after fill assign");
    printf("[OK] testVectorAssignFill()\n");
}

void testVectorClear2() {
    std::vector<int> vec = {1, 2, 3};
    vec.clear();
    _ASSERT(vec.empty(), "Vector should be empty after clear");
    _ASSERT(vec.size() == 0, "Vector size should be 0 after clear");
    printf("[OK] testVectorClear2()\n");
}

void testVectorBack() {
    std::vector<int> vec = {1, 2, 3};
    _ASSERT(vec.back() == 3, "Last element should be 3");
    vec.back() = 4;
    _ASSERT(vec.back() == 4, "Last element should be 4 after modification");
    printf("[OK] testVectorBack()\n");
}

void testVectorFront() {
    std::vector<int> vec = {1, 2, 3};
    _ASSERT(vec.front() == 1, "First element should be 1");
    vec.front() = 0;
    _ASSERT(vec.front() == 0, "First element should be 0 after modification");
    printf("[OK] testVectorFront()\n");
}

void testVectorMaxSize() {
    std::vector<int> vec;
    _ASSERT(vec.max_size() > 0, "Vector max_size should be greater than 0");
    printf("[OK] testVectorMaxSize()\n");
}

void testVectorResizeWithDefaultValue() {
    std::vector<int> vec(5, 1);
    vec.resize(10, 2);
    _ASSERT(vec.size() == 10, "Vector size should be 10 after resizing to 10");
    _ASSERT(vec[5] == 2, "New elements should be initialized to 2");
    _ASSERT(vec[9] == 2, "Last element should be 2 after resizing");
    printf("[OK] testVectorResizeWithDefaultValue()\n");
}

void testVectorEmptyComparison() {
    std::vector<int> vec1;
    std::vector<int> vec2;
    _ASSERT(vec1 == vec2, "Two empty vectors should be equal");
    vec1.push_back(1);
    _ASSERT(vec1 != vec2, "An empty vector and a non-empty vector should not be equal");
    printf("[OK] testVectorEmptyComparison()\n");
}

void testVectorCapacityGrowth() {
    std::vector<int> vec;
    vec.push_back(1);
    size_t initial_capacity = vec.capacity();
    for (int i = 0; i < 100; ++i) {
        vec.push_back(i);
    }
    _ASSERT(vec.capacity() > initial_capacity, "Vector capacity should grow as elements are added");
    printf("[OK] testVectorCapacityGrowth()\n");
}

void testVectorDefaultConstructor() {
    std::vector<int> vec;
    _ASSERT(vec.empty(), "Vector should be empty after default construction");
    printf("[OK] testVectorDefaultConstructor()\n");
}

void testVectorMoveConstructor() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2 = std::move(vec1);
    _ASSERT(vec1.empty(), "vec1 should be empty after move construction");
    _ASSERT(vec2.size() == 3, "vec2 should have size 3 after move construction");
    _ASSERT(vec2[0] == 1, "vec2's first element should be 1 after move construction");
    printf("[OK] testVectorMoveConstructor()\n");
}

void testVectorMoveAssignment() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2;
    vec2 = std::move(vec1);
    _ASSERT(vec1.empty(), "vec1 should be empty after move assignment");
    _ASSERT(vec2.size() == 3, "vec2 should have size 3 after move assignment");
    _ASSERT(vec2[0] == 1, "vec2's first element should be 1 after move assignment");
    printf("[OK] testVectorMoveAssignment()\n");
}

void testVectorLarge() {
    std::vector<int> vec;
    for (int i = 0; i < 1000; ++i) {
        vec.push_back(i);
    }
    _ASSERT(vec.size() == 1000, "Vector size should be 1,000 after adding 1,000 elements");
    _ASSERT(vec[999] == 999, "Last element should be 999");
    printf("[OK] testVectorLarge()\n");
}

void testVectorPointerStability() {
    std::vector<int> vec = {1, 2, 3};
    vec.reserve(10); // 再配置を防ぐために事前に容量を確保
    int* ptr = &vec[1];
    vec.push_back(4);
    _ASSERT(*ptr == 2, "Pointer should still point to the second element (2)");
    printf("[OK] testVectorPointerStability()\n");
}


class TestObject {
public:
    static int destructCount;
    TestObject() {}
    ~TestObject() { ++destructCount; }
};

int TestObject::destructCount = 0;

void testVectorObjectDestruction() {
    {
        std::vector<TestObject> vec(5);
    }
    _ASSERT(TestObject::destructCount == 5, "Destructors should be called 5 times for 5 elements");
    printf("[OK] testVectorObjectDestruction()\n");
}

void testVectorOfPointers() {
    std::vector<int*> vec;
    int a = 1, b = 2, c = 3;
    vec.push_back(&a);
    vec.push_back(&b);
    vec.push_back(&c);
    _ASSERT(*vec[0] == 1, "First element should point to 1");
    _ASSERT(*vec[1] == 2, "Second element should point to 2");
    _ASSERT(*vec[2] == 3, "Third element should point to 3");
    printf("[OK] testVectorOfPointers()\n");
}

void testStringInitialization() {
    std::string str1;
    _ASSERT(str1.empty(), "String should be empty upon initialization");

    std::string str2("Hello");
    _ASSERT(str2 == "Hello", "String should be initialized to 'Hello'");
    
    std::string str3(str2);
    _ASSERT(str3 == str2, "String should be copy-initialized to 'Hello'");
    
    printf("[OK] testStringInitialization()\n");
}

void testStringAppend() {
    std::string str = "Hello";
    str.append(" World");
    _ASSERT(str == "Hello World", "String should be 'Hello World' after append");
    
    str += "!";
    _ASSERT(str == "Hello World!", "String should be 'Hello World!' after append");
    
    printf("[OK] testStringAppend()\n");
}

void testStringAccess() {
    std::string str = "Hello";
    _ASSERT(str[0] == 'H', "First character should be 'H'");
    _ASSERT(str.at(1) == 'e', "Second character should be 'e'");
    _ASSERT(str.back() == 'o', "Last character should be 'o'");
    _ASSERT(str.front() == 'H', "First character should be 'H'");
    
    printf("[OK] testStringAccess()\n");
}

void testStringLengthAndEmpty() {
    std::string str = "Hello";
    _ASSERT(str.length() == 5, "String length should be 5");
    _ASSERT(!str.empty(), "String should not be empty");

    str.clear();
    _ASSERT(str.empty(), "String should be empty after clear");
    
    printf("[OK] testStringLengthAndEmpty()\n");
}

void testStringComparison() {
    std::string str1 = "Hello";
    std::string str2 = "World";
    std::string str3 = "Hello";
    
    _ASSERT(str1 == str3, "str1 and str3 should be equal");
    _ASSERT(str1 != str2, "str1 and str2 should not be equal");
    _ASSERT(str1 < str2, "str1 should be less than str2");
    
    printf("[OK] testStringComparison()\n");
}

void testStringSubstr() {
    std::string str = "Hello World";
    std::string substr = str.substr(6, 5);
    _ASSERT(substr == "World", "Substring should be 'World'");
    
    printf("[OK] testStringSubstr()\n");
}

void testStringFind() {
    std::string str = "Hello World";
    size_t pos = str.find("World");
    _ASSERT(pos == 6, "Position of 'World' should be 6");
    
    pos = str.find("world");
    _ASSERT(pos == std::string::npos, "Position of 'world' should be npos (not found)");
    
    printf("[OK] testStringFind()\n");
}

void testStringReplace() {
    std::string str = "Hello World";
    str.replace(6, 5, "Universe");
    _ASSERT(str == "Hello Universe", "String should be 'Hello Universe' after replace");
    
    printf("[OK] testStringReplace()\n");
}

void testStringInsert() {
    std::string str = "Hello World";
    str.insert(6, "Beautiful ");
    _ASSERT(str == "Hello Beautiful World", "String should be 'Hello Beautiful World' after insert");
    
    printf("[OK] testStringInsert()\n");
}

void testStringErase() {
    std::string str = "Hello Beautiful World";
    str.erase(6, 10);
    _ASSERT(str == "Hello World", "String should be 'Hello World' after erase");
    
    printf("[OK] testStringErase()\n");
}

void testStringConcatenation() {
    std::string str1 = "Hello";
    std::string str2 = "World";
    std::string str3 = str1 + " " + str2;
    _ASSERT(str3 == "Hello World", "Concatenated string should be 'Hello World'");
    printf("[OK] testStringConcatenation()\n");
}

void testStringSplit() {
    std::string str = "Hello World";
    size_t pos = str.find(' ');
    std::string first = str.substr(0, pos);
    std::string second = str.substr(pos + 1);
    _ASSERT(first == "Hello", "First part should be 'Hello'");
    _ASSERT(second == "World", "Second part should be 'World'");
    printf("[OK] testStringSplit()\n");
}

void testStringCStr() {
    std::string str = "Hello World";
    const char* cstr = str.c_str();
    _ASSERT(std::strcmp(cstr, "Hello World") == 0, "C-string should be 'Hello World'");
    printf("[OK] testStringCStr()\n");
}

void testStringClear() {
    std::string str = "Hello World";
    str.clear();
    _ASSERT(str.empty(), "String should be empty after clear");
    _ASSERT(str.length() == 0, "String length should be 0 after clear");
    printf("[OK] testStringClear()\n");
}

void testStringReserve() {
    std::string str;
    str.reserve(50);
    _ASSERT(str.capacity() >= 50, "String capacity should be at least 50 after reserve");
    str = "Hello World";
    _ASSERT(str.capacity() >= 50, "String capacity should remain at least 50 after assignment");
    printf("[OK] testStringReserve()\n");
}

void testStringSwap() {
    std::string str1 = "Hello";
    std::string str2 = "World";
    str1.swap(str2);
    _ASSERT(str1 == "World", "str1 should be 'World' after swap");
    _ASSERT(str2 == "Hello", "str2 should be 'Hello' after swap");
    printf("[OK] testStringSwap()\n");
}

void testStringCopy() {
    std::string str = "Hello World";
    char buffer[6];
    str.copy(buffer, 5, 0);
    buffer[5] = '\0';
    _ASSERT(strcmp(buffer, "Hello") == 0, "Buffer should contain 'Hello' after copy");
    printf("[OK] testStringCopy()\n");
}

void testStringResize() {
    std::string str = "Hello";
    str.resize(10, 'x');
    _ASSERT(str == "Helloxxxxx", "String should be 'Helloxxxxx' after resize");
    str.resize(5);
    _ASSERT(str == "Hello", "String should be 'Hello' after resize back to 5");
    printf("[OK] testStringResize()\n");
}

void testStringCapacity() {
    std::string str = "Hello";
    _ASSERT(str.capacity() >= str.size(), "String capacity should be at least equal to its size");
    str.reserve(50);
    _ASSERT(str.capacity() >= 50, "String capacity should be at least 50 after reserve");
    printf("[OK] testStringCapacity()\n");
}

void testStringShrinkToFit() {
    std::string str = "Hello";
    str.reserve(50);
    _ASSERT(str.capacity() >= 50, "String capacity should be at least 50 after reserve");
    str.shrink_to_fit();
    _ASSERT(str.capacity() < 50, "String capacity should be less than 50 after shrink_to_fit");
    printf("[OK] testStringShrinkToFit()\n");
}

void testStringFindFirstOf() {
    std::string str = "Hello World";
    size_t pos = str.find_first_of("aeiou");
    _ASSERT(pos == 1, "First vowel should be at position 1");
    printf("[OK] testStringFindFirstOf()\n");
}

void testStringFindLastOf() {
    std::string str = "Hello World";
    size_t pos = str.find_last_of("aeiou");
    _ASSERT(pos == 7, "Last vowel should be at position 7");
    printf("[OK] testStringFindLastOf()\n");
}

void testStringFindFirstNotOf() {
    std::string str = "Hello World";
    size_t pos = str.find_first_not_of("Helo Wrd");
    _ASSERT(pos == std::string::npos, "There should be no characters not in 'Helo Wrd'");
    printf("[OK] testStringFindFirstNotOf()\n");
}

void testStringFindLastNotOf() {
    std::string str = "Hello World";
    size_t pos = str.find_last_not_of("Helo Wrd");
    _ASSERT(pos == std::string::npos, "There should be no characters not in 'Helo Wrd'");
    printf("[OK] testStringFindLastNotOf()\n");
}

void testStringRFind() {
    std::string str = "Hello World World";
    size_t pos = str.rfind("World");
    _ASSERT(pos == 12, "Last occurrence of 'World' should be at position 12");
    printf("[OK] testStringRFind()\n");
}

void testStringCompare() {
    std::string str1 = "Hello";
    std::string str2 = "World";
    std::string str3 = "Hello";
    
    _ASSERT(str1.compare(str2) < 0, "str1 should be less than str2");
    _ASSERT(str1.compare(str3) == 0, "str1 should be equal to str3");
    _ASSERT(str2.compare(str1) > 0, "str2 should be greater than str1");
    
    printf("[OK] testStringCompare()\n");
}

void testStringAppendMultiple() {
    std::string str = "Hello";
    str.append(" World").append("!").append(" Welcome!");
    _ASSERT(str == "Hello World! Welcome!", "String should be 'Hello World! Welcome!' after multiple appends");
    printf("[OK] testStringAppendMultiple()\n");
}

void testStringAssign() {
    std::string str;
    str.assign("Hello");
    _ASSERT(str == "Hello", "String should be 'Hello' after assign");
    
    std::string str2;
    str2.assign(str, 0, 4);
    _ASSERT(str2 == "Hell", "String should be 'Hell' after assign with position and length");
    
    printf("[OK] testStringAssign()\n");
}

void testStringToString() {
    int num = 12345;
    std::string str = std::to_string(num);
    _ASSERT(str == "12345", "String should be '12345' after to_string");
    printf("[OK] testStringToString()\n");
}

void testStringStoi() {
    std::string str = "12345";
    int num = std::stoi(str);
    _ASSERT(num == 12345, "Integer should be 12345 after stoi");
    printf("[OK] testStringStoi()\n");
}

void testStringSubstrEdgeCases() {
    std::string str = "Hello";
    std::string substr = str.substr(5);
    _ASSERT(substr == "", "Substring from the end should be empty");
    
    substr = str.substr(0, 10);
    _ASSERT(substr == "Hello", "Substring with length exceeding the string should return the entire string");
    
    printf("[OK] testStringSubstrEdgeCases()\n");
}

void testStringEmpty() {
    std::string str = "";
    _ASSERT(str.empty(), "String should be empty after default construction with empty string");
    _ASSERT(str.length() == 0, "String length should be 0 for empty string");
    printf("[OK] testStringEmpty()\n");
}

void testStringCStrConsistency() {
    std::string str = "Hello";
    const char* cstr1 = str.c_str();
    const char* cstr2 = str.c_str();
    _ASSERT(cstr1 == cstr2, "c_str() should return the same pointer for the same string");
    printf("[OK] testStringCStrConsistency()\n");
}

void testStringAppendEdgeCases() {
    std::string str;
    str.append("");
    _ASSERT(str == "", "String should remain empty after appending an empty string");
    
    str.append("Non-empty");
    _ASSERT(str == "Non-empty", "String should be 'Non-empty' after appending a non-empty string");
    
    printf("[OK] testStringAppendEdgeCases()\n");
}

void testStringOperatorPlusEqual() {
    std::string str = "Hello";
    str += " World";
    _ASSERT(str == "Hello World", "String should be 'Hello World' after operator+=");
    str += '!';
    _ASSERT(str == "Hello World!", "String should be 'Hello World!' after operator+= with char");
    printf("[OK] testStringOperatorPlusEqual()\n");
}

void testStringPushBack() {
    std::string str = "Hello";
    str.push_back(' ');
    str.push_back('W');
    str.push_back('o');
    str.push_back('r');
    str.push_back('l');
    str.push_back('d');
    _ASSERT(str == "Hello World", "String should be 'Hello World' after push_back");
    printf("[OK] testStringPushBack()\n");
}

void testStringPopBack() {
    std::string str = "Hello!";
    str.pop_back();
    _ASSERT(str == "Hello", "String should be 'Hello' after pop_back");
    printf("[OK] testStringPopBack()\n");
}

void testStringReplaceEdgeCases() {
    std::string str = "Hello World";
    str.replace(0, 5, "Hi");
    _ASSERT(str == "Hi World", "String should be 'Hi World' after replace first part");
    str.replace(3, 5, "Universe");
    _ASSERT(str == "Hi Universe", "String should be 'Hi Universe' after replace middle part");
    printf("[OK] testStringReplaceEdgeCases()\n");
}

void testStringGetline() {
    std::stringstream ss("Hello World\nWelcome to the string tests");
    std::string str;
    std::getline(ss, str);
    _ASSERT(str == "Hello World", "First line should be 'Hello World'");
    std::getline(ss, str);
    _ASSERT(str == "Welcome to the string tests", "Second line should be 'Welcome to the string tests'");
    printf("[OK] testStringGetline()\n");
}

void testStringFrontBackEdgeCases() {
    std::string str = "A";
    _ASSERT(str.front() == 'A', "Front should be 'A' for single character string");
    _ASSERT(str.back() == 'A', "Back should be 'A' for single character string");
    str = "AB";
    _ASSERT(str.front() == 'A', "Front should be 'A' for 'AB'");
    _ASSERT(str.back() == 'B', "Back should be 'B' for 'AB'");
    printf("[OK] testStringFrontBackEdgeCases()\n");
}

void testStringAtException() {
    std::string str = "Hello";
    try {
        str.at(10); // This should throw an out_of_range exception
        _ASSERT(false, "Accessing out of range should throw an exception");
    } catch (const std::out_of_range&) {
        _ASSERT(true, "Accessing out of range correctly throws an exception");
        printf("[OK] testStringAtException()\n");
    }
}

void testStringCapacitySizeComparison() {
    std::string str = "Hello";
    _ASSERT(str.capacity() >= str.size(), "String capacity should be greater than or equal to size");
    printf("[OK] testStringCapacitySizeComparison()\n");
}

void testStringInsertEdgeCases() {
    std::string str = "Hello";
    str.insert(0, "Start ");
    _ASSERT(str == "Start Hello", "String should be 'Start Hello' after insert at beginning");
    str.insert(str.size(), " End");
    _ASSERT(str == "Start Hello End", "String should be 'Start Hello End' after insert at end");
    printf("[OK] testStringInsertEdgeCases()\n");
}

void testStringEraseEdgeCases() {
    std::string str = "Hello World";
    str.erase(0, 6);
    _ASSERT(str == "World", "String should be 'World' after erasing first part");
    str.erase(1, std::string::npos);
    _ASSERT(str == "W", "String should be 'W' after erasing from position 1 to end");
    printf("[OK] testStringEraseEdgeCases()\n");
}

void testStringFindFirstOfEdgeCases() {
    std::string str = "Hello World";
    size_t pos = str.find_first_of("xyz");
    _ASSERT(pos == std::string::npos, "No characters should be found");
    pos = str.find_first_of("H");
    _ASSERT(pos == 0, "First character should be 'H'");
    printf("[OK] testStringFindFirstOfEdgeCases()\n");
}

void testStringFindLastOfEdgeCases() {
    std::string str = "Hello World";
    size_t pos = str.find_last_of("xyz");
    _ASSERT(pos == std::string::npos, "No characters should be found");
    pos = str.find_last_of("d");
    _ASSERT(pos == str.size() - 1, "Last character should be 'd'");
    printf("[OK] testStringFindLastOfEdgeCases()\n");
}

void testStringFindFirstNotOfEdgeCases() {
    std::string str = "HHHHHello";
    size_t pos = str.find_first_not_of("H");
    _ASSERT(pos == 5, "First non-'H' character should be at position 5");
    pos = str.find_first_not_of("HHHHH");
    _ASSERT(pos == 5, "First non-'H' character should be at position 5");
    printf("[OK] testStringFindFirstNotOfEdgeCases()\n");
}

void testStringFindLastNotOfEdgeCases() {
    std::string str = "Hello!!!!!";
    size_t pos = str.find_last_not_of("!");
    _ASSERT(pos == 4, "Last non-'!' character should be at position 4");
    pos = str.find_last_not_of("!!!!!");
    _ASSERT(pos == 4, "Last non-'!' character should be at position 4");
    printf("[OK] testStringFindLastNotOfEdgeCases()\n");
}

void testStringAppendPerformance() {
    std::string str;
    for (int i = 0; i < 10000; ++i) {
        str.append("a");
    }
    _ASSERT(str.size() == 10000, "String size should be 10000 after appending 'a' 10000 times");
    printf("[OK] testStringAppendPerformance()\n");
}

void testStringReserveEdgeCases() {
    std::string str;
    str.reserve(0);
    _ASSERT((int)str.capacity() >= (int)0, "String capacity should be at least 0 after reserve(0)");
    str.reserve(100);
    _ASSERT(str.capacity() >= 100, "String capacity should be at least 100 after reserve(100)");
    printf("[OK] testStringReserveEdgeCases()\n");
}

void testStringShrinkToFitEdgeCases() {
    std::string str = "Hello";
    str.reserve(100);
    str.shrink_to_fit();
    _ASSERT(str.capacity() >= str.size(), "String capacity should be at least equal to size after shrink_to_fit");
    printf("[OK] testStringShrinkToFitEdgeCases()\n");
}

void testStringCopyEdgeCases() {
    std::string str = "Hello World";
    char buffer[12];
    str.copy(buffer, 5, 0);
    buffer[5] = '\0';
    _ASSERT(strcmp(buffer, "Hello") == 0, "Buffer should contain 'Hello' after copy");
    str.copy(buffer, 20, 0);
    buffer[11] = '\0';
    _ASSERT(strcmp(buffer, "Hello World") == 0, "Buffer should contain 'Hello World' after copying more than size");
    printf("[OK] testStringCopyEdgeCases()\n");
}

void testStringSwapEdgeCases() {
    std::string str1 = "Hello";
    std::string str2 = "World";
    str1.swap(str2);
    _ASSERT(str1 == "World", "str1 should be 'World' after swap");
    _ASSERT(str2 == "Hello", "str2 should be 'Hello' after swap");
    str1.swap(str2);
    _ASSERT(str1 == "Hello", "str1 should be 'Hello' after swap back");
    _ASSERT(str2 == "World", "str2 should be 'World' after swap back");
    printf("[OK] testStringSwapEdgeCases()\n");
}

void testMapInitialization() {
    std::map<int, std::string> m;
    _ASSERT(m.empty(), "Map should be empty upon initialization");
    printf("[OK] testMapInitialization()\n");
}

void testMapInsert() {
    std::map<int, std::string> m;
    m.insert({1, "one"});
    m.insert({2, "two"});
    m.insert({3, "three"});
    _ASSERT(m.size() == 3, "Map size should be 3 after three inserts");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one'");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two'");
    _ASSERT(m[3] == "three", "Element with key 3 should be 'three'");
    printf("[OK] testMapInsert()\n");
}

void testMapErase() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    m.erase(2);
    _ASSERT(m.size() == 2, "Map size should be 2 after erasing one element");
    _ASSERT(m.find(2) == m.end(), "Element with key 2 should not be found after erase");
    printf("[OK] testMapErase()\n");
}

void testMapFind() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    auto it = m.find(2);
    _ASSERT(it != m.end(), "Element with key 2 should be found");
    _ASSERT(it->second == "two", "Element with key 2 should be 'two'");
    it = m.find(4);
    _ASSERT(it == m.end(), "Element with key 4 should not be found");
    printf("[OK] testMapFind()\n");
}

void testMapSizeAndEmpty() {
    std::map<int, std::string> m;
    _ASSERT(m.empty(), "Map should be empty initially");
    m.insert({1, "one"});
    _ASSERT(m.size() == 1, "Map size should be 1 after one insert");
    _ASSERT(!m.empty(), "Map should not be empty after one insert");
    printf("[OK] testMapSizeAndEmpty()\n");
}

void testMapKeyRange() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    auto it = m.lower_bound(2);
    _ASSERT(it != m.end() && it->first == 2, "Lower bound of 2 should be 2");
    it = m.upper_bound(2);
    _ASSERT(it != m.end() && it->first == 3, "Upper bound of 2 should be 3");
    printf("[OK] testMapKeyRange()\n");
}

void testMapUpdate() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    m[2] = "updated";
    _ASSERT(m[2] == "updated", "Element with key 2 should be 'updated'");
    printf("[OK] testMapUpdate()\n");
}

void testMapIteration() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    std::string result;
    for (const auto& [key, value] : m) {
        result += value + " ";
    }
    _ASSERT(result == "one two three ", "Iteration result should be 'one two three '");
    printf("[OK] testMapIteration()\n");
}

void testMapOperatorSquareBrackets() {
    std::map<int, std::string> m;
    m[1] = "one";
    m[2] = "two";
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one'");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two'");
    printf("[OK] testMapOperatorSquareBrackets()\n");
}

void testMapAt() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    _ASSERT(m.at(1) == "one", "Element with key 1 should be 'one'");
    try {
        m.at(3);
        _ASSERT(false, "Accessing non-existent key should throw an exception");
    } catch (const std::out_of_range&) {
        printf("[OK] testMapAt()\n");
    }
}

void testMapClear() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    m.clear();
    _ASSERT(m.empty(), "Map should be empty after clear");
    _ASSERT(m.size() == 0, "Map size should be 0 after clear");
    printf("[OK] testMapClear()\n");
}

void testMapSwap() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2 = {{3, "three"}, {4, "four"}};
    m1.swap(m2);
    _ASSERT(m1.size() == 2, "m1 size should be 2 after swap");
    _ASSERT(m1[3] == "three", "m1 should contain key 3 with value 'three' after swap");
    _ASSERT(m2.size() == 2, "m2 size should be 2 after swap");
    _ASSERT(m2[1] == "one", "m2 should contain key 1 with value 'one' after swap");
    printf("[OK] testMapSwap()\n");
}

void testMapEmplace() {
    std::map<int, std::string> m;
    m.emplace(1, "one");
    m.emplace(2, "two");
    _ASSERT(m.size() == 2, "Map size should be 2 after emplace");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one' after emplace");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two' after emplace");
    printf("[OK] testMapEmplace()\n");
}

void testMapCount() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    _ASSERT(m.count(1) == 1, "Map should contain key 1");
    _ASSERT(m.count(3) == 0, "Map should not contain key 3");
    printf("[OK] testMapCount()\n");
}

void testMapConstructors() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2(m1);
    _ASSERT(m2.size() == 2, "Copied map should have size 2");
    _ASSERT(m2[1] == "one", "Copied map should contain key 1 with value 'one'");
    
    std::map<int, std::string> m3(std::move(m1));
    _ASSERT(m3.size() == 2, "Moved map should have size 2");
    _ASSERT(m1.empty(), "Original map should be empty after move");
    printf("[OK] testMapConstructors()\n");
}

void testMapCopyAndMove() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2 = m1;
    _ASSERT(m2.size() == 2, "Copied map should have size 2");
    _ASSERT(m2[1] == "one", "Copied map should contain key 1 with value 'one'");
    
    std::map<int, std::string> m3 = std::move(m1);
    _ASSERT(m3.size() == 2, "Moved map should have size 2");
    _ASSERT(m1.empty(), "Original map should be empty after move");
    printf("[OK] testMapCopyAndMove()\n");
}

void testMapEraseRange() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}};
    m.erase(m.find(2), m.find(4));
    _ASSERT(m.size() == 2, "Map size should be 2 after erasing a range");
    _ASSERT(m.find(2) == m.end(), "Element with key 2 should not be found after erase range");
    _ASSERT(m.find(3) == m.end(), "Element with key 3 should not be found after erase range");
    printf("[OK] testMapEraseRange()\n");
}

void testMapEqualRange() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    auto range = m.equal_range(2);
    _ASSERT(range.first->first == 2, "Lower bound should be 2");
    _ASSERT(range.second->first == 3, "Upper bound should be 3");
    printf("[OK] testMapEqualRange()\n");
}

void testMapEmplaceHint() {
    std::map<int, std::string> m;
    auto it = m.end();
    m.emplace_hint(it, 1, "one");
    m.emplace_hint(m.end(), 2, "two");
    _ASSERT(m.size() == 2, "Map size should be 2 after emplace_hint");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one' after emplace_hint");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two' after emplace_hint");
    printf("[OK] testMapEmplaceHint()\n");
}

void testMapBoundaries() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    auto lower = m.lower_bound(2);
    auto upper = m.upper_bound(2);
    _ASSERT(lower != m.end() && lower->first == 2, "Lower bound of 2 should be 2");
    _ASSERT(upper != m.end() && upper->first == 3, "Upper bound of 2 should be 3");
    printf("[OK] testMapBoundaries()\n");
}

void testMapCustomComparator() {
    auto cmp = [](int a, int b) { return a > b; };
    std::map<int, std::string, decltype(cmp)> m(cmp);
    m[1] = "one";
    m[2] = "two";
    m[3] = "three";
    auto it = m.begin();
    _ASSERT(it->first == 3, "First key should be 3 with custom comparator");
    ++it;
    _ASSERT(it->first == 2, "Second key should be 2 with custom comparator");
    ++it;
    _ASSERT(it->first == 1, "Third key should be 1 with custom comparator");
    printf("[OK] testMapCustomComparator()\n");
}

void testMapKeyCompValueComp() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    auto key_comp = m.key_comp();
    auto value_comp = m.value_comp();
    _ASSERT(key_comp(1, 2), "Key comparator should return true for 1 < 2");
    _ASSERT(!key_comp(2, 1), "Key comparator should return false for 2 > 1");
    _ASSERT(value_comp(*m.begin(), *std::next(m.begin())), "Value comparator should return true for (1, 'one') < (2, 'two')");
    printf("[OK] testMapKeyCompValueComp()\n");
}

void testMapRangeInsert() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2;
    m2.insert(m1.begin(), m1.end());
    _ASSERT(m2.size() == 2, "Map size should be 2 after range insert");
    _ASSERT(m2[1] == "one", "Element with key 1 should be 'one' after range insert");
    _ASSERT(m2[2] == "two", "Element with key 2 should be 'two' after range insert");
    printf("[OK] testMapRangeInsert()\n");
}

void testMapMultimapCompatibility() {
    std::multimap<int, std::string> mm = {{1, "one"}, {2, "two"}, {2, "deux"}};
    std::map<int, std::string> m(mm.begin(), mm.end());
    _ASSERT(m.size() == 2, "Map size should be 2 after inserting from multimap");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two' (the last inserted value for key 2)");
    printf("[OK] testMapMultimapCompatibility()\n");
}

void testMapFindEdgeCases() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    auto it = m.find(3);
    _ASSERT(it == m.end(), "Finding non-existent key should return end iterator");
    m.clear();
    it = m.find(1);
    _ASSERT(it == m.end(), "Finding any key in an empty map should return end iterator");
    printf("[OK] testMapFindEdgeCases()\n");
}

void testMapInsertOrAssign() {
    std::map<int, std::string> m;
    m.insert_or_assign(1, "one");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one' after insert_or_assign");

    m.insert_or_assign(1, "uno");
    _ASSERT(m[1] == "uno", "Element with key 1 should be 'uno' after insert_or_assign");
    printf("[OK] testMapInsertOrAssign()\n");
}

void testMapTryEmplace() {
    std::map<int, std::string> m;
    m.try_emplace(1, "one");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one' after try_emplace");

    m.try_emplace(1, "uno");
    _ASSERT(m[1] == "one", "Element with key 1 should remain 'one' after try_emplace with existing key");
    printf("[OK] testMapTryEmplace()\n");
}

void testMapExtractAndInsert() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2;

    auto node_handle = m1.extract(1);
    _ASSERT(node_handle.key() == 1, "Extracted node should have key 1");
    _ASSERT(node_handle.mapped() == "one", "Extracted node should have value 'one'");

    m2.insert(std::move(node_handle));
    _ASSERT(m2[1] == "one", "m2 should contain the node with key 1 and value 'one' after insert");
    _ASSERT(m1.find(1) == m1.end(), "m1 should not contain the key 1 after extract");
    printf("[OK] testMapExtractAndInsert()\n");
}

template <typename T>
struct CustomAllocator {
    typedef T value_type;
    CustomAllocator() = default;

    template <class U>
    constexpr CustomAllocator(const CustomAllocator<U>&) noexcept {}

    T* allocate(std::size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* p, std::size_t) noexcept {
        ::operator delete(p);
    }
};

template <class T, class U>
bool operator==(const CustomAllocator<T>&, const CustomAllocator<U>&) {
    return true;
}

template <class T, class U>
bool operator!=(const CustomAllocator<T>&, const CustomAllocator<U>&) {
    return false;
}

void testMapCustomAllocator() {
    std::map<int, std::string, std::less<int>, CustomAllocator<std::pair<const int, std::string>>> m;
    m[1] = "one";
    m[2] = "two";
    _ASSERT(m.size() == 2, "Map size should be 2 with custom allocator");
    _ASSERT(m[1] == "one", "Element with key 1 should be 'one' with custom allocator");
    _ASSERT(m[2] == "two", "Element with key 2 should be 'two' with custom allocator");
    printf("[OK] testMapCustomAllocator()\n");
}

void testMapMerge() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2 = {{3, "three"}, {4, "four"}};

    m1.merge(m2);
    _ASSERT(m1.size() == 4, "m1 size should be 4 after merge");
    _ASSERT(m1[3] == "three", "m1 should contain key 3 with value 'three' after merge");
    _ASSERT(m2.empty(), "m2 should be empty after merge");
    printf("[OK] testMapMerge()\n");
}

void testMapComparisonOperators() {
    std::map<int, std::string> m1 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m2 = {{1, "one"}, {2, "two"}};
    std::map<int, std::string> m3 = {{2, "two"}, {3, "three"}};

    _ASSERT(m1 == m2, "m1 should be equal to m2");
    _ASSERT(m1 != m3, "m1 should not be equal to m3");
    _ASSERT(m1 < m3, "m1 should be less than m3");
    _ASSERT(m3 > m1, "m3 should be greater than m1");
    printf("[OK] testMapComparisonOperators()\n");
}

void testMapMemoryManagement() {
    std::map<int, std::string> m;
    m[1] = "one";
    m[2] = "two";
    m[3] = "three";

    auto alloc = m.get_allocator();
    using PairType = std::pair<const int, std::string>;
    PairType* p = alloc.allocate(5);
    for (int i = 0; i < 5; ++i) {
        std::allocator_traits<decltype(alloc)>::construct(alloc, &p[i], PairType(i, std::to_string(i)));
    }
    for (int i = 0; i < 5; ++i) {
        _ASSERT(p[i].first == i && p[i].second == std::to_string(i), "Allocated memory should contain correct values");
    }
    for (int i = 0; i < 5; ++i) {
        std::allocator_traits<decltype(alloc)>::destroy(alloc, &p[i]);
    }
    alloc.deallocate(p, 5);
    printf("[OK] testMapMemoryManagement()\n");
}

void testMapMaxSize() {
    std::map<int, std::string> m;
    _ASSERT(m.max_size() > 0, "Map max_size should be greater than 0");
    printf("[OK] testMapMaxSize()\n");
}

void testMapExceptionSafety() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    try {
        m.at(3); // This should throw an out_of_range exception
        _ASSERT(false, "Accessing non-existent key with at() should throw an exception");
    } catch (const std::out_of_range&) {
        _ASSERT(true, "Accessing non-existent key with at() correctly throws an exception");
    }

    try {
        m.at(1); // This should not throw an exception
        _ASSERT(true, "Accessing existing key with at() should not throw an exception");
    } catch (...) {
        _ASSERT(false, "Accessing existing key with at() should not throw an exception");
    }

    printf("[OK] testMapExceptionSafety()\n");
}

void testSharedPtrBasic() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    _ASSERT(sp != nullptr, "Shared pointer should not be null after initialization");
    _ASSERT(*sp == 10, "Shared pointer should point to 10");
    printf("[OK] testSharedPtrBasic()\n");
}

void testSharedPtrCopyAndAssign() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = sp1;
    _ASSERT(sp1 == sp2, "Shared pointers should be equal after copy");
    _ASSERT(sp1.use_count() == 2, "Use count should be 2 after copy");

    std::shared_ptr<int> sp3;
    sp3 = sp1;
    _ASSERT(sp3 == sp1, "Shared pointers should be equal after assignment");
    _ASSERT(sp1.use_count() == 3, "Use count should be 3 after assignment");
    printf("[OK] testSharedPtrCopyAndAssign()\n");
}

void testSharedPtrMove() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = std::move(sp1);
    _ASSERT(sp1 == nullptr, "Shared pointer should be null after move");
    _ASSERT(sp2 != nullptr, "Moved shared pointer should not be null");
    _ASSERT(*sp2 == 10, "Moved shared pointer should point to 10");

    std::shared_ptr<int> sp3;
    sp3 = std::move(sp2);
    _ASSERT(sp2 == nullptr, "Shared pointer should be null after move assignment");
    _ASSERT(sp3 != nullptr, "Moved assigned shared pointer should not be null");
    _ASSERT(*sp3 == 10, "Moved assigned shared pointer should point to 10");
    printf("[OK] testSharedPtrMove()\n");
}

void testSharedPtrReset() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    sp.reset();
    _ASSERT(sp == nullptr, "Shared pointer should be null after reset");

    sp.reset(new int(20));
    _ASSERT(sp != nullptr, "Shared pointer should not be null after reset with new value");
    _ASSERT(*sp == 20, "Shared pointer should point to 20 after reset with new value");
    printf("[OK] testSharedPtrReset()\n");
}

void testSharedPtrUseCount() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = sp1;
    _ASSERT(sp1.use_count() == 2, "Use count should be 2 after copy");

    sp2.reset();
    _ASSERT(sp1.use_count() == 1, "Use count should be 1 after reset of one copy");
    printf("[OK] testSharedPtrUseCount()\n");
}

void customDeleter(int* p) {
    printf("Custom deleter called for %d\n", *p);
    delete p;
}

void testSharedPtrCustomDeleter() {
    std::shared_ptr<int> sp(new int(10), customDeleter);
    _ASSERT(sp != nullptr, "Shared pointer should not be null with custom deleter");
    _ASSERT(*sp == 10, "Shared pointer should point to 10 with custom deleter");
    printf("[OK] testSharedPtrCustomDeleter()\n");
}

void testMakeShared() {
    auto sp = std::make_shared<int>(10);
    _ASSERT(sp != nullptr, "Shared pointer should not be null with make_shared");
    _ASSERT(*sp == 10, "Shared pointer should point to 10 with make_shared");
    printf("[OK] testMakeShared()\n");
}

struct Node {
    std::shared_ptr<Node> next;
};

void testSharedPtrCircularReference() {
    std::shared_ptr<Node> n1 = std::make_shared<Node>();
    std::shared_ptr<Node> n2 = std::make_shared<Node>();
    n1->next = n2;
    n2->next = n1;

    _ASSERT(n1.use_count() == 2, "Use count of n1 should be 2");
    _ASSERT(n2.use_count() == 2, "Use count of n2 should be 2");
    printf("[OK] testSharedPtrCircularReference()\n");
}

void testSharedPtrAliasConstructor() {
    auto sp_base = std::make_shared<int>(10);
    std::shared_ptr<int> sp_alias(sp_base, sp_base.get());
    _ASSERT(sp_alias.use_count() == sp_base.use_count(), "Alias constructor should have the same use count as base");
    _ASSERT(*sp_alias == 10, "Alias constructor should point to the same value as base");
    printf("[OK] testSharedPtrAliasConstructor()\n");
}

void testSharedPtrArray() {
    std::shared_ptr<int[]> sp(new int[5]);
    for (int i = 0; i < 5; ++i) {
        sp[i] = i * 2;
    }
    for (int i = 0; i < 5; ++i) {
        _ASSERT(sp[i] == i * 2, "Shared pointer array should hold correct values");
    }
    printf("[OK] testSharedPtrArray()\n");
}

template <typename T>
struct CustomAllocator2 : std::allocator<T> {
    template <typename U>
    struct rebind {
        using other = CustomAllocator2<U>;
    };
};

void testSharedPtrCustomAllocator() {
    std::shared_ptr<int> sp = std::allocate_shared<int>(CustomAllocator2<int>(), 10);
    _ASSERT(sp != nullptr, "Shared pointer should not be null with custom allocator");
    _ASSERT(*sp == 10, "Shared pointer should point to 10 with custom allocator");
    printf("[OK] testSharedPtrCustomAllocator()\n");
}


void testSharedPtrWeakPtrConversion() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    std::weak_ptr<int> wp = sp;
    _ASSERT(wp.use_count() == sp.use_count(), "Weak pointer should have the same use count as shared pointer");

    std::shared_ptr<int> sp2 = wp.lock();
    _ASSERT(sp2 != nullptr, "Locked weak pointer should not be null");
    _ASSERT(*sp2 == 10, "Locked weak pointer should point to 10");
    printf("[OK] testSharedPtrWeakPtrConversion()\n");
}

void testSharedPtrNull() {
    std::shared_ptr<int> sp;
    _ASSERT(sp == nullptr, "Default constructed shared pointer should be null");
    _ASSERT(!sp, "Default constructed shared pointer should evaluate to false");
    printf("[OK] testSharedPtrNull()\n");
}

void testSharedPtrUseCountAfterReset() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = sp1;
    sp2.reset();
    _ASSERT(sp1.use_count() == 1, "Use count should be 1 after reset of one shared pointer");
    sp1.reset();
    _ASSERT(sp1.use_count() == 0, "Use count should be 0 after reset of all shared pointers");
    printf("[OK] testSharedPtrUseCountAfterReset()\n");
}

void testSharedPtrConst() {
    std::shared_ptr<const int> sp = std::make_shared<const int>(10);
    _ASSERT(*sp == 10, "Const shared pointer should point to 10");
    printf("[OK] testSharedPtrConst()\n");
}

void testSharedPtrVoid() {
    std::shared_ptr<void> sp = std::make_shared<int>(10);
    _ASSERT(sp != nullptr, "Void shared pointer should not be null");
    _ASSERT(*std::static_pointer_cast<int>(sp) == 10, "Void shared pointer should point to 10 when cast to int");
    printf("[OK] testSharedPtrVoid()\n");
}

void testSharedPtrSwap() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = std::make_shared<int>(20);
    sp1.swap(sp2);
    _ASSERT(*sp1 == 20, "sp1 should point to 20 after swap");
    _ASSERT(*sp2 == 10, "sp2 should point to 10 after swap");
    printf("[OK] testSharedPtrSwap()\n");
}

void testSharedPtrComparisonOperators() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = sp1;
    std::shared_ptr<int> sp3 = std::make_shared<int>(20);

    _ASSERT(sp1 == sp2, "sp1 should be equal to sp2");
    _ASSERT(sp1 != sp3, "sp1 should not be equal to sp3");
    printf("[OK] testSharedPtrComparisonOperators()\n");
}

void testSharedPtrGet() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    int* raw_ptr = sp.get();
    _ASSERT(raw_ptr != nullptr, "get() should return a non-null pointer");
    _ASSERT(*raw_ptr == 10, "get() should return a pointer to the value 10");
    printf("[OK] testSharedPtrGet()\n");
}

void testSharedPtrOwnerBefore() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = std::make_shared<int>(20);
    _ASSERT(sp1.owner_before(sp2) != sp2.owner_before(sp1), "owner_before should provide a strict weak ordering");
    printf("[OK] testSharedPtrOwnerBefore()\n");
}

void testSharedPtrUnique() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    _ASSERT(sp1.unique(), "shared_ptr should be unique after creation");
    
    std::shared_ptr<int> sp2 = sp1;
    _ASSERT(!sp1.unique(), "shared_ptr should not be unique after being copied");
    
    sp2.reset();
    _ASSERT(sp1.unique(), "shared_ptr should be unique again after reset of the copy");
    printf("[OK] testSharedPtrUnique()\n");
}

void customDeleterForReset(int* p) {
    printf("Custom deleter called for reset %d\n", *p);
    delete p;
}

void testSharedPtrResetWithDeleter() {
    std::shared_ptr<int> sp = std::make_shared<int>(10);
    sp.reset(new int(20), customDeleterForReset);
    _ASSERT(sp != nullptr, "Shared pointer should not be null after reset with custom deleter");
    _ASSERT(*sp == 20, "Shared pointer should point to 20 after reset with custom deleter");
    printf("[OK] testSharedPtrResetWithDeleter()\n");
}

class SharedFromThisClass : public std::enable_shared_from_this<SharedFromThisClass> {
public:
    std::shared_ptr<SharedFromThisClass> getShared() {
        return shared_from_this();
    }
};

void testSharedPtrSharedFromThis() {
    auto sp1 = std::make_shared<SharedFromThisClass>();
    auto sp2 = sp1->getShared();
    _ASSERT(sp1 == sp2, "shared_from_this should return the same shared_ptr");
    _ASSERT(sp1.use_count() == 2, "Use count should be 2 after shared_from_this");
    printf("[OK] testSharedPtrSharedFromThis()\n");
}

void testEnableSharedFromThis() {
    struct TestClass : public std::enable_shared_from_this<TestClass> {
        std::shared_ptr<TestClass> getSharedPtr() {
            return shared_from_this();
        }
    };

    std::shared_ptr<TestClass> sp1 = std::make_shared<TestClass>();
    std::shared_ptr<TestClass> sp2 = sp1->getSharedPtr();
    _ASSERT(sp1 == sp2, "enable_shared_from_this should return the same shared_ptr");
    _ASSERT(sp1.use_count() == 2, "Use count should be 2 after getting shared_ptr from enable_shared_from_this");
    printf("[OK] testEnableSharedFromThis()\n");
}

void testSharedPtrInitializerList() {
    auto sp = std::make_shared<std::vector<int>>(std::initializer_list<int>{1, 2, 3, 4});
    _ASSERT(sp->size() == 4, "Shared pointer to vector should have 4 elements");
    _ASSERT(sp->at(0) == 1, "First element should be 1");
    _ASSERT(sp->at(3) == 4, "Last element should be 4");
    printf("[OK] testSharedPtrInitializerList()\n");
}

void testSharedPtrUseCountEdgeCases() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    _ASSERT(sp1.use_count() == 1, "Use count should be 1 after creation");

    std::shared_ptr<int> sp2 = sp1;
    _ASSERT(sp1.use_count() == 2, "Use count should be 2 after copy");

    sp2.reset();
    _ASSERT(sp1.use_count() == 1, "Use count should be 1 after reset of copy");

    sp1.reset();
    _ASSERT(sp1.use_count() == 0, "Use count should be 0 after reset of original");
    printf("[OK] testSharedPtrUseCountEdgeCases()\n");
}

void testSharedPtrPointerComparison() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::shared_ptr<int> sp2 = sp1;
    std::shared_ptr<int> sp3 = std::make_shared<int>(10);

    _ASSERT(sp1 == sp2, "Pointers should be equal for shared ownership");
    _ASSERT(sp1 != sp3, "Pointers should not be equal for different allocations");
    printf("[OK] testSharedPtrPointerComparison()\n");
}

static  int main(){
  (void)arg;
 
  testVectorObjectDestruction();
  while(1){
    testSharedPtrBasic();
    testSharedPtrCopyAndAssign();
    testSharedPtrMove();
    testSharedPtrReset();
    testSharedPtrUseCount();
    testSharedPtrCustomDeleter();
    testMakeShared();
    testSharedPtrCircularReference();
    testSharedPtrAliasConstructor();
    testSharedPtrArray();
    testSharedPtrCustomAllocator();
    testSharedPtrWeakPtrConversion();
    testSharedPtrNull();
    testSharedPtrUseCountAfterReset();
    testSharedPtrConst();
    testSharedPtrVoid();
    testSharedPtrSwap();
    testSharedPtrComparisonOperators();
    testSharedPtrGet();
    testSharedPtrOwnerBefore();
    testSharedPtrUnique();
    testSharedPtrResetWithDeleter();
    testSharedPtrSharedFromThis();
    testEnableSharedFromThis();
    testSharedPtrInitializerList();
    testSharedPtrUseCountEdgeCases();
    testSharedPtrPointerComparison();

    testVectorInitialization();
    testVectorPushBack();
    testVectorAccess();
    testVectorResize();
    testVectorPopBack();
    testVectorClear();
    testVectorInsert();
    testVectorErase();
    testVectorSwap();
    testVectorCapacity();
    testVectorEmplace();
    testVectorFrontBack();
    testVectorAssign();
    testVectorData();
    testVectorMove();
    testVectorEquality();
    testVectorInequality();
    testVectorComparisonOperators();
    testVectorIterator();
    testVectorReverseIterator();
    testVectorCopy();
    testVectorAllocator();
    testVectorEmplaceBack();
    testVectorReserve();
    testVectorShrinkToFit();
    testVectorAssignRange();
    testVectorAssignFill();
    testVectorClear2();
    testVectorBack();
    testVectorFront();
    testVectorMaxSize();
    testVectorResizeWithDefaultValue();
    testVectorEmptyComparison();
    testVectorCapacityGrowth();
    testVectorDefaultConstructor();
    testVectorMoveConstructor();
    testVectorMoveAssignment();
    testVectorLarge();
    testVectorPointerStability();
    testVectorOfPointers();

    testStringInitialization();
    testStringAppend();
    testStringAccess();
    testStringLengthAndEmpty();
    testStringComparison();
    testStringSubstr();
    testStringFind();
    testStringReplace();
    testStringInsert();
    testStringErase();
    testStringConcatenation();
    testStringSplit();
    testStringCStr();
    testStringClear();
    testStringReserve();
    testStringSwap();
    testStringCopy();
    testStringResize();
    testStringCapacity();
    testStringShrinkToFit();
    testStringFindFirstOf();
    testStringFindLastOf();
    testStringFindFirstNotOf();
    testStringFindLastNotOf();

    testStringRFind();
    testStringCompare();
    testStringAppendMultiple();
    testStringAssign();
    testStringToString();
    testStringStoi();
    testStringSubstrEdgeCases();
    testStringEmpty();
    testStringCStrConsistency();
    testStringAppendEdgeCases();
    testStringOperatorPlusEqual();
    testStringPushBack();
    testStringPopBack();
    testStringReplaceEdgeCases();
    testStringGetline();
    testStringFrontBackEdgeCases();
    testStringAtException();
    testStringCapacitySizeComparison();
    testStringInsertEdgeCases();
    testStringEraseEdgeCases();
    testStringFindFirstOfEdgeCases();
    testStringFindLastOfEdgeCases();
    testStringFindFirstNotOfEdgeCases();
    testStringFindLastNotOfEdgeCases();
    testStringAppendPerformance();
    testStringReserveEdgeCases();
    testStringShrinkToFitEdgeCases();
    testStringCopyEdgeCases();
    testStringSwapEdgeCases();

    testMapInitialization();
    testMapInsert();
    testMapErase();
    testMapFind();
    testMapSizeAndEmpty();
    testMapKeyRange();
    testMapUpdate();
    testMapIteration();
    testMapOperatorSquareBrackets();
    testMapAt();
    testMapClear();
    testMapSwap();
    testMapEmplace();
    testMapCount();
    testMapConstructors();
    testMapCopyAndMove();
    testMapEraseRange();
    testMapEqualRange();
    testMapEmplaceHint();
    testMapBoundaries();
    testMapCustomComparator();
    testMapKeyCompValueComp();
    testMapRangeInsert();
    testMapMultimapCompatibility();
    testMapFindEdgeCases();
    testMapInsertOrAssign();
    testMapTryEmplace();
    testMapExtractAndInsert();
    testMapCustomAllocator();
    testMapMerge();
    testMapComparisonOperators();
    testMapMemoryManagement();
    testMapMaxSize();
    testMapExceptionSafety();
  }
}


いいなと思ったら応援しよう!