X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/4388f060552cc537e71e957d32f35e9d75a61233..1a147d096ae81f4c8262f7bfc56bd19fc2dee932:/icuSources/test/intltest/ustrtest.cpp?ds=sidebyside diff --git a/icuSources/test/intltest/ustrtest.cpp b/icuSources/test/intltest/ustrtest.cpp index 13251a35..c31a4650 100644 --- a/icuSources/test/intltest/ustrtest.cpp +++ b/icuSources/test/intltest/ustrtest.cpp @@ -1,9 +1,13 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2011, International Business Machines Corporation and + * Copyright (c) 1997-2016, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ +#include + #include "ustrtest.h" #include "unicode/appendable.h" #include "unicode/std_string.h" @@ -11,6 +15,7 @@ #include "unicode/uchar.h" #include "unicode/ustring.h" #include "unicode/locid.h" +#include "unicode/strenum.h" #include "unicode/ucnv.h" #include "unicode/uenum.h" #include "unicode/utf16.h" @@ -25,48 +30,44 @@ using namespace std; #endif -#define LENGTHOF(array) (int32_t)((sizeof(array)/sizeof((array)[0]))) - UnicodeStringTest::~UnicodeStringTest() {} +extern IntlTest *createStringCaseTest(); + void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char *par) { if (exec) logln("TestSuite UnicodeStringTest: "); - switch (index) { - case 0: - name = "StringCaseTest"; - if (exec) { - logln("StringCaseTest---"); logln(""); - StringCaseTest test; - callTest(test, par); - } - break; - case 1: name = "TestBasicManipulation"; if (exec) TestBasicManipulation(); break; - case 2: name = "TestCompare"; if (exec) TestCompare(); break; - case 3: name = "TestExtract"; if (exec) TestExtract(); break; - case 4: name = "TestRemoveReplace"; if (exec) TestRemoveReplace(); break; - case 5: name = "TestSearching"; if (exec) TestSearching(); break; - case 6: name = "TestSpacePadding"; if (exec) TestSpacePadding(); break; - case 7: name = "TestPrefixAndSuffix"; if (exec) TestPrefixAndSuffix(); break; - case 8: name = "TestFindAndReplace"; if (exec) TestFindAndReplace(); break; - case 9: name = "TestBogus"; if (exec) TestBogus(); break; - case 10: name = "TestReverse"; if (exec) TestReverse(); break; - case 11: name = "TestMiscellaneous"; if (exec) TestMiscellaneous(); break; - case 12: name = "TestStackAllocation"; if (exec) TestStackAllocation(); break; - case 13: name = "TestUnescape"; if (exec) TestUnescape(); break; - case 14: name = "TestCountChar32"; if (exec) TestCountChar32(); break; - case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break; - case 16: name = "TestNameSpace"; if (exec) TestNameSpace(); break; - case 17: name = "TestUTF32"; if (exec) TestUTF32(); break; - case 18: name = "TestUTF8"; if (exec) TestUTF8(); break; - case 19: name = "TestReadOnlyAlias"; if (exec) TestReadOnlyAlias(); break; - case 20: name = "TestAppendable"; if (exec) TestAppendable(); break; - case 21: name = "TestUnicodeStringImplementsAppendable"; if (exec) TestUnicodeStringImplementsAppendable(); break; - case 22: name = "TestSizeofUnicodeString"; if (exec) TestSizeofUnicodeString(); break; - case 23: name = "TestStartsWithAndEndsWithNulTerminated"; if (exec) TestStartsWithAndEndsWithNulTerminated(); break; - - default: name = ""; break; //needed to end loop - } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO_CREATE_CLASS(StringCaseTest); + TESTCASE_AUTO(TestBasicManipulation); + TESTCASE_AUTO(TestCompare); + TESTCASE_AUTO(TestExtract); + TESTCASE_AUTO(TestRemoveReplace); + TESTCASE_AUTO(TestSearching); + TESTCASE_AUTO(TestSpacePadding); + TESTCASE_AUTO(TestPrefixAndSuffix); + TESTCASE_AUTO(TestFindAndReplace); + TESTCASE_AUTO(TestBogus); + TESTCASE_AUTO(TestReverse); + TESTCASE_AUTO(TestMiscellaneous); + TESTCASE_AUTO(TestStackAllocation); + TESTCASE_AUTO(TestUnescape); + TESTCASE_AUTO(TestCountChar32); + TESTCASE_AUTO(TestStringEnumeration); + TESTCASE_AUTO(TestNameSpace); + TESTCASE_AUTO(TestUTF32); + TESTCASE_AUTO(TestUTF8); + TESTCASE_AUTO(TestReadOnlyAlias); + TESTCASE_AUTO(TestAppendable); + TESTCASE_AUTO(TestUnicodeStringImplementsAppendable); + TESTCASE_AUTO(TestSizeofUnicodeString); + TESTCASE_AUTO(TestStartsWithAndEndsWithNulTerminated); + TESTCASE_AUTO(TestMoveSwap); + TESTCASE_AUTO(TestUInt16Pointers); + TESTCASE_AUTO(TestWCharPointers); + TESTCASE_AUTO(TestNullPointers); + TESTCASE_AUTO(TestUnicodeStringInsertAppendToSelf); + TESTCASE_AUTO_END; } void @@ -113,9 +114,9 @@ UnicodeStringTest::TestBasicManipulation() errln("operator+=() failed: expected \"" + expectedValue + "\"\n,got \"" + test2 + "\""); if (test1.length() != 70) - errln("length() failed: expected 70, got " + test1.length()); + errln(UnicodeString("length() failed: expected 70, got ") + test1.length()); if (test2.length() != 30) - errln("length() failed: expected 30, got " + test2.length()); + errln(UnicodeString("length() failed: expected 30, got ") + test2.length()); UnicodeString test3; test3.append((UChar32)0x20402); @@ -123,7 +124,7 @@ UnicodeStringTest::TestBasicManipulation() errln((UnicodeString)"append failed for UChar32, expected \"\\\\ud841\\\\udc02\", got " + prettify(test3)); } if(test3.length() != 2){ - errln("append or length failed for UChar32, expected 2, got " + test3.length()); + errln(UnicodeString("append or length failed for UChar32, expected 2, got ") + test3.length()); } test3.append((UChar32)0x0074); if(test3 != CharsToUnicodeString("\\uD841\\uDC02t")){ @@ -199,9 +200,9 @@ UnicodeStringTest::TestBasicManipulation() } UChar buffer[10]={ 0x61, 0x62, 0x20ac, 0xd900, 0xdc05, 0, 0x62, 0xffff, 0xdbff, 0xdfff }; - UnicodeString s, t(buffer, -1, LENGTHOF(buffer)); + UnicodeString s, t(buffer, -1, UPRV_LENGTHOF(buffer)); - if(s.setTo(buffer, -1, LENGTHOF(buffer)).length()!=u_strlen(buffer)) { + if(s.setTo(buffer, -1, UPRV_LENGTHOF(buffer)).length()!=u_strlen(buffer)) { errln("UnicodeString.setTo(buffer, length, capacity) does not work with length==-1"); } if(t.length()!=u_strlen(buffer)) { @@ -216,11 +217,11 @@ UnicodeStringTest::TestBasicManipulation() } buffer[u_strlen(buffer)]=0xe4; - UnicodeString u(buffer, -1, LENGTHOF(buffer)); - if(s.setTo(buffer, -1, LENGTHOF(buffer)).length()!=LENGTHOF(buffer)) { + UnicodeString u(buffer, -1, UPRV_LENGTHOF(buffer)); + if(s.setTo(buffer, -1, UPRV_LENGTHOF(buffer)).length()!=UPRV_LENGTHOF(buffer)) { errln("UnicodeString.setTo(buffer without NUL, length, capacity) does not work with length==-1"); } - if(u.length()!=LENGTHOF(buffer)) { + if(u.length()!=UPRV_LENGTHOF(buffer)) { errln("UnicodeString(buffer without NUL, length, capacity) does not work with length==-1"); } @@ -243,7 +244,7 @@ UnicodeStringTest::TestBasicManipulation() static const UChar utf16[]={ 0x61, 0xE4, 0xDF, 0x4E00 }; UnicodeString from8a = UnicodeString((const char *)utf8); UnicodeString from8b = UnicodeString((const char *)utf8, (int32_t)sizeof(utf8)-1); - UnicodeString from16(FALSE, utf16, LENGTHOF(utf16)); + UnicodeString from16(FALSE, utf16, UPRV_LENGTHOF(utf16)); if(from8a != from16 || from8b != from16) { errln("UnicodeString(const char * U_CHARSET_IS_UTF8) failed"); } @@ -365,11 +366,11 @@ UnicodeStringTest::TestCompare() UnicodeString u[20]; // must be at least as long as strings[] int32_t i; - for(i=0; i<(int32_t)(sizeof(strings)/sizeof(strings[0])); ++i) { + for(i=0; i=0 || u[i].compareCodePointOrder(0, INT32_MAX, u[i+1].getBuffer())>=0) { errln("error: UnicodeString::compareCodePointOrder() fails for string %d and the following one\n", i); } @@ -721,14 +722,15 @@ UnicodeStringTest::TestSearching() (startPos = test1.indexOf(test2, startPos)) != -1 ? (++occurrences, startPos += 4) : 0) ; if (occurrences != 6) - errln("indexOf failed: expected to find 6 occurrences, found " + occurrences); - + errln(UnicodeString("indexOf failed: expected to find 6 occurrences, found ") + occurrences); + for ( occurrences = 0, startPos = 10; startPos != -1 && startPos < test1.length(); (startPos = test1.indexOf(test2, startPos)) != -1 ? (++occurrences, startPos += 4) : 0) ; if (occurrences != 4) - errln("indexOf with starting offset failed: expected to find 4 occurrences, found " + occurrences); + errln(UnicodeString("indexOf with starting offset failed: " + "expected to find 4 occurrences, found ") + occurrences); int32_t endPos = 28; for ( occurrences = 0, startPos = 5; @@ -736,7 +738,8 @@ UnicodeStringTest::TestSearching() (startPos = test1.indexOf(test2, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 4) : 0) ; if (occurrences != 4) - errln("indexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences); + errln(UnicodeString("indexOf with starting and ending offsets failed: " + "expected to find 4 occurrences, found ") + occurrences); //using UChar32 string for ( startPos=0, occurrences=0; @@ -751,7 +754,7 @@ UnicodeStringTest::TestSearching() (startPos = test3.indexOf(test4, startPos)) != -1 ? (++occurrences, startPos += 2) : 0) ; if (occurrences != 2) - errln("indexOf failed: expected to find 2 occurrences, found " + occurrences); + errln(UnicodeString("indexOf failed: expected to find 2 occurrences, found ") + occurrences); //--- for ( occurrences = 0, startPos = 0; @@ -759,21 +762,24 @@ UnicodeStringTest::TestSearching() (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0) ; if (occurrences != 16) - errln("indexOf with character failed: expected to find 16 occurrences, found " + occurrences); + errln(UnicodeString("indexOf with character failed: " + "expected to find 16 occurrences, found ") + occurrences); for ( occurrences = 0, startPos = 10; startPos != -1 && startPos < test1.length(); (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0) ; if (occurrences != 12) - errln("indexOf with character & start offset failed: expected to find 12 occurrences, found " + occurrences); + errln(UnicodeString("indexOf with character & start offset failed: " + "expected to find 12 occurrences, found ") + occurrences); for ( occurrences = 0, startPos = 5, endPos = 28; startPos != -1 && startPos < test1.length(); (startPos = test1.indexOf(testChar, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 1) : 0) ; if (occurrences != 10) - errln("indexOf with character & start & end offsets failed: expected to find 10 occurrences, found " + occurrences); + errln(UnicodeString("indexOf with character & start & end offsets failed: " + "expected to find 10 occurrences, found ") + occurrences); //testing for UChar32 UnicodeString subString; @@ -816,14 +822,16 @@ UnicodeStringTest::TestSearching() (startPos = test1.lastIndexOf(test2, 5, startPos - 5)) != -1 ? ++occurrences : 0) ; if (occurrences != 4) - errln("lastIndexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences); + errln(UnicodeString("lastIndexOf with starting and ending offsets failed: " + "expected to find 4 occurrences, found ") + occurrences); for ( occurrences = 0, startPos = 32; startPos != -1; (startPos = test1.lastIndexOf(testChar, 5, startPos - 5)) != -1 ? ++occurrences : 0) ; if (occurrences != 11) - errln("lastIndexOf with character & start & end offsets failed: expected to find 11 occurrences, found " + occurrences); + errln(UnicodeString("lastIndexOf with character & start & end offsets failed: " + "expected to find 11 occurrences, found ") + occurrences); //testing UChar32 startPos=test3.length(); @@ -1118,27 +1126,25 @@ UnicodeStringTest::TestMiscellaneous() errln("UnicodeString(u[-1]).getTerminatedBuffer() returns a bad buffer"); } - test1=UNICODE_STRING("la", 2); - test1.append(UNICODE_STRING(" lila", 5).getTerminatedBuffer(), 0, -1); - if(test1!=UNICODE_STRING("la lila", 7)) { - errln("UnicodeString::append(const UChar *, start, length) failed"); - } + // NOTE: Some compilers will optimize u"la" to point to the same static memory + // as u" lila", offset by 3 code units + test1=UnicodeString(TRUE, u"la", 2); + test1.append(UnicodeString(TRUE, u" lila", 5).getTerminatedBuffer(), 0, -1); + assertEquals("UnicodeString::append(const UChar *, start, length) failed", + u"la lila", test1); - test1.insert(3, UNICODE_STRING("dudum ", 6), 0, INT32_MAX); - if(test1!=UNICODE_STRING("la dudum lila", 13)) { - errln("UnicodeString::insert(start, const UniStr &, start, length) failed"); - } + test1.insert(3, UnicodeString(TRUE, u"dudum ", 6), 0, INT32_MAX); + assertEquals("UnicodeString::insert(start, const UniStr &, start, length) failed", + u"la dudum lila", test1); static const UChar ucs[]={ 0x68, 0x6d, 0x20, 0 }; test1.insert(9, ucs, -1); - if(test1!=UNICODE_STRING("la dudum hm lila", 16)) { - errln("UnicodeString::insert(start, const UChar *, length) failed"); - } + assertEquals("UnicodeString::insert(start, const UChar *, length) failed", + u"la dudum hm lila", test1); test1.replace(9, 2, (UChar)0x2b); - if(test1!=UNICODE_STRING("la dudum + lila", 15)) { - errln("UnicodeString::replace(start, length, UChar) failed"); - } + assertEquals("UnicodeString::replace(start, length, UChar) failed", + u"la dudum + lila", test1); if(test1.hasMetaData() || UnicodeString().hasMetaData()) { errln("UnicodeString::hasMetaData() returns TRUE"); @@ -1167,6 +1173,14 @@ UnicodeStringTest::TestMiscellaneous() errln("UnicodeString(shared buffer).remove().getTerminatedBuffer() " "modified another copy of the string!"); } + + // ticket #9740 + test1.setTo(TRUE, ucs, 3); + assertEquals("length of read-only alias", 3, test1.length()); + test1.trim(); + assertEquals("length of read-only alias after trim()", 2, test1.length()); + assertEquals("length of terminated buffer of read-only alias + trim()", + 2, u_strlen(test1.getTerminatedBuffer())); } void @@ -1395,7 +1409,7 @@ UnicodeStringTest::TestCountChar32(void) { 0xd804, 0xdc04, 0xd805, 0xdc05, 0x67 }; - UnicodeString string(str, LENGTHOF(str)); + UnicodeString string(str, UPRV_LENGTHOF(str)); int32_t start, length, number; /* test hasMoreChar32Than() */ @@ -1544,7 +1558,10 @@ UnicodeStringTest::TestBogus() { // writable alias to another string's buffer: very bad idea, just convenient for this test test3.setToBogus(); - if(!test3.isBogus() || test3.setTo((UChar *)test1.getBuffer(), test1.length(), test1.getCapacity()).isBogus() || test3!=test1) { + if(!test3.isBogus() || + test3.setTo(const_cast(test1.getBuffer()), + test1.length(), test1.getCapacity()).isBogus() || + test3!=test1) { errln("bogus.setTo(writable alias) failed"); } @@ -1599,8 +1616,8 @@ UnicodeStringTest::TestBogus() { // test that NULL primitive input string values are treated like // empty strings, not errors (bogus) test2.setTo((UChar32)0x10005); - if(test2.insert(1, NULL, 1).length()!=2) { - errln("UniStr.insert(...NULL...) should not modify the string but does"); + if(test2.insert(1, nullptr, 1).length()!=2) { + errln("UniStr.insert(...nullptr...) should not modify the string but does"); } UErrorCode errorCode=U_ZERO_ERROR; @@ -1649,11 +1666,11 @@ public: TestEnumeration() : i(0) {} virtual int32_t count(UErrorCode& /*status*/) const { - return LENGTHOF(testEnumStrings); + return UPRV_LENGTHOF(testEnumStrings); } virtual const UnicodeString *snext(UErrorCode &status) { - if(U_SUCCESS(status) && i(s6); + if(s1.getBuffer() != abc || s1.length() != 3) { + errln("UnicodeString move assignment operator did not move"); + } + UnicodeString s7(static_cast(s4)); + if(s7.getBuffer() != p || s7.length() != 100 || !s4.isBogus()) { + errln("UnicodeString move constructor did not move"); + } + + // Move self assignment leaves the object valid but in an undefined state. + // Do it to make sure there is no crash, + // but do not check for any particular resulting value. + moveFrom(s1, s1); + moveFrom(s2, s2); + moveFrom(s3, s3); + moveFrom(s4, s4); + moveFrom(s5, s5); + moveFrom(s6, s6); + moveFrom(s7, s7); + // Simple copy assignment must work. + UnicodeString simple = UNICODE_STRING_SIMPLE("simple"); + s1 = s6 = s4 = s7 = simple; + if(s1 != simple || s4 != simple || s6 != simple || s7 != simple) { + errln("UnicodeString copy after self-move did not work"); + } +} + +void +UnicodeStringTest::TestUInt16Pointers() { + static const uint16_t carr[] = { 0x61, 0x62, 0x63, 0 }; + uint16_t arr[4]; + + UnicodeString expected(u"abc"); + assertEquals("abc from pointer", expected, UnicodeString(carr)); + assertEquals("abc from pointer+length", expected, UnicodeString(carr, 3)); + assertEquals("abc from read-only-alias pointer", expected, UnicodeString(TRUE, carr, 3)); + + UnicodeString alias(arr, 0, 4); + alias.append(u'a').append(u'b').append(u'c'); + assertEquals("abc from writable alias", expected, alias); + assertEquals("buffer=abc from writable alias", expected, UnicodeString(arr, 3)); + + UErrorCode errorCode = U_ZERO_ERROR; + int32_t length = UnicodeString(u"def").extract(arr, 4, errorCode); + assertSuccess(WHERE, errorCode); + assertEquals("def from extract()", UnicodeString(u"def"), UnicodeString(arr, length)); +} + +void +UnicodeStringTest::TestWCharPointers() { +#if U_SIZEOF_WCHAR_T==2 + static const wchar_t carr[] = { 0x61, 0x62, 0x63, 0 }; + wchar_t arr[4]; + + UnicodeString expected(u"abc"); + assertEquals("abc from pointer", expected, UnicodeString(carr)); + assertEquals("abc from pointer+length", expected, UnicodeString(carr, 3)); + assertEquals("abc from read-only-alias pointer", expected, UnicodeString(TRUE, carr, 3)); + + UnicodeString alias(arr, 0, 4); + alias.append(u'a').append(u'b').append(u'c'); + assertEquals("abc from writable alias", expected, alias); + assertEquals("buffer=abc from writable alias", expected, UnicodeString(arr, 3)); + + UErrorCode errorCode = U_ZERO_ERROR; + int32_t length = UnicodeString(u"def").extract(arr, 4, errorCode); + assertSuccess(WHERE, errorCode); + assertEquals("def from extract()", UnicodeString(u"def"), UnicodeString(arr, length)); +#endif +} + +void +UnicodeStringTest::TestNullPointers() { + assertTrue("empty from nullptr", UnicodeString(nullptr).isEmpty()); + assertTrue("empty from nullptr+length", UnicodeString(nullptr, 2).isEmpty()); + assertTrue("empty from read-only-alias nullptr", UnicodeString(TRUE, nullptr, 3).isEmpty()); + + UnicodeString alias(nullptr, 4, 4); // empty, no alias + assertTrue("empty from writable alias", alias.isEmpty()); + alias.append(u'a').append(u'b').append(u'c'); + UnicodeString expected(u"abc"); + assertEquals("abc from writable alias", expected, alias); + + UErrorCode errorCode = U_ZERO_ERROR; + UnicodeString(u"def").extract(nullptr, 0, errorCode); + assertEquals("buffer overflow extracting to nullptr", U_BUFFER_OVERFLOW_ERROR, errorCode); +} + +void UnicodeStringTest::TestUnicodeStringInsertAppendToSelf() { + IcuTestErrorCode status(*this, "TestUnicodeStringAppendToSelf"); + + // Test append operation + UnicodeString str(u"foo "); + str.append(str); + str.append(str); + str.append(str); + assertEquals("", u"foo foo foo foo foo foo foo foo ", str); + + // Test append operation with readonly alias to start + str = UnicodeString(TRUE, u"foo ", 4); + str.append(str); + str.append(str); + str.append(str); + assertEquals("", u"foo foo foo foo foo foo foo foo ", str); + + // Test append operation with aliased substring + str = u"abcde"; + UnicodeString sub = str.tempSubString(1, 2); + str.append(sub); + assertEquals("", u"abcdebc", str); + + // Test append operation with double-aliased substring + str = UnicodeString(TRUE, u"abcde", 5); + sub = str.tempSubString(1, 2); + str.append(sub); + assertEquals("", u"abcdebc", str); + + // Test insert operation + str = u"a-*b"; + str.insert(2, str); + str.insert(4, str); + str.insert(8, str); + assertEquals("", u"a-a-a-a-a-a-a-a-*b*b*b*b*b*b*b*b", str); + + // Test insert operation with readonly alias to start + str = UnicodeString(TRUE, u"a-*b", 4); + str.insert(2, str); + str.insert(4, str); + str.insert(8, str); + assertEquals("", u"a-a-a-a-a-a-a-a-*b*b*b*b*b*b*b*b", str); + + // Test insert operation with aliased substring + str = u"abcde"; + sub = str.tempSubString(1, 3); + str.insert(2, sub); + assertEquals("", u"abbcdcde", str); + + // Test insert operation with double-aliased substring + str = UnicodeString(TRUE, u"abcde", 5); + sub = str.tempSubString(1, 3); + str.insert(2, sub); + assertEquals("", u"abbcdcde", str); }