]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/utxttest.cpp
ICU-511.34.tar.gz
[apple/icu.git] / icuSources / test / intltest / utxttest.cpp
index da6a4afb400d7d2effa5372d1220be976e0c3d3b..418ca99b4a0752b31b357d4b36c0469ec5a78fcc 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 2005-2006, International Business Machines Corporation and
+ * Copyright (c) 2005-2012, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 /************************************************************************
@@ -8,15 +8,14 @@
 *
 ************************************************************************/
 
-#include "unicode/utypes.h"
-
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unicode/utext.h>
-#include <unicode/utf8.h>
-#include <unicode/ustring.h>
-#include <unicode/uchriter.h>
+#include "unicode/utypes.h"
+#include "unicode/utext.h"
+#include "unicode/utf8.h"
+#include "unicode/ustring.h"
+#include "unicode/uchriter.h"
 #include "utxttest.h"
 
 static UBool  gFailed = FALSE;
@@ -54,6 +53,10 @@ UTextTest::runIndexedTest(int32_t index, UBool exec,
             if (exec) ErrorTest();   break;
         case 2: name = "FreezeTest";
             if (exec) FreezeTest();  break;
+        case 3: name = "Ticket5560";
+            if (exec) Ticket5560();  break;
+        case 4: name = "Ticket6847";
+            if (exec) Ticket6847();  break;
         default: name = "";          break;
     }
 }
@@ -274,9 +277,9 @@ void UTextTest::TestString(const UnicodeString &s) {
 
 
 
-       delete []cpMap;
-       delete []u8Map;
-       delete []u8String;
+    delete []cpMap;
+    delete []u8Map;
+    delete []u8String;
 }
 
 //  TestCMR   test Copy, Move and Replace operations.
@@ -539,11 +542,44 @@ cleanupAndReturn:
 }
 
 //
-//  TestAccess()    Test the read only access functions on a UText.
+//  TestAccess      Test the read only access functions on a UText, including cloning.
 //                  The text is accessed in a variety of ways, and compared with
 //                  the reference UnicodeString.
 //
 void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *cpMap) {
+    // Run the standard tests on the caller-supplied UText.
+    TestAccessNoClone(us, ut, cpCount, cpMap);
+
+    // Re-run tests on a shallow clone.
+    utext_setNativeIndex(ut, 0);
+    UErrorCode status = U_ZERO_ERROR;
+    UText *shallowClone = utext_clone(NULL, ut, FALSE /*deep*/, FALSE /*readOnly*/, &status);
+    TEST_SUCCESS(status);
+    TestAccessNoClone(us, shallowClone, cpCount, cpMap);
+
+    //
+    // Rerun again on a deep clone.
+    // Note that text providers are not required to provide deep cloning,
+    //   so unsupported errors are ignored.
+    //
+    status = U_ZERO_ERROR;
+    utext_setNativeIndex(shallowClone, 0);
+    UText *deepClone = utext_clone(NULL, shallowClone, TRUE, FALSE, &status);
+    utext_close(shallowClone);
+    if (status != U_UNSUPPORTED_ERROR) {
+        TEST_SUCCESS(status);
+        TestAccessNoClone(us, deepClone, cpCount, cpMap);
+    }
+    utext_close(deepClone);
+}
+    
+
+//
+//  TestAccessNoClone()    Test the read only access functions on a UText.
+//                         The text is accessed in a variety of ways, and compared with
+//                         the reference UnicodeString.
+//
+void UTextTest::TestAccessNoClone(const UnicodeString &us, UText *ut, int cpCount, m *cpMap) {
     UErrorCode  status = U_ZERO_ERROR;
     gTestNum++;
 
@@ -786,7 +822,7 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
         //   or whether the lead surrogate of the pair is extracted.
         //   It's a buffer overflow error in either case.
         TEST_ASSERT(buf[0] == us.charAt(0) ||
-                    buf[0] == 0x5555 && U_IS_SUPPLEMENTARY(us.char32At(0)));
+                    (buf[0] == 0x5555 && U_IS_SUPPLEMENTARY(us.char32At(0))));
         TEST_ASSERT(buf[1] == 0x5555);
         if (us.length() == 1) {
             TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
@@ -798,8 +834,6 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
     delete []buf;
 }
 
-
-
 //
 //  ErrorTest()    Check various error and edge cases.
 //
