]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/regcoll.cpp
ICU-62135.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / regcoll.cpp
index c5b03b2a919085f8f73351d88edbebe244525b88..766a72ec30054a23bfc1140e7861a2bd10644809 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /********************************************************************
- * COPYRIGHT: 
- * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * COPYRIGHT:
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
 #if !UCONFIG_NO_COLLATION
 
 #include "unicode/coll.h"
+#include "unicode/localpointer.h"
 #include "unicode/tblcoll.h"
 #include "unicode/unistr.h"
 #include "unicode/sortkey.h"
 #include "regcoll.h"
 #include "sfwdchit.h"
-
-#define ARRAY_LENGTH(array) ((int32_t)(sizeof array / sizeof array[0]))
+#include "testutil.h"
+#include "cmemory.h"
 
 CollationRegressionTest::CollationRegressionTest()
 {
@@ -25,7 +28,7 @@ CollationRegressionTest::CollationRegressionTest()
     if(U_FAILURE(status)) {
       delete en_us;
       en_us = 0;
-      errln("Collator creation failed with %s", u_errorName(status));
+      errcheckln(status, "Collator creation failed with %s", u_errorName(status));
       return;
     }
 }
@@ -82,19 +85,10 @@ void CollationRegressionTest::Test4048446(/* char* par */)
 //
 void CollationRegressionTest::Test4051866(/* char* par */)
 {
-/*
-    RuleBasedCollator c1 = new RuleBasedCollator("< o "
-                                                +"& oe ,o\u3080"
-                                                +"& oe ,\u1530 ,O"
-                                                +"& OE ,O\u3080"
-                                                +"& OE ,\u1520"
-                                                +"< p ,P");
-*/
-
     UnicodeString rules;
     UErrorCode status = U_ZERO_ERROR;
 
-    rules += "< o ";
+    rules += "&n < o ";
     rules += "& oe ,o";
     rules += (UChar)0x3080;
     rules += "& oe ,";
@@ -107,19 +101,24 @@ void CollationRegressionTest::Test4051866(/* char* par */)
     rules += "< p ,P";
 
     // Build a collator containing expanding characters
-    RuleBasedCollator *c1 = new RuleBasedCollator(rules, status);
+    LocalPointer<RuleBasedCollator> c1(new RuleBasedCollator(rules, status), status);
+    if (U_FAILURE(status)) {
+        errln("RuleBasedCollator(rule string) failed - %s", u_errorName(status));
+        return;
+    }
 
     // Build another using the rules from  the first
-    RuleBasedCollator *c2 = new RuleBasedCollator(c1->getRules(), status);
+    LocalPointer<RuleBasedCollator> c2(new RuleBasedCollator(c1->getRules(), status), status);
+    if (U_FAILURE(status)) {
+        errln("RuleBasedCollator(rule string from other RBC) failed - %s", u_errorName(status));
+        return;
+    }
 
     // Make sure they're the same
     if (!(c1->getRules() == c2->getRules()))
     {
         errln("Rules are not equal");
     }
-
-    delete c2;
-    delete c1;
 }
 
 // @bug 4053636
@@ -169,7 +168,7 @@ void CollationRegressionTest::Test4054734(/* char* par */)
             "A\u0001",  ">",    "~\u0002",      // Ensure A and ~ are not compared bitwise
             "\u00C0",   "=",    "A\u0300"       // Decomp should make these equal
         };
+
         String[] nodecomp = {
             "\u00C0",   ">",    "A\u0300"       // A-grave vs. A combining-grave
         };
@@ -183,14 +182,14 @@ void CollationRegressionTest::Test4054734(/* char* par */)
         {0x00c0, 0},      {0x3d, 0}, {0x41, 0x0300, 0}
     };
 
-    
+
     UErrorCode status = U_ZERO_ERROR;
     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
 
     c->setStrength(Collator::IDENTICAL);
 
     c->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
-    compareArray(*c, decomp, ARRAY_LENGTH(decomp));
+    compareArray(*c, decomp, UPRV_LENGTHOF(decomp));
 
     delete c;
 }
@@ -212,23 +211,23 @@ void CollationRegressionTest::Test4054736(/* char* par */)
         {0xFB4F, 0}, {0x3d, 0}, {0x05D0, 0x05DC}  // Alef-Lamed vs. Alef, Lamed
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
 
 // @bug 4058613
 //
