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    int         matchlimit  = 0;
341    UErrorCode  status      = U_ZERO_ERROR;
342    int32_t matchindex  = search.offset[count];
343    int32_t     textlength;
344    UChar       matchtext[128];
345
346    usearch_setAttribute(strsrch, USEARCH_ELEMENT_COMPARISON, search.elemCompare, &status);
347    if (U_FAILURE(status)) {
348        log_err("Error setting USEARCH_ELEMENT_COMPARISON attribute %s\n", u_errorName(status));
349        return FALSE;
350    }
351
352    if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
353        usearch_getMatchedLength(strsrch) != 0) {
354        log_err("Error with the initialization of match start and length\n");
355    }
356    /* start of following matches */
357    while (U_SUCCESS(status) && matchindex >= 0) {
358        uint32_t matchlength = search.size[count];
359        usearch_next(strsrch, &status);
360        if (matchindex != usearch_getMatchedStart(strsrch) ||
361            matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
362            char *str = toCharString(usearch_getText(strsrch, &textlength));
363            log_err("Text: %s\n", str);
364            str = toCharString(usearch_getPattern(strsrch, &textlength));
365            log_err("Pattern: %s\n", str);
366            log_err("Error following match found at idx,len %d,%d; expected %d,%d\n",
367                    usearch_getMatchedStart(strsrch), usearch_getMatchedLength(strsrch),
368                    matchindex, matchlength);
369            return FALSE;
370        }
371        count ++;
372
373        if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
374            (int32_t) matchlength || U_FAILURE(status) ||
375            memcmp(matchtext,
376                   usearch_getText(strsrch, &textlength) + matchindex,
377                   matchlength * sizeof(UChar)) != 0) {
378            log_err("Error getting following matched text\n");
379        }
380
381        matchindex = search.offset[count];
382    }
383    usearch_next(strsrch, &status);
384    if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
385        usearch_getMatchedLength(strsrch) != 0) {
386        char *str = toCharString(usearch_getText(strsrch, &textlength));
387        log_err("Text: %s\n", str);
388        str = toCharString(usearch_getPattern(strsrch, &textlength));
389        log_err("Pattern: %s\n", str);
390        log_err("Error following match found at %d %d\n",
391                    usearch_getMatchedStart(strsrch),
392                    usearch_getMatchedLength(strsrch));
393        return FALSE;
394    }
395    /* start of preceding matches */
396    count = count == 0 ? 0 : count - 1;
397    matchlimit = count;
398    matchindex = search.offset[count];
399
400    while (U_SUCCESS(status) && matchindex >= 0) {
401        uint32_t matchlength = search.size[count];
402        usearch_previous(strsrch, &status);
403        if (matchindex != usearch_getMatchedStart(strsrch) ||
404            matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
405            char *str = toCharString(usearch_getText(strsrch, &textlength));
406            log_err("Text: %s\n", str);
407            str = toCharString(usearch_getPattern(strsrch, &textlength));
408            log_err("Pattern: %s\n", str);
409            log_err("Error preceding match found at %d %d\n",
410                    usearch_getMatchedStart(strsrch),
411                    usearch_getMatchedLength(strsrch));
412            return FALSE;
413        }
414
415        if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
416            (int32_t) matchlength || U_FAILURE(status) ||
417            memcmp(matchtext,
418                   usearch_getText(strsrch, &textlength) + matchindex,
419                   matchlength * sizeof(UChar)) != 0) {
420            log_err("Error getting preceding matched text\n");
421        }
422
423        matchindex = count > 0 ? search.offset[count - 1] : -1;
424        count --;
425    }
426    usearch_previous(strsrch, &status);
427    if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
428        usearch_getMatchedLength(strsrch) != 0) {
429        char *str = toCharString(usearch_getText(strsrch, &textlength));
430        log_err("Text: %s\n", str);
431        str = toCharString(usearch_getPattern(strsrch, &textlength));
432        log_err("Pattern: %s\n", str);
433        log_err("Error preceding match found at %d %d\n",
434                    usearch_getMatchedStart(strsrch),
435                    usearch_getMatchedLength(strsrch));
436        return FALSE;
437    }
438
439    usearch_setAttribute(strsrch, USEARCH_ELEMENT_COMPARISON, USEARCH_STANDARD_ELEMENT_COMPARISON, &status);
440    return TRUE;
441}
442
443static UBool assertEqual(const SearchData search)
444{
445    UErrorCode      status      = U_ZERO_ERROR;
446    UChar           pattern[32];
447    UChar           text[128];
448    UCollator      *collator = getCollator(search.collator);
449    UBreakIterator *breaker  = getBreakIterator(search.breaker);
450    UStringSearch  *strsrch;
451
452    CHECK_BREAK_BOOL(search.breaker);
453
454    u_unescape(search.text, text, 128);
455    u_unescape(search.pattern, pattern, 32);
456    ucol_setStrength(collator, search.strength);
457    strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
458                                       breaker, &status);
459    if (U_FAILURE(status)) {
460        log_err("Error opening string search %s\n", u_errorName(status));
461        return FALSE;
462    }
463
464    if (!assertEqualWithUStringSearch(strsrch, search)) {
465        ucol_setStrength(collator, UCOL_TERTIARY);
466        usearch_close(strsrch);
467        return FALSE;
468    }
469    ucol_setStrength(collator, UCOL_TERTIARY);
470    usearch_close(strsrch);
471    return TRUE;
472}
473
474static UBool assertCanonicalEqual(const SearchData search)
475{
476    UErrorCode      status      = U_ZERO_ERROR;
477    UChar           pattern[32];
478    UChar           text[128];
479    UCollator      *collator = getCollator(search.collator);
480    UBreakIterator *breaker  = getBreakIterator(search.breaker);
481    UStringSearch  *strsrch;
482    UBool           result = TRUE;
483
484    CHECK_BREAK_BOOL(search.breaker);
485    u_unescape(search.text, text, 128);
486    u_unescape(search.pattern, pattern, 32);
487    ucol_setStrength(collator, search.strength);
488    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
489    strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
490                                       breaker, &status);
491    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
492                         &status);
493    if (U_FAILURE(status)) {
494        log_err("Error opening string search %s\n", u_errorName(status));
495        result = FALSE;
496        goto bail;
497    }
498
499    if (!assertEqualWithUStringSearch(strsrch, search)) {
500        ucol_setStrength(collator, UCOL_TERTIARY);
501        usearch_close(strsrch);
502        result = FALSE;
503        goto bail;
504    }
505
506bail:
507    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
508    ucol_setStrength(collator, UCOL_TERTIARY);
509    usearch_close(strsrch);
510    return result;
511}
512
513static UBool assertEqualWithAttribute(const SearchData            search,
514                                            USearchAttributeValue canonical,
515                                            USearchAttributeValue overlap)
516{
517    UErrorCode      status      = U_ZERO_ERROR;
518    UChar           pattern[32];
519    UChar           text[128];
520    UCollator      *collator = getCollator(search.collator);
521    UBreakIterator *breaker  = getBreakIterator(search.breaker);
522    UStringSearch  *strsrch;
523
524    CHECK_BREAK_BOOL(search.breaker);
525    u_unescape(search.text, text, 128);
526    u_unescape(search.pattern, pattern, 32);
527    ucol_setStrength(collator, search.strength);
528    strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
529                                       breaker, &status);
530    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, canonical,
531                         &status);
532    usearch_setAttribute(strsrch, USEARCH_OVERLAP, overlap, &status);
533
534    if (U_FAILURE(status)) {
535        log_err("Error opening string search %s\n", u_errorName(status));
536        return FALSE;
537    }
538
539    if (!assertEqualWithUStringSearch(strsrch, search)) {
540            ucol_setStrength(collator, UCOL_TERTIARY);
541            usearch_close(strsrch);
542            return FALSE;
543    }
544    ucol_setStrength(collator, UCOL_TERTIARY);
545    usearch_close(strsrch);
546    return TRUE;
547}
548
549static void TestBasic(void)
550{
551    int count = 0;
552    UErrorCode status = U_ZERO_ERROR;
553    open(&status);
554    if (U_FAILURE(status)) {
555        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
556        return;
557    }
558    while (BASIC[count].text != NULL) {
559        if (!assertEqual(BASIC[count])) {
560            log_err("Error at test number %d\n", count);
561        }
562        count ++;
563    }
564    close();
565}
566
567static void TestNormExact(void)
568{
569    int count = 0;
570    UErrorCode status = U_ZERO_ERROR;
571    open(&status);
572    if (U_FAILURE(status)) {
573        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
574        return;
575    }
576    ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
577    if (U_FAILURE(status)) {
578        log_err("Error setting collation normalization %s\n",
579            u_errorName(status));
580    }
581    while (BASIC[count].text != NULL) {
582        if (!assertEqual(BASIC[count])) {
583            log_err("Error at test number %d\n", count);
584        }
585        count ++;
586    }
587    count = 0;
588    while (NORMEXACT[count].text != NULL) {
589        if (!assertEqual(NORMEXACT[count])) {
590            log_err("Error at test number %d\n", count);
591        }
592        count ++;
593    }
594    ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
595    count = 0;
596    while (NONNORMEXACT[count].text != NULL) {
597        if (!assertEqual(NONNORMEXACT[count])) {
598            log_err("Error at test number %d\n", count);
599        }
600        count ++;
601    }
602    close();
603}
604
605static void TestStrength(void)
606{
607    int count = 0;
608    UErrorCode status = U_ZERO_ERROR;
609    open(&status);
610    if (U_FAILURE(status)) {
611        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
612        return;
613    }
614    while (STRENGTH[count].text != NULL) {
615        if (!assertEqual(STRENGTH[count])) {
616            log_err("Error at test number %d\n", count);
617        }
618        count ++;
619    }
620    close();
621}
622
623static void TestBreakIterator(void) {
624    UErrorCode      status      = U_ZERO_ERROR;
625    UStringSearch  *strsrch;
626    UChar           text[128];
627    UChar           pattern[32];
628    int             count = 0;
629
630    CHECK_BREAK("x");
631
632#if !UCONFIG_NO_BREAK_ITERATION
633    open(&status);
634    if (U_FAILURE(status)) {
635        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
636        return;
637    }
638    if (usearch_getBreakIterator(NULL) != NULL) {
639        log_err("Expected NULL breakiterator from NULL string search\n");
640    }
641    u_unescape(BREAKITERATOREXACT[0].text, text, 128);
642    u_unescape(BREAKITERATOREXACT[0].pattern, pattern, 32);
643    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, NULL,
644                                       &status);
645    if (U_FAILURE(status)) {
646        log_err("Error opening string search %s\n", u_errorName(status));
647        goto ENDTESTBREAKITERATOR;
648    }
649
650    usearch_setBreakIterator(strsrch, NULL, &status);
651    if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != NULL) {
652        log_err("Error usearch_getBreakIterator returned wrong object");
653        goto ENDTESTBREAKITERATOR;
654    }
655
656    usearch_setBreakIterator(strsrch, EN_CHARACTERBREAKER_, &status);
657    if (U_FAILURE(status) ||
658        usearch_getBreakIterator(strsrch) != EN_CHARACTERBREAKER_) {
659        log_err("Error usearch_getBreakIterator returned wrong object");
660        goto ENDTESTBREAKITERATOR;
661    }
662
663    usearch_setBreakIterator(strsrch, EN_WORDBREAKER_, &status);
664    if (U_FAILURE(status) ||
665        usearch_getBreakIterator(strsrch) != EN_WORDBREAKER_) {
666        log_err("Error usearch_getBreakIterator returned wrong object");
667        goto ENDTESTBREAKITERATOR;
668    }
669
670    usearch_close(strsrch);
671
672    count = 0;
673    while (count < 4) {
674        /* 0-3 test are fixed */
675        const SearchData     *search   = &(BREAKITERATOREXACT[count]);
676              UCollator      *collator = getCollator(search->collator);
677              UBreakIterator *breaker  = getBreakIterator(search->breaker);
678
679        u_unescape(search->text, text, 128);
680        u_unescape(search->pattern, pattern, 32);
681        ucol_setStrength(collator, search->strength);
682
683        strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
684                                           breaker, &status);
685        if (U_FAILURE(status) ||
686            usearch_getBreakIterator(strsrch) != breaker) {
687            log_err("Error setting break iterator\n");
688            if (strsrch != NULL) {
689                usearch_close(strsrch);
690            }
691        }
692        if (!assertEqualWithUStringSearch(strsrch, *search)) {
693            ucol_setStrength(collator, UCOL_TERTIARY);
694            usearch_close(strsrch);
695            goto ENDTESTBREAKITERATOR;
696        }
697        search   = &(BREAKITERATOREXACT[count + 1]);
698        breaker  = getBreakIterator(search->breaker);
699        usearch_setBreakIterator(strsrch, breaker, &status);
700        if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != breaker) {
701            log_err("Error setting break iterator\n");
702            usearch_close(strsrch);
703            goto ENDTESTBREAKITERATOR;
704        }
705        usearch_reset(strsrch);
706        if (!assertEqualWithUStringSearch(strsrch, *search)) {
707            log_err("Error at test number %d\n", count);
708            usearch_close(strsrch);
709            goto ENDTESTBREAKITERATOR;
710        }
711        usearch_close(strsrch);
712        count += 2;
713    }
714    count = 0;
715    while (BREAKITERATOREXACT[count].text != NULL) {
716         if (!assertEqual(BREAKITERATOREXACT[count])) {
717             log_err("Error at test number %d\n", count);
718             goto ENDTESTBREAKITERATOR;
719         }
720         count ++;
721    }
722
723ENDTESTBREAKITERATOR:
724    close();
725#endif
726}
727
728static void TestVariable(void)
729{
730    int count = 0;
731    UErrorCode status = U_ZERO_ERROR;
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    ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
738    if (U_FAILURE(status)) {
739        log_err("Error setting collation alternate attribute %s\n",
740            u_errorName(status));
741    }
742    while (VARIABLE[count].text != NULL) {
743        log_verbose("variable %d\n", count);
744        if (!assertEqual(VARIABLE[count])) {
745            log_err("Error at test number %d\n", count);
746        }
747        count ++;
748    }
749    ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
750                      UCOL_NON_IGNORABLE, &status);
751    close();
752}
753
754static void TestOverlap(void)
755{
756    int count = 0;
757    UErrorCode status = U_ZERO_ERROR;
758    open(&status);
759    if (U_FAILURE(status)) {
760        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
761        return;
762    }
763    while (OVERLAP[count].text != NULL) {
764        if (!assertEqualWithAttribute(OVERLAP[count], USEARCH_OFF,
765                                      USEARCH_ON)) {
766            log_err("Error at overlap test number %d\n", count);
767        }
768        count ++;
769    }
770    count = 0;
771    while (NONOVERLAP[count].text != NULL) {
772        if (!assertEqual(NONOVERLAP[count])) {
773            log_err("Error at non overlap test number %d\n", count);
774        }
775        count ++;
776    }
777
778    count = 0;
779    while (count < 1) {
780              UChar           pattern[32];
781              UChar           text[128];
782        const SearchData     *search   = &(OVERLAP[count]);
783              UCollator      *collator = getCollator(search->collator);
784              UStringSearch  *strsrch;
785              status   = U_ZERO_ERROR;
786
787        u_unescape(search->text, text, 128);
788        u_unescape(search->pattern, pattern, 32);
789        strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
790                                           NULL, &status);
791        if(status == U_FILE_ACCESS_ERROR) {
792          log_data_err("Is your data around?\n");
793          return;
794        } else if(U_FAILURE(status)) {
795          log_err("Error opening searcher\n");
796          return;
797        }
798        usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
799        if (U_FAILURE(status) ||
800            usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
801            log_err("Error setting overlap option\n");
802        }
803        if (!assertEqualWithUStringSearch(strsrch, *search)) {
804            usearch_close(strsrch);
805            return;
806        }
807        search   = &(NONOVERLAP[count]);
808        usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
809        if (U_FAILURE(status) ||
810            usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
811            log_err("Error setting overlap option\n");
812        }
813        usearch_reset(strsrch);
814        if (!assertEqualWithUStringSearch(strsrch, *search)) {
815            usearch_close(strsrch);
816            log_err("Error at test number %d\n", count);
817         }
818
819        count ++;
820        usearch_close(strsrch);
821    }
822    close();
823}
824
825static void TestCollator(void)
826{
827    /* test collator that thinks "o" and "p" are the same thing */
828          UChar          rules[32];
829          UCollator     *tailored = NULL;
830          UErrorCode     status   = U_ZERO_ERROR;
831          UChar          pattern[32];
832          UChar          text[128];
833          UStringSearch *strsrch;
834
835    text[0] = 0x41;
836    text[1] = 0x42;
837    text[2] = 0x43;
838    text[3] = 0x44;
839    text[4] = 0x45;
840    pattern[0] = 0x62;
841    pattern[1] = 0x63;
842    strsrch  = usearch_open(pattern, 2, text, 5, "en_US",  NULL,  &status);
843    if(status == U_FILE_ACCESS_ERROR) {
844      log_data_err("Is your data around?\n");
845      return;
846    } else if(U_FAILURE(status)) {
847      log_err("Error opening searcher\n");
848      return;
849    }
850    tailored = usearch_getCollator(strsrch);
851    if (usearch_next(strsrch, &status) != -1) {
852        log_err("Error: Found case insensitive match, when we shouldn't\n");
853    }
854    ucol_setStrength(tailored, UCOL_PRIMARY);
855    usearch_reset(strsrch);
856    if (usearch_next(strsrch, &status) != 1) {
857        log_err("Error: Found case insensitive match not found\n");
858    }
859    usearch_close(strsrch);
860
861    open(&status);
862
863    if (usearch_getCollator(NULL) != NULL) {
864        log_err("Expected NULL collator from NULL string search\n");
865    }
866    u_unescape(COLLATOR[0].text, text, 128);
867    u_unescape(COLLATOR[0].pattern, pattern, 32);
868
869    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
870                                       NULL, &status);
871    if (U_FAILURE(status)) {
872        log_err("Error opening string search %s\n", u_errorName(status));
873    }
874    if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
875        goto ENDTESTCOLLATOR;
876    }
877
878    u_unescape(TESTCOLLATORRULE, rules, 32);
879    tailored = ucol_openRules(rules, -1, UCOL_ON, COLLATOR[1].strength,
880                              NULL, &status);
881    if (U_FAILURE(status)) {
882        log_err("Error opening rule based collator %s\n", u_errorName(status));
883    }
884
885    usearch_setCollator(strsrch, tailored, &status);
886    if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
887        log_err("Error setting rule based collator\n");
888    }
889    usearch_reset(strsrch);
890    if (!assertEqualWithUStringSearch(strsrch, COLLATOR[1])) {
891        goto ENDTESTCOLLATOR;
892    }
893
894    usearch_setCollator(strsrch, EN_US_, &status);
895    usearch_reset(strsrch);
896    if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
897        log_err("Error setting rule based collator\n");
898    }
899    if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
900        goto ENDTESTCOLLATOR;
901    }
902
903ENDTESTCOLLATOR:
904    usearch_close(strsrch);
905    if (tailored != NULL) {
906        ucol_close(tailored);
907    }
908    close();
909}
910
911static void TestPattern(void)
912{
913          UStringSearch *strsrch;
914          UChar          pattern[32];
915          UChar          bigpattern[512];
916          UChar          text[128];
917    const UChar         *temp;
918          int32_t        templength;
919          UErrorCode     status = U_ZERO_ERROR;
920
921    open(&status);
922    if (U_FAILURE(status)) {
923        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
924        return;
925    }
926    if (usearch_getPattern(NULL, &templength) != NULL) {
927        log_err("Error NULL string search expected returning NULL pattern\n");
928    }
929    usearch_setPattern(NULL, pattern, 3, &status);
930    if (U_SUCCESS(status)) {
931        log_err("Error expected setting pattern in NULL strings search\n");
932    }
933    status = U_ZERO_ERROR;
934    u_unescape(PATTERN[0].text, text, 128);
935    u_unescape(PATTERN[0].pattern, pattern, 32);
936
937    ucol_setStrength(EN_US_, PATTERN[0].strength);
938    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
939                                       NULL, &status);
940    if(status == U_FILE_ACCESS_ERROR) {
941      log_data_err("Is your data around?\n");
942      return;
943    } else if(U_FAILURE(status)) {
944      log_err("Error opening searcher\n");
945      return;
946    }
947
948    status = U_ZERO_ERROR;
949    usearch_setPattern(strsrch, NULL, 3, &status);
950    if (U_SUCCESS(status)) {
951        log_err("Error expected setting NULL pattern in strings search\n");
952    }
953    status = U_ZERO_ERROR;
954    usearch_setPattern(strsrch, pattern, 0, &status);
955    if (U_SUCCESS(status)) {
956        log_err("Error expected setting pattern with length 0 in strings search\n");
957    }
958    status = U_ZERO_ERROR;
959    if (U_FAILURE(status)) {
960        log_err("Error opening string search %s\n", u_errorName(status));
961        goto ENDTESTPATTERN;
962    }
963    temp = usearch_getPattern(strsrch, &templength);
964    if (u_strcmp(pattern, temp) != 0) {
965        log_err("Error setting pattern\n");
966    }
967    if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
968        goto ENDTESTPATTERN;
969    }
970
971    u_unescape(PATTERN[1].pattern, pattern, 32);
972    usearch_setPattern(strsrch, pattern, -1, &status);
973    temp = usearch_getPattern(strsrch, &templength);
974    if (u_strcmp(pattern, temp) != 0) {
975        log_err("Error setting pattern\n");
976        goto ENDTESTPATTERN;
977    }
978    usearch_reset(strsrch);
979    if (U_FAILURE(status)) {
980        log_err("Error setting pattern %s\n", u_errorName(status));
981    }
982    if (!assertEqualWithUStringSearch(strsrch, PATTERN[1])) {
983        goto ENDTESTPATTERN;
984    }
985
986    u_unescape(PATTERN[0].pattern, pattern, 32);
987    usearch_setPattern(strsrch, pattern, -1, &status);
988    temp = usearch_getPattern(strsrch, &templength);
989    if (u_strcmp(pattern, temp) != 0) {
990        log_err("Error setting pattern\n");
991        goto ENDTESTPATTERN;
992    }
993    usearch_reset(strsrch);
994    if (U_FAILURE(status)) {
995        log_err("Error setting pattern %s\n", u_errorName(status));
996    }
997    if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
998        goto ENDTESTPATTERN;
999    }
1000    /* enormous pattern size to see if this crashes */
1001    for (templength = 0; templength != 512; templength ++) {
1002        bigpattern[templength] = 0x61;
1003    }
1004    bigpattern[511] = 0;
1005    usearch_setPattern(strsrch, bigpattern, -1, &status);
1006    if (U_FAILURE(status)) {
1007        log_err("Error setting pattern with size 512, %s \n",
1008            u_errorName(status));
1009    }
1010ENDTESTPATTERN:
1011    ucol_setStrength(EN_US_, UCOL_TERTIARY);
1012    if (strsrch != NULL) {
1013        usearch_close(strsrch);
1014    }
1015    close();
1016}
1017
1018static void TestText(void)
1019{
1020          UStringSearch *strsrch;
1021          UChar          pattern[32];
1022          UChar          text[128];
1023    const UChar         *temp;
1024          int32_t        templength;
1025          UErrorCode     status = U_ZERO_ERROR;
1026
1027    u_unescape(TEXT[0].text, text, 128);
1028    u_unescape(TEXT[0].pattern, pattern, 32);
1029
1030    open(&status);
1031    if (U_FAILURE(status)) {
1032        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1033        return;
1034    }
1035
1036    if (usearch_getText(NULL, &templength) != NULL) {
1037        log_err("Error NULL string search should return NULL text\n");
1038    }
1039
1040    usearch_setText(NULL, text, 10, &status);
1041    if (U_SUCCESS(status)) {
1042        log_err("Error NULL string search should have an error when setting text\n");
1043    }
1044
1045    status = U_ZERO_ERROR;
1046    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
1047                                       NULL, &status);
1048
1049    if (U_FAILURE(status)) {
1050        log_err("Error opening string search %s\n", u_errorName(status));
1051        goto ENDTESTPATTERN;
1052    }
1053    temp = usearch_getText(strsrch, &templength);
1054    if (u_strcmp(text, temp) != 0) {
1055        log_err("Error setting text\n");
1056    }
1057    if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
1058        goto ENDTESTPATTERN;
1059    }
1060
1061    u_unescape(TEXT[1].text, text, 32);
1062    usearch_setText(strsrch, text, -1, &status);
1063    temp = usearch_getText(strsrch, &templength);
1064    if (u_strcmp(text, temp) != 0) {
1065        log_err("Error setting text\n");
1066        goto ENDTESTPATTERN;
1067    }
1068    if (U_FAILURE(status)) {
1069        log_err("Error setting text %s\n", u_errorName(status));
1070    }
1071    if (!assertEqualWithUStringSearch(strsrch, TEXT[1])) {
1072        goto ENDTESTPATTERN;
1073    }
1074
1075    u_unescape(TEXT[0].text, text, 32);
1076    usearch_setText(strsrch, text, -1, &status);
1077    temp = usearch_getText(strsrch, &templength);
1078    if (u_strcmp(text, temp) != 0) {
1079        log_err("Error setting text\n");
1080        goto ENDTESTPATTERN;
1081    }
1082    if (U_FAILURE(status)) {
1083        log_err("Error setting pattern %s\n", u_errorName(status));
1084    }
1085    if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
1086        goto ENDTESTPATTERN;
1087    }
1088ENDTESTPATTERN:
1089    if (strsrch != NULL) {
1090        usearch_close(strsrch);
1091    }
1092    close();
1093}
1094
1095static void TestCompositeBoundaries(void)
1096{
1097    int count = 0;
1098    UErrorCode status = U_ZERO_ERROR;
1099    open(&status);
1100    if (U_FAILURE(status)) {
1101        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1102        return;
1103    }
1104    while (COMPOSITEBOUNDARIES[count].text != NULL) {
1105        log_verbose("composite %d\n", count);
1106        if (!assertEqual(COMPOSITEBOUNDARIES[count])) {
1107            log_err("Error at test number %d\n", count);
1108        }
1109        count ++;
1110    }
1111    close();
1112}
1113
1114static void TestGetSetOffset(void)
1115{
1116    int            searchDataIndex   = 0;
1117    UChar          pattern[32];
1118    UChar          text[128];
1119    UErrorCode     status  = U_ZERO_ERROR;
1120    UStringSearch *strsrch;
1121    memset(pattern, 0, 32*sizeof(UChar));
1122    memset(text, 0, 128*sizeof(UChar));
1123
1124    open(&status);
1125    if (U_FAILURE(status)) {
1126        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1127        return;
1128    }
1129    if (usearch_getOffset(NULL) != USEARCH_DONE) {
1130        log_err("usearch_getOffset(NULL) expected USEARCH_DONE\n");
1131    }
1132    strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
1133                                       &status);
1134    /* testing out of bounds error */
1135    usearch_setOffset(strsrch, -1, &status);
1136    if (U_SUCCESS(status)) {
1137        log_err("Error expecting set offset error\n");
1138    }
1139    usearch_setOffset(strsrch, 128, &status);
1140    if (U_SUCCESS(status)) {
1141        log_err("Error expecting set offset error\n");
1142    }
1143    while (BASIC[searchDataIndex].text != NULL) {
1144        int         count       = 0;
1145        SearchData  search      = BASIC[searchDataIndex ++];
1146        int32_t matchindex  = search.offset[count];
1147        int32_t     textlength;
1148
1149        u_unescape(search.text, text, 128);
1150        u_unescape(search.pattern, pattern, 32);
1151        status = U_ZERO_ERROR;
1152        usearch_setText(strsrch, text, -1, &status);
1153        usearch_setPattern(strsrch, pattern, -1, &status);
1154        ucol_setStrength(usearch_getCollator(strsrch), search.strength);
1155        usearch_reset(strsrch);
1156        while (U_SUCCESS(status) && matchindex >= 0) {
1157            uint32_t matchlength = search.size[count];
1158            usearch_next(strsrch, &status);
1159            if (matchindex != usearch_getMatchedStart(strsrch) ||
1160                matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
1161                char *str = toCharString(usearch_getText(strsrch,
1162                                                         &textlength));
1163                log_err("Text: %s\n", str);
1164                str = toCharString(usearch_getPattern(strsrch, &textlength));
1165                log_err("Pattern: %s\n", str);
1166                log_err("Error match found at %d %d\n",
1167                        usearch_getMatchedStart(strsrch),
1168                        usearch_getMatchedLength(strsrch));
1169                return;
1170            }
1171            usearch_setOffset(strsrch, matchindex + matchlength, &status);
1172            usearch_previous(strsrch, &status);
1173            if (matchindex != usearch_getMatchedStart(strsrch) ||
1174                matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
1175                char *str = toCharString(usearch_getText(strsrch,
1176                                                         &textlength));
1177                log_err("Text: %s\n", str);
1178                str = toCharString(usearch_getPattern(strsrch, &textlength));
1179                log_err("Pattern: %s\n", str);
1180                log_err("Error match found at %d %d\n",
1181                        usearch_getMatchedStart(strsrch),
1182                        usearch_getMatchedLength(strsrch));
1183                return;
1184            }
1185            usearch_setOffset(strsrch, matchindex + matchlength, &status);
1186            matchindex = search.offset[count + 1] == -1 ? -1 :
1187                         search.offset[count + 2];
1188            if (search.offset[count + 1] != -1) {
1189                usearch_setOffset(strsrch, search.offset[count + 1] + 1,
1190                                  &status);
1191                if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
1192                    log_err("Error setting offset\n");
1193                    return;
1194                }
1195            }
1196
1197            count += 2;
1198        }
1199        usearch_next(strsrch, &status);
1200        if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
1201            char *str = toCharString(usearch_getText(strsrch, &textlength));
1202            log_err("Text: %s\n", str);
1203            str = toCharString(usearch_getPattern(strsrch, &textlength));
1204            log_err("Pattern: %s\n", str);
1205            log_err("Error match found at %d %d\n",
1206                        usearch_getMatchedStart(strsrch),
1207                        usearch_getMatchedLength(strsrch));
1208            return;
1209        }
1210    }
1211    ucol_setStrength(usearch_getCollator(strsrch), UCOL_TERTIARY);
1212    usearch_close(strsrch);
1213    close();
1214}
1215
1216static void TestGetSetAttribute(void)
1217{
1218    UErrorCode      status    = U_ZERO_ERROR;
1219    UChar           pattern[32];
1220    UChar           text[128];
1221    UStringSearch  *strsrch;
1222
1223    memset(pattern, 0, 32*sizeof(UChar));
1224    memset(text, 0, 128*sizeof(UChar));
1225
1226    open(&status);
1227    if (U_FAILURE(status)) {
1228        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1229        return;
1230    }
1231    if (usearch_getAttribute(NULL, USEARCH_OVERLAP) != USEARCH_DEFAULT ||
1232        usearch_getAttribute(NULL, USEARCH_CANONICAL_MATCH) !=
1233                                                         USEARCH_DEFAULT) {
1234        log_err(
1235            "Attributes for NULL string search should be USEARCH_DEFAULT\n");
1236    }
1237    strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
1238                                       &status);
1239    if (U_FAILURE(status)) {
1240        log_err("Error opening search %s\n", u_errorName(status));
1241        return;
1242    }
1243
1244    usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_DEFAULT, &status);
1245    if (U_FAILURE(status) ||
1246        usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
1247        log_err("Error setting overlap to the default\n");
1248    }
1249    usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
1250    if (U_FAILURE(status) ||
1251        usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
1252        log_err("Error setting overlap true\n");
1253    }
1254    usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
1255    if (U_FAILURE(status) ||
1256        usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
1257        log_err("Error setting overlap false\n");
1258    }
1259    usearch_setAttribute(strsrch, USEARCH_OVERLAP,
1260                         USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
1261    if (U_SUCCESS(status)) {
1262        log_err("Error setting overlap to illegal value\n");
1263    }
1264    status = U_ZERO_ERROR;
1265    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT,
1266                         &status);
1267    if (U_FAILURE(status) ||
1268        usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
1269                                                        USEARCH_OFF) {
1270        log_err("Error setting canonical match to the default\n");
1271    }
1272    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1273                         &status);
1274    if (U_FAILURE(status) ||
1275        usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
1276                                                         USEARCH_ON) {
1277        log_err("Error setting canonical match true\n");
1278    }
1279    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_OFF,
1280                         &status);
1281    if (U_FAILURE(status) ||
1282        usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
1283                                                        USEARCH_OFF) {
1284        log_err("Error setting canonical match false\n");
1285    }
1286    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH,
1287                         USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
1288    if (U_SUCCESS(status)) {
1289        log_err("Error setting canonical match to illegal value\n");
1290    }
1291    status = U_ZERO_ERROR;
1292    usearch_setAttribute(strsrch, USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT,
1293                         &status);
1294    if (U_SUCCESS(status)) {
1295        log_err("Error setting illegal attribute success\n");
1296    }
1297
1298    usearch_close(strsrch);
1299    close();
1300}
1301
1302static void TestGetMatch(void)
1303{
1304    int            count       = 0;
1305    UErrorCode     status      = U_ZERO_ERROR;
1306    UChar          text[128];
1307    UChar          pattern[32];
1308    SearchData     search      = MATCH[0];
1309    int32_t    matchindex  = search.offset[count];
1310    UStringSearch *strsrch;
1311    int32_t        textlength;
1312    UChar          matchtext[128];
1313
1314    open(&status);
1315    if (U_FAILURE(status)) {
1316        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1317        return;
1318    }
1319
1320    if (usearch_getMatchedStart(NULL) != USEARCH_DONE ||
1321        usearch_getMatchedLength(NULL) != USEARCH_DONE) {
1322        log_err(
1323   "Expected start and length of NULL string search should be USEARCH_DONE\n");
1324    }
1325
1326    u_unescape(search.text, text, 128);
1327    u_unescape(search.pattern, pattern, 32);
1328    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
1329                                       NULL, &status);
1330    if (U_FAILURE(status)) {
1331        log_err("Error opening string search %s\n", u_errorName(status));
1332        if (strsrch != NULL) {
1333            usearch_close(strsrch);
1334        }
1335        return;
1336    }
1337
1338    while (U_SUCCESS(status) && matchindex >= 0) {
1339        int32_t matchlength = search.size[count];
1340        usearch_next(strsrch, &status);
1341        if (matchindex != usearch_getMatchedStart(strsrch) ||
1342            matchlength != usearch_getMatchedLength(strsrch)) {
1343            char *str = toCharString(usearch_getText(strsrch, &textlength));
1344            log_err("Text: %s\n", str);
1345            str = toCharString(usearch_getPattern(strsrch, &textlength));
1346            log_err("Pattern: %s\n", str);
1347            log_err("Error match found at %d %d\n",
1348                    usearch_getMatchedStart(strsrch),
1349                    usearch_getMatchedLength(strsrch));
1350            return;
1351        }
1352        count ++;
1353
1354        status = U_ZERO_ERROR;
1355        if (usearch_getMatchedText(NULL, matchtext, 128, &status) !=
1356            USEARCH_DONE || U_SUCCESS(status)){
1357            log_err("Error expecting errors with NULL string search\n");
1358        }
1359        status = U_ZERO_ERROR;
1360        if (usearch_getMatchedText(strsrch, NULL, 0, &status) !=
1361            (int32_t)matchlength || U_SUCCESS(status)){
1362            log_err("Error pre-flighting match length\n");
1363        }
1364        status = U_ZERO_ERROR;
1365        if (usearch_getMatchedText(strsrch, matchtext, 0, &status) !=
1366            (int32_t)matchlength || U_SUCCESS(status)){
1367            log_err("Error getting match text with buffer size 0\n");
1368        }
1369        status = U_ZERO_ERROR;
1370        if (usearch_getMatchedText(strsrch, matchtext, matchlength, &status)
1371            != (int32_t)matchlength || matchtext[matchlength - 1] == 0 ||
1372            U_FAILURE(status)){
1373            log_err("Error getting match text with exact size\n");
1374        }
1375        status = U_ZERO_ERROR;
1376        if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
1377            (int32_t) matchlength || U_FAILURE(status) ||
1378            memcmp(matchtext,
1379                   usearch_getText(strsrch, &textlength) + matchindex,
1380                   matchlength * sizeof(UChar)) != 0 ||
1381            matchtext[matchlength] != 0) {
1382            log_err("Error getting matched text\n");
1383        }
1384
1385        matchindex = search.offset[count];
1386    }
1387    status = U_ZERO_ERROR;
1388    usearch_next(strsrch, &status);
1389    if (usearch_getMatchedStart(strsrch)  != USEARCH_DONE ||
1390        usearch_getMatchedLength(strsrch) != 0) {
1391        log_err("Error end of match not found\n");
1392    }
1393    status = U_ZERO_ERROR;
1394    if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
1395        USEARCH_DONE) {
1396        log_err("Error getting null matches\n");
1397    }
1398    usearch_close(strsrch);
1399    close();
1400}
1401
1402static void TestSetMatch(void)
1403{
1404    int            count       = 0;
1405    UErrorCode status = U_ZERO_ERROR;
1406    open(&status);
1407    if (U_FAILURE(status)) {
1408        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1409        return;
1410    }
1411    while (MATCH[count].text != NULL) {
1412        SearchData     search = MATCH[count];
1413        int            size   = 0;
1414        int            offsetIndex = 0;
1415        UChar          text[128];
1416        UChar          pattern[32];
1417        UStringSearch *strsrch;
1418        status = U_ZERO_ERROR;
1419
1420        if (usearch_first(NULL, &status) != USEARCH_DONE ||
1421            usearch_last(NULL, &status) != USEARCH_DONE) {
1422            log_err("Error getting the first and last match of a NULL string search\n");
1423        }
1424        u_unescape(search.text, text, 128);
1425        u_unescape(search.pattern, pattern, 32);
1426        strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
1427                                           NULL, &status);
1428        if (U_FAILURE(status)) {
1429            log_err("Error opening string search %s\n", u_errorName(status));
1430            if (strsrch != NULL) {
1431                usearch_close(strsrch);
1432            }
1433            return;
1434        }
1435
1436        size = 0;
1437        while (search.offset[size] != -1) {
1438            size ++;
1439        }
1440
1441        if (usearch_first(strsrch, &status) != search.offset[0] ||
1442            U_FAILURE(status)) {
1443            log_err("Error getting first match\n");
1444        }
1445        if (usearch_last(strsrch, &status) != search.offset[size -1] ||
1446            U_FAILURE(status)) {
1447            log_err("Error getting last match\n");
1448        }
1449
1450        while (offsetIndex < size) {
1451            if (offsetIndex + 2 < size) {
1452                if (usearch_following(strsrch, search.offset[offsetIndex + 2] - 1,
1453                                      &status) != search.offset[offsetIndex + 2] ||
1454                    U_FAILURE(status)) {
1455                    log_err("Error getting following match at index %d\n",
1456                            search.offset[offsetIndex + 2] - 1);
1457                }
1458            }
1459            if (offsetIndex + 1 < size) {
1460                if (usearch_preceding(strsrch, search.offset[offsetIndex + 1] +
1461                                               search.size[offsetIndex + 1] + 1,
1462                                      &status) != search.offset[offsetIndex + 1] ||
1463                    U_FAILURE(status)) {
1464                    log_err("Error getting preceeding match at index %d\n",
1465                            search.offset[offsetIndex + 1] + 1);
1466                }
1467            }
1468            offsetIndex += 2;
1469        }
1470        status = U_ZERO_ERROR;
1471        if (usearch_following(strsrch, u_strlen(text), &status) !=
1472            USEARCH_DONE) {
1473            log_err("Error expecting out of bounds match\n");
1474        }
1475        if (usearch_preceding(strsrch, 0, &status) != USEARCH_DONE) {
1476            log_err("Error expecting out of bounds match\n");
1477        }
1478        count ++;
1479        usearch_close(strsrch);
1480    }
1481    close();
1482}
1483
1484static void TestReset(void)
1485{
1486    UErrorCode     status    = U_ZERO_ERROR;
1487    UChar          text[]    = {0x66, 0x69, 0x73, 0x68, 0x20,
1488                                0x66, 0x69, 0x73, 0x68};
1489    UChar          pattern[] = {0x73};
1490    UStringSearch *strsrch;
1491
1492    open(&status);
1493    if (U_FAILURE(status)) {
1494        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1495        return;
1496    }
1497    strsrch = usearch_openFromCollator(pattern, 1, text, 9,
1498                                                      EN_US_, NULL, &status);
1499    if (U_FAILURE(status)) {
1500        log_err("Error opening string search %s\n", u_errorName(status));
1501        if (strsrch != NULL) {
1502            usearch_close(strsrch);
1503        }
1504        return;
1505    }
1506    usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
1507    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1508                         &status);
1509    usearch_setOffset(strsrch, 9, &status);
1510    if (U_FAILURE(status)) {
1511        log_err("Error setting attributes and offsets\n");
1512    }
1513    else {
1514        usearch_reset(strsrch);
1515        if (usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF ||
1516            usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
1517                                 USEARCH_OFF ||
1518            usearch_getOffset(strsrch) != 0 ||
1519            usearch_getMatchedLength(strsrch) != 0 ||
1520            usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
1521            log_err("Error resetting string search\n");
1522        }
1523        usearch_previous(strsrch, &status);
1524        if (usearch_getMatchedStart(strsrch) != 7 ||
1525            usearch_getMatchedLength(strsrch) != 1) {
1526            log_err("Error resetting string search\n");
1527        }
1528    }
1529    usearch_close(strsrch);
1530    close();
1531}
1532
1533static void TestSupplementary(void)
1534{
1535    int count = 0;
1536    UErrorCode status = U_ZERO_ERROR;
1537    open(&status);
1538    if (U_FAILURE(status)) {
1539        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1540        return;
1541    }
1542    while (SUPPLEMENTARY[count].text != NULL) {
1543        if (!assertEqual(SUPPLEMENTARY[count])) {
1544            log_err("Error at test number %d\n", count);
1545        }
1546        count ++;
1547    }
1548    close();
1549}
1550
1551static void TestContraction(void)
1552{
1553    UChar          rules[128];
1554    UChar          pattern[128];
1555    UChar          text[128];
1556    UCollator     *collator;
1557    UErrorCode     status = U_ZERO_ERROR;
1558    int            count = 0;
1559    UStringSearch *strsrch;
1560    memset(rules, 0, 128*sizeof(UChar));
1561    memset(pattern, 0, 128*sizeof(UChar));
1562    memset(text, 0, 128*sizeof(UChar));
1563
1564    u_unescape(CONTRACTIONRULE, rules, 128);
1565    collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
1566                              UCOL_TERTIARY, NULL, &status);
1567    if(status == U_FILE_ACCESS_ERROR) {
1568      log_data_err("Is your data around?\n");
1569      return;
1570    } else if(U_FAILURE(status)) {
1571      log_err("Error opening collator %s\n", u_errorName(status));
1572      return;
1573    }
1574    strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
1575                                       &status);
1576    if (U_FAILURE(status)) {
1577        log_err("Error opening string search %s\n", u_errorName(status));
1578    }
1579
1580    while (CONTRACTION[count].text != NULL) {
1581        u_unescape(CONTRACTION[count].text, text, 128);
1582        u_unescape(CONTRACTION[count].pattern, pattern, 128);
1583        usearch_setText(strsrch, text, -1, &status);
1584        usearch_setPattern(strsrch, pattern, -1, &status);
1585        if (!assertEqualWithUStringSearch(strsrch, CONTRACTION[count])) {
1586            log_err("Error at test number %d\n", count);
1587        }
1588        count ++;
1589    }
1590    usearch_close(strsrch);
1591    ucol_close(collator);
1592}
1593
1594static void TestIgnorable(void)
1595{
1596    UChar          rules[128];
1597    UChar          pattern[128];
1598    UChar          text[128];
1599    UCollator     *collator;
1600    UErrorCode     status = U_ZERO_ERROR;
1601    UStringSearch *strsrch;
1602    uint32_t       count = 0;
1603
1604    memset(rules, 0, 128*sizeof(UChar));
1605    memset(pattern, 0, 128*sizeof(UChar));
1606    memset(text, 0, 128*sizeof(UChar));
1607
1608    u_unescape(IGNORABLERULE, rules, 128);
1609    collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
1610                              IGNORABLE[count].strength, NULL, &status);
1611    if(status == U_FILE_ACCESS_ERROR) {
1612      log_data_err("Is your data around?\n");
1613      return;
1614    } else if(U_FAILURE(status)) {
1615        log_err("Error opening collator %s\n", u_errorName(status));
1616        return;
1617    }
1618    strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
1619                                       &status);
1620    if (U_FAILURE(status)) {
1621        log_err("Error opening string search %s\n", u_errorName(status));
1622    }
1623
1624    while (IGNORABLE[count].text != NULL) {
1625        u_unescape(IGNORABLE[count].text, text, 128);
1626        u_unescape(IGNORABLE[count].pattern, pattern, 128);
1627        usearch_setText(strsrch, text, -1, &status);
1628        usearch_setPattern(strsrch, pattern, -1, &status);
1629        if (!assertEqualWithUStringSearch(strsrch, IGNORABLE[count])) {
1630            log_err("Error at test number %d\n", count);
1631        }
1632        count ++;
1633    }
1634    usearch_close(strsrch);
1635    ucol_close(collator);
1636}
1637
1638static void TestDiacriticMatch(void)
1639{
1640    UChar          pattern[128];
1641    UChar          text[128];
1642    UErrorCode     status = U_ZERO_ERROR;
1643    UStringSearch *strsrch = NULL;
1644    UCollator *coll = NULL;
1645    uint32_t       count = 0;
1646    SearchData search;
1647
1648    memset(pattern, 0, 128*sizeof(UChar));
1649    memset(text, 0, 128*sizeof(UChar));
1650
1651    strsrch = usearch_open(pattern, 1, text, 1, uloc_getDefault(), NULL, &status);
1652	if (U_FAILURE(status)) {
1653        log_err_status(status, "Error opening string search %s\n", u_errorName(status));
1654        return;
1655    }
1656
1657    search = DIACRITICMATCH[count];
1658    while (search.text != NULL) {
1659    	if (search.collator != NULL) {
1660    		coll = ucol_openFromShortString(search.collator, FALSE, NULL, &status);
1661    	} else {
1662            /* Always use "en_US" because some of these tests fail in Danish locales. */
1663    		coll = ucol_open("en_US"/*uloc_getDefault()*/, &status);
1664    		ucol_setStrength(coll, search.strength);
1665    	}
1666    	if (U_FAILURE(status)) {
1667	        log_err("Error opening string search collator(\"%s\") %s\n", search.collator, u_errorName(status));
1668	        return;
1669	    }
1670
1671    	usearch_setCollator(strsrch, coll, &status);
1672    	if (U_FAILURE(status)) {
1673	        log_err("Error setting string search collator %s\n", u_errorName(status));
1674	        return;
1675	    }
1676
1677        u_unescape(search.text, text, 128);
1678        u_unescape(search.pattern, pattern, 128);
1679        usearch_setText(strsrch, text, -1, &status);
1680        usearch_setPattern(strsrch, pattern, -1, &status);
1681        if (!assertEqualWithUStringSearch(strsrch, search)) {
1682            log_err("Error at test number %d\n", count);
1683        }
1684        ucol_close(coll);
1685
1686        search = DIACRITICMATCH[++count];
1687    }
1688    usearch_close(strsrch);
1689}
1690
1691static void TestCanonical(void)
1692{
1693    int count = 0;
1694    UErrorCode status = U_ZERO_ERROR;
1695    open(&status);
1696    if (U_FAILURE(status)) {
1697        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1698        return;
1699    }
1700    while (BASICCANONICAL[count].text != NULL) {
1701        if (!assertCanonicalEqual(BASICCANONICAL[count])) {
1702            log_err("Error at test number %d\n", count);
1703        }
1704        count ++;
1705    }
1706    close();
1707}
1708
1709static void TestNormCanonical(void)
1710{
1711    int count = 0;
1712    UErrorCode status = U_ZERO_ERROR;
1713    open(&status);
1714    if (U_FAILURE(status)) {
1715        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1716        return;
1717    }
1718    ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
1719    count = 0;
1720    while (NORMCANONICAL[count].text != NULL) {
1721        if (!assertCanonicalEqual(NORMCANONICAL[count])) {
1722            log_err("Error at test number %d\n", count);
1723        }
1724        count ++;
1725    }
1726    ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
1727    close();
1728}
1729
1730static void TestStrengthCanonical(void)
1731{
1732    int count = 0;
1733    UErrorCode status = U_ZERO_ERROR;
1734    open(&status);
1735    if (U_FAILURE(status)) {
1736        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1737        return;
1738    }
1739    while (STRENGTHCANONICAL[count].text != NULL) {
1740        if (!assertCanonicalEqual(STRENGTHCANONICAL[count])) {
1741            log_err("Error at test number %d\n", count);
1742        }
1743        count ++;
1744    }
1745    close();
1746}
1747
1748static void TestBreakIteratorCanonical(void) {
1749    UErrorCode      status      = U_ZERO_ERROR;
1750    int             count = 0;
1751
1752    CHECK_BREAK("x");
1753
1754#if !UCONFIG_NO_BREAK_ITERATION
1755
1756    open(&status);
1757    if (U_FAILURE(status)) {
1758        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1759        return;
1760    }
1761    while (count < 4) {
1762        /* 0-3 test are fixed */
1763              UChar           pattern[32];
1764              UChar           text[128];
1765        const SearchData     *search   = &(BREAKITERATORCANONICAL[count]);
1766              UCollator      *collator = getCollator(search->collator);
1767              UBreakIterator *breaker  = getBreakIterator(search->breaker);
1768              UStringSearch  *strsrch;
1769
1770        u_unescape(search->text, text, 128);
1771        u_unescape(search->pattern, pattern, 32);
1772        ucol_setStrength(collator, search->strength);
1773
1774        strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
1775                                           breaker, &status);
1776        if(status == U_FILE_ACCESS_ERROR) {
1777            log_data_err("Is your data around?\n");
1778            goto ENDTESTBREAKITERATOR;
1779        } else if(U_FAILURE(status)) {
1780            log_err("Error opening searcher\n");
1781            goto ENDTESTBREAKITERATOR;
1782        }
1783        usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1784                             &status);
1785        if (U_FAILURE(status) ||
1786            usearch_getBreakIterator(strsrch) != breaker) {
1787            log_err("Error setting break iterator\n");
1788            usearch_close(strsrch);
1789            goto ENDTESTBREAKITERATOR;
1790        }
1791        if (!assertEqualWithUStringSearch(strsrch, *search)) {
1792            ucol_setStrength(collator, UCOL_TERTIARY);
1793            usearch_close(strsrch);
1794            goto ENDTESTBREAKITERATOR;
1795        }
1796        search   = &(BREAKITERATOREXACT[count + 1]);
1797        breaker  = getBreakIterator(search->breaker);
1798        usearch_setBreakIterator(strsrch, breaker, &status);
1799        if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != breaker) {
1800            log_err("Error setting break iterator\n");
1801            usearch_close(strsrch);
1802            goto ENDTESTBREAKITERATOR;
1803        }
1804        usearch_reset(strsrch);
1805        usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1806                             &status);
1807        if (!assertEqualWithUStringSearch(strsrch, *search)) {
1808            log_err("Error at test number %d\n", count);
1809            usearch_close(strsrch);
1810            goto ENDTESTBREAKITERATOR;
1811        }
1812        usearch_close(strsrch);
1813        count += 2;
1814    }
1815    count = 0;
1816    while (BREAKITERATORCANONICAL[count].text != NULL) {
1817         if (!assertEqual(BREAKITERATORCANONICAL[count])) {
1818             log_err("Error at test number %d\n", count);
1819             goto ENDTESTBREAKITERATOR;
1820         }
1821         count ++;
1822    }
1823
1824ENDTESTBREAKITERATOR:
1825    close();
1826#endif
1827}
1828
1829static void TestVariableCanonical(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    ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
1839    if (U_FAILURE(status)) {
1840        log_err("Error setting collation alternate attribute %s\n",
1841            u_errorName(status));
1842    }
1843    while (VARIABLE[count].text != NULL) {
1844        log_verbose("variable %d\n", count);
1845        if (!assertCanonicalEqual(VARIABLE[count])) {
1846            log_err("Error at test number %d\n", count);
1847        }
1848        count ++;
1849    }
1850    ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
1851                      UCOL_NON_IGNORABLE, &status);
1852    close();
1853}
1854
1855static void TestOverlapCanonical(void)
1856{
1857    int count = 0;
1858    UErrorCode status = U_ZERO_ERROR;
1859    open(&status);
1860    if (U_FAILURE(status)) {
1861        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1862        return;
1863    }
1864    while (OVERLAPCANONICAL[count].text != NULL) {
1865        if (!assertEqualWithAttribute(OVERLAPCANONICAL[count], USEARCH_ON,
1866                                      USEARCH_ON)) {
1867            log_err("Error at overlap test number %d\n", count);
1868        }
1869        count ++;
1870    }
1871    count = 0;
1872    while (NONOVERLAP[count].text != NULL) {
1873        if (!assertCanonicalEqual(NONOVERLAPCANONICAL[count])) {
1874            log_err("Error at non overlap test number %d\n", count);
1875        }
1876        count ++;
1877    }
1878
1879    count = 0;
1880    while (count < 1) {
1881              UChar           pattern[32];
1882              UChar           text[128];
1883        const SearchData     *search   = &(OVERLAPCANONICAL[count]);
1884              UCollator      *collator = getCollator(search->collator);
1885              UStringSearch  *strsrch;
1886              status   = U_ZERO_ERROR;
1887
1888        u_unescape(search->text, text, 128);
1889        u_unescape(search->pattern, pattern, 32);
1890        strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
1891                                           NULL, &status);
1892        if(status == U_FILE_ACCESS_ERROR) {
1893          log_data_err("Is your data around?\n");
1894          return;
1895        } else if(U_FAILURE(status)) {
1896          log_err("Error opening searcher\n");
1897          return;
1898        }
1899        usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1900                             &status);
1901        usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
1902        if (U_FAILURE(status) ||
1903            usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
1904            log_err("Error setting overlap option\n");
1905        }
1906        if (!assertEqualWithUStringSearch(strsrch, *search)) {
1907            usearch_close(strsrch);
1908            return;
1909        }
1910        search   = &(NONOVERLAPCANONICAL[count]);
1911        usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
1912        if (U_FAILURE(status) ||
1913            usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
1914            log_err("Error setting overlap option\n");
1915        }
1916        usearch_reset(strsrch);
1917        if (!assertEqualWithUStringSearch(strsrch, *search)) {
1918            usearch_close(strsrch);
1919            log_err("Error at test number %d\n", count);
1920         }
1921
1922        count ++;
1923        usearch_close(strsrch);
1924    }
1925    close();
1926}
1927
1928static void TestCollatorCanonical(void)
1929{
1930    /* test collator that thinks "o" and "p" are the same thing */
1931          UChar          rules[32];
1932          UCollator     *tailored = NULL;
1933          UErrorCode     status = U_ZERO_ERROR;
1934          UChar          pattern[32];
1935          UChar          text[128];
1936          UStringSearch *strsrch;
1937
1938    open(&status);
1939    if (U_FAILURE(status)) {
1940        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
1941        return;
1942    }
1943    u_unescape(COLLATORCANONICAL[0].text, text, 128);
1944    u_unescape(COLLATORCANONICAL[0].pattern, pattern, 32);
1945
1946    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
1947                                       NULL, &status);
1948    if(status == U_FILE_ACCESS_ERROR) {
1949      log_data_err("Is your data around?\n");
1950      return;
1951    } else if(U_FAILURE(status)) {
1952      log_err("Error opening searcher\n");
1953      return;
1954    }
1955    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1956                         &status);
1957    if (U_FAILURE(status)) {
1958        log_err("Error opening string search %s\n", u_errorName(status));
1959    }
1960    if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
1961        goto ENDTESTCOLLATOR;
1962    }
1963
1964    u_unescape(TESTCOLLATORRULE, rules, 32);
1965    tailored = ucol_openRules(rules, -1, UCOL_ON,
1966                              COLLATORCANONICAL[1].strength, NULL, &status);
1967    if (U_FAILURE(status)) {
1968        log_err("Error opening rule based collator %s\n", u_errorName(status));
1969    }
1970
1971    usearch_setCollator(strsrch, tailored, &status);
1972    if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
1973        log_err("Error setting rule based collator\n");
1974    }
1975    usearch_reset(strsrch);
1976    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1977                         &status);
1978    if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[1])) {
1979        goto ENDTESTCOLLATOR;
1980    }
1981
1982    usearch_setCollator(strsrch, EN_US_, &status);
1983    usearch_reset(strsrch);
1984    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
1985                         &status);
1986    if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
1987        log_err("Error setting rule based collator\n");
1988    }
1989    if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
1990        goto ENDTESTCOLLATOR;
1991    }
1992
1993ENDTESTCOLLATOR:
1994    usearch_close(strsrch);
1995    if (tailored != NULL) {
1996        ucol_close(tailored);
1997    }
1998    close();
1999}
2000
2001static void TestPatternCanonical(void)
2002{
2003          UStringSearch *strsrch;
2004          UChar          pattern[32];
2005          UChar          text[128];
2006    const UChar         *temp;
2007          int32_t        templength;
2008          UErrorCode     status = U_ZERO_ERROR;
2009
2010    open(&status);
2011    if (U_FAILURE(status)) {
2012        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
2013        return;
2014    }
2015    u_unescape(PATTERNCANONICAL[0].text, text, 128);
2016    u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
2017
2018    ucol_setStrength(EN_US_, PATTERNCANONICAL[0].strength);
2019    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
2020                                       NULL, &status);
2021    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2022                         &status);
2023    if (U_FAILURE(status)) {
2024        log_err("Error opening string search %s\n", u_errorName(status));
2025        goto ENDTESTPATTERN;
2026    }
2027    temp = usearch_getPattern(strsrch, &templength);
2028    if (u_strcmp(pattern, temp) != 0) {
2029        log_err("Error setting pattern\n");
2030    }
2031    if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
2032        goto ENDTESTPATTERN;
2033    }
2034
2035    u_unescape(PATTERNCANONICAL[1].pattern, pattern, 32);
2036    usearch_setPattern(strsrch, pattern, -1, &status);
2037    temp = usearch_getPattern(strsrch, &templength);
2038    if (u_strcmp(pattern, temp) != 0) {
2039        log_err("Error setting pattern\n");
2040        goto ENDTESTPATTERN;
2041    }
2042    usearch_reset(strsrch);
2043    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2044                         &status);
2045    if (U_FAILURE(status)) {
2046        log_err("Error setting pattern %s\n", u_errorName(status));
2047    }
2048    if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[1])) {
2049        goto ENDTESTPATTERN;
2050    }
2051
2052    u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
2053    usearch_setPattern(strsrch, pattern, -1, &status);
2054    temp = usearch_getPattern(strsrch, &templength);
2055    if (u_strcmp(pattern, temp) != 0) {
2056        log_err("Error setting pattern\n");
2057        goto ENDTESTPATTERN;
2058    }
2059    usearch_reset(strsrch);
2060    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2061                         &status);
2062    if (U_FAILURE(status)) {
2063        log_err("Error setting pattern %s\n", u_errorName(status));
2064    }
2065    if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
2066        goto ENDTESTPATTERN;
2067    }
2068ENDTESTPATTERN:
2069    ucol_setStrength(EN_US_, UCOL_TERTIARY);
2070    if (strsrch != NULL) {
2071        usearch_close(strsrch);
2072    }
2073    close();
2074}
2075
2076static void TestTextCanonical(void)
2077{
2078          UStringSearch *strsrch;
2079          UChar          pattern[32];
2080          UChar          text[128];
2081    const UChar         *temp;
2082          int32_t        templength;
2083          UErrorCode     status = U_ZERO_ERROR;
2084
2085    u_unescape(TEXTCANONICAL[0].text, text, 128);
2086    u_unescape(TEXTCANONICAL[0].pattern, pattern, 32);
2087
2088    open(&status);
2089    if (U_FAILURE(status)) {
2090        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
2091        return;
2092    }
2093    strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
2094                                       NULL, &status);
2095    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2096                         &status);
2097
2098    if (U_FAILURE(status)) {
2099        log_err("Error opening string search %s\n", u_errorName(status));
2100        goto ENDTESTPATTERN;
2101    }
2102    temp = usearch_getText(strsrch, &templength);
2103    if (u_strcmp(text, temp) != 0) {
2104        log_err("Error setting text\n");
2105    }
2106    if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
2107        goto ENDTESTPATTERN;
2108    }
2109
2110    u_unescape(TEXTCANONICAL[1].text, text, 32);
2111    usearch_setText(strsrch, text, -1, &status);
2112    temp = usearch_getText(strsrch, &templength);
2113    if (u_strcmp(text, temp) != 0) {
2114        log_err("Error setting text\n");
2115        goto ENDTESTPATTERN;
2116    }
2117    if (U_FAILURE(status)) {
2118        log_err("Error setting text %s\n", u_errorName(status));
2119    }
2120    if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[1])) {
2121        goto ENDTESTPATTERN;
2122    }
2123
2124    u_unescape(TEXTCANONICAL[0].text, text, 32);
2125    usearch_setText(strsrch, text, -1, &status);
2126    temp = usearch_getText(strsrch, &templength);
2127    if (u_strcmp(text, temp) != 0) {
2128        log_err("Error setting text\n");
2129        goto ENDTESTPATTERN;
2130    }
2131    if (U_FAILURE(status)) {
2132        log_err("Error setting pattern %s\n", u_errorName(status));
2133    }
2134    if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
2135        goto ENDTESTPATTERN;
2136    }
2137ENDTESTPATTERN:
2138    if (strsrch != NULL) {
2139        usearch_close(strsrch);
2140    }
2141    close();
2142}
2143
2144static void TestCompositeBoundariesCanonical(void)
2145{
2146    int count = 0;
2147    UErrorCode status = U_ZERO_ERROR;
2148    open(&status);
2149    if (U_FAILURE(status)) {
2150        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
2151        return;
2152    }
2153    while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
2154        log_verbose("composite %d\n", count);
2155        if (!assertCanonicalEqual(COMPOSITEBOUNDARIESCANONICAL[count])) {
2156            log_err("Error at test number %d\n", count);
2157        }
2158        count ++;
2159    }
2160    close();
2161}
2162
2163static void TestGetSetOffsetCanonical(void)
2164{
2165    int            searchDataIndex   = 0;
2166    UChar          pattern[32];
2167    UChar          text[128];
2168    UErrorCode     status  = U_ZERO_ERROR;
2169    UStringSearch *strsrch;
2170    UCollator     *collator;
2171
2172    memset(pattern, 0, 32*sizeof(UChar));
2173    memset(text, 0, 128*sizeof(UChar));
2174
2175    open(&status);
2176    if (U_FAILURE(status)) {
2177        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
2178        return;
2179    }
2180    strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
2181                                       &status);
2182
2183    collator = usearch_getCollator(strsrch);
2184    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
2185
2186    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2187                         &status);
2188
2189    /* testing out of bounds error */
2190    usearch_setOffset(strsrch, -1, &status);
2191    if (U_SUCCESS(status)) {
2192        log_err("Error expecting set offset error\n");
2193    }
2194    usearch_setOffset(strsrch, 128, &status);
2195    if (U_SUCCESS(status)) {
2196        log_err("Error expecting set offset error\n");
2197    }
2198    while (BASICCANONICAL[searchDataIndex].text != NULL) {
2199        int         count       = 0;
2200        SearchData  search      = BASICCANONICAL[searchDataIndex ++];
2201        int32_t matchindex  = search.offset[count];
2202        int32_t     textlength;
2203
2204        if (BASICCANONICAL[searchDataIndex].text == NULL) {
2205            /* skip the last one */
2206            break;
2207        }
2208
2209        u_unescape(search.text, text, 128);
2210        u_unescape(search.pattern, pattern, 32);
2211        status = U_ZERO_ERROR;
2212        usearch_setText(strsrch, text, -1, &status);
2213        usearch_setPattern(strsrch, pattern, -1, &status);
2214        while (U_SUCCESS(status) && matchindex >= 0) {
2215            uint32_t matchlength = search.size[count];
2216            usearch_next(strsrch, &status);
2217            if (matchindex != usearch_getMatchedStart(strsrch) ||
2218                matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
2219                char *str = toCharString(usearch_getText(strsrch,
2220                                                         &textlength));
2221                log_err("Text: %s\n", str);
2222                str = toCharString(usearch_getPattern(strsrch, &textlength));
2223                log_err("Pattern: %s\n", str);
2224                log_err("Error match found at %d %d\n",
2225                        usearch_getMatchedStart(strsrch),
2226                        usearch_getMatchedLength(strsrch));
2227                goto bail;
2228            }
2229            matchindex = search.offset[count + 1] == -1 ? -1 :
2230                         search.offset[count + 2];
2231            if (search.offset[count + 1] != -1) {
2232                usearch_setOffset(strsrch, search.offset[count + 1] + 1,
2233                                  &status);
2234                if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
2235                    log_err("Error setting offset\n");
2236                    goto bail;
2237                }
2238            }
2239
2240            count += 2;
2241        }
2242        usearch_next(strsrch, &status);
2243        if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
2244            char *str = toCharString(usearch_getText(strsrch, &textlength));
2245            log_err("Text: %s\n", str);
2246            str = toCharString(usearch_getPattern(strsrch, &textlength));
2247            log_err("Pattern: %s\n", str);
2248            log_err("Error match found at %d %d\n",
2249                        usearch_getMatchedStart(strsrch),
2250                        usearch_getMatchedLength(strsrch));
2251            goto bail;
2252        }
2253    }
2254
2255bail:
2256    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
2257    usearch_close(strsrch);
2258    close();
2259}
2260
2261static void TestSupplementaryCanonical(void)
2262{
2263    int count = 0;
2264    UErrorCode status = U_ZERO_ERROR;
2265    open(&status);
2266    if (U_FAILURE(status)) {
2267        log_err_status(status, "Unable to open static collators %s\n", u_errorName(status));
2268        return;
2269    }
2270    while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
2271        if (!assertCanonicalEqual(SUPPLEMENTARYCANONICAL[count])) {
2272            log_err("Error at test number %d\n", count);
2273        }
2274        count ++;
2275    }
2276    close();
2277}
2278
2279static void TestContractionCanonical(void)
2280{
2281    UChar          rules[128];
2282    UChar          pattern[128];
2283    UChar          text[128];
2284    UCollator     *collator = NULL;
2285    UErrorCode     status = U_ZERO_ERROR;
2286    int            count = 0;
2287    UStringSearch *strsrch = NULL;
2288    memset(rules, 0, 128*sizeof(UChar));
2289    memset(pattern, 0, 128*sizeof(UChar));
2290    memset(text, 0, 128*sizeof(UChar));
2291
2292    u_unescape(CONTRACTIONRULE, rules, 128);
2293    collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
2294                              UCOL_TERTIARY, NULL, &status);
2295    if(status == U_FILE_ACCESS_ERROR) {
2296      log_data_err("Is your data around?\n");
2297      return;
2298    } else if(U_FAILURE(status)) {
2299      log_err("Error opening collator %s\n", u_errorName(status));
2300      return;
2301    }
2302    strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
2303                                       &status);
2304    usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
2305                         &status);
2306    if (U_FAILURE(status)) {
2307        log_err("Error opening string search %s\n", u_errorName(status));
2308    }
2309
2310    while (CONTRACTIONCANONICAL[count].text != NULL) {
2311        u_unescape(CONTRACTIONCANONICAL[count].text, text, 128);
2312        u_unescape(CONTRACTIONCANONICAL[count].pattern, pattern, 128);
2313        usearch_setText(strsrch, text, -1, &status);
2314        usearch_setPattern(strsrch, pattern, -1, &status);
2315        if (!assertEqualWithUStringSearch(strsrch,
2316                                              CONTRACTIONCANONICAL[count])) {
2317            log_err("Error at test number %d\n", count);
2318        }
2319        count ++;
2320    }
2321    usearch_close(strsrch);
2322    ucol_close(collator);
2323}
2324
2325static void TestNumeric(void) {
2326    UCollator     *coll = NULL;
2327    UStringSearch *strsrch = NULL;
2328    UErrorCode     status = U_ZERO_ERROR;
2329
2330    UChar          pattern[128];
2331    UChar          text[128];
2332    memset(pattern, 0, 128*sizeof(UChar));
2333    memset(text, 0, 128*sizeof(UChar));
2334
2335    coll = ucol_open("", &status);
2336    if(U_FAILURE(status)) {
2337        log_data_err("Could not open UCA. Is your data around?\n");
2338        return;
2339    }
2340
2341    ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status);
2342
2343    strsrch = usearch_openFromCollator(pattern, 1, text, 1, coll, NULL, &status);
2344
2345    if(status != U_UNSUPPORTED_ERROR || U_SUCCESS(status)) {
2346        log_err("Expected U_UNSUPPORTED_ERROR when trying to instantiate a search object from a CODAN collator, got %s instead\n", u_errorName(status));
2347        if(strsrch) {
2348            usearch_close(strsrch);
2349        }
2350    }
2351
2352    ucol_close(coll);
2353
2354}
2355
2356/* This test is for ticket 4038 due to incorrect backward searching when certain patterns have a length > 1 */
2357static void TestForwardBackward(void) {
2358    UErrorCode status = U_ZERO_ERROR;
2359    UCollator *coll = NULL;
2360    UStringSearch *search = NULL;
2361    UChar usrcstr[32], value[4];
2362    int32_t pos= -1;
2363    int32_t expectedPos = 9;
2364
2365    coll = ucol_open("en_GB", &status);
2366    if (U_FAILURE(status)) {
2367        log_err_status(status, "ucol_open failed: %s\n", u_errorName(status));
2368        goto exitTestForwardBackward;
2369    }
2370    ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status);
2371    ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &status);
2372    ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
2373
2374    u_uastrcpy(usrcstr, "QBitArray::bitarr_data"); /* text */
2375    u_uastrcpy(value, "::");                       /* pattern */
2376
2377    search = usearch_openFromCollator(value, 2, usrcstr, 22, coll, NULL, &status);
2378    if (U_FAILURE(status)) {
2379        log_err("usearch_openFromCollator failed: %s\n", u_errorName(status));
2380        goto exitTestForwardBackward;
2381    }
2382
2383    usearch_reset(search);
2384    /* forward search */
2385    pos = usearch_first(search, &status);
2386    if (pos != expectedPos) {
2387        log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
2388        goto exitTestForwardBackward;
2389    }
2390
2391    pos = -1;
2392    usearch_reset(search);
2393    /* backward search */
2394    pos = usearch_last(search, &status);
2395    if (pos != expectedPos) {
2396        log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
2397    }
2398
2399exitTestForwardBackward :
2400    if (coll != NULL) {
2401        ucol_close(coll);
2402    }
2403    if (search != NULL) {
2404        usearch_close(search);
2405    }
2406}
2407
2408#define TEST_ASSERT(x) \
2409   {if (U_FAILURE(x)) {log_err_status(x, "%s:%d: FAIL: test assertion failure \n", __FILE__, __LINE__);\
2410   }}
2411
2412static void TestSearchForNull(void) {
2413    UCollator *coll;
2414    UErrorCode ec;
2415    UStringSearch *search;
2416    int pos;
2417    int len;
2418    int expectedPos;
2419    int expectedLen;
2420    int expectedNum;
2421    int count = 0;
2422    const UChar zerodigit = 0x0030; /* 0 */
2423    const UChar nulldigit = 0x0000; /* null */
2424
2425    /* static const UChar var[(length)+1]=U_DECLARE_UTF16(cs) */
2426#define PATTERN_LEN 4
2427#define TEXT_LEN 10
2428
2429    U_STRING_DECL(_pattern, "IS 0", PATTERN_LEN);
2430    U_STRING_DECL(_text, "_0IS 0 OK?", TEXT_LEN);
2431    UChar pattern[PATTERN_LEN + 1], text[TEXT_LEN + 1];
2432
2433    U_STRING_INIT(_pattern, "IS 0", PATTERN_LEN);
2434    U_STRING_INIT(_text, "_0IS 0 OK?", TEXT_LEN);
2435    expectedPos = 2;
2436    expectedLen = 4;
2437    expectedNum = 1;
2438
2439    for (pos = 0; pos < PATTERN_LEN; pos++) {
2440        if (_pattern[pos] == zerodigit) {
2441            pattern[pos] = nulldigit;
2442        } else {
2443            pattern[pos] = _pattern[pos];
2444        }
2445    }
2446    pattern[PATTERN_LEN] = 0x0000;
2447
2448    for (pos = 0; pos < TEXT_LEN; pos++) {
2449        if (_text[pos] == zerodigit) {
2450            text[pos] = nulldigit;
2451        } else {
2452            text[pos] = _text[pos];
2453        }
2454    }
2455    text[TEXT_LEN] = 0x0000;
2456
2457    ec = U_ZERO_ERROR;
2458
2459    /* create a US-English collator */
2460    coll = ucol_open("en_US", &ec);
2461
2462    /* make sure we didn't fail. */
2463     TEST_ASSERT (ec);
2464
2465    ucol_setStrength(coll, UCOL_IDENTICAL);
2466
2467    /* open a search looking for 0 */
2468    search = usearch_openFromCollator(pattern, PATTERN_LEN, text,
2469            TEXT_LEN, coll, NULL, &ec);
2470     TEST_ASSERT (ec);
2471
2472    if (coll != NULL && search != NULL) {
2473        pos = usearch_first(search, &ec);
2474        len = usearch_getMatchedLength(search);
2475        if (pos != expectedPos) {
2476            log_err("Expected search result: %d; Got instead: %d\n", expectedPos,
2477                    pos);
2478        }
2479
2480        if (len != expectedLen) {
2481            log_err("Expected search result length: %d; Got instead: %d\n",
2482                    expectedLen, len);
2483        }
2484
2485        for (pos = usearch_first(search, &ec); pos != USEARCH_DONE; pos
2486                = usearch_next(search, &ec)) {
2487            log_verbose("Match at %d\n", pos);
2488            count += 1;
2489        }
2490
2491        if (count != expectedNum) {
2492            log_err("Expected %d search hits, found %d\n", expectedNum, count);
2493        }
2494    }
2495
2496    ucol_close(coll);
2497    usearch_close(search);
2498}
2499
2500static void TestStrengthIdentical(void)
2501{
2502	UCollator *coll;
2503	UErrorCode ec = U_ZERO_ERROR;
2504	UStringSearch *search;
2505
2506    UChar pattern[] = {0x05E9, 0x0591, 0x05E9};
2507    UChar text[]    = {0x05E9, 0x0592, 0x05E9};
2508    int32_t pLen = sizeof (pattern) / sizeof(pattern[0]);
2509    int32_t tLen = sizeof(text) / sizeof (text[0]);
2510	int32_t expectedPos = 0;
2511	int32_t expectedLen = 3;
2512
2513	int32_t pos;
2514	int32_t len;
2515
2516    /* create a US-English collator */
2517	coll = ucol_open ("en_US", &ec);
2518
2519	/* make sure we didn't fail. */
2520	TEST_ASSERT (ec);
2521
2522    ucol_setStrength( coll, UCOL_TERTIARY);
2523
2524	/* open a search looking for 0 */
2525	search = usearch_openFromCollator (pattern, pLen, text, tLen, coll, NULL, &ec);
2526	TEST_ASSERT (ec);
2527
2528    if (coll != NULL && search != NULL) {
2529	    pos = usearch_first(search, &ec);
2530	    len = usearch_getMatchedLength(search);
2531
2532	    if(pos != expectedPos) {
2533		    log_err("Expected search result: %d; Got instead: %d\n", expectedPos, pos);
2534	    }
2535
2536	    if(len != expectedLen) {
2537		    log_err("Expected search result length: %d; Got instead: %d\n", expectedLen, len);
2538	    }
2539
2540        /* Now try it at strength == UCOL_IDENTICAL */
2541        ucol_setStrength(coll, UCOL_IDENTICAL);
2542	    usearch_reset(search);
2543
2544	    pos = usearch_first(search, &ec);
2545	    len = usearch_getMatchedLength(search);
2546
2547	    if(pos != -1) {
2548		    log_err("Expected failure for strentgh = UCOL_IDENTICAL: got %d instead.\n", pos);
2549	    }
2550    }
2551
2552    usearch_close(search);
2553    ucol_close(coll);
2554}
2555
2556/**
2557* TestUsingSearchCollator
2558*/
2559
2560#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
2561
2562typedef struct {
2563    const UChar *   pattern;
2564    const int32_t * offsets;
2565    int32_t         offsetsLen;
2566} PatternAndOffsets;
2567
2568static const UChar scKoText[] = {
2569       0x0020,
2570/*01*/ 0xAC00, 0x0020,                         /* simple LV Hangul */
2571/*03*/ 0xAC01, 0x0020,                         /* simple LVT Hangul */
2572/*05*/ 0xAC0F, 0x0020,                         /* LVTT, last jamo expands for search */
2573/*07*/ 0xAFFF, 0x0020,                         /* LLVVVTT, every jamo expands for search */
2574/*09*/ 0x1100, 0x1161, 0x11A8, 0x0020,         /* 0xAC01 as conjoining jamo */
2575/*13*/ 0x1100, 0x1161, 0x1100, 0x0020,         /* 0xAC01 as basic conjoining jamo (per search rules) */
2576/*17*/ 0x3131, 0x314F, 0x3131, 0x0020,         /* 0xAC01 as compatibility jamo */
2577/*21*/ 0x1100, 0x1161, 0x11B6, 0x0020,         /* 0xAC0F as conjoining jamo; last expands for search */
2578/*25*/ 0x1100, 0x1161, 0x1105, 0x1112, 0x0020, /* 0xAC0F as basic conjoining jamo; last expands for search */
2579/*30*/ 0x1101, 0x1170, 0x11B6, 0x0020,         /* 0xAFFF as conjoining jamo; all expand for search */
2580/*34*/ 0x00E6, 0x0020,                         /* small letter ae, expands */
2581/*36*/ 0x1E4D, 0x0020,                         /* small letter o with tilde and acute, decomposes */
2582       0
2583};
2584
2585static const UChar scKoPat0[] = { 0xAC01, 0 };
2586static const UChar scKoPat1[] = { 0x1100, 0x1161, 0x11A8, 0 }; /* 0xAC01 as conjoining jamo */
2587static const UChar scKoPat2[] = { 0xAC0F, 0 };
2588static const UChar scKoPat3[] = { 0x1100, 0x1161, 0x1105, 0x1112, 0 }; /* 0xAC0F as basic conjoining jamo */
2589static const UChar scKoPat4[] = { 0xAFFF, 0 };
2590static const UChar scKoPat5[] = { 0x1101, 0x1170, 0x11B6, 0 }; /* 0xAFFF as conjoining jamo */
2591
2592static const int32_t scKoSrchOff01[] = { 3,  9, 13 };
2593static const int32_t scKoSrchOff23[] = { 5, 21, 25 };
2594static const int32_t scKoSrchOff45[] = { 7, 30     };
2595
2596static const PatternAndOffsets scKoSrchPatternsOffsets[] = {
2597    { scKoPat0, scKoSrchOff01, ARRAY_LENGTH(scKoSrchOff01) },
2598    { scKoPat1, scKoSrchOff01, ARRAY_LENGTH(scKoSrchOff01) },
2599    { scKoPat2, scKoSrchOff23, ARRAY_LENGTH(scKoSrchOff23) },
2600    { scKoPat3, scKoSrchOff23, ARRAY_LENGTH(scKoSrchOff23) },
2601    { scKoPat4, scKoSrchOff45, ARRAY_LENGTH(scKoSrchOff45) },
2602    { scKoPat5, scKoSrchOff45, ARRAY_LENGTH(scKoSrchOff45) },
2603    { NULL,     NULL,          0                           }
2604};
2605
2606static const int32_t scKoStndOff01[] = { 3,  9 };
2607static const int32_t scKoStndOff2[]  = { 5, 21 };
2608static const int32_t scKoStndOff3[]  = { 25    };
2609static const int32_t scKoStndOff45[] = { 7, 30 };
2610
2611static const PatternAndOffsets scKoStndPatternsOffsets[] = {
2612    { scKoPat0, scKoStndOff01, ARRAY_LENGTH(scKoStndOff01) },
2613    { scKoPat1, scKoStndOff01, ARRAY_LENGTH(scKoStndOff01) },
2614    { scKoPat2, scKoStndOff2,  ARRAY_LENGTH(scKoStndOff2)  },
2615    { scKoPat3, scKoStndOff3,  ARRAY_LENGTH(scKoStndOff3)  },
2616    { scKoPat4, scKoStndOff45, ARRAY_LENGTH(scKoStndOff45) },
2617    { scKoPat5, scKoStndOff45, ARRAY_LENGTH(scKoStndOff45) },
2618    { NULL,     NULL,          0                           }
2619};
2620
2621typedef struct {
2622    const char *  locale;
2623    const UChar * text;
2624    const PatternAndOffsets * patternsAndOffsets;
2625} TUSCItem;
2626
2627static const TUSCItem tuscItems[] = {
2628    { "root",                  scKoText, scKoStndPatternsOffsets },
2629    { "root@collation=search", scKoText, scKoSrchPatternsOffsets },
2630    { "ko@collation=search",   scKoText, scKoSrchPatternsOffsets },
2631    { NULL,                    NULL,     NULL                    }
2632};
2633
2634static const UChar dummyPat[] = { 0x0061, 0 };
2635
2636static void TestUsingSearchCollator(void)
2637{
2638    const TUSCItem * tuscItemPtr;
2639    for (tuscItemPtr = tuscItems; tuscItemPtr->locale != NULL; tuscItemPtr++) {
2640        UErrorCode status = U_ZERO_ERROR;
2641        UCollator* ucol = ucol_open(tuscItemPtr->locale, &status);
2642        if ( U_SUCCESS(status) ) {
2643            UStringSearch* usrch = usearch_openFromCollator(dummyPat, -1, tuscItemPtr->text, -1, ucol, NULL, &status);
2644            if ( U_SUCCESS(status) ) {
2645                const PatternAndOffsets * patternsOffsetsPtr;
2646                for ( patternsOffsetsPtr = tuscItemPtr->patternsAndOffsets; patternsOffsetsPtr->pattern != NULL; patternsOffsetsPtr++) {
2647                    usearch_setPattern(usrch, patternsOffsetsPtr->pattern, -1, &status);
2648                    if ( U_SUCCESS(status) ) {
2649                        int32_t offset;
2650                        const int32_t * nextOffsetPtr;
2651                        const int32_t * limitOffsetPtr;
2652
2653                        usearch_reset(usrch);
2654                        nextOffsetPtr = patternsOffsetsPtr->offsets;
2655                        limitOffsetPtr = patternsOffsetsPtr->offsets + patternsOffsetsPtr->offsetsLen;
2656                        while (TRUE) {
2657                            offset = usearch_next(usrch, &status);
2658                            if ( U_FAILURE(status) || offset == USEARCH_DONE ) {
2659                                break;
2660                            }
2661                            if ( nextOffsetPtr < limitOffsetPtr ) {
2662                                 if (offset != *nextOffsetPtr) {
2663                                     log_err("error, locale %s, expected usearch_next %d, got %d\n", tuscItemPtr->locale, *nextOffsetPtr, offset);
2664                                     nextOffsetPtr = limitOffsetPtr;
2665                                     break;
2666                                 }
2667                                 nextOffsetPtr++;
2668                            } else {
2669                                log_err("error, locale %s, usearch_next returned more matches than expected\n", tuscItemPtr->locale );
2670                            }
2671                        }
2672                        if ( U_FAILURE(status) ) {
2673                            log_err("error, locale %s, usearch_next failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
2674                        } else if ( nextOffsetPtr < limitOffsetPtr ) {
2675                            log_err("error, locale %s, usearch_next returned fewer matches than expected\n", tuscItemPtr->locale );
2676                        }
2677
2678                        status = U_ZERO_ERROR;
2679                        usearch_reset(usrch);
2680                        nextOffsetPtr = patternsOffsetsPtr->offsets + patternsOffsetsPtr->offsetsLen;
2681                        limitOffsetPtr = patternsOffsetsPtr->offsets;
2682                        while (TRUE) {
2683                            offset = usearch_previous(usrch, &status);
2684                            if ( U_FAILURE(status) || offset == USEARCH_DONE ) {
2685                                break;
2686                            }
2687                            if ( nextOffsetPtr > limitOffsetPtr ) {
2688                                nextOffsetPtr--;
2689                                if (offset != *nextOffsetPtr) {
2690                                     log_err("error, locale %s, expected usearch_previous %d, got %d\n", tuscItemPtr->locale, *nextOffsetPtr, offset);
2691                                     nextOffsetPtr = limitOffsetPtr;
2692                                      break;
2693                                }
2694                            } else {
2695                                log_err("error, locale %s, usearch_previous returned more matches than expected\n", tuscItemPtr->locale );
2696                            }
2697                        }
2698                        if ( U_FAILURE(status) ) {
2699                            log_err("error, locale %s, usearch_previous failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
2700                        } else if ( nextOffsetPtr > limitOffsetPtr ) {
2701                            log_err("error, locale %s, usearch_previous returned fewer matches than expected\n", tuscItemPtr->locale );
2702                        }
2703
2704                    } else {
2705                        log_err("error, locale %s, usearch_setPattern failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
2706                    }
2707                }
2708                usearch_close(usrch);
2709            } else {
2710                log_err("error, locale %s, usearch_openFromCollator failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
2711            }
2712            ucol_close(ucol);
2713        } else {
2714            log_err("error, locale %s, ucol_open failed: %s\n", tuscItemPtr->locale, u_errorName(status) );
2715        }
2716    }
2717}
2718
2719/**
2720* addSearchTest
2721*/
2722
2723void addSearchTest(TestNode** root)
2724{
2725    addTest(root, &TestStart, "tscoll/usrchtst/TestStart");
2726    addTest(root, &TestOpenClose, "tscoll/usrchtst/TestOpenClose");
2727    addTest(root, &TestInitialization, "tscoll/usrchtst/TestInitialization");
2728    addTest(root, &TestBasic, "tscoll/usrchtst/TestBasic");
2729    addTest(root, &TestNormExact, "tscoll/usrchtst/TestNormExact");
2730    addTest(root, &TestStrength, "tscoll/usrchtst/TestStrength");
2731    addTest(root, &TestBreakIterator, "tscoll/usrchtst/TestBreakIterator");
2732    addTest(root, &TestVariable, "tscoll/usrchtst/TestVariable");
2733    addTest(root, &TestOverlap, "tscoll/usrchtst/TestOverlap");
2734    addTest(root, &TestCollator, "tscoll/usrchtst/TestCollator");
2735    addTest(root, &TestPattern, "tscoll/usrchtst/TestPattern");
2736    addTest(root, &TestText, "tscoll/usrchtst/TestText");
2737    addTest(root, &TestCompositeBoundaries,
2738                                  "tscoll/usrchtst/TestCompositeBoundaries");
2739    addTest(root, &TestGetSetOffset, "tscoll/usrchtst/TestGetSetOffset");
2740    addTest(root, &TestGetSetAttribute,
2741                                      "tscoll/usrchtst/TestGetSetAttribute");
2742    addTest(root, &TestGetMatch, "tscoll/usrchtst/TestGetMatch");
2743    addTest(root, &TestSetMatch, "tscoll/usrchtst/TestSetMatch");
2744    addTest(root, &TestReset, "tscoll/usrchtst/TestReset");
2745    addTest(root, &TestSupplementary, "tscoll/usrchtst/TestSupplementary");
2746    addTest(root, &TestContraction, "tscoll/usrchtst/TestContraction");
2747    addTest(root, &TestIgnorable, "tscoll/usrchtst/TestIgnorable");
2748    addTest(root, &TestCanonical, "tscoll/usrchtst/TestCanonical");
2749    addTest(root, &TestNormCanonical, "tscoll/usrchtst/TestNormCanonical");
2750    addTest(root, &TestStrengthCanonical,
2751                                    "tscoll/usrchtst/TestStrengthCanonical");
2752    addTest(root, &TestBreakIteratorCanonical,
2753                               "tscoll/usrchtst/TestBreakIteratorCanonical");
2754    addTest(root, &TestVariableCanonical,
2755                                    "tscoll/usrchtst/TestVariableCanonical");
2756    addTest(root, &TestOverlapCanonical,
2757                                     "tscoll/usrchtst/TestOverlapCanonical");
2758    addTest(root, &TestCollatorCanonical,
2759                                    "tscoll/usrchtst/TestCollatorCanonical");
2760    addTest(root, &TestPatternCanonical,
2761                                     "tscoll/usrchtst/TestPatternCanonical");
2762    addTest(root, &TestTextCanonical, "tscoll/usrchtst/TestTextCanonical");
2763    addTest(root, &TestCompositeBoundariesCanonical,
2764                         "tscoll/usrchtst/TestCompositeBoundariesCanonical");
2765    addTest(root, &TestGetSetOffsetCanonical,
2766                                "tscoll/usrchtst/TestGetSetOffsetCanonical");
2767    addTest(root, &TestSupplementaryCanonical,
2768                               "tscoll/usrchtst/TestSupplementaryCanonical");
2769    addTest(root, &TestContractionCanonical,
2770                                 "tscoll/usrchtst/TestContractionCanonical");
2771    addTest(root, &TestEnd, "tscoll/usrchtst/TestEnd");
2772    addTest(root, &TestNumeric, "tscoll/usrchtst/TestNumeric");
2773    addTest(root, &TestDiacriticMatch, "tscoll/usrchtst/TestDiacriticMatch");
2774    addTest(root, &TestForwardBackward, "tscoll/usrchtst/TestForwardBackward");
2775	addTest(root, &TestSearchForNull, "tscoll/usrchtst/TestSearchForNull");
2776    addTest(root, &TestStrengthIdentical, "tscoll/usrchtst/TestStrengthIdentical");
2777    addTest(root, &TestUsingSearchCollator, "tscoll/usrchtst/TestUsingSearchCollator");
2778}
2779
2780#endif /* #if !UCONFIG_NO_COLLATION */
2781