@@ -867,6 +901,28 @@ void UTextTest::ErrorTest()
         TEST_ASSERT(utp == &ut);
     }
 
+    // Invalid parameters on open
+    //
+    {
+        UErrorCode status = U_ZERO_ERROR;
+        UText ut = UTEXT_INITIALIZER;
+        
+        utext_openUChars(&ut, NULL, 5, &status);
+        TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
+
+        status = U_ZERO_ERROR;
+        utext_openUChars(&ut, NULL, -1, &status);
+        TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
+
+        status = U_ZERO_ERROR;
+        utext_openUTF8(&ut, NULL, 4, &status);
+        TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
+
+        status = U_ZERO_ERROR;
+        utext_openUTF8(&ut, NULL, -1, &status);
+        TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
+    }
+
     //
     //  UTF-8 with malformed sequences.
     //    These should come through as the Unicode replacement char, \ufffd
@@ -996,7 +1052,8 @@ void UTextTest::ErrorTest()
             TEST_ASSERT(extractedLen == exLen[i]);
             if (extractedLen > 0) {
                 UChar32  c32;
-                U16_GET(buf, 0, 0, extractedLen, c32);
+                /* extractedLen-extractedLen == 0 is used to get around a compiler warning. */
+                U16_GET(buf, 0, extractedLen-extractedLen, extractedLen, c32);
                 TEST_ASSERT(c32 == c32Map[i]);
             }
         }
@@ -1008,7 +1065,7 @@ void UTextTest::ErrorTest()
     {    //  Similar test, with utf16 instead of utf8
          //  TODO:  merge the common parts of these tests.
         
-        UnicodeString u16str("\\u1000\\U00011000\\u2000\\U00022000");
+        UnicodeString u16str("\\u1000\\U00011000\\u2000\\U00022000", -1, US_INV);
         int32_t startMap[]  ={ 0,     1,   1,    3,     4,  4,     6,  6};
         int32_t nextMap[]  = { 1,     3,   3,    4,     6,  6,     6,  6};
         int32_t prevMap[]  = { 0,     0,   0,    1,     3,  3,     4,  4};
@@ -1064,7 +1121,8 @@ void UTextTest::ErrorTest()
             TEST_ASSERT(extractedLen == exLen[i]);
             if (extractedLen > 0) {
                 UChar32  c32;
-                U16_GET(buf, 0, 0, extractedLen, c32);
+                /* extractedLen-extractedLen == 0 is used to get around a compiler warning. */
+                U16_GET(buf, 0, extractedLen-extractedLen, extractedLen, c32);
                 TEST_ASSERT(c32 == c32Map[i]);
             }
         }
@@ -1075,7 +1133,7 @@ void UTextTest::ErrorTest()
     {    //  Similar test, with UText over Replaceable
          //  TODO:  merge the common parts of these tests.
         
-        UnicodeString u16str("\\u1000\\U00011000\\u2000\\U00022000");
+        UnicodeString u16str("\\u1000\\U00011000\\u2000\\U00022000", -1, US_INV);
         int32_t startMap[]  ={ 0,     1,   1,    3,     4,  4,     6,  6};
         int32_t nextMap[]  = { 1,     3,   3,    4,     6,  6,     6,  6};
         int32_t prevMap[]  = { 0,     0,   0,    1,     3,  3,     4,  4};
@@ -1131,7 +1189,8 @@ void UTextTest::ErrorTest()
             TEST_ASSERT(extractedLen == exLen[i]);
             if (extractedLen > 0) {
                 UChar32  c32;
-                U16_GET(buf, 0, 0, extractedLen, c32);
+                /* extractedLen-extractedLen == 0 is used to get around a compiler warning. */
+                U16_GET(buf, 0, extractedLen-extractedLen, extractedLen, c32);
                 TEST_ASSERT(c32 == c32Map[i]);
             }
         }
@@ -1274,11 +1333,30 @@ fragTextAccess(UText *ut, int64_t index, UBool forward) {
     }
     return false;
 }
-U_CDECL_END
 
 // Function table to be used with this fragmented text provider.
 //   Initialized in the open function.
