12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci******************************************************************************* 52e5b6d6dSopenharmony_ci* 62e5b6d6dSopenharmony_ci* Copyright (C) 2002-2016, International Business Machines 72e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 82e5b6d6dSopenharmony_ci* 92e5b6d6dSopenharmony_ci******************************************************************************* 102e5b6d6dSopenharmony_ci* file name: strcase.cpp 112e5b6d6dSopenharmony_ci* encoding: UTF-8 122e5b6d6dSopenharmony_ci* tab size: 8 (not used) 132e5b6d6dSopenharmony_ci* indentation:4 142e5b6d6dSopenharmony_ci* 152e5b6d6dSopenharmony_ci* created on: 2002mar12 162e5b6d6dSopenharmony_ci* created by: Markus W. Scherer 172e5b6d6dSopenharmony_ci* 182e5b6d6dSopenharmony_ci* Test file for string casing C++ API functions. 192e5b6d6dSopenharmony_ci*/ 202e5b6d6dSopenharmony_ci 212e5b6d6dSopenharmony_ci#include "unicode/std_string.h" 222e5b6d6dSopenharmony_ci#include "unicode/brkiter.h" 232e5b6d6dSopenharmony_ci#include "unicode/casemap.h" 242e5b6d6dSopenharmony_ci#include "unicode/edits.h" 252e5b6d6dSopenharmony_ci#include "unicode/uchar.h" 262e5b6d6dSopenharmony_ci#include "unicode/ures.h" 272e5b6d6dSopenharmony_ci#include "unicode/uloc.h" 282e5b6d6dSopenharmony_ci#include "unicode/locid.h" 292e5b6d6dSopenharmony_ci#include "unicode/ubrk.h" 302e5b6d6dSopenharmony_ci#include "unicode/unistr.h" 312e5b6d6dSopenharmony_ci#include "unicode/ucasemap.h" 322e5b6d6dSopenharmony_ci#include "unicode/ustring.h" 332e5b6d6dSopenharmony_ci#include "ucase.h" 342e5b6d6dSopenharmony_ci#include "ustrtest.h" 352e5b6d6dSopenharmony_ci#include "unicode/tstdtmod.h" 362e5b6d6dSopenharmony_ci#include "cmemory.h" 372e5b6d6dSopenharmony_ci#include "testutil.h" 382e5b6d6dSopenharmony_ci 392e5b6d6dSopenharmony_ciclass StringCaseTest: public IntlTest { 402e5b6d6dSopenharmony_cipublic: 412e5b6d6dSopenharmony_ci StringCaseTest(); 422e5b6d6dSopenharmony_ci virtual ~StringCaseTest(); 432e5b6d6dSopenharmony_ci 442e5b6d6dSopenharmony_ci void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0) override; 452e5b6d6dSopenharmony_ci 462e5b6d6dSopenharmony_ci void TestCaseConversion(); 472e5b6d6dSopenharmony_ci 482e5b6d6dSopenharmony_ci void TestCasingImpl(const UnicodeString &input, 492e5b6d6dSopenharmony_ci const UnicodeString &output, 502e5b6d6dSopenharmony_ci int32_t whichCase, 512e5b6d6dSopenharmony_ci void *iter, const char *localeID, uint32_t options); 522e5b6d6dSopenharmony_ci void TestCasing(); 532e5b6d6dSopenharmony_ci void TestTitleOptions(); 542e5b6d6dSopenharmony_ci void TestDutchTitle(); 552e5b6d6dSopenharmony_ci void TestFullCaseFoldingIterator(); 562e5b6d6dSopenharmony_ci void TestGreekUpper(); 572e5b6d6dSopenharmony_ci void TestArmenian(); 582e5b6d6dSopenharmony_ci void TestLongUpper(); 592e5b6d6dSopenharmony_ci void TestMalformedUTF8(); 602e5b6d6dSopenharmony_ci void TestBufferOverflow(); 612e5b6d6dSopenharmony_ci void TestEdits(); 622e5b6d6dSopenharmony_ci void TestCopyMoveEdits(); 632e5b6d6dSopenharmony_ci void TestEditsFindFwdBwd(); 642e5b6d6dSopenharmony_ci void TestMergeEdits(); 652e5b6d6dSopenharmony_ci void TestCaseMapWithEdits(); 662e5b6d6dSopenharmony_ci void TestCaseMapUTF8WithEdits(); 672e5b6d6dSopenharmony_ci void TestCaseMapToString(); 682e5b6d6dSopenharmony_ci void TestCaseMapUTF8ToString(); 692e5b6d6dSopenharmony_ci void TestLongUnicodeString(); 702e5b6d6dSopenharmony_ci void TestBug13127(); 712e5b6d6dSopenharmony_ci void TestInPlaceTitle(); 722e5b6d6dSopenharmony_ci void TestCaseMapEditsIteratorDocs(); 732e5b6d6dSopenharmony_ci void TestCaseMapGreekExtended(); 742e5b6d6dSopenharmony_ci 752e5b6d6dSopenharmony_ciprivate: 762e5b6d6dSopenharmony_ci void assertGreekUpper(const char16_t *s, const char16_t *expected); 772e5b6d6dSopenharmony_ci 782e5b6d6dSopenharmony_ci Locale GREEK_LOCALE_; 792e5b6d6dSopenharmony_ci}; 802e5b6d6dSopenharmony_ci 812e5b6d6dSopenharmony_ciStringCaseTest::StringCaseTest() : GREEK_LOCALE_("el") {} 822e5b6d6dSopenharmony_ci 832e5b6d6dSopenharmony_ciStringCaseTest::~StringCaseTest() {} 842e5b6d6dSopenharmony_ci 852e5b6d6dSopenharmony_ciextern IntlTest *createStringCaseTest() { 862e5b6d6dSopenharmony_ci return new StringCaseTest(); 872e5b6d6dSopenharmony_ci} 882e5b6d6dSopenharmony_ci 892e5b6d6dSopenharmony_civoid 902e5b6d6dSopenharmony_ciStringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) { 912e5b6d6dSopenharmony_ci if(exec) { 922e5b6d6dSopenharmony_ci logln("TestSuite StringCaseTest: "); 932e5b6d6dSopenharmony_ci } 942e5b6d6dSopenharmony_ci TESTCASE_AUTO_BEGIN; 952e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseConversion); 962e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION 972e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCasing); 982e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestTitleOptions); 992e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestDutchTitle); 1002e5b6d6dSopenharmony_ci#endif 1012e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestFullCaseFoldingIterator); 1022e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestGreekUpper); 1032e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestArmenian); 1042e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestLongUpper); 1052e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestMalformedUTF8); 1062e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestBufferOverflow); 1072e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestEdits); 1082e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCopyMoveEdits); 1092e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestEditsFindFwdBwd); 1102e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestMergeEdits); 1112e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapWithEdits); 1122e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapUTF8WithEdits); 1132e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapToString); 1142e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapUTF8ToString); 1152e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestLongUnicodeString); 1162e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 1172e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestBug13127); 1182e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestInPlaceTitle); 1192e5b6d6dSopenharmony_ci#endif 1202e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapEditsIteratorDocs); 1212e5b6d6dSopenharmony_ci TESTCASE_AUTO(TestCaseMapGreekExtended); 1222e5b6d6dSopenharmony_ci TESTCASE_AUTO_END; 1232e5b6d6dSopenharmony_ci} 1242e5b6d6dSopenharmony_ci 1252e5b6d6dSopenharmony_civoid 1262e5b6d6dSopenharmony_ciStringCaseTest::TestCaseConversion() 1272e5b6d6dSopenharmony_ci{ 1282e5b6d6dSopenharmony_ci static const UChar uppercaseGreek[] = 1292e5b6d6dSopenharmony_ci { 0x399, 0x395, 0x3a3, 0x3a5, 0x3a3, 0x20, 0x03a7, 0x3a1, 0x399, 0x3a3, 0x3a4, 1302e5b6d6dSopenharmony_ci 0x39f, 0x3a3, 0 }; 1312e5b6d6dSopenharmony_ci // "IESUS CHRISTOS" 1322e5b6d6dSopenharmony_ci 1332e5b6d6dSopenharmony_ci static const UChar lowercaseGreek[] = 1342e5b6d6dSopenharmony_ci { 0x3b9, 0x3b5, 0x3c3, 0x3c5, 0x3c2, 0x20, 0x03c7, 0x3c1, 0x3b9, 0x3c3, 0x3c4, 1352e5b6d6dSopenharmony_ci 0x3bf, 0x3c2, 0 }; 1362e5b6d6dSopenharmony_ci // "iesus christos" 1372e5b6d6dSopenharmony_ci 1382e5b6d6dSopenharmony_ci static const UChar lowercaseTurkish[] = 1392e5b6d6dSopenharmony_ci { 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 1402e5b6d6dSopenharmony_ci 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x0131, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x21, 0 }; 1412e5b6d6dSopenharmony_ci 1422e5b6d6dSopenharmony_ci static const UChar uppercaseTurkish[] = 1432e5b6d6dSopenharmony_ci { 0x54, 0x4f, 0x50, 0x4b, 0x41, 0x50, 0x49, 0x20, 0x50, 0x41, 0x4c, 0x41, 0x43, 0x45, 0x2c, 0x20, 1442e5b6d6dSopenharmony_ci 0x0130, 0x53, 0x54, 0x41, 0x4e, 0x42, 0x55, 0x4c, 0 }; 1452e5b6d6dSopenharmony_ci 1462e5b6d6dSopenharmony_ci UnicodeString expectedResult; 1472e5b6d6dSopenharmony_ci UnicodeString test3; 1482e5b6d6dSopenharmony_ci 1492e5b6d6dSopenharmony_ci test3 += (UChar32)0x0130; 1502e5b6d6dSopenharmony_ci test3 += "STANBUL, NOT CONSTANTINOPLE!"; 1512e5b6d6dSopenharmony_ci 1522e5b6d6dSopenharmony_ci UnicodeString test4(test3); 1532e5b6d6dSopenharmony_ci test4.toLower(Locale("")); 1542e5b6d6dSopenharmony_ci expectedResult = UnicodeString("i\\u0307stanbul, not constantinople!", "").unescape(); 1552e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1562e5b6d6dSopenharmony_ci errln("1. toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 1572e5b6d6dSopenharmony_ci 1582e5b6d6dSopenharmony_ci test4 = test3; 1592e5b6d6dSopenharmony_ci test4.toLower(Locale("tr", "TR")); 1602e5b6d6dSopenharmony_ci expectedResult = lowercaseTurkish; 1612e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1622e5b6d6dSopenharmony_ci errln("2. toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 1632e5b6d6dSopenharmony_ci 1642e5b6d6dSopenharmony_ci test3 = "topkap"; 1652e5b6d6dSopenharmony_ci test3 += (UChar32)0x0131; 1662e5b6d6dSopenharmony_ci test3 += " palace, istanbul"; 1672e5b6d6dSopenharmony_ci test4 = test3; 1682e5b6d6dSopenharmony_ci 1692e5b6d6dSopenharmony_ci test4.toUpper(Locale("")); 1702e5b6d6dSopenharmony_ci expectedResult = "TOPKAPI PALACE, ISTANBUL"; 1712e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1722e5b6d6dSopenharmony_ci errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 1732e5b6d6dSopenharmony_ci 1742e5b6d6dSopenharmony_ci test4 = test3; 1752e5b6d6dSopenharmony_ci test4.toUpper(Locale("tr", "TR")); 1762e5b6d6dSopenharmony_ci expectedResult = uppercaseTurkish; 1772e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1782e5b6d6dSopenharmony_ci errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 1792e5b6d6dSopenharmony_ci 1802e5b6d6dSopenharmony_ci test3 = CharsToUnicodeString("S\\u00FC\\u00DFmayrstra\\u00DFe"); 1812e5b6d6dSopenharmony_ci 1822e5b6d6dSopenharmony_ci test3.toUpper(Locale("de", "DE")); 1832e5b6d6dSopenharmony_ci expectedResult = CharsToUnicodeString("S\\u00DCSSMAYRSTRASSE"); 1842e5b6d6dSopenharmony_ci if (test3 != expectedResult) 1852e5b6d6dSopenharmony_ci errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test3 + "\"."); 1862e5b6d6dSopenharmony_ci 1872e5b6d6dSopenharmony_ci test4.replace(0, test4.length(), uppercaseGreek); 1882e5b6d6dSopenharmony_ci 1892e5b6d6dSopenharmony_ci test4.toLower(Locale("el", "GR")); 1902e5b6d6dSopenharmony_ci expectedResult = lowercaseGreek; 1912e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1922e5b6d6dSopenharmony_ci errln("toLower failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_ci test4.replace(0, test4.length(), lowercaseGreek); 1952e5b6d6dSopenharmony_ci 1962e5b6d6dSopenharmony_ci test4.toUpper(); 1972e5b6d6dSopenharmony_ci expectedResult = uppercaseGreek; 1982e5b6d6dSopenharmony_ci if (test4 != expectedResult) 1992e5b6d6dSopenharmony_ci errln("toUpper failed: expected \"" + expectedResult + "\", got \"" + test4 + "\"."); 2002e5b6d6dSopenharmony_ci 2012e5b6d6dSopenharmony_ci // more string case mapping tests with the new implementation 2022e5b6d6dSopenharmony_ci { 2032e5b6d6dSopenharmony_ci static const UChar 2042e5b6d6dSopenharmony_ci 2052e5b6d6dSopenharmony_ci beforeLower[]= { 0x61, 0x42, 0x49, 0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff }, 2062e5b6d6dSopenharmony_ci lowerRoot[]= { 0x61, 0x62, 0x69, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }, 2072e5b6d6dSopenharmony_ci lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }, 2082e5b6d6dSopenharmony_ci 2092e5b6d6dSopenharmony_ci beforeUpper[]= { 0x61, 0x42, 0x69, 0x3c2, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xfb03, 0xfb03, 0xd93f, 0xdfff }, 2102e5b6d6dSopenharmony_ci upperRoot[]= { 0x41, 0x42, 0x49, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0xd93f, 0xdfff }, 2112e5b6d6dSopenharmony_ci upperTurkish[]={ 0x41, 0x42, 0x130, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0x46, 0x46, 0x49, 0xd93f, 0xdfff }, 2122e5b6d6dSopenharmony_ci 2132e5b6d6dSopenharmony_ci beforeMiniUpper[]= { 0xdf, 0x61 }, 2142e5b6d6dSopenharmony_ci miniUpper[]= { 0x53, 0x53, 0x41 }; 2152e5b6d6dSopenharmony_ci 2162e5b6d6dSopenharmony_ci UnicodeString s; 2172e5b6d6dSopenharmony_ci 2182e5b6d6dSopenharmony_ci /* lowercase with root locale */ 2192e5b6d6dSopenharmony_ci s=UnicodeString(false, beforeLower, UPRV_LENGTHOF(beforeLower)); 2202e5b6d6dSopenharmony_ci s.toLower(""); 2212e5b6d6dSopenharmony_ci if( s.length()!=UPRV_LENGTHOF(lowerRoot) || 2222e5b6d6dSopenharmony_ci s!=UnicodeString(false, lowerRoot, s.length()) 2232e5b6d6dSopenharmony_ci ) { 2242e5b6d6dSopenharmony_ci errln("error in toLower(root locale)=\"" + s + "\" expected \"" + UnicodeString(false, lowerRoot, UPRV_LENGTHOF(lowerRoot)) + "\""); 2252e5b6d6dSopenharmony_ci } 2262e5b6d6dSopenharmony_ci 2272e5b6d6dSopenharmony_ci /* lowercase with turkish locale */ 2282e5b6d6dSopenharmony_ci s=UnicodeString(false, beforeLower, UPRV_LENGTHOF(beforeLower)); 2292e5b6d6dSopenharmony_ci s.setCharAt(0, beforeLower[0]).toLower(Locale("tr")); 2302e5b6d6dSopenharmony_ci if( s.length()!=UPRV_LENGTHOF(lowerTurkish) || 2312e5b6d6dSopenharmony_ci s!=UnicodeString(false, lowerTurkish, s.length()) 2322e5b6d6dSopenharmony_ci ) { 2332e5b6d6dSopenharmony_ci errln("error in toLower(turkish locale)=\"" + s + "\" expected \"" + UnicodeString(false, lowerTurkish, UPRV_LENGTHOF(lowerTurkish)) + "\""); 2342e5b6d6dSopenharmony_ci } 2352e5b6d6dSopenharmony_ci 2362e5b6d6dSopenharmony_ci /* uppercase with root locale */ 2372e5b6d6dSopenharmony_ci s=UnicodeString(false, beforeUpper, UPRV_LENGTHOF(beforeUpper)); 2382e5b6d6dSopenharmony_ci s.setCharAt(0, beforeUpper[0]).toUpper(Locale("")); 2392e5b6d6dSopenharmony_ci if( s.length()!=UPRV_LENGTHOF(upperRoot) || 2402e5b6d6dSopenharmony_ci s!=UnicodeString(false, upperRoot, s.length()) 2412e5b6d6dSopenharmony_ci ) { 2422e5b6d6dSopenharmony_ci errln("error in toUpper(root locale)=\"" + s + "\" expected \"" + UnicodeString(false, upperRoot, UPRV_LENGTHOF(upperRoot)) + "\""); 2432e5b6d6dSopenharmony_ci } 2442e5b6d6dSopenharmony_ci 2452e5b6d6dSopenharmony_ci /* uppercase with turkish locale */ 2462e5b6d6dSopenharmony_ci s=UnicodeString(false, beforeUpper, UPRV_LENGTHOF(beforeUpper)); 2472e5b6d6dSopenharmony_ci s.toUpper(Locale("tr")); 2482e5b6d6dSopenharmony_ci if( s.length()!=UPRV_LENGTHOF(upperTurkish) || 2492e5b6d6dSopenharmony_ci s!=UnicodeString(false, upperTurkish, s.length()) 2502e5b6d6dSopenharmony_ci ) { 2512e5b6d6dSopenharmony_ci errln("error in toUpper(turkish locale)=\"" + s + "\" expected \"" + UnicodeString(false, upperTurkish, UPRV_LENGTHOF(upperTurkish)) + "\""); 2522e5b6d6dSopenharmony_ci } 2532e5b6d6dSopenharmony_ci 2542e5b6d6dSopenharmony_ci /* uppercase a short string with root locale */ 2552e5b6d6dSopenharmony_ci s=UnicodeString(false, beforeMiniUpper, UPRV_LENGTHOF(beforeMiniUpper)); 2562e5b6d6dSopenharmony_ci s.setCharAt(0, beforeMiniUpper[0]).toUpper(""); 2572e5b6d6dSopenharmony_ci if( s.length()!=UPRV_LENGTHOF(miniUpper) || 2582e5b6d6dSopenharmony_ci s!=UnicodeString(false, miniUpper, s.length()) 2592e5b6d6dSopenharmony_ci ) { 2602e5b6d6dSopenharmony_ci errln("error in toUpper(root locale)=\"" + s + "\" expected \"" + UnicodeString(false, miniUpper, UPRV_LENGTHOF(miniUpper)) + "\""); 2612e5b6d6dSopenharmony_ci } 2622e5b6d6dSopenharmony_ci } 2632e5b6d6dSopenharmony_ci 2642e5b6d6dSopenharmony_ci // test some supplementary characters (>= Unicode 3.1) 2652e5b6d6dSopenharmony_ci { 2662e5b6d6dSopenharmony_ci UnicodeString t; 2672e5b6d6dSopenharmony_ci 2682e5b6d6dSopenharmony_ci UnicodeString 2692e5b6d6dSopenharmony_ci deseretInput=UnicodeString("\\U0001043C\\U00010414", "").unescape(), 2702e5b6d6dSopenharmony_ci deseretLower=UnicodeString("\\U0001043C\\U0001043C", "").unescape(), 2712e5b6d6dSopenharmony_ci deseretUpper=UnicodeString("\\U00010414\\U00010414", "").unescape(); 2722e5b6d6dSopenharmony_ci (t=deseretInput).toLower(); 2732e5b6d6dSopenharmony_ci if(t!=deseretLower) { 2742e5b6d6dSopenharmony_ci errln("error lowercasing Deseret (plane 1) characters"); 2752e5b6d6dSopenharmony_ci } 2762e5b6d6dSopenharmony_ci (t=deseretInput).toUpper(); 2772e5b6d6dSopenharmony_ci if(t!=deseretUpper) { 2782e5b6d6dSopenharmony_ci errln("error uppercasing Deseret (plane 1) characters"); 2792e5b6d6dSopenharmony_ci } 2802e5b6d6dSopenharmony_ci } 2812e5b6d6dSopenharmony_ci 2822e5b6d6dSopenharmony_ci // test some more cases that looked like problems 2832e5b6d6dSopenharmony_ci { 2842e5b6d6dSopenharmony_ci UnicodeString t; 2852e5b6d6dSopenharmony_ci 2862e5b6d6dSopenharmony_ci UnicodeString 2872e5b6d6dSopenharmony_ci ljInput=UnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 \\U0001043C\\U00010414", "").unescape(), 2882e5b6d6dSopenharmony_ci ljLower=UnicodeString("ab'cd \\uFB00i\\u0131ii\\u0307 \\u01C9\\u01C9\\u01C9 \\U0001043C\\U0001043C", "").unescape(), 2892e5b6d6dSopenharmony_ci ljUpper=UnicodeString("AB'CD FFIII\\u0130 \\u01C7\\u01C7\\u01C7 \\U00010414\\U00010414", "").unescape(); 2902e5b6d6dSopenharmony_ci (t=ljInput).toLower("en"); 2912e5b6d6dSopenharmony_ci if(t!=ljLower) { 2922e5b6d6dSopenharmony_ci errln("error lowercasing LJ characters"); 2932e5b6d6dSopenharmony_ci } 2942e5b6d6dSopenharmony_ci (t=ljInput).toUpper("en"); 2952e5b6d6dSopenharmony_ci if(t!=ljUpper) { 2962e5b6d6dSopenharmony_ci errln("error uppercasing LJ characters"); 2972e5b6d6dSopenharmony_ci } 2982e5b6d6dSopenharmony_ci } 2992e5b6d6dSopenharmony_ci 3002e5b6d6dSopenharmony_ci#if !UCONFIG_NO_NORMALIZATION 3012e5b6d6dSopenharmony_ci // some context-sensitive casing depends on normalization data being present 3022e5b6d6dSopenharmony_ci 3032e5b6d6dSopenharmony_ci // Unicode 3.1.1 SpecialCasing tests 3042e5b6d6dSopenharmony_ci { 3052e5b6d6dSopenharmony_ci UnicodeString t; 3062e5b6d6dSopenharmony_ci 3072e5b6d6dSopenharmony_ci // sigmas preceded and/or followed by cased letters 3082e5b6d6dSopenharmony_ci UnicodeString 3092e5b6d6dSopenharmony_ci sigmas=UnicodeString("i\\u0307\\u03a3\\u0308j \\u0307\\u03a3\\u0308j i\\u00ad\\u03a3\\u0308 \\u0307\\u03a3\\u0308 ", "").unescape(), 3102e5b6d6dSopenharmony_ci sigmasLower=UnicodeString("i\\u0307\\u03c3\\u0308j \\u0307\\u03c3\\u0308j i\\u00ad\\u03c2\\u0308 \\u0307\\u03c3\\u0308 ", "").unescape(), 3112e5b6d6dSopenharmony_ci sigmasUpper=UnicodeString("I\\u0307\\u03a3\\u0308J \\u0307\\u03a3\\u0308J I\\u00ad\\u03a3\\u0308 \\u0307\\u03a3\\u0308 ", "").unescape(); 3122e5b6d6dSopenharmony_ci 3132e5b6d6dSopenharmony_ci (t=sigmas).toLower(); 3142e5b6d6dSopenharmony_ci if(t!=sigmasLower) { 3152e5b6d6dSopenharmony_ci errln("error in sigmas.toLower()=\"" + t + "\" expected \"" + sigmasLower + "\""); 3162e5b6d6dSopenharmony_ci } 3172e5b6d6dSopenharmony_ci 3182e5b6d6dSopenharmony_ci (t=sigmas).toUpper(Locale("")); 3192e5b6d6dSopenharmony_ci if(t!=sigmasUpper) { 3202e5b6d6dSopenharmony_ci errln("error in sigmas.toUpper()=\"" + t + "\" expected \"" + sigmasUpper + "\""); 3212e5b6d6dSopenharmony_ci } 3222e5b6d6dSopenharmony_ci 3232e5b6d6dSopenharmony_ci // turkish & azerbaijani dotless i & dotted I 3242e5b6d6dSopenharmony_ci // remove dot above if there was a capital I before and there are no more accents above 3252e5b6d6dSopenharmony_ci UnicodeString 3262e5b6d6dSopenharmony_ci dots=UnicodeString("I \\u0130 I\\u0307 I\\u0327\\u0307 I\\u0301\\u0307 I\\u0327\\u0307\\u0301", "").unescape(), 3272e5b6d6dSopenharmony_ci dotsTurkish=UnicodeString("\\u0131 i i i\\u0327 \\u0131\\u0301\\u0307 i\\u0327\\u0301", "").unescape(), 3282e5b6d6dSopenharmony_ci dotsDefault=UnicodeString("i i\\u0307 i\\u0307 i\\u0327\\u0307 i\\u0301\\u0307 i\\u0327\\u0307\\u0301", "").unescape(); 3292e5b6d6dSopenharmony_ci 3302e5b6d6dSopenharmony_ci (t=dots).toLower("tr"); 3312e5b6d6dSopenharmony_ci if(t!=dotsTurkish) { 3322e5b6d6dSopenharmony_ci errln("error in dots.toLower(tr)=\"" + t + "\" expected \"" + dotsTurkish + "\""); 3332e5b6d6dSopenharmony_ci } 3342e5b6d6dSopenharmony_ci 3352e5b6d6dSopenharmony_ci (t=dots).toLower("de"); 3362e5b6d6dSopenharmony_ci if(t!=dotsDefault) { 3372e5b6d6dSopenharmony_ci errln("error in dots.toLower(de)=\"" + t + "\" expected \"" + dotsDefault + "\""); 3382e5b6d6dSopenharmony_ci } 3392e5b6d6dSopenharmony_ci } 3402e5b6d6dSopenharmony_ci 3412e5b6d6dSopenharmony_ci // more Unicode 3.1.1 tests 3422e5b6d6dSopenharmony_ci { 3432e5b6d6dSopenharmony_ci UnicodeString t; 3442e5b6d6dSopenharmony_ci 3452e5b6d6dSopenharmony_ci // lithuanian dot above in uppercasing 3462e5b6d6dSopenharmony_ci UnicodeString 3472e5b6d6dSopenharmony_ci dots=UnicodeString("a\\u0307 \\u0307 i\\u0307 j\\u0327\\u0307 j\\u0301\\u0307", "").unescape(), 3482e5b6d6dSopenharmony_ci dotsLithuanian=UnicodeString("A\\u0307 \\u0307 I J\\u0327 J\\u0301\\u0307", "").unescape(), 3492e5b6d6dSopenharmony_ci dotsDefault=UnicodeString("A\\u0307 \\u0307 I\\u0307 J\\u0327\\u0307 J\\u0301\\u0307", "").unescape(); 3502e5b6d6dSopenharmony_ci 3512e5b6d6dSopenharmony_ci (t=dots).toUpper("lt"); 3522e5b6d6dSopenharmony_ci if(t!=dotsLithuanian) { 3532e5b6d6dSopenharmony_ci errln("error in dots.toUpper(lt)=\"" + t + "\" expected \"" + dotsLithuanian + "\""); 3542e5b6d6dSopenharmony_ci } 3552e5b6d6dSopenharmony_ci 3562e5b6d6dSopenharmony_ci (t=dots).toUpper("de"); 3572e5b6d6dSopenharmony_ci if(t!=dotsDefault) { 3582e5b6d6dSopenharmony_ci errln("error in dots.toUpper(de)=\"" + t + "\" expected \"" + dotsDefault + "\""); 3592e5b6d6dSopenharmony_ci } 3602e5b6d6dSopenharmony_ci 3612e5b6d6dSopenharmony_ci // lithuanian adds dot above to i in lowercasing if there are more above accents 3622e5b6d6dSopenharmony_ci UnicodeString 3632e5b6d6dSopenharmony_ci i=UnicodeString("I I\\u0301 J J\\u0301 \\u012e \\u012e\\u0301 \\u00cc\\u00cd\\u0128", "").unescape(), 3642e5b6d6dSopenharmony_ci iLithuanian=UnicodeString("i i\\u0307\\u0301 j j\\u0307\\u0301 \\u012f \\u012f\\u0307\\u0301 i\\u0307\\u0300i\\u0307\\u0301i\\u0307\\u0303", "").unescape(), 3652e5b6d6dSopenharmony_ci iDefault=UnicodeString("i i\\u0301 j j\\u0301 \\u012f \\u012f\\u0301 \\u00ec\\u00ed\\u0129", "").unescape(); 3662e5b6d6dSopenharmony_ci 3672e5b6d6dSopenharmony_ci (t=i).toLower("lt"); 3682e5b6d6dSopenharmony_ci if(t!=iLithuanian) { 3692e5b6d6dSopenharmony_ci errln("error in i.toLower(lt)=\"" + t + "\" expected \"" + iLithuanian + "\""); 3702e5b6d6dSopenharmony_ci } 3712e5b6d6dSopenharmony_ci 3722e5b6d6dSopenharmony_ci (t=i).toLower("de"); 3732e5b6d6dSopenharmony_ci if(t!=iDefault) { 3742e5b6d6dSopenharmony_ci errln("error in i.toLower(de)=\"" + t + "\" expected \"" + iDefault + "\""); 3752e5b6d6dSopenharmony_ci } 3762e5b6d6dSopenharmony_ci } 3772e5b6d6dSopenharmony_ci 3782e5b6d6dSopenharmony_ci#endif 3792e5b6d6dSopenharmony_ci 3802e5b6d6dSopenharmony_ci // test case folding 3812e5b6d6dSopenharmony_ci { 3822e5b6d6dSopenharmony_ci UnicodeString 3832e5b6d6dSopenharmony_ci s=UnicodeString("A\\u00df\\u00b5\\ufb03\\U0001040c\\u0130\\u0131", "").unescape(), 3842e5b6d6dSopenharmony_ci f=UnicodeString("ass\\u03bcffi\\U00010434i\\u0307\\u0131", "").unescape(), 3852e5b6d6dSopenharmony_ci g=UnicodeString("ass\\u03bcffi\\U00010434i\\u0131", "").unescape(), 3862e5b6d6dSopenharmony_ci t; 3872e5b6d6dSopenharmony_ci 3882e5b6d6dSopenharmony_ci (t=s).foldCase(); 3892e5b6d6dSopenharmony_ci if(f!=t) { 3902e5b6d6dSopenharmony_ci errln("error in foldCase(\"" + s + "\", default)=\"" + t + "\" but expected \"" + f + "\""); 3912e5b6d6dSopenharmony_ci } 3922e5b6d6dSopenharmony_ci 3932e5b6d6dSopenharmony_ci // alternate handling for dotted I/dotless i (U+0130, U+0131) 3942e5b6d6dSopenharmony_ci (t=s).foldCase(U_FOLD_CASE_EXCLUDE_SPECIAL_I); 3952e5b6d6dSopenharmony_ci if(g!=t) { 3962e5b6d6dSopenharmony_ci errln("error in foldCase(\"" + s + "\", U_FOLD_CASE_EXCLUDE_SPECIAL_I)=\"" + t + "\" but expected \"" + g + "\""); 3972e5b6d6dSopenharmony_ci } 3982e5b6d6dSopenharmony_ci } 3992e5b6d6dSopenharmony_ci} 4002e5b6d6dSopenharmony_ci 4012e5b6d6dSopenharmony_ci// data-driven case mapping tests ------------------------------------------ *** 4022e5b6d6dSopenharmony_ci 4032e5b6d6dSopenharmony_cienum { 4042e5b6d6dSopenharmony_ci TEST_LOWER, 4052e5b6d6dSopenharmony_ci TEST_UPPER, 4062e5b6d6dSopenharmony_ci TEST_TITLE, 4072e5b6d6dSopenharmony_ci TEST_FOLD, 4082e5b6d6dSopenharmony_ci TEST_COUNT 4092e5b6d6dSopenharmony_ci}; 4102e5b6d6dSopenharmony_ci 4112e5b6d6dSopenharmony_ci// names of TestData children in casing.txt 4122e5b6d6dSopenharmony_cistatic const char *const dataNames[TEST_COUNT+1]={ 4132e5b6d6dSopenharmony_ci "lowercasing", 4142e5b6d6dSopenharmony_ci "uppercasing", 4152e5b6d6dSopenharmony_ci "titlecasing", 4162e5b6d6dSopenharmony_ci "casefolding", 4172e5b6d6dSopenharmony_ci "" 4182e5b6d6dSopenharmony_ci}; 4192e5b6d6dSopenharmony_ci 4202e5b6d6dSopenharmony_civoid 4212e5b6d6dSopenharmony_ciStringCaseTest::TestCasingImpl(const UnicodeString &input, 4222e5b6d6dSopenharmony_ci const UnicodeString &output, 4232e5b6d6dSopenharmony_ci int32_t whichCase, 4242e5b6d6dSopenharmony_ci void *iter, const char *localeID, uint32_t options) { 4252e5b6d6dSopenharmony_ci // UnicodeString 4262e5b6d6dSopenharmony_ci UnicodeString result; 4272e5b6d6dSopenharmony_ci const char *name; 4282e5b6d6dSopenharmony_ci Locale locale(localeID); 4292e5b6d6dSopenharmony_ci 4302e5b6d6dSopenharmony_ci result=input; 4312e5b6d6dSopenharmony_ci switch(whichCase) { 4322e5b6d6dSopenharmony_ci case TEST_LOWER: 4332e5b6d6dSopenharmony_ci name="toLower"; 4342e5b6d6dSopenharmony_ci result.toLower(locale); 4352e5b6d6dSopenharmony_ci break; 4362e5b6d6dSopenharmony_ci case TEST_UPPER: 4372e5b6d6dSopenharmony_ci name="toUpper"; 4382e5b6d6dSopenharmony_ci result.toUpper(locale); 4392e5b6d6dSopenharmony_ci break; 4402e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 4412e5b6d6dSopenharmony_ci case TEST_TITLE: 4422e5b6d6dSopenharmony_ci name="toTitle"; 4432e5b6d6dSopenharmony_ci result.toTitle((BreakIterator *)iter, locale, options); 4442e5b6d6dSopenharmony_ci break; 4452e5b6d6dSopenharmony_ci#endif 4462e5b6d6dSopenharmony_ci case TEST_FOLD: 4472e5b6d6dSopenharmony_ci name="foldCase"; 4482e5b6d6dSopenharmony_ci result.foldCase(options); 4492e5b6d6dSopenharmony_ci break; 4502e5b6d6dSopenharmony_ci default: 4512e5b6d6dSopenharmony_ci name=""; 4522e5b6d6dSopenharmony_ci break; // won't happen 4532e5b6d6dSopenharmony_ci } 4542e5b6d6dSopenharmony_ci if(result!=output) { 4552e5b6d6dSopenharmony_ci dataerrln("error: UnicodeString.%s() got a wrong result for a test case from casing.res", name); 4562e5b6d6dSopenharmony_ci dataerrln(UnicodeString("input = [") + input + "], expected = [" + output + "], actual = [" + result + "]"); 4572e5b6d6dSopenharmony_ci } 4582e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 4592e5b6d6dSopenharmony_ci if(whichCase==TEST_TITLE && options==0) { 4602e5b6d6dSopenharmony_ci result=input; 4612e5b6d6dSopenharmony_ci result.toTitle((BreakIterator *)iter, locale); 4622e5b6d6dSopenharmony_ci if(result!=output) { 4632e5b6d6dSopenharmony_ci dataerrln("error: UnicodeString.toTitle(options=0) got a wrong result for a test case from casing.res"); 4642e5b6d6dSopenharmony_ci } 4652e5b6d6dSopenharmony_ci } 4662e5b6d6dSopenharmony_ci#endif 4672e5b6d6dSopenharmony_ci 4682e5b6d6dSopenharmony_ci // UTF-8 4692e5b6d6dSopenharmony_ci char utf8In[100], utf8Out[100]; 4702e5b6d6dSopenharmony_ci int32_t utf8InLength, utf8OutLength, resultLength; 4712e5b6d6dSopenharmony_ci UChar *buffer; 4722e5b6d6dSopenharmony_ci 4732e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCasingImpl"); 4742e5b6d6dSopenharmony_ci LocalUCaseMapPointer csm(ucasemap_open(localeID, options, errorCode)); 4752e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 4762e5b6d6dSopenharmony_ci if(iter!=NULL) { 4772e5b6d6dSopenharmony_ci // Clone the break iterator so that the UCaseMap can safely adopt it. 4782e5b6d6dSopenharmony_ci UBreakIterator *clone=ubrk_safeClone((UBreakIterator *)iter, NULL, NULL, errorCode); 4792e5b6d6dSopenharmony_ci ucasemap_setBreakIterator(csm.getAlias(), clone, errorCode); 4802e5b6d6dSopenharmony_ci } 4812e5b6d6dSopenharmony_ci#endif 4822e5b6d6dSopenharmony_ci 4832e5b6d6dSopenharmony_ci u_strToUTF8(utf8In, (int32_t)sizeof(utf8In), &utf8InLength, input.getBuffer(), input.length(), errorCode); 4842e5b6d6dSopenharmony_ci switch(whichCase) { 4852e5b6d6dSopenharmony_ci case TEST_LOWER: 4862e5b6d6dSopenharmony_ci name="ucasemap_utf8ToLower"; 4872e5b6d6dSopenharmony_ci utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), 4882e5b6d6dSopenharmony_ci utf8Out, (int32_t)sizeof(utf8Out), 4892e5b6d6dSopenharmony_ci utf8In, utf8InLength, errorCode); 4902e5b6d6dSopenharmony_ci break; 4912e5b6d6dSopenharmony_ci case TEST_UPPER: 4922e5b6d6dSopenharmony_ci name="ucasemap_utf8ToUpper"; 4932e5b6d6dSopenharmony_ci utf8OutLength=ucasemap_utf8ToUpper(csm.getAlias(), 4942e5b6d6dSopenharmony_ci utf8Out, (int32_t)sizeof(utf8Out), 4952e5b6d6dSopenharmony_ci utf8In, utf8InLength, errorCode); 4962e5b6d6dSopenharmony_ci break; 4972e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 4982e5b6d6dSopenharmony_ci case TEST_TITLE: 4992e5b6d6dSopenharmony_ci name="ucasemap_utf8ToTitle"; 5002e5b6d6dSopenharmony_ci utf8OutLength=ucasemap_utf8ToTitle(csm.getAlias(), 5012e5b6d6dSopenharmony_ci utf8Out, (int32_t)sizeof(utf8Out), 5022e5b6d6dSopenharmony_ci utf8In, utf8InLength, errorCode); 5032e5b6d6dSopenharmony_ci break; 5042e5b6d6dSopenharmony_ci#endif 5052e5b6d6dSopenharmony_ci case TEST_FOLD: 5062e5b6d6dSopenharmony_ci name="ucasemap_utf8FoldCase"; 5072e5b6d6dSopenharmony_ci utf8OutLength=ucasemap_utf8FoldCase(csm.getAlias(), 5082e5b6d6dSopenharmony_ci utf8Out, (int32_t)sizeof(utf8Out), 5092e5b6d6dSopenharmony_ci utf8In, utf8InLength, errorCode); 5102e5b6d6dSopenharmony_ci break; 5112e5b6d6dSopenharmony_ci default: 5122e5b6d6dSopenharmony_ci name=""; 5132e5b6d6dSopenharmony_ci utf8OutLength=0; 5142e5b6d6dSopenharmony_ci break; // won't happen 5152e5b6d6dSopenharmony_ci } 5162e5b6d6dSopenharmony_ci buffer=result.getBuffer(utf8OutLength); 5172e5b6d6dSopenharmony_ci u_strFromUTF8(buffer, result.getCapacity(), &resultLength, utf8Out, utf8OutLength, errorCode); 5182e5b6d6dSopenharmony_ci result.releaseBuffer(errorCode.isSuccess() ? resultLength : 0); 5192e5b6d6dSopenharmony_ci 5202e5b6d6dSopenharmony_ci if(errorCode.isFailure()) { 5212e5b6d6dSopenharmony_ci errcheckln(errorCode, "error: %s() got an error for a test case from casing.res - %s", name, u_errorName(errorCode)); 5222e5b6d6dSopenharmony_ci errorCode.reset(); 5232e5b6d6dSopenharmony_ci } else if(result!=output) { 5242e5b6d6dSopenharmony_ci errln("error: %s() got a wrong result for a test case from casing.res", name); 5252e5b6d6dSopenharmony_ci errln("expected \"" + output + "\" got \"" + result + "\"" ); 5262e5b6d6dSopenharmony_ci } 5272e5b6d6dSopenharmony_ci} 5282e5b6d6dSopenharmony_ci 5292e5b6d6dSopenharmony_civoid 5302e5b6d6dSopenharmony_ciStringCaseTest::TestCasing() { 5312e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 5322e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 5332e5b6d6dSopenharmony_ci LocalUBreakIteratorPointer iter; 5342e5b6d6dSopenharmony_ci#endif 5352e5b6d6dSopenharmony_ci char cLocaleID[100]; 5362e5b6d6dSopenharmony_ci UnicodeString locale, input, output, optionsString, result; 5372e5b6d6dSopenharmony_ci uint32_t options; 5382e5b6d6dSopenharmony_ci int32_t whichCase, type; 5392e5b6d6dSopenharmony_ci LocalPointer<TestDataModule> driver(TestDataModule::getTestDataModule("casing", *this, status)); 5402e5b6d6dSopenharmony_ci if(U_SUCCESS(status)) { 5412e5b6d6dSopenharmony_ci for(whichCase=0; whichCase<TEST_COUNT; ++whichCase) { 5422e5b6d6dSopenharmony_ci#if UCONFIG_NO_BREAK_ITERATION 5432e5b6d6dSopenharmony_ci if(whichCase==TEST_TITLE) { 5442e5b6d6dSopenharmony_ci continue; 5452e5b6d6dSopenharmony_ci } 5462e5b6d6dSopenharmony_ci#endif 5472e5b6d6dSopenharmony_ci LocalPointer<TestData> casingTest(driver->createTestData(dataNames[whichCase], status)); 5482e5b6d6dSopenharmony_ci if(U_FAILURE(status)) { 5492e5b6d6dSopenharmony_ci errln("TestCasing failed to createTestData(%s) - %s", dataNames[whichCase], u_errorName(status)); 5502e5b6d6dSopenharmony_ci break; 5512e5b6d6dSopenharmony_ci } 5522e5b6d6dSopenharmony_ci const DataMap *myCase = NULL; 5532e5b6d6dSopenharmony_ci while(casingTest->nextCase(myCase, status)) { 5542e5b6d6dSopenharmony_ci input = myCase->getString("Input", status); 5552e5b6d6dSopenharmony_ci output = myCase->getString("Output", status); 5562e5b6d6dSopenharmony_ci 5572e5b6d6dSopenharmony_ci if(whichCase!=TEST_FOLD) { 5582e5b6d6dSopenharmony_ci locale = myCase->getString("Locale", status); 5592e5b6d6dSopenharmony_ci } 5602e5b6d6dSopenharmony_ci locale.extract(0, 0x7fffffff, cLocaleID, sizeof(cLocaleID), ""); 5612e5b6d6dSopenharmony_ci 5622e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 5632e5b6d6dSopenharmony_ci if(whichCase==TEST_TITLE) { 5642e5b6d6dSopenharmony_ci type = myCase->getInt("Type", status); 5652e5b6d6dSopenharmony_ci if(type>=0) { 5662e5b6d6dSopenharmony_ci iter.adoptInstead(ubrk_open((UBreakIteratorType)type, cLocaleID, NULL, 0, &status)); 5672e5b6d6dSopenharmony_ci } else if(type==-2) { 5682e5b6d6dSopenharmony_ci // Open a trivial break iterator that only delivers { 0, length } 5692e5b6d6dSopenharmony_ci // or even just { 0 } as boundaries. 5702e5b6d6dSopenharmony_ci static const UChar rules[] = { 0x2e, 0x2a, 0x3b }; // ".*;" 5712e5b6d6dSopenharmony_ci UParseError parseError; 5722e5b6d6dSopenharmony_ci iter.adoptInstead(ubrk_openRules(rules, UPRV_LENGTHOF(rules), NULL, 0, &parseError, &status)); 5732e5b6d6dSopenharmony_ci } 5742e5b6d6dSopenharmony_ci } 5752e5b6d6dSopenharmony_ci#endif 5762e5b6d6dSopenharmony_ci options = 0; 5772e5b6d6dSopenharmony_ci if(whichCase==TEST_TITLE || whichCase==TEST_FOLD) { 5782e5b6d6dSopenharmony_ci optionsString = myCase->getString("Options", status); 5792e5b6d6dSopenharmony_ci if(optionsString.indexOf((UChar)0x54)>=0) { // T 5802e5b6d6dSopenharmony_ci options|=U_FOLD_CASE_EXCLUDE_SPECIAL_I; 5812e5b6d6dSopenharmony_ci } 5822e5b6d6dSopenharmony_ci if(optionsString.indexOf((UChar)0x4c)>=0) { // L 5832e5b6d6dSopenharmony_ci options|=U_TITLECASE_NO_LOWERCASE; 5842e5b6d6dSopenharmony_ci } 5852e5b6d6dSopenharmony_ci if(optionsString.indexOf((UChar)0x41)>=0) { // A 5862e5b6d6dSopenharmony_ci options|=U_TITLECASE_NO_BREAK_ADJUSTMENT; 5872e5b6d6dSopenharmony_ci } 5882e5b6d6dSopenharmony_ci } 5892e5b6d6dSopenharmony_ci 5902e5b6d6dSopenharmony_ci if(U_FAILURE(status)) { 5912e5b6d6dSopenharmony_ci dataerrln("error: TestCasing() setup failed for %s test case from casing.res: %s", dataNames[whichCase], u_errorName(status)); 5922e5b6d6dSopenharmony_ci status = U_ZERO_ERROR; 5932e5b6d6dSopenharmony_ci } else { 5942e5b6d6dSopenharmony_ci#if UCONFIG_NO_BREAK_ITERATION 5952e5b6d6dSopenharmony_ci LocalPointer<UMemory> iter; 5962e5b6d6dSopenharmony_ci#endif 5972e5b6d6dSopenharmony_ci TestCasingImpl(input, output, whichCase, iter.getAlias(), cLocaleID, options); 5982e5b6d6dSopenharmony_ci } 5992e5b6d6dSopenharmony_ci 6002e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 6012e5b6d6dSopenharmony_ci iter.adoptInstead(NULL); 6022e5b6d6dSopenharmony_ci#endif 6032e5b6d6dSopenharmony_ci } 6042e5b6d6dSopenharmony_ci } 6052e5b6d6dSopenharmony_ci } 6062e5b6d6dSopenharmony_ci 6072e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 6082e5b6d6dSopenharmony_ci // more tests for API coverage 6092e5b6d6dSopenharmony_ci status=U_ZERO_ERROR; 6102e5b6d6dSopenharmony_ci input=UNICODE_STRING_SIMPLE("sTrA\\u00dfE").unescape(); 6112e5b6d6dSopenharmony_ci (result=input).toTitle(NULL); 6122e5b6d6dSopenharmony_ci if(result!=UNICODE_STRING_SIMPLE("Stra\\u00dfe").unescape()) { 6132e5b6d6dSopenharmony_ci dataerrln("UnicodeString::toTitle(NULL) failed."); 6142e5b6d6dSopenharmony_ci } 6152e5b6d6dSopenharmony_ci#endif 6162e5b6d6dSopenharmony_ci} 6172e5b6d6dSopenharmony_ci 6182e5b6d6dSopenharmony_civoid 6192e5b6d6dSopenharmony_ciStringCaseTest::TestTitleOptions() { 6202e5b6d6dSopenharmony_ci // New options in ICU 60. 6212e5b6d6dSopenharmony_ci TestCasingImpl(u"ʻcAt! ʻeTc.", u"ʻCat! ʻetc.", TEST_TITLE, 6222e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING); 6232e5b6d6dSopenharmony_ci TestCasingImpl(u"a ʻCaT. A ʻdOg! ʻeTc.", u"A ʻCaT. A ʻdOg! ʻETc.", TEST_TITLE, 6242e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_SENTENCES|U_TITLECASE_NO_LOWERCASE); 6252e5b6d6dSopenharmony_ci TestCasingImpl(u"49eRs", u"49ers", TEST_TITLE, 6262e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING); 6272e5b6d6dSopenharmony_ci TestCasingImpl(u"«丰(aBc)»", u"«丰(abc)»", TEST_TITLE, 6282e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING); 6292e5b6d6dSopenharmony_ci TestCasingImpl(u"49eRs", u"49Ers", TEST_TITLE, 6302e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING|U_TITLECASE_ADJUST_TO_CASED); 6312e5b6d6dSopenharmony_ci TestCasingImpl(u"«丰(aBc)»", u"«丰(Abc)»", TEST_TITLE, 6322e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING|U_TITLECASE_ADJUST_TO_CASED); 6332e5b6d6dSopenharmony_ci TestCasingImpl(u" john. Smith", u" John. Smith", TEST_TITLE, 6342e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING|U_TITLECASE_NO_LOWERCASE); 6352e5b6d6dSopenharmony_ci TestCasingImpl(u" john. Smith", u" john. smith", TEST_TITLE, 6362e5b6d6dSopenharmony_ci nullptr, "", U_TITLECASE_WHOLE_STRING|U_TITLECASE_NO_BREAK_ADJUSTMENT); 6372e5b6d6dSopenharmony_ci TestCasingImpl(u"«ijs»", u"«IJs»", TEST_TITLE, 6382e5b6d6dSopenharmony_ci nullptr, "nl-BE", U_TITLECASE_WHOLE_STRING); 6392e5b6d6dSopenharmony_ci TestCasingImpl(u"«ijs»", u"«İjs»", TEST_TITLE, 6402e5b6d6dSopenharmony_ci nullptr, "tr-DE", U_TITLECASE_WHOLE_STRING); 6412e5b6d6dSopenharmony_ci 6422e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 6432e5b6d6dSopenharmony_ci // Test conflicting settings. 6442e5b6d6dSopenharmony_ci // If & when we add more options, then the ORed combinations may become 6452e5b6d6dSopenharmony_ci // indistinguishable from valid values. 6462e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestTitleOptions"); 6472e5b6d6dSopenharmony_ci CaseMap::toTitle("", U_TITLECASE_NO_BREAK_ADJUSTMENT|U_TITLECASE_ADJUST_TO_CASED, nullptr, 6482e5b6d6dSopenharmony_ci u"", 0, nullptr, 0, nullptr, errorCode); 6492e5b6d6dSopenharmony_ci if (errorCode.get() != U_ILLEGAL_ARGUMENT_ERROR) { 6502e5b6d6dSopenharmony_ci errln("CaseMap::toTitle(multiple adjustment options) -> %s not illegal argument", 6512e5b6d6dSopenharmony_ci errorCode.errorName()); 6522e5b6d6dSopenharmony_ci } 6532e5b6d6dSopenharmony_ci errorCode.reset(); 6542e5b6d6dSopenharmony_ci CaseMap::toTitle("", U_TITLECASE_WHOLE_STRING|U_TITLECASE_SENTENCES, nullptr, 6552e5b6d6dSopenharmony_ci u"", 0, nullptr, 0, nullptr, errorCode); 6562e5b6d6dSopenharmony_ci if (errorCode.get() != U_ILLEGAL_ARGUMENT_ERROR) { 6572e5b6d6dSopenharmony_ci errln("CaseMap::toTitle(multiple iterator options) -> %s not illegal argument", 6582e5b6d6dSopenharmony_ci errorCode.errorName()); 6592e5b6d6dSopenharmony_ci } 6602e5b6d6dSopenharmony_ci errorCode.reset(); 6612e5b6d6dSopenharmony_ci LocalPointer<BreakIterator> iter( 6622e5b6d6dSopenharmony_ci BreakIterator::createCharacterInstance(Locale::getRoot(), errorCode)); 6632e5b6d6dSopenharmony_ci CaseMap::toTitle("", U_TITLECASE_WHOLE_STRING, iter.getAlias(), 6642e5b6d6dSopenharmony_ci u"", 0, nullptr, 0, nullptr, errorCode); 6652e5b6d6dSopenharmony_ci if (errorCode.get() != U_ILLEGAL_ARGUMENT_ERROR) { 6662e5b6d6dSopenharmony_ci errln("CaseMap::toTitle(iterator option + iterator) -> %s not illegal argument", 6672e5b6d6dSopenharmony_ci errorCode.errorName()); 6682e5b6d6dSopenharmony_ci } 6692e5b6d6dSopenharmony_ci errorCode.reset(); 6702e5b6d6dSopenharmony_ci#endif 6712e5b6d6dSopenharmony_ci} 6722e5b6d6dSopenharmony_ci 6732e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 6742e5b6d6dSopenharmony_civoid StringCaseTest::TestDutchTitle() { 6752e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestDutchTitle"); 6762e5b6d6dSopenharmony_ci 6772e5b6d6dSopenharmony_ci Locale nl("nl"); // Dutch 6782e5b6d6dSopenharmony_ci LocalPointer<BreakIterator> iter( 6792e5b6d6dSopenharmony_ci BreakIterator::createWordInstance(nl, errorCode)); 6802e5b6d6dSopenharmony_ci 6812e5b6d6dSopenharmony_ci // Dutch titlecase check in English 6822e5b6d6dSopenharmony_ci TestCasingImpl( 6832e5b6d6dSopenharmony_ci u"ijssel igloo IJMUIDEN", 6842e5b6d6dSopenharmony_ci u"Ijssel Igloo Ijmuiden", 6852e5b6d6dSopenharmony_ci TEST_TITLE, 6862e5b6d6dSopenharmony_ci nullptr, 6872e5b6d6dSopenharmony_ci "en", 6882e5b6d6dSopenharmony_ci 0); 6892e5b6d6dSopenharmony_ci 6902e5b6d6dSopenharmony_ci // Dutch titlecase check in Dutch 6912e5b6d6dSopenharmony_ci TestCasingImpl( 6922e5b6d6dSopenharmony_ci u"ijssel igloo IJMUIDEN", 6932e5b6d6dSopenharmony_ci u"IJssel Igloo IJmuiden", 6942e5b6d6dSopenharmony_ci TEST_TITLE, 6952e5b6d6dSopenharmony_ci nullptr, 6962e5b6d6dSopenharmony_ci "nl", 6972e5b6d6dSopenharmony_ci 0); 6982e5b6d6dSopenharmony_ci 6992e5b6d6dSopenharmony_ci // Dutch titlecase check in Dutch with nolowercase option 7002e5b6d6dSopenharmony_ci if (U_SUCCESS(errorCode)) { 7012e5b6d6dSopenharmony_ci iter->setText(u"ijssel igloo IjMUIdEN iPoD ijenough"); 7022e5b6d6dSopenharmony_ci TestCasingImpl( 7032e5b6d6dSopenharmony_ci u"ijssel igloo IjMUIdEN iPoD ijenough", 7042e5b6d6dSopenharmony_ci u"IJssel Igloo IJMUIdEN IPoD IJenough", 7052e5b6d6dSopenharmony_ci TEST_TITLE, 7062e5b6d6dSopenharmony_ci nullptr, 7072e5b6d6dSopenharmony_ci "nl", 7082e5b6d6dSopenharmony_ci U_TITLECASE_NO_LOWERCASE); 7092e5b6d6dSopenharmony_ci } 7102e5b6d6dSopenharmony_ci 7112e5b6d6dSopenharmony_ci errorCode.reset(); 7122e5b6d6dSopenharmony_ci 7132e5b6d6dSopenharmony_ci // Accented IJ testing 7142e5b6d6dSopenharmony_ci 7152e5b6d6dSopenharmony_ci struct dutchTitleTestCase { 7162e5b6d6dSopenharmony_ci const UnicodeString input; 7172e5b6d6dSopenharmony_ci const UnicodeString expectedFull; 7182e5b6d6dSopenharmony_ci const UnicodeString expectedOnlyChanged; 7192e5b6d6dSopenharmony_ci } dutchTitleTestCases[] = { 7202e5b6d6dSopenharmony_ci // input, expectedFull, expectedOnlyChanged 7212e5b6d6dSopenharmony_ci {u"ij", u"IJ", u"IJ"}, 7222e5b6d6dSopenharmony_ci {u"IJ", u"IJ", u""}, 7232e5b6d6dSopenharmony_ci {u"íj́", u"ÍJ́", u"ÍJ"}, 7242e5b6d6dSopenharmony_ci {u"ÍJ́", u"ÍJ́", u""}, 7252e5b6d6dSopenharmony_ci {u"íJ́", u"ÍJ́", u"Í"}, 7262e5b6d6dSopenharmony_ci {u"Ij́", u"Ij́", u""}, 7272e5b6d6dSopenharmony_ci {u"ij́", u"Ij́", u"I"}, 7282e5b6d6dSopenharmony_ci {u"ïj́", u"Ïj́", u"Ï"}, 7292e5b6d6dSopenharmony_ci {u"íj\u0308", u"Íj\u0308", u"Í"}, 7302e5b6d6dSopenharmony_ci {u"íj́\U0001D16E", u"Íj́\U0001D16E", u"Í"}, 7312e5b6d6dSopenharmony_ci {u"íj\u1ABE", u"Íj\u1ABE", u"Í"}, 7322e5b6d6dSopenharmony_ci 7332e5b6d6dSopenharmony_ci {u"ijabc", u"IJabc", u"IJ"}, 7342e5b6d6dSopenharmony_ci {u"IJabc", u"IJabc", u""}, 7352e5b6d6dSopenharmony_ci {u"íj́abc", u"ÍJ́abc", u"ÍJ"}, 7362e5b6d6dSopenharmony_ci {u"ÍJ́abc", u"ÍJ́abc", u""}, 7372e5b6d6dSopenharmony_ci {u"íJ́abc", u"ÍJ́abc", u"Í"}, 7382e5b6d6dSopenharmony_ci {u"Ij́abc", u"Ij́abc", u""}, 7392e5b6d6dSopenharmony_ci {u"ij́abc", u"Ij́abc", u"I"}, 7402e5b6d6dSopenharmony_ci {u"ïj́abc", u"Ïj́abc", u"Ï"}, 7412e5b6d6dSopenharmony_ci {u"íjabc\u0308", u"Íjabc\u0308", u"Í"}, 7422e5b6d6dSopenharmony_ci {u"íj́abc\U0001D16E", u"ÍJ́abc\U0001D16E", u"ÍJ"}, 7432e5b6d6dSopenharmony_ci {u"íjabc\u1ABE", u"Íjabc\u1ABE", u"Í"}, 7442e5b6d6dSopenharmony_ci 7452e5b6d6dSopenharmony_ci // Bug ICU-21919 7462e5b6d6dSopenharmony_ci {u"Í", u"Í", u""}, 7472e5b6d6dSopenharmony_ci }; 7482e5b6d6dSopenharmony_ci 7492e5b6d6dSopenharmony_ci for (const auto& cas : dutchTitleTestCases) { 7502e5b6d6dSopenharmony_ci const UnicodeString &input = cas.input; 7512e5b6d6dSopenharmony_ci const UnicodeString &expectedFull = cas.expectedFull; 7522e5b6d6dSopenharmony_ci const UnicodeString &expectedOnlyChanged = cas.expectedOnlyChanged; 7532e5b6d6dSopenharmony_ci 7542e5b6d6dSopenharmony_ci for (const auto& isOnlyChanged : {true, false}) { 7552e5b6d6dSopenharmony_ci uint32_t testOptions = U_TITLECASE_NO_LOWERCASE 7562e5b6d6dSopenharmony_ci | (isOnlyChanged ? U_OMIT_UNCHANGED_TEXT : 0); 7572e5b6d6dSopenharmony_ci 7582e5b6d6dSopenharmony_ci const UnicodeString &expected = isOnlyChanged ? expectedOnlyChanged : expectedFull; 7592e5b6d6dSopenharmony_ci 7602e5b6d6dSopenharmony_ci TestCasingImpl( 7612e5b6d6dSopenharmony_ci input, 7622e5b6d6dSopenharmony_ci expected, 7632e5b6d6dSopenharmony_ci TEST_TITLE, 7642e5b6d6dSopenharmony_ci nullptr, 7652e5b6d6dSopenharmony_ci "nl", 7662e5b6d6dSopenharmony_ci testOptions 7672e5b6d6dSopenharmony_ci ); 7682e5b6d6dSopenharmony_ci } 7692e5b6d6dSopenharmony_ci } 7702e5b6d6dSopenharmony_ci} 7712e5b6d6dSopenharmony_ci#endif 7722e5b6d6dSopenharmony_ci 7732e5b6d6dSopenharmony_civoid 7742e5b6d6dSopenharmony_ciStringCaseTest::TestFullCaseFoldingIterator() { 7752e5b6d6dSopenharmony_ci UnicodeString ffi=UNICODE_STRING_SIMPLE("ffi"); 7762e5b6d6dSopenharmony_ci UnicodeString ss=UNICODE_STRING_SIMPLE("ss"); 7772e5b6d6dSopenharmony_ci FullCaseFoldingIterator iter; 7782e5b6d6dSopenharmony_ci int32_t count=0; 7792e5b6d6dSopenharmony_ci int32_t countSpecific=0; 7802e5b6d6dSopenharmony_ci UChar32 c; 7812e5b6d6dSopenharmony_ci UnicodeString full; 7822e5b6d6dSopenharmony_ci while((c=iter.next(full))>=0) { 7832e5b6d6dSopenharmony_ci ++count; 7842e5b6d6dSopenharmony_ci // Check that the full Case_Folding has more than 1 code point. 7852e5b6d6dSopenharmony_ci if(!full.hasMoreChar32Than(0, 0x7fffffff, 1)) { 7862e5b6d6dSopenharmony_ci errln("error: FullCaseFoldingIterator.next()=U+%04lX full Case_Folding has at most 1 code point", (long)c); 7872e5b6d6dSopenharmony_ci continue; 7882e5b6d6dSopenharmony_ci } 7892e5b6d6dSopenharmony_ci // Check that full == Case_Folding(c). 7902e5b6d6dSopenharmony_ci UnicodeString cf(c); 7912e5b6d6dSopenharmony_ci cf.foldCase(); 7922e5b6d6dSopenharmony_ci if(full!=cf) { 7932e5b6d6dSopenharmony_ci errln("error: FullCaseFoldingIterator.next()=U+%04lX full Case_Folding != cf(c)", (long)c); 7942e5b6d6dSopenharmony_ci continue; 7952e5b6d6dSopenharmony_ci } 7962e5b6d6dSopenharmony_ci // Spot-check a couple of specific cases. 7972e5b6d6dSopenharmony_ci if((full==ffi && c==0xfb03) || (full==ss && (c==0xdf || c==0x1e9e))) { 7982e5b6d6dSopenharmony_ci ++countSpecific; 7992e5b6d6dSopenharmony_ci } 8002e5b6d6dSopenharmony_ci } 8012e5b6d6dSopenharmony_ci if(countSpecific!=3) { 8022e5b6d6dSopenharmony_ci errln("error: FullCaseFoldingIterator did not yield exactly the expected specific cases"); 8032e5b6d6dSopenharmony_ci } 8042e5b6d6dSopenharmony_ci if(count<70) { 8052e5b6d6dSopenharmony_ci errln("error: FullCaseFoldingIterator yielded only %d (cp, full) pairs", (int)count); 8062e5b6d6dSopenharmony_ci } 8072e5b6d6dSopenharmony_ci} 8082e5b6d6dSopenharmony_ci 8092e5b6d6dSopenharmony_civoid 8102e5b6d6dSopenharmony_ciStringCaseTest::assertGreekUpper(const char16_t *s, const char16_t *expected) { 8112e5b6d6dSopenharmony_ci UnicodeString s16(s); 8122e5b6d6dSopenharmony_ci UnicodeString expected16(expected); 8132e5b6d6dSopenharmony_ci UnicodeString msg = UnicodeString("UnicodeString::toUpper/Greek(\"") + s16 + "\")"; 8142e5b6d6dSopenharmony_ci UnicodeString result16(s16); 8152e5b6d6dSopenharmony_ci result16.toUpper(GREEK_LOCALE_); 8162e5b6d6dSopenharmony_ci assertEquals(msg, expected16, result16); 8172e5b6d6dSopenharmony_ci 8182e5b6d6dSopenharmony_ci msg = UnicodeString("u_strToUpper/Greek(\"") + s16 + "\") cap="; 8192e5b6d6dSopenharmony_ci int32_t length = expected16.length(); 8202e5b6d6dSopenharmony_ci int32_t capacities[] = { 8212e5b6d6dSopenharmony_ci // Keep in sync with the UTF-8 capacities near the bottom of this function. 8222e5b6d6dSopenharmony_ci 0, length / 2, length - 1, length, length + 1 8232e5b6d6dSopenharmony_ci }; 8242e5b6d6dSopenharmony_ci for (int32_t i = 0; i < UPRV_LENGTHOF(capacities); ++i) { 8252e5b6d6dSopenharmony_ci int32_t cap = capacities[i]; 8262e5b6d6dSopenharmony_ci UChar *dest16 = result16.getBuffer(expected16.length() + 1); 8272e5b6d6dSopenharmony_ci u_memset(dest16, 0x55AA, result16.getCapacity()); 8282e5b6d6dSopenharmony_ci UErrorCode errorCode = U_ZERO_ERROR; 8292e5b6d6dSopenharmony_ci length = u_strToUpper(dest16, cap, s16.getBuffer(), s16.length(), "el", &errorCode); 8302e5b6d6dSopenharmony_ci assertEquals(msg + cap, expected16.length(), length); 8312e5b6d6dSopenharmony_ci UErrorCode expectedErrorCode; 8322e5b6d6dSopenharmony_ci if (cap < expected16.length()) { 8332e5b6d6dSopenharmony_ci expectedErrorCode = U_BUFFER_OVERFLOW_ERROR; 8342e5b6d6dSopenharmony_ci } else if (cap == expected16.length()) { 8352e5b6d6dSopenharmony_ci expectedErrorCode = U_STRING_NOT_TERMINATED_WARNING; 8362e5b6d6dSopenharmony_ci } else { 8372e5b6d6dSopenharmony_ci expectedErrorCode = U_ZERO_ERROR; 8382e5b6d6dSopenharmony_ci assertEquals(msg + cap + " NUL", 0, dest16[length]); 8392e5b6d6dSopenharmony_ci } 8402e5b6d6dSopenharmony_ci assertEquals(msg + cap + " errorCode", expectedErrorCode, errorCode); 8412e5b6d6dSopenharmony_ci result16.releaseBuffer(length); 8422e5b6d6dSopenharmony_ci if (cap >= expected16.length()) { 8432e5b6d6dSopenharmony_ci assertEquals(msg + cap, expected16, result16); 8442e5b6d6dSopenharmony_ci } 8452e5b6d6dSopenharmony_ci } 8462e5b6d6dSopenharmony_ci 8472e5b6d6dSopenharmony_ci UErrorCode errorCode = U_ZERO_ERROR; 8482e5b6d6dSopenharmony_ci LocalUCaseMapPointer csm(ucasemap_open("el", 0, &errorCode)); 8492e5b6d6dSopenharmony_ci assertSuccess("ucasemap_open", errorCode); 8502e5b6d6dSopenharmony_ci std::string s8; 8512e5b6d6dSopenharmony_ci s16.toUTF8String(s8); 8522e5b6d6dSopenharmony_ci msg = UnicodeString("ucasemap_utf8ToUpper/Greek(\"") + s16 + "\")"; 8532e5b6d6dSopenharmony_ci char dest8[1000]; 8542e5b6d6dSopenharmony_ci length = ucasemap_utf8ToUpper(csm.getAlias(), dest8, UPRV_LENGTHOF(dest8), 8552e5b6d6dSopenharmony_ci s8.data(), static_cast<int32_t>(s8.length()), &errorCode); 8562e5b6d6dSopenharmony_ci assertSuccess("ucasemap_utf8ToUpper", errorCode); 8572e5b6d6dSopenharmony_ci StringPiece result8(dest8, length); 8582e5b6d6dSopenharmony_ci UnicodeString result16From8 = UnicodeString::fromUTF8(result8); 8592e5b6d6dSopenharmony_ci assertEquals(msg, expected16, result16From8); 8602e5b6d6dSopenharmony_ci 8612e5b6d6dSopenharmony_ci msg += " cap="; 8622e5b6d6dSopenharmony_ci capacities[1] = length / 2; 8632e5b6d6dSopenharmony_ci capacities[2] = length - 1; 8642e5b6d6dSopenharmony_ci capacities[3] = length; 8652e5b6d6dSopenharmony_ci capacities[4] = length + 1; 8662e5b6d6dSopenharmony_ci char dest8b[1000]; 8672e5b6d6dSopenharmony_ci int32_t expected8Length = length; // Assuming the previous call worked. 8682e5b6d6dSopenharmony_ci for (int32_t i = 0; i < UPRV_LENGTHOF(capacities); ++i) { 8692e5b6d6dSopenharmony_ci int32_t cap = capacities[i]; 8702e5b6d6dSopenharmony_ci memset(dest8b, 0x5A, UPRV_LENGTHOF(dest8b)); 8712e5b6d6dSopenharmony_ci UErrorCode errorCode = U_ZERO_ERROR; 8722e5b6d6dSopenharmony_ci length = ucasemap_utf8ToUpper(csm.getAlias(), dest8b, cap, 8732e5b6d6dSopenharmony_ci s8.data(), static_cast<int32_t>(s8.length()), &errorCode); 8742e5b6d6dSopenharmony_ci assertEquals(msg + cap, expected8Length, length); 8752e5b6d6dSopenharmony_ci UErrorCode expectedErrorCode; 8762e5b6d6dSopenharmony_ci if (cap < expected8Length) { 8772e5b6d6dSopenharmony_ci expectedErrorCode = U_BUFFER_OVERFLOW_ERROR; 8782e5b6d6dSopenharmony_ci } else if (cap == expected8Length) { 8792e5b6d6dSopenharmony_ci expectedErrorCode = U_STRING_NOT_TERMINATED_WARNING; 8802e5b6d6dSopenharmony_ci } else { 8812e5b6d6dSopenharmony_ci expectedErrorCode = U_ZERO_ERROR; 8822e5b6d6dSopenharmony_ci // Casts to int32_t to avoid matching UBool. 8832e5b6d6dSopenharmony_ci assertEquals(msg + cap + " NUL", (int32_t)0, (int32_t)dest8b[length]); 8842e5b6d6dSopenharmony_ci } 8852e5b6d6dSopenharmony_ci assertEquals(msg + cap + " errorCode", expectedErrorCode, errorCode); 8862e5b6d6dSopenharmony_ci if (cap >= expected8Length) { 8872e5b6d6dSopenharmony_ci assertEquals(msg + cap + " (memcmp)", 0, memcmp(dest8, dest8b, expected8Length)); 8882e5b6d6dSopenharmony_ci } 8892e5b6d6dSopenharmony_ci } 8902e5b6d6dSopenharmony_ci} 8912e5b6d6dSopenharmony_ci 8922e5b6d6dSopenharmony_civoid 8932e5b6d6dSopenharmony_ciStringCaseTest::TestGreekUpper() { 8942e5b6d6dSopenharmony_ci // https://unicode-org.atlassian.net/browse/ICU-5456 8952e5b6d6dSopenharmony_ci assertGreekUpper(u"άδικος, κείμενο, ίριδα", u"ΑΔΙΚΟΣ, ΚΕΙΜΕΝΟ, ΙΡΙΔΑ"); 8962e5b6d6dSopenharmony_ci // https://bugzilla.mozilla.org/show_bug.cgi?id=307039 8972e5b6d6dSopenharmony_ci // https://bug307039.bmoattachments.org/attachment.cgi?id=194893 8982e5b6d6dSopenharmony_ci assertGreekUpper(u"Πατάτα", u"ΠΑΤΑΤΑ"); 8992e5b6d6dSopenharmony_ci assertGreekUpper(u"Αέρας, Μυστήριο, Ωραίο", u"ΑΕΡΑΣ, ΜΥΣΤΗΡΙΟ, ΩΡΑΙΟ"); 9002e5b6d6dSopenharmony_ci assertGreekUpper(u"Μαΐου, Πόρος, Ρύθμιση", u"ΜΑΪΟΥ, ΠΟΡΟΣ, ΡΥΘΜΙΣΗ"); 9012e5b6d6dSopenharmony_ci assertGreekUpper(u"ΰ, Τηρώ, Μάιος", u"Ϋ, ΤΗΡΩ, ΜΑΪΟΣ"); 9022e5b6d6dSopenharmony_ci assertGreekUpper(u"άυλος", u"ΑΫΛΟΣ"); 9032e5b6d6dSopenharmony_ci assertGreekUpper(u"ΑΫΛΟΣ", u"ΑΫΛΟΣ"); 9042e5b6d6dSopenharmony_ci assertGreekUpper(u"Άκλιτα ρήματα ή άκλιτες μετοχές", u"ΑΚΛΙΤΑ ΡΗΜΑΤΑ Ή ΑΚΛΙΤΕΣ ΜΕΤΟΧΕΣ"); 9052e5b6d6dSopenharmony_ci // http://www.unicode.org/udhr/d/udhr_ell_monotonic.html 9062e5b6d6dSopenharmony_ci assertGreekUpper(u"Επειδή η αναγνώριση της αξιοπρέπειας", u"ΕΠΕΙΔΗ Η ΑΝΑΓΝΩΡΙΣΗ ΤΗΣ ΑΞΙΟΠΡΕΠΕΙΑΣ"); 9072e5b6d6dSopenharmony_ci assertGreekUpper(u"νομικού ή διεθνούς", u"ΝΟΜΙΚΟΥ Ή ΔΙΕΘΝΟΥΣ"); 9082e5b6d6dSopenharmony_ci // http://unicode.org/udhr/d/udhr_ell_polytonic.html 9092e5b6d6dSopenharmony_ci assertGreekUpper(u"Ἐπειδὴ ἡ ἀναγνώριση", u"ΕΠΕΙΔΗ Η ΑΝΑΓΝΩΡΙΣΗ"); 9102e5b6d6dSopenharmony_ci assertGreekUpper(u"νομικοῦ ἢ διεθνοῦς", u"ΝΟΜΙΚΟΥ Ή ΔΙΕΘΝΟΥΣ"); 9112e5b6d6dSopenharmony_ci // From Google bug report 9122e5b6d6dSopenharmony_ci assertGreekUpper(u"Νέο, Δημιουργία", u"ΝΕΟ, ΔΗΜΙΟΥΡΓΙΑ"); 9132e5b6d6dSopenharmony_ci // http://crbug.com/234797 9142e5b6d6dSopenharmony_ci assertGreekUpper(u"Ελάτε να φάτε τα καλύτερα παϊδάκια!", u"ΕΛΑΤΕ ΝΑ ΦΑΤΕ ΤΑ ΚΑΛΥΤΕΡΑ ΠΑΪΔΑΚΙΑ!"); 9152e5b6d6dSopenharmony_ci assertGreekUpper(u"Μαΐου, τρόλεϊ", u"ΜΑΪΟΥ, ΤΡΟΛΕΪ"); 9162e5b6d6dSopenharmony_ci assertGreekUpper(u"Το ένα ή το άλλο.", u"ΤΟ ΕΝΑ Ή ΤΟ ΑΛΛΟ."); 9172e5b6d6dSopenharmony_ci // http://multilingualtypesetting.co.uk/blog/greek-typesetting-tips/ 9182e5b6d6dSopenharmony_ci assertGreekUpper(u"ρωμέικα", u"ΡΩΜΕΪΚΑ"); 9192e5b6d6dSopenharmony_ci assertGreekUpper(u"ή.", u"Ή."); 9202e5b6d6dSopenharmony_ci} 9212e5b6d6dSopenharmony_ci 9222e5b6d6dSopenharmony_civoid StringCaseTest::TestArmenian() { 9232e5b6d6dSopenharmony_ci Locale hy("hy"); // Eastern Armenian 9242e5b6d6dSopenharmony_ci Locale hyw("hyw"); // Western Armenian 9252e5b6d6dSopenharmony_ci Locale root = Locale::getRoot(); 9262e5b6d6dSopenharmony_ci // See ICU-13416: 9272e5b6d6dSopenharmony_ci // և ligature ech-yiwn 9282e5b6d6dSopenharmony_ci // uppercases to ԵՒ=ech+yiwn by default and in Western Armenian, 9292e5b6d6dSopenharmony_ci // but to ԵՎ=ech+vew in Eastern Armenian. 9302e5b6d6dSopenharmony_ci UnicodeString s(u"և Երևանի"); 9312e5b6d6dSopenharmony_ci 9322e5b6d6dSopenharmony_ci assertEquals("upper root", u"ԵՒ ԵՐԵՒԱՆԻ", UnicodeString(s).toUpper(root)); 9332e5b6d6dSopenharmony_ci assertEquals("upper hy", u"ԵՎ ԵՐԵՎԱՆԻ", UnicodeString(s).toUpper(hy)); 9342e5b6d6dSopenharmony_ci assertEquals("upper hyw", u"ԵՒ ԵՐԵՒԱՆԻ", UnicodeString(s).toUpper(hyw)); 9352e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 9362e5b6d6dSopenharmony_ci assertEquals("title root", u"Եւ Երևանի", UnicodeString(s).toTitle(nullptr, root)); 9372e5b6d6dSopenharmony_ci assertEquals("title hy", u"Եվ Երևանի", UnicodeString(s).toTitle(nullptr, hy)); 9382e5b6d6dSopenharmony_ci assertEquals("title hyw", u"Եւ Երևանի", UnicodeString(s).toTitle(nullptr, hyw)); 9392e5b6d6dSopenharmony_ci#endif 9402e5b6d6dSopenharmony_ci} 9412e5b6d6dSopenharmony_ci 9422e5b6d6dSopenharmony_civoid 9432e5b6d6dSopenharmony_ciStringCaseTest::TestLongUpper() { 9442e5b6d6dSopenharmony_ci if (quick) { 9452e5b6d6dSopenharmony_ci logln("not exhaustive mode: skipping this test"); 9462e5b6d6dSopenharmony_ci return; 9472e5b6d6dSopenharmony_ci } 9482e5b6d6dSopenharmony_ci // Ticket #12663, crash with an extremely long string where 9492e5b6d6dSopenharmony_ci // U+0390 maps to 0399 0308 0301 so that the result is three times as long 9502e5b6d6dSopenharmony_ci // and overflows an int32_t. 9512e5b6d6dSopenharmony_ci int32_t length = 0x40000004; // more than 1G UChars 9522e5b6d6dSopenharmony_ci UnicodeString s(length, (UChar32)0x390, length); 9532e5b6d6dSopenharmony_ci UnicodeString result; 9542e5b6d6dSopenharmony_ci UChar *dest = result.getBuffer(length + 1); 9552e5b6d6dSopenharmony_ci if (s.isBogus() || dest == NULL) { 9562e5b6d6dSopenharmony_ci logln("Out of memory, unable to run this test on this machine."); 9572e5b6d6dSopenharmony_ci return; 9582e5b6d6dSopenharmony_ci } 9592e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestLongUpper"); 9602e5b6d6dSopenharmony_ci int32_t destLength = u_strToUpper(dest, result.getCapacity(), 9612e5b6d6dSopenharmony_ci s.getBuffer(), s.length(), "", errorCode); 9622e5b6d6dSopenharmony_ci result.releaseBuffer(destLength); 9632e5b6d6dSopenharmony_ci if (errorCode.reset() != U_INDEX_OUTOFBOUNDS_ERROR) { 9642e5b6d6dSopenharmony_ci errln("expected U_INDEX_OUTOFBOUNDS_ERROR, got %s (destLength is undefined, got %ld)", 9652e5b6d6dSopenharmony_ci errorCode.errorName(), (long)destLength); 9662e5b6d6dSopenharmony_ci } 9672e5b6d6dSopenharmony_ci} 9682e5b6d6dSopenharmony_ci 9692e5b6d6dSopenharmony_civoid StringCaseTest::TestMalformedUTF8() { 9702e5b6d6dSopenharmony_ci // ticket #12639 9712e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestMalformedUTF8"); 9722e5b6d6dSopenharmony_ci LocalUCaseMapPointer csm(ucasemap_open("en", U_TITLECASE_NO_BREAK_ADJUSTMENT, errorCode)); 9732e5b6d6dSopenharmony_ci if (errorCode.isFailure()) { 9742e5b6d6dSopenharmony_ci errln("ucasemap_open(English) failed - %s", errorCode.errorName()); 9752e5b6d6dSopenharmony_ci return; 9762e5b6d6dSopenharmony_ci } 9772e5b6d6dSopenharmony_ci char src[1] = { (char)0x85 }; // malformed UTF-8 9782e5b6d6dSopenharmony_ci char dest[3] = { 0, 0, 0 }; 9792e5b6d6dSopenharmony_ci int32_t destLength; 9802e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 9812e5b6d6dSopenharmony_ci destLength = ucasemap_utf8ToTitle(csm.getAlias(), dest, 3, src, 1, errorCode); 9822e5b6d6dSopenharmony_ci if (errorCode.isFailure() || destLength != 1 || dest[0] != src[0]) { 9832e5b6d6dSopenharmony_ci errln("ucasemap_utf8ToTitle(\\x85) failed: %s destLength=%d dest[0]=0x%02x", 9842e5b6d6dSopenharmony_ci errorCode.errorName(), (int)destLength, dest[0]); 9852e5b6d6dSopenharmony_ci } 9862e5b6d6dSopenharmony_ci#endif 9872e5b6d6dSopenharmony_ci 9882e5b6d6dSopenharmony_ci errorCode.reset(); 9892e5b6d6dSopenharmony_ci dest[0] = 0; 9902e5b6d6dSopenharmony_ci destLength = ucasemap_utf8ToLower(csm.getAlias(), dest, 3, src, 1, errorCode); 9912e5b6d6dSopenharmony_ci if (errorCode.isFailure() || destLength != 1 || dest[0] != src[0]) { 9922e5b6d6dSopenharmony_ci errln("ucasemap_utf8ToLower(\\x85) failed: %s destLength=%d dest[0]=0x%02x", 9932e5b6d6dSopenharmony_ci errorCode.errorName(), (int)destLength, dest[0]); 9942e5b6d6dSopenharmony_ci } 9952e5b6d6dSopenharmony_ci 9962e5b6d6dSopenharmony_ci errorCode.reset(); 9972e5b6d6dSopenharmony_ci dest[0] = 0; 9982e5b6d6dSopenharmony_ci destLength = ucasemap_utf8ToUpper(csm.getAlias(), dest, 3, src, 1, errorCode); 9992e5b6d6dSopenharmony_ci if (errorCode.isFailure() || destLength != 1 || dest[0] != src[0]) { 10002e5b6d6dSopenharmony_ci errln("ucasemap_utf8ToUpper(\\x85) failed: %s destLength=%d dest[0]=0x%02x", 10012e5b6d6dSopenharmony_ci errorCode.errorName(), (int)destLength, dest[0]); 10022e5b6d6dSopenharmony_ci } 10032e5b6d6dSopenharmony_ci 10042e5b6d6dSopenharmony_ci errorCode.reset(); 10052e5b6d6dSopenharmony_ci dest[0] = 0; 10062e5b6d6dSopenharmony_ci destLength = ucasemap_utf8FoldCase(csm.getAlias(), dest, 3, src, 1, errorCode); 10072e5b6d6dSopenharmony_ci if (errorCode.isFailure() || destLength != 1 || dest[0] != src[0]) { 10082e5b6d6dSopenharmony_ci errln("ucasemap_utf8FoldCase(\\x85) failed: %s destLength=%d dest[0]=0x%02x", 10092e5b6d6dSopenharmony_ci errorCode.errorName(), (int)destLength, dest[0]); 10102e5b6d6dSopenharmony_ci } 10112e5b6d6dSopenharmony_ci} 10122e5b6d6dSopenharmony_ci 10132e5b6d6dSopenharmony_civoid StringCaseTest::TestBufferOverflow() { 10142e5b6d6dSopenharmony_ci // Ticket #12849, incorrect result from Title Case preflight operation, 10152e5b6d6dSopenharmony_ci // when buffer overflow error is expected. 10162e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestBufferOverflow"); 10172e5b6d6dSopenharmony_ci LocalUCaseMapPointer csm(ucasemap_open("en", 0, errorCode)); 10182e5b6d6dSopenharmony_ci if (errorCode.isFailure()) { 10192e5b6d6dSopenharmony_ci errln("ucasemap_open(English) failed - %s", errorCode.errorName()); 10202e5b6d6dSopenharmony_ci return; 10212e5b6d6dSopenharmony_ci } 10222e5b6d6dSopenharmony_ci 10232e5b6d6dSopenharmony_ci UnicodeString data("hello world"); 10242e5b6d6dSopenharmony_ci int32_t result; 10252e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 10262e5b6d6dSopenharmony_ci result = ucasemap_toTitle(csm.getAlias(), NULL, 0, data.getBuffer(), data.length(), errorCode); 10272e5b6d6dSopenharmony_ci if (errorCode.get() != U_BUFFER_OVERFLOW_ERROR || result != data.length()) { 10282e5b6d6dSopenharmony_ci errln("%s:%d ucasemap_toTitle(\"hello world\") failed: " 10292e5b6d6dSopenharmony_ci "expected (U_BUFFER_OVERFLOW_ERROR, %d), got (%s, %d)", 10302e5b6d6dSopenharmony_ci __FILE__, __LINE__, data.length(), errorCode.errorName(), result); 10312e5b6d6dSopenharmony_ci } 10322e5b6d6dSopenharmony_ci#endif 10332e5b6d6dSopenharmony_ci errorCode.reset(); 10342e5b6d6dSopenharmony_ci 10352e5b6d6dSopenharmony_ci std::string data_utf8; 10362e5b6d6dSopenharmony_ci data.toUTF8String(data_utf8); 10372e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 10382e5b6d6dSopenharmony_ci result = ucasemap_utf8ToTitle(csm.getAlias(), NULL, 0, data_utf8.c_str(), static_cast<int32_t>(data_utf8.length()), errorCode); 10392e5b6d6dSopenharmony_ci if (errorCode.get() != U_BUFFER_OVERFLOW_ERROR || result != (int32_t)data_utf8.length()) { 10402e5b6d6dSopenharmony_ci errln("%s:%d ucasemap_toTitle(\"hello world\") failed: " 10412e5b6d6dSopenharmony_ci "expected (U_BUFFER_OVERFLOW_ERROR, %d), got (%s, %d)", 10422e5b6d6dSopenharmony_ci __FILE__, __LINE__, data_utf8.length(), errorCode.errorName(), result); 10432e5b6d6dSopenharmony_ci } 10442e5b6d6dSopenharmony_ci#endif 10452e5b6d6dSopenharmony_ci errorCode.reset(); 10462e5b6d6dSopenharmony_ci} 10472e5b6d6dSopenharmony_ci 10482e5b6d6dSopenharmony_civoid StringCaseTest::TestEdits() { 10492e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestEdits"); 10502e5b6d6dSopenharmony_ci Edits edits; 10512e5b6d6dSopenharmony_ci assertFalse("new Edits hasChanges", edits.hasChanges()); 10522e5b6d6dSopenharmony_ci assertEquals("new Edits numberOfChanges", 0, edits.numberOfChanges()); 10532e5b6d6dSopenharmony_ci assertEquals("new Edits", 0, edits.lengthDelta()); 10542e5b6d6dSopenharmony_ci edits.addUnchanged(1); // multiple unchanged ranges are combined 10552e5b6d6dSopenharmony_ci edits.addUnchanged(10000); // too long, and they are split 10562e5b6d6dSopenharmony_ci edits.addReplace(0, 0); 10572e5b6d6dSopenharmony_ci edits.addUnchanged(2); 10582e5b6d6dSopenharmony_ci assertFalse("unchanged 10003 hasChanges", edits.hasChanges()); 10592e5b6d6dSopenharmony_ci assertEquals("unchanged 10003 numberOfChanges", 0, edits.numberOfChanges()); 10602e5b6d6dSopenharmony_ci assertEquals("unchanged 10003", 0, edits.lengthDelta()); 10612e5b6d6dSopenharmony_ci edits.addReplace(2, 1); // multiple short equal-lengths edits are compressed 10622e5b6d6dSopenharmony_ci edits.addUnchanged(0); 10632e5b6d6dSopenharmony_ci edits.addReplace(2, 1); 10642e5b6d6dSopenharmony_ci edits.addReplace(2, 1); 10652e5b6d6dSopenharmony_ci edits.addReplace(0, 10); 10662e5b6d6dSopenharmony_ci edits.addReplace(100, 0); 10672e5b6d6dSopenharmony_ci edits.addReplace(3000, 4000); // variable-length encoding 10682e5b6d6dSopenharmony_ci edits.addReplace(100000, 100000); 10692e5b6d6dSopenharmony_ci assertTrue("some edits hasChanges", edits.hasChanges()); 10702e5b6d6dSopenharmony_ci assertEquals("some edits numberOfChanges", 7, edits.numberOfChanges()); 10712e5b6d6dSopenharmony_ci assertEquals("some edits", -3 + 10 - 100 + 1000, edits.lengthDelta()); 10722e5b6d6dSopenharmony_ci UErrorCode outErrorCode = U_ZERO_ERROR; 10732e5b6d6dSopenharmony_ci assertFalse("edits done: copyErrorTo", edits.copyErrorTo(outErrorCode)); 10742e5b6d6dSopenharmony_ci 10752e5b6d6dSopenharmony_ci static const EditChange coarseExpectedChanges[] = { 10762e5b6d6dSopenharmony_ci { false, 10003, 10003 }, 10772e5b6d6dSopenharmony_ci { true, 103106, 104013 } 10782e5b6d6dSopenharmony_ci }; 10792e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"coarse", 10802e5b6d6dSopenharmony_ci edits.getCoarseIterator(), edits.getCoarseIterator(), 10812e5b6d6dSopenharmony_ci coarseExpectedChanges, UPRV_LENGTHOF(coarseExpectedChanges), true, errorCode); 10822e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"coarse changes", 10832e5b6d6dSopenharmony_ci edits.getCoarseChangesIterator(), edits.getCoarseChangesIterator(), 10842e5b6d6dSopenharmony_ci coarseExpectedChanges, UPRV_LENGTHOF(coarseExpectedChanges), false, errorCode); 10852e5b6d6dSopenharmony_ci 10862e5b6d6dSopenharmony_ci static const EditChange fineExpectedChanges[] = { 10872e5b6d6dSopenharmony_ci { false, 10003, 10003 }, 10882e5b6d6dSopenharmony_ci { true, 2, 1 }, 10892e5b6d6dSopenharmony_ci { true, 2, 1 }, 10902e5b6d6dSopenharmony_ci { true, 2, 1 }, 10912e5b6d6dSopenharmony_ci { true, 0, 10 }, 10922e5b6d6dSopenharmony_ci { true, 100, 0 }, 10932e5b6d6dSopenharmony_ci { true, 3000, 4000 }, 10942e5b6d6dSopenharmony_ci { true, 100000, 100000 } 10952e5b6d6dSopenharmony_ci }; 10962e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"fine", 10972e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 10982e5b6d6dSopenharmony_ci fineExpectedChanges, UPRV_LENGTHOF(fineExpectedChanges), true, errorCode); 10992e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"fine changes", 11002e5b6d6dSopenharmony_ci edits.getFineChangesIterator(), edits.getFineChangesIterator(), 11012e5b6d6dSopenharmony_ci fineExpectedChanges, UPRV_LENGTHOF(fineExpectedChanges), false, errorCode); 11022e5b6d6dSopenharmony_ci 11032e5b6d6dSopenharmony_ci edits.reset(); 11042e5b6d6dSopenharmony_ci assertFalse("reset hasChanges", edits.hasChanges()); 11052e5b6d6dSopenharmony_ci assertEquals("reset numberOfChanges", 0, edits.numberOfChanges()); 11062e5b6d6dSopenharmony_ci assertEquals("reset", 0, edits.lengthDelta()); 11072e5b6d6dSopenharmony_ci Edits::Iterator ei = edits.getCoarseChangesIterator(); 11082e5b6d6dSopenharmony_ci assertFalse("reset then iterator", ei.next(errorCode)); 11092e5b6d6dSopenharmony_ci} 11102e5b6d6dSopenharmony_ci 11112e5b6d6dSopenharmony_civoid StringCaseTest::TestCopyMoveEdits() { 11122e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCopyMoveEdits"); 11132e5b6d6dSopenharmony_ci // Exceed the stack array capacity. 11142e5b6d6dSopenharmony_ci Edits a; 11152e5b6d6dSopenharmony_ci for (int32_t i = 0; i < 250; ++i) { 11162e5b6d6dSopenharmony_ci a.addReplace(i % 10, (i % 10) + 1); 11172e5b6d6dSopenharmony_ci } 11182e5b6d6dSopenharmony_ci assertEquals("a: many edits, length delta", 250, a.lengthDelta()); 11192e5b6d6dSopenharmony_ci 11202e5b6d6dSopenharmony_ci // copy 11212e5b6d6dSopenharmony_ci Edits b(a); 11222e5b6d6dSopenharmony_ci assertEquals("b: copy of many edits, length delta", 250, b.lengthDelta()); 11232e5b6d6dSopenharmony_ci assertEquals("a remains: many edits, length delta", 250, a.lengthDelta()); 11242e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"b copy of a", a, b, errorCode); 11252e5b6d6dSopenharmony_ci 11262e5b6d6dSopenharmony_ci // assign 11272e5b6d6dSopenharmony_ci Edits c; 11282e5b6d6dSopenharmony_ci c.addUnchanged(99); 11292e5b6d6dSopenharmony_ci c.addReplace(88, 77); 11302e5b6d6dSopenharmony_ci c = b; 11312e5b6d6dSopenharmony_ci assertEquals("c: assigned many edits, length delta", 250, c.lengthDelta()); 11322e5b6d6dSopenharmony_ci assertEquals("b remains: many edits, length delta", 250, b.lengthDelta()); 11332e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"c = b", b, c, errorCode); 11342e5b6d6dSopenharmony_ci 11352e5b6d6dSopenharmony_ci // std::move trouble on these platforms. 11362e5b6d6dSopenharmony_ci // See https://unicode-org.atlassian.net/browse/ICU-13393 11372e5b6d6dSopenharmony_ci#if !(U_PLATFORM == U_PF_AIX || U_PLATFORM == U_PF_OS390) 11382e5b6d6dSopenharmony_ci // move constructor empties object with heap array 11392e5b6d6dSopenharmony_ci Edits d(std::move(a)); 11402e5b6d6dSopenharmony_ci assertEquals("d: move-constructed many edits, length delta", 250, d.lengthDelta()); 11412e5b6d6dSopenharmony_ci assertFalse("a moved away: no more hasChanges", a.hasChanges()); 11422e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"d() <- a", d, b, errorCode); 11432e5b6d6dSopenharmony_ci Edits empty; 11442e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"a moved away", empty, a, errorCode); 11452e5b6d6dSopenharmony_ci 11462e5b6d6dSopenharmony_ci // move assignment empties object with heap array 11472e5b6d6dSopenharmony_ci Edits e; 11482e5b6d6dSopenharmony_ci e.addReplace(0, 1000); 11492e5b6d6dSopenharmony_ci e = std::move(b); 11502e5b6d6dSopenharmony_ci assertEquals("e: move-assigned many edits, length delta", 250, e.lengthDelta()); 11512e5b6d6dSopenharmony_ci assertFalse("b moved away: no more hasChanges", b.hasChanges()); 11522e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"e <- b", e, c, errorCode); 11532e5b6d6dSopenharmony_ci TestUtility::checkEqualEdits(*this, u"b moved away", empty, b, errorCode); 11542e5b6d6dSopenharmony_ci 11552e5b6d6dSopenharmony_ci // Edits::Iterator default constructor. 11562e5b6d6dSopenharmony_ci Edits::Iterator iter; 11572e5b6d6dSopenharmony_ci assertFalse("Edits::Iterator().next()", iter.next(errorCode)); 11582e5b6d6dSopenharmony_ci assertSuccess("Edits::Iterator().next()", errorCode); 11592e5b6d6dSopenharmony_ci iter = e.getFineChangesIterator(); 11602e5b6d6dSopenharmony_ci assertTrue("iter.next()", iter.next(errorCode)); 11612e5b6d6dSopenharmony_ci assertSuccess("iter.next()", errorCode); 11622e5b6d6dSopenharmony_ci assertTrue("iter.hasChange()", iter.hasChange()); 11632e5b6d6dSopenharmony_ci assertEquals("iter.newLength()", 1, iter.newLength()); 11642e5b6d6dSopenharmony_ci#endif 11652e5b6d6dSopenharmony_ci} 11662e5b6d6dSopenharmony_ci 11672e5b6d6dSopenharmony_civoid StringCaseTest::TestEditsFindFwdBwd() { 11682e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestEditsFindFwdBwd"); 11692e5b6d6dSopenharmony_ci // Some users need index mappings to be efficient when they are out of order. 11702e5b6d6dSopenharmony_ci // The most interesting failure case for this test is it taking a very long time. 11712e5b6d6dSopenharmony_ci Edits e; 11722e5b6d6dSopenharmony_ci constexpr int32_t N = 200000; 11732e5b6d6dSopenharmony_ci for (int32_t i = 0; i < N; ++i) { 11742e5b6d6dSopenharmony_ci e.addUnchanged(1); 11752e5b6d6dSopenharmony_ci e.addReplace(3, 1); 11762e5b6d6dSopenharmony_ci } 11772e5b6d6dSopenharmony_ci Edits::Iterator iter = e.getFineIterator(); 11782e5b6d6dSopenharmony_ci for (int32_t i = 0; i <= N; i += 2) { 11792e5b6d6dSopenharmony_ci assertEquals("ascending", i * 2, iter.sourceIndexFromDestinationIndex(i, errorCode)); 11802e5b6d6dSopenharmony_ci assertEquals("ascending", i * 2 + 1, iter.sourceIndexFromDestinationIndex(i + 1, errorCode)); 11812e5b6d6dSopenharmony_ci } 11822e5b6d6dSopenharmony_ci for (int32_t i = N; i >= 0; i -= 2) { 11832e5b6d6dSopenharmony_ci assertEquals("descending", i * 2 + 1, iter.sourceIndexFromDestinationIndex(i + 1, errorCode)); 11842e5b6d6dSopenharmony_ci assertEquals("descending", i * 2, iter.sourceIndexFromDestinationIndex(i, errorCode)); 11852e5b6d6dSopenharmony_ci } 11862e5b6d6dSopenharmony_ci} 11872e5b6d6dSopenharmony_ci 11882e5b6d6dSopenharmony_civoid StringCaseTest::TestMergeEdits() { 11892e5b6d6dSopenharmony_ci // For debugging, set -v to see matching edits up to a failure. 11902e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestMergeEdits"); 11912e5b6d6dSopenharmony_ci Edits ab, bc, ac, expected_ac; 11922e5b6d6dSopenharmony_ci 11932e5b6d6dSopenharmony_ci // Simple: Two parallel non-changes. 11942e5b6d6dSopenharmony_ci ab.addUnchanged(2); 11952e5b6d6dSopenharmony_ci bc.addUnchanged(2); 11962e5b6d6dSopenharmony_ci expected_ac.addUnchanged(2); 11972e5b6d6dSopenharmony_ci 11982e5b6d6dSopenharmony_ci // Simple: Two aligned changes. 11992e5b6d6dSopenharmony_ci ab.addReplace(3, 2); 12002e5b6d6dSopenharmony_ci bc.addReplace(2, 1); 12012e5b6d6dSopenharmony_ci expected_ac.addReplace(3, 1); 12022e5b6d6dSopenharmony_ci 12032e5b6d6dSopenharmony_ci // Unequal non-changes. 12042e5b6d6dSopenharmony_ci ab.addUnchanged(5); 12052e5b6d6dSopenharmony_ci bc.addUnchanged(3); 12062e5b6d6dSopenharmony_ci expected_ac.addUnchanged(3); 12072e5b6d6dSopenharmony_ci // ab ahead by 2 12082e5b6d6dSopenharmony_ci 12092e5b6d6dSopenharmony_ci // Overlapping changes accumulate until they share a boundary. 12102e5b6d6dSopenharmony_ci ab.addReplace(4, 3); 12112e5b6d6dSopenharmony_ci bc.addReplace(3, 2); 12122e5b6d6dSopenharmony_ci ab.addReplace(4, 3); 12132e5b6d6dSopenharmony_ci bc.addReplace(3, 2); 12142e5b6d6dSopenharmony_ci ab.addReplace(4, 3); 12152e5b6d6dSopenharmony_ci bc.addReplace(3, 2); 12162e5b6d6dSopenharmony_ci bc.addUnchanged(4); 12172e5b6d6dSopenharmony_ci expected_ac.addReplace(14, 8); 12182e5b6d6dSopenharmony_ci // bc ahead by 2 12192e5b6d6dSopenharmony_ci 12202e5b6d6dSopenharmony_ci // Balance out intermediate-string lengths. 12212e5b6d6dSopenharmony_ci ab.addUnchanged(2); 12222e5b6d6dSopenharmony_ci expected_ac.addUnchanged(2); 12232e5b6d6dSopenharmony_ci 12242e5b6d6dSopenharmony_ci // Insert something and delete it: Should disappear. 12252e5b6d6dSopenharmony_ci ab.addReplace(0, 5); 12262e5b6d6dSopenharmony_ci ab.addReplace(0, 2); 12272e5b6d6dSopenharmony_ci bc.addReplace(7, 0); 12282e5b6d6dSopenharmony_ci 12292e5b6d6dSopenharmony_ci // Parallel change to make a new boundary. 12302e5b6d6dSopenharmony_ci ab.addReplace(1, 2); 12312e5b6d6dSopenharmony_ci bc.addReplace(2, 3); 12322e5b6d6dSopenharmony_ci expected_ac.addReplace(1, 3); 12332e5b6d6dSopenharmony_ci 12342e5b6d6dSopenharmony_ci // Multiple ab deletions should remain separate at the boundary. 12352e5b6d6dSopenharmony_ci ab.addReplace(1, 0); 12362e5b6d6dSopenharmony_ci ab.addReplace(2, 0); 12372e5b6d6dSopenharmony_ci ab.addReplace(3, 0); 12382e5b6d6dSopenharmony_ci expected_ac.addReplace(1, 0); 12392e5b6d6dSopenharmony_ci expected_ac.addReplace(2, 0); 12402e5b6d6dSopenharmony_ci expected_ac.addReplace(3, 0); 12412e5b6d6dSopenharmony_ci 12422e5b6d6dSopenharmony_ci // Unequal non-changes can be split for another boundary. 12432e5b6d6dSopenharmony_ci ab.addUnchanged(2); 12442e5b6d6dSopenharmony_ci bc.addUnchanged(1); 12452e5b6d6dSopenharmony_ci expected_ac.addUnchanged(1); 12462e5b6d6dSopenharmony_ci // ab ahead by 1 12472e5b6d6dSopenharmony_ci 12482e5b6d6dSopenharmony_ci // Multiple bc insertions should create a boundary and remain separate. 12492e5b6d6dSopenharmony_ci bc.addReplace(0, 4); 12502e5b6d6dSopenharmony_ci bc.addReplace(0, 5); 12512e5b6d6dSopenharmony_ci bc.addReplace(0, 6); 12522e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 4); 12532e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 5); 12542e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 6); 12552e5b6d6dSopenharmony_ci // ab ahead by 1 12562e5b6d6dSopenharmony_ci 12572e5b6d6dSopenharmony_ci // Multiple ab deletions in the middle of a bc change are merged. 12582e5b6d6dSopenharmony_ci bc.addReplace(2, 2); 12592e5b6d6dSopenharmony_ci // bc ahead by 1 12602e5b6d6dSopenharmony_ci ab.addReplace(1, 0); 12612e5b6d6dSopenharmony_ci ab.addReplace(2, 0); 12622e5b6d6dSopenharmony_ci ab.addReplace(3, 0); 12632e5b6d6dSopenharmony_ci ab.addReplace(4, 1); 12642e5b6d6dSopenharmony_ci expected_ac.addReplace(11, 2); 12652e5b6d6dSopenharmony_ci 12662e5b6d6dSopenharmony_ci // Multiple bc insertions in the middle of an ab change are merged. 12672e5b6d6dSopenharmony_ci ab.addReplace(5, 6); 12682e5b6d6dSopenharmony_ci bc.addReplace(3, 3); 12692e5b6d6dSopenharmony_ci // ab ahead by 3 12702e5b6d6dSopenharmony_ci bc.addReplace(0, 4); 12712e5b6d6dSopenharmony_ci bc.addReplace(0, 5); 12722e5b6d6dSopenharmony_ci bc.addReplace(0, 6); 12732e5b6d6dSopenharmony_ci bc.addReplace(3, 7); 12742e5b6d6dSopenharmony_ci expected_ac.addReplace(5, 25); 12752e5b6d6dSopenharmony_ci 12762e5b6d6dSopenharmony_ci // Delete around a deletion. 12772e5b6d6dSopenharmony_ci ab.addReplace(4, 4); 12782e5b6d6dSopenharmony_ci ab.addReplace(3, 0); 12792e5b6d6dSopenharmony_ci ab.addUnchanged(2); 12802e5b6d6dSopenharmony_ci bc.addReplace(2, 2); 12812e5b6d6dSopenharmony_ci bc.addReplace(4, 0); 12822e5b6d6dSopenharmony_ci expected_ac.addReplace(9, 2); 12832e5b6d6dSopenharmony_ci 12842e5b6d6dSopenharmony_ci // Insert into an insertion. 12852e5b6d6dSopenharmony_ci ab.addReplace(0, 2); 12862e5b6d6dSopenharmony_ci bc.addReplace(1, 1); 12872e5b6d6dSopenharmony_ci bc.addReplace(0, 8); 12882e5b6d6dSopenharmony_ci bc.addUnchanged(4); 12892e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 10); 12902e5b6d6dSopenharmony_ci // bc ahead by 3 12912e5b6d6dSopenharmony_ci 12922e5b6d6dSopenharmony_ci // Balance out intermediate-string lengths. 12932e5b6d6dSopenharmony_ci ab.addUnchanged(3); 12942e5b6d6dSopenharmony_ci expected_ac.addUnchanged(3); 12952e5b6d6dSopenharmony_ci 12962e5b6d6dSopenharmony_ci // Deletions meet insertions. 12972e5b6d6dSopenharmony_ci // Output order is arbitrary in principle, but we expect insertions first 12982e5b6d6dSopenharmony_ci // and want to keep it that way. 12992e5b6d6dSopenharmony_ci ab.addReplace(2, 0); 13002e5b6d6dSopenharmony_ci ab.addReplace(4, 0); 13012e5b6d6dSopenharmony_ci ab.addReplace(6, 0); 13022e5b6d6dSopenharmony_ci bc.addReplace(0, 1); 13032e5b6d6dSopenharmony_ci bc.addReplace(0, 3); 13042e5b6d6dSopenharmony_ci bc.addReplace(0, 5); 13052e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 1); 13062e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 3); 13072e5b6d6dSopenharmony_ci expected_ac.addReplace(0, 5); 13082e5b6d6dSopenharmony_ci expected_ac.addReplace(2, 0); 13092e5b6d6dSopenharmony_ci expected_ac.addReplace(4, 0); 13102e5b6d6dSopenharmony_ci expected_ac.addReplace(6, 0); 13112e5b6d6dSopenharmony_ci 13122e5b6d6dSopenharmony_ci // End with a non-change, so that further edits are never reordered. 13132e5b6d6dSopenharmony_ci ab.addUnchanged(1); 13142e5b6d6dSopenharmony_ci bc.addUnchanged(1); 13152e5b6d6dSopenharmony_ci expected_ac.addUnchanged(1); 13162e5b6d6dSopenharmony_ci 13172e5b6d6dSopenharmony_ci ac.mergeAndAppend(ab, bc, errorCode); 13182e5b6d6dSopenharmony_ci assertSuccess("ab+bc", errorCode); 13192e5b6d6dSopenharmony_ci if (!TestUtility::checkEqualEdits(*this, u"ab+bc", expected_ac, ac, errorCode)) { 13202e5b6d6dSopenharmony_ci return; 13212e5b6d6dSopenharmony_ci } 13222e5b6d6dSopenharmony_ci 13232e5b6d6dSopenharmony_ci // Append more Edits. 13242e5b6d6dSopenharmony_ci Edits ab2, bc2; 13252e5b6d6dSopenharmony_ci ab2.addUnchanged(5); 13262e5b6d6dSopenharmony_ci bc2.addReplace(1, 2); 13272e5b6d6dSopenharmony_ci bc2.addUnchanged(4); 13282e5b6d6dSopenharmony_ci expected_ac.addReplace(1, 2); 13292e5b6d6dSopenharmony_ci expected_ac.addUnchanged(4); 13302e5b6d6dSopenharmony_ci ac.mergeAndAppend(ab2, bc2, errorCode); 13312e5b6d6dSopenharmony_ci assertSuccess("ab2+bc2", errorCode); 13322e5b6d6dSopenharmony_ci if (!TestUtility::checkEqualEdits(*this, u"ab2+bc2", expected_ac, ac, errorCode)) { 13332e5b6d6dSopenharmony_ci return; 13342e5b6d6dSopenharmony_ci } 13352e5b6d6dSopenharmony_ci 13362e5b6d6dSopenharmony_ci // Append empty edits. 13372e5b6d6dSopenharmony_ci Edits empty; 13382e5b6d6dSopenharmony_ci ac.mergeAndAppend(empty, empty, errorCode); 13392e5b6d6dSopenharmony_ci assertSuccess("empty+empty", errorCode); 13402e5b6d6dSopenharmony_ci if (!TestUtility::checkEqualEdits(*this, u"empty+empty", expected_ac, ac, errorCode)) { 13412e5b6d6dSopenharmony_ci return; 13422e5b6d6dSopenharmony_ci } 13432e5b6d6dSopenharmony_ci 13442e5b6d6dSopenharmony_ci // Error: Append more edits with mismatched intermediate-string lengths. 13452e5b6d6dSopenharmony_ci Edits mismatch; 13462e5b6d6dSopenharmony_ci mismatch.addReplace(1, 1); 13472e5b6d6dSopenharmony_ci ac.mergeAndAppend(ab2, mismatch, errorCode); 13482e5b6d6dSopenharmony_ci assertEquals("ab2+mismatch", U_ILLEGAL_ARGUMENT_ERROR, errorCode.get()); 13492e5b6d6dSopenharmony_ci errorCode.reset(); 13502e5b6d6dSopenharmony_ci ac.mergeAndAppend(mismatch, bc2, errorCode); 13512e5b6d6dSopenharmony_ci assertEquals("mismatch+bc2", U_ILLEGAL_ARGUMENT_ERROR, errorCode.get()); 13522e5b6d6dSopenharmony_ci errorCode.reset(); 13532e5b6d6dSopenharmony_ci} 13542e5b6d6dSopenharmony_ci 13552e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapWithEdits() { 13562e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCaseMapWithEdits"); 13572e5b6d6dSopenharmony_ci UChar dest[20]; 13582e5b6d6dSopenharmony_ci Edits edits; 13592e5b6d6dSopenharmony_ci 13602e5b6d6dSopenharmony_ci int32_t length = CaseMap::toLower("tr", U_OMIT_UNCHANGED_TEXT, 13612e5b6d6dSopenharmony_ci u"IstanBul", 8, dest, UPRV_LENGTHOF(dest), &edits, errorCode); 13622e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", UnicodeString(u"ıb"), UnicodeString(true, dest, length)); 13632e5b6d6dSopenharmony_ci static const EditChange lowerExpectedChanges[] = { 13642e5b6d6dSopenharmony_ci { true, 1, 1 }, 13652e5b6d6dSopenharmony_ci { false, 4, 4 }, 13662e5b6d6dSopenharmony_ci { true, 1, 1 }, 13672e5b6d6dSopenharmony_ci { false, 2, 2 } 13682e5b6d6dSopenharmony_ci }; 13692e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toLower(IstanBul)", 13702e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 13712e5b6d6dSopenharmony_ci lowerExpectedChanges, UPRV_LENGTHOF(lowerExpectedChanges), 13722e5b6d6dSopenharmony_ci true, errorCode); 13732e5b6d6dSopenharmony_ci 13742e5b6d6dSopenharmony_ci edits.reset(); 13752e5b6d6dSopenharmony_ci length = CaseMap::toUpper("el", U_OMIT_UNCHANGED_TEXT, 13762e5b6d6dSopenharmony_ci u"Πατάτα", 6, dest, UPRV_LENGTHOF(dest), &edits, errorCode); 13772e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", UnicodeString(u"ΑΤΑΤΑ"), UnicodeString(true, dest, length)); 13782e5b6d6dSopenharmony_ci static const EditChange upperExpectedChanges[] = { 13792e5b6d6dSopenharmony_ci { false, 1, 1 }, 13802e5b6d6dSopenharmony_ci { true, 1, 1 }, 13812e5b6d6dSopenharmony_ci { true, 1, 1 }, 13822e5b6d6dSopenharmony_ci { true, 1, 1 }, 13832e5b6d6dSopenharmony_ci { true, 1, 1 }, 13842e5b6d6dSopenharmony_ci { true, 1, 1 } 13852e5b6d6dSopenharmony_ci }; 13862e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toUpper(Πατάτα)", 13872e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 13882e5b6d6dSopenharmony_ci upperExpectedChanges, UPRV_LENGTHOF(upperExpectedChanges), 13892e5b6d6dSopenharmony_ci true, errorCode); 13902e5b6d6dSopenharmony_ci 13912e5b6d6dSopenharmony_ci edits.reset(); 13922e5b6d6dSopenharmony_ci 13932e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 13942e5b6d6dSopenharmony_ci length = CaseMap::toTitle("nl", 13952e5b6d6dSopenharmony_ci U_OMIT_UNCHANGED_TEXT | 13962e5b6d6dSopenharmony_ci U_TITLECASE_NO_BREAK_ADJUSTMENT | 13972e5b6d6dSopenharmony_ci U_TITLECASE_NO_LOWERCASE, 13982e5b6d6dSopenharmony_ci nullptr, u"IjssEL IglOo", 12, 13992e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), &edits, errorCode); 14002e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", UnicodeString(u"J"), UnicodeString(true, dest, length)); 14012e5b6d6dSopenharmony_ci static const EditChange titleExpectedChanges[] = { 14022e5b6d6dSopenharmony_ci { false, 1, 1 }, 14032e5b6d6dSopenharmony_ci { true, 1, 1 }, 14042e5b6d6dSopenharmony_ci { false, 10, 10 } 14052e5b6d6dSopenharmony_ci }; 14062e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toTitle(IjssEL IglOo)", 14072e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 14082e5b6d6dSopenharmony_ci titleExpectedChanges, UPRV_LENGTHOF(titleExpectedChanges), 14092e5b6d6dSopenharmony_ci true, errorCode); 14102e5b6d6dSopenharmony_ci#endif 14112e5b6d6dSopenharmony_ci 14122e5b6d6dSopenharmony_ci // No explicit nor automatic edits.reset(). Edits should be appended. 14132e5b6d6dSopenharmony_ci length = CaseMap::fold(U_OMIT_UNCHANGED_TEXT | U_EDITS_NO_RESET | U_FOLD_CASE_EXCLUDE_SPECIAL_I, 14142e5b6d6dSopenharmony_ci u"IßtanBul", 8, dest, UPRV_LENGTHOF(dest), &edits, errorCode); 14152e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", UnicodeString(u"ıssb"), UnicodeString(true, dest, length)); 14162e5b6d6dSopenharmony_ci static const EditChange foldExpectedChanges[] = { 14172e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 14182e5b6d6dSopenharmony_ci // From titlecasing. 14192e5b6d6dSopenharmony_ci { false, 1, 1 }, 14202e5b6d6dSopenharmony_ci { true, 1, 1 }, 14212e5b6d6dSopenharmony_ci { false, 10, 10 }, 14222e5b6d6dSopenharmony_ci#endif 14232e5b6d6dSopenharmony_ci // From case folding. 14242e5b6d6dSopenharmony_ci { true, 1, 1 }, 14252e5b6d6dSopenharmony_ci { true, 1, 2 }, 14262e5b6d6dSopenharmony_ci { false, 3, 3 }, 14272e5b6d6dSopenharmony_ci { true, 1, 1 }, 14282e5b6d6dSopenharmony_ci { false, 2, 2 } 14292e5b6d6dSopenharmony_ci }; 14302e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"foldCase(no Edits reset, IßtanBul)", 14312e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 14322e5b6d6dSopenharmony_ci foldExpectedChanges, UPRV_LENGTHOF(foldExpectedChanges), 14332e5b6d6dSopenharmony_ci true, errorCode); 14342e5b6d6dSopenharmony_ci} 14352e5b6d6dSopenharmony_ci 14362e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapUTF8WithEdits() { 14372e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCaseMapUTF8WithEdits"); 14382e5b6d6dSopenharmony_ci char dest[50]; 14392e5b6d6dSopenharmony_ci Edits edits; 14402e5b6d6dSopenharmony_ci 14412e5b6d6dSopenharmony_ci int32_t length = CaseMap::utf8ToLower("tr", U_OMIT_UNCHANGED_TEXT, 14422e5b6d6dSopenharmony_ci reinterpret_cast<const char*>(u8"IstanBul"), 8, 14432e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), &edits, errorCode); 14442e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", UnicodeString(u"ıb"), 14452e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(StringPiece(dest, length))); 14462e5b6d6dSopenharmony_ci static const EditChange lowerExpectedChanges[] = { 14472e5b6d6dSopenharmony_ci { true, 1, 2 }, 14482e5b6d6dSopenharmony_ci { false, 4, 4 }, 14492e5b6d6dSopenharmony_ci { true, 1, 1 }, 14502e5b6d6dSopenharmony_ci { false, 2, 2 } 14512e5b6d6dSopenharmony_ci }; 14522e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toLower(IstanBul)", 14532e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 14542e5b6d6dSopenharmony_ci lowerExpectedChanges, UPRV_LENGTHOF(lowerExpectedChanges), 14552e5b6d6dSopenharmony_ci true, errorCode); 14562e5b6d6dSopenharmony_ci 14572e5b6d6dSopenharmony_ci edits.reset(); 14582e5b6d6dSopenharmony_ci length = CaseMap::utf8ToUpper("el", U_OMIT_UNCHANGED_TEXT, 14592e5b6d6dSopenharmony_ci reinterpret_cast<const char*>(u8"Πατάτα"), 6 * 2, 14602e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), &edits, errorCode); 14612e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", UnicodeString(u"ΑΤΑΤΑ"), 14622e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(StringPiece(dest, length))); 14632e5b6d6dSopenharmony_ci static const EditChange upperExpectedChanges[] = { 14642e5b6d6dSopenharmony_ci { false, 2, 2 }, 14652e5b6d6dSopenharmony_ci { true, 2, 2 }, 14662e5b6d6dSopenharmony_ci { true, 2, 2 }, 14672e5b6d6dSopenharmony_ci { true, 2, 2 }, 14682e5b6d6dSopenharmony_ci { true, 2, 2 }, 14692e5b6d6dSopenharmony_ci { true, 2, 2 } 14702e5b6d6dSopenharmony_ci }; 14712e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toUpper(Πατάτα)", 14722e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 14732e5b6d6dSopenharmony_ci upperExpectedChanges, UPRV_LENGTHOF(upperExpectedChanges), 14742e5b6d6dSopenharmony_ci true, errorCode); 14752e5b6d6dSopenharmony_ci 14762e5b6d6dSopenharmony_ci edits.reset(); 14772e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 14782e5b6d6dSopenharmony_ci length = CaseMap::utf8ToTitle("nl", 14792e5b6d6dSopenharmony_ci U_OMIT_UNCHANGED_TEXT | 14802e5b6d6dSopenharmony_ci U_TITLECASE_NO_BREAK_ADJUSTMENT | 14812e5b6d6dSopenharmony_ci U_TITLECASE_NO_LOWERCASE, 14822e5b6d6dSopenharmony_ci nullptr, reinterpret_cast<const char*>(u8"IjssEL IglOo"), 12, 14832e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), &edits, errorCode); 14842e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", UnicodeString(u"J"), 14852e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(StringPiece(dest, length))); 14862e5b6d6dSopenharmony_ci static const EditChange titleExpectedChanges[] = { 14872e5b6d6dSopenharmony_ci { false, 1, 1 }, 14882e5b6d6dSopenharmony_ci { true, 1, 1 }, 14892e5b6d6dSopenharmony_ci { false, 10, 10 } 14902e5b6d6dSopenharmony_ci }; 14912e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"toTitle(IjssEL IglOo)", 14922e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 14932e5b6d6dSopenharmony_ci titleExpectedChanges, UPRV_LENGTHOF(titleExpectedChanges), 14942e5b6d6dSopenharmony_ci true, errorCode); 14952e5b6d6dSopenharmony_ci#endif 14962e5b6d6dSopenharmony_ci 14972e5b6d6dSopenharmony_ci // No explicit nor automatic edits.reset(). Edits should be appended. 14982e5b6d6dSopenharmony_ci length = CaseMap::utf8Fold(U_OMIT_UNCHANGED_TEXT | U_EDITS_NO_RESET | 14992e5b6d6dSopenharmony_ci U_FOLD_CASE_EXCLUDE_SPECIAL_I, 15002e5b6d6dSopenharmony_ci reinterpret_cast<const char*>(u8"IßtanBul"), 1 + 2 + 6, 15012e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), &edits, errorCode); 15022e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", UnicodeString(u"ıssb"), 15032e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(StringPiece(dest, length))); 15042e5b6d6dSopenharmony_ci static const EditChange foldExpectedChanges[] = { 15052e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 15062e5b6d6dSopenharmony_ci // From titlecasing. 15072e5b6d6dSopenharmony_ci { false, 1, 1 }, 15082e5b6d6dSopenharmony_ci { true, 1, 1 }, 15092e5b6d6dSopenharmony_ci { false, 10, 10 }, 15102e5b6d6dSopenharmony_ci#endif 15112e5b6d6dSopenharmony_ci // From case folding. 15122e5b6d6dSopenharmony_ci { true, 1, 2 }, 15132e5b6d6dSopenharmony_ci { true, 2, 2 }, 15142e5b6d6dSopenharmony_ci { false, 3, 3 }, 15152e5b6d6dSopenharmony_ci { true, 1, 1 }, 15162e5b6d6dSopenharmony_ci { false, 2, 2 } 15172e5b6d6dSopenharmony_ci }; 15182e5b6d6dSopenharmony_ci TestUtility::checkEditsIter(*this, u"foldCase(IßtanBul)", 15192e5b6d6dSopenharmony_ci edits.getFineIterator(), edits.getFineIterator(), 15202e5b6d6dSopenharmony_ci foldExpectedChanges, UPRV_LENGTHOF(foldExpectedChanges), 15212e5b6d6dSopenharmony_ci true, errorCode); 15222e5b6d6dSopenharmony_ci} 15232e5b6d6dSopenharmony_ci 15242e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapToString() { 15252e5b6d6dSopenharmony_ci // This test function name is parallel with one in UCharacterCaseTest.java. 15262e5b6d6dSopenharmony_ci // It is a bit of a misnomer until we have CaseMap API that writes to 15272e5b6d6dSopenharmony_ci // a UnicodeString, at which point we should change this code here. 15282e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCaseMapToString"); 15292e5b6d6dSopenharmony_ci UChar dest[20]; 15302e5b6d6dSopenharmony_ci 15312e5b6d6dSopenharmony_ci // Omit unchanged text. 15322e5b6d6dSopenharmony_ci int32_t length = CaseMap::toLower("tr", U_OMIT_UNCHANGED_TEXT, 15332e5b6d6dSopenharmony_ci u"IstanBul", 8, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15342e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", 15352e5b6d6dSopenharmony_ci UnicodeString(u"ıb"), UnicodeString(true, dest, length)); 15362e5b6d6dSopenharmony_ci length = CaseMap::toUpper("el", U_OMIT_UNCHANGED_TEXT, 15372e5b6d6dSopenharmony_ci u"Πατάτα", 6, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15382e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", 15392e5b6d6dSopenharmony_ci UnicodeString(u"ΑΤΑΤΑ"), UnicodeString(true, dest, length)); 15402e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 15412e5b6d6dSopenharmony_ci length = CaseMap::toTitle("nl", 15422e5b6d6dSopenharmony_ci U_OMIT_UNCHANGED_TEXT | 15432e5b6d6dSopenharmony_ci U_TITLECASE_NO_BREAK_ADJUSTMENT | 15442e5b6d6dSopenharmony_ci U_TITLECASE_NO_LOWERCASE, 15452e5b6d6dSopenharmony_ci nullptr, u"IjssEL IglOo", 12, 15462e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15472e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", 15482e5b6d6dSopenharmony_ci UnicodeString(u"J"), UnicodeString(true, dest, length)); 15492e5b6d6dSopenharmony_ci#endif 15502e5b6d6dSopenharmony_ci length = CaseMap::fold(U_OMIT_UNCHANGED_TEXT | U_FOLD_CASE_EXCLUDE_SPECIAL_I, 15512e5b6d6dSopenharmony_ci u"IßtanBul", 8, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15522e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", 15532e5b6d6dSopenharmony_ci UnicodeString(u"ıssb"), UnicodeString(true, dest, length)); 15542e5b6d6dSopenharmony_ci 15552e5b6d6dSopenharmony_ci // Return the whole result string. 15562e5b6d6dSopenharmony_ci length = CaseMap::toLower("tr", 0, 15572e5b6d6dSopenharmony_ci u"IstanBul", 8, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15582e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", 15592e5b6d6dSopenharmony_ci UnicodeString(u"ıstanbul"), UnicodeString(true, dest, length)); 15602e5b6d6dSopenharmony_ci length = CaseMap::toUpper("el", 0, 15612e5b6d6dSopenharmony_ci u"Πατάτα", 6, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15622e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", 15632e5b6d6dSopenharmony_ci UnicodeString(u"ΠΑΤΑΤΑ"), UnicodeString(true, dest, length)); 15642e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 15652e5b6d6dSopenharmony_ci length = CaseMap::toTitle("nl", 15662e5b6d6dSopenharmony_ci U_TITLECASE_NO_BREAK_ADJUSTMENT | 15672e5b6d6dSopenharmony_ci U_TITLECASE_NO_LOWERCASE, 15682e5b6d6dSopenharmony_ci nullptr, u"IjssEL IglOo", 12, 15692e5b6d6dSopenharmony_ci dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15702e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", 15712e5b6d6dSopenharmony_ci UnicodeString(u"IJssEL IglOo"), UnicodeString(true, dest, length)); 15722e5b6d6dSopenharmony_ci#endif 15732e5b6d6dSopenharmony_ci length = CaseMap::fold(U_FOLD_CASE_EXCLUDE_SPECIAL_I, 15742e5b6d6dSopenharmony_ci u"IßtanBul", 8, dest, UPRV_LENGTHOF(dest), nullptr, errorCode); 15752e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", 15762e5b6d6dSopenharmony_ci UnicodeString(u"ısstanbul"), UnicodeString(true, dest, length)); 15772e5b6d6dSopenharmony_ci} 15782e5b6d6dSopenharmony_ci 15792e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapUTF8ToString() { 15802e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestCaseMapUTF8ToString"); 15812e5b6d6dSopenharmony_ci std::string dest; 15822e5b6d6dSopenharmony_ci StringByteSink<std::string> sink(&dest); 15832e5b6d6dSopenharmony_ci 15842e5b6d6dSopenharmony_ci // Omit unchanged text. 15852e5b6d6dSopenharmony_ci CaseMap::utf8ToLower("tr", U_OMIT_UNCHANGED_TEXT, u8"IstanBul", sink, nullptr, errorCode); 15862e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", UnicodeString(u"ıb"), UnicodeString::fromUTF8(dest)); 15872e5b6d6dSopenharmony_ci dest.clear(); 15882e5b6d6dSopenharmony_ci CaseMap::utf8ToUpper("el", U_OMIT_UNCHANGED_TEXT, u8"Πατάτα", sink, nullptr, errorCode); 15892e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", UnicodeString(u"ΑΤΑΤΑ"), 15902e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 15912e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 15922e5b6d6dSopenharmony_ci dest.clear(); 15932e5b6d6dSopenharmony_ci CaseMap::utf8ToTitle( 15942e5b6d6dSopenharmony_ci "nl", U_OMIT_UNCHANGED_TEXT | U_TITLECASE_NO_BREAK_ADJUSTMENT | U_TITLECASE_NO_LOWERCASE, 15952e5b6d6dSopenharmony_ci nullptr, u8"IjssEL IglOo", sink, nullptr, errorCode); 15962e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", UnicodeString(u"J"), 15972e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 15982e5b6d6dSopenharmony_ci#endif 15992e5b6d6dSopenharmony_ci dest.clear(); 16002e5b6d6dSopenharmony_ci CaseMap::utf8Fold(U_OMIT_UNCHANGED_TEXT | U_FOLD_CASE_EXCLUDE_SPECIAL_I, 16012e5b6d6dSopenharmony_ci u8"IßtanBul", sink, nullptr, errorCode); 16022e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", UnicodeString(u"ıssb"), 16032e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 16042e5b6d6dSopenharmony_ci 16052e5b6d6dSopenharmony_ci // Return the whole result string. 16062e5b6d6dSopenharmony_ci dest.clear(); 16072e5b6d6dSopenharmony_ci CaseMap::utf8ToLower("tr", 0, u8"IstanBul", sink, nullptr, errorCode); 16082e5b6d6dSopenharmony_ci assertEquals(u"toLower(IstanBul)", UnicodeString(u"ıstanbul"), 16092e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 16102e5b6d6dSopenharmony_ci dest.clear(); 16112e5b6d6dSopenharmony_ci CaseMap::utf8ToUpper("el", 0, u8"Πατάτα", sink, nullptr, errorCode); 16122e5b6d6dSopenharmony_ci assertEquals(u"toUpper(Πατάτα)", UnicodeString(u"ΠΑΤΑΤΑ"), 16132e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 16142e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 16152e5b6d6dSopenharmony_ci dest.clear(); 16162e5b6d6dSopenharmony_ci CaseMap::utf8ToTitle("nl", U_TITLECASE_NO_BREAK_ADJUSTMENT | U_TITLECASE_NO_LOWERCASE, 16172e5b6d6dSopenharmony_ci nullptr, u8"IjssEL IglOo", sink, nullptr, errorCode); 16182e5b6d6dSopenharmony_ci assertEquals(u"toTitle(IjssEL IglOo)", UnicodeString(u"IJssEL IglOo"), 16192e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 16202e5b6d6dSopenharmony_ci#endif 16212e5b6d6dSopenharmony_ci dest.clear(); 16222e5b6d6dSopenharmony_ci CaseMap::utf8Fold(U_FOLD_CASE_EXCLUDE_SPECIAL_I, u8"IßtanBul", sink, nullptr, errorCode); 16232e5b6d6dSopenharmony_ci assertEquals(u"foldCase(IßtanBul)", UnicodeString(u"ısstanbul"), 16242e5b6d6dSopenharmony_ci UnicodeString::fromUTF8(dest)); 16252e5b6d6dSopenharmony_ci} 16262e5b6d6dSopenharmony_ci 16272e5b6d6dSopenharmony_civoid StringCaseTest::TestLongUnicodeString() { 16282e5b6d6dSopenharmony_ci // Code coverage for UnicodeString case mapping code handling 16292e5b6d6dSopenharmony_ci // long strings or many changes in a string. 16302e5b6d6dSopenharmony_ci UnicodeString s(true, 16312e5b6d6dSopenharmony_ci (const UChar *) 16322e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF" 16332e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF" 16342e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF" 16352e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF" 16362e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF" 16372e5b6d6dSopenharmony_ci u"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeF", 6 * 51); 16382e5b6d6dSopenharmony_ci UnicodeString expected(true, 16392e5b6d6dSopenharmony_ci (const UChar *) 16402e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF" 16412e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF" 16422e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF" 16432e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF" 16442e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF" 16452e5b6d6dSopenharmony_ci u"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEF", 6 * 51); 16462e5b6d6dSopenharmony_ci s.toUpper(Locale::getRoot()); 16472e5b6d6dSopenharmony_ci assertEquals("string length 306", expected, s); 16482e5b6d6dSopenharmony_ci} 16492e5b6d6dSopenharmony_ci 16502e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 16512e5b6d6dSopenharmony_civoid StringCaseTest::TestBug13127() { 16522e5b6d6dSopenharmony_ci // Test case crashed when the bug was present. 16532e5b6d6dSopenharmony_ci const char16_t *s16 = u"日本語"; 16542e5b6d6dSopenharmony_ci UnicodeString s(true, s16, -1); 16552e5b6d6dSopenharmony_ci s.toTitle(0, Locale::getEnglish()); 16562e5b6d6dSopenharmony_ci} 16572e5b6d6dSopenharmony_ci 16582e5b6d6dSopenharmony_civoid StringCaseTest::TestInPlaceTitle() { 16592e5b6d6dSopenharmony_ci // Similar to TestBug13127. u_strToTitle() can modify the buffer in-place. 16602e5b6d6dSopenharmony_ci IcuTestErrorCode errorCode(*this, "TestInPlaceTitle"); 16612e5b6d6dSopenharmony_ci char16_t s[32] = u"ß ß ß日本語 abcdef"; 16622e5b6d6dSopenharmony_ci const char16_t *expected = u"Ss Ss Ss日本語 Abcdef"; 16632e5b6d6dSopenharmony_ci int32_t length = u_strToTitle(s, UPRV_LENGTHOF(s), s, -1, nullptr, "", errorCode); 16642e5b6d6dSopenharmony_ci assertEquals("u_strToTitle(in-place) length", u_strlen(expected), length); 16652e5b6d6dSopenharmony_ci assertEquals("u_strToTitle(in-place)", expected, s); 16662e5b6d6dSopenharmony_ci} 16672e5b6d6dSopenharmony_ci#endif 16682e5b6d6dSopenharmony_ci 16692e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapEditsIteratorDocs() { 16702e5b6d6dSopenharmony_ci IcuTestErrorCode status(*this, "TestCaseMapEditsIteratorDocs"); 16712e5b6d6dSopenharmony_ci const char16_t* input = u"abcßDeF"; 16722e5b6d6dSopenharmony_ci int32_t inputLength = u_strlen(input); 16732e5b6d6dSopenharmony_ci // output: "abcssdef" 16742e5b6d6dSopenharmony_ci 16752e5b6d6dSopenharmony_ci char16_t output[10]; 16762e5b6d6dSopenharmony_ci Edits edits; 16772e5b6d6dSopenharmony_ci CaseMap::fold(0, input, -1, output, 10, &edits, status); 16782e5b6d6dSopenharmony_ci 16792e5b6d6dSopenharmony_ci static const char16_t* fineIteratorExpected[] = { 16802e5b6d6dSopenharmony_ci u"{ src[0..3] ≡ dest[0..3] (no-change) }", 16812e5b6d6dSopenharmony_ci u"{ src[3..4] ⇝ dest[3..5], repl[0..2] }", 16822e5b6d6dSopenharmony_ci u"{ src[4..5] ⇝ dest[5..6], repl[2..3] }", 16832e5b6d6dSopenharmony_ci u"{ src[5..6] ≡ dest[6..7] (no-change) }", 16842e5b6d6dSopenharmony_ci u"{ src[6..7] ⇝ dest[7..8], repl[3..4] }", 16852e5b6d6dSopenharmony_ci }; 16862e5b6d6dSopenharmony_ci static const char16_t* fineChangesIteratorExpected[] = { 16872e5b6d6dSopenharmony_ci u"{ src[3..4] ⇝ dest[3..5], repl[0..2] }", 16882e5b6d6dSopenharmony_ci u"{ src[4..5] ⇝ dest[5..6], repl[2..3] }", 16892e5b6d6dSopenharmony_ci u"{ src[6..7] ⇝ dest[7..8], repl[3..4] }", 16902e5b6d6dSopenharmony_ci }; 16912e5b6d6dSopenharmony_ci static const char16_t* coarseIteratorExpected[] = { 16922e5b6d6dSopenharmony_ci u"{ src[0..3] ≡ dest[0..3] (no-change) }", 16932e5b6d6dSopenharmony_ci u"{ src[3..5] ⇝ dest[3..6], repl[0..3] }", 16942e5b6d6dSopenharmony_ci u"{ src[5..6] ≡ dest[6..7] (no-change) }", 16952e5b6d6dSopenharmony_ci u"{ src[6..7] ⇝ dest[7..8], repl[3..4] }", 16962e5b6d6dSopenharmony_ci }; 16972e5b6d6dSopenharmony_ci static const char16_t* coarseChangesIteratorExpected[] = { 16982e5b6d6dSopenharmony_ci u"{ src[3..5] ⇝ dest[3..6], repl[0..3] }", 16992e5b6d6dSopenharmony_ci u"{ src[6..7] ⇝ dest[7..8], repl[3..4] }", 17002e5b6d6dSopenharmony_ci }; 17012e5b6d6dSopenharmony_ci 17022e5b6d6dSopenharmony_ci // Expected destination indices when source index is queried 17032e5b6d6dSopenharmony_ci static int32_t expectedDestFineEditIndices[] = {0, 0, 0, 3, 5, 6, 7}; 17042e5b6d6dSopenharmony_ci static int32_t expectedDestCoarseEditIndices[] = {0, 0, 0, 3, 3, 6, 7}; 17052e5b6d6dSopenharmony_ci static int32_t expectedDestFineStringIndices[] = {0, 1, 2, 3, 5, 6, 7}; 17062e5b6d6dSopenharmony_ci static int32_t expectedDestCoarseStringIndices[] = {0, 1, 2, 3, 6, 6, 7}; 17072e5b6d6dSopenharmony_ci 17082e5b6d6dSopenharmony_ci // Expected source indices when destination index is queried 17092e5b6d6dSopenharmony_ci static int32_t expectedSrcFineEditIndices[] = { 0, 0, 0, 3, 3, 4, 5, 6 }; 17102e5b6d6dSopenharmony_ci static int32_t expectedSrcCoarseEditIndices[] = { 0, 0, 0, 3, 3, 3, 5, 6 }; 17112e5b6d6dSopenharmony_ci static int32_t expectedSrcFineStringIndices[] = { 0, 1, 2, 3, 4, 4, 5, 6 }; 17122e5b6d6dSopenharmony_ci static int32_t expectedSrcCoarseStringIndices[] = { 0, 1, 2, 3, 5, 5, 5, 6 }; 17132e5b6d6dSopenharmony_ci 17142e5b6d6dSopenharmony_ci // Demonstrate the iterator next() method: 17152e5b6d6dSopenharmony_ci Edits::Iterator fineIterator = edits.getFineIterator(); 17162e5b6d6dSopenharmony_ci int i = 0; 17172e5b6d6dSopenharmony_ci UnicodeString toString; 17182e5b6d6dSopenharmony_ci while (fineIterator.next(status)) { 17192e5b6d6dSopenharmony_ci UnicodeString expected = fineIteratorExpected[i++]; 17202e5b6d6dSopenharmony_ci assertEquals(UnicodeString(u"Iteration #") + i, 17212e5b6d6dSopenharmony_ci expected, 17222e5b6d6dSopenharmony_ci fineIterator.toString(toString.remove())); 17232e5b6d6dSopenharmony_ci } 17242e5b6d6dSopenharmony_ci Edits::Iterator fineChangesIterator = edits.getFineChangesIterator(); 17252e5b6d6dSopenharmony_ci i = 0; 17262e5b6d6dSopenharmony_ci while (fineChangesIterator.next(status)) { 17272e5b6d6dSopenharmony_ci UnicodeString expected = fineChangesIteratorExpected[i++]; 17282e5b6d6dSopenharmony_ci assertEquals(UnicodeString(u"Iteration #") + i, 17292e5b6d6dSopenharmony_ci expected, 17302e5b6d6dSopenharmony_ci fineChangesIterator.toString(toString.remove())); 17312e5b6d6dSopenharmony_ci } 17322e5b6d6dSopenharmony_ci Edits::Iterator coarseIterator = edits.getCoarseIterator(); 17332e5b6d6dSopenharmony_ci i = 0; 17342e5b6d6dSopenharmony_ci while (coarseIterator.next(status)) { 17352e5b6d6dSopenharmony_ci UnicodeString expected = coarseIteratorExpected[i++]; 17362e5b6d6dSopenharmony_ci assertEquals(UnicodeString(u"Iteration #") + i, 17372e5b6d6dSopenharmony_ci expected, 17382e5b6d6dSopenharmony_ci coarseIterator.toString(toString.remove())); 17392e5b6d6dSopenharmony_ci } 17402e5b6d6dSopenharmony_ci Edits::Iterator coarseChangesIterator = edits.getCoarseChangesIterator(); 17412e5b6d6dSopenharmony_ci i = 0; 17422e5b6d6dSopenharmony_ci while (coarseChangesIterator.next(status)) { 17432e5b6d6dSopenharmony_ci UnicodeString expected = coarseChangesIteratorExpected[i++]; 17442e5b6d6dSopenharmony_ci assertEquals(UnicodeString(u"Iteration #") + i, 17452e5b6d6dSopenharmony_ci expected, 17462e5b6d6dSopenharmony_ci coarseChangesIterator.toString(toString.remove())); 17472e5b6d6dSopenharmony_ci } 17482e5b6d6dSopenharmony_ci 17492e5b6d6dSopenharmony_ci // Demonstrate the iterator indexing methods: 17502e5b6d6dSopenharmony_ci // fineIterator should have the same behavior as fineChangesIterator, and 17512e5b6d6dSopenharmony_ci // coarseIterator should have the same behavior as coarseChangesIterator. 17522e5b6d6dSopenharmony_ci for (int32_t srcIndex=0; srcIndex<inputLength; srcIndex++) { 17532e5b6d6dSopenharmony_ci fineIterator.findSourceIndex(srcIndex, status); 17542e5b6d6dSopenharmony_ci fineChangesIterator.findSourceIndex(srcIndex, status); 17552e5b6d6dSopenharmony_ci coarseIterator.findSourceIndex(srcIndex, status); 17562e5b6d6dSopenharmony_ci coarseChangesIterator.findSourceIndex(srcIndex, status); 17572e5b6d6dSopenharmony_ci 17582e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17592e5b6d6dSopenharmony_ci expectedDestFineEditIndices[srcIndex], 17602e5b6d6dSopenharmony_ci fineIterator.destinationIndex()); 17612e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17622e5b6d6dSopenharmony_ci expectedDestFineEditIndices[srcIndex], 17632e5b6d6dSopenharmony_ci fineChangesIterator.destinationIndex()); 17642e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17652e5b6d6dSopenharmony_ci expectedDestCoarseEditIndices[srcIndex], 17662e5b6d6dSopenharmony_ci coarseIterator.destinationIndex()); 17672e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17682e5b6d6dSopenharmony_ci expectedDestCoarseEditIndices[srcIndex], 17692e5b6d6dSopenharmony_ci coarseChangesIterator.destinationIndex()); 17702e5b6d6dSopenharmony_ci 17712e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17722e5b6d6dSopenharmony_ci expectedDestFineStringIndices[srcIndex], 17732e5b6d6dSopenharmony_ci fineIterator.destinationIndexFromSourceIndex(srcIndex, status)); 17742e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17752e5b6d6dSopenharmony_ci expectedDestFineStringIndices[srcIndex], 17762e5b6d6dSopenharmony_ci fineChangesIterator.destinationIndexFromSourceIndex(srcIndex, status)); 17772e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17782e5b6d6dSopenharmony_ci expectedDestCoarseStringIndices[srcIndex], 17792e5b6d6dSopenharmony_ci coarseIterator.destinationIndexFromSourceIndex(srcIndex, status)); 17802e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Source index: ") + srcIndex, 17812e5b6d6dSopenharmony_ci expectedDestCoarseStringIndices[srcIndex], 17822e5b6d6dSopenharmony_ci coarseChangesIterator.destinationIndexFromSourceIndex(srcIndex, status)); 17832e5b6d6dSopenharmony_ci } 17842e5b6d6dSopenharmony_ci for (int32_t destIndex=0; destIndex<inputLength; destIndex++) { 17852e5b6d6dSopenharmony_ci fineIterator.findDestinationIndex(destIndex, status); 17862e5b6d6dSopenharmony_ci fineChangesIterator.findDestinationIndex(destIndex, status); 17872e5b6d6dSopenharmony_ci coarseIterator.findDestinationIndex(destIndex, status); 17882e5b6d6dSopenharmony_ci coarseChangesIterator.findDestinationIndex(destIndex, status); 17892e5b6d6dSopenharmony_ci 17902e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 17912e5b6d6dSopenharmony_ci expectedSrcFineEditIndices[destIndex], 17922e5b6d6dSopenharmony_ci fineIterator.sourceIndex()); 17932e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 17942e5b6d6dSopenharmony_ci expectedSrcFineEditIndices[destIndex], 17952e5b6d6dSopenharmony_ci fineChangesIterator.sourceIndex()); 17962e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 17972e5b6d6dSopenharmony_ci expectedSrcCoarseEditIndices[destIndex], 17982e5b6d6dSopenharmony_ci coarseIterator.sourceIndex()); 17992e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 18002e5b6d6dSopenharmony_ci expectedSrcCoarseEditIndices[destIndex], 18012e5b6d6dSopenharmony_ci coarseChangesIterator.sourceIndex()); 18022e5b6d6dSopenharmony_ci 18032e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 18042e5b6d6dSopenharmony_ci expectedSrcFineStringIndices[destIndex], 18052e5b6d6dSopenharmony_ci fineIterator.sourceIndexFromDestinationIndex(destIndex, status)); 18062e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 18072e5b6d6dSopenharmony_ci expectedSrcFineStringIndices[destIndex], 18082e5b6d6dSopenharmony_ci fineChangesIterator.sourceIndexFromDestinationIndex(destIndex, status)); 18092e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 18102e5b6d6dSopenharmony_ci expectedSrcCoarseStringIndices[destIndex], 18112e5b6d6dSopenharmony_ci coarseIterator.sourceIndexFromDestinationIndex(destIndex, status)); 18122e5b6d6dSopenharmony_ci assertEquals(UnicodeString("Destination index: ") + destIndex, 18132e5b6d6dSopenharmony_ci expectedSrcCoarseStringIndices[destIndex], 18142e5b6d6dSopenharmony_ci coarseChangesIterator.sourceIndexFromDestinationIndex(destIndex, status)); 18152e5b6d6dSopenharmony_ci } 18162e5b6d6dSopenharmony_ci} 18172e5b6d6dSopenharmony_ci 18182e5b6d6dSopenharmony_civoid StringCaseTest::TestCaseMapGreekExtended() { 18192e5b6d6dSopenharmony_ci // Ticket 13851 18202e5b6d6dSopenharmony_ci UnicodeString s(u"\u1F80\u1F88\u1FFC"); 18212e5b6d6dSopenharmony_ci UnicodeString result(s); 18222e5b6d6dSopenharmony_ci result.toLower(Locale::getRoot()); 18232e5b6d6dSopenharmony_ci assertEquals(u"lower", u"\u1F80\u1F80\u1FF3", result); 18242e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION 18252e5b6d6dSopenharmony_ci result = s; 18262e5b6d6dSopenharmony_ci result.toTitle(nullptr, Locale::getRoot()); 18272e5b6d6dSopenharmony_ci assertEquals(u"title", u"\u1F88\u1F80\u1FF3", result); 18282e5b6d6dSopenharmony_ci#endif 18292e5b6d6dSopenharmony_ci} 18302e5b6d6dSopenharmony_ci 18312e5b6d6dSopenharmony_ci//#endif 1832