From 387a445d6416450b85ce8c7fc56c9536c2367283 Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Fri, 28 Mar 2025 19:30:02 -0700 Subject: [PATCH] ICU-23004 shared testSafeFwdIter() impl --- .../source/test/intltest/utfiteratortest.cpp | 133 +++++------------- 1 file changed, 35 insertions(+), 98 deletions(-) diff --git a/icu4c/source/test/intltest/utfiteratortest.cpp b/icu4c/source/test/intltest/utfiteratortest.cpp index 67c458e33cf..f85c6c8400b 100644 --- a/icu4c/source/test/intltest/utfiteratortest.cpp +++ b/icu4c/source/test/intltest/utfiteratortest.cpp @@ -304,6 +304,9 @@ public: template void testSafeSinglePassIter(StringView piped); + template + void testSafeFwdIter(StringView piped); + static constexpr std::u16string_view good16{u"a|b|ç|カ|🚴"}; static const char *good8Chars; static constexpr std::u32string_view good32{U"a|b|ç|カ|🚴"}; @@ -338,7 +341,9 @@ public: void testSafe16SinglePassIter() { testSafeSinglePassIter(good16); } - void testSafe16FwdIter(); + void testSafe16FwdIter() { + testSafeFwdIter(good16); + } void testSafe8Good() { testSafeGood(std::string_view{good8Chars}); @@ -354,7 +359,9 @@ public: void testSafe8SinglePassIter() { testSafeSinglePassIter(std::string_view{good8Chars}); } - void testSafe8FwdIter(); + void testSafe8FwdIter() { + testSafeFwdIter(std::string_view{good8Chars}); + } void testSafe32Good() { testSafeGood(good32); @@ -371,7 +378,9 @@ public: void testSafe32SinglePassIter() { testSafeSinglePassIter(good32); } - void testSafe32FwdIter(); + void testSafe32FwdIter() { + testSafeFwdIter(good32); + } }; const char *UTFIteratorTest::good8Chars = reinterpret_cast(u8"a|b|ç|カ|🚴"); @@ -532,12 +541,16 @@ void UTFIteratorTest::testSafeSinglePassIter(StringView piped) { assertTrue("iter == endIter", iter == rangeLimit); } -void UTFIteratorTest::testSafe16FwdIter() { - std::u16string_view good(u"abçカ🚴"sv); - FwdIter goodBegin(good.data()); - FwdIter goodLimit(good.data() + good.length()); - auto iter = utfIterator(goodBegin, goodLimit); - auto rangeLimit = utfIterator(goodLimit); +template +void UTFIteratorTest::testSafeFwdIter(StringView piped) { + using Unit = typename StringView::value_type; + auto parts = split(piped); + auto joined = join(parts); + // "abçカ🚴" + FwdIter goodBegin(joined.data()); + FwdIter goodLimit(joined.data() + joined.length()); + auto iter = utfIterator(goodBegin, goodLimit); + auto rangeLimit = utfIterator(goodLimit); assertTrue( "forward_iterator_tag", std::is_same_v< @@ -548,11 +561,15 @@ void UTFIteratorTest::testSafe16FwdIter() { ++iter; // pre-increment auto units = *iter; assertEquals("iter[1] * codePoint", u'b', units.codePoint()); - assertEquals("iter[1] * length", 1, units.length()); + assertEquals("iter[1] * length", parts[1].length(), units.length()); assertTrue("iter[1] * wellFormed", units.wellFormed()); // No units.stringView() when the unit iterator is not a pointer. - assertTrue("iter[1] * begin()[0]", *units.begin() == u'b'); - assertTrue("iter[1] * end()[0]", *units.end() == u'ç'); + auto unitsIter = units.begin(); + for (auto c : parts[1]) { + assertEquals("iter[1] * begin()[i]", + static_cast(c), static_cast(*unitsIter++)); + } + assertTrue("iter[1] * end()[0]", *units.end() == parts[2][0]); ++iter; assertEquals("iter[2] * codePoint", u'ç', (*iter++).codePoint()); // post-increment assertEquals("iter[3] -> codePoint", u'カ', iter->codePoint()); @@ -561,93 +578,13 @@ void UTFIteratorTest::testSafe16FwdIter() { assertEquals("iter[4.0] * codePoint", U'🚴', (*iter).codePoint()); units = *iter++; assertEquals("iter[4] * codePoint", U'🚴', units.codePoint()); - assertEquals("iter[4] * length", 2, units.length()); + assertEquals("iter[4] * length", parts[4].length(), units.length()); assertTrue("iter[4] * wellFormed", units.wellFormed()); - FwdIter unitsIter = units.begin(); - assertTrue("iter[4] * begin()[0]", *unitsIter++ == u"🚴"[0]); - assertTrue("iter[4] * begin()[1]", *unitsIter == u"🚴"[1]); - assertTrue("iter[4] * end() == endIter", units.end() == goodLimit); - assertTrue("iter == endIter", iter == rangeLimit); -} - -void UTFIteratorTest::testSafe8FwdIter() { - std::string_view good(reinterpret_cast(u8"abçカ🚴")); - FwdIter goodBegin(good.data()); - FwdIter goodLimit(good.data() + good.length()); - auto iter = utfIterator(goodBegin, goodLimit); - auto rangeLimit = utfIterator(goodLimit); - assertTrue( - "forward_iterator_tag", - std::is_same_v< - typename std::iterator_traits::iterator_category, - std::forward_iterator_tag>); - assertEquals("iter[0] * codePoint", u'a', (*iter).codePoint()); - assertEquals("iter[0] -> codePoint", u'a', iter->codePoint()); - ++iter; // pre-increment - auto units = *iter; - assertEquals("iter[1] * codePoint", u'b', units.codePoint()); - assertEquals("iter[1] * length", 1, units.length()); - assertTrue("iter[1] * wellFormed", units.wellFormed()); - // No units.stringView() when the unit iterator is not a pointer. - assertTrue("iter[1] * begin()[0]", *units.begin() == u8'b'); - assertTrue("iter[1] * end()[0]", - static_cast(*units.end()) == static_cast(u8"ç"[0])); - ++iter; - assertEquals("iter[2] * codePoint", u'ç', (*iter++).codePoint()); // post-increment - assertEquals("iter[3] -> codePoint", u'カ', iter->codePoint()); - ++iter; - // Fetch the current code point twice. - assertEquals("iter[4.0] * codePoint", U'🚴', (*iter).codePoint()); - units = *iter++; - assertEquals("iter[4] * codePoint", U'🚴', units.codePoint()); - assertEquals("iter[4] * length", 4, units.length()); - assertTrue("iter[4] * wellFormed", units.wellFormed()); - FwdIter unitsIter = units.begin(); - assertTrue("iter[4] * begin()[0]", - static_cast(*unitsIter++) == static_cast(u8"🚴"[0])); - assertTrue("iter[4] * begin()[1]", - static_cast(*unitsIter++) == static_cast(u8"🚴"[1])); - assertTrue("iter[4] * begin()[2]", - static_cast(*unitsIter++) == static_cast(u8"🚴"[2])); - assertTrue("iter[4] * begin()[3]", - static_cast(*unitsIter) == static_cast(u8"🚴"[3])); - assertTrue("iter[4] * end() == endIter", units.end() == goodLimit); - assertTrue("iter == endIter", iter == rangeLimit); -} - -void UTFIteratorTest::testSafe32FwdIter() { - std::u32string_view good(U"abçカ🚴"sv); - FwdIter goodBegin(good.data()); - FwdIter goodLimit(good.data() + good.length()); - auto iter = utfIterator(goodBegin, goodLimit); - auto rangeLimit = utfIterator(goodLimit); - assertTrue( - "forward_iterator_tag", - std::is_same_v< - typename std::iterator_traits::iterator_category, - std::forward_iterator_tag>); - assertEquals("iter[0] * codePoint", u'a', (*iter).codePoint()); - assertEquals("iter[0] -> codePoint", u'a', iter->codePoint()); - ++iter; // pre-increment - auto units = *iter; - assertEquals("iter[1] * codePoint", u'b', units.codePoint()); - assertEquals("iter[1] * length", 1, units.length()); - assertTrue("iter[1] * wellFormed", units.wellFormed()); - // No units.stringView() when the unit iterator is not a pointer. - assertTrue("iter[1] * begin()[0]", *units.begin() == u'b'); - assertTrue("iter[1] * end()[0]", *units.end() == u'ç'); - ++iter; - assertEquals("iter[2] * codePoint", u'ç', (*iter++).codePoint()); // post-increment - assertEquals("iter[3] -> codePoint", u'カ', iter->codePoint()); - ++iter; - // Fetch the current code point twice. - assertEquals("iter[4.0] * codePoint", U'🚴', (*iter).codePoint()); - units = *iter++; - assertEquals("iter[4] * codePoint", U'🚴', units.codePoint()); - assertEquals("iter[4] * length", 1, units.length()); - assertTrue("iter[4] * wellFormed", units.wellFormed()); - FwdIter unitsIter = units.begin(); - assertTrue("iter[4] * begin()[0]", *unitsIter == U'🚴'); + unitsIter = units.begin(); + for (auto c : parts[4]) { + assertEquals("iter[back 4] * begin()[i]", + static_cast(c), static_cast(*unitsIter++)); + } assertTrue("iter[4] * end() == endIter", units.end() == goodLimit); assertTrue("iter == endIter", iter == rangeLimit); }