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