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