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