Path: blob/master/src/common-tests/string_pool_tests.cpp
10595 views
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "common/string_pool.h"45#include <gtest/gtest.h>67// ---- BumpStringPool ----89TEST(BumpStringPool, InitiallyEmpty)10{11BumpStringPool pool;12EXPECT_TRUE(pool.IsEmpty());13EXPECT_EQ(pool.GetSize(), 0u);14}1516TEST(BumpStringPool, AddSingleString)17{18BumpStringPool pool;19auto offset = pool.AddString("hello");20EXPECT_NE(offset, BumpStringPool::InvalidOffset);21EXPECT_FALSE(pool.IsEmpty());22EXPECT_EQ(pool.GetString(offset), "hello");23}2425TEST(BumpStringPool, AddEmptyStringReturnsInvalid)26{27BumpStringPool pool;28auto offset = pool.AddString("");29EXPECT_EQ(offset, BumpStringPool::InvalidOffset);30EXPECT_TRUE(pool.IsEmpty());31}3233TEST(BumpStringPool, AddEmptyStringViewReturnsInvalid)34{35BumpStringPool pool;36auto offset = pool.AddString(std::string_view{});37EXPECT_EQ(offset, BumpStringPool::InvalidOffset);38EXPECT_TRUE(pool.IsEmpty());39}4041TEST(BumpStringPool, AddMultipleStrings)42{43BumpStringPool pool;44auto o1 = pool.AddString("alpha");45auto o2 = pool.AddString("beta");46auto o3 = pool.AddString("gamma");4748EXPECT_NE(o1, o2);49EXPECT_NE(o2, o3);50EXPECT_EQ(pool.GetString(o1), "alpha");51EXPECT_EQ(pool.GetString(o2), "beta");52EXPECT_EQ(pool.GetString(o3), "gamma");53}5455TEST(BumpStringPool, DuplicateStringsStored)56{57BumpStringPool pool;58auto o1 = pool.AddString("same");59const size_t size1 = pool.GetSize();6061auto o2 = pool.AddString("same");62EXPECT_NE(o1, o2);63EXPECT_GT(pool.GetSize(), size1);64EXPECT_EQ(pool.GetString(o1), "same");65EXPECT_EQ(pool.GetString(o2), "same");66}6768TEST(BumpStringPool, GetStringWithOffset)69{70BumpStringPool pool;71auto offset = pool.AddString("world");72EXPECT_EQ(pool.GetString(offset), "world");73}7475TEST(BumpStringPool, GetStringWithOffsetAndLength)76{77BumpStringPool pool;78auto offset = pool.AddString("hello world");79EXPECT_EQ(pool.GetString(offset, 5), "hello");80EXPECT_EQ(pool.GetString(offset, 11), "hello world");81}8283TEST(BumpStringPool, GetStringInvalidOffset)84{85BumpStringPool pool;86EXPECT_EQ(pool.GetString(BumpStringPool::InvalidOffset), std::string_view{});87}8889TEST(BumpStringPool, GetStringOutOfBounds)90{91BumpStringPool pool;92std::ignore = pool.AddString("test");93EXPECT_EQ(pool.GetString(9999), std::string_view{});94}9596TEST(BumpStringPool, GetStringWithLengthOutOfBounds)97{98BumpStringPool pool;99auto offset = pool.AddString("short");100EXPECT_EQ(pool.GetString(offset, 9999), std::string_view{});101}102103TEST(BumpStringPool, SizeIncludesNullTerminators)104{105BumpStringPool pool;106std::ignore = pool.AddString("abc"); // 3 chars + 1 null = 4107EXPECT_EQ(pool.GetSize(), 4u);108109std::ignore = pool.AddString("de"); // 2 chars + 1 null = 3110EXPECT_EQ(pool.GetSize(), 7u);111}112113TEST(BumpStringPool, Clear)114{115BumpStringPool pool;116std::ignore = pool.AddString("one");117std::ignore = pool.AddString("two");118EXPECT_FALSE(pool.IsEmpty());119120pool.Clear();121EXPECT_TRUE(pool.IsEmpty());122EXPECT_EQ(pool.GetSize(), 0u);123}124125TEST(BumpStringPool, ClearThenReuse)126{127BumpStringPool pool;128std::ignore = pool.AddString("before");129pool.Clear();130131auto offset = pool.AddString("after");132EXPECT_NE(offset, BumpStringPool::InvalidOffset);133EXPECT_EQ(pool.GetString(offset), "after");134}135136TEST(BumpStringPool, ReserveDoesNotChangeState)137{138BumpStringPool pool;139pool.Reserve(4096);140EXPECT_TRUE(pool.IsEmpty());141EXPECT_EQ(pool.GetSize(), 0u);142}143144TEST(BumpStringPool, UnicodeStrings)145{146BumpStringPool pool;147auto jp = pool.AddString("日本語テスト");148auto emoji = pool.AddString("🎮🕹️");149150EXPECT_EQ(pool.GetString(jp), "日本語テスト");151EXPECT_EQ(pool.GetString(emoji), "🎮🕹️");152}153154TEST(BumpStringPool, SingleCharacterString)155{156BumpStringPool pool;157auto offset = pool.AddString("x");158EXPECT_EQ(pool.GetString(offset), "x");159EXPECT_EQ(pool.GetSize(), 2u); // 1 char + null160}161162TEST(BumpStringPool, VeryLongString)163{164BumpStringPool pool;165std::string long_str(10000, 'z');166auto offset = pool.AddString(long_str);167EXPECT_EQ(pool.GetString(offset), long_str);168EXPECT_EQ(pool.GetSize(), 10001u);169}170171TEST(BumpStringPool, ManyStrings)172{173BumpStringPool pool;174pool.Reserve(2000);175176for (int i = 0; i < 200; i++)177{178std::string s = "str_" + std::to_string(i);179auto offset = pool.AddString(s);180EXPECT_EQ(pool.GetString(offset), s);181}182}183184TEST(BumpStringPool, SpecialCharacters)185{186BumpStringPool pool;187auto tab = pool.AddString("a\tb");188auto newline = pool.AddString("c\nd");189190EXPECT_EQ(pool.GetString(tab), "a\tb");191EXPECT_EQ(pool.GetString(newline), "c\nd");192}193194// ---- BumpUniqueStringPool ----195196TEST(BumpUniqueStringPool, InitiallyEmpty)197{198BumpUniqueStringPool pool;199EXPECT_TRUE(pool.IsEmpty());200EXPECT_EQ(pool.GetSize(), 0u);201EXPECT_EQ(pool.GetCount(), 0u);202}203204TEST(BumpUniqueStringPool, AddSingleString)205{206BumpUniqueStringPool pool;207auto offset = pool.AddString("hello");208EXPECT_NE(offset, BumpUniqueStringPool::InvalidOffset);209EXPECT_EQ(pool.GetCount(), 1u);210EXPECT_EQ(pool.GetString(offset), "hello");211}212213TEST(BumpUniqueStringPool, AddEmptyStringReturnsInvalid)214{215BumpUniqueStringPool pool;216auto offset = pool.AddString("");217EXPECT_EQ(offset, BumpUniqueStringPool::InvalidOffset);218EXPECT_TRUE(pool.IsEmpty());219EXPECT_EQ(pool.GetCount(), 0u);220}221222TEST(BumpUniqueStringPool, AddEmptyStringViewReturnsInvalid)223{224BumpUniqueStringPool pool;225auto offset = pool.AddString(std::string_view{});226EXPECT_EQ(offset, BumpUniqueStringPool::InvalidOffset);227EXPECT_TRUE(pool.IsEmpty());228}229230TEST(BumpUniqueStringPool, DeduplicatesSameString)231{232BumpUniqueStringPool pool;233auto offset1 = pool.AddString("duplicate");234const size_t size_after_first = pool.GetSize();235const size_t count_after_first = pool.GetCount();236237auto offset2 = pool.AddString("duplicate");238EXPECT_EQ(offset1, offset2);239EXPECT_EQ(pool.GetSize(), size_after_first);240EXPECT_EQ(pool.GetCount(), count_after_first);241}242243TEST(BumpUniqueStringPool, DeduplicateMultipleAdds)244{245BumpUniqueStringPool pool;246auto offset = pool.AddString("test");247const size_t size_after = pool.GetSize();248249for (int i = 0; i < 100; i++)250{251EXPECT_EQ(pool.AddString("test"), offset);252}253254EXPECT_EQ(pool.GetSize(), size_after);255EXPECT_EQ(pool.GetCount(), 1u);256}257258TEST(BumpUniqueStringPool, DistinguishesDifferentStrings)259{260BumpUniqueStringPool pool;261auto offset1 = pool.AddString("alpha");262auto offset2 = pool.AddString("beta");263EXPECT_NE(offset1, offset2);264EXPECT_EQ(pool.GetCount(), 2u);265EXPECT_EQ(pool.GetString(offset1), "alpha");266EXPECT_EQ(pool.GetString(offset2), "beta");267}268269TEST(BumpUniqueStringPool, SizeDoesNotGrowOnDuplicate)270{271BumpUniqueStringPool pool;272std::ignore = pool.AddString("aaa");273std::ignore = pool.AddString("bbb");274std::ignore = pool.AddString("ccc");275const size_t size_before = pool.GetSize();276const size_t count_before = pool.GetCount();277278std::ignore = pool.AddString("aaa");279std::ignore = std::ignore = pool.AddString("bbb");280std::ignore = pool.AddString("ccc");281EXPECT_EQ(pool.GetSize(), size_before);282EXPECT_EQ(pool.GetCount(), count_before);283}284285TEST(BumpUniqueStringPool, SizeGrowsOnlyForNewStrings)286{287BumpUniqueStringPool pool;288std::ignore = pool.AddString("aaa");289const size_t size1 = pool.GetSize();290291std::ignore = pool.AddString("aaa"); // duplicate292EXPECT_EQ(pool.GetSize(), size1);293294std::ignore = pool.AddString("bbb"); // new295EXPECT_GT(pool.GetSize(), size1);296const size_t size2 = pool.GetSize();297298std::ignore = pool.AddString("bbb"); // duplicate299EXPECT_EQ(pool.GetSize(), size2);300}301302TEST(BumpUniqueStringPool, GetStringWithOffset)303{304BumpUniqueStringPool pool;305auto offset = pool.AddString("world");306EXPECT_EQ(pool.GetString(offset), "world");307}308309TEST(BumpUniqueStringPool, GetStringWithOffsetAndLength)310{311BumpUniqueStringPool pool;312auto offset = pool.AddString("hello world");313EXPECT_EQ(pool.GetString(offset, 5), "hello");314EXPECT_EQ(pool.GetString(offset, 11), "hello world");315}316317TEST(BumpUniqueStringPool, GetStringInvalidOffset)318{319BumpUniqueStringPool pool;320EXPECT_EQ(pool.GetString(BumpUniqueStringPool::InvalidOffset), std::string_view{});321}322323TEST(BumpUniqueStringPool, GetStringOutOfBounds)324{325BumpUniqueStringPool pool;326std::ignore = pool.AddString("test");327EXPECT_EQ(pool.GetString(9999), std::string_view{});328}329330TEST(BumpUniqueStringPool, GetStringWithLengthOutOfBounds)331{332BumpUniqueStringPool pool;333auto offset = pool.AddString("short");334EXPECT_EQ(pool.GetString(offset, 9999), std::string_view{});335}336337TEST(BumpUniqueStringPool, Clear)338{339BumpUniqueStringPool pool;340std::ignore = pool.AddString("one");341std::ignore = pool.AddString("two");342std::ignore = pool.AddString("three");343EXPECT_FALSE(pool.IsEmpty());344EXPECT_EQ(pool.GetCount(), 3u);345346pool.Clear();347EXPECT_TRUE(pool.IsEmpty());348EXPECT_EQ(pool.GetSize(), 0u);349EXPECT_EQ(pool.GetCount(), 0u);350}351352TEST(BumpUniqueStringPool, ClearThenReuse)353{354BumpUniqueStringPool pool;355std::ignore = pool.AddString("before");356pool.Clear();357358auto offset = pool.AddString("after");359EXPECT_NE(offset, BumpUniqueStringPool::InvalidOffset);360EXPECT_EQ(pool.GetString(offset), "after");361EXPECT_EQ(pool.GetCount(), 1u);362}363364TEST(BumpUniqueStringPool, ReserveDoesNotChangeState)365{366BumpUniqueStringPool pool;367pool.Reserve(100, 4096);368EXPECT_TRUE(pool.IsEmpty());369EXPECT_EQ(pool.GetSize(), 0u);370EXPECT_EQ(pool.GetCount(), 0u);371}372373TEST(BumpUniqueStringPool, ManyUniqueStrings)374{375BumpUniqueStringPool pool;376pool.Reserve(200, 2000);377378for (int i = 0; i < 200; i++)379{380std::string s = "string_" + std::to_string(i);381std::ignore = pool.AddString(s);382}383384EXPECT_EQ(pool.GetCount(), 200u);385386// Verify all are retrievable and deduplicated.387for (int i = 0; i < 200; i++)388{389std::string s = "string_" + std::to_string(i);390auto offset = pool.AddString(s);391EXPECT_EQ(pool.GetString(offset), s);392}393394// Count should not have grown.395EXPECT_EQ(pool.GetCount(), 200u);396}397398TEST(BumpUniqueStringPool, CaseSensitive)399{400BumpUniqueStringPool pool;401auto lower = pool.AddString("hello");402auto upper = pool.AddString("Hello");403auto allupper = pool.AddString("HELLO");404405EXPECT_NE(lower, upper);406EXPECT_NE(upper, allupper);407EXPECT_NE(lower, allupper);408EXPECT_EQ(pool.GetCount(), 3u);409}410411TEST(BumpUniqueStringPool, SubstringNotDeduplicated)412{413BumpUniqueStringPool pool;414auto full = pool.AddString("hello world");415auto sub = pool.AddString("hello");416EXPECT_NE(full, sub);417EXPECT_EQ(pool.GetCount(), 2u);418EXPECT_EQ(pool.GetString(full), "hello world");419EXPECT_EQ(pool.GetString(sub), "hello");420}421422TEST(BumpUniqueStringPool, PrefixSuffixDistinct)423{424BumpUniqueStringPool pool;425auto a = pool.AddString("abc");426auto b = pool.AddString("abcd");427auto c = pool.AddString("ab");428EXPECT_NE(a, b);429EXPECT_NE(a, c);430EXPECT_NE(b, c);431EXPECT_EQ(pool.GetCount(), 3u);432}433434TEST(BumpUniqueStringPool, UnicodeStrings)435{436BumpUniqueStringPool pool;437auto jp = pool.AddString("日本語テスト");438auto cn = pool.AddString("中文测试");439auto emoji = pool.AddString("🎮🕹️");440441EXPECT_EQ(pool.GetString(jp), "日本語テスト");442EXPECT_EQ(pool.GetString(cn), "中文测试");443EXPECT_EQ(pool.GetString(emoji), "🎮🕹️");444EXPECT_EQ(pool.GetCount(), 3u);445}446447TEST(BumpUniqueStringPool, UnicodeDeduplicated)448{449BumpUniqueStringPool pool;450auto offset1 = pool.AddString("日本語");451const size_t size_after = pool.GetSize();452453auto offset2 = pool.AddString("日本語");454EXPECT_EQ(offset1, offset2);455EXPECT_EQ(pool.GetSize(), size_after);456EXPECT_EQ(pool.GetCount(), 1u);457}458459TEST(BumpUniqueStringPool, SpecialCharacters)460{461BumpUniqueStringPool pool;462auto tab = pool.AddString("hello\tworld");463auto newline = pool.AddString("hello\nworld");464auto null_inside = pool.AddString(std::string_view("a\0b", 3));465466EXPECT_EQ(pool.GetString(tab), "hello\tworld");467EXPECT_EQ(pool.GetString(newline), "hello\nworld");468// Embedded null: GetString(offset) stops at null, but GetString(offset, length) returns full view.469EXPECT_EQ(pool.GetString(null_inside, 3), std::string_view("a\0b", 3));470EXPECT_EQ(pool.GetCount(), 3u);471}472473TEST(BumpUniqueStringPool, SingleCharacterStrings)474{475BumpUniqueStringPool pool;476auto a = pool.AddString("a");477auto b = pool.AddString("b");478auto a2 = pool.AddString("a");479480EXPECT_NE(a, b);481EXPECT_EQ(a, a2);482EXPECT_EQ(pool.GetCount(), 2u);483}484485TEST(BumpUniqueStringPool, VeryLongString)486{487BumpUniqueStringPool pool;488std::string long_str(10000, 'x');489auto offset1 = pool.AddString(long_str);490const size_t size_after = pool.GetSize();491492auto offset2 = pool.AddString(long_str);493EXPECT_EQ(offset1, offset2);494EXPECT_EQ(pool.GetSize(), size_after);495EXPECT_EQ(pool.GetString(offset1), long_str);496}497498TEST(BumpUniqueStringPool, InterleaveAddAndLookup)499{500BumpUniqueStringPool pool;501auto a = pool.AddString("zebra");502auto b = pool.AddString("apple");503auto c = pool.AddString("mango");504505// All original offsets still valid after sorted insertions.506EXPECT_EQ(pool.GetString(a), "zebra");507EXPECT_EQ(pool.GetString(b), "apple");508EXPECT_EQ(pool.GetString(c), "mango");509510// Duplicates return same offsets.511EXPECT_EQ(pool.AddString("mango"), c);512EXPECT_EQ(pool.AddString("apple"), b);513EXPECT_EQ(pool.AddString("zebra"), a);514EXPECT_EQ(pool.GetCount(), 3u);515}516517TEST(BumpUniqueStringPool, CountMatchesUniqueStrings)518{519BumpUniqueStringPool pool;520std::ignore = pool.AddString("a");521std::ignore = pool.AddString("b");522std::ignore = pool.AddString("c");523std::ignore = pool.AddString("a");524std::ignore = pool.AddString("b");525std::ignore = pool.AddString("d");526std::ignore = pool.AddString("c");527528EXPECT_EQ(pool.GetCount(), 4u); // a, b, c, d529}530531// ---- StringPool ----532533TEST(StringPool, InitiallyEmpty)534{535StringPool pool;536EXPECT_TRUE(pool.IsEmpty());537EXPECT_EQ(pool.GetSize(), 0u);538EXPECT_EQ(pool.GetCount(), 0u);539}540541TEST(StringPool, AddSingleString)542{543StringPool pool;544auto offset = pool.AddString("hello");545EXPECT_NE(offset, StringPool::InvalidOffset);546EXPECT_EQ(pool.GetCount(), 1u);547EXPECT_EQ(pool.GetString(offset), "hello");548}549550TEST(StringPool, AddEmptyStringReturnsInvalid)551{552StringPool pool;553auto offset = pool.AddString("");554EXPECT_EQ(offset, StringPool::InvalidOffset);555EXPECT_TRUE(pool.IsEmpty());556EXPECT_EQ(pool.GetCount(), 0u);557}558559TEST(StringPool, AddEmptyStringViewReturnsInvalid)560{561StringPool pool;562auto offset = pool.AddString(std::string_view{});563EXPECT_EQ(offset, StringPool::InvalidOffset);564EXPECT_TRUE(pool.IsEmpty());565}566567TEST(StringPool, DeduplicatesSameString)568{569StringPool pool;570auto offset1 = pool.AddString("duplicate");571const size_t size_after_first = pool.GetSize();572const size_t count_after_first = pool.GetCount();573574auto offset2 = pool.AddString("duplicate");575EXPECT_EQ(offset1, offset2);576EXPECT_EQ(pool.GetSize(), size_after_first);577EXPECT_EQ(pool.GetCount(), count_after_first);578}579580TEST(StringPool, DeduplicateMultipleAdds)581{582StringPool pool;583auto offset = pool.AddString("test");584const size_t size_after = pool.GetSize();585586for (int i = 0; i < 100; i++)587{588EXPECT_EQ(pool.AddString("test"), offset);589}590591EXPECT_EQ(pool.GetSize(), size_after);592EXPECT_EQ(pool.GetCount(), 1u);593}594595TEST(StringPool, DistinguishesDifferentStrings)596{597StringPool pool;598auto offset1 = pool.AddString("alpha");599auto offset2 = pool.AddString("beta");600EXPECT_NE(offset1, offset2);601EXPECT_EQ(pool.GetCount(), 2u);602EXPECT_EQ(pool.GetString(offset1), "alpha");603EXPECT_EQ(pool.GetString(offset2), "beta");604}605606TEST(StringPool, SizeDoesNotGrowOnDuplicate)607{608StringPool pool;609std::ignore = pool.AddString("aaa");610std::ignore = pool.AddString("bbb");611std::ignore = pool.AddString("ccc");612const size_t size_before = pool.GetSize();613const size_t count_before = pool.GetCount();614615std::ignore = pool.AddString("aaa");616std::ignore = pool.AddString("bbb");617std::ignore = pool.AddString("ccc");618EXPECT_EQ(pool.GetSize(), size_before);619EXPECT_EQ(pool.GetCount(), count_before);620}621622TEST(StringPool, SizeGrowsOnlyForNewStrings)623{624StringPool pool;625std::ignore = pool.AddString("aaa");626const size_t size1 = pool.GetSize();627628std::ignore = pool.AddString("aaa"); // duplicate629EXPECT_EQ(pool.GetSize(), size1);630631std::ignore = pool.AddString("bbb"); // new632EXPECT_GT(pool.GetSize(), size1);633const size_t size2 = pool.GetSize();634635std::ignore = pool.AddString("bbb"); // duplicate636EXPECT_EQ(pool.GetSize(), size2);637}638639TEST(StringPool, GetStringWithOffset)640{641StringPool pool;642auto offset = pool.AddString("world");643EXPECT_EQ(pool.GetString(offset), "world");644}645646TEST(StringPool, GetStringWithOffsetAndLength)647{648StringPool pool;649auto offset = pool.AddString("hello world");650EXPECT_EQ(pool.GetString(offset, 5), "hello");651EXPECT_EQ(pool.GetString(offset, 11), "hello world");652}653654TEST(StringPool, GetStringOutOfBounds)655{656StringPool pool;657std::ignore = pool.AddString("test");658EXPECT_EQ(pool.GetString(9999), std::string_view{});659}660661TEST(StringPool, GetStringWithLengthOutOfBounds)662{663StringPool pool;664auto offset = pool.AddString("short");665EXPECT_EQ(pool.GetString(offset, 9999), std::string_view{});666}667668TEST(StringPool, Clear)669{670StringPool pool;671std::ignore = pool.AddString("one");672std::ignore = pool.AddString("two");673std::ignore = pool.AddString("three");674EXPECT_FALSE(pool.IsEmpty());675EXPECT_EQ(pool.GetCount(), 3u);676677pool.Clear();678EXPECT_TRUE(pool.IsEmpty());679EXPECT_EQ(pool.GetSize(), 0u);680EXPECT_EQ(pool.GetCount(), 0u);681}682683TEST(StringPool, ReserveDoesNotChangeState)684{685StringPool pool;686pool.Reserve(4096);687EXPECT_TRUE(pool.IsEmpty());688EXPECT_EQ(pool.GetSize(), 0u);689EXPECT_EQ(pool.GetCount(), 0u);690}691692TEST(StringPool, CaseSensitive)693{694StringPool pool;695auto lower = pool.AddString("hello");696auto upper = pool.AddString("Hello");697auto allupper = pool.AddString("HELLO");698699EXPECT_NE(lower, upper);700EXPECT_NE(upper, allupper);701EXPECT_NE(lower, allupper);702EXPECT_EQ(pool.GetCount(), 3u);703}704705TEST(StringPool, SubstringNotDeduplicated)706{707StringPool pool;708auto full = pool.AddString("hello world");709auto sub = pool.AddString("hello");710EXPECT_NE(full, sub);711EXPECT_EQ(pool.GetCount(), 2u);712}713714TEST(StringPool, UnicodeStrings)715{716StringPool pool;717auto jp = pool.AddString("日本語テスト");718auto cn = pool.AddString("中文测试");719auto emoji = pool.AddString("🎮🕹️");720721EXPECT_EQ(pool.GetString(jp), "日本語テスト");722EXPECT_EQ(pool.GetString(cn), "中文测试");723EXPECT_EQ(pool.GetString(emoji), "🎮🕹️");724EXPECT_EQ(pool.GetCount(), 3u);725}726727TEST(StringPool, UnicodeDeduplicated)728{729StringPool pool;730auto offset1 = pool.AddString("日本語");731const size_t size_after = pool.GetSize();732733auto offset2 = pool.AddString("日本語");734EXPECT_EQ(offset1, offset2);735EXPECT_EQ(pool.GetSize(), size_after);736EXPECT_EQ(pool.GetCount(), 1u);737}738739TEST(StringPool, ManyUniqueStrings)740{741StringPool pool;742pool.Reserve(2000);743744for (int i = 0; i < 200; i++)745{746std::string s = "string_" + std::to_string(i);747std::ignore = pool.AddString(s);748}749750EXPECT_EQ(pool.GetCount(), 200u);751752// Verify all are retrievable and deduplicated.753for (int i = 0; i < 200; i++)754{755std::string s = "string_" + std::to_string(i);756auto offset = pool.AddString(s);757EXPECT_EQ(pool.GetString(offset), s);758}759760EXPECT_EQ(pool.GetCount(), 200u);761}762763TEST(StringPool, VeryLongString)764{765StringPool pool;766std::string long_str(10000, 'x');767auto offset1 = pool.AddString(long_str);768const size_t size_after = pool.GetSize();769770auto offset2 = pool.AddString(long_str);771EXPECT_EQ(offset1, offset2);772EXPECT_EQ(pool.GetSize(), size_after);773EXPECT_EQ(pool.GetString(offset1), long_str);774}775776TEST(StringPool, GetStringInvalidOffset)777{778StringPool pool;779const auto retrieved = pool.GetString(StringPool::InvalidOffset);780781EXPECT_TRUE(retrieved.empty());782}783784TEST(StringPool, SpecialCharacters)785{786StringPool pool;787const std::string_view special_str = "Hello\nWorld\t!@#$%^&*()";788const auto offset = pool.AddString(special_str);789790EXPECT_NE(offset, StringPool::InvalidOffset);791EXPECT_EQ(pool.GetString(offset), special_str);792}793794TEST(StringPool, GetCountTracksUniqueStrings)795{796StringPool pool;797EXPECT_EQ(pool.GetCount(), 0u);798799std::ignore = pool.AddString("unique1");800EXPECT_EQ(pool.GetCount(), 1u);801802std::ignore = pool.AddString("unique2");803EXPECT_EQ(pool.GetCount(), 2u);804805std::ignore = pool.AddString("unique1"); // Duplicate806EXPECT_EQ(pool.GetCount(), 2u);807808std::ignore = pool.AddString("unique3");809EXPECT_EQ(pool.GetCount(), 3u);810}811812TEST(StringPool, ReuseAfterClear)813{814StringPool pool;815const std::string_view test_str = "reuse";816817const auto offset1 = pool.AddString(test_str);818EXPECT_EQ(offset1, 0u);819EXPECT_EQ(pool.GetCount(), 1u);820821pool.Clear();822823const auto offset2 = pool.AddString(test_str);824EXPECT_EQ(pool.GetCount(), 1u);825826// After clear, new strings start at offset 0 again827EXPECT_EQ(offset2, 0u);828EXPECT_EQ(pool.GetString(offset2), test_str);829}830831832