-// Collator::createInstance() causes an ArrayIndexOutofBoundsException for Korean  
+// Collator::createInstance() causes an ArrayIndexOutofBoundsException for Korean
 //
 void CollationRegressionTest::Test4058613(/* char* par */)
 {
     // Creating a default collator doesn't work when Korean is the default
     // locale
-    
+
     Locale oldDefault = Locale::getDefault();
     UErrorCode status = U_ZERO_ERROR;
-    
+
     Locale::setDefault(Locale::getKorean(), status);
 
     if (U_FAILURE(status))
@@ -238,7 +237,7 @@ void CollationRegressionTest::Test4058613(/* char* par */)
     }
 
     Collator *c = NULL;
-    
+
     c = Collator::createInstance("en_US", status);
 
     if (c == NULL || U_FAILURE(status))
@@ -248,7 +247,7 @@ void CollationRegressionTest::Test4058613(/* char* par */)
         delete c;
         return;
     }
-    
+
     // Since the fix to this bug was to turn off decomposition for Korean collators,
     // ensure that's what we got
     if (c->getAttribute(UCOL_NORMALIZATION_MODE, status) != UCOL_OFF)
@@ -271,8 +270,8 @@ void CollationRegressionTest::Test4059820(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
 
     RuleBasedCollator *c = NULL;
-    UnicodeString rules = "< a < b , c/a < d < z";
-    
+    UnicodeString rules = "&9 < a < b , c/a < d < z";
+
     c = new RuleBasedCollator(rules, status);
 
     if (c == NULL || U_FAILURE(status))
@@ -299,7 +298,7 @@ void CollationRegressionTest::Test4060154(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     UnicodeString rules;
 
-    rules += "< g, G < h, H < i, I < j, J";
+    rules += "&f < g, G < h, H < i, I < j, J";
     rules +=  " & H < ";
     rules += (UChar)0x0131;
     rules += ", ";
@@ -307,7 +306,7 @@ void CollationRegressionTest::Test4060154(/* char* par */)
     rules += ", i, I";
 
     RuleBasedCollator *c = NULL;
-    
+
     c = new RuleBasedCollator(rules, status);
 
     if (c == NULL || U_FAILURE(status))
@@ -341,7 +340,7 @@ void CollationRegressionTest::Test4060154(/* char* par */)
     };
 
     c->setStrength(Collator::TERTIARY);
-    compareArray(*c, tertiary, ARRAY_LENGTH(tertiary));
+    compareArray(*c, tertiary, UPRV_LENGTHOF(tertiary));
 
     /*
     String[] secondary = {
@@ -356,7 +355,7 @@ void CollationRegressionTest::Test4060154(/* char* par */)
     };
 
     c->setStrength(Collator::PRIMARY);
-    compareArray(*c, secondary, ARRAY_LENGTH(secondary));
+    compareArray(*c, secondary, UPRV_LENGTHOF(secondary));
 
     delete c;
 }
