///////////////////////////////////////////////////////////////////////////// // Copyright (c) Electronic Arts Inc. All rights reserved. ///////////////////////////////////////////////////////////////////////////// #include EA_DISABLE_GCC_WARNING(-Warray-bounds) #include "EASTLTest.h" #include #include #ifdef _MSC_VER #pragma warning(push, 0) #endif #include #if defined(_MSC_VER) #pragma warning(pop) #endif using namespace eastl; // Template instantations. // These tell the compiler to compile all the functions for the given class. template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_string; template class eastl::fixed_substring; template class eastl::fixed_substring; /* // This does not compile, since the fixed_string allocator (among other things) is // templated on sizeof(T), not just T. Thus, the full type is required at the time // of instantiation, but it is not available. // See EATech Core JIRA issue ETCR-1608 for more information. struct StructWithContainerOfStructs { eastl::fixed_string children; }; */ int TestFixedSubstring() { int nErrorCount = 0; { const char* pSource1 = "hello world"; const char* pSource2 = "hola mundo"; basic_string str(pSource1); fixed_substring sub(str, 2, 5); EATEST_VERIFY(sub.size() == 5); EATEST_VERIFY(sub[0] == 'l'); EATEST_VERIFY(sub == "llo w"); sub.assign(pSource2); EATEST_VERIFY(sub.size() == 10); EATEST_VERIFY(sub[0] == pSource2[0]); EATEST_VERIFY(sub == pSource2); fixed_substring sub2(sub); EATEST_VERIFY(sub2.size() == 10); EATEST_VERIFY(sub2[0] == pSource2[0]); EATEST_VERIFY(sub2 == pSource2); sub.assign(sub2, 1, 3); EATEST_VERIFY(sub.size() == 3); EATEST_VERIFY(sub == "ola"); sub.assign(pSource2, 3); EATEST_VERIFY(sub.size() == 3); EATEST_VERIFY(sub == "hol"); sub.assign(pSource2, pSource2 + 4); EATEST_VERIFY(sub.size() == 4); EATEST_VERIFY(sub == "hola"); sub = pSource1; EATEST_VERIFY(sub.size() == strlen(pSource1)); EATEST_VERIFY(sub == pSource1); } { // Test fixed_substring with a C character array char pArray[256]; fixed_substring str(pArray, 255); str.resize(5); EATEST_VERIFY(str.size() == 5); str[0] = 'a'; EATEST_VERIFY(str[0] == 'a'); str.sprintf("Hello %s", "world"); EATEST_VERIFY(str == "Hello world"); str += " Hola mundo"; EATEST_VERIFY(str == "Hello world Hola mundo"); str.pop_back(); EATEST_VERIFY(str == "Hello world Hola mund"); str.replace(6, 5, "abcdefghijlk"); EATEST_VERIFY(str == "Hello abcdefghijlk Hola mund"); str.clear(); EATEST_VERIFY(str.empty()); EATEST_VERIFY(str == ""); } return nErrorCount; } int TestFixedString() { int nErrorCount = 0; { fixed_string::CtorSprintf cs; fixed_string s8(cs, "hello world %d.", 1); EATEST_VERIFY(s8 == "hello world 1."); EATEST_VERIFY(s8.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage. EATEST_VERIFY(s8.max_size() == 63); s8.append_sprintf(" More hello %d.", 2); EATEST_VERIFY(s8 == "hello world 1. More hello 2."); EATEST_VERIFY(s8.capacity() == 63); } { fixed_string::CtorSprintf cs; fixed_string sW(cs, L"hello world %d.", 1); EATEST_VERIFY(sW == L"hello world 1."); EATEST_VERIFY(sW.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage. sW.append_sprintf(L" More hello %d.", 2); EATEST_VERIFY(sW == L"hello world 1. More hello 2."); EATEST_VERIFY(sW.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage. } { typedef fixed_string FixedString64; typedef fixed_string FixedString64NoOverflow; FixedString64::CtorSprintf cs; FixedString64::CtorDoNotInitialize cdni; // fixed_string(); FixedString64 fs1; EATEST_VERIFY(fs1.size() == 0); EATEST_VERIFY(fs1.capacity() == 63); FixedString64NoOverflow fsNo; EATEST_VERIFY(fs1.can_overflow() == true); EATEST_VERIFY(fsNo.can_overflow() == false); EATEST_VERIFY(fs1.full() == false); EATEST_VERIFY(fs1.has_overflowed() == false); const char8_t* pCStr = fs1.c_str(); EATEST_VERIFY(*pCStr == 0); // fixed_string(const this_type& x); FixedString64 fs2(fs1); EATEST_VERIFY(fs2.size() == 0); EATEST_VERIFY(fs2.capacity() == 63); fs1 = EA_CHAR8("abc"); FixedString64 fs3(fs1); EATEST_VERIFY(fs3.size() == 3); EATEST_VERIFY(fs3.capacity() == 63); EATEST_VERIFY(fs3 == EA_CHAR8("abc")); // fixed_string(const this_type& x, size_type position, size_type n = npos); FixedString64 fs4(fs1, 1, 2); EATEST_VERIFY(fs4.size() == 2); EATEST_VERIFY(fs4.capacity() == 63); EATEST_VERIFY(fs4 == EA_CHAR8("bc")); // fixed_string(const value_type* p, size_type n); FixedString64 fs5(EA_CHAR8("abcdef"), 6); EATEST_VERIFY(fs5.size() == 6); EATEST_VERIFY(fs5.capacity() == 63); EATEST_VERIFY(fs5 == EA_CHAR8("abcdef")); // fixed_string(const value_type* p); FixedString64 fs6(EA_CHAR8("abcdef")); EATEST_VERIFY(fs6.size() == 6); EATEST_VERIFY(fs6.capacity() == 63); EATEST_VERIFY(fs6 == EA_CHAR8("abcdef")); // fixed_string(size_type n, const value_type& value); FixedString64 fs7(8, 'a'); EATEST_VERIFY(fs7.size() == 8); EATEST_VERIFY(fs7.capacity() == 63); EATEST_VERIFY(fs7 == EA_CHAR8("aaaaaaaa")); // fixed_string(const value_type* pBegin, const value_type* pEnd); FixedString64 fs8(&fs6[0], &fs6[5]); EATEST_VERIFY(fs8.size() == 5); EATEST_VERIFY(fs8.capacity() == 63); EATEST_VERIFY(fs8 == EA_CHAR8("abcde")); // fixed_string(CtorDoNotInitialize, size_type n); FixedString64 fs9(cdni, 7); EATEST_VERIFY(fs9.size() == 7); EATEST_VERIFY(fs9.capacity() == 63); // fixed_string(CtorSprintf, const value_type* pFormat, ...); FixedString64 fs10(cs, EA_CHAR8("%d"), 37); EATEST_VERIFY(fs10.size() == 2); EATEST_VERIFY(fs10.capacity() == 63); EATEST_VERIFY(fs10 == EA_CHAR8("37")); // this_type& operator=(const const value_type* p); // this_type& operator=(const this_type& x); fs9 = EA_CHAR8("hello"); EATEST_VERIFY(fs9 == EA_CHAR8("hello")); fs9 = fs10; EATEST_VERIFY(fs9 == fs10); EATEST_VERIFY(fs9 == EA_CHAR8("37")); // void swap(this_type& x); swap(fs7, fs9); EATEST_VERIFY(fs7 == EA_CHAR8("37")); EATEST_VERIFY(fs9 == EA_CHAR8("aaaaaaaa")); // void set_capacity(size_type n); fs9.set_capacity(100); EATEST_VERIFY(fs9.size() == 8); EATEST_VERIFY(fs9.capacity() == 100); EATEST_VERIFY(fs9.full() == true); EATEST_VERIFY(fs9.has_overflowed() == true); fs9.set_capacity(100); // EATEST_VERIFY that this has no effect. EATEST_VERIFY(fs9.size() == 8); EATEST_VERIFY(fs9.capacity() == 100); EATEST_VERIFY(fs9.full() == true); EATEST_VERIFY(fs9.has_overflowed() == true); fs9.resize(100); fs9.set_capacity(100); EATEST_VERIFY(fs9.size() == 100); EATEST_VERIFY(fs9.capacity() == 100); EATEST_VERIFY(fs9.full() == true); EATEST_VERIFY(fs9.has_overflowed() == true); fs9.set_capacity(1); EATEST_VERIFY(fs9.size() == 1); EATEST_VERIFY(fs9.capacity() < fs9.max_size()); // We don't test for capacity == 1, because with fixed_strings, the fixed-size capacity is the lowest it ever gets. EATEST_VERIFY(fs9.full() == false); EATEST_VERIFY(fs9.has_overflowed() == false); fs9.set_capacity(0); EATEST_VERIFY(fs9.size() == 0); EATEST_VERIFY(fs9.capacity() < fs9.max_size()); // We don't test for capacity == 1, because with fixed_strings, the fixed-size capacity is the lowest it ever gets. EATEST_VERIFY(fs9.full() == false); EATEST_VERIFY(fs9.has_overflowed() == false); // Exercise the freeing of memory in set_capacity. fixed_string fs88; eastl_size_t capacity = fs88.capacity(); fs88.resize(capacity); fs88.set_capacity(capacity * 2); EATEST_VERIFY(fs88.capacity() >= (capacity * 2)); // void reset_lose_memory(); fs6.reset_lose_memory(); EATEST_VERIFY(fs6.size() == 0); EATEST_VERIFY(fs5.capacity() == 63); // size_type max_size() const; EATEST_VERIFY(fs7.max_size() == 63); // global operator + { // fixed_string operator+(const fixed_string& a, const fixed_string& b); // fixed_string operator+(value_type* p, const fixed_string& b); // fixed_string operator+(value_type c, const fixed_string& b); // fixed_string operator+(const fixed_string& a, const value_type* p); // fixed_string operator+(const fixed_string& a, value_type c); typedef fixed_string FSTest; // Make it a small size so it's easily overflowed when we want. FSTest a("abc"); FSTest b("def"); FSTest c(a + b); EATEST_VERIFY(c == "abcdef"); c = a + "ghi"; EATEST_VERIFY(c == "abcghi"); c = "ghi" + a; EATEST_VERIFY(c == "ghiabc"); c = a + 'g'; EATEST_VERIFY(c == "abcg"); c = 'g' + a; EATEST_VERIFY(c == "gabc"); // fixed_string operator+(fixed_string&& a, fixed_string&& b); // fixed_string operator+(fixed_string&& a, const fixed_string& b); // fixed_string operator+(const value_type* p, fixed_string&& b); // fixed_string operator+(fixed_string&& a, const value_type* p); // fixed_string operator+(fixed_string&& a, value_type b); c = eastl::move(a) + eastl::move(b); EATEST_VERIFY(c == "abcdef"); c.clear(); FSTest a1("abc"); FSTest b1("def"); c = eastl::move(a1) + b1; EATEST_VERIFY(c == "abcdef"); c.clear(); FSTest b2("def"); c = "abc" + eastl::move(b2); EATEST_VERIFY(c == "abcdef"); c.clear(); FSTest a3("abc"); c = eastl::move(a3) + "def"; EATEST_VERIFY(c == "abcdef"); c.clear(); FSTest a4("abc"); c = eastl::move(a4) + 'd'; EATEST_VERIFY(c == "abcd"); c.clear(); } // bool operator==(const fixed_string<& a, const fixed_string& b) // bool operator!=(const fixed_string<& a, const fixed_string& b) EATEST_VERIFY( fs7 != fs8); EATEST_VERIFY(!(fs7 == fs8)); fs7 = fs8; EATEST_VERIFY( fs7 == fs8); EATEST_VERIFY(!(fs7 != fs8)); } { // Test overflow allocator specification typedef fixed_string FixedString64Malloc; FixedString64Malloc fs; fs.push_back('a'); EATEST_VERIFY(fs.size() == 1); EATEST_VERIFY(fs[0] == 'a'); fs.resize(95); fs[94] = 'b'; EATEST_VERIFY(fs[0] == 'a'); EATEST_VERIFY(fs[94] == 'b'); EATEST_VERIFY(fs.size() == 95); fs.clear(); EATEST_VERIFY(fs.empty()); fs.push_back('a'); EATEST_VERIFY(fs.size() == 1); EATEST_VERIFY(fs[0] == 'a'); fs.resize(195); fs[194] = 'b'; EATEST_VERIFY(fs[0] == 'a'); EATEST_VERIFY(fs[194] == 'b'); EATEST_VERIFY(fs.size() == 195); } { // Test construction of a container with an overflow allocator constructor argument. MallocAllocator overflowAllocator; void* p = overflowAllocator.allocate(1); fixed_string c(overflowAllocator); c.resize(65); EATEST_VERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65. overflowAllocator.deallocate(p, 1); } { // Regression for compile failure when EASTL_NO_RVALUE_REFERENCES is 0. typedef eastl::fixed_string TestString; TestString ts1; TestString ts2(ts1 + "Test"); EATEST_VERIFY(ts1.empty() && ts2.size() == 4); } { // Test equality tests of differently-sized fixed_strings. /* Disabled because this isn't currently supported by fixed_string. typedef fixed_string FixedString64Malloc; typedef fixed_string FixedString32; FixedString64Malloc s64M; FixedString32 s32; EATEST_VERIFY(s64M == s32); */ } nErrorCount += TestFixedSubstring(); return nErrorCount; }