Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2012, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*******************************************************************************
      7 *
      8 * File CALLCOLL.C
      9 *
     10 * Modification History:
     11 *        Name                     Description
     12 *     Madhu Katragadda              Ported for C API
     13 ********************************************************************************
     14 */
     15 
     16 /*
     17  * Important: This file is included into intltest/allcoll.cpp so that the
     18  * test data is shared. This makes it easier to maintain the test data,
     19  * especially since the Unicode data must be portable and quoted character
     20  * literals will not work.
     21  * If it is included, then there will be a #define INCLUDE_CALLCOLL_C
     22  * that must prevent the actual code in here from being part of the
     23  * allcoll.cpp compilation.
     24  */
     25 
     26 /**
     27  * CollationDummyTest is a third level test class.  This tests creation of
     28  * a customized collator object.  For example, number 1 to be sorted
     29  * equlivalent to word 'one'.
     30  */
     31 
     32 #include <string.h>
     33 #include <stdlib.h>
     34 
     35 #include "unicode/utypes.h"
     36 
     37 #if !UCONFIG_NO_COLLATION
     38 
     39 #include "unicode/ucol.h"
     40 #include "unicode/uloc.h"
     41 #include "unicode/ures.h"
     42 #include "unicode/udata.h"
     43 #include "unicode/ucoleitr.h"
     44 #include "unicode/ustring.h"
     45 #include "unicode/uclean.h"
     46 #include "unicode/putil.h"
     47 #include "unicode/uenum.h"
     48 
     49 #include "cintltst.h"
     50 #include "ccolltst.h"
     51 #include "callcoll.h"
     52 #include "calldata.h"
     53 #include "cstring.h"
     54 #include "cmemory.h"
     55 
     56 /* set to 1 to test offsets in backAndForth() */
     57 #define TEST_OFFSETS 0
     58 
     59 /* perform test with strength PRIMARY */
     60 static void TestPrimary(void);
     61 
     62 /* perform test with strength SECONDARY */
     63 static void TestSecondary(void);
     64 
     65 /* perform test with strength tertiary */
     66 static void TestTertiary(void);
     67 
     68 /*perform tests with strength Identical */
     69 static void TestIdentical(void);
     70 
     71 /* perform extra tests */
     72 static void TestExtra(void);
     73 
     74 /* Test jitterbug 581 */
     75 static void TestJB581(void);
     76 
     77 /* Test jitterbug 1401 */
     78 static void TestJB1401(void);
     79 
     80 /* Test [variable top] in the rule syntax */
     81 static void TestVariableTop(void);
     82 
     83 /* Test surrogates */
     84 static void TestSurrogates(void);
     85 
     86 static void TestInvalidRules(void);
     87 
     88 static void TestJitterbug1098(void);
     89 
     90 static void TestFCDCrash(void);
     91 
     92 static void TestJ5298(void);
     93 
     94 const UCollationResult results[] = {
     95     UCOL_LESS,
     96     UCOL_LESS, /*UCOL_GREATER,*/
     97     UCOL_LESS,
     98     UCOL_LESS,
     99     UCOL_LESS,
    100     UCOL_LESS,
    101     UCOL_LESS,
    102     UCOL_GREATER,
    103     UCOL_GREATER,
    104     UCOL_LESS,                                     /*  10 */
    105     UCOL_GREATER,
    106     UCOL_LESS,
    107     UCOL_GREATER,
    108     UCOL_GREATER,
    109     UCOL_LESS,
    110     UCOL_LESS,
    111     UCOL_LESS,
    112     /*  test primary > 17 */
    113     UCOL_EQUAL,
    114     UCOL_EQUAL,
    115     UCOL_EQUAL,                                    /*  20 */
    116     UCOL_LESS,
    117     UCOL_LESS,
    118     UCOL_EQUAL,
    119     UCOL_EQUAL,
    120     UCOL_EQUAL,
    121     UCOL_LESS,
    122     /*  test secondary > 26 */
    123     UCOL_EQUAL,
    124     UCOL_EQUAL,
    125     UCOL_EQUAL,
    126     UCOL_EQUAL,
    127     UCOL_EQUAL,                                    /*  30 */
    128     UCOL_EQUAL,
    129     UCOL_LESS,
    130     UCOL_EQUAL,                                     /*  34 */
    131     UCOL_EQUAL,
    132     UCOL_EQUAL,
    133     UCOL_LESS                                        /* 37 */
    134 };
    135 
    136 
    137 static
    138 void uprv_appendByteToHexString(char *dst, uint8_t val) {
    139   uint32_t len = (uint32_t)uprv_strlen(dst);
    140   *(dst+len) = T_CString_itosOffset((val >> 4));
    141   *(dst+len+1) = T_CString_itosOffset((val & 0xF));
    142   *(dst+len+2) = 0;
    143 }
    144 
    145 /* this function makes a string with representation of a sortkey */
    146 static char* U_EXPORT2 sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) {
    147     int32_t strength = UCOL_PRIMARY;
    148     uint32_t res_size = 0;
    149     UBool doneCase = FALSE;
    150     UErrorCode errorCode = U_ZERO_ERROR;
    151 
    152     char *current = buffer;
    153     const uint8_t *currentSk = sortkey;
    154 
    155     uprv_strcpy(current, "[");
    156 
    157     while(strength <= UCOL_QUATERNARY && strength <= ucol_getStrength(coll)) {
    158         if(strength > UCOL_PRIMARY) {
    159             uprv_strcat(current, " . ");
    160         }
    161         while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */
    162             uprv_appendByteToHexString(current, *currentSk++);
    163             uprv_strcat(current, " ");
    164         }
    165         if(ucol_getAttribute(coll, UCOL_CASE_LEVEL, &errorCode) == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) {
    166             doneCase = TRUE;
    167         } else if(ucol_getAttribute(coll, UCOL_CASE_LEVEL, &errorCode) == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) {
    168             strength ++;
    169         }
    170         if (*currentSk) {
    171             uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */
    172         }
    173         if(strength == UCOL_QUATERNARY && ucol_getAttribute(coll, UCOL_ALTERNATE_HANDLING, &errorCode) == UCOL_NON_IGNORABLE) {
    174             break;
    175         }
    176     }
    177 
    178     if(ucol_getStrength(coll) == UCOL_IDENTICAL) {
    179         uprv_strcat(current, " . ");
    180         while(*currentSk != 0) {
    181             uprv_appendByteToHexString(current, *currentSk++);
    182             uprv_strcat(current, " ");
    183         }
    184 
    185         uprv_appendByteToHexString(current, *currentSk++);
    186     }
    187     uprv_strcat(current, "]");
    188 
    189     if(res_size > *len) {
    190         return NULL;
    191     }
    192 
    193     return buffer;
    194 }
    195 
    196 void addAllCollTest(TestNode** root)
    197 {
    198     addTest(root, &TestPrimary, "tscoll/callcoll/TestPrimary");
    199     addTest(root, &TestSecondary, "tscoll/callcoll/TestSecondary");
    200     addTest(root, &TestTertiary, "tscoll/callcoll/TestTertiary");
    201     addTest(root, &TestIdentical, "tscoll/callcoll/TestIdentical");
    202     addTest(root, &TestExtra, "tscoll/callcoll/TestExtra");
    203     addTest(root, &TestJB581, "tscoll/callcoll/TestJB581");
    204     addTest(root, &TestVariableTop, "tscoll/callcoll/TestVariableTop");
    205     addTest(root, &TestSurrogates, "tscoll/callcoll/TestSurrogates");
    206     addTest(root, &TestInvalidRules, "tscoll/callcoll/TestInvalidRules");
    207     addTest(root, &TestJB1401, "tscoll/callcoll/TestJB1401");
    208     addTest(root, &TestJitterbug1098, "tscoll/callcoll/TestJitterbug1098");
    209     addTest(root, &TestFCDCrash, "tscoll/callcoll/TestFCDCrash");
    210     addTest(root, &TestJ5298, "tscoll/callcoll/TestJ5298");
    211 }
    212 
    213 UBool hasCollationElements(const char *locName) {
    214 
    215   UErrorCode status = U_ZERO_ERROR;
    216 
    217   UResourceBundle *loc = ures_open(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "coll", locName, &status);;
    218 
    219   if(U_SUCCESS(status)) {
    220     status = U_ZERO_ERROR;
    221     loc = ures_getByKey(loc, "collations", loc, &status);
    222     ures_close(loc);
    223     if(status == U_ZERO_ERROR) { /* do the test - there are real elements */
    224       return TRUE;
    225     }
    226   }
    227   return FALSE;
    228 }
    229 
    230 static UCollationResult compareUsingPartials(UCollator *coll, const UChar source[], int32_t sLen, const UChar target[], int32_t tLen, int32_t pieceSize, UErrorCode *status) {
    231   int32_t partialSKResult = 0;
    232   UCharIterator sIter, tIter;
    233   uint32_t sState[2], tState[2];
    234   int32_t sSize = pieceSize, tSize = pieceSize;
    235   /*int32_t i = 0;*/
    236   uint8_t sBuf[16384], tBuf[16384];
    237   if(pieceSize > 16384) {
    238     log_err("Partial sortkey size buffer too small. Please consider increasing the buffer!\n");
    239     *status = U_BUFFER_OVERFLOW_ERROR;
    240     return UCOL_EQUAL;
    241   }
    242   *status = U_ZERO_ERROR;
    243   sState[0] = 0; sState[1] = 0;
    244   tState[0] = 0; tState[1] = 0;
    245   while(sSize == pieceSize && tSize == pieceSize && partialSKResult == 0) {
    246     uiter_setString(&sIter, source, sLen);
    247     uiter_setString(&tIter, target, tLen);
    248     sSize = ucol_nextSortKeyPart(coll, &sIter, sState, sBuf, pieceSize, status);
    249     tSize = ucol_nextSortKeyPart(coll, &tIter, tState, tBuf, pieceSize, status);
    250 
    251     if(sState[0] != 0 || tState[0] != 0) {
    252       /*log_verbose("State != 0 : %08X %08X\n", sState[0], tState[0]);*/
    253     }
    254     /*log_verbose("%i ", i++);*/
    255 
    256     partialSKResult = memcmp(sBuf, tBuf, pieceSize);
    257   }
    258 
    259   if(partialSKResult < 0) {
    260       return UCOL_LESS;
    261   } else if(partialSKResult > 0) {
    262     return UCOL_GREATER;
    263   } else {
    264     return UCOL_EQUAL;
    265   }
    266 }
    267 
    268 static void doTestVariant(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
    269 {
    270     int32_t sortklen1, sortklen2, sortklenmax, sortklenmin;
    271     int temp=0, gSortklen1=0,gSortklen2=0;
    272     UCollationResult compareResult, compareResulta, keyResult, compareResultIter = result;
    273     uint8_t *sortKey1, *sortKey2, *sortKey1a, *sortKey2a;
    274     uint32_t sLen = u_strlen(source);
    275     uint32_t tLen = u_strlen(target);
    276     char buffer[256];
    277     uint32_t len;
    278     UErrorCode status = U_ZERO_ERROR;
    279     UColAttributeValue norm = ucol_getAttribute(myCollation, UCOL_NORMALIZATION_MODE, &status);
    280 
    281     UCharIterator sIter, tIter;
    282 
    283     compareResult  = ucol_strcoll(myCollation, source, sLen, target, tLen);
    284     if (compareResult != result) {
    285         log_err("ucol_strcoll with explicit length returned wrong result (%i exp. %i): %s, %s\n",
    286             compareResult, result, aescstrdup(source,-1), aescstrdup(target,-1));
    287     }
    288     compareResulta = ucol_strcoll(myCollation, source, -1,   target, -1);
    289     if (compareResulta != result) {
    290         log_err("ucol_strcoll with null terminated strings returned wrong result (%i exp. %i): %s, %s\n",
    291             compareResult, result, aescstrdup(source,-1), aescstrdup(target,-1));
    292     }
    293 
    294     uiter_setString(&sIter, source, sLen);
    295     uiter_setString(&tIter, target, tLen);
    296     compareResultIter = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
    297     if(compareResultIter != result) {
    298         log_err("different results in iterative comparison for UTF-16 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
    299     }
    300 
    301     /* convert the strings to UTF-8 and do try comparing with char iterator and ucol_strcollUTF8 */
    302     {
    303         char utf8Source[256], utf8Target[256];
    304         int32_t utf8SourceLen = 0, utf8TargetLen = 0;
    305 
    306         u_strToUTF8(utf8Source, 256, &utf8SourceLen, source, sLen, &status);
    307         if(U_FAILURE(status)) { /* probably buffer is not big enough */
    308             log_verbose("Src UTF-8 buffer too small! Will not compare!\n");
    309         } else {
    310             u_strToUTF8(utf8Target, 256, &utf8TargetLen, target, tLen, &status);
    311             if(U_SUCCESS(status)) {
    312                 {
    313                     /* ucol_strcollUTF8 */
    314                     compareResulta = ucol_strcollUTF8(myCollation, utf8Source, utf8SourceLen, utf8Target, utf8TargetLen, &status);
    315                     if (U_FAILURE(status)) {
    316                         log_err("Error in ucol_strcollUTF8 with explicit length\n");
    317                         status = U_ZERO_ERROR;
    318                     } else if (compareResulta != result) {
    319                         log_err("ucol_strcollUTF8 with explicit length returned wrong result (%i exp. %i): %s, %s\n",
    320                             compareResulta, result, aescstrdup(source,-1), aescstrdup(target,-1));
    321                     }
    322                     compareResulta = ucol_strcollUTF8(myCollation, utf8Source, -1, utf8Target, -1, &status);
    323                     if (U_FAILURE(status)) {
    324                         log_err("Error in ucol_strcollUTF8 with null terminated strings\n");
    325                         status = U_ZERO_ERROR;
    326                     } else if (compareResulta != result) {
    327                         log_err("ucol_strcollUTF8 with null terminated strings returned wrong result (%i exp. %i): %s, %s\n",
    328                             compareResulta, result, aescstrdup(source,-1), aescstrdup(target,-1));
    329                     }
    330                 }
    331 
    332                 {
    333                     /* char iterator over UTF8 */
    334                     UCollationResult compareResultUTF8Iter = result, compareResultUTF8IterNorm = result;
    335 
    336                     uiter_setUTF8(&sIter, utf8Source, utf8SourceLen);
    337                     uiter_setUTF8(&tIter, utf8Target, utf8TargetLen);
    338                     compareResultUTF8Iter = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
    339 
    340                     ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    341                     sIter.move(&sIter, 0, UITER_START);
    342                     tIter.move(&tIter, 0, UITER_START);
    343                     compareResultUTF8IterNorm = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
    344 
    345                     ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
    346                     if(compareResultUTF8Iter != compareResultIter) {
    347                         log_err("different results in iterative comparison for UTF-16 and UTF-8 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
    348                     }
    349                     if(compareResultUTF8Iter != compareResultUTF8IterNorm) {
    350                         log_err("different results in iterative when normalization is turned on with UTF-8 strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
    351                     }
    352                 }
    353             } else {
    354                 log_verbose("Target UTF-8 buffer too small! Did not compare!\n");
    355             }
    356             if(U_FAILURE(status)) {
    357                 log_verbose("UTF-8 strcoll failed! Ignoring result\n");
    358             }
    359         }
    360     }
    361 
    362     /* testing the partial sortkeys */
    363     if(1) { /*!QUICK*/
    364       int32_t i = 0;
    365       int32_t partialSizes[] = { 3, 1, 2, 4, 8, 20, 80 }; /* just size 3 in the quick mode */
    366       int32_t partialSizesSize = 1;
    367       if(getTestOption(QUICK_OPTION) <= 0) {
    368         partialSizesSize = 7;
    369       }
    370       /*log_verbose("partial sortkey test piecesize=");*/
    371       for(i = 0; i < partialSizesSize; i++) {
    372         UCollationResult partialSKResult = result, partialNormalizedSKResult = result;
    373         /*log_verbose("%i ", partialSizes[i]);*/
    374 
    375         partialSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
    376         if(partialSKResult != result) {
    377           log_err("Partial sortkey comparison returned wrong result (%i exp. %i): %s, %s (size %i)\n",
    378             partialSKResult, result,
    379             aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
    380         }
    381 
    382         if(getTestOption(QUICK_OPTION) <= 0 && norm != UCOL_ON) {
    383           /*log_verbose("N ");*/
    384           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    385           partialNormalizedSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
    386           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
    387           if(partialSKResult != partialNormalizedSKResult) {
    388             log_err("Partial sortkey comparison gets different result when normalization is on: %s, %s (size %i)\n",
    389               aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
    390           }
    391         }
    392       }
    393       /*log_verbose("\n");*/
    394     }
    395 
    396     sortklen1=ucol_getSortKey(myCollation, source, sLen,  NULL, 0);
    397     sortklen2=ucol_getSortKey(myCollation, target, tLen,  NULL, 0);
    398 
    399     sortklenmax = (sortklen1>sortklen2?sortklen1:sortklen2);
    400     sortklenmin = (sortklen1<sortklen2?sortklen1:sortklen2);
    401 
    402     sortKey1 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    403     sortKey1a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    404     ucol_getSortKey(myCollation, source, sLen, sortKey1,  sortklen1+1);
    405     ucol_getSortKey(myCollation, source, -1,   sortKey1a, sortklen1+1);
    406 
    407     sortKey2 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    408     sortKey2a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    409     ucol_getSortKey(myCollation, target, tLen, sortKey2,  sortklen2+1);
    410     ucol_getSortKey(myCollation, target, -1,   sortKey2a, sortklen2+1);
    411 
    412     /* Check that sort key generated with null terminated string is identical  */
    413     /*  to that generted with a length specified.                              */
    414     if (uprv_strcmp((const char *)sortKey1, (const char *)sortKey1a) != 0 ||
    415         uprv_strcmp((const char *)sortKey2, (const char *)sortKey2a) != 0 ) {
    416         log_err("Sort Keys from null terminated and explicit length strings differ.\n");
    417     }
    418 
    419     /*memcmp(sortKey1, sortKey2,sortklenmax);*/
    420     temp= uprv_strcmp((const char *)sortKey1, (const char *)sortKey2);
    421     gSortklen1 = uprv_strlen((const char *)sortKey1)+1;
    422     gSortklen2 = uprv_strlen((const char *)sortKey2)+1;
    423     if(sortklen1 != gSortklen1){
    424         log_err("SortKey length does not match Expected: %i Got: %i\n",sortklen1, gSortklen1);
    425         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey1, buffer, &len));
    426     }
    427     if(sortklen2!= gSortklen2){
    428         log_err("SortKey length does not match Expected: %i Got: %i\n", sortklen2, gSortklen2);
    429         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey2, buffer, &len));
    430     }
    431 
    432     if(temp < 0) {
    433         keyResult=UCOL_LESS;
    434     }
    435     else if(temp > 0) {
    436         keyResult= UCOL_GREATER;
    437     }
    438     else {
    439         keyResult = UCOL_EQUAL;
    440     }
    441     reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResultIter, result );
    442     free(sortKey1);
    443     free(sortKey2);
    444     free(sortKey1a);
    445     free(sortKey2a);
    446 
    447 }
    448 
    449 void doTest(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
    450 {
    451   if(myCollation) {
    452     doTestVariant(myCollation, source, target, result);
    453     if(result == UCOL_LESS) {
    454       doTestVariant(myCollation, target, source, UCOL_GREATER);
    455     } else if(result == UCOL_GREATER) {
    456       doTestVariant(myCollation, target, source, UCOL_LESS);
    457     } else {
    458       doTestVariant(myCollation, target, source, UCOL_EQUAL);
    459     }
    460   } else {
    461     log_data_err("No collator! Any data around?\n");
    462   }
    463 }
    464 
    465 
    466 /**
    467  * Return an integer array containing all of the collation orders
    468  * returned by calls to next on the specified iterator
    469  */
    470 OrderAndOffset* getOrders(UCollationElements *iter, int32_t *orderLength)
    471 {
    472     UErrorCode status;
    473     int32_t order;
    474     int32_t maxSize = 100;
    475     int32_t size = 0;
    476     int32_t offset = ucol_getOffset(iter);
    477     OrderAndOffset *temp;
    478     OrderAndOffset *orders =(OrderAndOffset *)malloc(sizeof(OrderAndOffset) * maxSize);
    479     status= U_ZERO_ERROR;
    480 
    481 
    482     while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER)
    483     {
    484         if (size == maxSize)
    485         {
    486             maxSize *= 2;
    487             temp = (OrderAndOffset *)malloc(sizeof(OrderAndOffset) * maxSize);
    488 
    489             memcpy(temp, orders, size * sizeof(OrderAndOffset));
    490             free(orders);
    491             orders = temp;
    492 
    493         }
    494 
    495         orders[size].order  = order;
    496         orders[size].offset = offset;
    497 
    498         offset = ucol_getOffset(iter);
    499         size += 1;
    500     }
    501 
    502     if (maxSize > size && size > 0)
    503     {
    504         temp = (OrderAndOffset *)malloc(sizeof(OrderAndOffset) * size);
    505 
    506         memcpy(temp, orders, size * sizeof(OrderAndOffset));
    507         free(orders);
    508         orders = temp;
    509 
    510 
    511     }
    512 
    513     *orderLength = size;
    514     return orders;
    515 }
    516 
    517 
    518 void
    519 backAndForth(UCollationElements *iter)
    520 {
    521     /* Run through the iterator forwards and stick it into an array */
    522     int32_t idx, o;
    523     UErrorCode status = U_ZERO_ERROR;
    524     int32_t orderLength = 0;
    525     OrderAndOffset *orders = getOrders(iter, &orderLength);
    526 
    527 
    528     /* Now go through it backwards and make sure we get the same values */
    529     idx = orderLength;
    530     ucol_reset(iter);
    531 
    532     /* synwee : changed */
    533     while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) {
    534 #if TEST_OFFSETS
    535       int32_t offset =
    536 #endif
    537         ucol_getOffset(iter);
    538 
    539       idx -= 1;
    540       if (o != orders[idx].order) {
    541         if (o == 0)
    542           idx ++;
    543         else {
    544           while (idx > 0 && orders[-- idx].order == 0) {
    545             /* nothing... */
    546           }
    547 
    548           if (o != orders[idx].order) {
    549               log_err("Mismatched order at index %d: 0x%8.8X vs. 0x%8.8X\n", idx,
    550                 orders[idx].order, o);
    551             goto bail;
    552           }
    553         }
    554       }
    555 
    556 #if TEST_OFFSETS
    557       if (offset != orders[idx].offset) {
    558         log_err("Mismatched offset at index %d: %d vs. %d\n", idx,
    559             orders[idx].offset, offset);
    560         goto bail;
    561       }
    562 #endif
    563 
    564     }
    565 
    566     while (idx != 0 && orders[idx - 1].order == 0) {
    567       idx -= 1;
    568     }
    569 
    570     if (idx != 0) {
    571         log_err("Didn't get back to beginning - index is %d\n", idx);
    572 
    573         ucol_reset(iter);
    574         log_err("\nnext: ");
    575 
    576         if ((o = ucol_next(iter, &status)) != UCOL_NULLORDER) {
    577             log_err("Error at %x\n", o);
    578         }
    579 
    580         log_err("\nprev: ");
    581 
    582         if ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) {
    583             log_err("Error at %x\n", o);
    584         }
    585 
    586         log_verbose("\n");
    587     }
    588 
    589 bail:
    590     free(orders);
    591 }
    592 
    593 void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result) {
    594   UChar t1[2048] = {0};
    595   UChar t2[2048] = {0};
    596   UCollationElements *iter;
    597   UErrorCode status = U_ZERO_ERROR;
    598 
    599   uint32_t i = 0, j = 0;
    600   log_verbose("testing sequence:\n");
    601   for(i = 0; i < size; i++) {
    602     log_verbose("%s\n", s[i]);
    603   }
    604 
    605   iter = ucol_openElements(coll, t1, u_strlen(t1), &status);
    606   if (U_FAILURE(status)) {
    607     log_err("Creation of iterator failed\n");
    608   }
    609   for(i = 0; i < size-1; i++) {
    610     for(j = i+1; j < size; j++) {
    611       u_unescape(s[i], t1, 2048);
    612       u_unescape(s[j], t2, 2048);
    613       doTest(coll, t1, t2, result);
    614       /* synwee : added collation element iterator test */
    615       ucol_setText(iter, t1, u_strlen(t1), &status);
    616       backAndForth(iter);
    617       ucol_setText(iter, t2, u_strlen(t2), &status);
    618       backAndForth(iter);
    619     }
    620   }
    621   ucol_closeElements(iter);
    622 }
    623 
    624 void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size) {
    625   genericOrderingTestWithResult(coll, s, size, UCOL_LESS);
    626 }
    627 
    628 void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size) {
    629   UErrorCode status = U_ZERO_ERROR;
    630   UCollator *coll = ucol_open(locale, &status);
    631 
    632   log_verbose("Locale starter for %s\n", locale);
    633 
    634   if(U_SUCCESS(status)) {
    635     genericOrderingTest(coll, s, size);
    636   } else if(status == U_FILE_ACCESS_ERROR) {
    637     log_data_err("Is your data around?\n");
    638     return;
    639   } else {
    640     log_err("Unable to open collator for locale %s\n", locale);
    641   }
    642   ucol_close(coll);
    643 }
    644 
    645 void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result) {
    646   UErrorCode status = U_ZERO_ERROR;
    647   UCollator *coll = ucol_open(locale, &status);
    648 
    649   log_verbose("Locale starter for %s\n", locale);
    650 
    651   if(U_SUCCESS(status)) {
    652     genericOrderingTestWithResult(coll, s, size, result);
    653   } else if(status == U_FILE_ACCESS_ERROR) {
    654     log_data_err("Is your data around?\n");
    655     return;
    656   } else {
    657     log_err("Unable to open collator for locale %s\n", locale);
    658   }
    659   ucol_close(coll);
    660 }
    661 
    662 /* currently not used with options */
    663 void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
    664   UErrorCode status = U_ZERO_ERROR;
    665   UChar rlz[RULE_BUFFER_LEN] = { 0 };
    666   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
    667   uint32_t i;
    668 
    669   UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
    670 
    671   log_verbose("Rules starter for %s\n", rules);
    672 
    673   if(U_SUCCESS(status)) {
    674     log_verbose("Setting attributes\n");
    675     for(i = 0; i < attsize; i++) {
    676       ucol_setAttribute(coll, attrs[i], values[i], &status);
    677     }
    678 
    679     genericOrderingTestWithResult(coll, s, size, result);
    680   } else {
    681     log_err_status(status, "Unable to open collator with rules %s\n", rules);
    682   }
    683   ucol_close(coll);
    684 }
    685 
    686 void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
    687   UErrorCode status = U_ZERO_ERROR;
    688   uint32_t i;
    689 
    690   UCollator *coll = ucol_open(locale, &status);
    691 
    692   log_verbose("Locale starter for %s\n", locale);
    693 
    694   if(U_SUCCESS(status)) {
    695 
    696     log_verbose("Setting attributes\n");
    697     for(i = 0; i < attsize; i++) {
    698       ucol_setAttribute(coll, attrs[i], values[i], &status);
    699     }
    700 
    701     genericOrderingTestWithResult(coll, s, size, result);
    702   } else {
    703     log_err_status(status, "Unable to open collator for locale %s\n", locale);
    704   }
    705   ucol_close(coll);
    706 }
    707 
    708 void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize) {
    709   genericLocaleStarterWithOptionsAndResult(locale, s, size, attrs, values, attsize, UCOL_LESS);
    710 }
    711 
    712 void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result) {
    713   UErrorCode status = U_ZERO_ERROR;
    714   UChar rlz[RULE_BUFFER_LEN] = { 0 };
    715   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
    716 
    717   UCollator *coll = NULL;
    718   coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
    719   log_verbose("Rules starter for %s\n", rules);
    720 
    721   if(U_SUCCESS(status)) {
    722     genericOrderingTestWithResult(coll, s, size, result);
    723     ucol_close(coll);
    724   } else if(status == U_FILE_ACCESS_ERROR) {
    725     log_data_err("Is your data around?\n");
    726   } else {
    727     log_err("Unable to open collator with rules %s\n", rules);
    728   }
    729 }
    730 
    731 void genericRulesStarter(const char *rules, const char * const s[], uint32_t size) {
    732   genericRulesStarterWithResult(rules, s, size, UCOL_LESS);
    733 }
    734 
    735 static void TestTertiary()
    736 {
    737     int32_t len,i;
    738     UCollator *myCollation;
    739     UErrorCode status=U_ZERO_ERROR;
    740     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    741     UChar rules[sizeof(str)];
    742     len = strlen(str);
    743     u_uastrcpy(rules, str);
    744 
    745     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
    746     if(U_FAILURE(status)){
    747         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    748         return;
    749     }
    750 
    751     ucol_setStrength(myCollation, UCOL_TERTIARY);
    752     for (i = 0; i < 17 ; i++)
    753     {
    754         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    755     }
    756     ucol_close(myCollation);
    757     myCollation = 0;
    758 }
    759 
    760 static void TestPrimary( )
    761 {
    762     int32_t len,i;
    763     UCollator *myCollation;
    764     UErrorCode status=U_ZERO_ERROR;
    765     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    766     UChar rules[sizeof(str)];
    767     len = strlen(str);
    768     u_uastrcpy(rules, str);
    769 
    770     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    771     if(U_FAILURE(status)){
    772         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    773         return;
    774     }
    775     ucol_setStrength(myCollation, UCOL_PRIMARY);
    776 
    777     for (i = 17; i < 26 ; i++)
    778     {
    779 
    780         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    781     }
    782     ucol_close(myCollation);
    783     myCollation = 0;
    784 }
    785 
    786 static void TestSecondary()
    787 {
    788     int32_t i;
    789     int32_t len;
    790     UCollator *myCollation;
    791     UErrorCode status=U_ZERO_ERROR;
    792     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    793     UChar rules[sizeof(str)];
    794     len = strlen(str);
    795     u_uastrcpy(rules, str);
    796 
    797     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    798     if(U_FAILURE(status)){
    799         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    800         return;
    801     }
    802     ucol_setStrength(myCollation, UCOL_SECONDARY);
    803     for (i = 26; i < 34 ; i++)
    804     {
    805         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    806     }
    807     ucol_close(myCollation);
    808     myCollation = 0;
    809 }
    810 
    811 static void TestIdentical()
    812 {
    813     int32_t i;
    814     int32_t len;
    815     UCollator *myCollation;
    816     UErrorCode status=U_ZERO_ERROR;
    817     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    818     UChar rules[sizeof(str)];
    819     len = strlen(str);
    820     u_uastrcpy(rules, str);
    821 
    822     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_IDENTICAL, NULL,&status);
    823     if(U_FAILURE(status)){
    824         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    825         return;
    826     }
    827     for(i= 34; i<37; i++)
    828     {
    829         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    830     }
    831     ucol_close(myCollation);
    832     myCollation = 0;
    833 }
    834 
    835 static void TestExtra()
    836 {
    837     int32_t i, j;
    838     int32_t len;
    839     UCollator *myCollation;
    840     UErrorCode status = U_ZERO_ERROR;
    841     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    842     UChar rules[sizeof(str)];
    843     len = strlen(str);
    844     u_uastrcpy(rules, str);
    845 
    846     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    847     if(U_FAILURE(status)){
    848         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    849         return;
    850     }
    851     ucol_setStrength(myCollation, UCOL_TERTIARY);
    852     for (i = 0; i < COUNT_TEST_CASES-1 ; i++)
    853     {
    854         for (j = i + 1; j < COUNT_TEST_CASES; j += 1)
    855         {
    856 
    857             doTest(myCollation, testCases[i], testCases[j], UCOL_LESS);
    858         }
    859     }
    860     ucol_close(myCollation);
    861     myCollation = 0;
    862 }
    863 
    864 static void TestJB581(void)
    865 {
    866     int32_t     bufferLen   = 0;
    867     UChar       source      [100];
    868     UChar       target      [100];
    869     UCollationResult result     = UCOL_EQUAL;
    870     uint8_t     sourceKeyArray  [100];
    871     uint8_t     targetKeyArray  [100];
    872     int32_t     sourceKeyOut    = 0,
    873                 targetKeyOut    = 0;
    874     UCollator   *myCollator = 0;
    875     UErrorCode status = U_ZERO_ERROR;
    876 
    877     /*u_uastrcpy(source, "This is a test.");*/
    878     /*u_uastrcpy(target, "THISISATEST.");*/
    879     u_uastrcpy(source, "THISISATEST.");
    880     u_uastrcpy(target, "Thisisatest.");
    881 
    882     myCollator = ucol_open("en_US", &status);
    883     if (U_FAILURE(status)){
    884         log_err_status(status, "ERROR: Failed to create the collator : %s\n", u_errorName(status));
    885         return;
    886     }
    887     result = ucol_strcoll(myCollator, source, -1, target, -1);
    888     /* result is 1, secondary differences only for ignorable space characters*/
    889     if (result != 1)
    890     {
    891         log_err("Comparing two strings with only secondary differences in C failed.\n");
    892     }
    893     /* To compare them with just primary differences */
    894     ucol_setStrength(myCollator, UCOL_PRIMARY);
    895     result = ucol_strcoll(myCollator, source, -1, target, -1);
    896     /* result is 0 */
    897     if (result != 0)
    898     {
    899         log_err("Comparing two strings with no differences in C failed.\n");
    900     }
    901     /* Now, do the same comparison with keys */
    902     sourceKeyOut = ucol_getSortKey(myCollator, source, -1, sourceKeyArray, 100);
    903     targetKeyOut = ucol_getSortKey(myCollator, target, -1, targetKeyArray, 100);
    904     bufferLen = ((targetKeyOut > 100) ? 100 : targetKeyOut);
    905     if (memcmp(sourceKeyArray, targetKeyArray, bufferLen) != 0)
    906     {
    907         log_err("Comparing two strings with sort keys in C failed.\n");
    908     }
    909     ucol_close(myCollator);
    910 }
    911 
    912 static void TestJB1401(void)
    913 {
    914     UCollator     *myCollator = 0;
    915     UErrorCode     status = U_ZERO_ERROR;
    916     static UChar   NFD_UnsafeStartChars[] = {
    917         0x0f73,          /* Tibetan Vowel Sign II */
    918         0x0f75,          /* Tibetan Vowel Sign UU */
    919         0x0f81,          /* Tibetan Vowel Sign Reversed II */
    920             0
    921     };
    922     int            i;
    923 
    924 
    925     myCollator = ucol_open("en_US", &status);
    926     if (U_FAILURE(status)){
    927         log_err_status(status, "ERROR: Failed to create the collator : %s\n", u_errorName(status));
    928         return;
    929     }
    930     ucol_setAttribute(myCollator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    931     if (U_FAILURE(status)){
    932         log_err("ERROR: Failed to set normalization mode ON for collator.\n");
    933         return;
    934     }
    935 
    936     for (i=0; ; i++) {
    937         UChar    c;
    938         UChar    X[4];
    939         UChar    Y[20];
    940         UChar    Z[20];
    941 
    942         /*  Get the next funny character to be tested, and set up the
    943          *  three test strings X, Y, Z, consisting of an A-grave + test char,
    944          *    in original form, NFD, and then NFC form.
    945          */
    946         c = NFD_UnsafeStartChars[i];
    947         if (c==0) {break;}
    948 
    949         X[0]=0xC0; X[1]=c; X[2]=0;   /* \u00C0 is A Grave*/
    950 
    951         unorm_normalize(X, -1, UNORM_NFD, 0, Y, 20, &status);
    952         unorm_normalize(Y, -1, UNORM_NFC, 0, Z, 20, &status);
    953         if (U_FAILURE(status)){
    954             log_err("ERROR: Failed to normalize test of character %x\n", c);
    955             return;
    956         }
    957 
    958         /* Collation test.  All three strings should be equal.
    959          *   doTest does both strcoll and sort keys, with params in both orders.
    960          */
    961         doTest(myCollator, X, Y, UCOL_EQUAL);
    962         doTest(myCollator, X, Z, UCOL_EQUAL);
    963         doTest(myCollator, Y, Z, UCOL_EQUAL);
    964 
    965         /* Run collation element iterators over the three strings.  Results should be same for each.
    966          */
    967         {
    968             UCollationElements *ceiX, *ceiY, *ceiZ;
    969             int32_t             ceX,   ceY,   ceZ;
    970             int                 j;
    971 
    972             ceiX = ucol_openElements(myCollator, X, -1, &status);
    973             ceiY = ucol_openElements(myCollator, Y, -1, &status);
    974             ceiZ = ucol_openElements(myCollator, Z, -1, &status);
    975             if (U_FAILURE(status)) {
    976                 log_err("ERROR: uucol_openElements failed.\n");
    977                 return;
    978             }
    979 
    980             for (j=0;; j++) {
    981                 ceX = ucol_next(ceiX, &status);
    982                 ceY = ucol_next(ceiY, &status);
    983                 ceZ = ucol_next(ceiZ, &status);
    984                 if (U_FAILURE(status)) {
    985                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
    986                     break;
    987                 }
    988                 if (ceX != ceY || ceY != ceZ) {
    989                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
    990                     break;
    991                 }
    992                 if (ceX == UCOL_NULLORDER) {
    993                     break;
    994                 }
    995             }
    996             ucol_closeElements(ceiX);
    997             ucol_closeElements(ceiY);
    998             ucol_closeElements(ceiZ);
    999         }
   1000     }
   1001     ucol_close(myCollator);
   1002 }
   1003 
   1004 
   1005 
   1006 /**
   1007 * Tests the [variable top] tag in rule syntax. Since the default [alternate]
   1008 * tag has the value shifted, any codepoints before [variable top] should give
   1009 * a primary ce of 0.
   1010 */
   1011 static void TestVariableTop(void)
   1012 {
   1013     static const char       str[]          = "&z = [variable top]";
   1014           int         len          = strlen(str);
   1015           UChar      rules[sizeof(str)];
   1016           UCollator  *myCollation;
   1017           UCollator  *enCollation;
   1018           UErrorCode  status       = U_ZERO_ERROR;
   1019           UChar       source[1];
   1020           UChar       ch;
   1021           uint8_t     result[20];
   1022           uint8_t     expected[20];
   1023 
   1024     u_uastrcpy(rules, str);
   1025 
   1026     enCollation = ucol_open("en_US", &status);
   1027     if (U_FAILURE(status)) {
   1028         log_err_status(status, "ERROR: in creation of collator :%s\n",
   1029                 myErrorName(status));
   1030         return;
   1031     }
   1032     myCollation = ucol_openRules(rules, len, UCOL_OFF,
   1033                                  UCOL_PRIMARY,NULL, &status);
   1034     if (U_FAILURE(status)) {
   1035         ucol_close(enCollation);
   1036         log_err("ERROR: in creation of rule based collator :%s\n",
   1037                 myErrorName(status));
   1038         return;
   1039     }
   1040 
   1041     ucol_setStrength(enCollation, UCOL_PRIMARY);
   1042     ucol_setAttribute(enCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
   1043                       &status);
   1044     ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
   1045                       &status);
   1046 
   1047     if (ucol_getAttribute(myCollation, UCOL_ALTERNATE_HANDLING, &status) !=
   1048         UCOL_SHIFTED || U_FAILURE(status)) {
   1049         log_err("ERROR: ALTERNATE_HANDLING value can not be set to SHIFTED\n");
   1050     }
   1051 
   1052     uprv_memset(expected, 0, 20);
   1053 
   1054     /* space is supposed to be a variable */
   1055     source[0] = ' ';
   1056     len = ucol_getSortKey(enCollation, source, 1, result,
   1057                           sizeof(result));
   1058 
   1059     if (uprv_memcmp(expected, result, len) != 0) {
   1060         log_err("ERROR: SHIFTED alternate does not return 0 for primary of space\n");
   1061     }
   1062 
   1063     ch = 'a';
   1064     while (ch < 'z') {
   1065         source[0] = ch;
   1066         len = ucol_getSortKey(myCollation, source, 1, result,
   1067                               sizeof(result));
   1068         if (uprv_memcmp(expected, result, len) != 0) {
   1069             log_err("ERROR: SHIFTED alternate does not return 0 for primary of %c\n",
   1070                     ch);
   1071         }
   1072         ch ++;
   1073     }
   1074 
   1075     ucol_close(enCollation);
   1076     ucol_close(myCollation);
   1077     enCollation = NULL;
   1078     myCollation = NULL;
   1079 }
   1080 
   1081 /**
   1082   * Tests surrogate support.
   1083   * NOTE: This test used \\uD801\\uDC01 pair, which is now assigned to Desseret
   1084   * Therefore, another (unassigned) code point was used for this test.
   1085   */
   1086 static void TestSurrogates(void)
   1087 {
   1088     static const char       str[]          =
   1089                               "&z<'\\uD800\\uDC00'<'\\uD800\\uDC0A\\u0308'<A";
   1090           int         len          = strlen(str);
   1091           int         rlen         = 0;
   1092           UChar      rules[sizeof(str)];
   1093           UCollator  *myCollation;
   1094           UCollator  *enCollation;
   1095           UErrorCode  status       = U_ZERO_ERROR;
   1096           UChar       source[][4]    =
   1097           {{'z', 0, 0}, {0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {0xD800, 0xDC02}};
   1098           UChar       target[][4]    =
   1099           {{0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {'A', 0, 0}, {0xD800, 0xDC03}};
   1100           int         count        = 0;
   1101           uint8_t enresult[20], myresult[20];
   1102           int enlen, mylen;
   1103 
   1104     /* tests for open rules with surrogate rules */
   1105     rlen = u_unescape(str, rules, len);
   1106 
   1107     enCollation = ucol_open("en_US", &status);
   1108     if (U_FAILURE(status)) {
   1109         log_err_status(status, "ERROR: in creation of collator :%s\n",
   1110                 myErrorName(status));
   1111         return;
   1112     }
   1113     myCollation = ucol_openRules(rules, rlen, UCOL_OFF,
   1114                                  UCOL_TERTIARY,NULL, &status);
   1115     if (U_FAILURE(status)) {
   1116         ucol_close(enCollation);
   1117         log_err("ERROR: in creation of rule based collator :%s\n",
   1118                 myErrorName(status));
   1119         return;
   1120     }
   1121 
   1122     /*
   1123     this test is to verify the supplementary sort key order in the english
   1124     collator
   1125     */
   1126     log_verbose("start of english collation supplementary characters test\n");
   1127     while (count < 2) {
   1128         doTest(enCollation, source[count], target[count], UCOL_LESS);
   1129         count ++;
   1130     }
   1131     doTest(enCollation, source[count], target[count], UCOL_GREATER);
   1132 
   1133     log_verbose("start of tailored collation supplementary characters test\n");
   1134     count = 0;
   1135     /* tests getting collation elements for surrogates for tailored rules */
   1136     while (count < 4) {
   1137         doTest(myCollation, source[count], target[count], UCOL_LESS);
   1138         count ++;
   1139     }
   1140 
   1141     /* tests that \uD800\uDC02 still has the same value, not changed */
   1142     enlen = ucol_getSortKey(enCollation, source[3], 2, enresult, 20);
   1143     mylen = ucol_getSortKey(myCollation, source[3], 2, myresult, 20);
   1144     if (enlen != mylen ||
   1145         uprv_memcmp(enresult, myresult, enlen) != 0) {
   1146         log_verbose("Failed : non-tailored supplementary characters should have the same value\n");
   1147     }
   1148 
   1149     ucol_close(enCollation);
   1150     ucol_close(myCollation);
   1151     enCollation = NULL;
   1152     myCollation = NULL;
   1153 }
   1154 
   1155 /*
   1156  *### TODO: Add more invalid rules to test all different scenarios.
   1157  *
   1158  */
   1159 static void
   1160 TestInvalidRules(){
   1161 #define MAX_ERROR_STATES 2
   1162 
   1163     static const char* rulesArr[MAX_ERROR_STATES] = {
   1164         "& C < ch, cH, Ch[this should fail]<d",
   1165         "& C < ch, cH, & Ch[variable top]"
   1166     };
   1167     static const char* preContextArr[MAX_ERROR_STATES] = {
   1168         "his should fail",
   1169         "& C < ch, cH, ",
   1170 
   1171     };
   1172     static const char* postContextArr[MAX_ERROR_STATES] = {
   1173         "<d",
   1174         " Ch[variable t"
   1175     };
   1176     int i;
   1177 
   1178     for(i = 0;i<MAX_ERROR_STATES;i++){
   1179         UChar rules[1000]       = { '\0' };
   1180         UChar preContextExp[1000]  = { '\0' };
   1181         UChar postContextExp[1000] = { '\0' };
   1182         UParseError parseError;
   1183         UErrorCode status = U_ZERO_ERROR;
   1184         UCollator* coll=0;
   1185         u_charsToUChars(rulesArr[i],rules,uprv_strlen(rulesArr[i])+1);
   1186         u_charsToUChars(preContextArr[i],preContextExp,uprv_strlen(preContextArr[i])+1);
   1187         u_charsToUChars(postContextArr[i],postContextExp,uprv_strlen(postContextArr[i])+1);
   1188         /* clean up stuff in parseError */
   1189         u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
   1190         u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
   1191         /* open the rules and test */
   1192         coll = ucol_openRules(rules,u_strlen(rules),UCOL_OFF,UCOL_DEFAULT_STRENGTH,&parseError,&status);
   1193         if(u_strcmp(parseError.preContext,preContextExp)!=0){
   1194             log_err_status(status, "preContext in UParseError for ucol_openRules does not match\n");
   1195         }
   1196         if(u_strcmp(parseError.postContext,postContextExp)!=0){
   1197             log_err_status(status, "postContext in UParseError for ucol_openRules does not match\n");
   1198         }
   1199     }
   1200 }
   1201 
   1202 static void
   1203 TestJitterbug1098(){
   1204     UChar rule[1000];
   1205     UCollator* c1 = NULL;
   1206     UErrorCode status = U_ZERO_ERROR;
   1207     UParseError parseError;
   1208     char preContext[200]={0};
   1209     char postContext[200]={0};
   1210     int i=0;
   1211     const char* rules[] = {
   1212          "&''<\\\\",
   1213          "&\\'<\\\\",
   1214          "&\\\"<'\\'",
   1215          "&'\"'<\\'",
   1216          '\0'
   1217 
   1218     };
   1219     const UCollationResult results1098[] = {
   1220         UCOL_LESS,
   1221         UCOL_LESS,
   1222         UCOL_LESS,
   1223         UCOL_LESS,
   1224     };
   1225     const UChar input[][2]= {
   1226         {0x0027,0x005c},
   1227         {0x0027,0x005c},
   1228         {0x0022,0x005c},
   1229         {0x0022,0x0027},
   1230     };
   1231     UChar X[2] ={0};
   1232     UChar Y[2] ={0};
   1233     u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
   1234     u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
   1235     for(;rules[i]!=0;i++){
   1236         u_uastrcpy(rule, rules[i]);
   1237         c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, &parseError, &status);
   1238         if(U_FAILURE(status)){
   1239             log_err_status(status, "Could not parse the rules syntax. Error: %s\n", u_errorName(status));
   1240 
   1241             if (status == U_PARSE_ERROR) {
   1242                 u_UCharsToChars(parseError.preContext,preContext,20);
   1243                 u_UCharsToChars(parseError.postContext,postContext,20);
   1244                 log_verbose("\n\tPre-Context: %s \n\tPost-Context:%s \n",preContext,postContext);
   1245             }
   1246 
   1247             return;
   1248         }
   1249         X[0] = input[i][0];
   1250         Y[0] = input[i][1];
   1251         doTest(c1,X,Y,results1098[i]);
   1252         ucol_close(c1);
   1253     }
   1254 }
   1255 
   1256 static void
   1257 TestFCDCrash(void) {
   1258     static const char *test[] = {
   1259     "Gr\\u00F6\\u00DFe",
   1260     "Grossist"
   1261     };
   1262 
   1263     UErrorCode status = U_ZERO_ERROR;
   1264     UCollator *coll = ucol_open("es", &status);
   1265     if(U_FAILURE(status)) {
   1266         log_err_status(status, "Couldn't open collator -> %s\n", u_errorName(status));
   1267         return;
   1268     }
   1269     ucol_close(coll);
   1270     coll = NULL;
   1271     ctest_resetICU();
   1272     coll = ucol_open("de_DE", &status);
   1273     if(U_FAILURE(status)) {
   1274         log_err_status(status, "Couldn't open collator -> %s\n", u_errorName(status));
   1275         return;
   1276     }
   1277     ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
   1278     genericOrderingTest(coll, test, 2);
   1279     ucol_close(coll);
   1280 }
   1281 
   1282 /*static UBool
   1283 find(UEnumeration* list, const char* str, UErrorCode* status){
   1284     const char* value = NULL;
   1285     int32_t length=0;
   1286     if(U_FAILURE(*status)){
   1287         return FALSE;
   1288     }
   1289     uenum_reset(list, status);
   1290     while( (value= uenum_next(list, &length, status))!=NULL){
   1291         if(strcmp(value, str)==0){
   1292             return TRUE;
   1293         }
   1294     }
   1295     return FALSE;
   1296 }*/
   1297 
   1298 static void TestJ5298(void)
   1299 {
   1300     UErrorCode status = U_ZERO_ERROR;
   1301     char input[256], output[256];
   1302     UBool isAvailable;
   1303     int32_t i = 0;
   1304     UEnumeration* values = NULL;
   1305     const char *keywordValue = NULL;
   1306     log_verbose("Number of collator locales returned : %i \n", ucol_countAvailable());
   1307     values = ucol_getKeywordValues("collation", &status);
   1308     for (i = 0; i < ucol_countAvailable(); i++) {
   1309         uenum_reset(values, &status);
   1310         while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) {
   1311             strcpy(input, ucol_getAvailable(i));
   1312             if (strcmp(keywordValue, "standard") != 0) {
   1313                 strcat(input, "@collation=");
   1314                 strcat(input, keywordValue);
   1315             }
   1316 
   1317             ucol_getFunctionalEquivalent(output, 256, "collation", input, &isAvailable, &status);
   1318             if (strcmp(input, output) == 0) { /* Unique locale, print it out */
   1319                 log_verbose("%s, \n", output);
   1320             }
   1321         }
   1322     }
   1323     uenum_close(values);
   1324     log_verbose("\n");
   1325 }
   1326 #endif /* #if !UCONFIG_NO_COLLATION */
   1327