Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * Copyright (c) 2001-2011 International Business Machines
      3  * Corporation and others. All Rights Reserved.
      4  ********************************************************************
      5  * File usrchtst.c
      6  * Modification History:
      7  * Name           Date             Description
      8  * synwee         July 19 2001     creation
      9  ********************************************************************/
     10 
     11 #include "unicode/utypes.h"
     12 
     13 #if !UCONFIG_NO_COLLATION && !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO
     14 
     15 #include "unicode/usearch.h"
     16 #include "unicode/ustring.h"
     17 #include "ccolltst.h"
     18 #include "cmemory.h"
     19 #include <stdio.h>
     20 #include "usrchdat.c"
     21 #include "unicode/ubrk.h"
     22 #include <assert.h>
     23 
     24 static UBool      TOCLOSE_ = TRUE;
     25 static UCollator *EN_US_;
     26 static UCollator *FR_FR_;
     27 static UCollator *DE_;
     28 static UCollator *ES_;
     29 
     30 /**
     31  * CHECK_BREAK(char *brk)
     32  *     Test if a break iterator is passed in AND break iteration is disabled.
     33  *     Skip the test if so.
     34  * CHECK_BREAK_BOOL(char *brk)
     35  *     Same as above, but returns 'TRUE' as a passing result
     36  */
     37 
     38 #if !UCONFIG_NO_BREAK_ITERATION
     39 static UBreakIterator *EN_WORDBREAKER_;
     40 static UBreakIterator *EN_CHARACTERBREAKER_;
     41 #define CHECK_BREAK(x)
     42 #define CHECK_BREAK_BOOL(x)
     43 #else
     44 #define CHECK_BREAK(x)  if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return; }
     45 #define CHECK_BREAK_BOOL(x)  if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return TRUE; }
     46 #endif
     47 
     48 /**
     49 * Opening all static collators and break iterators
     50 */
     51 static void open(UErrorCode* status)
     52 {
     53     if (TOCLOSE_) {
     54         UChar      rules[1024];
     55         int32_t    rulelength = 0;
     56         *status = U_ZERO_ERROR;
     57 
     58         EN_US_ = ucol_open("en_US", status);
     59         if(U_FAILURE(*status)) {
     60           log_err_status(*status, "Error opening collator\n");
     61           return;
     62         }
     63         FR_FR_ = ucol_open("fr_FR", status);
     64         DE_ = ucol_open("de_DE", status);
     65         ES_ = ucol_open("es_ES", status);
     66 
     67         u_strcpy(rules, ucol_getRules(DE_, &rulelength));
     68         u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength);
     69 
     70         ucol_close(DE_);
     71 
     72         DE_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY,
     73                              (UParseError *)NULL, status);
     74         u_strcpy(rules, ucol_getRules(ES_, &rulelength));
     75         u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength);
     76 
     77         ucol_close(ES_);
     78         ES_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY,
     79                              NULL, status);
     80 #if !UCONFIG_NO_BREAK_ITERATION
     81         EN_WORDBREAKER_     = ubrk_open(UBRK_WORD, "en_US", NULL, 0, status);
     82         EN_CHARACTERBREAKER_ = ubrk_open(UBRK_CHARACTER, "en_US", NULL, 0,
     83                                         status);
     84 #endif
     85         TOCLOSE_ = TRUE;
     86     }
     87 }
     88 
     89 /**
     90 * Start opening all static collators and break iterators
     91 */
     92 static void TestStart(void)
     93 {
     94     UErrorCode status = U_ZERO_ERROR;
     95     open(&status);
     96     if (U_FAILURE(status)) {
     97         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
     98         return;
     99     }
    100     TOCLOSE_ = FALSE;
    101 }
    102 
    103 /**
    104 * Closing all static collators and break iterators
    105 */
    106 static void close(void)
    107 {
    108     if (TOCLOSE_) {
    109         ucol_close(EN_US_);
    110         ucol_close(FR_FR_);
    111         ucol_close(DE_);
    112         ucol_close(ES_);
    113 #if !UCONFIG_NO_BREAK_ITERATION
    114         ubrk_close(EN_WORDBREAKER_);
    115         ubrk_close(EN_CHARACTERBREAKER_);
    116 #endif
    117     }
    118     TOCLOSE_ = FALSE;
    119 }
    120 
    121 /**
    122 * End closing all static collators and break iterators
    123 */
    124 static void TestEnd(void)
    125 {
    126     TOCLOSE_ = TRUE;
    127     close();
    128     TOCLOSE_ = TRUE;
    129 }
    130 
    131 /**
    132 * output UChar strings for printing.
    133 */
    134 static char *toCharString(const UChar* unichars)
    135 {
    136     static char result[1024];
    137     char *temp   = result;
    138     int   count  = 0;
    139     int   length = u_strlen(unichars);
    140 
    141     for (; count < length; count ++) {
    142         UChar ch = unichars[count];
    143         if (ch >= 0x20 && ch <= 0x7e) {
    144             *temp ++ = (char)ch;
    145         }
    146         else {
    147             sprintf(temp, "\\u%04x", ch);
    148             temp += 6; /* \uxxxx */
    149         }
    150     }
    151     *temp = 0;
    152 
    153     return result;
    154 }
    155 
    156 /**
    157 * Getting the collator
    158 */
    159 static UCollator *getCollator(const char *collator)
    160 {
    161     if (collator == NULL) {
    162         return EN_US_;
    163     }
    164     if (strcmp(collator, "fr") == 0) {
    165         return FR_FR_;
    166     }
    167     else if (strcmp(collator, "de") == 0) {
    168         return DE_;
    169     }
    170     else if (strcmp(collator, "es") == 0) {
    171         return ES_;
    172     }
    173     else {
    174         return EN_US_;
    175     }
    176 }
    177 
    178 /**
    179 * Getting the breakiterator
    180 */
    181 static UBreakIterator *getBreakIterator(const char *breaker)
    182 {
    183     if (breaker == NULL) {
    184         return NULL;
    185     }
    186 #if !UCONFIG_NO_BREAK_ITERATION
    187     if (strcmp(breaker, "wordbreaker") == 0) {
    188         return EN_WORDBREAKER_;
    189     }
    190     else {
    191         return EN_CHARACTERBREAKER_;
    192     }
    193 #else
    194     return NULL;
    195 #endif
    196 }
    197 
    198 static void TestOpenClose(void)
    199 {
    200           UErrorCode      status    = U_ZERO_ERROR;
    201           UStringSearch  *result;
    202     const UChar           pattern[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
    203     const UChar           text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67};
    204 #if !UCONFIG_NO_BREAK_ITERATION
    205           UBreakIterator *breakiter = ubrk_open(UBRK_WORD, "en_US",
    206                                                 text, 6, &status);
    207 #endif
    208     /* testing null arguments */
    209     result = usearch_open(NULL, 0, NULL, 0, NULL, NULL, &status);
    210     if (U_SUCCESS(status) || result != NULL) {
    211         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    212     }
    213     status = U_ZERO_ERROR;
    214     result = usearch_openFromCollator(NULL, 0, NULL, 0, NULL, NULL, &status);
    215     if (U_SUCCESS(status) || result != NULL) {
    216         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    217     }
    218 
    219     status = U_ZERO_ERROR;
    220     result = usearch_open(pattern, 3, NULL, 0, NULL, NULL, &status);
    221     if (U_SUCCESS(status) || result != NULL) {
    222         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    223     }
    224     status = U_ZERO_ERROR;
    225     result = usearch_openFromCollator(pattern, 3, NULL, 0, NULL, NULL,
    226                                       &status);
    227     if (U_SUCCESS(status) || result != NULL) {
    228         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    229     }
    230 
    231     status = U_ZERO_ERROR;
    232     result = usearch_open(pattern, 3, text, 6, NULL, NULL, &status);
    233     if (U_SUCCESS(status) || result != NULL) {
    234         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    235     }
    236     status = U_ZERO_ERROR;
    237     result = usearch_openFromCollator(pattern, 3, text, 6, NULL, NULL,
    238                                       &status);
    239     if (U_SUCCESS(status) || result != NULL) {
    240         log_err("Error: NULL arguments should produce an error and a NULL result\n");
    241     }
    242 
    243     status = U_ZERO_ERROR;
    244     result = usearch_open(pattern, 3, text, 6, "en_US", NULL, &status);
    245     if (U_FAILURE(status) || result == NULL) {
    246         log_err_status(status, "Error: NULL break iterator is valid for opening search\n");
    247     }
    248     else {
    249         usearch_close(result);
    250     }
    251     open(&status);
    252     if (U_FAILURE(status)) {
    253         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    254         return;
    255     }
    256     status = U_ZERO_ERROR;
    257     result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, NULL,
    258                                       &status);
    259     if (U_FAILURE(status) || result == NULL) {
    260         if (EN_US_ == NULL) {
    261             log_data_err("Opening collator failed.\n");
    262         } else {
    263             log_err("Error: NULL break iterator is valid for opening search\n");
    264         }
    265     }
    266     else {
    267         usearch_close(result);
    268     }
    269 
    270 
    271     status = U_ZERO_ERROR;
    272 #if !UCONFIG_NO_BREAK_ITERATION
    273 
    274     result = usearch_open(pattern, 3, text, 6, "en_US", breakiter, &status);
    275     if (U_FAILURE(status) || result == NULL) {
    276         log_err_status(status, "Error: Break iterator is valid for opening search\n");
    277     }
    278     else {
    279         usearch_close(result);
    280     }
    281     status = U_ZERO_ERROR;
    282     result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, breakiter,
    283                                       &status);
    284     if (U_FAILURE(status) || result == NULL) {
    285         if (EN_US_ == NULL) {
    286             log_data_err("Opening collator failed.\n");
    287         } else {
    288             log_err("Error: Break iterator is valid for opening search\n");
    289         }
    290     }
    291     else {
    292         usearch_close(result);
    293     }
    294     ubrk_close(breakiter);
    295 #endif
    296     close();
    297 }
    298 
    299 static void TestInitialization(void)
    300 {
    301           UErrorCode      status = U_ZERO_ERROR;
    302           UChar           pattern[512];
    303     const UChar           text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
    304     int32_t i = 0;
    305     UStringSearch  *result;
    306 
    307     /* simple test on the pattern ce construction */
    308     pattern[0] = 0x41;
    309     pattern[1] = 0x42;
    310     open(&status);
    311     if (U_FAILURE(status)) {
    312         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    313         return;
    314     }
    315     result = usearch_openFromCollator(pattern, 2, text, 3, EN_US_, NULL,
    316                                       &status);
    317     if (U_FAILURE(status)) {
    318         log_err("Error opening search %s\n", u_errorName(status));
    319     }
    320     usearch_close(result);
    321 
    322     /* testing if an extremely large pattern will fail the initialization */
    323     for(i = 0; i < 512; i++) {
    324       pattern[i] = 0x41;
    325     }
    326     /*uprv_memset(pattern, 0x41, 512);*/
    327     result = usearch_openFromCollator(pattern, 512, text, 3, EN_US_, NULL,
    328                                       &status);
    329     if (U_FAILURE(status)) {
    330         log_err("Error opening search %s\n", u_errorName(status));
    331     }
    332     usearch_close(result);
    333     close();
    334 }
    335 
    336 static UBool assertEqualWithUStringSearch(      UStringSearch *strsrch,
    337                                           const SearchData     search)
    338 {
    339     int         count       = 0;
    340     UErrorCode  status      = U_ZERO_ERROR;
    341     int32_t matchindex  = search.offset[count];
    342     int32_t     textlength;
    343     UChar       matchtext[128];
    344     int32_t     matchlength;
    345     int32_t     nextStart;
    346     UBool       isOverlap;
    347 
    348     usearch_setAttribute(strsrch, USEARCH_ELEMENT_COMPARISON, search.elemCompare, &status);
    349     if (U_FAILURE(status)) {
    350         log_err("Error setting USEARCH_ELEMENT_COMPARISON attribute %s\n", u_errorName(status));
    351         return FALSE;
    352     }
    353 
    354     if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
    355         usearch_getMatchedLength(strsrch) != 0) {
    356         log_err("Error with the initialization of match start and length\n");
    357     }
    358     /* start of next matches */
    359     while (U_SUCCESS(status) && matchindex >= 0) {
    360         matchlength = search.size[count];
    361         usearch_next(strsrch, &status);
    362         if (matchindex != usearch_getMatchedStart(strsrch) ||
    363             matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
    364             char *str = toCharString(usearch_getText(strsrch, &textlength));
    365             log_err("Text: %s\n", str);
    366             str = toCharString(usearch_getPattern(strsrch, &textlength));
    367             log_err("Pattern: %s\n", str);
    368             log_err("Error next match found at idx %d (len:%d); expected %d (len:%d)\n",
    369                     usearch_getMatchedStart(strsrch), usearch_getMatchedLength(strsrch),
    370                     matchindex, matchlength);
    371             return FALSE;
    372         }
    373         count ++;
    374 
    375         if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
    376             (int32_t) matchlength || U_FAILURE(status) ||
    377             memcmp(matchtext,
    378                    usearch_getText(strsrch, &textlength) + matchindex,
    379                    matchlength * sizeof(UChar)) != 0) {
    380             log_err("Error getting next matched text\n");
    381         }
    382 
    383         matchindex = search.offset[count];
    384     }
    385     usearch_next(strsrch, &status);
    386     if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
    387         usearch_getMatchedLength(strsrch) != 0) {
    388         char *str = toCharString(usearch_getText(strsrch, &textlength));
    389         log_err("Text: %s\n", str);
    390         str = toCharString(usearch_getPattern(strsrch, &textlength));
    391         log_err("Pattern: %s\n", str);
    392         log_err("Error next match found at %d (len:%d); expected <NO MATCH>\n",
    393                     usearch_getMatchedStart(strsrch),
    394                     usearch_getMatchedLength(strsrch));
    395         return FALSE;
    396     }
    397     /* start of previous matches */
    398     count = count == 0 ? 0 : count - 1;
    399     matchindex = search.offset[count];
    400 
    401     while (U_SUCCESS(status) && matchindex >= 0) {
    402         matchlength = search.size[count];
    403         usearch_previous(strsrch, &status);
    404         if (matchindex != usearch_getMatchedStart(strsrch) ||
    405             matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
    406             char *str = toCharString(usearch_getText(strsrch, &textlength));
    407             log_err("Text: %s\n", str);
    408             str = toCharString(usearch_getPattern(strsrch, &textlength));
    409             log_err("Pattern: %s\n", str);
    410             log_err("Error previous match found at %d (len:%d); expected %d (len:%d)\n",
    411                     usearch_getMatchedStart(strsrch), usearch_getMatchedLength(strsrch),
    412                     matchindex, matchlength);
    413             return FALSE;
    414         }
    415 
    416         if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
    417             (int32_t) matchlength || U_FAILURE(status) ||
    418             memcmp(matchtext,
    419                    usearch_getText(strsrch, &textlength) + matchindex,
    420                    matchlength * sizeof(UChar)) != 0) {
    421             log_err("Error getting previous matched text\n");
    422         }
    423 
    424         matchindex = count > 0 ? search.offset[count - 1] : -1;
    425         count --;
    426     }
    427     usearch_previous(strsrch, &status);
    428     if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
    429         usearch_getMatchedLength(strsrch) != 0) {
    430         char *str = toCharString(usearch_getText(strsrch, &textlength));
    431         log_err("Text: %s\n", str);
    432         str = toCharString(usearch_getPattern(strsrch, &textlength));
    433         log_err("Pattern: %s\n", str);
    434         log_err("Error previous match found at %d (len:%d); expected <NO MATCH>\n",
    435                     usearch_getMatchedStart(strsrch),
    436                     usearch_getMatchedLength(strsrch));
    437         return FALSE;
    438     }
    439 
    440 
    441     isOverlap = (usearch_getAttribute(strsrch, USEARCH_OVERLAP) == USEARCH_ON);
    442 
    443     /* start of following matches */
    444     count = 0;
    445     matchindex  = search.offset[count];
    446     nextStart = 0;
    447 
    448     while (TRUE) {
    449         usearch_following(strsrch, nextStart, &status);
    450 
    451         if (matchindex < 0) {
    452             if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || usearch_getMatchedLength(strsrch) != 0) {
    453                 char *str = toCharString(usearch_getText(strsrch, &textlength));
    454                 log_err("Text: %s\n", str);
    455                 str = toCharString(usearch_getPattern(strsrch, &textlength));
    456                 log_err("Pattern: %s\n", str);
    457                 log_err("Error following match starting at %d (overlap:%d) found at %d (len:%d); expected <NO MATCH>\n",
    458                             nextStart, isOverlap,
    459                             usearch_getMatchedStart(strsrch),
    460                             usearch_getMatchedLength(strsrch));
    461                 return FALSE;
    462             }
    463             /* no more matches */
    464             break;
    465         }
    466 
    467         matchlength = search.size[count];
    468         if (usearch_getMatchedStart(strsrch) != matchindex
    469                 || usearch_getMatchedLength(strsrch) != matchlength
    470                 || U_FAILURE(status)) {
    471             char *str = toCharString(usearch_getText(strsrch, &textlength));
    472             log_err("Text: %s\n", str);
    473             str = toCharString(usearch_getPattern(strsrch, &textlength));
    474             log_err("Pattern: %s\n", str);
    475             log_err("Error following match starting at %d (overlap: %d) found at %d (len:%d); expected %d (len:%d)\n",
    476                         nextStart, isOverlap,
    477                         usearch_getMatchedStart(strsrch), usearch_getMatchedLength(strsrch),
    478                         matchindex, matchlength);
    479             return FALSE;
    480         }
    481 
    482         if (isOverlap || usearch_getMatchedLength(strsrch) == 0) {
    483             nextStart = usearch_getMatchedStart(strsrch) + 1;
    484         } else {
    485             nextStart = usearch_getMatchedStart(strsrch) + usearch_getMatchedLength(strsrch);
    486         }
    487 
    488         count++;
    489         matchindex = search.offset[count];
    490     }
    491 
    492     /* start of preceding matches */
    493     count = -1; /* last non-negative offset index, could be -1 if no match */
    494     while (search.offset[count + 1] >= 0) {
    495         count++;
    496     }
    497     usearch_getText(strsrch, &nextStart);
    498 
    499     while (TRUE) {
    500         usearch_preceding(strsrch, nextStart, &status);
    501 
    502         if (count < 0) {
    503             if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || usearch_getMatchedLength(strsrch) != 0) {
    504                 char *str = toCharString(usearch_getText(strsrch, &textlength));
    505                 log_err("Text: %s\n", str);
    506                 str = toCharString(usearch_getPattern(strsrch, &textlength));
    507                 log_err("Pattern: %s\n", str);
    508                 log_err("Error preceding match starting at %d (overlap: %d) found at %d (len:%d); expected <NO MATCH>\n",
    509                             nextStart, isOverlap,
    510                             usearch_getMatchedStart(strsrch),
    511                             usearch_getMatchedLength(strsrch));
    512                 return FALSE;
    513             }
    514             /* no more matches */
    515             break;
    516         }
    517 
    518         matchindex = search.offset[count];
    519         matchlength = search.size[count];
    520         if (usearch_getMatchedStart(strsrch) != matchindex
    521                 || usearch_getMatchedLength(strsrch) != matchlength
    522                 || U_FAILURE(status)) {
    523             char *str = toCharString(usearch_getText(strsrch, &textlength));
    524             log_err("Text: %s\n", str);
    525             str = toCharString(usearch_getPattern(strsrch, &textlength));
    526             log_err("Pattern: %s\n", str);
    527             log_err("Error preceding match starting at %d (overlap: %d) found at %d (len:%d); expected %d (len:%d)\n",
    528                         nextStart, isOverlap,
    529                         usearch_getMatchedStart(strsrch), usearch_getMatchedLength(strsrch),
    530                         matchindex, matchlength);
    531             return FALSE;
    532         }
    533 
    534         nextStart = matchindex;
    535         count--;
    536     }
    537 
    538     usearch_setAttribute(strsrch, USEARCH_ELEMENT_COMPARISON, USEARCH_STANDARD_ELEMENT_COMPARISON, &status);
    539     return TRUE;
    540 }
    541 
    542 static UBool assertEqual(const SearchData search)
    543 {
    544     UErrorCode      status      = U_ZERO_ERROR;
    545     UChar           pattern[32];
    546     UChar           text[128];
    547     UCollator      *collator = getCollator(search.collator);
    548     UBreakIterator *breaker  = getBreakIterator(search.breaker);
    549     UStringSearch  *strsrch;
    550 
    551     CHECK_BREAK_BOOL(search.breaker);
    552 
    553     u_unescape(search.text, text, 128);
    554     u_unescape(search.pattern, pattern, 32);
    555     ucol_setStrength(collator, search.strength);
    556     strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
    557                                        breaker, &status);
    558     if (U_FAILURE(status)) {
    559         log_err("Error opening string search %s\n", u_errorName(status));
    560         return FALSE;
    561     }
    562 
    563     if (!assertEqualWithUStringSearch(strsrch, search)) {
    564         ucol_setStrength(collator, UCOL_TERTIARY);
    565         usearch_close(strsrch);
    566         return FALSE;
    567     }
    568     ucol_setStrength(collator, UCOL_TERTIARY);
    569     usearch_close(strsrch);
    570     return TRUE;
    571 }
    572 
    573 static UBool assertCanonicalEqual(const SearchData search)
    574 {
    575     UErrorCode      status      = U_ZERO_ERROR;
    576     UChar           pattern[32];
    577     UChar           text[128];
    578     UCollator      *collator = getCollator(search.collator);
    579     UBreakIterator *breaker  = getBreakIterator(search.breaker);
    580     UStringSearch  *strsrch;
    581     UBool           result = TRUE;
    582 
    583     CHECK_BREAK_BOOL(search.breaker);
    584     u_unescape(search.text, text, 128);
    585     u_unescape(search.pattern, pattern, 32);
    586     ucol_setStrength(collator, search.strength);
    587     ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    588     strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
    589                                        breaker, &status);
    590     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
    591                          &status);
    592     if (U_FAILURE(status)) {
    593         log_err("Error opening string search %s\n", u_errorName(status));
    594         result = FALSE;
    595         goto bail;
    596     }
    597 
    598     if (!assertEqualWithUStringSearch(strsrch, search)) {
    599         ucol_setStrength(collator, UCOL_TERTIARY);
    600         usearch_close(strsrch);
    601         result = FALSE;
    602         goto bail;
    603     }
    604 
    605 bail:
    606     ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
    607     ucol_setStrength(collator, UCOL_TERTIARY);
    608     usearch_close(strsrch);
    609     return result;
    610 }
    611 
    612 static UBool assertEqualWithAttribute(const SearchData            search,
    613                                             USearchAttributeValue canonical,
    614                                             USearchAttributeValue overlap)
    615 {
    616     UErrorCode      status      = U_ZERO_ERROR;
    617     UChar           pattern[32];
    618     UChar           text[128];
    619     UCollator      *collator = getCollator(search.collator);
    620     UBreakIterator *breaker  = getBreakIterator(search.breaker);
    621     UStringSearch  *strsrch;
    622 
    623     CHECK_BREAK_BOOL(search.breaker);
    624     u_unescape(search.text, text, 128);
    625     u_unescape(search.pattern, pattern, 32);
    626     ucol_setStrength(collator, search.strength);
    627     strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
    628                                        breaker, &status);
    629     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, canonical,
    630                          &status);
    631     usearch_setAttribute(strsrch, USEARCH_OVERLAP, overlap, &status);
    632 
    633     if (U_FAILURE(status)) {
    634         log_err("Error opening string search %s\n", u_errorName(status));
    635         return FALSE;
    636     }
    637 
    638     if (!assertEqualWithUStringSearch(strsrch, search)) {
    639             ucol_setStrength(collator, UCOL_TERTIARY);
    640             usearch_close(strsrch);
    641             return FALSE;
    642     }
    643     ucol_setStrength(collator, UCOL_TERTIARY);
    644     usearch_close(strsrch);
    645     return TRUE;
    646 }
    647 
    648 static void TestBasic(void)
    649 {
    650     int count = 0;
    651     UErrorCode status = U_ZERO_ERROR;
    652     open(&status);
    653     if (U_FAILURE(status)) {
    654         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    655         return;
    656     }
    657     while (BASIC[count].text != NULL) {
    658         if (!assertEqual(BASIC[count])) {
    659             log_err("Error at test number %d\n", count);
    660         }
    661         count ++;
    662     }
    663     close();
    664 }
    665 
    666 static void TestNormExact(void)
    667 {
    668     int count = 0;
    669     UErrorCode status = U_ZERO_ERROR;
    670     open(&status);
    671     if (U_FAILURE(status)) {
    672         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    673         return;
    674     }
    675     ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
    676     if (U_FAILURE(status)) {
    677         log_err("Error setting collation normalization %s\n",
    678             u_errorName(status));
    679     }
    680     while (BASIC[count].text != NULL) {
    681         if (!assertEqual(BASIC[count])) {
    682             log_err("Error at test number %d\n", count);
    683         }
    684         count ++;
    685     }
    686     count = 0;
    687     while (NORMEXACT[count].text != NULL) {
    688         if (!assertEqual(NORMEXACT[count])) {
    689             log_err("Error at test number %d\n", count);
    690         }
    691         count ++;
    692     }
    693     ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
    694     count = 0;
    695     while (NONNORMEXACT[count].text != NULL) {
    696         if (!assertEqual(NONNORMEXACT[count])) {
    697             log_err("Error at test number %d\n", count);
    698         }
    699         count ++;
    700     }
    701     close();
    702 }
    703 
    704 static void TestStrength(void)
    705 {
    706     int count = 0;
    707     UErrorCode status = U_ZERO_ERROR;
    708     open(&status);
    709     if (U_FAILURE(status)) {
    710         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    711         return;
    712     }
    713     while (STRENGTH[count].text != NULL) {
    714         if (!assertEqual(STRENGTH[count])) {
    715             log_err("Error at test number %d\n", count);
    716         }
    717         count ++;
    718     }
    719     close();
    720 }
    721 
    722 static void TestBreakIterator(void) {
    723     UErrorCode      status      = U_ZERO_ERROR;
    724     UStringSearch  *strsrch;
    725     UChar           text[128];
    726     UChar           pattern[32];
    727     int             count = 0;
    728 
    729     CHECK_BREAK("x");
    730 
    731 #if !UCONFIG_NO_BREAK_ITERATION
    732     open(&status);
    733     if (U_FAILURE(status)) {
    734         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    735         return;
    736     }
    737     if (usearch_getBreakIterator(NULL) != NULL) {
    738         log_err("Expected NULL breakiterator from NULL string search\n");
    739     }
    740     u_unescape(BREAKITERATOREXACT[0].text, text, 128);
    741     u_unescape(BREAKITERATOREXACT[0].pattern, pattern, 32);
    742     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, NULL,
    743                                        &status);
    744     if (U_FAILURE(status)) {
    745         log_err("Error opening string search %s\n", u_errorName(status));
    746         goto ENDTESTBREAKITERATOR;
    747     }
    748 
    749     usearch_setBreakIterator(strsrch, NULL, &status);
    750     if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != NULL) {
    751         log_err("Error usearch_getBreakIterator returned wrong object");
    752         goto ENDTESTBREAKITERATOR;
    753     }
    754 
    755     usearch_setBreakIterator(strsrch, EN_CHARACTERBREAKER_, &status);
    756     if (U_FAILURE(status) ||
    757         usearch_getBreakIterator(strsrch) != EN_CHARACTERBREAKER_) {
    758         log_err("Error usearch_getBreakIterator returned wrong object");
    759         goto ENDTESTBREAKITERATOR;
    760     }
    761 
    762     usearch_setBreakIterator(strsrch, EN_WORDBREAKER_, &status);
    763     if (U_FAILURE(status) ||
    764         usearch_getBreakIterator(strsrch) != EN_WORDBREAKER_) {
    765         log_err("Error usearch_getBreakIterator returned wrong object");
    766         goto ENDTESTBREAKITERATOR;
    767     }
    768 
    769     usearch_close(strsrch);
    770 
    771     count = 0;
    772     while (count < 4) {
    773         /* 0-3 test are fixed */
    774         const SearchData     *search   = &(BREAKITERATOREXACT[count]);
    775               UCollator      *collator = getCollator(search->collator);
    776               UBreakIterator *breaker  = getBreakIterator(search->breaker);
    777 
    778         u_unescape(search->text, text, 128);
    779         u_unescape(search->pattern, pattern, 32);
    780         ucol_setStrength(collator, search->strength);
    781 
    782         strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
    783                                            breaker, &status);
    784         if (U_FAILURE(status) ||
    785             usearch_getBreakIterator(strsrch) != breaker) {
    786             log_err("Error setting break iterator\n");
    787             if (strsrch != NULL) {
    788                 usearch_close(strsrch);
    789             }
    790         }
    791         if (!assertEqualWithUStringSearch(strsrch, *search)) {
    792             ucol_setStrength(collator, UCOL_TERTIARY);
    793             usearch_close(strsrch);
    794             goto ENDTESTBREAKITERATOR;
    795         }
    796         search   = &(BREAKITERATOREXACT[count + 1]);
    797         breaker  = getBreakIterator(search->breaker);
    798         usearch_setBreakIterator(strsrch, breaker, &status);
    799         if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != breaker) {
    800             log_err("Error setting break iterator\n");
    801             usearch_close(strsrch);
    802             goto ENDTESTBREAKITERATOR;
    803         }
    804         usearch_reset(strsrch);
    805         if (!assertEqualWithUStringSearch(strsrch, *search)) {
    806             log_err("Error at test number %d\n", count);
    807             usearch_close(strsrch);
    808             goto ENDTESTBREAKITERATOR;
    809         }
    810         usearch_close(strsrch);
    811         count += 2;
    812     }
    813     count = 0;
    814     while (BREAKITERATOREXACT[count].text != NULL) {
    815          if (!assertEqual(BREAKITERATOREXACT[count])) {
    816              log_err("Error at test number %d\n", count);
    817              goto ENDTESTBREAKITERATOR;
    818          }
    819          count ++;
    820     }
    821 
    822 ENDTESTBREAKITERATOR:
    823     close();
    824 #endif
    825 }
    826 
    827 static void TestVariable(void)
    828 {
    829     int count = 0;
    830     UErrorCode status = U_ZERO_ERROR;
    831     open(&status);
    832     if (U_FAILURE(status)) {
    833         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    834         return;
    835     }
    836     ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
    837     if (U_FAILURE(status)) {
    838         log_err("Error setting collation alternate attribute %s\n",
    839             u_errorName(status));
    840     }
    841     while (VARIABLE[count].text != NULL) {
    842         log_verbose("variable %d\n", count);
    843         if (!assertEqual(VARIABLE[count])) {
    844             log_err("Error at test number %d\n", count);
    845         }
    846         count ++;
    847     }
    848     ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
    849                       UCOL_NON_IGNORABLE, &status);
    850     close();
    851 }
    852 
    853 static void TestOverlap(void)
    854 {
    855     int count = 0;
    856     UErrorCode status = U_ZERO_ERROR;
    857     open(&status);
    858     if (U_FAILURE(status)) {
    859         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
    860         return;
    861     }
    862     while (OVERLAP[count].text != NULL) {
    863         if (!assertEqualWithAttribute(OVERLAP[count], USEARCH_OFF,
    864                                       USEARCH_ON)) {
    865             log_err("Error at overlap test number %d\n", count);
    866         }
    867         count ++;
    868     }
    869     count = 0;
    870     while (NONOVERLAP[count].text != NULL) {
    871         if (!assertEqual(NONOVERLAP[count])) {
    872             log_err("Error at non overlap test number %d\n", count);
    873         }
    874         count ++;
    875     }
    876 
    877     count = 0;
    878     while (count < 1) {
    879               UChar           pattern[32];
    880               UChar           text[128];
    881         const SearchData     *search   = &(OVERLAP[count]);
    882               UCollator      *collator = getCollator(search->collator);
    883               UStringSearch  *strsrch;
    884               status   = U_ZERO_ERROR;
    885 
    886         u_unescape(search->text, text, 128);
    887         u_unescape(search->pattern, pattern, 32);
    888         strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
    889                                            NULL, &status);
    890         if(status == U_FILE_ACCESS_ERROR) {
    891           log_data_err("Is your data around?\n");
    892           return;
    893         } else if(U_FAILURE(status)) {
    894           log_err("Error opening searcher\n");
    895           return;
    896         }
    897         usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
    898         if (U_FAILURE(status) ||
    899             usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
    900             log_err("Error setting overlap option\n");
    901         }
    902         if (!assertEqualWithUStringSearch(strsrch, *search)) {
    903             usearch_close(strsrch);
    904             return;
    905         }
    906         search   = &(NONOVERLAP[count]);
    907         usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
    908         if (U_FAILURE(status) ||
    909             usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
    910             log_err("Error setting overlap option\n");
    911         }
    912         usearch_reset(strsrch);
    913         if (!assertEqualWithUStringSearch(strsrch, *search)) {
    914             usearch_close(strsrch);
    915             log_err("Error at test number %d\n", count);
    916          }
    917 
    918         count ++;
    919         usearch_close(strsrch);
    920     }
    921     close();
    922 }
    923 
    924 static void TestCollator(void)
    925 {
    926     /* test collator that thinks "o" and "p" are the same thing */
    927           UChar          rules[32];
    928           UCollator     *tailored = NULL;
    929           UErrorCode     status   = U_ZERO_ERROR;
    930           UChar          pattern[32];
    931           UChar          text[128];
    932           UStringSearch *strsrch;
    933 
    934     text[0] = 0x41;
    935     text[1] = 0x42;
    936     text[2] = 0x43;
    937     text[3] = 0x44;
    938     text[4] = 0x45;
    939     pattern[0] = 0x62;
    940     pattern[1] = 0x63;
    941     strsrch  = usearch_open(pattern, 2, text, 5, "en_US",  NULL,  &status);
    942     if(status == U_FILE_ACCESS_ERROR) {
    943       log_data_err("Is your data around?\n");
    944       return;
    945     } else if(U_FAILURE(status)) {
    946       log_err("Error opening searcher\n");
    947       return;
    948     }
    949     tailored = usearch_getCollator(strsrch);
    950     if (usearch_next(strsrch, &status) != -1) {
    951         log_err("Error: Found case insensitive match, when we shouldn't\n");
    952     }
    953     ucol_setStrength(tailored, UCOL_PRIMARY);
    954     usearch_reset(strsrch);
    955     if (usearch_next(strsrch, &status) != 1) {
    956         log_err("Error: Found case insensitive match not found\n");
    957     }
    958     usearch_close(strsrch);
    959 
    960     open(&status);
    961 
    962     if (usearch_getCollator(NULL) != NULL) {
    963         log_err("Expected NULL collator from NULL string search\n");
    964     }
    965     u_unescape(COLLATOR[0].text, text, 128);
    966     u_unescape(COLLATOR[0].pattern, pattern, 32);
    967 
    968     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
    969                                        NULL, &status);
    970     if (U_FAILURE(status)) {
    971         log_err("Error opening string search %s\n", u_errorName(status));
    972     }
    973     if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
    974         goto ENDTESTCOLLATOR;
    975     }
    976 
    977     u_unescape(TESTCOLLATORRULE, rules, 32);
    978     tailored = ucol_openRules(rules, -1, UCOL_ON, COLLATOR[1].strength,
    979                               NULL, &status);
    980     if (U_FAILURE(status)) {
    981         log_err("Error opening rule based collator %s\n", u_errorName(status));
    982     }
    983 
    984     usearch_setCollator(strsrch, tailored, &status);
    985     if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
    986         log_err("Error setting rule based collator\n");
    987     }
    988     usearch_reset(strsrch);
    989     if (!assertEqualWithUStringSearch(strsrch, COLLATOR[1])) {
    990         goto ENDTESTCOLLATOR;
    991     }
    992 
    993     usearch_setCollator(strsrch, EN_US_, &status);
    994     usearch_reset(strsrch);
    995     if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
    996         log_err("Error setting rule based collator\n");
    997     }
    998     if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
    999         goto ENDTESTCOLLATOR;
   1000     }
   1001 
   1002 ENDTESTCOLLATOR:
   1003     usearch_close(strsrch);
   1004     if (tailored != NULL) {
   1005         ucol_close(tailored);
   1006     }
   1007     close();
   1008 }
   1009 
   1010 static void TestPattern(void)
   1011 {
   1012           UStringSearch *strsrch;
   1013           UChar          pattern[32];
   1014           UChar          bigpattern[512];
   1015           UChar          text[128];
   1016     const UChar         *temp;
   1017           int32_t        templength;
   1018           UErrorCode     status = U_ZERO_ERROR;
   1019 
   1020     open(&status);
   1021     if (U_FAILURE(status)) {
   1022         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1023         return;
   1024     }
   1025     if (usearch_getPattern(NULL, &templength) != NULL) {
   1026         log_err("Error NULL string search expected returning NULL pattern\n");
   1027     }
   1028     usearch_setPattern(NULL, pattern, 3, &status);
   1029     if (U_SUCCESS(status)) {
   1030         log_err("Error expected setting pattern in NULL strings search\n");
   1031     }
   1032     status = U_ZERO_ERROR;
   1033     u_unescape(PATTERN[0].text, text, 128);
   1034     u_unescape(PATTERN[0].pattern, pattern, 32);
   1035 
   1036     ucol_setStrength(EN_US_, PATTERN[0].strength);
   1037     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   1038                                        NULL, &status);
   1039     if(status == U_FILE_ACCESS_ERROR) {
   1040       log_data_err("Is your data around?\n");
   1041       return;
   1042     } else if(U_FAILURE(status)) {
   1043       log_err("Error opening searcher\n");
   1044       return;
   1045     }
   1046 
   1047     status = U_ZERO_ERROR;
   1048     usearch_setPattern(strsrch, NULL, 3, &status);
   1049     if (U_SUCCESS(status)) {
   1050         log_err("Error expected setting NULL pattern in strings search\n");
   1051     }
   1052     status = U_ZERO_ERROR;
   1053     usearch_setPattern(strsrch, pattern, 0, &status);
   1054     if (U_SUCCESS(status)) {
   1055         log_err("Error expected setting pattern with length 0 in strings search\n");
   1056     }
   1057     status = U_ZERO_ERROR;
   1058     if (U_FAILURE(status)) {
   1059         log_err("Error opening string search %s\n", u_errorName(status));
   1060         goto ENDTESTPATTERN;
   1061     }
   1062     temp = usearch_getPattern(strsrch, &templength);
   1063     if (u_strcmp(pattern, temp) != 0) {
   1064         log_err("Error setting pattern\n");
   1065     }
   1066     if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
   1067         goto ENDTESTPATTERN;
   1068     }
   1069 
   1070     u_unescape(PATTERN[1].pattern, pattern, 32);
   1071     usearch_setPattern(strsrch, pattern, -1, &status);
   1072     temp = usearch_getPattern(strsrch, &templength);
   1073     if (u_strcmp(pattern, temp) != 0) {
   1074         log_err("Error setting pattern\n");
   1075         goto ENDTESTPATTERN;
   1076     }
   1077     usearch_reset(strsrch);
   1078     if (U_FAILURE(status)) {
   1079         log_err("Error setting pattern %s\n", u_errorName(status));
   1080     }
   1081     if (!assertEqualWithUStringSearch(strsrch, PATTERN[1])) {
   1082         goto ENDTESTPATTERN;
   1083     }
   1084 
   1085     u_unescape(PATTERN[0].pattern, pattern, 32);
   1086     usearch_setPattern(strsrch, pattern, -1, &status);
   1087     temp = usearch_getPattern(strsrch, &templength);
   1088     if (u_strcmp(pattern, temp) != 0) {
   1089         log_err("Error setting pattern\n");
   1090         goto ENDTESTPATTERN;
   1091     }
   1092     usearch_reset(strsrch);
   1093     if (U_FAILURE(status)) {
   1094         log_err("Error setting pattern %s\n", u_errorName(status));
   1095     }
   1096     if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
   1097         goto ENDTESTPATTERN;
   1098     }
   1099     /* enormous pattern size to see if this crashes */
   1100     for (templength = 0; templength != 512; templength ++) {
   1101         bigpattern[templength] = 0x61;
   1102     }
   1103     bigpattern[511] = 0;
   1104     usearch_setPattern(strsrch, bigpattern, -1, &status);
   1105     if (U_FAILURE(status)) {
   1106         log_err("Error setting pattern with size 512, %s \n",
   1107             u_errorName(status));
   1108     }
   1109 ENDTESTPATTERN:
   1110     ucol_setStrength(EN_US_, UCOL_TERTIARY);
   1111     if (strsrch != NULL) {
   1112         usearch_close(strsrch);
   1113     }
   1114     close();
   1115 }
   1116 
   1117 static void TestText(void)
   1118 {
   1119           UStringSearch *strsrch;
   1120           UChar          pattern[32];
   1121           UChar          text[128];
   1122     const UChar         *temp;
   1123           int32_t        templength;
   1124           UErrorCode     status = U_ZERO_ERROR;
   1125 
   1126     u_unescape(TEXT[0].text, text, 128);
   1127     u_unescape(TEXT[0].pattern, pattern, 32);
   1128 
   1129     open(&status);
   1130     if (U_FAILURE(status)) {
   1131         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1132         return;
   1133     }
   1134 
   1135     if (usearch_getText(NULL, &templength) != NULL) {
   1136         log_err("Error NULL string search should return NULL text\n");
   1137     }
   1138 
   1139     usearch_setText(NULL, text, 10, &status);
   1140     if (U_SUCCESS(status)) {
   1141         log_err("Error NULL string search should have an error when setting text\n");
   1142     }
   1143 
   1144     status = U_ZERO_ERROR;
   1145     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   1146                                        NULL, &status);
   1147 
   1148     if (U_FAILURE(status)) {
   1149         log_err("Error opening string search %s\n", u_errorName(status));
   1150         goto ENDTESTPATTERN;
   1151     }
   1152     temp = usearch_getText(strsrch, &templength);
   1153     if (u_strcmp(text, temp) != 0) {
   1154         log_err("Error setting text\n");
   1155     }
   1156     if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
   1157         goto ENDTESTPATTERN;
   1158     }
   1159 
   1160     u_unescape(TEXT[1].text, text, 32);
   1161     usearch_setText(strsrch, text, -1, &status);
   1162     temp = usearch_getText(strsrch, &templength);
   1163     if (u_strcmp(text, temp) != 0) {
   1164         log_err("Error setting text\n");
   1165         goto ENDTESTPATTERN;
   1166     }
   1167     if (U_FAILURE(status)) {
   1168         log_err("Error setting text %s\n", u_errorName(status));
   1169     }
   1170     if (!assertEqualWithUStringSearch(strsrch, TEXT[1])) {
   1171         goto ENDTESTPATTERN;
   1172     }
   1173 
   1174     u_unescape(TEXT[0].text, text, 32);
   1175     usearch_setText(strsrch, text, -1, &status);
   1176     temp = usearch_getText(strsrch, &templength);
   1177     if (u_strcmp(text, temp) != 0) {
   1178         log_err("Error setting text\n");
   1179         goto ENDTESTPATTERN;
   1180     }
   1181     if (U_FAILURE(status)) {
   1182         log_err("Error setting pattern %s\n", u_errorName(status));
   1183     }
   1184     if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
   1185         goto ENDTESTPATTERN;
   1186     }
   1187 ENDTESTPATTERN:
   1188     if (strsrch != NULL) {
   1189         usearch_close(strsrch);
   1190     }
   1191     close();
   1192 }
   1193 
   1194 static void TestCompositeBoundaries(void)
   1195 {
   1196     int count = 0;
   1197     UErrorCode status = U_ZERO_ERROR;
   1198     open(&status);
   1199     if (U_FAILURE(status)) {
   1200         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1201         return;
   1202     }
   1203     while (COMPOSITEBOUNDARIES[count].text != NULL) {
   1204         log_verbose("composite %d\n", count);
   1205         if (!assertEqual(COMPOSITEBOUNDARIES[count])) {
   1206             log_err("Error at test number %d\n", count);
   1207         }
   1208         count ++;
   1209     }
   1210     close();
   1211 }
   1212 
   1213 static void TestGetSetOffset(void)
   1214 {
   1215     int            searchDataIndex   = 0;
   1216     UChar          pattern[32];
   1217     UChar          text[128];
   1218     UErrorCode     status  = U_ZERO_ERROR;
   1219     UStringSearch *strsrch;
   1220     memset(pattern, 0, 32*sizeof(UChar));
   1221     memset(text, 0, 128*sizeof(UChar));
   1222 
   1223     open(&status);
   1224     if (U_FAILURE(status)) {
   1225         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1226         return;
   1227     }
   1228     if (usearch_getOffset(NULL) != USEARCH_DONE) {
   1229         log_err("usearch_getOffset(NULL) expected USEARCH_DONE\n");
   1230     }
   1231     strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
   1232                                        &status);
   1233     /* testing out of bounds error */
   1234     usearch_setOffset(strsrch, -1, &status);
   1235     if (U_SUCCESS(status)) {
   1236         log_err("Error expecting set offset error\n");
   1237     }
   1238     usearch_setOffset(strsrch, 128, &status);
   1239     if (U_SUCCESS(status)) {
   1240         log_err("Error expecting set offset error\n");
   1241     }
   1242     while (BASIC[searchDataIndex].text != NULL) {
   1243         int         count       = 0;
   1244         SearchData  search      = BASIC[searchDataIndex ++];
   1245         int32_t matchindex  = search.offset[count];
   1246         int32_t     textlength;
   1247 
   1248         u_unescape(search.text, text, 128);
   1249         u_unescape(search.pattern, pattern, 32);
   1250         status = U_ZERO_ERROR;
   1251         usearch_setText(strsrch, text, -1, &status);
   1252         usearch_setPattern(strsrch, pattern, -1, &status);
   1253         ucol_setStrength(usearch_getCollator(strsrch), search.strength);
   1254         usearch_reset(strsrch);
   1255         while (U_SUCCESS(status) && matchindex >= 0) {
   1256             uint32_t matchlength = search.size[count];
   1257             usearch_next(strsrch, &status);
   1258             if (matchindex != usearch_getMatchedStart(strsrch) ||
   1259                 matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
   1260                 char *str = toCharString(usearch_getText(strsrch,
   1261                                                          &textlength));
   1262                 log_err("Text: %s\n", str);
   1263                 str = toCharString(usearch_getPattern(strsrch, &textlength));
   1264                 log_err("Pattern: %s\n", str);
   1265                 log_err("Error match found at %d %d\n",
   1266                         usearch_getMatchedStart(strsrch),
   1267                         usearch_getMatchedLength(strsrch));
   1268                 return;
   1269             }
   1270             usearch_setOffset(strsrch, matchindex + matchlength, &status);
   1271             usearch_previous(strsrch, &status);
   1272             if (matchindex != usearch_getMatchedStart(strsrch) ||
   1273                 matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
   1274                 char *str = toCharString(usearch_getText(strsrch,
   1275                                                          &textlength));
   1276                 log_err("Text: %s\n", str);
   1277                 str = toCharString(usearch_getPattern(strsrch, &textlength));
   1278                 log_err("Pattern: %s\n", str);
   1279                 log_err("Error match found at %d %d\n",
   1280                         usearch_getMatchedStart(strsrch),
   1281                         usearch_getMatchedLength(strsrch));
   1282                 return;
   1283             }
   1284             usearch_setOffset(strsrch, matchindex + matchlength, &status);
   1285             matchindex = search.offset[count + 1] == -1 ? -1 :
   1286                          search.offset[count + 2];
   1287             if (search.offset[count + 1] != -1) {
   1288                 usearch_setOffset(strsrch, search.offset[count + 1] + 1,
   1289                                   &status);
   1290                 if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
   1291                     log_err("Error setting offset\n");
   1292                     return;
   1293                 }
   1294             }
   1295 
   1296             count += 2;
   1297         }
   1298         usearch_next(strsrch, &status);
   1299         if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
   1300             char *str = toCharString(usearch_getText(strsrch, &textlength));
   1301             log_err("Text: %s\n", str);
   1302             str = toCharString(usearch_getPattern(strsrch, &textlength));
   1303             log_err("Pattern: %s\n", str);
   1304             log_err("Error match found at %d %d\n",
   1305                         usearch_getMatchedStart(strsrch),
   1306                         usearch_getMatchedLength(strsrch));
   1307             return;
   1308         }
   1309     }
   1310     ucol_setStrength(usearch_getCollator(strsrch), UCOL_TERTIARY);
   1311     usearch_close(strsrch);
   1312     close();
   1313 }
   1314 
   1315 static void TestGetSetAttribute(void)
   1316 {
   1317     UErrorCode      status    = U_ZERO_ERROR;
   1318     UChar           pattern[32];
   1319     UChar           text[128];
   1320     UStringSearch  *strsrch;
   1321 
   1322     memset(pattern, 0, 32*sizeof(UChar));
   1323     memset(text, 0, 128*sizeof(UChar));
   1324 
   1325     open(&status);
   1326     if (U_FAILURE(status)) {
   1327         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1328         return;
   1329     }
   1330     if (usearch_getAttribute(NULL, USEARCH_OVERLAP) != USEARCH_DEFAULT ||
   1331         usearch_getAttribute(NULL, USEARCH_CANONICAL_MATCH) !=
   1332                                                          USEARCH_DEFAULT) {
   1333         log_err(
   1334             "Attributes for NULL string search should be USEARCH_DEFAULT\n");
   1335     }
   1336     strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
   1337                                        &status);
   1338     if (U_FAILURE(status)) {
   1339         log_err("Error opening search %s\n", u_errorName(status));
   1340         return;
   1341     }
   1342 
   1343     usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_DEFAULT, &status);
   1344     if (U_FAILURE(status) ||
   1345         usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
   1346         log_err("Error setting overlap to the default\n");
   1347     }
   1348     usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
   1349     if (U_FAILURE(status) ||
   1350         usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
   1351         log_err("Error setting overlap true\n");
   1352     }
   1353     usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
   1354     if (U_FAILURE(status) ||
   1355         usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
   1356         log_err("Error setting overlap false\n");
   1357     }
   1358     usearch_setAttribute(strsrch, USEARCH_OVERLAP,
   1359                          USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
   1360     if (U_SUCCESS(status)) {
   1361         log_err("Error setting overlap to illegal value\n");
   1362     }
   1363     status = U_ZERO_ERROR;
   1364     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT,
   1365                          &status);
   1366     if (U_FAILURE(status) ||
   1367         usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
   1368                                                         USEARCH_OFF) {
   1369         log_err("Error setting canonical match to the default\n");
   1370     }
   1371     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   1372                          &status);
   1373     if (U_FAILURE(status) ||
   1374         usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
   1375                                                          USEARCH_ON) {
   1376         log_err("Error setting canonical match true\n");
   1377     }
   1378     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_OFF,
   1379                          &status);
   1380     if (U_FAILURE(status) ||
   1381         usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
   1382                                                         USEARCH_OFF) {
   1383         log_err("Error setting canonical match false\n");
   1384     }
   1385     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH,
   1386                          USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
   1387     if (U_SUCCESS(status)) {
   1388         log_err("Error setting canonical match to illegal value\n");
   1389     }
   1390     status = U_ZERO_ERROR;
   1391     usearch_setAttribute(strsrch, USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT,
   1392                          &status);
   1393     if (U_SUCCESS(status)) {
   1394         log_err("Error setting illegal attribute success\n");
   1395     }
   1396 
   1397     usearch_close(strsrch);
   1398     close();
   1399 }
   1400 
   1401 static void TestGetMatch(void)
   1402 {
   1403     int            count       = 0;
   1404     UErrorCode     status      = U_ZERO_ERROR;
   1405     UChar          text[128];
   1406     UChar          pattern[32];
   1407     SearchData     search      = MATCH[0];
   1408     int32_t    matchindex  = search.offset[count];
   1409     UStringSearch *strsrch;
   1410     int32_t        textlength;
   1411     UChar          matchtext[128];
   1412 
   1413     open(&status);
   1414     if (U_FAILURE(status)) {
   1415         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1416         return;
   1417     }
   1418 
   1419     if (usearch_getMatchedStart(NULL) != USEARCH_DONE ||
   1420         usearch_getMatchedLength(NULL) != USEARCH_DONE) {
   1421         log_err(
   1422    "Expected start and length of NULL string search should be USEARCH_DONE\n");
   1423     }
   1424 
   1425     u_unescape(search.text, text, 128);
   1426     u_unescape(search.pattern, pattern, 32);
   1427     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   1428                                        NULL, &status);
   1429     if (U_FAILURE(status)) {
   1430         log_err("Error opening string search %s\n", u_errorName(status));
   1431         if (strsrch != NULL) {
   1432             usearch_close(strsrch);
   1433         }
   1434         return;
   1435     }
   1436 
   1437     while (U_SUCCESS(status) && matchindex >= 0) {
   1438         int32_t matchlength = search.size[count];
   1439         usearch_next(strsrch, &status);
   1440         if (matchindex != usearch_getMatchedStart(strsrch) ||
   1441             matchlength != usearch_getMatchedLength(strsrch)) {
   1442             char *str = toCharString(usearch_getText(strsrch, &textlength));
   1443             log_err("Text: %s\n", str);
   1444             str = toCharString(usearch_getPattern(strsrch, &textlength));
   1445             log_err("Pattern: %s\n", str);
   1446             log_err("Error match found at %d %d\n",
   1447                     usearch_getMatchedStart(strsrch),
   1448                     usearch_getMatchedLength(strsrch));
   1449             return;
   1450         }
   1451         count ++;
   1452 
   1453         status = U_ZERO_ERROR;
   1454         if (usearch_getMatchedText(NULL, matchtext, 128, &status) !=
   1455             USEARCH_DONE || U_SUCCESS(status)){
   1456             log_err("Error expecting errors with NULL string search\n");
   1457         }
   1458         status = U_ZERO_ERROR;
   1459         if (usearch_getMatchedText(strsrch, NULL, 0, &status) !=
   1460             (int32_t)matchlength || U_SUCCESS(status)){
   1461             log_err("Error pre-flighting match length\n");
   1462         }
   1463         status = U_ZERO_ERROR;
   1464         if (usearch_getMatchedText(strsrch, matchtext, 0, &status) !=
   1465             (int32_t)matchlength || U_SUCCESS(status)){
   1466             log_err("Error getting match text with buffer size 0\n");
   1467         }
   1468         status = U_ZERO_ERROR;
   1469         if (usearch_getMatchedText(strsrch, matchtext, matchlength, &status)
   1470             != (int32_t)matchlength || matchtext[matchlength - 1] == 0 ||
   1471             U_FAILURE(status)){
   1472             log_err("Error getting match text with exact size\n");
   1473         }
   1474         status = U_ZERO_ERROR;
   1475         if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
   1476             (int32_t) matchlength || U_FAILURE(status) ||
   1477             memcmp(matchtext,
   1478                    usearch_getText(strsrch, &textlength) + matchindex,
   1479                    matchlength * sizeof(UChar)) != 0 ||
   1480             matchtext[matchlength] != 0) {
   1481             log_err("Error getting matched text\n");
   1482         }
   1483 
   1484         matchindex = search.offset[count];
   1485     }
   1486     status = U_ZERO_ERROR;
   1487     usearch_next(strsrch, &status);
   1488     if (usearch_getMatchedStart(strsrch)  != USEARCH_DONE ||
   1489         usearch_getMatchedLength(strsrch) != 0) {
   1490         log_err("Error end of match not found\n");
   1491     }
   1492     status = U_ZERO_ERROR;
   1493     if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
   1494         USEARCH_DONE) {
   1495         log_err("Error getting null matches\n");
   1496     }
   1497     usearch_close(strsrch);
   1498     close();
   1499 }
   1500 
   1501 static void TestSetMatch(void)
   1502 {
   1503     int            count       = 0;
   1504     UErrorCode status = U_ZERO_ERROR;
   1505     open(&status);
   1506     if (U_FAILURE(status)) {
   1507         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1508         return;
   1509     }
   1510     while (MATCH[count].text != NULL) {
   1511         SearchData     search = MATCH[count];
   1512         int            size   = 0;
   1513         int            offsetIndex = 0;
   1514         UChar          text[128];
   1515         UChar          pattern[32];
   1516         UStringSearch *strsrch;
   1517         status = U_ZERO_ERROR;
   1518 
   1519         if (usearch_first(NULL, &status) != USEARCH_DONE ||
   1520             usearch_last(NULL, &status) != USEARCH_DONE) {
   1521             log_err("Error getting the first and last match of a NULL string search\n");
   1522         }
   1523         u_unescape(search.text, text, 128);
   1524         u_unescape(search.pattern, pattern, 32);
   1525         strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   1526                                            NULL, &status);
   1527         if (U_FAILURE(status)) {
   1528             log_err("Error opening string search %s\n", u_errorName(status));
   1529             if (strsrch != NULL) {
   1530                 usearch_close(strsrch);
   1531             }
   1532             return;
   1533         }
   1534 
   1535         size = 0;
   1536         while (search.offset[size] != -1) {
   1537             size ++;
   1538         }
   1539 
   1540         if (usearch_first(strsrch, &status) != search.offset[0] ||
   1541             U_FAILURE(status)) {
   1542             log_err("Error getting first match\n");
   1543         }
   1544         if (usearch_last(strsrch, &status) != search.offset[size -1] ||
   1545             U_FAILURE(status)) {
   1546             log_err("Error getting last match\n");
   1547         }
   1548 
   1549         while (offsetIndex < size) {
   1550             if (offsetIndex + 2 < size) {
   1551                 if (usearch_following(strsrch, search.offset[offsetIndex + 2] - 1,
   1552                                       &status) != search.offset[offsetIndex + 2] ||
   1553                     U_FAILURE(status)) {
   1554                     log_err("Error getting following match at index %d\n",
   1555                             search.offset[offsetIndex + 2] - 1);
   1556                 }
   1557             }
   1558             if (offsetIndex + 1 < size) {
   1559                 if (usearch_preceding(strsrch, search.offset[offsetIndex + 1] +
   1560                                                search.size[offsetIndex + 1] + 1,
   1561                                       &status) != search.offset[offsetIndex + 1] ||
   1562                     U_FAILURE(status)) {
   1563                     log_err("Error getting preceeding match at index %d\n",
   1564                             search.offset[offsetIndex + 1] + 1);
   1565                 }
   1566             }
   1567             offsetIndex += 2;
   1568         }
   1569         status = U_ZERO_ERROR;
   1570         if (usearch_following(strsrch, u_strlen(text), &status) !=
   1571             USEARCH_DONE) {
   1572             log_err("Error expecting out of bounds match\n");
   1573         }
   1574         if (usearch_preceding(strsrch, 0, &status) != USEARCH_DONE) {
   1575             log_err("Error expecting out of bounds match\n");
   1576         }
   1577         count ++;
   1578         usearch_close(strsrch);
   1579     }
   1580     close();
   1581 }
   1582 
   1583 static void TestReset(void)
   1584 {
   1585     UErrorCode     status    = U_ZERO_ERROR;
   1586     UChar          text[]    = {0x66, 0x69, 0x73, 0x68, 0x20,
   1587                                 0x66, 0x69, 0x73, 0x68};
   1588     UChar          pattern[] = {0x73};
   1589     UStringSearch *strsrch;
   1590 
   1591     open(&status);
   1592     if (U_FAILURE(status)) {
   1593         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1594         return;
   1595     }
   1596     strsrch = usearch_openFromCollator(pattern, 1, text, 9,
   1597                                                       EN_US_, NULL, &status);
   1598     if (U_FAILURE(status)) {
   1599         log_err("Error opening string search %s\n", u_errorName(status));
   1600         if (strsrch != NULL) {
   1601             usearch_close(strsrch);
   1602         }
   1603         return;
   1604     }
   1605     usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
   1606     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   1607                          &status);
   1608     usearch_setOffset(strsrch, 9, &status);
   1609     if (U_FAILURE(status)) {
   1610         log_err("Error setting attributes and offsets\n");
   1611     }
   1612     else {
   1613         usearch_reset(strsrch);
   1614         if (usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF ||
   1615             usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
   1616                                  USEARCH_OFF ||
   1617             usearch_getOffset(strsrch) != 0 ||
   1618             usearch_getMatchedLength(strsrch) != 0 ||
   1619             usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
   1620             log_err("Error resetting string search\n");
   1621         }
   1622         usearch_previous(strsrch, &status);
   1623         if (usearch_getMatchedStart(strsrch) != 7 ||
   1624             usearch_getMatchedLength(strsrch) != 1) {
   1625             log_err("Error resetting string search\n");
   1626         }
   1627     }
   1628     usearch_close(strsrch);
   1629     close();
   1630 }
   1631 
   1632 static void TestSupplementary(void)
   1633 {
   1634     int count = 0;
   1635     UErrorCode status = U_ZERO_ERROR;
   1636     open(&status);
   1637     if (U_FAILURE(status)) {
   1638         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1639         return;
   1640     }
   1641     while (SUPPLEMENTARY[count].text != NULL) {
   1642         if (!assertEqual(SUPPLEMENTARY[count])) {
   1643             log_err("Error at test number %d\n", count);
   1644         }
   1645         count ++;
   1646     }
   1647     close();
   1648 }
   1649 
   1650 static void TestContraction(void)
   1651 {
   1652     UChar          rules[128];
   1653     UChar          pattern[128];
   1654     UChar          text[128];
   1655     UCollator     *collator;
   1656     UErrorCode     status = U_ZERO_ERROR;
   1657     int            count = 0;
   1658     UStringSearch *strsrch;
   1659     memset(rules, 0, 128*sizeof(UChar));
   1660     memset(pattern, 0, 128*sizeof(UChar));
   1661     memset(text, 0, 128*sizeof(UChar));
   1662 
   1663     u_unescape(CONTRACTIONRULE, rules, 128);
   1664     collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
   1665                               UCOL_TERTIARY, NULL, &status);
   1666     if(status == U_FILE_ACCESS_ERROR) {
   1667       log_data_err("Is your data around?\n");
   1668       return;
   1669     } else if(U_FAILURE(status)) {
   1670       log_err("Error opening collator %s\n", u_errorName(status));
   1671       return;
   1672     }
   1673     strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
   1674                                        &status);
   1675     if (U_FAILURE(status)) {
   1676         log_err("Error opening string search %s\n", u_errorName(status));
   1677     }
   1678 
   1679     while (CONTRACTION[count].text != NULL) {
   1680         u_unescape(CONTRACTION[count].text, text, 128);
   1681         u_unescape(CONTRACTION[count].pattern, pattern, 128);
   1682         usearch_setText(strsrch, text, -1, &status);
   1683         usearch_setPattern(strsrch, pattern, -1, &status);
   1684         if (!assertEqualWithUStringSearch(strsrch, CONTRACTION[count])) {
   1685             log_err("Error at test number %d\n", count);
   1686         }
   1687         count ++;
   1688     }
   1689     usearch_close(strsrch);
   1690     ucol_close(collator);
   1691 }
   1692 
   1693 static void TestIgnorable(void)
   1694 {
   1695     UChar          rules[128];
   1696     UChar          pattern[128];
   1697     UChar          text[128];
   1698     UCollator     *collator;
   1699     UErrorCode     status = U_ZERO_ERROR;
   1700     UStringSearch *strsrch;
   1701     uint32_t       count = 0;
   1702 
   1703     memset(rules, 0, 128*sizeof(UChar));
   1704     memset(pattern, 0, 128*sizeof(UChar));
   1705     memset(text, 0, 128*sizeof(UChar));
   1706 
   1707     u_unescape(IGNORABLERULE, rules, 128);
   1708     collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
   1709                               IGNORABLE[count].strength, NULL, &status);
   1710     if(status == U_FILE_ACCESS_ERROR) {
   1711       log_data_err("Is your data around?\n");
   1712       return;
   1713     } else if(U_FAILURE(status)) {
   1714         log_err("Error opening collator %s\n", u_errorName(status));
   1715         return;
   1716     }
   1717     strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
   1718                                        &status);
   1719     if (U_FAILURE(status)) {
   1720         log_err("Error opening string search %s\n", u_errorName(status));
   1721     }
   1722 
   1723     while (IGNORABLE[count].text != NULL) {
   1724         u_unescape(IGNORABLE[count].text, text, 128);
   1725         u_unescape(IGNORABLE[count].pattern, pattern, 128);
   1726         usearch_setText(strsrch, text, -1, &status);
   1727         usearch_setPattern(strsrch, pattern, -1, &status);
   1728         if (!assertEqualWithUStringSearch(strsrch, IGNORABLE[count])) {
   1729             log_err("Error at test number %d\n", count);
   1730         }
   1731         count ++;
   1732     }
   1733     usearch_close(strsrch);
   1734     ucol_close(collator);
   1735 }
   1736 
   1737 static void TestDiacriticMatch(void)
   1738 {
   1739     UChar          pattern[128];
   1740     UChar          text[128];
   1741     UErrorCode     status = U_ZERO_ERROR;
   1742     UStringSearch *strsrch = NULL;
   1743     UCollator *coll = NULL;
   1744     uint32_t       count = 0;
   1745     SearchData search;
   1746 
   1747     memset(pattern, 0, 128*sizeof(UChar));
   1748     memset(text, 0, 128*sizeof(UChar));
   1749 
   1750     strsrch = usearch_open(pattern, 1, text, 1, uloc_getDefault(), NULL, &status);
   1751     if (U_FAILURE(status)) {
   1752         log_err_status(status, "Error opening string search %s\n", u_errorName(status));
   1753         return;
   1754     }
   1755 
   1756     search = DIACRITICMATCH[count];
   1757     while (search.text != NULL) {
   1758         if (search.collator != NULL) {
   1759             coll = ucol_openFromShortString(search.collator, FALSE, NULL, &status);
   1760         } else {
   1761             /* Always use "en_US" because some of these tests fail in Danish locales. */
   1762             coll = ucol_open("en_US"/*uloc_getDefault()*/, &status);
   1763             ucol_setStrength(coll, search.strength);
   1764         }
   1765         if (U_FAILURE(status)) {
   1766             log_err("Error opening string search collator(\"%s\") %s\n", search.collator, u_errorName(status));
   1767             return;
   1768         }
   1769 
   1770         usearch_setCollator(strsrch, coll, &status);
   1771         if (U_FAILURE(status)) {
   1772             log_err("Error setting string search collator %s\n", u_errorName(status));
   1773             return;
   1774         }
   1775 
   1776         u_unescape(search.text, text, 128);
   1777         u_unescape(search.pattern, pattern, 128);
   1778         usearch_setText(strsrch, text, -1, &status);
   1779         usearch_setPattern(strsrch, pattern, -1, &status);
   1780         if (!assertEqualWithUStringSearch(strsrch, search)) {
   1781             log_err("Error at test number %d\n", count);
   1782         }
   1783         ucol_close(coll);
   1784 
   1785         search = DIACRITICMATCH[++count];
   1786     }
   1787     usearch_close(strsrch);
   1788 }
   1789 
   1790 static void TestCanonical(void)
   1791 {
   1792     int count = 0;
   1793     UErrorCode status = U_ZERO_ERROR;
   1794     open(&status);
   1795     if (U_FAILURE(status)) {
   1796         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1797         return;
   1798     }
   1799     while (BASICCANONICAL[count].text != NULL) {
   1800         if (!assertCanonicalEqual(BASICCANONICAL[count])) {
   1801             log_err("Error at test number %d\n", count);
   1802         }
   1803         count ++;
   1804     }
   1805     close();
   1806 }
   1807 
   1808 static void TestNormCanonical(void)
   1809 {
   1810     int count = 0;
   1811     UErrorCode status = U_ZERO_ERROR;
   1812     open(&status);
   1813     if (U_FAILURE(status)) {
   1814         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1815         return;
   1816     }
   1817     ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
   1818     count = 0;
   1819     while (NORMCANONICAL[count].text != NULL) {
   1820         if (!assertCanonicalEqual(NORMCANONICAL[count])) {
   1821             log_err("Error at test number %d\n", count);
   1822         }
   1823         count ++;
   1824     }
   1825     ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
   1826     close();
   1827 }
   1828 
   1829 static void TestStrengthCanonical(void)
   1830 {
   1831     int count = 0;
   1832     UErrorCode status = U_ZERO_ERROR;
   1833     open(&status);
   1834     if (U_FAILURE(status)) {
   1835         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1836         return;
   1837     }
   1838     while (STRENGTHCANONICAL[count].text != NULL) {
   1839         if (!assertCanonicalEqual(STRENGTHCANONICAL[count])) {
   1840             log_err("Error at test number %d\n", count);
   1841         }
   1842         count ++;
   1843     }
   1844     close();
   1845 }
   1846 
   1847 static void TestBreakIteratorCanonical(void) {
   1848     UErrorCode      status      = U_ZERO_ERROR;
   1849     int             count = 0;
   1850 
   1851     CHECK_BREAK("x");
   1852 
   1853 #if !UCONFIG_NO_BREAK_ITERATION
   1854 
   1855     open(&status);
   1856     if (U_FAILURE(status)) {
   1857         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1858         return;
   1859     }
   1860     while (count < 4) {
   1861         /* 0-3 test are fixed */
   1862               UChar           pattern[32];
   1863               UChar           text[128];
   1864         const SearchData     *search   = &(BREAKITERATORCANONICAL[count]);
   1865               UCollator      *collator = getCollator(search->collator);
   1866               UBreakIterator *breaker  = getBreakIterator(search->breaker);
   1867               UStringSearch  *strsrch;
   1868 
   1869         u_unescape(search->text, text, 128);
   1870         u_unescape(search->pattern, pattern, 32);
   1871         ucol_setStrength(collator, search->strength);
   1872 
   1873         strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
   1874                                            breaker, &status);
   1875         if(status == U_FILE_ACCESS_ERROR) {
   1876             log_data_err("Is your data around?\n");
   1877             goto ENDTESTBREAKITERATOR;
   1878         } else if(U_FAILURE(status)) {
   1879             log_err("Error opening searcher\n");
   1880             goto ENDTESTBREAKITERATOR;
   1881         }
   1882         usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   1883                              &status);
   1884         if (U_FAILURE(status) ||
   1885             usearch_getBreakIterator(strsrch) != breaker) {
   1886             log_err("Error setting break iterator\n");
   1887             usearch_close(strsrch);
   1888             goto ENDTESTBREAKITERATOR;
   1889         }
   1890         if (!assertEqualWithUStringSearch(strsrch, *search)) {
   1891             ucol_setStrength(collator, UCOL_TERTIARY);
   1892             usearch_close(strsrch);
   1893             goto ENDTESTBREAKITERATOR;
   1894         }
   1895         search   = &(BREAKITERATOREXACT[count + 1]);
   1896         breaker  = getBreakIterator(search->breaker);
   1897         usearch_setBreakIterator(strsrch, breaker, &status);
   1898         if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != breaker) {
   1899             log_err("Error setting break iterator\n");
   1900             usearch_close(strsrch);
   1901             goto ENDTESTBREAKITERATOR;
   1902         }
   1903         usearch_reset(strsrch);
   1904         usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   1905                              &status);
   1906         if (!assertEqualWithUStringSearch(strsrch, *search)) {
   1907             log_err("Error at test number %d\n", count);
   1908             usearch_close(strsrch);
   1909             goto ENDTESTBREAKITERATOR;
   1910         }
   1911         usearch_close(strsrch);
   1912         count += 2;
   1913     }
   1914     count = 0;
   1915     while (BREAKITERATORCANONICAL[count].text != NULL) {
   1916          if (!assertEqual(BREAKITERATORCANONICAL[count])) {
   1917              log_err("Error at test number %d\n", count);
   1918              goto ENDTESTBREAKITERATOR;
   1919          }
   1920          count ++;
   1921     }
   1922 
   1923 ENDTESTBREAKITERATOR:
   1924     close();
   1925 #endif
   1926 }
   1927 
   1928 static void TestVariableCanonical(void)
   1929 {
   1930     int count = 0;
   1931     UErrorCode status = U_ZERO_ERROR;
   1932     open(&status);
   1933     if (U_FAILURE(status)) {
   1934         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1935         return;
   1936     }
   1937     ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
   1938     if (U_FAILURE(status)) {
   1939         log_err("Error setting collation alternate attribute %s\n",
   1940             u_errorName(status));
   1941     }
   1942     while (VARIABLE[count].text != NULL) {
   1943         log_verbose("variable %d\n", count);
   1944         if (!assertCanonicalEqual(VARIABLE[count])) {
   1945             log_err("Error at test number %d\n", count);
   1946         }
   1947         count ++;
   1948     }
   1949     ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
   1950                       UCOL_NON_IGNORABLE, &status);
   1951     close();
   1952 }
   1953 
   1954 static void TestOverlapCanonical(void)
   1955 {
   1956     int count = 0;
   1957     UErrorCode status = U_ZERO_ERROR;
   1958     open(&status);
   1959     if (U_FAILURE(status)) {
   1960         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   1961         return;
   1962     }
   1963     while (OVERLAPCANONICAL[count].text != NULL) {
   1964         if (!assertEqualWithAttribute(OVERLAPCANONICAL[count], USEARCH_ON,
   1965                                       USEARCH_ON)) {
   1966             log_err("Error at overlap test number %d\n", count);
   1967         }
   1968         count ++;
   1969     }
   1970     count = 0;
   1971     while (NONOVERLAP[count].text != NULL) {
   1972         if (!assertCanonicalEqual(NONOVERLAPCANONICAL[count])) {
   1973             log_err("Error at non overlap test number %d\n", count);
   1974         }
   1975         count ++;
   1976     }
   1977 
   1978     count = 0;
   1979     while (count < 1) {
   1980               UChar           pattern[32];
   1981               UChar           text[128];
   1982         const SearchData     *search   = &(OVERLAPCANONICAL[count]);
   1983               UCollator      *collator = getCollator(search->collator);
   1984               UStringSearch  *strsrch;
   1985               status   = U_ZERO_ERROR;
   1986 
   1987         u_unescape(search->text, text, 128);
   1988         u_unescape(search->pattern, pattern, 32);
   1989         strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
   1990                                            NULL, &status);
   1991         if(status == U_FILE_ACCESS_ERROR) {
   1992           log_data_err("Is your data around?\n");
   1993           return;
   1994         } else if(U_FAILURE(status)) {
   1995           log_err("Error opening searcher\n");
   1996           return;
   1997         }
   1998         usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   1999                              &status);
   2000         usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
   2001         if (U_FAILURE(status) ||
   2002             usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
   2003             log_err("Error setting overlap option\n");
   2004         }
   2005         if (!assertEqualWithUStringSearch(strsrch, *search)) {
   2006             usearch_close(strsrch);
   2007             return;
   2008         }
   2009         search   = &(NONOVERLAPCANONICAL[count]);
   2010         usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
   2011         if (U_FAILURE(status) ||
   2012             usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
   2013             log_err("Error setting overlap option\n");
   2014         }
   2015         usearch_reset(strsrch);
   2016         if (!assertEqualWithUStringSearch(strsrch, *search)) {
   2017             usearch_close(strsrch);
   2018             log_err("Error at test number %d\n", count);
   2019          }
   2020 
   2021         count ++;
   2022         usearch_close(strsrch);
   2023     }
   2024     close();
   2025 }
   2026 
   2027 static void TestCollatorCanonical(void)
   2028 {
   2029     /* test collator that thinks "o" and "p" are the same thing */
   2030           UChar          rules[32];
   2031           UCollator     *tailored = NULL;
   2032           UErrorCode     status = U_ZERO_ERROR;
   2033           UChar          pattern[32];
   2034           UChar          text[128];
   2035           UStringSearch *strsrch;
   2036 
   2037     open(&status);
   2038     if (U_FAILURE(status)) {
   2039         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2040         return;
   2041     }
   2042     u_unescape(COLLATORCANONICAL[0].text, text, 128);
   2043     u_unescape(COLLATORCANONICAL[0].pattern, pattern, 32);
   2044 
   2045     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   2046                                        NULL, &status);
   2047     if(status == U_FILE_ACCESS_ERROR) {
   2048       log_data_err("Is your data around?\n");
   2049       return;
   2050     } else if(U_FAILURE(status)) {
   2051       log_err("Error opening searcher\n");
   2052       return;
   2053     }
   2054     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2055                          &status);
   2056     if (U_FAILURE(status)) {
   2057         log_err("Error opening string search %s\n", u_errorName(status));
   2058     }
   2059     if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
   2060         goto ENDTESTCOLLATOR;
   2061     }
   2062 
   2063     u_unescape(TESTCOLLATORRULE, rules, 32);
   2064     tailored = ucol_openRules(rules, -1, UCOL_ON,
   2065                               COLLATORCANONICAL[1].strength, NULL, &status);
   2066     if (U_FAILURE(status)) {
   2067         log_err("Error opening rule based collator %s\n", u_errorName(status));
   2068     }
   2069 
   2070     usearch_setCollator(strsrch, tailored, &status);
   2071     if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
   2072         log_err("Error setting rule based collator\n");
   2073     }
   2074     usearch_reset(strsrch);
   2075     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2076                          &status);
   2077     if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[1])) {
   2078         goto ENDTESTCOLLATOR;
   2079     }
   2080 
   2081     usearch_setCollator(strsrch, EN_US_, &status);
   2082     usearch_reset(strsrch);
   2083     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2084                          &status);
   2085     if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
   2086         log_err("Error setting rule based collator\n");
   2087     }
   2088     if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
   2089         goto ENDTESTCOLLATOR;
   2090     }
   2091 
   2092 ENDTESTCOLLATOR:
   2093     usearch_close(strsrch);
   2094     if (tailored != NULL) {
   2095         ucol_close(tailored);
   2096     }
   2097     close();
   2098 }
   2099 
   2100 static void TestPatternCanonical(void)
   2101 {
   2102           UStringSearch *strsrch;
   2103           UChar          pattern[32];
   2104           UChar          text[128];
   2105     const UChar         *temp;
   2106           int32_t        templength;
   2107           UErrorCode     status = U_ZERO_ERROR;
   2108 
   2109     open(&status);
   2110     if (U_FAILURE(status)) {
   2111         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2112         return;
   2113     }
   2114     u_unescape(PATTERNCANONICAL[0].text, text, 128);
   2115     u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
   2116 
   2117     ucol_setStrength(EN_US_, PATTERNCANONICAL[0].strength);
   2118     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   2119                                        NULL, &status);
   2120     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2121                          &status);
   2122     if (U_FAILURE(status)) {
   2123         log_err("Error opening string search %s\n", u_errorName(status));
   2124         goto ENDTESTPATTERN;
   2125     }
   2126     temp = usearch_getPattern(strsrch, &templength);
   2127     if (u_strcmp(pattern, temp) != 0) {
   2128         log_err("Error setting pattern\n");
   2129     }
   2130     if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
   2131         goto ENDTESTPATTERN;
   2132     }
   2133 
   2134     u_unescape(PATTERNCANONICAL[1].pattern, pattern, 32);
   2135     usearch_setPattern(strsrch, pattern, -1, &status);
   2136     temp = usearch_getPattern(strsrch, &templength);
   2137     if (u_strcmp(pattern, temp) != 0) {
   2138         log_err("Error setting pattern\n");
   2139         goto ENDTESTPATTERN;
   2140     }
   2141     usearch_reset(strsrch);
   2142     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2143                          &status);
   2144     if (U_FAILURE(status)) {
   2145         log_err("Error setting pattern %s\n", u_errorName(status));
   2146     }
   2147     if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[1])) {
   2148         goto ENDTESTPATTERN;
   2149     }
   2150 
   2151     u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
   2152     usearch_setPattern(strsrch, pattern, -1, &status);
   2153     temp = usearch_getPattern(strsrch, &templength);
   2154     if (u_strcmp(pattern, temp) != 0) {
   2155         log_err("Error setting pattern\n");
   2156         goto ENDTESTPATTERN;
   2157     }
   2158     usearch_reset(strsrch);
   2159     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2160                          &status);
   2161     if (U_FAILURE(status)) {
   2162         log_err("Error setting pattern %s\n", u_errorName(status));
   2163     }
   2164     if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
   2165         goto ENDTESTPATTERN;
   2166     }
   2167 ENDTESTPATTERN:
   2168     ucol_setStrength(EN_US_, UCOL_TERTIARY);
   2169     if (strsrch != NULL) {
   2170         usearch_close(strsrch);
   2171     }
   2172     close();
   2173 }
   2174 
   2175 static void TestTextCanonical(void)
   2176 {
   2177           UStringSearch *strsrch;
   2178           UChar          pattern[32];
   2179           UChar          text[128];
   2180     const UChar         *temp;
   2181           int32_t        templength;
   2182           UErrorCode     status = U_ZERO_ERROR;
   2183 
   2184     u_unescape(TEXTCANONICAL[0].text, text, 128);
   2185     u_unescape(TEXTCANONICAL[0].pattern, pattern, 32);
   2186 
   2187     open(&status);
   2188     if (U_FAILURE(status)) {
   2189         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2190         return;
   2191     }
   2192     strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
   2193                                        NULL, &status);
   2194     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2195                          &status);
   2196 
   2197     if (U_FAILURE(status)) {
   2198         log_err("Error opening string search %s\n", u_errorName(status));
   2199         goto ENDTESTPATTERN;
   2200     }
   2201     temp = usearch_getText(strsrch, &templength);
   2202     if (u_strcmp(text, temp) != 0) {
   2203         log_err("Error setting text\n");
   2204     }
   2205     if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
   2206         goto ENDTESTPATTERN;
   2207     }
   2208 
   2209     u_unescape(TEXTCANONICAL[1].text, text, 32);
   2210     usearch_setText(strsrch, text, -1, &status);
   2211     temp = usearch_getText(strsrch, &templength);
   2212     if (u_strcmp(text, temp) != 0) {
   2213         log_err("Error setting text\n");
   2214         goto ENDTESTPATTERN;
   2215     }
   2216     if (U_FAILURE(status)) {
   2217         log_err("Error setting text %s\n", u_errorName(status));
   2218     }
   2219     if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[1])) {
   2220         goto ENDTESTPATTERN;
   2221     }
   2222 
   2223     u_unescape(TEXTCANONICAL[0].text, text, 32);
   2224     usearch_setText(strsrch, text, -1, &status);
   2225     temp = usearch_getText(strsrch, &templength);
   2226     if (u_strcmp(text, temp) != 0) {
   2227         log_err("Error setting text\n");
   2228         goto ENDTESTPATTERN;
   2229     }
   2230     if (U_FAILURE(status)) {
   2231         log_err("Error setting pattern %s\n", u_errorName(status));
   2232     }
   2233     if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
   2234         goto ENDTESTPATTERN;
   2235     }
   2236 ENDTESTPATTERN:
   2237     if (strsrch != NULL) {
   2238         usearch_close(strsrch);
   2239     }
   2240     close();
   2241 }
   2242 
   2243 static void TestCompositeBoundariesCanonical(void)
   2244 {
   2245     int count = 0;
   2246     UErrorCode status = U_ZERO_ERROR;
   2247     open(&status);
   2248     if (U_FAILURE(status)) {
   2249         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2250         return;
   2251     }
   2252     while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
   2253         log_verbose("composite %d\n", count);
   2254         if (!assertCanonicalEqual(COMPOSITEBOUNDARIESCANONICAL[count])) {
   2255             log_err("Error at test number %d\n", count);
   2256         }
   2257         count ++;
   2258     }
   2259     close();
   2260 }
   2261 
   2262 static void TestGetSetOffsetCanonical(void)
   2263 {
   2264     int            searchDataIndex   = 0;
   2265     UChar          pattern[32];
   2266     UChar          text[128];
   2267     UErrorCode     status  = U_ZERO_ERROR;
   2268     UStringSearch *strsrch;
   2269     UCollator     *collator;
   2270 
   2271     memset(pattern, 0, 32*sizeof(UChar));
   2272     memset(text, 0, 128*sizeof(UChar));
   2273 
   2274     open(&status);
   2275     if (U_FAILURE(status)) {
   2276         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2277         return;
   2278     }
   2279     strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
   2280                                        &status);
   2281 
   2282     collator = usearch_getCollator(strsrch);
   2283     ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
   2284 
   2285     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2286                          &status);
   2287 
   2288     /* testing out of bounds error */
   2289     usearch_setOffset(strsrch, -1, &status);
   2290     if (U_SUCCESS(status)) {
   2291         log_err("Error expecting set offset error\n");
   2292     }
   2293     usearch_setOffset(strsrch, 128, &status);
   2294     if (U_SUCCESS(status)) {
   2295         log_err("Error expecting set offset error\n");
   2296     }
   2297     while (BASICCANONICAL[searchDataIndex].text != NULL) {
   2298         int         count       = 0;
   2299         SearchData  search      = BASICCANONICAL[searchDataIndex ++];
   2300         int32_t matchindex  = search.offset[count];
   2301         int32_t     textlength;
   2302 
   2303         if (BASICCANONICAL[searchDataIndex].text == NULL) {
   2304             /* skip the last one */
   2305             break;
   2306         }
   2307 
   2308         u_unescape(search.text, text, 128);
   2309         u_unescape(search.pattern, pattern, 32);
   2310         status = U_ZERO_ERROR;
   2311         usearch_setText(strsrch, text, -1, &status);
   2312         usearch_setPattern(strsrch, pattern, -1, &status);
   2313         while (U_SUCCESS(status) && matchindex >= 0) {
   2314             uint32_t matchlength = search.size[count];
   2315             usearch_next(strsrch, &status);
   2316             if (matchindex != usearch_getMatchedStart(strsrch) ||
   2317                 matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
   2318                 char *str = toCharString(usearch_getText(strsrch,
   2319                                                          &textlength));
   2320                 log_err("Text: %s\n", str);
   2321                 str = toCharString(usearch_getPattern(strsrch, &textlength));
   2322                 log_err("Pattern: %s\n", str);
   2323                 log_err("Error match found at %d %d\n",
   2324                         usearch_getMatchedStart(strsrch),
   2325                         usearch_getMatchedLength(strsrch));
   2326                 goto bail;
   2327             }
   2328             matchindex = search.offset[count + 1] == -1 ? -1 :
   2329                          search.offset[count + 2];
   2330             if (search.offset[count + 1] != -1) {
   2331                 usearch_setOffset(strsrch, search.offset[count + 1] + 1,
   2332                                   &status);
   2333                 if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
   2334                     log_err("Error setting offset\n");
   2335                     goto bail;
   2336                 }
   2337             }
   2338 
   2339             count += 2;
   2340         }
   2341         usearch_next(strsrch, &status);
   2342         if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
   2343             char *str = toCharString(usearch_getText(strsrch, &textlength));
   2344             log_err("Text: %s\n", str);
   2345             str = toCharString(usearch_getPattern(strsrch, &textlength));
   2346             log_err("Pattern: %s\n", str);
   2347             log_err("Error match found at %d %d\n",
   2348                         usearch_getMatchedStart(strsrch),
   2349                         usearch_getMatchedLength(strsrch));
   2350             goto bail;
   2351         }
   2352     }
   2353 
   2354 bail:
   2355     ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
   2356     usearch_close(strsrch);
   2357     close();
   2358 }
   2359 
   2360 static void TestSupplementaryCanonical(void)
   2361 {
   2362     int count = 0;
   2363     UErrorCode status = U_ZERO_ERROR;
   2364     open(&status);
   2365     if (U_FAILURE(status)) {
   2366         log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
   2367         return;
   2368     }
   2369     while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
   2370         if (!assertCanonicalEqual(SUPPLEMENTARYCANONICAL[count])) {
   2371             log_err("Error at test number %d\n", count);
   2372         }
   2373         count ++;
   2374     }
   2375     close();
   2376 }
   2377 
   2378 static void TestContractionCanonical(void)
   2379 {
   2380     UChar          rules[128];
   2381     UChar          pattern[128];
   2382     UChar          text[128];
   2383     UCollator     *collator = NULL;
   2384     UErrorCode     status = U_ZERO_ERROR;
   2385     int            count = 0;
   2386     UStringSearch *strsrch = NULL;
   2387     memset(rules, 0, 128*sizeof(UChar));
   2388     memset(pattern, 0, 128*sizeof(UChar));
   2389     memset(text, 0, 128*sizeof(UChar));
   2390 
   2391     u_unescape(CONTRACTIONRULE, rules, 128);
   2392     collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
   2393                               UCOL_TERTIARY, NULL, &status);
   2394     if(status == U_FILE_ACCESS_ERROR) {
   2395       log_data_err("Is your data around?\n");
   2396       return;
   2397     } else if(U_FAILURE(status)) {
   2398       log_err("Error opening collator %s\n", u_errorName(status));
   2399       return;
   2400     }
   2401     strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
   2402                                        &status);
   2403     usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
   2404                          &status);
   2405     if (U_FAILURE(status)) {
   2406         log_err("Error opening string search %s\n", u_errorName(status));
   2407     }
   2408 
   2409     while (CONTRACTIONCANONICAL[count].text != NULL) {
   2410         u_unescape(CONTRACTIONCANONICAL[count].text, text, 128);
   2411         u_unescape(CONTRACTIONCANONICAL[count].pattern, pattern, 128);
   2412         usearch_setText(strsrch, text, -1, &status);
   2413         usearch_setPattern(strsrch, pattern, -1, &status);
   2414         if (!assertEqualWithUStringSearch(strsrch,
   2415                                               CONTRACTIONCANONICAL[count])) {
   2416             log_err("Error at test number %d\n", count);
   2417         }
   2418         count ++;
   2419     }
   2420     usearch_close(strsrch);
   2421     ucol_close(collator);
   2422 }
   2423 
   2424 static void TestNumeric(void) {
   2425     UCollator     *coll = NULL;
   2426     UStringSearch *strsrch = NULL;
   2427     UErrorCode     status = U_ZERO_ERROR;
   2428 
   2429     UChar          pattern[128];
   2430     UChar          text[128];
   2431     memset(pattern, 0, 128*sizeof(UChar));
   2432     memset(text, 0, 128*sizeof(UChar));
   2433 
   2434     coll = ucol_open("", &status);
   2435     if(U_FAILURE(status)) {
   2436         log_data_err("Could not open UCA. Is your data around?\n");
   2437         return;
   2438     }
   2439 
   2440     ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status);
   2441 
   2442     strsrch = usearch_openFromCollator(pattern, 1, text, 1, coll, NULL, &status);
   2443 
   2444     if(status != U_UNSUPPORTED_ERROR || U_SUCCESS(status)) {
   2445         log_err("Expected U_UNSUPPORTED_ERROR when trying to instantiate a search object from a CODAN collator, got %s instead\n", u_errorName(status));
   2446         if(strsrch) {
   2447             usearch_close(strsrch);
   2448         }
   2449     }
   2450 
   2451     ucol_close(coll);
   2452 
   2453 }
   2454 
   2455 /* This test is for ticket 4038 due to incorrect backward searching when certain patterns have a length > 1 */
   2456 static void TestForwardBackward(void) {
   2457     UErrorCode status = U_ZERO_ERROR;
   2458     UCollator *coll = NULL;
   2459     UStringSearch *search = NULL;
   2460     UChar usrcstr[32], value[4];
   2461     int32_t pos= -1;
   2462     int32_t expectedPos = 9;
   2463 
   2464     coll = ucol_open("en_GB", &status);
   2465     if (U_FAILURE(status)) {
   2466         log_err_status(status, "ucol_open failed: %s\n", u_errorName(status));
   2467         goto exitTestForwardBackward;
   2468     }
   2469     ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status);
   2470     ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &status);
   2471     ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
   2472 
   2473     u_uastrcpy(usrcstr, "QBitArray::bitarr_data"); /* text */
   2474     u_uastrcpy(value, "::");                       /* pattern */
   2475 
   2476     search = usearch_openFromCollator(value, 2, usrcstr, 22, coll, NULL, &status);
   2477     if (U_FAILURE(status)) {
   2478         log_err("usearch_openFromCollator failed: %s\n", u_errorName(status));
   2479         goto exitTestForwardBackward;
   2480     }
   2481 
   2482     usearch_reset(search);
   2483     /* forward search */
   2484     pos = usearch_first(search, &status);
   2485     if (pos != expectedPos) {
   2486         log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
   2487         goto exitTestForwardBackward;
   2488     }
   2489 
   2490     pos = -1;
   2491     usearch_reset(search);
   2492     /* backward search */
   2493     pos = usearch_last(search, &status);
   2494     if (pos != expectedPos) {
   2495         log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
   2496     }
   2497 
   2498 exitTestForwardBackward :
   2499     if (coll != NULL) {
   2500         ucol_close(coll);
   2501     }
   2502     if (search != NULL) {
   2503         usearch_close(search);
   2504     }
   2505 }
   2506 
   2507 #define TEST_ASSERT(x) \
   2508    {if (U_FAILURE(x)) {log_err_status(x, "%s:%d: FAIL: test assertion failure \n", __FILE__, __LINE__);\
   2509    }}
   2510 
   2511 static void TestSearchForNull(void) {
   2512     UCollator *coll;
   2513     UErrorCode ec;
   2514     UStringSearch *search;
   2515     int pos;
   2516     int len;
   2517     int expectedPos;
   2518     int expectedLen;
   2519     int expectedNum;
   2520     int count = 0;
   2521     const UChar zerodigit = 0x0030; /* 0 */
   2522     const UChar nulldigit = 0x0000; /* null */
   2523 
   2524     /* static const UChar var[(length)+1]=U_DECLARE_UTF16(cs) */
   2525 #define PATTERN_LEN 4
   2526 #define TEXT_LEN 10
   2527 
   2528     U_STRING_DECL(_pattern, "IS 0", PATTERN_LEN);
   2529     U_STRING_DECL(_text, "_0IS 0 OK?", TEXT_LEN);
   2530     UChar pattern[PATTERN_LEN + 1], text[TEXT_LEN + 1];
   2531 
   2532     U_STRING_INIT(_pattern, "IS 0", PATTERN_LEN);
   2533     U_STRING_INIT(_text, "_0IS 0 OK?", TEXT_LEN);
   2534     expectedPos = 2;
   2535     expectedLen = 4;
   2536     expectedNum = 1;
   2537 
   2538     for (pos = 0; pos < PATTERN_LEN; pos++) {
   2539         if (_pattern[pos] == zerodigit) {
   2540             pattern[pos] = nulldigit;
   2541         } else {
   2542             pattern[pos] = _pattern[pos];
   2543         }
   2544     }
   2545     pattern[PATTERN_LEN] = 0x0000;
   2546 
   2547     for (pos = 0; pos < TEXT_LEN; pos++) {
   2548         if (_text[pos] == zerodigit) {
   2549             text[pos] = nulldigit;
   2550         } else {
   2551             text[pos] = _text[pos];
   2552         }
   2553     }
   2554     text[TEXT_LEN] = 0x0000;
   2555 
   2556     ec = U_ZERO_ERROR;
   2557 
   2558     /* create a US-English collator */
   2559     coll = ucol_open("en_US", &ec);
   2560 
   2561     /* make sure we didn't fail. */
   2562      TEST_ASSERT (ec);
   2563 
   2564     ucol_setStrength(coll, UCOL_IDENTICAL);
   2565 
   2566     /* open a search looking for 0 */
   2567     search = usearch_openFromCollator(pattern, PATTERN_LEN, text,
   2568             TEXT_LEN, coll, NULL, &ec);
   2569      TEST_ASSERT (ec);
   2570 
   2571     if (coll != NULL && search != NULL) {
   2572         pos = usearch_first(search, &ec);
   2573         len = usearch_getMatchedLength(search);
   2574         if (pos != expectedPos) {
   2575             log_err("Expected search result: %d; Got instead: %d\n", expectedPos,
   2576                     pos);
   2577         }
   2578 
   2579         if (len != expectedLen) {
   2580             log_err("Expected search result length: %d; Got instead: %d\n",
   2581                     expectedLen, len);
   2582         }
   2583 
   2584         for (pos = usearch_first(search, &ec); pos != USEARCH_DONE; pos
   2585                 = usearch_next(search, &ec)) {
   2586             log_verbose("Match at %d\n", pos);
   2587             count += 1;
   2588         }
   2589 
   2590         if (count != expectedNum) {
   2591             log_err("Expected %d search hits, found %d\n", expectedNum, count);
   2592         }
   2593     }
   2594 
   2595     ucol_close(coll);
   2596     usearch_close(search);
   2597 }
   2598 
   2599 static void TestStrengthIdentical(void)
   2600 {
   2601     UCollator *coll;
   2602     UErrorCode ec = U_ZERO_ERROR;
   2603     UStringSearch *search;
   2604 
   2605     UChar pattern[] = {0x05E9, 0x0591, 0x05E9};
   2606     UChar text[]    = {0x05E9, 0x0592, 0x05E9};
   2607     int32_t pLen = sizeof (pattern) / sizeof(pattern[0]);
   2608     int32_t tLen = sizeof(text) / sizeof (text[0]);
   2609     int32_t expectedPos = 0;
   2610     int32_t expectedLen = 3;
   2611 
   2612     int32_t pos;
   2613     int32_t len;
   2614 
   2615     /* create a US-English collator */
   2616     coll = ucol_open ("en_US", &ec);
   2617 
   2618     /* make sure we didn't fail. */
   2619     TEST_ASSERT (ec);
   2620 
   2621     ucol_setStrength( coll, UCOL_TERTIARY);
   2622 
   2623     /* open a search looking for 0 */
   2624     search = usearch_openFromCollator (pattern, pLen, text, tLen, coll, NULL, &ec);
   2625     TEST_ASSERT (ec);
   2626 
   2627     if (coll != NULL && search != NULL) {
   2628         pos = usearch_first(search, &ec);
   2629         len = usearch_getMatchedLength(search);
   2630 
   2631         if(pos != expectedPos) {
   2632             log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
   2633         }
   2634 
   2635         if(len != expectedLen) {
   2636             log_err("Expected search result length: %d; Got instead: %d\n", expectedLen, len);
   2637         }
   2638 
   2639         /* Now try it at strength == UCOL_IDENTICAL */
   2640         ucol_setStrength(coll, UCOL_IDENTICAL);
   2641         usearch_reset(search);
   2642 
   2643         pos = usearch_first(search, &ec);
   2644         len = usearch_getMatchedLength(search);
   2645 
   2646         if(pos != -1) {
   2647             log_err("Expected failure for strentgh = UCOL_IDENTICAL: got %d instead.\n", pos);
   2648         }
   2649     }
   2650 
   2651     usearch_close(search);
   2652     ucol_close(coll);
   2653 }
   2654 
   2655 /**
   2656 * TestUsingSearchCollator
   2657 */
   2658 
   2659 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
   2660 
   2661 typedef struct {
   2662     const UChar *   pattern;
   2663     const int32_t * offsets;
   2664     int32_t         offsetsLen;
   2665 } PatternAndOffsets;
   2666 
   2667 static const UChar scKoText[] = {
   2668        0x0020,
   2669 /*01*/ 0xAC00, 0x0020,                         /* simple LV Hangul */
   2670 /*03*/ 0xAC01, 0x0020,                         /* simple LVT Hangul */
   2671 /*05*/ 0xAC0F, 0x0020,                         /* LVTT, last jamo expands for search */
   2672 /*07*/ 0xAFFF, 0x0020,                         /* LLVVVTT, every jamo expands for search */
   2673 /*09*/ 0x1100, 0x1161, 0x11A8, 0x0020,         /* 0xAC01 as conjoining jamo */
   2674 /*13*/ 0x1100, 0x1161, 0x1100, 0x0020,         /* 0xAC01 as basic conjoining jamo (per search rules) */
   2675 /*17*/ 0x3131, 0x314F, 0x3131, 0x0020,         /* 0xAC01 as compatibility jamo */
   2676 /*21*/ 0x1100, 0x1161, 0x11B6, 0x0020,         /* 0xAC0F as conjoining jamo; last expands for search */
   2677 /*25*/ 0x1100, 0x1161, 0x1105, 0x1112, 0x0020, /* 0xAC0F as basic conjoining jamo; last expands for search */
   2678 /*30*/ 0x1101, 0x1170, 0x11B6, 0x0020,         /* 0xAFFF as conjoining jamo; all expand for search */
   2679 /*34*/ 0x00E6, 0x0020,                         /* small letter ae, expands */
   2680 /*36*/ 0x1E4D, 0x0020,                         /* small letter o with tilde and acute, decomposes */
   2681        0
   2682 };
   2683 
   2684 static const UChar scKoPat0[] = { 0xAC01, 0 };
   2685 static const UChar scKoPat1[] = { 0x1100, 0x1161, 0x11A8, 0 }; /* 0xAC01 as conjoining jamo */
   2686 static const UChar scKoPat2[] = { 0xAC0F, 0 };
   2687 static const UChar scKoPat3[] = { 0x1100, 0x1161, 0x1105, 0x1112, 0 }; /* 0xAC0F as basic conjoining jamo */
   2688 static const UChar scKoPat4[] = { 0xAFFF, 0 };
   2689 static const UChar scKoPat5[] = { 0x1101, 0x1170, 0x11B6, 0 }; /* 0xAFFF as conjoining jamo */
   2690 
   2691 static const int32_t scKoSrchOff01[] = { 3,  9, 13 };
   2692 static const int32_t scKoSrchOff23[] = { 5, 21, 25 };
   2693 static const int32_t scKoSrchOff45[] = { 7, 30     };
   2694 
   2695 static const PatternAndOffsets scKoSrchPatternsOffsets[] = {
   2696     { scKoPat0, scKoSrchOff01, ARRAY_LENGTH(scKoSrchOff01) },
   2697     { scKoPat1, scKoSrchOff01, ARRAY_LENGTH(scKoSrchOff01) },
   2698     { scKoPat2, scKoSrchOff23, ARRAY_LENGTH(scKoSrchOff23) },
   2699     { scKoPat3, scKoSrchOff23, ARRAY_LENGTH(scKoSrchOff23) },
   2700     { scKoPat4, scKoSrchOff45, ARRAY_LENGTH(scKoSrchOff45) },
   2701     { scKoPat5, scKoSrchOff45, ARRAY_LENGTH(scKoSrchOff45) },
   2702     { NULL,     NULL,          0                           }
   2703 };
   2704 
   2705 static const int32_t scKoStndOff01[] = { 3,  9 };
   2706 static const int32_t scKoStndOff2[]  = { 5, 21 };
   2707 static const int32_t scKoStndOff3[]  = { 25    };
   2708 static const int32_t scKoStndOff45[] = { 7, 30 };
   2709 
   2710 static const PatternAndOffsets scKoStndPatternsOffsets[] = {
   2711     { scKoPat0, scKoStndOff01, ARRAY_LENGTH(scKoStndOff01) },
   2712     { scKoPat1, scKoStndOff01, ARRAY_LENGTH(scKoStndOff01) },
   2713     { scKoPat2, scKoStndOff2,  ARRAY_LENGTH(scKoStndOff2)  },
   2714     { scKoPat3, scKoStndOff3,  ARRAY_LENGTH(scKoStndOff3)  },
   2715     { scKoPat4, scKoStndOff45, ARRAY_LENGTH(scKoStndOff45) },
   2716     { scKoPat5, scKoStndOff45, ARRAY_LENGTH(scKoStndOff45) },
   2717     { NULL,     NULL,          0                           }
   2718 };
   2719 
   2720 typedef struct {
   2721     const char *  locale;
   2722     const UChar * text;
   2723     const PatternAndOffsets * patternsAndOffsets;
   2724 } TUSCItem;
   2725 
   2726 static const TUSCItem tuscItems[] = {
   2727     { "root",                  scKoText, scKoStndPatternsOffsets },
   2728     { "root@collation=search", scKoText, scKoSrchPatternsOffsets },
   2729     { "ko@collation=search",   scKoText, scKoSrchPatternsOffsets },
   2730     { NULL,                    NULL,     NULL                    }
   2731 };
   2732 
   2733 static const UChar dummyPat[] = { 0x0061, 0 };
   2734 
   2735 static void TestUsingSearchCollator(void)
   2736 {
   2737     const TUSCItem * tuscItemPtr;
   2738     for (tuscItemPtr = tuscItems; tuscItemPtr->locale != NULL; tuscItemPtr++) {
   2739         UErrorCode status = U_ZERO_ERROR;
   2740         UCollator* ucol = ucol_open(tuscItemPtr->locale, &status);
   2741         if ( U_SUCCESS(status) ) {
   2742             UStringSearch* usrch = usearch_openFromCollator(dummyPat, -1, tuscItemPtr->text, -1, ucol, NULL, &status);
   2743             if ( U_SUCCESS(status) ) {
   2744                 const PatternAndOffsets * patternsOffsetsPtr;
   2745                 for ( patternsOffsetsPtr = tuscItemPtr->patternsAndOffsets; patternsOffsetsPtr->pattern != NULL; patternsOffsetsPtr++) {
   2746                     usearch_setPattern(usrch, patternsOffsetsPtr->pattern, -1, &status);
   2747                     if ( U_SUCCESS(status) ) {
   2748                         int32_t offset;
   2749                         const int32_t * nextOffsetPtr;
   2750                         const int32_t * limitOffsetPtr;
   2751 
   2752                         usearch_reset(usrch);
   2753                         nextOffsetPtr = patternsOffsetsPtr->offsets;
   2754                         limitOffsetPtr = patternsOffsetsPtr->offsets + patternsOffsetsPtr->offsetsLen;
   2755                         while (TRUE) {
   2756                             offset = usearch_next(usrch, &status);
   2757                             if ( U_FAILURE(status) || offset == USEARCH_DONE ) {
   2758                                 break;
   2759                             }
   2760                             if ( nextOffsetPtr < limitOffsetPtr ) {
   2761                                  if (offset != *nextOffsetPtr) {
   2762                                      log_err("error, locale %s, expected usearch_next %d, got %d\n", tuscItemPtr->locale, *nextOffsetPtr, offset);
   2763                                      nextOffsetPtr = limitOffsetPtr;
   2764                                      break;
   2765                                  }
   2766                                  nextOffsetPtr++;
   2767                             } else {
   2768                                 log_err("error, locale %s, usearch_next returned more matches than expected\n", tuscItemPtr->locale );
   2769                             }
   2770                         }
   2771                         if ( U_FAILURE(status) ) {
   2772                             log_err("error, locale %s, usearch_next failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
   2773                         } else if ( nextOffsetPtr < limitOffsetPtr ) {
   2774                             log_err("error, locale %s, usearch_next returned fewer matches than expected\n", tuscItemPtr->locale );
   2775                         }
   2776 
   2777                         status = U_ZERO_ERROR;
   2778                         usearch_reset(usrch);
   2779                         nextOffsetPtr = patternsOffsetsPtr->offsets + patternsOffsetsPtr->offsetsLen;
   2780                         limitOffsetPtr = patternsOffsetsPtr->offsets;
   2781                         while (TRUE) {
   2782                             offset = usearch_previous(usrch, &status);
   2783                             if ( U_FAILURE(status) || offset == USEARCH_DONE ) {
   2784                                 break;
   2785                             }
   2786                             if ( nextOffsetPtr > limitOffsetPtr ) {
   2787                                 nextOffsetPtr--;
   2788                                 if (offset != *nextOffsetPtr) {
   2789                                      log_err("error, locale %s, expected usearch_previous %d, got %d\n", tuscItemPtr->locale, *nextOffsetPtr, offset);
   2790                                      nextOffsetPtr = limitOffsetPtr;
   2791                                       break;
   2792                                 }
   2793                             } else {
   2794                                 log_err("error, locale %s, usearch_previous returned more matches than expected\n", tuscItemPtr->locale );
   2795                             }
   2796                         }
   2797                         if ( U_FAILURE(status) ) {
   2798                             log_err("error, locale %s, usearch_previous failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
   2799                         } else if ( nextOffsetPtr > limitOffsetPtr ) {
   2800                             log_err("error, locale %s, usearch_previous returned fewer matches than expected\n", tuscItemPtr->locale );
   2801                         }
   2802 
   2803                     } else {
   2804                         log_err("error, locale %s, usearch_setPattern failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
   2805                     }
   2806                 }
   2807                 usearch_close(usrch);
   2808             } else {
   2809                 log_err("error, locale %s, usearch_openFromCollator failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
   2810             }
   2811             ucol_close(ucol);
   2812         } else {
   2813             log_data_err("error, locale %s, ucol_open failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
   2814         }
   2815     }
   2816 }
   2817 
   2818 
   2819 static void TestPCEBuffer_with(const UChar *search, uint32_t searchLen, const UChar *source, uint32_t sourceLen) {
   2820    UErrorCode icuStatus = U_ZERO_ERROR;
   2821    UCollator *coll;
   2822    const char *locale;
   2823    UBreakIterator *ubrk;
   2824    UStringSearch *usearch;
   2825    int32_t match = 0;
   2826 
   2827 
   2828    coll = ucol_openFromShortString( "LSK_AS_CX_EX_FX_HX_NX_S4",
   2829                                     FALSE,
   2830                                     NULL,
   2831                                     &icuStatus );
   2832    if ( U_FAILURE(icuStatus) )
   2833    {
   2834      log_data_err( "ucol_openFromShortString error %s\n" , u_errorName(icuStatus));
   2835       goto exit;
   2836    }
   2837 
   2838    locale = ucol_getLocaleByType( coll,
   2839                                   ULOC_VALID_LOCALE,
   2840                                   &icuStatus );
   2841    if ( U_FAILURE(icuStatus) )
   2842    {
   2843      log_err( "ucol_getLocaleByType error %s\n", u_errorName(icuStatus) );
   2844       goto exit;
   2845    }
   2846 
   2847    log_verbose("locale=%s\n", locale);
   2848 
   2849    ubrk = ubrk_open( UBRK_CHARACTER,
   2850                      locale,
   2851                      source,
   2852                      sourceLen,
   2853                      &icuStatus );
   2854    if ( U_FAILURE(icuStatus) )
   2855    {
   2856      log_err( "ubrk_open error %s\n", u_errorName(icuStatus) );
   2857       goto exit;
   2858    }
   2859 
   2860    usearch = usearch_openFromCollator( search,
   2861                                        searchLen,
   2862                                        source,
   2863                                        sourceLen,
   2864                                        coll,
   2865                                        ubrk,
   2866                                        &icuStatus );
   2867    if ( U_FAILURE(icuStatus) )
   2868    {
   2869      log_err( "usearch_openFromCollator error %s\n", u_errorName(icuStatus) );
   2870       goto exit;
   2871    }
   2872 
   2873    match = usearch_first( usearch,
   2874                           &icuStatus );
   2875    if ( U_FAILURE(icuStatus) )
   2876    {
   2877      log_err( "usearch_first error %s\n", u_errorName(icuStatus) );
   2878      goto exit;
   2879    }
   2880 
   2881    if(match==0) {
   2882      log_verbose("OK: match=%d\n", match);
   2883    } else {
   2884      log_err("Err: match expected 0 got %d\n", match);
   2885    }
   2886 
   2887    usearch_close(usearch);
   2888    ubrk_close(ubrk);
   2889    ucol_close(coll);
   2890 
   2891 exit:
   2892    return;
   2893 }
   2894 
   2895 
   2896 static void TestPCEBuffer_100df(void) {
   2897   UChar search[] =
   2898     { 0x0020, 0x0020, 0x00df, 0x0020, 0x0041, 0x00df, 0x0020, 0x0061, 0x00df, 0x0020, 0x00c5, 0x00df, 0x0020, 0x212b, 0x00df, 0x0020, 0x0041, 0x030a, 0x00df, 0x0020, 0x00e5, 0x00df, 0x0020, 0x0061, 0x02da, 0x00df, 0x0020, 0x0061, 0x030a, 0x00df, 0x0020, 0xd8fa, 0xdeae, 0x00df, 0x0020, 0x2027, 0x00df }; /* 38 cp, 9 of them unpaired surrogates */
   2899   UChar source[] =
   2900     { 0x0020, 0x0020, 0x00df, 0x0020, 0x0041, 0x00df, 0x0020, 0x0061, 0x00df, 0x0020, 0x00c5, 0x00df, 0x0020, 0x212b, 0x00df, 0x0020, 0x0041, 0x030a, 0x00df, 0x0020, 0x00e5, 0x00df, 0x0020, 0x0061, 0x02da, 0x00df, 0x0020, 0x0061, 0x030a, 0x00df, 0x0020, 0xd8fa, 0xdeae, 0x00df, 0x0020, 0x2027, 0x00df };
   2901   uint32_t searchLen = sizeof(search)/sizeof(UChar);
   2902   uint32_t sourceLen = sizeof(source)/sizeof(UChar);
   2903   TestPCEBuffer_with(search,searchLen,source,sourceLen);
   2904  }
   2905 
   2906 
   2907 static void TestPCEBuffer_2surr(void) {
   2908   UChar search[] =
   2909     { 0x0020, 0x0020, 0xdfff, 0x0020, 0x0041, 0xdfff, 0x0020, 0x0061, 0xdfff, 0x0020, 0x00c5, 0xdfff, 0x0020, 0x212b, 0xdfff, 0x0020, 0x0041, 0x030a, 0xdfff, 0x0020, 0x00e5, 0xdfff, 0x0020, 0x0061, 0x02da, 0xdfff, 0x0020, 0x0061, 0x030a, 0xdfff, 0x0020, 0xd8fa, 0xdeae, 0xdfff, 0x0020, 0x2027, 0xdfff }; /* 38 cp, 9 of them unpaired surrogates */
   2910   UChar source[] =
   2911     { 0x0020, 0x0020, 0xdfff, 0x0020, 0x0041, 0xdfff, 0x0020, 0x0061, 0xdfff, 0x0020, 0x00c5, 0xdfff, 0x0020, 0x212b, 0xdfff, 0x0020, 0x0041, 0x030a, 0xdfff, 0x0020, 0x00e5, 0xdfff, 0x0020, 0x0061, 0x02da, 0xdfff, 0x0020, 0x0061, 0x030a, 0xdfff, 0x0020, 0xd8fa, 0xdeae, 0xdfff, 0x0020, 0x2027, 0xdfff };
   2912   uint32_t searchLen = sizeof(search)/sizeof(UChar);
   2913   uint32_t sourceLen = sizeof(source)/sizeof(UChar);
   2914   TestPCEBuffer_with(search,searchLen,source,sourceLen);
   2915 }
   2916 
   2917 static void TestMatchFollowedByIgnorables(void) {
   2918     /* test case for ticket#8482 */
   2919     UChar search[] = { 0x00c9 };
   2920     UChar source[] = { 0x00c9, 0x0000, 0x0041 };
   2921     int32_t searchLen;
   2922     int32_t sourceLen;
   2923     UErrorCode icuStatus = U_ZERO_ERROR;
   2924     UCollator *coll;
   2925     const char *locale;
   2926     UBreakIterator *ubrk;
   2927     UStringSearch *usearch;
   2928     int32_t match = 0;
   2929     int32_t matchLength = 0;
   2930     const int32_t expectedMatchLength = 1;
   2931 
   2932     searchLen = sizeof(search)/sizeof(UChar);
   2933     sourceLen = sizeof(source)/sizeof(UChar);
   2934 
   2935     coll = ucol_openFromShortString("LHR_AN_CX_EX_FX_HX_NX_S3",
   2936                                     FALSE,
   2937                                     NULL,
   2938                                     &icuStatus);
   2939     if (U_FAILURE(icuStatus)) {
   2940         log_data_err("ucol_openFromShortString error - %s\n", u_errorName(icuStatus));
   2941     }
   2942 
   2943     locale = ucol_getLocaleByType(coll,
   2944                                     ULOC_VALID_LOCALE,
   2945                                     &icuStatus);
   2946     if (U_FAILURE(icuStatus)) {
   2947         log_data_err("ucol_getLocaleByType error - %s\n", u_errorName(icuStatus));
   2948     }
   2949 
   2950     ubrk = ubrk_open(UBRK_CHARACTER,
   2951                         locale,
   2952                         source,
   2953                         sourceLen,
   2954                         &icuStatus);
   2955     if (U_FAILURE(icuStatus)) {
   2956         log_data_err("ubrk_open error - %s\n", u_errorName(icuStatus));
   2957     }
   2958 
   2959     usearch = usearch_openFromCollator(search,
   2960                                         searchLen,
   2961                                         source,
   2962                                         sourceLen,
   2963                                         coll,
   2964                                         ubrk,
   2965                                         &icuStatus);
   2966     if (U_FAILURE(icuStatus)) {
   2967         log_data_err("usearch_openFromCollator error - %s\n", u_errorName(icuStatus));
   2968     }
   2969 
   2970     match = usearch_first(usearch,
   2971                             &icuStatus);
   2972     if (U_FAILURE(icuStatus)) {
   2973         log_data_err("usearch_first error - %s\n", u_errorName(icuStatus));
   2974     } else {
   2975 
   2976         log_verbose("match=%d\n", match);
   2977 
   2978         matchLength = usearch_getMatchedLength(usearch);
   2979 
   2980         if (matchLength != expectedMatchLength) {
   2981             log_err("Error: matchLength=%d, expected=%d\n", matchLength, expectedMatchLength);
   2982         }
   2983     }
   2984 
   2985     usearch_close(usearch);
   2986     ubrk_close(ubrk);
   2987     ucol_close(coll);
   2988 }
   2989 
   2990 /**
   2991 * addSearchTest
   2992 */
   2993 
   2994 void addSearchTest(TestNode** root)
   2995 {
   2996     addTest(root, &TestStart, "tscoll/usrchtst/TestStart");
   2997     addTest(root, &TestOpenClose, "tscoll/usrchtst/TestOpenClose");
   2998     addTest(root, &TestInitialization, "tscoll/usrchtst/TestInitialization");
   2999     addTest(root, &TestBasic, "tscoll/usrchtst/TestBasic");
   3000     addTest(root, &TestNormExact, "tscoll/usrchtst/TestNormExact");
   3001     addTest(root, &TestStrength, "tscoll/usrchtst/TestStrength");
   3002     addTest(root, &TestBreakIterator, "tscoll/usrchtst/TestBreakIterator");
   3003     addTest(root, &TestVariable, "tscoll/usrchtst/TestVariable");
   3004     addTest(root, &TestOverlap, "tscoll/usrchtst/TestOverlap");
   3005     addTest(root, &TestCollator, "tscoll/usrchtst/TestCollator");
   3006     addTest(root, &TestPattern, "tscoll/usrchtst/TestPattern");
   3007     addTest(root, &TestText, "tscoll/usrchtst/TestText");
   3008     addTest(root, &TestCompositeBoundaries,
   3009                                   "tscoll/usrchtst/TestCompositeBoundaries");
   3010     addTest(root, &TestGetSetOffset, "tscoll/usrchtst/TestGetSetOffset");
   3011     addTest(root, &TestGetSetAttribute,
   3012                                       "tscoll/usrchtst/TestGetSetAttribute");
   3013     addTest(root, &TestGetMatch, "tscoll/usrchtst/TestGetMatch");
   3014     addTest(root, &TestSetMatch, "tscoll/usrchtst/TestSetMatch");
   3015     addTest(root, &TestReset, "tscoll/usrchtst/TestReset");
   3016     addTest(root, &TestSupplementary, "tscoll/usrchtst/TestSupplementary");
   3017     addTest(root, &TestContraction, "tscoll/usrchtst/TestContraction");
   3018     addTest(root, &TestIgnorable, "tscoll/usrchtst/TestIgnorable");
   3019     addTest(root, &TestCanonical, "tscoll/usrchtst/TestCanonical");
   3020     addTest(root, &TestNormCanonical, "tscoll/usrchtst/TestNormCanonical");
   3021     addTest(root, &TestStrengthCanonical,
   3022                                     "tscoll/usrchtst/TestStrengthCanonical");
   3023     addTest(root, &TestBreakIteratorCanonical,
   3024                                "tscoll/usrchtst/TestBreakIteratorCanonical");
   3025     addTest(root, &TestVariableCanonical,
   3026                                     "tscoll/usrchtst/TestVariableCanonical");
   3027     addTest(root, &TestOverlapCanonical,
   3028                                      "tscoll/usrchtst/TestOverlapCanonical");
   3029     addTest(root, &TestCollatorCanonical,
   3030                                     "tscoll/usrchtst/TestCollatorCanonical");
   3031     addTest(root, &TestPatternCanonical,
   3032                                      "tscoll/usrchtst/TestPatternCanonical");
   3033     addTest(root, &TestTextCanonical, "tscoll/usrchtst/TestTextCanonical");
   3034     addTest(root, &TestCompositeBoundariesCanonical,
   3035                          "tscoll/usrchtst/TestCompositeBoundariesCanonical");
   3036     addTest(root, &TestGetSetOffsetCanonical,
   3037                                 "tscoll/usrchtst/TestGetSetOffsetCanonical");
   3038     addTest(root, &TestSupplementaryCanonical,
   3039                                "tscoll/usrchtst/TestSupplementaryCanonical");
   3040     addTest(root, &TestContractionCanonical,
   3041                                  "tscoll/usrchtst/TestContractionCanonical");
   3042     addTest(root, &TestEnd, "tscoll/usrchtst/TestEnd");
   3043     addTest(root, &TestNumeric, "tscoll/usrchtst/TestNumeric");
   3044     addTest(root, &TestDiacriticMatch, "tscoll/usrchtst/TestDiacriticMatch");
   3045     addTest(root, &TestForwardBackward, "tscoll/usrchtst/TestForwardBackward");
   3046     addTest(root, &TestSearchForNull, "tscoll/usrchtst/TestSearchForNull");
   3047     addTest(root, &TestStrengthIdentical, "tscoll/usrchtst/TestStrengthIdentical");
   3048     addTest(root, &TestUsingSearchCollator, "tscoll/usrchtst/TestUsingSearchCollator");
   3049     addTest(root, &TestPCEBuffer_100df, "tscoll/usrchtst/TestPCEBuffer/1_00df");
   3050     addTest(root, &TestPCEBuffer_2surr, "tscoll/usrchtst/TestPCEBuffer/2_dfff");
   3051     addTest(root, &TestMatchFollowedByIgnorables, "tscoll/usrchtst/TestMatchFollowedByIgnorables");
   3052 }
   3053 
   3054 #endif /* #if !UCONFIG_NO_COLLATION */
   3055