@@ -370,12 +369,12 @@ void CollationRegressionTest::Test4062418(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
 
     RuleBasedCollator *c = NULL;
-    
-    c = (RuleBasedCollator *) Collator::createInstance(Locale::getFrance(), status);
+
+    c = (RuleBasedCollator *) Collator::createInstance(Locale::getCanadaFrench(), status);
 
     if (c == NULL || U_FAILURE(status))
     {
-        errln("Failed to create collator for Locale::getFrance()");
+        errln("Failed to create collator for Locale::getCanadaFrench()");
         delete c;
         return;
     }
@@ -392,7 +391,7 @@ void CollationRegressionTest::Test4062418(/* char* par */)
         {0x70, 0x00EA, 0x63, 0x68, 0x65, 0}, {0x3c, 0}, {0x70, 0x00E9, 0x63, 0x68, 0x00E9, 0}
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -450,12 +449,12 @@ void CollationRegressionTest::Test4066696(/* char* par */)
 {
     UErrorCode status = U_ZERO_ERROR;
     RuleBasedCollator *c = NULL;
-    
-    c = (RuleBasedCollator *)Collator::createInstance(Locale::getFrance(), status);
+
+    c = (RuleBasedCollator *)Collator::createInstance(Locale::getCanadaFrench(), status);
 
     if (c == NULL || U_FAILURE(status))
     {
-        errln("Failure creating collator for Locale::getFrance()");
+        errln("Failure creating collator for Locale::getCanadaFrench()");
         delete c;
         return;
     }
@@ -480,7 +479,7 @@ void CollationRegressionTest::Test4066696(/* char* par */)
         {0x00E0, 0}, {0x3e, 0}, {0x01FA, 0}
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -542,7 +541,7 @@ void CollationRegressionTest::Test4079231(/* char* par */)
 void CollationRegressionTest::Test4078588(/* char *par */)
 {
     UErrorCode status = U_ZERO_ERROR;
-    RuleBasedCollator *rbc = new RuleBasedCollator((UnicodeString)"< a < bb", status);
+    RuleBasedCollator *rbc = new RuleBasedCollator("&9 < a < bb", status);
 
     if (rbc == NULL || U_FAILURE(status))
     {
@@ -576,7 +575,7 @@ void CollationRegressionTest::Test4081866(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
     c->setStrength(Collator::TERTIARY);
-    
+
     // Now that the default collators are set to NO_DECOMPOSITION
     // (as a result of fixing bug 4114077), we must set it explicitly
     // when we're testing reordering behavior.  -- lwerner, 5/5/98
@@ -599,7 +598,7 @@ void CollationRegressionTest::Test4087241(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     Locale da_DK("da", "DK");
     RuleBasedCollator *c = NULL;
-    
+
     c = (RuleBasedCollator *) Collator::createInstance(da_DK, status);
 
     if (c == NULL || U_FAILURE(status))
@@ -614,11 +613,11 @@ void CollationRegressionTest::Test4087241(/* char* par */)
     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
     {
         {0x7a, 0},          {0x3c, 0}, {0x00E6, 0},            // z        < ae
-        {0x61, 0x0308, 0}, {0x3c, 0}, {0x61, 0x030A, 0},      // a-unlaut < a-ring
+        {0x61, 0x0308, 0},  {0x3c, 0}, {0x61, 0x030A, 0},      // a-umlaut < a-ring
         {0x59, 0},          {0x3c, 0}, {0x75, 0x0308, 0},      // Y        < u-umlaut
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -637,7 +636,7 @@ void CollationRegressionTest::Test4087243(/* char* par */)
         {0x31, 0x32, 0x33, 0}, {0x3d, 0}, {0x31, 0x32, 0x33, 0x0001, 0}    // 1 2 3  =  1 2 3 ctrl-A
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -652,7 +651,7 @@ void CollationRegressionTest::Test4092260(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     Locale el("el", "");
     Collator *c = NULL;
-    
+
     c = Collator::createInstance(el, status);
 
     if (c == NULL || U_FAILURE(status))
@@ -670,7 +669,7 @@ void CollationRegressionTest::Test4092260(/* char* par */)
         {0x00B5, 0}, {0x3d, 0}, {0x03BC, 0}
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -698,7 +697,7 @@ void CollationRegressionTest::Test4095316(/* char* par */)
         {0x03D4, 0}, {0x3d, 0}, {0x03AB, 0}
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -709,9 +708,9 @@ void CollationRegressionTest::Test4101940(/* char* par */)
 {
     UErrorCode status = U_ZERO_ERROR;
     RuleBasedCollator *c = NULL;
-    UnicodeString rules = "< a < b";
+    UnicodeString rules = "&9 < a < b";
     UnicodeString nothing = "";
-    
+
     c = new RuleBasedCollator(rules, status);
 
     if (c == NULL || U_FAILURE(status))
@@ -748,7 +747,7 @@ void CollationRegressionTest::Test4103436(/* char* par */)
         {0x66, 0x69, 0x6c, 0x65, 0}, {0x3c, 0}, {0x66, 0x69, 0x6c, 0x65, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0}
     };
 
-    compareArray(*c, tests, ARRAY_LENGTH(tests));
+    compareArray(*c, tests, UPRV_LENGTHOF(tests));
 
     delete c;
 }
@@ -774,11 +773,11 @@ void CollationRegressionTest::Test4114076(/* char* par */)
     };
 
     c->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
-    compareArray(*c, test1, ARRAY_LENGTH(test1));
+    compareArray(*c, test1, UPRV_LENGTHOF(test1));
 
     // From UTR #15:
     // *In earlier versions of Unicode, jamo characters like ksf
-    //  had compatibility mappings to kf + sf. These mappings were 
+    //  had compatibility mappings to kf + sf. These mappings were
     //  removed in Unicode 2.1.9 to ensure that Hangul syllables are maintained.)
     // That is, the following test is obsolete as of 2.1.9
 
@@ -791,7 +790,7 @@ void CollationRegressionTest::Test4114076(/* char* par */)
 //obsolete-    };
 //obsolete-
 //obsolete-    c->setDecomposition(Normalizer::DECOMP_COMPAT);
-//obsolete-    compareArray(*c, test2, ARRAY_LENGTH(test2));
+//obsolete-    compareArray(*c, test2, UPRV_LENGTHOF(test2));
 
     delete c;
 }
@@ -805,9 +804,9 @@ void CollationRegressionTest::Test4124632(/* char* par */)
 {
     UErrorCode status = U_ZERO_ERROR;
     Collator *coll = NULL;
-    
+
     coll = Collator::createInstance(Locale::getJapan(), status);
-    
+
     if (coll == NULL || U_FAILURE(status))
     {
         errln("Failed to create collator for Locale::JAPAN");
@@ -817,7 +816,7 @@ void CollationRegressionTest::Test4124632(/* char* par */)
 
     static const UChar test[] = {0x41, 0x0308, 0x62, 0x63, 0};
     CollationKey key;
-    
+
     coll->getCollationKey(test, key, status);
 
     if (key.isBogus() || U_FAILURE(status))
@@ -837,13 +836,13 @@ void CollationRegressionTest::Test4132736(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
 
     Collator *c = NULL;
-    
-    c = Collator::createInstance(Locale::getFrance(), status);
+
+    c = Collator::createInstance(Locale::getCanadaFrench(), status);
     c->setStrength(Collator::TERTIARY);
-    
+
     if (c == NULL || U_FAILURE(status))
     {
-        errln("Failed to create a collator for Locale::getFrance()");
+        errln("Failed to create a collator for Locale::getCanadaFrench()");
         delete c;
         return;
     }
@@ -854,7 +853,7 @@ void CollationRegressionTest::Test4132736(/* char* par */)
         {0x65, 0x0300, 0x0301, 0},       {0x3c, 0}, {0x65, 0x0301, 0x0300, 0}
     };
 
-    compareArray(*c, test1, ARRAY_LENGTH(test1));
+    compareArray(*c, test1, UPRV_LENGTHOF(test1));
 
     delete c;
 }
@@ -872,22 +871,22 @@ void CollationRegressionTest::Test4133509(/* char* par */)
         {0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0},                  {0x3c, 0}, {0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0}
     };
 
-    compareArray(*en_us, test1, ARRAY_LENGTH(test1));
+    compareArray(*en_us, test1, UPRV_LENGTHOF(test1));
 }
 
 // @bug 4114077
 //
-// Collation with decomposition off doesn't work for Europe 
+// Collation with decomposition off doesn't work for Europe
 //
 void CollationRegressionTest::Test4114077(/* char* par */)
 {
     // Ensure that we get the same results with decomposition off
     // as we do with it on....
-    
+
     UErrorCode status = U_ZERO_ERROR;
     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
     c->setStrength(Collator::TERTIARY);
-    
+
     static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] =
     {
         {0x00C0, 0},                     {0x3d, 0}, {0x41, 0x0300, 0},            // Should be equivalent
@@ -899,7 +898,7 @@ void CollationRegressionTest::Test4114077(/* char* par */)
     };
 
     c->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
-    compareArray(*c, test1, ARRAY_LENGTH(test1));
+    compareArray(*c, test1, UPRV_LENGTHOF(test1));
 
     static const UChar test2[][CollationRegressionTest::MAX_TOKEN_LEN] =
     {
@@ -907,14 +906,14 @@ void CollationRegressionTest::Test4114077(/* char* par */)
     };
 
     c->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
-    compareArray(*c, test2, ARRAY_LENGTH(test2));
+    compareArray(*c, test2, UPRV_LENGTHOF(test2));
 
     delete c;
 }
 
 // @bug 4141640
 //
-// Support for Swedish gone in 1.1.6 (Can't create Swedish collator) 
+// Support for Swedish gone in 1.1.6 (Can't create Swedish collator)
 //
 void CollationRegressionTest::Test4141640(/* char* par */)
 {
@@ -926,7 +925,7 @@ void CollationRegressionTest::Test4141640(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     int32_t i, localeCount;
     const Locale *locales = Locale::getAvailableLocales(localeCount);
-    
+
     for (i = 0; i < localeCount; i += 1)
     {
         Collator *c = NULL;
@@ -950,7 +949,7 @@ void CollationRegressionTest::Test4141640(/* char* par */)
 
 // @bug 4139572
 //
-// getCollationKey throws exception for spanish text 
+// getCollationKey throws exception for spanish text
 // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6
 //
 void CollationRegressionTest::Test4139572(/* char* par */)
@@ -963,7 +962,7 @@ void CollationRegressionTest::Test4139572(/* char* par */)
     UErrorCode status = U_ZERO_ERROR;
     Locale l("es", "es");
     Collator *col = NULL;
-    
+
     col = Collator::createInstance(l, status);
 
     if (col == NULL || U_FAILURE(status))
@@ -987,7 +986,7 @@ void CollationRegressionTest::Test4139572(/* char* par */)
 }
 /* HSYS : RuleBasedCollator::compare() performance enhancements
           compare() does not create CollationElementIterator() anymore.*/
-          
+
 class My4146160Collator : public RuleBasedCollator
 {
 public:
@@ -997,7 +996,7 @@ public:
     CollationElementIterator *createCollationElementIterator(const UnicodeString &text) const;
 
     CollationElementIterator *createCollationElementIterator(const CharacterIterator &text) const;
-    
+
     static int32_t count;
 };
 
@@ -1040,7 +1039,7 @@ void CollationRegressionTest::Test4146160(/* char* par */)
 
     My4146160Collator::count = 0;
     My4146160Collator *mc = NULL;
-    
+
     mc = new My4146160Collator(*en_us, status);
 
     if (mc == NULL || U_FAILURE(status))
@@ -1075,6 +1074,271 @@ void CollationRegressionTest::Test4146160(/* char* par */)
     delete mc;
 #endif
 }
+
+void CollationRegressionTest::Test4179216() {
+    // you can position a CollationElementIterator in the middle of
+    // a contracting character sequence, yielding a bogus collation
+    // element
+    IcuTestErrorCode errorCode(*this, "Test4179216");
+    RuleBasedCollator coll(en_us->getRules() + " & C < ch , cH , Ch , CH < cat < crunchy", errorCode);
+    UnicodeString testText = "church church catcatcher runcrunchynchy";
+    CollationElementIterator *iter = coll.createCollationElementIterator(testText);
+
+    // test that the "ch" combination works properly
+    iter->setOffset(4, errorCode);
+    int32_t elt4 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->reset();
+    int32_t elt0 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(5, errorCode);
+    int32_t elt5 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    // Compares and prints only 16-bit primary weights.
+    if (elt4 != elt0 || elt5 != elt0) {
+        errln("The collation elements at positions 0 (0x%04x), "
+                "4 (0x%04x), and 5 (0x%04x) don't match.",
+                elt0, elt4, elt5);
+    }
+
+    // test that the "cat" combination works properly
+    iter->setOffset(14, errorCode);
+    int32_t elt14 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(15, errorCode);
+    int32_t elt15 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(16, errorCode);
+    int32_t elt16 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(17, errorCode);
+    int32_t elt17 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(18, errorCode);
+    int32_t elt18 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    iter->setOffset(19, errorCode);
+    int32_t elt19 = CollationElementIterator::primaryOrder(iter->next(errorCode));
+
+    // Compares and prints only 16-bit primary weights.
+    if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17
+            || elt14 != elt18 || elt14 != elt19) {
+        errln("\"cat\" elements don't match: elt14 = 0x%04x, "
+                "elt15 = 0x%04x, elt16 = 0x%04x, elt17 = 0x%04x, "
+                "elt18 = 0x%04x, elt19 = 0x%04x",
+                elt14, elt15, elt16, elt17, elt18, elt19);
+    }
+
+    // now generate a complete list of the collation elements,
+    // first using next() and then using setOffset(), and
+    // make sure both interfaces return the same set of elements
+    iter->reset();
+
+    int32_t elt = iter->next(errorCode);
+    int32_t count = 0;
+    while (elt != CollationElementIterator::NULLORDER) {
+        ++count;
+        elt = iter->next(errorCode);
+    }
+
+    LocalArray<UnicodeString> nextElements(new UnicodeString[count]);
+    LocalArray<UnicodeString> setOffsetElements(new UnicodeString[count]);
+    int32_t lastPos = 0;
+
+    iter->reset();
+    elt = iter->next(errorCode);
+    count = 0;
+    while (elt != CollationElementIterator::NULLORDER) {
+        nextElements[count++] = testText.tempSubStringBetween(lastPos, iter->getOffset());
+        lastPos = iter->getOffset();
+        elt = iter->next(errorCode);
+    }
+    int32_t nextElementsLength = count;
+    count = 0;
+    for (int32_t i = 0; i < testText.length(); ) {
+        iter->setOffset(i, errorCode);
+        lastPos = iter->getOffset();
+        elt = iter->next(errorCode);
+        setOffsetElements[count++] = testText.tempSubStringBetween(lastPos, iter->getOffset());
+        i = iter->getOffset();
+    }
+    for (int32_t i = 0; i < nextElementsLength; i++) {
+        if (nextElements[i] == setOffsetElements[i]) {
+            logln(nextElements[i]);
+        } else {
+            errln(UnicodeString("Error: next() yielded ") + nextElements[i] +
+                ", but setOffset() yielded " + setOffsetElements[i]);
+        }
+    }
+    delete iter;
+}
+
+// Ticket 7189
+//
+// nextSortKeyPart incorrect for EO_S1 collation
+static int32_t calcKeyIncremental(UCollator *coll, const UChar* text, int32_t len, uint8_t *keyBuf, int32_t /*keyBufLen*/, UErrorCode& status) {
+    UCharIterator uiter;
+    uint32_t state[2] = { 0, 0 };
+    int32_t keyLen;
+    int32_t count = 8;
+
+    uiter_setString(&uiter, text, len);
+    keyLen = 0;
+    while (TRUE) {
+        int32_t keyPartLen = ucol_nextSortKeyPart(coll, &uiter, state, &keyBuf[keyLen], count, &status);
+        if (U_FAILURE(status)) {
+            return -1;
+        }
+        if (keyPartLen == 0) {
+            break;
+        }
+        keyLen += keyPartLen;
+    }
+    return keyLen;
+}
+
+void CollationRegressionTest::TestT7189() {
+    UErrorCode status = U_ZERO_ERROR;
+    UCollator *coll;
+    uint32_t i;
+
+    static const UChar text1[][CollationRegressionTest::MAX_TOKEN_LEN] = {
+    // "Achter De Hoven"
+        { 0x41, 0x63, 0x68, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x20, 0x48, 0x6F, 0x76, 0x65, 0x6E, 0x00 },
+        // "ABC"
+        { 0x41, 0x42, 0x43, 0x00 },
+        // "HELLO world!"
+        { 0x48, 0x45, 0x4C, 0x4C, 0x4F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00 }
+    };
+
+    static const UChar text2[][CollationRegressionTest::MAX_TOKEN_LEN] = {
+    // "Achter de Hoven"
+        { 0x41, 0x63, 0x68, 0x74, 0x65, 0x72, 0x20, 0x64, 0x65, 0x20, 0x48, 0x6F, 0x76, 0x65, 0x6E, 0x00 },
+        // "abc"
+        { 0x61, 0x62, 0x63, 0x00 },
+        // "hello world!"
+        { 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00 }
+    };
+
+    // Open the collator
+    coll = ucol_openFromShortString("EO_S1", FALSE, NULL, &status);
+    if (U_FAILURE(status)) {
+        errln("Failed to create a collator for short string EO_S1");
+        return;
+    }
+
+    for (i = 0; i < UPRV_LENGTHOF(text1); i++) {
+        uint8_t key1[100], key2[100];
+        int32_t len1, len2;
+
+        len1 = calcKeyIncremental(coll, text1[i], -1, key1, sizeof(key1), status);
+        if (U_FAILURE(status)) {
+            errln(UnicodeString("Failed to get a partial collation key for ") + text1[i]);
+            break;
+        }
+        len2 = calcKeyIncremental(coll, text2[i], -1, key2, sizeof(key2), status);
+        if (U_FAILURE(status)) {
+            errln(UnicodeString("Failed to get a partial collation key for ") + text2[i]);
+            break;
+        }
+
+        if (len1 == len2 && uprv_memcmp(key1, key2, len1) == 0) {
+            errln(UnicodeString("Failed: Identical key\n") + "    text1: " + text1[i] + "\n" + "    text2: " + text2[i] + "\n" + "    key  : " + TestUtility::hex(key1, len1));
+        } else {
+            logln(UnicodeString("Keys produced -\n") + "    text1: " + text1[i] + "\n" + "    key1 : " + TestUtility::hex(key1, len1) + "\n" + "    text2: " + text2[i] + "\n" + "    key2 : "
+                    + TestUtility::hex(key2, len2));
+        }
+    }
+    ucol_close(coll);
+}
+
+void CollationRegressionTest::TestCaseFirstCompression() {
+    RuleBasedCollator *col = (RuleBasedCollator *) en_us->clone();
+    UErrorCode status = U_ZERO_ERROR;
+
+    // default
+    caseFirstCompressionSub(col, "default");
+
+    // Upper first
+    col->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
+    if (U_FAILURE(status)) {
+        errln("Failed to set UCOL_UPPER_FIRST");
+        return;
+    }
+    caseFirstCompressionSub(col, "upper first");
+
+    // Lower first
+    col->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
+    if (U_FAILURE(status)) {
+        errln("Failed to set UCOL_LOWER_FIRST");
+        return;
+    }
+    caseFirstCompressionSub(col, "lower first");
+
+    delete col;
+}
+
+void CollationRegressionTest::caseFirstCompressionSub(Collator *col, UnicodeString opt) {
+    const int32_t maxLength = 50;
+
+    UChar str1[maxLength];
+    UChar str2[maxLength];
+
+    CollationKey key1, key2;
+
+    for (int32_t len = 1; len <= maxLength; len++) {
+        int32_t i = 0;
+        for (; i < len - 1; i++) {
+            str1[i] = str2[i] = (UChar)0x61; // 'a'
+        }
+        str1[i] = (UChar)0x41; // 'A'
+        str2[i] = (UChar)0x61; // 'a'
+
+        UErrorCode status = U_ZERO_ERROR;
+        col->getCollationKey(str1, len, key1, status);
+        col->getCollationKey(str2, len, key2, status);
+
+        UCollationResult cmpKey = key1.compareTo(key2, status);
+        UCollationResult cmpCol = col->compare(str1, len, str2, len, status);
+
+        if (U_FAILURE(status)) {
+            errln("Error in caseFirstCompressionSub");
+        } else if (cmpKey != cmpCol) {
+            errln((UnicodeString)"Inconsistent comparison(" + opt
+                + "): str1=" + UnicodeString(str1, len) + ", str2=" + UnicodeString(str2, len)
+                + ", cmpKey=" + cmpKey + ", cmpCol=" + cmpCol);
+        }
+    }
+}
+
+void CollationRegressionTest::TestTrailingComment() {
+    // ICU ticket #8070:
+    // Check that the rule parser handles a comment without terminating end-of-line.
+    IcuTestErrorCode errorCode(*this, "TestTrailingComment");
+    RuleBasedCollator coll(UNICODE_STRING_SIMPLE("&c<b#comment1\n<a#comment2"), errorCode);
+    UnicodeString a((UChar)0x61), b((UChar)0x62), c((UChar)0x63);
+    assertTrue("c<b", coll.compare(c, b) < 0);
+    assertTrue("b<a", coll.compare(b, a) < 0);
+}
+
+void CollationRegressionTest::TestBeforeWithTooStrongAfter() {
+    // ICU ticket #9959:
+    // Forbid rules with a before-reset followed by a stronger relation.
+    IcuTestErrorCode errorCode(*this, "TestBeforeWithTooStrongAfter");
+    RuleBasedCollator before2(UNICODE_STRING_SIMPLE("&[before 2]x<<q<p"), errorCode);
+    if(errorCode.isSuccess()) {
+        errln("should forbid before-2-reset followed by primary relation");
+    } else {
+        errorCode.reset();
+    }
+    RuleBasedCollator before3(UNICODE_STRING_SIMPLE("&[before 3]x<<<q<<s<p"), errorCode);
+    if(errorCode.isSuccess()) {
+        errln("should forbid before-3-reset followed by primary or secondary relation");
+    } else {
+        errorCode.reset();
+    }
+}
+
 void CollationRegressionTest::compareArray(Collator &c,
                                            const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN],
                                            int32_t testCount)
@@ -1148,7 +1412,7 @@ void CollationRegressionTest::assertEqual(CollationElementIterator &i1, Collatio
         if (c1 != c2)
         {
             UnicodeString msg, msg1("    ");
-            
+
             msg += msg1 + count;
             msg += ": strength(0x";
             appendHex(c1, 8, msg);
@@ -1172,46 +1436,49 @@ void CollationRegressionTest::runIndexedTest(int32_t index, UBool exec, const ch
         logln("Collation Regression Tests: ");
     }
 
-    if(en_us) {
-      switch (index)
-      {
-          case  0: name = "Test4048446"; if (exec) Test4048446(/* par */); break;
-          case  1: name = "Test4051866"; if (exec) Test4051866(/* par */); break;
-          case  2: name = "Test4053636"; if (exec) Test4053636(/* par */); break;
-          case  3: name = "Test4054238"; if (exec) Test4054238(/* par */); break;
-          case  4: name = "Test4054734"; if (exec) Test4054734(/* par */); break;
-          case  5: name = "Test4054736"; if (exec) Test4054736(/* par */); break;
-          case  6: name = "Test4058613"; if (exec) Test4058613(/* par */); break;
-          case  7: name = "Test4059820"; if (exec) Test4059820(/* par */); break;
-          case  8: name = "Test4060154"; if (exec) Test4060154(/* par */); break;
-          case  9: name = "Test4062418"; if (exec) Test4062418(/* par */); break;
-          case 10: name = "Test4065540"; if (exec) Test4065540(/* par */); break;
-          case 11: name = "Test4066189"; if (exec) Test4066189(/* par */); break;
-          case 12: name = "Test4066696"; if (exec) Test4066696(/* par */); break;
-          case 13: name = "Test4076676"; if (exec) Test4076676(/* par */); break;
-          case 14: name = "Test4078588"; if (exec) Test4078588(/* par */); break;
-          case 15: name = "Test4079231"; if (exec) Test4079231(/* par */); break;
-          case 16: name = "Test4081866"; if (exec) Test4081866(/* par */); break;
-          case 17: name = "Test4087241"; if (exec) Test4087241(/* par */); break;
-          case 18: name = "Test4087243"; if (exec) Test4087243(/* par */); break;
-          case 19: name = "Test4092260"; if (exec) Test4092260(/* par */); break;
-          case 20: name = "Test4095316"; if (exec) Test4095316(/* par */); break;
-          case 21: name = "Test4101940"; if (exec) Test4101940(/* par */); break;
-          case 22: name = "Test4103436"; if (exec) Test4103436(/* par */); break;
-          case 23: name = "Test4114076"; if (exec) Test4114076(/* par */); break;
-          case 24: name = "Test4114077"; if (exec) Test4114077(/* par */); break;
-          case 25: name = "Test4124632"; if (exec) Test4124632(/* par */); break;
-          case 26: name = "Test4132736"; if (exec) Test4132736(/* par */); break;
-          case 27: name = "Test4133509"; if (exec) Test4133509(/* par */); break;
-          case 28: name = "Test4139572"; if (exec) Test4139572(/* par */); break;
-          case 29: name = "Test4141640"; if (exec) Test4141640(/* par */); break;
-          case 30: name = "Test4146160"; if (exec) Test4146160(/* par */); break;
-          default: name = ""; break;
-      }
-    } else {
-      errln("Class collator not instantiated");
-      name = "";
+    if(en_us == NULL) {
+        dataerrln("Class collator not instantiated");
+        name = "";
+        return;
     }
+    TESTCASE_AUTO_BEGIN;
+    TESTCASE_AUTO(Test4048446);
+    TESTCASE_AUTO(Test4051866);
+    TESTCASE_AUTO(Test4053636);
+    TESTCASE_AUTO(Test4054238);
+    TESTCASE_AUTO(Test4054734);
+    TESTCASE_AUTO(Test4054736);
+    TESTCASE_AUTO(Test4058613);
+    TESTCASE_AUTO(Test4059820);
+    TESTCASE_AUTO(Test4060154);
+    TESTCASE_AUTO(Test4062418);
+    TESTCASE_AUTO(Test4065540);
+    TESTCASE_AUTO(Test4066189);
+    TESTCASE_AUTO(Test4066696);
+    TESTCASE_AUTO(Test4076676);
+    TESTCASE_AUTO(Test4078588);
+    TESTCASE_AUTO(Test4079231);
+    TESTCASE_AUTO(Test4081866);
+    TESTCASE_AUTO(Test4087241);
+    TESTCASE_AUTO(Test4087243);
+    TESTCASE_AUTO(Test4092260);
+    TESTCASE_AUTO(Test4095316);
+    TESTCASE_AUTO(Test4101940);
+    TESTCASE_AUTO(Test4103436);
+    TESTCASE_AUTO(Test4114076);
+    TESTCASE_AUTO(Test4114077);
+    TESTCASE_AUTO(Test4124632);
+    TESTCASE_AUTO(Test4132736);
+    TESTCASE_AUTO(Test4133509);
+    TESTCASE_AUTO(Test4139572);
+    TESTCASE_AUTO(Test4141640);
+    TESTCASE_AUTO(Test4146160);
+    TESTCASE_AUTO(Test4179216);
+    TESTCASE_AUTO(TestT7189);
+    TESTCASE_AUTO(TestCaseFirstCompression);
+    TESTCASE_AUTO(TestTrailingComment);
+    TESTCASE_AUTO(TestBeforeWithTooStrongAfter);
+    TESTCASE_AUTO_END;
 }
 
 #endif /* #if !UCONFIG_NO_COLLATION */