Path: blob/master/src/common-tests/small_string_tests.cpp
7197 views
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "common/small_string.h"45#include <fmt/format.h>6#include <gtest/gtest.h>7#include <string>8#include <string_view>910using namespace std::string_view_literals;1112//////////////////////////////////////////////////////////////////////////13// SmallStringBase Test Suite14//////////////////////////////////////////////////////////////////////////1516// Constructor Tests17TEST(SmallStringBase, DefaultConstructor)18{19SmallString s;20EXPECT_TRUE(s.empty());21EXPECT_EQ(s.length(), 0u);22EXPECT_STREQ(s.c_str(), "");23}2425TEST(SmallStringBase, ConstCharConstructor)26{27SmallString s("Hello");28EXPECT_FALSE(s.empty());29EXPECT_EQ(s.length(), 5u);30EXPECT_STREQ(s.c_str(), "Hello");31}3233TEST(SmallStringBase, ConstCharWithLengthConstructor)34{35SmallString s("Hello World", 5);36EXPECT_EQ(s.length(), 5u);37EXPECT_STREQ(s.c_str(), "Hello");38}3940TEST(SmallStringBase, CopyConstructor)41{42SmallString original("Test String");43SmallString copy(original);44EXPECT_EQ(copy.length(), original.length());45EXPECT_STREQ(copy.c_str(), original.c_str());46}4748TEST(SmallStringBase, MoveConstructor)49{50SmallString original("Test String");51SmallString moved(std::move(original));52EXPECT_EQ(moved.length(), 11u);53EXPECT_STREQ(moved.c_str(), "Test String");54}5556TEST(SmallStringBase, StdStringConstructor)57{58std::string stdStr = "Hello from std::string";59SmallString s(stdStr);60EXPECT_EQ(s.length(), stdStr.length());61EXPECT_STREQ(s.c_str(), stdStr.c_str());62}6364TEST(SmallStringBase, StringViewConstructor)65{66std::string_view sv = "Hello from string_view";67SmallString s(sv);68EXPECT_EQ(s.length(), sv.length());69EXPECT_EQ(s.view(), sv);70}7172// Assignment Tests73TEST(SmallStringBase, AssignConstChar)74{75SmallString str;76str.assign("New Value");77EXPECT_EQ(str.length(), 9u);78EXPECT_STREQ(str.c_str(), "New Value");79}8081TEST(SmallStringBase, AssignConstCharWithLength)82{83SmallString str;84str.assign("New Value Extended", 9);85EXPECT_EQ(str.length(), 9u);86EXPECT_STREQ(str.c_str(), "New Value");87}8889TEST(SmallStringBase, AssignStdString)90{91SmallString str;92std::string stdStr = "std::string value";93str.assign(stdStr);94EXPECT_STREQ(str.c_str(), stdStr.c_str());95}9697TEST(SmallStringBase, AssignStringView)98{99SmallString str;100std::string_view sv = "string_view value"sv;101str.assign(sv);102EXPECT_EQ(str.view(), sv);103}104105TEST(SmallStringBase, AssignSmallStringBase)106{107SmallString str;108SmallString other("Other string");109str.assign(other);110EXPECT_STREQ(str.c_str(), other.c_str());111}112113TEST(SmallStringBase, AssignMove)114{115SmallString str;116SmallString other("Move this");117str.assign(std::move(other));118EXPECT_STREQ(str.c_str(), "Move this");119}120121// Clear Tests122TEST(SmallStringBase, Clear)123{124SmallString str("Some content");125EXPECT_FALSE(str.empty());126str.clear();127EXPECT_TRUE(str.empty());128EXPECT_EQ(str.length(), 0u);129}130131// Append Tests132TEST(SmallStringBase, AppendChar)133{134SmallString str("Hello");135str.append('!');136EXPECT_STREQ(str.c_str(), "Hello!");137}138139TEST(SmallStringBase, AppendConstChar)140{141SmallString str("Hello");142str.append(" World");143EXPECT_STREQ(str.c_str(), "Hello World");144}145146TEST(SmallStringBase, AppendConstCharWithLength)147{148SmallString str("Hello");149str.append(" World!!!", 6);150EXPECT_STREQ(str.c_str(), "Hello World");151}152153TEST(SmallStringBase, AppendStdString)154{155SmallString str("Hello");156std::string suffix = " World";157str.append(suffix);158EXPECT_STREQ(str.c_str(), "Hello World");159}160161TEST(SmallStringBase, AppendStringView)162{163SmallString str("Hello");164str.append(" World"sv);165EXPECT_STREQ(str.c_str(), "Hello World");166}167168TEST(SmallStringBase, AppendSmallStringBase)169{170SmallString str("Hello");171SmallString suffix(" World");172str.append(suffix);173EXPECT_STREQ(str.c_str(), "Hello World");174}175176TEST(SmallStringBase, AppendSprintf)177{178SmallString str("Value: ");179str.append_sprintf("%d", 42);180EXPECT_STREQ(str.c_str(), "Value: 42");181}182183TEST(SmallStringBase, AppendFormat)184{185SmallString str("Value: ");186str.append_format("{}", 42);187EXPECT_STREQ(str.c_str(), "Value: 42");188}189190TEST(SmallStringBase, AppendHex)191{192SmallString str;193const u8 data[] = {0xDE, 0xAD, 0xBE, 0xEF};194str.append_hex(data, sizeof(data));195EXPECT_STREQ(str.c_str(), "deadbeef");196}197198TEST(SmallStringBase, AppendHexCommaSeparated)199{200SmallString str;201const u8 data[] = {0xDE, 0xAD};202str.append_hex(data, sizeof(data), true);203EXPECT_STREQ(str.c_str(), "0xde, 0xad");204}205206// Prepend Tests207TEST(SmallStringBase, PrependChar)208{209SmallString str("ello");210str.prepend('H');211EXPECT_STREQ(str.c_str(), "Hello");212}213214TEST(SmallStringBase, PrependConstChar)215{216SmallString str("World");217str.prepend("Hello ");218EXPECT_STREQ(str.c_str(), "Hello World");219}220221TEST(SmallStringBase, PrependConstCharWithLength)222{223SmallString str("World");224str.prepend("Hello XXX", 6);225EXPECT_STREQ(str.c_str(), "Hello World");226}227228TEST(SmallStringBase, PrependStdString)229{230SmallString str("World");231std::string prefix = "Hello ";232str.prepend(prefix);233EXPECT_STREQ(str.c_str(), "Hello World");234}235236TEST(SmallStringBase, PrependStringView)237{238SmallString str("World");239str.prepend("Hello "sv);240EXPECT_STREQ(str.c_str(), "Hello World");241}242243TEST(SmallStringBase, PrependSmallStringBase)244{245SmallString str("World");246SmallString prefix("Hello ");247str.prepend(prefix);248EXPECT_STREQ(str.c_str(), "Hello World");249}250251TEST(SmallStringBase, PrependSprintf)252{253SmallString str(" items");254str.prepend_sprintf("%d", 5);255EXPECT_STREQ(str.c_str(), "5 items");256}257258TEST(SmallStringBase, PrependFormat)259{260SmallString str(" items");261str.prepend_format("{}", 5);262EXPECT_STREQ(str.c_str(), "5 items");263}264265// Insert Tests266TEST(SmallStringBase, InsertConstChar)267{268SmallString str("Hello World");269str.insert(5, " Beautiful");270EXPECT_STREQ(str.c_str(), "Hello Beautiful World");271}272273TEST(SmallStringBase, InsertConstCharWithLength)274{275SmallString str("Hello World");276str.insert(5, " BeautifulXXX", 10);277EXPECT_STREQ(str.c_str(), "Hello Beautiful World");278}279280TEST(SmallStringBase, InsertStdString)281{282SmallString str("Hello World");283std::string insert = " Beautiful";284str.insert(5, insert);285EXPECT_STREQ(str.c_str(), "Hello Beautiful World");286}287288TEST(SmallStringBase, InsertStringView)289{290SmallString str("Hello World");291str.insert(5, " Beautiful"sv);292EXPECT_STREQ(str.c_str(), "Hello Beautiful World");293}294295TEST(SmallStringBase, InsertSmallStringBase)296{297SmallString str("Hello World");298SmallString insert(" Beautiful");299str.insert(5, insert);300EXPECT_STREQ(str.c_str(), "Hello Beautiful World");301}302303TEST(SmallStringBase, InsertNegativeOffset)304{305SmallString str("Hello World");306str.insert(-6, "Beautiful ");307EXPECT_STREQ(str.c_str(), "HelloBeautiful World");308}309310// Format Tests311TEST(SmallStringBase, Sprintf)312{313SmallString str;314str.sprintf("Value: %d, String: %s", 42, "test");315EXPECT_STREQ(str.c_str(), "Value: 42, String: test");316}317318TEST(SmallStringBase, Format)319{320SmallString str;321str.format("Value: {}, String: {}", 42, "test");322EXPECT_STREQ(str.c_str(), "Value: 42, String: test");323}324325// Comparison Tests - equals326TEST(SmallStringBase, EqualsConstChar)327{328SmallString str("Hello");329EXPECT_TRUE(str.equals("Hello"));330EXPECT_FALSE(str.equals("hello"));331EXPECT_FALSE(str.equals("Hello World"));332}333334TEST(SmallStringBase, EqualsSmallStringBase)335{336SmallString str("Hello");337SmallString other("Hello");338SmallString different("World");339EXPECT_TRUE(str.equals(other));340EXPECT_FALSE(str.equals(different));341}342343TEST(SmallStringBase, EqualsStringView)344{345SmallString str("Hello");346EXPECT_TRUE(str.equals("Hello"sv));347EXPECT_FALSE(str.equals("hello"sv));348}349350TEST(SmallStringBase, EqualsStdString)351{352SmallString str("Hello");353std::string same = "Hello";354std::string different = "World";355EXPECT_TRUE(str.equals(same));356EXPECT_FALSE(str.equals(different));357}358359TEST(SmallStringBase, EqualsEmptyString)360{361SmallString str;362EXPECT_TRUE(str.equals(""));363EXPECT_FALSE(str.equals("x"));364}365366// Comparison Tests - iequals (case insensitive)367TEST(SmallStringBase, IEqualsConstChar)368{369SmallString str("Hello");370EXPECT_TRUE(str.iequals("hello"));371EXPECT_TRUE(str.iequals("HELLO"));372EXPECT_TRUE(str.iequals("HeLLo"));373EXPECT_FALSE(str.iequals("World"));374}375376TEST(SmallStringBase, IEqualsStringView)377{378SmallString str("Hello");379EXPECT_TRUE(str.iequals("hello"sv));380EXPECT_TRUE(str.iequals("HELLO"sv));381}382383TEST(SmallStringBase, IEqualsStdString)384{385SmallString str("Hello");386std::string same = "hello";387EXPECT_TRUE(str.iequals(same));388}389390// Comparison Tests - compare391TEST(SmallStringBase, CompareConstChar)392{393SmallString str("banana");394EXPECT_LT(str.compare("cherry"), 0);395EXPECT_GT(str.compare("apple"), 0);396EXPECT_EQ(str.compare("banana"), 0);397}398399TEST(SmallStringBase, CompareSmallStringBase)400{401SmallString str("banana");402SmallString less("apple");403SmallString greater("cherry");404SmallString equal("banana");405EXPECT_GT(str.compare(less), 0);406EXPECT_LT(str.compare(greater), 0);407EXPECT_EQ(str.compare(equal), 0);408}409410TEST(SmallStringBase, CompareStringView)411{412SmallString str("banana");413EXPECT_LT(str.compare("cherry"sv), 0);414EXPECT_GT(str.compare("apple"sv), 0);415EXPECT_EQ(str.compare("banana"sv), 0);416}417418TEST(SmallStringBase, CompareStdString)419{420SmallString str("banana");421std::string less = "apple";422std::string greater = "cherry";423std::string equal = "banana";424EXPECT_GT(str.compare(less), 0);425EXPECT_LT(str.compare(greater), 0);426EXPECT_EQ(str.compare(equal), 0);427}428429TEST(SmallStringBase, CompareEmptyStrings)430{431SmallString str;432EXPECT_EQ(str.compare(""), 0);433EXPECT_LT(str.compare("a"), 0);434435str.assign("a");436SmallString empty;437EXPECT_GT(str.compare(empty), 0);438}439440TEST(SmallStringBase, CompareDifferentLengths)441{442SmallString str("abc");443EXPECT_LT(str.compare("abcd"), 0);444EXPECT_GT(str.compare("ab"), 0);445}446447// Comparison Tests - icompare (case insensitive)448TEST(SmallStringBase, ICompareConstChar)449{450SmallString str("Banana");451EXPECT_LT(str.icompare("CHERRY"), 0);452EXPECT_GT(str.icompare("APPLE"), 0);453EXPECT_EQ(str.icompare("BANANA"), 0);454}455456TEST(SmallStringBase, ICompareSmallStringBase)457{458SmallString str("Banana");459SmallString equal("BANANA");460EXPECT_EQ(str.icompare(equal), 0);461}462463TEST(SmallStringBase, ICompareStringView)464{465SmallString str("Banana");466EXPECT_EQ(str.icompare("BANANA"sv), 0);467}468469TEST(SmallStringBase, ICompareStdString)470{471SmallString str("Banana");472std::string equal = "BANANA";473EXPECT_EQ(str.icompare(equal), 0);474}475476// StartsWith Tests477TEST(SmallStringBase, StartsWithConstChar)478{479SmallString str("Hello World");480EXPECT_TRUE(str.starts_with("Hello"));481EXPECT_TRUE(str.starts_with("H"));482EXPECT_TRUE(str.starts_with(""));483EXPECT_FALSE(str.starts_with("World"));484EXPECT_FALSE(str.starts_with("hello"));485}486487TEST(SmallStringBase, StartsWithCaseInsensitive)488{489SmallString str("Hello World");490EXPECT_TRUE(str.starts_with("HELLO", false));491EXPECT_TRUE(str.starts_with("hello", false));492EXPECT_FALSE(str.starts_with("hello", true));493}494495TEST(SmallStringBase, StartsWithSmallStringBase)496{497SmallString str("Hello World");498SmallString prefix("Hello");499EXPECT_TRUE(str.starts_with(prefix));500}501502TEST(SmallStringBase, StartsWithStringView)503{504SmallString str("Hello World");505EXPECT_TRUE(str.starts_with("Hello"sv));506}507508TEST(SmallStringBase, StartsWithStdString)509{510SmallString str("Hello World");511std::string prefix = "Hello";512EXPECT_TRUE(str.starts_with(prefix));513}514515TEST(SmallStringBase, StartsWithLongerPrefix)516{517SmallString str("Hi");518EXPECT_FALSE(str.starts_with("Hello"));519}520521// EndsWith Tests522TEST(SmallStringBase, EndsWithConstChar)523{524SmallString str("Hello World");525EXPECT_TRUE(str.ends_with("World"));526EXPECT_TRUE(str.ends_with("d"));527EXPECT_TRUE(str.ends_with(""));528EXPECT_FALSE(str.ends_with("Hello"));529EXPECT_FALSE(str.ends_with("world"));530}531532TEST(SmallStringBase, EndsWithCaseInsensitive)533{534SmallString str("Hello World");535EXPECT_TRUE(str.ends_with("WORLD", false));536EXPECT_TRUE(str.ends_with("world", false));537EXPECT_FALSE(str.ends_with("world", true));538}539540TEST(SmallStringBase, EndsWithSmallStringBase)541{542SmallString str("Hello World");543SmallString suffix("World");544EXPECT_TRUE(str.ends_with(suffix));545}546547TEST(SmallStringBase, EndsWithStringView)548{549SmallString str("Hello World");550EXPECT_TRUE(str.ends_with("World"sv));551}552553TEST(SmallStringBase, EndsWithStdString)554{555SmallString str("Hello World");556std::string suffix = "World";557EXPECT_TRUE(str.ends_with(suffix));558}559560TEST(SmallStringBase, EndsWithLongerSuffix)561{562SmallString str("Hi");563EXPECT_FALSE(str.ends_with("Hello"));564}565566// Find Tests567TEST(SmallStringBase, FindChar)568{569SmallString str("Hello World");570EXPECT_EQ(str.find('o'), 4);571EXPECT_EQ(str.find('W'), 6);572EXPECT_EQ(str.find('z'), -1);573}574575TEST(SmallStringBase, FindCharWithOffset)576{577SmallString str("Hello World");578EXPECT_EQ(str.find('o', 5), 7);579EXPECT_EQ(str.find('o', 8), -1);580}581582TEST(SmallStringBase, RFindChar)583{584SmallString str("Hello World");585EXPECT_EQ(str.rfind('o'), 7);586EXPECT_EQ(str.rfind('l'), 9);587}588589TEST(SmallStringBase, FindCharEmptyString)590{591SmallString str;592EXPECT_EQ(str.find('a'), -1);593EXPECT_EQ(str.rfind('a'), -1);594}595596TEST(SmallStringBase, FindString)597{598SmallString str("Hello World Hello");599EXPECT_EQ(str.find("Hello"), 0);600EXPECT_EQ(str.find("World"), 6);601EXPECT_EQ(str.find("Goodbye"), -1);602}603604TEST(SmallStringBase, FindStringWithOffset)605{606SmallString str("Hello World Hello");607EXPECT_EQ(str.find("Hello", 1), 12);608EXPECT_EQ(str.find("Hello", 13), -1);609}610611// Count Tests612TEST(SmallStringBase, Count)613{614SmallString str("Hello World");615EXPECT_EQ(str.count('l'), 3u);616EXPECT_EQ(str.count('o'), 2u);617EXPECT_EQ(str.count('z'), 0u);618}619620// Replace Tests621TEST(SmallStringBase, Replace)622{623SmallString str("Hello World");624u32 count = str.replace("World", "Universe");625EXPECT_EQ(count, 1u);626EXPECT_STREQ(str.c_str(), "Hello Universe");627}628629TEST(SmallStringBase, ReplaceMultiple)630{631SmallString str("Hello Hello Hello");632u32 count = str.replace("Hello", "Hi");633EXPECT_EQ(count, 3u);634EXPECT_STREQ(str.c_str(), "Hi Hi Hi");635}636637TEST(SmallStringBase, ReplaceNoMatch)638{639SmallString str("Hello World");640u32 count = str.replace("Goodbye", "Hi");641EXPECT_EQ(count, 0u);642EXPECT_STREQ(str.c_str(), "Hello World");643}644645TEST(SmallStringBase, ReplaceWithLonger)646{647SmallString str("Hi");648str.replace("Hi", "Hello World");649EXPECT_STREQ(str.c_str(), "Hello World");650}651652TEST(SmallStringBase, ReplaceWithShorter)653{654SmallString str("Hello World");655str.replace("Hello World", "Hi");656EXPECT_STREQ(str.c_str(), "Hi");657}658659// Erase Tests660TEST(SmallStringBase, EraseFromOffset)661{662SmallString str("Hello World");663str.erase(5);664EXPECT_STREQ(str.c_str(), "Hello");665}666667TEST(SmallStringBase, EraseWithCount)668{669SmallString str("Hello World");670str.erase(5, 1);671EXPECT_STREQ(str.c_str(), "HelloWorld");672}673674TEST(SmallStringBase, EraseNegativeOffset)675{676SmallString str("Hello World");677str.erase(-5);678EXPECT_STREQ(str.c_str(), "Hello ");679}680681TEST(SmallStringBase, EraseAll)682{683SmallString str("Hello World");684str.erase(0);685EXPECT_TRUE(str.empty());686}687688// Reserve/Resize Tests689TEST(SmallStringBase, Reserve)690{691SmallString str;692str.reserve(100);693EXPECT_GE(str.buffer_size(), 100u);694EXPECT_TRUE(str.empty());695}696697TEST(SmallStringBase, ResizeGrow)698{699SmallString str("Hello");700str.resize(10, 'X');701EXPECT_EQ(str.length(), 10u);702EXPECT_STREQ(str.c_str(), "HelloXXXXX");703}704705TEST(SmallStringBase, ResizeShrink)706{707SmallString str("Hello World");708str.resize(5);709EXPECT_EQ(str.length(), 5u);710EXPECT_STREQ(str.c_str(), "Hello");711}712713TEST(SmallStringBase, SetSize)714{715SmallString str("Hello World");716str.set_size(5);717EXPECT_EQ(str.length(), 5u);718EXPECT_STREQ(str.c_str(), "Hello");719}720721TEST(SmallStringBase, UpdateSize)722{723SmallString str;724str.reserve(20);725std::strcpy(str.data(), "Manual");726str.update_size();727EXPECT_EQ(str.length(), 6u);728EXPECT_STREQ(str.c_str(), "Manual");729}730731TEST(SmallStringBase, MakeRoomFor)732{733SmallString str("Hello");734str.make_room_for(1000);735EXPECT_GE(str.buffer_size(), str.length() + 1000u);736}737738// Case Conversion Tests739TEST(SmallStringBase, ConvertToLowerCase)740{741SmallString str("HELLO WORLD");742str.convert_to_lower_case();743EXPECT_STREQ(str.c_str(), "hello world");744}745746TEST(SmallStringBase, ConvertToUpperCase)747{748SmallString str("hello world");749str.convert_to_upper_case();750EXPECT_STREQ(str.c_str(), "HELLO WORLD");751}752753// View/Substr Tests754TEST(SmallStringBase, View)755{756SmallString str("Hello World");757std::string_view sv = str.view();758EXPECT_EQ(sv, "Hello World");759}760761TEST(SmallStringBase, ViewEmpty)762{763SmallString str;764std::string_view sv = str.view();765EXPECT_TRUE(sv.empty());766}767768TEST(SmallStringBase, Substr)769{770SmallString str("Hello World");771std::string_view sv = str.substr(0, 5);772EXPECT_EQ(sv, "Hello");773}774775TEST(SmallStringBase, SubstrNegativeOffset)776{777SmallString str("Hello World");778std::string_view sv = str.substr(-5, 5);779EXPECT_EQ(sv, "World");780}781782TEST(SmallStringBase, SubstrNegativeCount)783{784SmallString str("Hello World");785std::string_view sv = str.substr(0, -6);786EXPECT_EQ(sv, "Hello");787}788789// Span Tests790TEST(SmallStringBase, CSpan)791{792SmallString str("Hello");793std::span<const char> sp = str.cspan();794EXPECT_EQ(sp.size(), 5u);795EXPECT_EQ(sp[0], 'H');796}797798TEST(SmallStringBase, Span)799{800SmallString str("Hello");801std::span<char> sp = str.span();802sp[0] = 'J';803EXPECT_STREQ(str.c_str(), "Jello");804}805806TEST(SmallStringBase, CBSpan)807{808SmallString str("AB");809std::span<const u8> sp = str.cbspan();810EXPECT_EQ(sp.size(), 2u);811EXPECT_EQ(sp[0], static_cast<u8>('A'));812}813814TEST(SmallStringBase, BSpan)815{816SmallString str("AB");817std::span<u8> sp = str.bspan();818sp[0] = static_cast<u8>('X');819EXPECT_STREQ(str.c_str(), "XB");820}821822// STL Adapter Tests823TEST(SmallStringBase, Front)824{825SmallString str("Hello");826EXPECT_EQ(str.front(), 'H');827}828829TEST(SmallStringBase, Back)830{831SmallString str("Hello");832EXPECT_EQ(str.back(), 'o');833}834835TEST(SmallStringBase, PushBack)836{837SmallString str("Hello");838str.push_back('!');839EXPECT_STREQ(str.c_str(), "Hello!");840}841842TEST(SmallStringBase, PopBack)843{844SmallString str("Hello!");845str.pop_back();846EXPECT_STREQ(str.c_str(), "Hello");847}848849// Accessor Tests850TEST(SmallStringBase, Length)851{852SmallString str("Hello");853EXPECT_EQ(str.length(), 5u);854}855856TEST(SmallStringBase, Empty)857{858SmallString str;859EXPECT_TRUE(str.empty());860str.assign("x");861EXPECT_FALSE(str.empty());862}863864TEST(SmallStringBase, BufferSize)865{866SmallString str;867EXPECT_GT(str.buffer_size(), 0u);868}869870TEST(SmallStringBase, CStr)871{872SmallString str("Hello");873EXPECT_STREQ(str.c_str(), "Hello");874}875876TEST(SmallStringBase, Data)877{878SmallString str("Hello");879str.data()[0] = 'J';880EXPECT_STREQ(str.c_str(), "Jello");881}882883TEST(SmallStringBase, EndPtr)884{885SmallString str("Hello");886const char* end = str.end_ptr();887EXPECT_EQ(end - str.c_str(), 5);888}889890// Operator Tests891TEST(SmallStringBase, OperatorConstCharStar)892{893SmallString str("Hello");894const char* ptr = str;895EXPECT_STREQ(ptr, "Hello");896}897898TEST(SmallStringBase, OperatorCharStar)899{900SmallString str("Hello");901char* ptr = str;902ptr[0] = 'J';903EXPECT_STREQ(str.c_str(), "Jello");904}905906TEST(SmallStringBase, OperatorStringView)907{908SmallString str("Hello");909std::string_view sv = str;910EXPECT_EQ(sv, "Hello");911}912913TEST(SmallStringBase, OperatorEqualityConstChar)914{915SmallString str("Hello");916EXPECT_TRUE(str == "Hello");917EXPECT_FALSE(str == "World");918}919920TEST(SmallStringBase, OperatorEqualitySmallStringBase)921{922SmallString str("Hello");923SmallString other("Hello");924SmallString different("World");925EXPECT_TRUE(str == other);926EXPECT_FALSE(str == different);927}928929TEST(SmallStringBase, OperatorEqualityStringView)930{931SmallString str("Hello");932EXPECT_TRUE(str == "Hello"sv);933EXPECT_FALSE(str == "World"sv);934}935936TEST(SmallStringBase, OperatorEqualityStdString)937{938SmallString str("Hello");939std::string same = "Hello";940std::string different = "World";941EXPECT_TRUE(str == same);942EXPECT_FALSE(str == different);943}944945TEST(SmallStringBase, OperatorInequality)946{947SmallString str("Hello");948EXPECT_TRUE(str != "World");949EXPECT_FALSE(str != "Hello");950}951952TEST(SmallStringBase, OperatorLessThan)953{954SmallString str("apple");955EXPECT_TRUE(str < "banana");956EXPECT_FALSE(str < "aardvark");957}958959TEST(SmallStringBase, OperatorGreaterThan)960{961SmallString str("banana");962EXPECT_TRUE(str > "apple");963EXPECT_FALSE(str > "cherry");964}965966TEST(SmallStringBase, OperatorAssignConstChar)967{968SmallString str;969str = "Hello";970EXPECT_STREQ(str.c_str(), "Hello");971}972973TEST(SmallStringBase, OperatorAssignStdString)974{975SmallString str;976std::string s = "Hello";977str = s;978EXPECT_STREQ(str.c_str(), "Hello");979}980981TEST(SmallStringBase, OperatorAssignStringView)982{983SmallString str;984str = "Hello"sv;985EXPECT_STREQ(str.c_str(), "Hello");986}987988TEST(SmallStringBase, OperatorAssignSmallStringBase)989{990SmallString str;991SmallString other("Hello");992str = other;993EXPECT_STREQ(str.c_str(), "Hello");994}995996TEST(SmallStringBase, OperatorAssignMove)997{998SmallString str;999SmallString other("Hello");1000str = std::move(other);1001EXPECT_STREQ(str.c_str(), "Hello");1002}10031004// ShrinkToFit Tests1005TEST(SmallStringBase, ShrinkToFit)1006{1007SmallString str;1008str.reserve(1000);1009str.assign("Hi");1010u32 size_before = str.buffer_size();1011str.shrink_to_fit();1012EXPECT_LE(str.buffer_size(), size_before);1013EXPECT_STREQ(str.c_str(), "Hi");1014}10151016TEST(SmallStringBase, ShrinkToFitEmpty)1017{1018SmallString str;1019str.reserve(1000);1020str.clear();1021str.shrink_to_fit();1022EXPECT_TRUE(str.empty());1023}10241025// Edge Cases1026TEST(SmallStringBase, AppendEmptyString)1027{1028SmallString str("Hello");1029str.append("");1030EXPECT_STREQ(str.c_str(), "Hello");1031}10321033TEST(SmallStringBase, PrependEmptyString)1034{1035SmallString str("Hello");1036str.prepend("");1037EXPECT_STREQ(str.c_str(), "Hello");1038}10391040TEST(SmallStringBase, InsertEmptyString)1041{1042SmallString str("Hello");1043str.insert(2, "");1044EXPECT_STREQ(str.c_str(), "Hello");1045}10461047TEST(SmallStringBase, LargeStringAppend)1048{1049SmallString str;1050for (int i = 0; i < 1000; i++)1051{1052str.append('X');1053}1054EXPECT_EQ(str.length(), 1000u);1055}10561057TEST(SmallStringBase, EraseNegativeOffsetMiddle)1058{1059SmallString str("Hello World");1060// Erase 3 characters starting from position -6 (i.e., position 5 = ' ')1061// Should result in "Hellorld" (erase " Wo")1062str.erase(-6, 3);1063EXPECT_STREQ(str.c_str(), "Hellorld");1064EXPECT_EQ(str.length(), 8u);1065}10661067TEST(SmallStringBase, MoveAssignmentActuallyMoves)1068{1069// Create a string large enough to force heap allocation1070SmallString source;1071source.reserve(1000);1072source.assign("This is a long string that should be on the heap");10731074const char* original_buffer = source.c_str();10751076SmallString dest;1077dest = std::move(source);10781079EXPECT_STREQ(dest.c_str(), "This is a long string that should be on the heap");1080EXPECT_TRUE(source.empty() || source.c_str() != original_buffer);1081}10821083TEST(SmallStringBase, SmallStringBaseCaseInsensitive)1084{1085SmallString str("Hello");1086SmallString other("HELLO");1087SmallString otherLower("hello");1088SmallString otherMixed("hElLo");10891090EXPECT_TRUE(str.iequals(other));1091EXPECT_TRUE(str.iequals(otherLower));1092EXPECT_TRUE(str.iequals(otherMixed));10931094// Check const char* overloads1095EXPECT_TRUE(str.iequals("Hello"));1096EXPECT_TRUE(str.iequals("HELLO"));1097EXPECT_TRUE(str.iequals("hello"));1098EXPECT_TRUE(str.iequals("hElLo"));1099}11001101#ifdef _WIN3211021103TEST(SmallStringBase, WStringViewAssignNullTermination)1104{1105SmallString str;1106// First assign something to ensure the buffer has garbage after1107str.assign("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");11081109// Now assign a shorter wstring1110std::wstring_view wstr = L"Hello";1111str.assign(wstr);11121113EXPECT_EQ(str.length(), 5u);1114EXPECT_STREQ(str.c_str(), "Hello");11151116// Verify the string is properly null-terminated by checking length matches strlen1117EXPECT_EQ(std::strlen(str.c_str()), str.length());1118}11191120TEST(SmallStringBase, WStringViewAssignEmptyFollowedByContent)1121{1122SmallString str;1123str.reserve(100);11241125// Assign via wstring_view1126std::wstring_view wstr = L"Test";1127str.assign(wstr);11281129// The string should be exactly "Test" with no trailing garbage1130EXPECT_EQ(str.length(), 4u);1131EXPECT_EQ(str.view(), "Test");11321133// Append should work correctly if null-terminated properly1134str.append("123");1135EXPECT_STREQ(str.c_str(), "Test123");1136}1137#endif11381139TEST(SmallStringBase, EraseNegativeOffsetPreservesRemainder)1140{1141SmallString str("ABCDEFGHIJ");1142// Erase 2 characters starting from -5 (position 5 = 'F')1143// Should result in "ABCDEHIJ" (erase "FG")1144str.erase(-5, 2);1145EXPECT_STREQ(str.c_str(), "ABCDEHIJ");1146EXPECT_EQ(str.length(), 8u);1147}11481149TEST(SmallStringBase, AppendHexNullTermination)1150{1151SmallString str;1152// Pre-fill with garbage to detect missing null terminator1153str.assign("XXXXXXXXXXXXXXXXXXXX");1154str.clear();11551156const u8 data[] = {0xAB, 0xCD};1157str.append_hex(data, sizeof(data));11581159EXPECT_EQ(str.length(), 4u);1160EXPECT_STREQ(str.c_str(), "abcd");1161// Verify null termination by checking strlen matches length1162EXPECT_EQ(std::strlen(str.c_str()), str.length());1163}11641165TEST(SmallStringBase, AppendHexCommaSeparatedNullTermination)1166{1167SmallString str;1168str.assign("XXXXXXXXXXXXXXXXXXXX");1169str.clear();11701171const u8 data[] = {0xAB, 0xCD};1172str.append_hex(data, sizeof(data), true);11731174EXPECT_EQ(str.length(), 10u);1175EXPECT_STREQ(str.c_str(), "0xab, 0xcd");1176EXPECT_EQ(std::strlen(str.c_str()), str.length());1177}11781179TEST(SmallStringBase, AppendHexThenAppendMore)1180{1181SmallString str("Prefix: ");1182const u8 data[] = {0xFF};1183str.append_hex(data, sizeof(data));1184str.append(" Suffix");11851186// If null terminator is missing, append will start from wrong position1187EXPECT_STREQ(str.c_str(), "Prefix: ff Suffix");1188}11891190TEST(SmallStringBase, PrependSprintfLargeString)1191{1192SmallString str(" end");11931194std::string largeFormat(1500, 'X');1195str.prepend_sprintf("%s", largeFormat.c_str());11961197std::string expected = largeFormat + " end";1198EXPECT_STREQ(str.c_str(), expected.c_str());1199}12001201TEST(SmallStringBase, ShrinkToFitEmptyHeapStringResetsState)1202{1203SmallString str;1204str.reserve(1000); // Force heap allocation1205str.clear(); // Empty the string1206str.shrink_to_fit(); // Should free heap and restore to valid state12071208// After shrink_to_fit on empty heap string, string should still be usable1209EXPECT_TRUE(str.empty());1210EXPECT_EQ(str.length(), 0u);12111212// These operations should not crash1213str.append("Hello");1214EXPECT_STREQ(str.c_str(), "Hello");1215}12161217TEST(SmallStringBase, ShrinkToFitEmptyThenClear)1218{1219SmallString str;1220str.reserve(1000); // Force heap allocation1221str.clear();1222str.shrink_to_fit();12231224// clear() should not crash after shrink_to_fit on empty heap string1225str.clear();1226EXPECT_TRUE(str.empty());1227}12281229TEST(SmallStringBase, ShrinkToFitEmptyThenReserve)1230{1231SmallString str;1232str.reserve(1000); // Force heap allocation1233str.clear();1234str.shrink_to_fit();12351236// reserve() should work correctly after shrink_to_fit on empty heap string1237str.reserve(100);1238EXPECT_GE(str.buffer_size(), 100u);12391240str.assign("Test");1241EXPECT_STREQ(str.c_str(), "Test");1242}12431244TEST(SmallStringBase, ReplaceMiddleNullTermination)1245{1246SmallString str("Hello World End");1247str.replace("World", "X");12481249EXPECT_EQ(str.length(), 11u); // "Hello X End" = 11 chars1250EXPECT_STREQ(str.c_str(), "Hello X End");12511252// Verify null termination by checking strlen matches length1253EXPECT_EQ(std::strlen(str.c_str()), str.length());1254}12551256TEST(SmallStringBase, ReplaceMiddleShorterReplacement)1257{1258SmallString str("AAABBBCCC");1259str.replace("BBB", "X");12601261EXPECT_EQ(str.length(), 7u); // "AAAXCCC" = 7 chars1262EXPECT_STREQ(str.c_str(), "AAAXCCC");1263EXPECT_EQ(std::strlen(str.c_str()), str.length());1264}12651266TEST(SmallStringBase, ReplaceMiddleThenAppend)1267{1268SmallString str("Hello World End");1269str.replace("World", "X");12701271// If null terminator is missing, append will start from wrong position1272str.append("!");1273EXPECT_STREQ(str.c_str(), "Hello X End!");1274EXPECT_EQ(str.length(), 12u);1275}12761277TEST(SmallStringBase, ReplaceMultipleInMiddle)1278{1279SmallString str("aXXXbXXXc");1280u32 count = str.replace("XXX", "Y");12811282EXPECT_EQ(count, 2u);1283EXPECT_STREQ(str.c_str(), "aYbYc");1284EXPECT_EQ(str.length(), 5u);1285EXPECT_EQ(std::strlen(str.c_str()), str.length());1286}12871288TEST(SmallStringBase, ReplaceEmptySearchString)1289{1290SmallString str("Hello");12911292// This should either be a no-op or handle gracefully, not infinite loop1293// Set a timeout expectation or just verify it completes1294u32 count = str.replace("", "X");12951296// Expected: either 0 replacements, or reasonable behavior1297// Actual with bug: infinite loop (test hangs)1298EXPECT_EQ(count, 0u);1299EXPECT_STREQ(str.c_str(), "Hello");1300}13011302//////////////////////////////////////////////////////////////////////////1303// SmallStackString Test Suite1304//////////////////////////////////////////////////////////////////////////13051306TEST(SmallStackString, DefaultConstructor)1307{1308SmallString s;1309EXPECT_TRUE(s.empty());1310EXPECT_EQ(s.length(), 0u);1311EXPECT_EQ(s.buffer_size(), 256u);1312}13131314TEST(SmallStackString, ConstCharConstructor)1315{1316SmallString s("Hello");1317EXPECT_EQ(s.length(), 5u);1318EXPECT_STREQ(s.c_str(), "Hello");1319}13201321TEST(SmallStackString, ConstCharWithLengthConstructor)1322{1323SmallString s("Hello World", 5);1324EXPECT_EQ(s.length(), 5u);1325EXPECT_STREQ(s.c_str(), "Hello");1326}13271328TEST(SmallStackString, CopyConstructorFromBase)1329{1330SmallString original("Test");1331SmallStringBase& base = original;1332SmallString copy(base);1333EXPECT_STREQ(copy.c_str(), "Test");1334}13351336TEST(SmallStackString, MoveConstructorFromBase)1337{1338SmallString original("Test");1339SmallStringBase& base = original;1340SmallString moved(std::move(base));1341EXPECT_STREQ(moved.c_str(), "Test");1342}13431344TEST(SmallStackString, CopyConstructorFromSame)1345{1346SmallString original("Test");1347SmallString copy(original);1348EXPECT_STREQ(copy.c_str(), "Test");1349}13501351TEST(SmallStackString, MoveConstructorFromSame)1352{1353SmallString original("Test");1354SmallString moved(std::move(original));1355EXPECT_STREQ(moved.c_str(), "Test");1356}13571358TEST(SmallStackString, StdStringConstructor)1359{1360std::string s = "Hello";1361SmallString ss(s);1362EXPECT_STREQ(ss.c_str(), "Hello");1363}13641365TEST(SmallStackString, StringViewConstructor)1366{1367SmallString ss("Hello"sv);1368EXPECT_STREQ(ss.c_str(), "Hello");1369}13701371TEST(SmallStackString, AssignmentFromBase)1372{1373SmallString str;1374SmallString other("Source");1375SmallStringBase& base = other;1376str = base;1377EXPECT_STREQ(str.c_str(), "Source");1378}13791380TEST(SmallStackString, AssignmentMoveFromBase)1381{1382SmallString str;1383SmallString other("Source");1384SmallStringBase& base = other;1385str = std::move(base);1386EXPECT_STREQ(str.c_str(), "Source");1387}13881389TEST(SmallStackString, AssignmentFromSame)1390{1391SmallString str;1392SmallString other("Source");1393str = other;1394EXPECT_STREQ(str.c_str(), "Source");1395}13961397TEST(SmallStackString, AssignmentMoveFromSame)1398{1399SmallString str;1400SmallString other("Source");1401str = std::move(other);1402EXPECT_STREQ(str.c_str(), "Source");1403}14041405TEST(SmallStackString, AssignmentFromStdString)1406{1407SmallString str;1408std::string s = "Source";1409str = s;1410EXPECT_STREQ(str.c_str(), "Source");1411}14121413TEST(SmallStackString, AssignmentFromStringView)1414{1415SmallString str;1416str = "Source"sv;1417EXPECT_STREQ(str.c_str(), "Source");1418}14191420TEST(SmallStackString, AssignmentFromConstChar)1421{1422SmallString str;1423str = "Source";1424EXPECT_STREQ(str.c_str(), "Source");1425}14261427TEST(SmallStackString, FromSprintf)1428{1429SmallString s = SmallString::from_sprintf("Value: %d", 42);1430EXPECT_STREQ(s.c_str(), "Value: 42");1431}14321433TEST(SmallStackString, FromFormat)1434{1435SmallString s = SmallString::from_format("Value: {}", 42);1436EXPECT_STREQ(s.c_str(), "Value: 42");1437}14381439TEST(SmallStackString, FromVFormat)1440{1441constexpr int i = 42;1442auto args = fmt::make_format_args(i);1443SmallString s = SmallString::from_vformat("Value: {}", args);1444EXPECT_STREQ(s.c_str(), "Value: 42");1445}14461447TEST(SmallStackString, TinyStringSize)1448{1449TinyString tiny;1450EXPECT_EQ(tiny.buffer_size(), 64u);1451}14521453TEST(SmallStackString, SmallStringSize)1454{1455SmallString small;1456EXPECT_EQ(small.buffer_size(), 256u);1457}14581459TEST(SmallStackString, LargeStringSize)1460{1461LargeString large;1462EXPECT_EQ(large.buffer_size(), 512u);1463}14641465TEST(SmallStackString, StackBufferOverflow)1466{1467TinyString tiny;1468// TinyString has 64 bytes, so appending more should trigger heap allocation1469for (int i = 0; i < 100; i++)1470{1471tiny.append('X');1472}1473EXPECT_EQ(tiny.length(), 100u);1474EXPECT_GE(tiny.buffer_size(), 100u);1475}14761477TEST(SmallStackString, FmtFormatter)1478{1479SmallString s("test");1480std::string formatted = fmt::format("Value: {}", s);1481EXPECT_EQ(formatted, "Value: test");1482}14831484TEST(SmallStackString, TinyStringFmtFormatter)1485{1486TinyString s("tiny");1487std::string formatted = fmt::format("Value: {}", s);1488EXPECT_EQ(formatted, "Value: tiny");1489}14901491TEST(SmallStackString, LargeStringFmtFormatter)1492{1493LargeString s("large");1494std::string formatted = fmt::format("Value: {}", s);1495EXPECT_EQ(formatted, "Value: large");1496}149714981499TEST(SmallStackString, MoveConstructorFromSameType)1500{1501SmallString source;1502source.reserve(1000); // Force heap allocation1503source.assign("Heap allocated string");15041505const char* original_buffer = source.c_str();15061507SmallString dest(std::move(source));15081509EXPECT_STREQ(dest.c_str(), "Heap allocated string");1510// After proper move, source should be empty or have different buffer1511EXPECT_TRUE(source.empty() || source.c_str() != original_buffer);1512}15131514TEST(SmallStackString, MoveConstructorFromBaseHeap)1515{1516SmallString source;1517source.reserve(1000); // Force heap allocation1518source.assign("Heap allocated string");15191520const char* original_buffer = source.c_str();1521SmallStringBase& baseRef = source;15221523SmallString dest(std::move(baseRef));15241525EXPECT_STREQ(dest.c_str(), "Heap allocated string");1526// After proper move, source should be empty or have different buffer1527EXPECT_TRUE(source.empty() || source.c_str() != original_buffer);1528}152915301531