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