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