X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..151279e3792e85d0417b499c229886b3af724f55:/icuSources/test/intltest/strcase.cpp diff --git a/icuSources/test/intltest/strcase.cpp b/icuSources/test/intltest/strcase.cpp index b10fa17f..75fc7404 100644 --- a/icuSources/test/intltest/strcase.cpp +++ b/icuSources/test/intltest/strcase.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2002-2005, International Business Machines +* Copyright (C) 2002-2012, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -23,25 +23,26 @@ #include "unicode/ubrk.h" #include "unicode/unistr.h" #include "unicode/ucasemap.h" +#include "ucase.h" #include "ustrtest.h" #include "unicode/tstdtmod.h" +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + StringCaseTest::~StringCaseTest() {} void StringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) { - if (exec) logln("TestSuite StringCaseTest: "); - switch (index) { - case 0: name = "TestCaseConversion"; if (exec) TestCaseConversion(); break; - case 1: - name = "TestCasing"; -#if !UCONFIG_NO_BREAK_ITERATION - if(exec) TestCasing(); -#endif - break; - - default: name = ""; break; //needed to end loop + if(exec) { + logln("TestSuite StringCaseTest: "); } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(TestCaseConversion); +#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION + TESTCASE_AUTO(TestCasing); +#endif + TESTCASE_AUTO(TestFullCaseFoldingIterator); + TESTCASE_AUTO_END; } void @@ -325,9 +326,8 @@ StringCaseTest::TestCaseConversion() enum { TEST_LOWER, TEST_UPPER, -#if !UCONFIG_NO_BREAK_ITERATION TEST_TITLE, -#endif + TEST_FOLD, TEST_COUNT }; @@ -335,9 +335,8 @@ enum { static const char *const dataNames[TEST_COUNT+1]={ "lowercasing", "uppercasing", -#if !UCONFIG_NO_BREAK_ITERATION "titlecasing", -#endif + "casefolding", "" }; @@ -345,53 +344,92 @@ void StringCaseTest::TestCasingImpl(const UnicodeString &input, const UnicodeString &output, int32_t whichCase, - const char *localeID, uint32_t options) { + void *iter, const char *localeID, uint32_t options) { // UnicodeString UnicodeString result; const char *name; + Locale locale(localeID); result=input; switch(whichCase) { case TEST_LOWER: name="toLower"; - result.toLower(Locale(localeID)); + result.toLower(locale); break; case TEST_UPPER: name="toUpper"; - result.toUpper(Locale(localeID)); + result.toUpper(locale); + break; +#if !UCONFIG_NO_BREAK_ITERATION + case TEST_TITLE: + name="toTitle"; + result.toTitle((BreakIterator *)iter, locale, options); + break; +#endif + case TEST_FOLD: + name="foldCase"; + result.foldCase(options); break; default: name=""; break; // won't happen } if(result!=output) { - errln("error: UnicodeString.%s() got a wrong result for a test case from casing.res", name); + dataerrln("error: UnicodeString.%s() got a wrong result for a test case from casing.res", name); + } +#if !UCONFIG_NO_BREAK_ITERATION + if(whichCase==TEST_TITLE && options==0) { + result=input; + result.toTitle((BreakIterator *)iter, locale); + if(result!=output) { + dataerrln("error: UnicodeString.toTitle(options=0) got a wrong result for a test case from casing.res"); + } } +#endif // UTF-8 char utf8In[100], utf8Out[100]; int32_t utf8InLength, utf8OutLength, resultLength; UChar *buffer; - UCaseMap *csm; - UErrorCode errorCode; - - errorCode=U_ZERO_ERROR; - csm=ucasemap_open(localeID, options, &errorCode); + IcuTestErrorCode errorCode(*this, "TestCasingImpl"); + LocalUCaseMapPointer csm(ucasemap_open(localeID, options, errorCode)); +#if !UCONFIG_NO_BREAK_ITERATION + if(iter!=NULL) { + // Clone the break iterator so that the UCaseMap can safely adopt it. + int32_t size=1; // Not 0 because that only gives preflighting. + UBreakIterator *clone=ubrk_safeClone((UBreakIterator *)iter, NULL, &size, errorCode); + ucasemap_setBreakIterator(csm.getAlias(), clone, errorCode); + } +#endif - u_strToUTF8(utf8In, (int32_t)sizeof(utf8In), &utf8InLength, input.getBuffer(), input.length(), &errorCode); + u_strToUTF8(utf8In, (int32_t)sizeof(utf8In), &utf8InLength, input.getBuffer(), input.length(), errorCode); switch(whichCase) { case TEST_LOWER: name="ucasemap_utf8ToLower"; - utf8OutLength=ucasemap_utf8ToLower(csm, + utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), utf8Out, (int32_t)sizeof(utf8Out), - utf8In, utf8InLength, &errorCode); + utf8In, utf8InLength, errorCode); break; case TEST_UPPER: name="ucasemap_utf8ToUpper"; - utf8OutLength=ucasemap_utf8ToUpper(csm, + utf8OutLength=ucasemap_utf8ToUpper(csm.getAlias(), + utf8Out, (int32_t)sizeof(utf8Out), + utf8In, utf8InLength, errorCode); + break; +#if !UCONFIG_NO_BREAK_ITERATION + case TEST_TITLE: + name="ucasemap_utf8ToTitle"; + utf8OutLength=ucasemap_utf8ToTitle(csm.getAlias(), utf8Out, (int32_t)sizeof(utf8Out), - utf8In, utf8InLength, &errorCode); + utf8In, utf8InLength, errorCode); + break; +#endif + case TEST_FOLD: + name="ucasemap_utf8FoldCase"; + utf8OutLength=ucasemap_utf8FoldCase(csm.getAlias(), + utf8Out, (int32_t)sizeof(utf8Out), + utf8In, utf8InLength, errorCode); break; default: name=""; @@ -399,99 +437,95 @@ StringCaseTest::TestCasingImpl(const UnicodeString &input, break; // won't happen } buffer=result.getBuffer(utf8OutLength); - u_strFromUTF8(buffer, result.getCapacity(), &resultLength, utf8Out, utf8OutLength, &errorCode); - result.releaseBuffer(U_SUCCESS(errorCode) ? resultLength : 0); + u_strFromUTF8(buffer, result.getCapacity(), &resultLength, utf8Out, utf8OutLength, errorCode); + result.releaseBuffer(errorCode.isSuccess() ? resultLength : 0); - if(U_FAILURE(errorCode)) { - errln("error: %s() got an error for a test case from casing.res - %s", name, u_errorName(errorCode)); + if(errorCode.isFailure()) { + errcheckln(errorCode, "error: %s() got an error for a test case from casing.res - %s", name, u_errorName(errorCode)); + errorCode.reset(); } else if(result!=output) { errln("error: %s() got a wrong result for a test case from casing.res", name); - } - ucasemap_close(csm); -} - -#if !UCONFIG_NO_BREAK_ITERATION - -void -StringCaseTest::TestTitleCasing(const UnicodeString &input, - const UnicodeString &output, - const char *localeID, - UBreakIterator *iter) { - UnicodeString result; - - result=input; - result.toTitle((BreakIterator *)iter, Locale(localeID)); - if(result!=output) { - errln("error: UnicodeString.toTitle() got a wrong result for a test case from casing.res"); + errln("expected \"" + output + "\" got \"" + result + "\"" ); } } -#endif - void StringCaseTest::TestCasing() { UErrorCode status = U_ZERO_ERROR; #if !UCONFIG_NO_BREAK_ITERATION - UBreakIterator *iter; + LocalUBreakIteratorPointer iter; #endif char cLocaleID[100]; - UnicodeString locale, input, output, result; + UnicodeString locale, input, output, optionsString, result; + uint32_t options; int32_t whichCase, type; - TestDataModule *driver = TestDataModule::getTestDataModule("casing", *this, status); + LocalPointer driver(TestDataModule::getTestDataModule("casing", *this, status)); if(U_SUCCESS(status)) { for(whichCase=0; whichCasecreateTestData(dataNames[whichCase], status); +#if UCONFIG_NO_BREAK_ITERATION + if(whichCase==TEST_TITLE) { + continue; + } +#endif + LocalPointer casingTest(driver->createTestData(dataNames[whichCase], status)); if(U_FAILURE(status)) { errln("TestCasing failed to createTestData(%s) - %s", dataNames[whichCase], u_errorName(status)); break; } const DataMap *myCase = NULL; while(casingTest->nextCase(myCase, status)) { - locale = myCase->getString("Locale", status); - locale.extract(0, 0x7fffffff, cLocaleID, sizeof(cLocaleID), ""); - input = myCase->getString("Input", status); output = myCase->getString("Output", status); + if(whichCase!=TEST_FOLD) { + locale = myCase->getString("Locale", status); + } + locale.extract(0, 0x7fffffff, cLocaleID, sizeof(cLocaleID), ""); + #if !UCONFIG_NO_BREAK_ITERATION - iter=NULL; if(whichCase==TEST_TITLE) { type = myCase->getInt("Type", status); if(type>=0) { - iter=ubrk_open((UBreakIteratorType)type, cLocaleID, NULL, 0, &status); + iter.adoptInstead(ubrk_open((UBreakIteratorType)type, cLocaleID, NULL, 0, &status)); + } else if(type==-2) { + // Open a trivial break iterator that only delivers { 0, length } + // or even just { 0 } as boundaries. + static const UChar rules[] = { 0x2e, 0x2a, 0x3b }; // ".*;" + UParseError parseError; + iter.adoptInstead(ubrk_openRules(rules, LENGTHOF(rules), NULL, 0, &parseError, &status)); } } #endif + options = 0; + if(whichCase==TEST_TITLE || whichCase==TEST_FOLD) { + optionsString = myCase->getString("Options", status); + if(optionsString.indexOf((UChar)0x54)>=0) { // T + options|=U_FOLD_CASE_EXCLUDE_SPECIAL_I; + } + if(optionsString.indexOf((UChar)0x4c)>=0) { // L + options|=U_TITLECASE_NO_LOWERCASE; + } + if(optionsString.indexOf((UChar)0x41)>=0) { // A + options|=U_TITLECASE_NO_BREAK_ADJUSTMENT; + } + } if(U_FAILURE(status)) { - errln("error: TestCasing() setup failed for %s test case from casing.res: %s", dataNames[whichCase], u_errorName(status)); + dataerrln("error: TestCasing() setup failed for %s test case from casing.res: %s", dataNames[whichCase], u_errorName(status)); status = U_ZERO_ERROR; } else { - switch(whichCase) { - case TEST_LOWER: - case TEST_UPPER: - TestCasingImpl(input, output, whichCase, cLocaleID, 0); - break; -#if !UCONFIG_NO_BREAK_ITERATION - case TEST_TITLE: - TestTitleCasing(input, output, cLocaleID, iter); - break; +#if UCONFIG_NO_BREAK_ITERATION + LocalPointer iter; #endif - default: - break; // won't happen - } + TestCasingImpl(input, output, whichCase, iter.getAlias(), cLocaleID, options); } #if !UCONFIG_NO_BREAK_ITERATION - if(iter!=NULL) { - ubrk_close(iter); - } + iter.adoptInstead(NULL); #endif } - delete casingTest; } } - delete driver; #if !UCONFIG_NO_BREAK_ITERATION // more tests for API coverage @@ -499,7 +533,43 @@ StringCaseTest::TestCasing() { input=UNICODE_STRING_SIMPLE("sTrA\\u00dfE").unescape(); (result=input).toTitle(NULL); if(result!=UNICODE_STRING_SIMPLE("Stra\\u00dfe").unescape()) { - errln("UnicodeString::toTitle(NULL) failed"); + dataerrln("UnicodeString::toTitle(NULL) failed."); } #endif } + +void +StringCaseTest::TestFullCaseFoldingIterator() { + UnicodeString ffi=UNICODE_STRING_SIMPLE("ffi"); + UnicodeString ss=UNICODE_STRING_SIMPLE("ss"); + FullCaseFoldingIterator iter; + int32_t count=0; + int32_t countSpecific=0; + UChar32 c; + UnicodeString full; + while((c=iter.next(full))>=0) { + ++count; + // Check that the full Case_Folding has more than 1 code point. + if(!full.hasMoreChar32Than(0, 0x7fffffff, 1)) { + errln("error: FullCaseFoldingIterator.next()=U+%04lX full Case_Folding has at most 1 code point", (long)c); + continue; + } + // Check that full == Case_Folding(c). + UnicodeString cf(c); + cf.foldCase(); + if(full!=cf) { + errln("error: FullCaseFoldingIterator.next()=U+%04lX full Case_Folding != cf(c)", (long)c); + continue; + } + // Spot-check a couple of specific cases. + if((full==ffi && c==0xfb03) || (full==ss && (c==0xdf || c==0x1e9e))) { + ++countSpecific; + } + } + if(countSpecific!=3) { + errln("error: FullCaseFoldingIterator did not yield exactly the expected specific cases"); + } + if(count<70) { + errln("error: FullCaseFoldingIterator yielded only %d (cp, full) pairs", (int)count); + } +}