Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2014, 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     (void)sortklenmin;  /* Suppress set but not used warning. */
    402 
    403     sortKey1 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    404     sortKey1a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    405     ucol_getSortKey(myCollation, source, sLen, sortKey1,  sortklen1+1);
    406     ucol_getSortKey(myCollation, source, -1,   sortKey1a, sortklen1+1);
    407 
    408     sortKey2 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    409     sortKey2a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
    410     ucol_getSortKey(myCollation, target, tLen, sortKey2,  sortklen2+1);
    411     ucol_getSortKey(myCollation, target, -1,   sortKey2a, sortklen2+1);
    412 
    413     /* Check that sort key generated with null terminated string is identical  */
    414     /*  to that generted with a length specified.                              */
    415     if (uprv_strcmp((const char *)sortKey1, (const char *)sortKey1a) != 0 ||
    416         uprv_strcmp((const char *)sortKey2, (const char *)sortKey2a) != 0 ) {
    417         log_err("Sort Keys from null terminated and explicit length strings differ.\n");
    418     }
    419 
    420     /*memcmp(sortKey1, sortKey2,sortklenmax);*/
    421     temp= uprv_strcmp((const char *)sortKey1, (const char *)sortKey2);
    422     gSortklen1 = uprv_strlen((const char *)sortKey1)+1;
    423     gSortklen2 = uprv_strlen((const char *)sortKey2)+1;
    424     if(sortklen1 != gSortklen1){
    425         log_err("SortKey length does not match Expected: %i Got: %i\n",sortklen1, gSortklen1);
    426         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey1, buffer, &len));
    427     }
    428     if(sortklen2!= gSortklen2){
    429         log_err("SortKey length does not match Expected: %i Got: %i\n", sortklen2, gSortklen2);
    430         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey2, buffer, &len));
    431     }
    432 
    433     if(temp < 0) {
    434         keyResult=UCOL_LESS;
    435     }
    436     else if(temp > 0) {
    437         keyResult= UCOL_GREATER;
    438     }
    439     else {
    440         keyResult = UCOL_EQUAL;
    441     }
    442     reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResultIter, result );
    443     free(sortKey1);
    444     free(sortKey2);
    445     free(sortKey1a);
    446     free(sortKey2a);
    447 
    448 }
    449 
    450 void doTest(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
    451 {
    452   if(myCollation) {
    453     doTestVariant(myCollation, source, target, result);
    454     if(result == UCOL_LESS) {
    455       doTestVariant(myCollation, target, source, UCOL_GREATER);
    456     } else if(result == UCOL_GREATER) {
    457       doTestVariant(myCollation, target, source, UCOL_LESS);
    458     } else {
    459       doTestVariant(myCollation, target, source, UCOL_EQUAL);
    460     }
    461   } else {
    462     log_data_err("No collator! Any data around?\n");
    463   }
    464 }
    465 
    466 
    467 /**
    468  * Return an integer array containing all of the collation orders
    469  * returned by calls to next on the specified iterator
    470  */
    471 OrderAndOffset* getOrders(UCollationElements *iter, int32_t *orderLength)
    472 {
    473     UErrorCode status;
    474     int32_t order;
    475     int32_t maxSize = 100;
    476     int32_t size = 0;
    477     int32_t offset = ucol_getOffset(iter);
    478     OrderAndOffset *temp;
    479     OrderAndOffset *orders =(OrderAndOffset *)malloc(sizeof(OrderAndOffset) * maxSize);
    480     status= U_ZERO_ERROR;
    481 
    482 
    483     while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER)
    484     {
    485         if (size == maxSize)
    486         {
    487             maxSize *= 2;
    488             temp = (OrderAndOffset *)malloc(sizeof(OrderAndOffset) * maxSize);
    489 
    490             memcpy(temp, orders, size * sizeof(OrderAndOffset));
    491             free(orders);
    492             orders = temp;
    493 
    494         }
    495 
    496         orders[size].order  = order;
    497         orders[size].offset = offset;
    498 
    499         offset = ucol_getOffset(iter);
    500         size += 1;
    501     }
    502 
    503     if (maxSize > size && size > 0)
    504     {
    505         temp = (OrderAndOffset *)malloc(sizeof(OrderAndOffset) * size);
    506 
    507         memcpy(temp, orders, size * sizeof(OrderAndOffset));
    508         free(orders);
    509         orders = temp;
    510 
    511 
    512     }
    513 
    514     *orderLength = size;
    515     return orders;
    516 }
    517 
    518 
    519 void
    520 backAndForth(UCollationElements *iter)
    521 {
    522     /* Run through the iterator forwards and stick it into an array */
    523     int32_t idx, o;
    524     UErrorCode status = U_ZERO_ERROR;
    525     int32_t orderLength = 0;
    526     OrderAndOffset *orders = getOrders(iter, &orderLength);
    527 
    528 
    529     /* Now go through it backwards and make sure we get the same values */
    530     idx = orderLength;
    531     ucol_reset(iter);
    532 
    533     /* synwee : changed */
    534     while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) {
    535 #if TEST_OFFSETS
    536       int32_t offset =
    537 #endif
    538         ucol_getOffset(iter);
    539 
    540       idx -= 1;
    541       if (o != orders[idx].order) {
    542         if (o == 0)
    543           idx ++;
    544         else {
    545           while (idx > 0 && orders[-- idx].order == 0) {
    546             /* nothing... */
    547           }
    548 
    549           if (o != orders[idx].order) {
    550               log_err("Mismatched order at index %d: 0x%8.8X vs. 0x%8.8X\n", idx,
    551                 orders[idx].order, o);
    552             goto bail;
    553           }
    554         }
    555       }
    556 
    557 #if TEST_OFFSETS
    558       if (offset != orders[idx].offset) {
    559         log_err("Mismatched offset at index %d: %d vs. %d\n", idx,
    560             orders[idx].offset, offset);
    561         goto bail;
    562       }
    563 #endif
    564 
    565     }
    566 
    567     while (idx != 0 && orders[idx - 1].order == 0) {
    568       idx -= 1;
    569     }
    570 
    571     if (idx != 0) {
    572         log_err("Didn't get back to beginning - index is %d\n", idx);
    573 
    574         ucol_reset(iter);
    575         log_err("\nnext: ");
    576 
    577         if ((o = ucol_next(iter, &status)) != UCOL_NULLORDER) {
    578             log_err("Error at %x\n", o);
    579         }
    580 
    581         log_err("\nprev: ");
    582 
    583         if ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) {
    584             log_err("Error at %x\n", o);
    585         }
    586 
    587         log_verbose("\n");
    588     }
    589 
    590 bail:
    591     free(orders);
    592 }
    593 
    594 void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result) {
    595   UChar t1[2048] = {0};
    596   UChar t2[2048] = {0};
    597   UCollationElements *iter;
    598   UErrorCode status = U_ZERO_ERROR;
    599 
    600   uint32_t i = 0, j = 0;
    601   log_verbose("testing sequence:\n");
    602   for(i = 0; i < size; i++) {
    603     log_verbose("%s\n", s[i]);
    604   }
    605 
    606   iter = ucol_openElements(coll, t1, u_strlen(t1), &status);
    607   if (U_FAILURE(status)) {
    608     log_err("Creation of iterator failed\n");
    609   }
    610   for(i = 0; i < size-1; i++) {
    611     for(j = i+1; j < size; j++) {
    612       u_unescape(s[i], t1, 2048);
    613       u_unescape(s[j], t2, 2048);
    614       doTest(coll, t1, t2, result);
    615       /* synwee : added collation element iterator test */
    616       ucol_setText(iter, t1, u_strlen(t1), &status);
    617       backAndForth(iter);
    618       ucol_setText(iter, t2, u_strlen(t2), &status);
    619       backAndForth(iter);
    620     }
    621   }
    622   ucol_closeElements(iter);
    623 }
    624 
    625 void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size) {
    626   genericOrderingTestWithResult(coll, s, size, UCOL_LESS);
    627 }
    628 
    629 void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size) {
    630   UErrorCode status = U_ZERO_ERROR;
    631   UCollator *coll = ucol_open(locale, &status);
    632 
    633   log_verbose("Locale starter for %s\n", locale);
    634 
    635   if(U_SUCCESS(status)) {
    636     genericOrderingTest(coll, s, size);
    637   } else if(status == U_FILE_ACCESS_ERROR) {
    638     log_data_err("Is your data around?\n");
    639     return;
    640   } else {
    641     log_err("Unable to open collator for locale %s\n", locale);
    642   }
    643   ucol_close(coll);
    644 }
    645 
    646 void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result) {
    647   UErrorCode status = U_ZERO_ERROR;
    648   UCollator *coll = ucol_open(locale, &status);
    649 
    650   log_verbose("Locale starter for %s\n", locale);
    651 
    652   if(U_SUCCESS(status)) {
    653     genericOrderingTestWithResult(coll, s, size, result);
    654   } else if(status == U_FILE_ACCESS_ERROR) {
    655     log_data_err("Is your data around?\n");
    656     return;
    657   } else {
    658     log_err("Unable to open collator for locale %s\n", locale);
    659   }
    660   ucol_close(coll);
    661 }
    662 
    663 /* currently not used with options */
    664 void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
    665   UErrorCode status = U_ZERO_ERROR;
    666   UChar rlz[RULE_BUFFER_LEN] = { 0 };
    667   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
    668   uint32_t i;
    669 
    670   UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
    671 
    672   log_verbose("Rules starter for %s\n", rules);
    673 
    674   if(U_SUCCESS(status)) {
    675     log_verbose("Setting attributes\n");
    676     for(i = 0; i < attsize; i++) {
    677       ucol_setAttribute(coll, attrs[i], values[i], &status);
    678     }
    679 
    680     genericOrderingTestWithResult(coll, s, size, result);
    681   } else {
    682     log_err_status(status, "Unable to open collator with rules %s\n", rules);
    683   }
    684   ucol_close(coll);
    685 }
    686 
    687 void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
    688   UErrorCode status = U_ZERO_ERROR;
    689   uint32_t i;
    690 
    691   UCollator *coll = ucol_open(locale, &status);
    692 
    693   log_verbose("Locale starter for %s\n", locale);
    694 
    695   if(U_SUCCESS(status)) {
    696 
    697     log_verbose("Setting attributes\n");
    698     for(i = 0; i < attsize; i++) {
    699       ucol_setAttribute(coll, attrs[i], values[i], &status);
    700     }
    701 
    702     genericOrderingTestWithResult(coll, s, size, result);
    703   } else {
    704     log_err_status(status, "Unable to open collator for locale %s\n", locale);
    705   }
    706   ucol_close(coll);
    707 }
    708 
    709 void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize) {
    710   genericLocaleStarterWithOptionsAndResult(locale, s, size, attrs, values, attsize, UCOL_LESS);
    711 }
    712 
    713 void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result) {
    714   UErrorCode status = U_ZERO_ERROR;
    715   UChar rlz[RULE_BUFFER_LEN] = { 0 };
    716   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
    717 
    718   UCollator *coll = NULL;
    719   coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
    720   log_verbose("Rules starter for %s\n", rules);
    721 
    722   if(U_SUCCESS(status)) {
    723     genericOrderingTestWithResult(coll, s, size, result);
    724     ucol_close(coll);
    725   } else if(status == U_FILE_ACCESS_ERROR) {
    726     log_data_err("Is your data around?\n");
    727   } else {
    728     log_err("Unable to open collator with rules %s\n", rules);
    729   }
    730 }
    731 
    732 void genericRulesStarter(const char *rules, const char * const s[], uint32_t size) {
    733   genericRulesStarterWithResult(rules, s, size, UCOL_LESS);
    734 }
    735 
    736 static void TestTertiary()
    737 {
    738     int32_t len,i;
    739     UCollator *myCollation;
    740     UErrorCode status=U_ZERO_ERROR;
    741     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    742     UChar rules[sizeof(str)];
    743     len = strlen(str);
    744     u_uastrcpy(rules, str);
    745 
    746     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
    747     if(U_FAILURE(status)){
    748         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    749         return;
    750     }
    751 
    752     ucol_setStrength(myCollation, UCOL_TERTIARY);
    753     for (i = 0; i < 17 ; i++)
    754     {
    755         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    756     }
    757     ucol_close(myCollation);
    758     myCollation = 0;
    759 }
    760 
    761 static void TestPrimary( )
    762 {
    763     int32_t len,i;
    764     UCollator *myCollation;
    765     UErrorCode status=U_ZERO_ERROR;
    766     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    767     UChar rules[sizeof(str)];
    768     len = strlen(str);
    769     u_uastrcpy(rules, str);
    770 
    771     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    772     if(U_FAILURE(status)){
    773         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    774         return;
    775     }
    776     ucol_setStrength(myCollation, UCOL_PRIMARY);
    777 
    778     for (i = 17; i < 26 ; i++)
    779     {
    780 
    781         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    782     }
    783     ucol_close(myCollation);
    784     myCollation = 0;
    785 }
    786 
    787 static void TestSecondary()
    788 {
    789     int32_t i;
    790     int32_t len;
    791     UCollator *myCollation;
    792     UErrorCode status=U_ZERO_ERROR;
    793     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    794     UChar rules[sizeof(str)];
    795     len = strlen(str);
    796     u_uastrcpy(rules, str);
    797 
    798     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    799     if(U_FAILURE(status)){
    800         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    801         return;
    802     }
    803     ucol_setStrength(myCollation, UCOL_SECONDARY);
    804     for (i = 26; i < 34 ; i++)
    805     {
    806         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    807     }
    808     ucol_close(myCollation);
    809     myCollation = 0;
    810 }
    811 
    812 static void TestIdentical()
    813 {
    814     int32_t i;
    815     int32_t len;
    816     UCollator *myCollation;
    817     UErrorCode status=U_ZERO_ERROR;
    818     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    819     UChar rules[sizeof(str)];
    820     len = strlen(str);
    821     u_uastrcpy(rules, str);
    822 
    823     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_IDENTICAL, NULL,&status);
    824     if(U_FAILURE(status)){
    825         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    826         return;
    827     }
    828     for(i= 34; i<37; i++)
    829     {
    830         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
    831     }
    832     ucol_close(myCollation);
    833     myCollation = 0;
    834 }
    835 
    836 static void TestExtra()
    837 {
    838     int32_t i, j;
    839     int32_t len;
    840     UCollator *myCollation;
    841     UErrorCode status = U_ZERO_ERROR;
    842     static const char str[]="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
    843     UChar rules[sizeof(str)];
    844     len = strlen(str);
    845     u_uastrcpy(rules, str);
    846 
    847     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
    848     if(U_FAILURE(status)){
    849         log_err_status(status, "ERROR: in creation of rule based collator :%s\n", myErrorName(status));
    850         return;
    851     }
    852     ucol_setStrength(myCollation, UCOL_TERTIARY);
    853     for (i = 0; i < COUNT_TEST_CASES-1 ; i++)
    854     {
    855         for (j = i + 1; j < COUNT_TEST_CASES; j += 1)
    856         {
    857 
    858             doTest(myCollation, testCases[i], testCases[j], UCOL_LESS);
    859         }
    860     }
    861     ucol_close(myCollation);
    862     myCollation = 0;
    863 }
    864 
    865 static void TestJB581(void)
    866 {
    867     int32_t     bufferLen   = 0;
    868     UChar       source      [100];
    869     UChar       target      [100];
    870     UCollationResult result     = UCOL_EQUAL;
    871     uint8_t     sourceKeyArray  [100];
    872     uint8_t     targetKeyArray  [100];
    873     int32_t     sourceKeyOut    = 0,
    874                 targetKeyOut    = 0;
    875     UCollator   *myCollator = 0;
    876     UErrorCode status = U_ZERO_ERROR;
    877 
    878     /*u_uastrcpy(source, "This is a test.");*/
    879     /*u_uastrcpy(target, "THISISATEST.");*/
    880     u_uastrcpy(source, "THISISATEST.");
    881     u_uastrcpy(target, "Thisisatest.");
    882 
    883     myCollator = ucol_open("en_US", &status);
    884     if (U_FAILURE(status)){
    885         log_err_status(status, "ERROR: Failed to create the collator : %s\n", u_errorName(status));
    886         return;
    887     }
    888     result = ucol_strcoll(myCollator, source, -1, target, -1);
    889     /* result is 1, secondary differences only for ignorable space characters*/
    890     if (result != 1)
    891     {
    892         log_err("Comparing two strings with only secondary differences in C failed.\n");
    893     }
    894     /* To compare them with just primary differences */
    895     ucol_setStrength(myCollator, UCOL_PRIMARY);
    896     result = ucol_strcoll(myCollator, source, -1, target, -1);
    897     /* result is 0 */
    898     if (result != 0)
    899     {
    900         log_err("Comparing two strings with no differences in C failed.\n");
    901     }
    902     /* Now, do the same comparison with keys */
    903     sourceKeyOut = ucol_getSortKey(myCollator, source, -1, sourceKeyArray, 100);
    904     (void)sourceKeyOut;    /* Suppress set but not used warning. */
    905     targetKeyOut = ucol_getSortKey(myCollator, target, -1, targetKeyArray, 100);
    906     bufferLen = ((targetKeyOut > 100) ? 100 : targetKeyOut);
    907     if (memcmp(sourceKeyArray, targetKeyArray, bufferLen) != 0)
    908     {
    909         log_err("Comparing two strings with sort keys in C failed.\n");
    910     }
    911     ucol_close(myCollator);
    912 }
    913 
    914 static void TestJB1401(void)
    915 {
    916     UCollator     *myCollator = 0;
    917     UErrorCode     status = U_ZERO_ERROR;
    918     static UChar   NFD_UnsafeStartChars[] = {
    919         0x0f73,          /* Tibetan Vowel Sign II */
    920         0x0f75,          /* Tibetan Vowel Sign UU */
    921         0x0f81,          /* Tibetan Vowel Sign Reversed II */
    922             0
    923     };
    924     int            i;
    925 
    926 
    927     myCollator = ucol_open("en_US", &status);
    928     if (U_FAILURE(status)){
    929         log_err_status(status, "ERROR: Failed to create the collator : %s\n", u_errorName(status));
    930         return;
    931     }
    932     ucol_setAttribute(myCollator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    933     if (U_FAILURE(status)){
    934         log_err("ERROR: Failed to set normalization mode ON for collator.\n");
    935         return;
    936     }
    937 
    938     for (i=0; ; i++) {
    939         UChar    c;
    940         UChar    X[4];
    941         UChar    Y[20];
    942         UChar    Z[20];
    943 
    944         /*  Get the next funny character to be tested, and set up the
    945          *  three test strings X, Y, Z, consisting of an A-grave + test char,
    946          *    in original form, NFD, and then NFC form.
    947          */
    948         c = NFD_UnsafeStartChars[i];
    949         if (c==0) {break;}
    950 
    951         X[0]=0xC0; X[1]=c; X[2]=0;   /* \u00C0 is A Grave*/
    952 
    953         unorm_normalize(X, -1, UNORM_NFD, 0, Y, 20, &status);
    954         unorm_normalize(Y, -1, UNORM_NFC, 0, Z, 20, &status);
    955         if (U_FAILURE(status)){
    956             log_err("ERROR: Failed to normalize test of character %x\n", c);
    957             return;
    958         }
    959 
    960         /* Collation test.  All three strings should be equal.
    961          *   doTest does both strcoll and sort keys, with params in both orders.
    962          */
    963         doTest(myCollator, X, Y, UCOL_EQUAL);
    964         doTest(myCollator, X, Z, UCOL_EQUAL);
    965         doTest(myCollator, Y, Z, UCOL_EQUAL);
    966 
    967         /* Run collation element iterators over the three strings.  Results should be same for each.
    968          */
    969         {
    970             UCollationElements *ceiX, *ceiY, *ceiZ;
    971             int32_t             ceX,   ceY,   ceZ;
    972             int                 j;
    973 
    974             ceiX = ucol_openElements(myCollator, X, -1, &status);
    975             ceiY = ucol_openElements(myCollator, Y, -1, &status);
    976             ceiZ = ucol_openElements(myCollator, Z, -1, &status);
    977             if (U_FAILURE(status)) {
    978                 log_err("ERROR: uucol_openElements failed.\n");
    979                 return;
    980             }
    981 
    982             for (j=0;; j++) {
    983                 ceX = ucol_next(ceiX, &status);
    984                 ceY = ucol_next(ceiY, &status);
    985                 ceZ = ucol_next(ceiZ, &status);
    986                 if (U_FAILURE(status)) {
    987                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
    988                     break;
    989                 }
    990                 if (ceX != ceY || ceY != ceZ) {
    991                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
    992                     break;
    993                 }
    994                 if (ceX == UCOL_NULLORDER) {
    995                     break;
    996                 }
    997             }
    998             ucol_closeElements(ceiX);
    999             ucol_closeElements(ceiY);
   1000             ucol_closeElements(ceiZ);
   1001         }
   1002     }
   1003     ucol_close(myCollator);
   1004 }
   1005 
   1006 
   1007 
   1008 /**
   1009 * Tests the [variable top] tag in rule syntax. Since the default [alternate]
   1010 * tag has the value shifted, any codepoints before [variable top] should give
   1011 * a primary ce of 0.
   1012 */
   1013 static void TestVariableTop(void)
   1014 {
   1015 #if 0
   1016     /*
   1017      * Starting with ICU 53, setting the variable top via a pseudo relation string
   1018      * is not supported any more.
   1019      * It was replaced by the [maxVariable symbol] setting.
   1020      * See ICU tickets #9958 and #8032.
   1021      */
   1022     static const char       str[]          = "&z = [variable top]";
   1023           int         len          = strlen(str);
   1024           UChar      rules[sizeof(str)];
   1025           UCollator  *myCollation;
   1026           UCollator  *enCollation;
   1027           UErrorCode  status       = U_ZERO_ERROR;
   1028           UChar       source[1];
   1029           UChar       ch;
   1030           uint8_t     result[20];
   1031           uint8_t     expected[20];
   1032 
   1033     u_uastrcpy(rules, str);
   1034 
   1035     enCollation = ucol_open("en_US", &status);
   1036     if (U_FAILURE(status)) {
   1037         log_err_status(status, "ERROR: in creation of collator :%s\n",
   1038                 myErrorName(status));
   1039         return;
   1040     }
   1041     myCollation = ucol_openRules(rules, len, UCOL_OFF,
   1042                                  UCOL_PRIMARY,NULL, &status);
   1043     if (U_FAILURE(status)) {
   1044         ucol_close(enCollation);
   1045         log_err("ERROR: in creation of rule based collator :%s\n",
   1046                 myErrorName(status));
   1047         return;
   1048     }
   1049 
   1050     ucol_setStrength(enCollation, UCOL_PRIMARY);
   1051     ucol_setAttribute(enCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
   1052                       &status);
   1053     ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
   1054                       &status);
   1055 
   1056     if (ucol_getAttribute(myCollation, UCOL_ALTERNATE_HANDLING, &status) !=
   1057         UCOL_SHIFTED || U_FAILURE(status)) {
   1058         log_err("ERROR: ALTERNATE_HANDLING value can not be set to SHIFTED\n");
   1059     }
   1060 
   1061     uprv_memset(expected, 0, 20);
   1062 
   1063     /* space is supposed to be a variable */
   1064     source[0] = ' ';
   1065     len = ucol_getSortKey(enCollation, source, 1, result,
   1066                           sizeof(result));
   1067 
   1068     if (uprv_memcmp(expected, result, len) != 0) {
   1069         log_err("ERROR: SHIFTED alternate does not return 0 for primary of space\n");
   1070     }
   1071 
   1072     ch = 'a';
   1073     while (ch < 'z') {
   1074         source[0] = ch;
   1075         len = ucol_getSortKey(myCollation, source, 1, result,
   1076                               sizeof(result));
   1077         if (uprv_memcmp(expected, result, len) != 0) {
   1078             log_err("ERROR: SHIFTED alternate does not return 0 for primary of %c\n",
   1079                     ch);
   1080         }
   1081         ch ++;
   1082     }
   1083 
   1084     ucol_close(enCollation);
   1085     ucol_close(myCollation);
   1086     enCollation = NULL;
   1087     myCollation = NULL;
   1088 #endif
   1089 }
   1090 
   1091 /**
   1092   * Tests surrogate support.
   1093   * NOTE: This test used \\uD801\\uDC01 pair, which is now assigned to Desseret
   1094   * Therefore, another (unassigned) code point was used for this test.
   1095   */
   1096 static void TestSurrogates(void)
   1097 {
   1098     static const char       str[]          =
   1099                               "&z<'\\uD800\\uDC00'<'\\uD800\\uDC0A\\u0308'<A";
   1100           int         len          = strlen(str);
   1101           int         rlen         = 0;
   1102           UChar      rules[sizeof(str)];
   1103           UCollator  *myCollation;
   1104           UCollator  *enCollation;
   1105           UErrorCode  status       = U_ZERO_ERROR;
   1106           UChar       source[][4]    =
   1107           {{'z', 0, 0}, {0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {0xD800, 0xDC02}};
   1108           UChar       target[][4]    =
   1109           {{0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {'A', 0, 0}, {0xD800, 0xDC03}};
   1110           int         count        = 0;
   1111           uint8_t enresult[20], myresult[20];
   1112           int enlen, mylen;
   1113 
   1114     /* tests for open rules with surrogate rules */
   1115     rlen = u_unescape(str, rules, len);
   1116 
   1117     enCollation = ucol_open("en_US", &status);
   1118     if (U_FAILURE(status)) {
   1119         log_err_status(status, "ERROR: in creation of collator :%s\n",
   1120                 myErrorName(status));
   1121         return;
   1122     }
   1123     myCollation = ucol_openRules(rules, rlen, UCOL_OFF,
   1124                                  UCOL_TERTIARY,NULL, &status);
   1125     if (U_FAILURE(status)) {
   1126         ucol_close(enCollation);
   1127         log_err("ERROR: in creation of rule based collator :%s\n",
   1128                 myErrorName(status));
   1129         return;
   1130     }
   1131 
   1132     /*
   1133     this test is to verify the supplementary sort key order in the english
   1134     collator
   1135     */
   1136     log_verbose("start of english collation supplementary characters test\n");
   1137     while (count < 2) {
   1138         doTest(enCollation, source[count], target[count], UCOL_LESS);
   1139         count ++;
   1140     }
   1141     doTest(enCollation, source[count], target[count], UCOL_GREATER);
   1142 
   1143     log_verbose("start of tailored collation supplementary characters test\n");
   1144     count = 0;
   1145     /* tests getting collation elements for surrogates for tailored rules */
   1146     while (count < 4) {
   1147         doTest(myCollation, source[count], target[count], UCOL_LESS);
   1148         count ++;
   1149     }
   1150 
   1151     /* tests that \uD800\uDC02 still has the same value, not changed */
   1152     enlen = ucol_getSortKey(enCollation, source[3], 2, enresult, 20);
   1153     mylen = ucol_getSortKey(myCollation, source[3], 2, myresult, 20);
   1154     if (enlen != mylen ||
   1155         uprv_memcmp(enresult, myresult, enlen) != 0) {
   1156         log_verbose("Failed : non-tailored supplementary characters should have the same value\n");
   1157     }
   1158 
   1159     ucol_close(enCollation);
   1160     ucol_close(myCollation);
   1161     enCollation = NULL;
   1162     myCollation = NULL;
   1163 }
   1164 
   1165 /*
   1166  *### TODO: Add more invalid rules to test all different scenarios.
   1167  *
   1168  */
   1169 static void
   1170 TestInvalidRules(){
   1171 #define MAX_ERROR_STATES 2
   1172 
   1173     static const char* rulesArr[MAX_ERROR_STATES] = {
   1174         "& C < ch, cH, Ch[this should fail]<d",
   1175         "& C < ch, cH, & Ch[variable top]"
   1176     };
   1177     static const char* preContextArr[MAX_ERROR_STATES] = {
   1178         " C < ch, cH, Ch",
   1179         "& C < ch, cH",
   1180 
   1181     };
   1182     static const char* postContextArr[MAX_ERROR_STATES] = {
   1183         "[this should fa",
   1184         ", & Ch[variable"
   1185     };
   1186     int i;
   1187 
   1188     for(i = 0;i<MAX_ERROR_STATES;i++){
   1189         UChar rules[1000]       = { '\0' };
   1190         UChar preContextExp[1000]  = { '\0' };
   1191         UChar postContextExp[1000] = { '\0' };
   1192         UParseError parseError;
   1193         UErrorCode status = U_ZERO_ERROR;
   1194         UCollator* coll=0;
   1195         u_charsToUChars(rulesArr[i],rules,uprv_strlen(rulesArr[i])+1);
   1196         u_charsToUChars(preContextArr[i],preContextExp,uprv_strlen(preContextArr[i])+1);
   1197         u_charsToUChars(postContextArr[i],postContextExp,uprv_strlen(postContextArr[i])+1);
   1198         /* clean up stuff in parseError */
   1199         u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
   1200         u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
   1201         /* open the rules and test */
   1202         coll = ucol_openRules(rules,u_strlen(rules),UCOL_OFF,UCOL_DEFAULT_STRENGTH,&parseError,&status);
   1203         (void)coll;   /* Suppress set but not used warning. */
   1204         if(u_strcmp(parseError.preContext,preContextExp)!=0){
   1205             log_err_status(status, "preContext in UParseError for ucol_openRules does not match: \"%s\"\n",
   1206                            aescstrdup(parseError.preContext, -1));
   1207         }
   1208         if(u_strcmp(parseError.postContext,postContextExp)!=0){
   1209             log_err_status(status, "postContext in UParseError for ucol_openRules does not match: \"%s\"\n",
   1210                            aescstrdup(parseError.postContext, -1));
   1211         }
   1212     }
   1213 }
   1214 
   1215 static void
   1216 TestJitterbug1098(){
   1217     UChar rule[1000];
   1218     UCollator* c1 = NULL;
   1219     UErrorCode status = U_ZERO_ERROR;
   1220     UParseError parseError;
   1221     char preContext[200]={0};
   1222     char postContext[200]={0};
   1223     int i=0;
   1224     const char* rules[] = {
   1225          "&''<\\\\",
   1226          "&\\'<\\\\",
   1227          "&\\\"<'\\'",
   1228          "&'\"'<\\'",
   1229          NULL
   1230 
   1231     };
   1232     const UCollationResult results1098[] = {
   1233         UCOL_LESS,
   1234         UCOL_LESS,
   1235         UCOL_LESS,
   1236         UCOL_LESS,
   1237     };
   1238     const UChar input[][2]= {
   1239         {0x0027,0x005c},
   1240         {0x0027,0x005c},
   1241         {0x0022,0x005c},
   1242         {0x0022,0x0027},
   1243     };
   1244     UChar X[2] ={0};
   1245     UChar Y[2] ={0};
   1246     u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
   1247     u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
   1248     for(;rules[i]!=0;i++){
   1249         u_uastrcpy(rule, rules[i]);
   1250         c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, &parseError, &status);
   1251         if(U_FAILURE(status)){
   1252             log_err_status(status, "Could not parse the rules syntax. Error: %s\n", u_errorName(status));
   1253 
   1254             if (status == U_PARSE_ERROR) {
   1255                 u_UCharsToChars(parseError.preContext,preContext,20);
   1256                 u_UCharsToChars(parseError.postContext,postContext,20);
   1257                 log_verbose("\n\tPre-Context: %s \n\tPost-Context:%s \n",preContext,postContext);
   1258             }
   1259 
   1260             return;
   1261         }
   1262         X[0] = input[i][0];
   1263         Y[0] = input[i][1];
   1264         doTest(c1,X,Y,results1098[i]);
   1265         ucol_close(c1);
   1266     }
   1267 }
   1268 
   1269 static void
   1270 TestFCDCrash(void) {
   1271     static const char *test[] = {
   1272     "Gr\\u00F6\\u00DFe",
   1273     "Grossist"
   1274     };
   1275 
   1276     UErrorCode status = U_ZERO_ERROR;
   1277     UCollator *coll = ucol_open("es", &status);
   1278     if(U_FAILURE(status)) {
   1279         log_err_status(status, "Couldn't open collator -> %s\n", u_errorName(status));
   1280         return;
   1281     }
   1282     ucol_close(coll);
   1283     coll = NULL;
   1284     ctest_resetICU();
   1285     coll = ucol_open("de_DE", &status);
   1286     if(U_FAILURE(status)) {
   1287         log_err_status(status, "Couldn't open collator -> %s\n", u_errorName(status));
   1288         return;
   1289     }
   1290     ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
   1291     genericOrderingTest(coll, test, 2);
   1292     ucol_close(coll);
   1293 }
   1294 
   1295 /*static UBool
   1296 find(UEnumeration* list, const char* str, UErrorCode* status){
   1297     const char* value = NULL;
   1298     int32_t length=0;
   1299     if(U_FAILURE(*status)){
   1300         return FALSE;
   1301     }
   1302     uenum_reset(list, status);
   1303     while( (value= uenum_next(list, &length, status))!=NULL){
   1304         if(strcmp(value, str)==0){
   1305             return TRUE;
   1306         }
   1307     }
   1308     return FALSE;
   1309 }*/
   1310 
   1311 static void TestJ5298(void)
   1312 {
   1313     UErrorCode status = U_ZERO_ERROR;
   1314     char input[256], output[256];
   1315     UBool isAvailable;
   1316     int32_t i = 0;
   1317     UEnumeration* values = NULL;
   1318     const char *keywordValue = NULL;
   1319     log_verbose("Number of collator locales returned : %i \n", ucol_countAvailable());
   1320     values = ucol_getKeywordValues("collation", &status);
   1321     while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) {
   1322         if (strncmp(keywordValue, "private-", 8) == 0) {
   1323             log_err("ucol_getKeywordValues() returns private collation keyword: %s\n", keywordValue);
   1324         }
   1325     }
   1326     for (i = 0; i < ucol_countAvailable(); i++) {
   1327         uenum_reset(values, &status);
   1328         while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) {
   1329             strcpy(input, ucol_getAvailable(i));
   1330             if (strcmp(keywordValue, "standard") != 0) {
   1331                 strcat(input, "@collation=");
   1332                 strcat(input, keywordValue);
   1333             }
   1334 
   1335             ucol_getFunctionalEquivalent(output, 256, "collation", input, &isAvailable, &status);
   1336             if (strcmp(input, output) == 0) { /* Unique locale, print it out */
   1337                 log_verbose("%s, \n", output);
   1338             }
   1339         }
   1340     }
   1341     uenum_close(values);
   1342     log_verbose("\n");
   1343 }
   1344 #endif /* #if !UCONFIG_NO_COLLATION */
   1345