-UTextFuncs  fragmentFuncs;
+static UTextFuncs  fragmentFuncs;
+
+// Clone function for fragmented text provider.
+//   Didn't really want to provide this, but it's easier to provide it than to keep it
+//   out of the tests.
+//
+UText *
+cloneFragmentedUnicodeString(UText *dest, const UText *src, UBool deep, UErrorCode *status) {
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    if (deep) {
+        *status = U_UNSUPPORTED_ERROR;
+        return NULL;
+    }
+    dest = utext_openUnicodeString(dest, (UnicodeString *)src->context, status);
+    utext_setNativeIndex(dest, utext_getNativeIndex(src));
+    return dest;
+}
+
+U_CDECL_END
 
 // Open function for the fragmented text provider.
 UText *
@@ -1292,6 +1370,7 @@ openFragmentedUnicodeString(UText *ut, UnicodeString *s, UErrorCode *status) {
     //   and replace the entry for the access function.
     memcpy(&fragmentFuncs, ut->pFuncs, sizeof(fragmentFuncs));
     fragmentFuncs.access = fragTextAccess;
+    fragmentFuncs.clone  = cloneFragmentedUnicodeString;
     ut->pFuncs = &fragmentFuncs;
 
     ut->chunkContents = (UChar *)&ut->b;
@@ -1299,4 +1378,77 @@ openFragmentedUnicodeString(UText *ut, UnicodeString *s, UErrorCode *status) {
     return ut;
 }
 
+// Regression test for Ticket 5560
+//   Clone fails to update chunkContentPointer in the cloned copy.
+//   This is only an issue for UText types that work in a local buffer,
+//      (UTF-8 wrapper, for example)
+//
+//   The test:
+//     1.  Create an inital UText
+//     2.  Deep clone it.  Contents should match original.
+//     3.  Reset original to something different.
+//     4.  Check that clone contents did not change.  
+//
+void UTextTest::Ticket5560() {
+    /* The following two strings are in UTF-8 even on EBCDIC platforms. */
+    static const char s1[] = {0x41,0x42,0x43,0x44,0x45,0x46,0}; /* "ABCDEF" */
+    static const char s2[] = {0x31,0x32,0x33,0x34,0x35,0x36,0}; /* "123456" */
+       UErrorCode status = U_ZERO_ERROR;
+
+       UText ut1 = UTEXT_INITIALIZER;
+       UText ut2 = UTEXT_INITIALIZER;
+
+       utext_openUTF8(&ut1, s1, -1, &status);
+       UChar c = utext_next32(&ut1);
+       TEST_ASSERT(c == 0x41);  // c == 'A'
+
+       utext_clone(&ut2, &ut1, TRUE, FALSE, &status);
+       TEST_SUCCESS(status);
+    c = utext_next32(&ut2);
+       TEST_ASSERT(c == 0x42);  // c == 'B'
+    c = utext_next32(&ut1);
+       TEST_ASSERT(c == 0x42);  // c == 'B'
+
+       utext_openUTF8(&ut1, s2, -1, &status);
+       c = utext_next32(&ut1);
+       TEST_ASSERT(c == 0x31);  // c == '1'
+    c = utext_next32(&ut2);
+       TEST_ASSERT(c == 0x43);  // c == 'C'
+
+    utext_close(&ut1);
+    utext_close(&ut2);
+}
+
+
+// Test for Ticket 6847
+//
+void UTextTest::Ticket6847() {
+    const int STRLEN = 90;
+    UChar s[STRLEN+1];
+    u_memset(s, 0x41, STRLEN);
+    s[STRLEN] = 0;
+
+    UErrorCode status = U_ZERO_ERROR;
+    UText *ut = utext_openUChars(NULL, s, -1, &status);
+
+    utext_setNativeIndex(ut, 0);
+    int32_t count = 0;
+    UChar32 c = 0;
+    int64_t nativeIndex = UTEXT_GETNATIVEINDEX(ut);
+    TEST_ASSERT(nativeIndex == 0);
+    while ((c = utext_next32(ut)) != U_SENTINEL) {
+        TEST_ASSERT(c == 0x41);
+        TEST_ASSERT(count < STRLEN);
+        if (count >= STRLEN) {
+            break;
+        }
+        count++;
+        nativeIndex = UTEXT_GETNATIVEINDEX(ut);
+        TEST_ASSERT(nativeIndex == count);
+    }
+    TEST_ASSERT(count == STRLEN);
+    nativeIndex = UTEXT_GETNATIVEINDEX(ut);
+    TEST_ASSERT(nativeIndex == STRLEN);
+    utext_close(ut);
+}