1/*
2*****************************************************************************
3* Copyright (C) 2001-2009, International Business Machines orporation
4* and others. All Rights Reserved.
5****************************************************************************/
6
7#include "unicode/utypes.h"
8
9#if !UCONFIG_NO_COLLATION
10
11#include "srchtest.h"
12#include "../cintltst/usrchdat.c"
13#include "unicode/stsearch.h"
14#include "unicode/ustring.h"
15#include "unicode/schriter.h"
16#include <string.h>
17#include <stdio.h>
18
19// private definitions -----------------------------------------------------
20
21#define CASE(id,test)                 \
22    case id:                          \
23        name = #test;                 \
24        if (exec) {                   \
25            logln(#test "---");       \
26            logln((UnicodeString)""); \
27            if(areBroken) {           \
28                  dataerrln(__FILE__ " cannot test - failed to create collator.");  \
29            } else {                  \
30                test();               \
31            }                         \
32        }                             \
33        break;
34
35// public contructors and destructors --------------------------------------
36
37StringSearchTest::StringSearchTest()
38#if !UCONFIG_NO_BREAK_ITERATION
39:
40    m_en_wordbreaker_(NULL), m_en_characterbreaker_(NULL)
41#endif
42{
43#if !UCONFIG_NO_BREAK_ITERATION
44    UErrorCode    status = U_ZERO_ERROR;
45
46    m_en_us_ = (RuleBasedCollator *)Collator::createInstance("en_US", status);
47    m_fr_fr_ = (RuleBasedCollator *)Collator::createInstance("fr_FR", status);
48    m_de_    = (RuleBasedCollator *)Collator::createInstance("de_DE", status);
49    m_es_    = (RuleBasedCollator *)Collator::createInstance("es_ES", status);
50    if(U_FAILURE(status)) {
51      delete m_en_us_;
52      delete m_fr_fr_;
53      delete m_de_;
54      delete m_es_;
55      m_en_us_ = 0;
56      m_fr_fr_ = 0;
57      m_de_ = 0;
58      m_es_ = 0;
59      errln("Collator creation failed with %s", u_errorName(status));
60      return;
61    }
62
63
64    UnicodeString rules;
65    rules.setTo(((RuleBasedCollator *)m_de_)->getRules());
66    UChar extrarules[128];
67    u_unescape(EXTRACOLLATIONRULE, extrarules, 128);
68    rules.append(extrarules, u_strlen(extrarules));
69    delete m_de_;
70
71    m_de_ = new RuleBasedCollator(rules, status);
72
73    rules.setTo(((RuleBasedCollator *)m_es_)->getRules());
74    rules.append(extrarules, u_strlen(extrarules));
75
76    delete m_es_;
77
78    m_es_ = new RuleBasedCollator(rules, status);
79
80#if !UCONFIG_NO_BREAK_ITERATION
81    m_en_wordbreaker_      = BreakIterator::createWordInstance(
82                                                    Locale::getEnglish(), status);
83    m_en_characterbreaker_ = BreakIterator::createCharacterInstance(
84                                                    Locale::getEnglish(), status);
85#endif
86#endif
87}
88
89StringSearchTest::~StringSearchTest()
90{
91#if !UCONFIG_NO_BREAK_ITERATION
92    delete m_en_us_;
93    delete m_fr_fr_;
94    delete m_de_;
95    delete m_es_;
96#if !UCONFIG_NO_BREAK_ITERATION
97    delete m_en_wordbreaker_;
98    delete m_en_characterbreaker_;
99#endif
100#endif
101}
102
103// public methods ----------------------------------------------------------
104
105void StringSearchTest::runIndexedTest(int32_t index, UBool exec,
106                                      const char* &name, char* )
107{
108#if !UCONFIG_NO_BREAK_ITERATION
109    UBool areBroken = FALSE;
110    if (m_en_us_ == NULL && m_fr_fr_ == NULL && m_de_ == NULL &&
111        m_es_ == NULL && m_en_wordbreaker_ == NULL &&
112        m_en_characterbreaker_ == NULL && exec) {
113        areBroken = TRUE;
114    }
115
116    switch (index) {
117        CASE(0, TestOpenClose)
118        CASE(1, TestInitialization)
119        CASE(2, TestBasic)
120        CASE(3, TestNormExact)
121        CASE(4, TestStrength)
122#if UCONFIG_NO_BREAK_ITERATION
123    case 5:
124        name = "TestBreakIterator";
125        break;
126#else
127        CASE(5, TestBreakIterator)
128#endif
129        CASE(6, TestVariable)
130        CASE(7, TestOverlap)
131        CASE(8, TestCollator)
132        CASE(9, TestPattern)
133        CASE(10, TestText)
134        CASE(11, TestCompositeBoundaries)
135        CASE(12, TestGetSetOffset)
136        CASE(13, TestGetSetAttribute)
137        CASE(14, TestGetMatch)
138        CASE(15, TestSetMatch)
139        CASE(16, TestReset)
140        CASE(17, TestSupplementary)
141        CASE(18, TestContraction)
142        CASE(19, TestIgnorable)
143        CASE(20, TestCanonical)
144        CASE(21, TestNormCanonical)
145        CASE(22, TestStrengthCanonical)
146#if UCONFIG_NO_BREAK_ITERATION
147    case 23:
148        name = "TestBreakIteratorCanonical";
149        break;
150#else
151        CASE(23, TestBreakIteratorCanonical)
152#endif
153        CASE(24, TestVariableCanonical)
154        CASE(25, TestOverlapCanonical)
155        CASE(26, TestCollatorCanonical)
156        CASE(27, TestPatternCanonical)
157        CASE(28, TestTextCanonical)
158        CASE(29, TestCompositeBoundariesCanonical)
159        CASE(30, TestGetSetOffsetCanonical)
160        CASE(31, TestSupplementaryCanonical)
161        CASE(32, TestContractionCanonical)
162        CASE(33, TestUClassID)
163        CASE(34, TestSubclass)
164        CASE(35, TestCoverage)
165        CASE(36, TestDiacriticMatch)
166        default: name = ""; break;
167    }
168#else
169    name="";
170#endif
171}
172
173#if !UCONFIG_NO_BREAK_ITERATION
174// private methods ------------------------------------------------------
175
176RuleBasedCollator * StringSearchTest::getCollator(const char *collator)
177{
178    if (collator == NULL) {
179        return m_en_us_;
180    }
181    if (strcmp(collator, "fr") == 0) {
182        return m_fr_fr_;
183    }
184    else if (strcmp(collator, "de") == 0) {
185        return m_de_;
186    }
187    else if (strcmp(collator, "es") == 0) {
188        return m_es_;
189    }
190    else {
191        return m_en_us_;
192    }
193}
194
195BreakIterator * StringSearchTest::getBreakIterator(const char *breaker)
196{
197#if UCONFIG_NO_BREAK_ITERATION
198    return NULL;
199#else
200    if (breaker == NULL) {
201        return NULL;
202    }
203    if (strcmp(breaker, "wordbreaker") == 0) {
204        return m_en_wordbreaker_;
205    }
206    else {
207        return m_en_characterbreaker_;
208    }
209#endif
210}
211
212char * StringSearchTest::toCharString(const UnicodeString &text)
213{
214    static char   result[1024];
215           int    index  = 0;
216           int    count  = 0;
217           int    length = text.length();
218
219    for (; count < length; count ++) {
220        UChar ch = text[count];
221        if (ch >= 0x20 && ch <= 0x7e) {
222            result[index ++] = (char)ch;
223        }
224        else {
225            sprintf(result+index, "\\u%04x", ch);
226            index += 6; /* \uxxxx */
227        }
228    }
229    result[index] = 0;
230
231    return result;
232}
233
234Collator::ECollationStrength StringSearchTest::getECollationStrength(
235                                    const UCollationStrength &strength) const
236{
237  switch (strength)
238  {
239  case UCOL_PRIMARY :
240    return Collator::PRIMARY;
241  case UCOL_SECONDARY :
242    return Collator::SECONDARY;
243  case UCOL_TERTIARY :
244    return Collator::TERTIARY;
245  default :
246    return Collator::IDENTICAL;
247  }
248}
249
250UBool StringSearchTest::assertEqualWithStringSearch(StringSearch *strsrch,
251                                                    const SearchData *search)
252{
253    int           count       = 0;
254    UErrorCode    status      = U_ZERO_ERROR;
255    int32_t   matchindex  = search->offset[count];
256    UnicodeString matchtext;
257
258    if (strsrch->getMatchedStart() != USEARCH_DONE ||
259        strsrch->getMatchedLength() != 0) {
260        errln("Error with the initialization of match start and length");
261    }
262    // start of following matches
263    while (U_SUCCESS(status) && matchindex >= 0) {
264        int32_t matchlength = search->size[count];
265        strsrch->next(status);
266        if (matchindex != strsrch->getMatchedStart() ||
267            matchlength != strsrch->getMatchedLength()) {
268            char *str = toCharString(strsrch->getText());
269            errln("Text: %s", str);
270            str = toCharString(strsrch->getPattern());
271            infoln("Pattern: %s", str);
272            infoln("Error following match found at %d %d",
273                    strsrch->getMatchedStart(), strsrch->getMatchedLength());
274            return FALSE;
275        }
276        count ++;
277
278        strsrch->getMatchedText(matchtext);
279
280        if (U_FAILURE(status) ||
281            strsrch->getText().compareBetween(matchindex,
282                                              matchindex + matchlength,
283                                              matchtext, 0,
284                                              matchtext.length())) {
285            errln("Error getting following matched text");
286        }
287
288        matchindex = search->offset[count];
289    }
290    strsrch->next(status);
291    if (strsrch->getMatchedStart() != USEARCH_DONE ||
292        strsrch->getMatchedLength() != 0) {
293        char *str = toCharString(strsrch->getText());
294            errln("Text: %s", str);
295            str = toCharString(strsrch->getPattern());
296            errln("Pattern: %s", str);
297            errln("Error following match found at %d %d",
298                    strsrch->getMatchedStart(), strsrch->getMatchedLength());
299            return FALSE;
300    }
301    // start of preceding matches
302    count = count == 0 ? 0 : count - 1;
303    matchindex = search->offset[count];
304    while (U_SUCCESS(status) && matchindex >= 0) {
305        int32_t matchlength = search->size[count];
306        strsrch->previous(status);
307        if (matchindex != strsrch->getMatchedStart() ||
308            matchlength != strsrch->getMatchedLength()) {
309            char *str = toCharString(strsrch->getText());
310            errln("Text: %s", str);
311            str = toCharString(strsrch->getPattern());
312            errln("Pattern: %s", str);
313            errln("Error following match found at %d %d",
314                    strsrch->getMatchedStart(), strsrch->getMatchedLength());
315            return FALSE;
316        }
317
318        strsrch->getMatchedText(matchtext);
319
320        if (U_FAILURE(status) ||
321            strsrch->getText().compareBetween(matchindex,
322                                              matchindex + matchlength,
323                                              matchtext, 0,
324                                              matchtext.length())) {
325            errln("Error getting following matched text");
326        }
327
328        matchindex = count > 0 ? search->offset[count - 1] : -1;
329        count --;
330    }
331    strsrch->previous(status);
332    if (strsrch->getMatchedStart() != USEARCH_DONE ||
333        strsrch->getMatchedLength() != 0) {
334        char *str = toCharString(strsrch->getText());
335            errln("Text: %s", str);
336            str = toCharString(strsrch->getPattern());
337            errln("Pattern: %s", str);
338            errln("Error following match found at %d %d",
339                    strsrch->getMatchedStart(), strsrch->getMatchedLength());
340            return FALSE;
341    }
342    return TRUE;
343}
344
345UBool StringSearchTest::assertEqual(const SearchData *search)
346{
347    UErrorCode     status   = U_ZERO_ERROR;
348
349    Collator      *collator = getCollator(search->collator);
350    BreakIterator *breaker  = getBreakIterator(search->breaker);
351    StringSearch  *strsrch, *strsrch2;
352    UChar          temp[128];
353
354#if UCONFIG_NO_BREAK_ITERATION
355    if(search->breaker) {
356      return TRUE; /* skip test */
357    }
358#endif
359    u_unescape(search->text, temp, 128);
360    UnicodeString text;
361    text.setTo(temp);
362    u_unescape(search->pattern, temp, 128);
363    UnicodeString  pattern;
364    pattern.setTo(temp);
365
366#if !UCONFIG_NO_BREAK_ITERATION
367    if (breaker != NULL) {
368        breaker->setText(text);
369    }
370#endif
371    collator->setStrength(getECollationStrength(search->strength));
372    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
373                               breaker, status);
374    if (U_FAILURE(status)) {
375        errln("Error opening string search %s", u_errorName(status));
376        return FALSE;
377    }
378
379    if (!assertEqualWithStringSearch(strsrch, search)) {
380        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
381        delete strsrch;
382        return FALSE;
383    }
384
385
386    strsrch2 = strsrch->clone();
387    if( strsrch2 == strsrch || *strsrch2 != *strsrch ||
388        !assertEqualWithStringSearch(strsrch2, search)
389    ) {
390        infoln("failure with StringSearch.clone()");
391        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
392        delete strsrch;
393        delete strsrch2;
394        return FALSE;
395    }
396    delete strsrch2;
397
398    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
399    delete strsrch;
400    return TRUE;
401}
402
403UBool StringSearchTest::assertCanonicalEqual(const SearchData *search)
404{
405    UErrorCode     status   = U_ZERO_ERROR;
406    Collator      *collator = getCollator(search->collator);
407    BreakIterator *breaker  = getBreakIterator(search->breaker);
408    StringSearch  *strsrch;
409    UChar          temp[128];
410    UBool          result = TRUE;
411
412#if UCONFIG_NO_BREAK_ITERATION
413    if(search->breaker) {
414      return TRUE; /* skip test */
415    }
416#endif
417
418    u_unescape(search->text, temp, 128);
419    UnicodeString text;
420    text.setTo(temp);
421    u_unescape(search->pattern, temp, 128);
422    UnicodeString  pattern;
423    pattern.setTo(temp);
424
425#if !UCONFIG_NO_BREAK_ITERATION
426    if (breaker != NULL) {
427        breaker->setText(text);
428    }
429#endif
430    collator->setStrength(getECollationStrength(search->strength));
431    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
432    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
433                               breaker, status);
434    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
435    if (U_FAILURE(status)) {
436        errln("Error opening string search %s", u_errorName(status));
437        result = FALSE;
438        goto bail;
439    }
440
441    if (!assertEqualWithStringSearch(strsrch, search)) {
442        result = FALSE;
443        goto bail;
444    }
445
446bail:
447    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
448    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
449    delete strsrch;
450
451    return result;
452}
453
454UBool StringSearchTest::assertEqualWithAttribute(const SearchData *search,
455                                            USearchAttributeValue canonical,
456                                            USearchAttributeValue overlap)
457{
458    UErrorCode     status   = U_ZERO_ERROR;
459    Collator      *collator = getCollator(search->collator);
460    BreakIterator *breaker  = getBreakIterator(search->breaker);
461    StringSearch  *strsrch;
462    UChar          temp[128];
463
464
465#if UCONFIG_NO_BREAK_ITERATION
466    if(search->breaker) {
467      return TRUE; /* skip test */
468    }
469#endif
470
471    u_unescape(search->text, temp, 128);
472    UnicodeString text;
473    text.setTo(temp);
474    u_unescape(search->pattern, temp, 128);
475    UnicodeString  pattern;
476    pattern.setTo(temp);
477
478#if !UCONFIG_NO_BREAK_ITERATION
479    if (breaker != NULL) {
480        breaker->setText(text);
481    }
482#endif
483    collator->setStrength(getECollationStrength(search->strength));
484    strsrch = new StringSearch(pattern, text, (RuleBasedCollator *)collator,
485                               breaker, status);
486    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, canonical, status);
487    strsrch->setAttribute(USEARCH_OVERLAP, overlap, status);
488
489    if (U_FAILURE(status)) {
490        errln("Error opening string search %s", u_errorName(status));
491        return FALSE;
492    }
493
494    if (!assertEqualWithStringSearch(strsrch, search)) {
495        collator->setStrength(getECollationStrength(UCOL_TERTIARY));
496        delete strsrch;
497        return FALSE;
498    }
499    collator->setStrength(getECollationStrength(UCOL_TERTIARY));
500    delete strsrch;
501    return TRUE;
502}
503
504void StringSearchTest::TestOpenClose()
505{
506    UErrorCode               status    = U_ZERO_ERROR;
507    StringSearch            *result;
508    BreakIterator           *breakiter = m_en_wordbreaker_;
509    UnicodeString            pattern;
510    UnicodeString            text;
511    UnicodeString            temp("a");
512    StringCharacterIterator  chariter(text);
513
514    /* testing null arguments */
515    result = new StringSearch(pattern, text, NULL, NULL, status);
516    if (U_SUCCESS(status)) {
517        errln("Error: NULL arguments should produce an error");
518    }
519    delete result;
520
521    chariter.setText(text);
522    status = U_ZERO_ERROR;
523    result = new StringSearch(pattern, chariter, NULL, NULL, status);
524    if (U_SUCCESS(status)) {
525        errln("Error: NULL arguments should produce an error");
526    }
527    delete result;
528
529    text.append(0, 0x1);
530    status = U_ZERO_ERROR;
531    result = new StringSearch(pattern, text, NULL, NULL, status);
532    if (U_SUCCESS(status)) {
533        errln("Error: Empty pattern should produce an error");
534    }
535    delete result;
536
537    chariter.setText(text);
538    status = U_ZERO_ERROR;
539    result = new StringSearch(pattern, chariter, NULL, NULL, status);
540    if (U_SUCCESS(status)) {
541        errln("Error: Empty pattern should produce an error");
542    }
543    delete result;
544
545    text.remove();
546    pattern.append(temp);
547    status = U_ZERO_ERROR;
548    result = new StringSearch(pattern, text, NULL, NULL, status);
549    if (U_SUCCESS(status)) {
550        errln("Error: Empty text should produce an error");
551    }
552    delete result;
553
554    chariter.setText(text);
555    status = U_ZERO_ERROR;
556    result = new StringSearch(pattern, chariter, NULL, NULL, status);
557    if (U_SUCCESS(status)) {
558        errln("Error: Empty text should produce an error");
559    }
560    delete result;
561
562    text.append(temp);
563    status = U_ZERO_ERROR;
564    result = new StringSearch(pattern, text, NULL, NULL, status);
565    if (U_SUCCESS(status)) {
566        errln("Error: NULL arguments should produce an error");
567    }
568    delete result;
569
570    chariter.setText(text);
571    status = U_ZERO_ERROR;
572    result = new StringSearch(pattern, chariter, NULL, NULL, status);
573    if (U_SUCCESS(status)) {
574        errln("Error: NULL arguments should produce an error");
575    }
576    delete result;
577
578    status = U_ZERO_ERROR;
579    result = new StringSearch(pattern, text, m_en_us_, NULL, status);
580    if (U_FAILURE(status)) {
581        errln("Error: NULL break iterator is valid for opening search");
582    }
583    delete result;
584
585    status = U_ZERO_ERROR;
586    result = new StringSearch(pattern, chariter, m_en_us_, NULL, status);
587    if (U_FAILURE(status)) {
588        errln("Error: NULL break iterator is valid for opening search");
589    }
590    delete result;
591
592    status = U_ZERO_ERROR;
593    result = new StringSearch(pattern, text, Locale::getEnglish(), NULL, status);
594    if (U_FAILURE(status) || result == NULL) {
595        errln("Error: NULL break iterator is valid for opening search");
596    }
597    delete result;
598
599    status = U_ZERO_ERROR;
600    result = new StringSearch(pattern, chariter, Locale::getEnglish(), NULL, status);
601    if (U_FAILURE(status)) {
602        errln("Error: NULL break iterator is valid for opening search");
603    }
604    delete result;
605
606    status = U_ZERO_ERROR;
607    result = new StringSearch(pattern, text, m_en_us_, breakiter, status);
608    if (U_FAILURE(status)) {
609        errln("Error: Break iterator is valid for opening search");
610    }
611    delete result;
612
613    status = U_ZERO_ERROR;
614    result = new StringSearch(pattern, chariter, m_en_us_, NULL, status);
615    if (U_FAILURE(status)) {
616        errln("Error: Break iterator is valid for opening search");
617    }
618    delete result;
619}
620
621void StringSearchTest::TestInitialization()
622{
623    UErrorCode     status = U_ZERO_ERROR;
624    UnicodeString  pattern;
625    UnicodeString  text;
626    UnicodeString  temp("a");
627    StringSearch  *result;
628    int count;
629
630    /* simple test on the pattern ce construction */
631    pattern.append(temp);
632    pattern.append(temp);
633    text.append(temp);
634    text.append(temp);
635    text.append(temp);
636    result = new StringSearch(pattern, text, m_en_us_, NULL, status);
637    if (U_FAILURE(status)) {
638        errln("Error opening search %s", u_errorName(status));
639    }
640    StringSearch *copy = new StringSearch(*result);
641    if (*(copy->getCollator()) != *(result->getCollator()) ||
642        copy->getBreakIterator() != result->getBreakIterator() ||
643        copy->getMatchedLength() != result->getMatchedLength() ||
644        copy->getMatchedStart() != result->getMatchedStart() ||
645        copy->getOffset() != result->getOffset() ||
646        copy->getPattern() != result->getPattern() ||
647        copy->getText() != result->getText() ||
648        *(copy) != *(result))
649    {
650        errln("Error copying StringSearch");
651    }
652    delete copy;
653
654    copy = (StringSearch *)result->safeClone();
655    if (*(copy->getCollator()) != *(result->getCollator()) ||
656        copy->getBreakIterator() != result->getBreakIterator() ||
657        copy->getMatchedLength() != result->getMatchedLength() ||
658        copy->getMatchedStart() != result->getMatchedStart() ||
659        copy->getOffset() != result->getOffset() ||
660        copy->getPattern() != result->getPattern() ||
661        copy->getText() != result->getText() ||
662        *(copy) != *(result)) {
663        errln("Error copying StringSearch");
664    }
665    delete result;
666
667    /* testing if an extremely large pattern will fail the initialization */
668    for (count = 0; count < 512; count ++) {
669        pattern.append(temp);
670    }
671    result = new StringSearch(pattern, text, m_en_us_, NULL, status);
672    if (*result != *result) {
673        errln("Error: string search object expected to match itself");
674    }
675    if (*result == *copy) {
676        errln("Error: string search objects are not expected to match");
677    }
678    *copy  = *result;
679    if (*(copy->getCollator()) != *(result->getCollator()) ||
680        copy->getBreakIterator() != result->getBreakIterator() ||
681        copy->getMatchedLength() != result->getMatchedLength() ||
682        copy->getMatchedStart() != result->getMatchedStart() ||
683        copy->getOffset() != result->getOffset() ||
684        copy->getPattern() != result->getPattern() ||
685        copy->getText() != result->getText() ||
686        *(copy) != *(result)) {
687        errln("Error copying StringSearch");
688    }
689    if (U_FAILURE(status)) {
690        errln("Error opening search %s", u_errorName(status));
691    }
692    delete result;
693    delete copy;
694}
695
696void StringSearchTest::TestBasic()
697{
698    int count = 0;
699    while (BASIC[count].text != NULL) {
700        //printf("count %d", count);
701        if (!assertEqual(&BASIC[count])) {
702            infoln("Error at test number %d", count);
703        }
704        count ++;
705    }
706}
707
708void StringSearchTest::TestNormExact()
709{
710    int count = 0;
711    UErrorCode status = U_ZERO_ERROR;
712    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
713    if (U_FAILURE(status)) {
714        errln("Error setting collation normalization %s",
715              u_errorName(status));
716    }
717    while (BASIC[count].text != NULL) {
718        if (!assertEqual(&BASIC[count])) {
719            infoln("Error at test number %d", count);
720        }
721        count ++;
722    }
723    count = 0;
724    while (NORMEXACT[count].text != NULL) {
725        if (!assertEqual(&NORMEXACT[count])) {
726            infoln("Error at test number %d", count);
727        }
728        count ++;
729    }
730    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
731    count = 0;
732    while (NONNORMEXACT[count].text != NULL) {
733        if (!assertEqual(&NONNORMEXACT[count])) {
734            infoln("Error at test number %d", count);
735        }
736        count ++;
737    }
738}
739
740void StringSearchTest::TestStrength()
741{
742    int count = 0;
743    while (STRENGTH[count].text != NULL) {
744        if (!assertEqual(&STRENGTH[count])) {
745            infoln("Error at test number %d", count);
746        }
747        count ++;
748    }
749}
750
751#if !UCONFIG_NO_BREAK_ITERATION
752
753void StringSearchTest::TestBreakIterator()
754{
755    UChar temp[128];
756    u_unescape(BREAKITERATOREXACT[0].text, temp, 128);
757    UnicodeString text;
758    text.setTo(temp, u_strlen(temp));
759    u_unescape(BREAKITERATOREXACT[0].pattern, temp, 128);
760    UnicodeString pattern;
761    pattern.setTo(temp, u_strlen(temp));
762
763    UErrorCode status = U_ZERO_ERROR;
764    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
765                                             status);
766    if (U_FAILURE(status)) {
767        errln("Error opening string search %s", u_errorName(status));
768    }
769
770    strsrch->setBreakIterator(NULL, status);
771    if (U_FAILURE(status) || strsrch->getBreakIterator() != NULL) {
772        errln("Error usearch_getBreakIterator returned wrong object");
773    }
774
775    strsrch->setBreakIterator(m_en_characterbreaker_, status);
776    if (U_FAILURE(status) ||
777        strsrch->getBreakIterator() != m_en_characterbreaker_) {
778        errln("Error usearch_getBreakIterator returned wrong object");
779    }
780
781    strsrch->setBreakIterator(m_en_wordbreaker_, status);
782    if (U_FAILURE(status) ||
783        strsrch->getBreakIterator() != m_en_wordbreaker_) {
784        errln("Error usearch_getBreakIterator returned wrong object");
785    }
786
787    delete strsrch;
788
789    int count = 0;
790    while (count < 4) {
791        // special purposes for tests numbers 0-3
792        const SearchData        *search   = &(BREAKITERATOREXACT[count]);
793              RuleBasedCollator *collator = getCollator(search->collator);
794              BreakIterator     *breaker  = getBreakIterator(search->breaker);
795              StringSearch      *strsrch;
796
797        u_unescape(search->text, temp, 128);
798        text.setTo(temp, u_strlen(temp));
799        u_unescape(search->pattern, temp, 128);
800        pattern.setTo(temp, u_strlen(temp));
801        if (breaker != NULL) {
802            breaker->setText(text);
803        }
804        collator->setStrength(getECollationStrength(search->strength));
805
806        strsrch = new StringSearch(pattern, text, collator, breaker, status);
807        if (U_FAILURE(status) ||
808            strsrch->getBreakIterator() != breaker) {
809            errln("Error setting break iterator");
810            if (strsrch != NULL) {
811                delete strsrch;
812            }
813        }
814        if (!assertEqualWithStringSearch(strsrch, search)) {
815            collator->setStrength(getECollationStrength(UCOL_TERTIARY));
816            delete strsrch;
817        }
818        search   = &(BREAKITERATOREXACT[count + 1]);
819        breaker  = getBreakIterator(search->breaker);
820        if (breaker != NULL) {
821            breaker->setText(text);
822        }
823        strsrch->setBreakIterator(breaker, status);
824        if (U_FAILURE(status) ||
825            strsrch->getBreakIterator() != breaker) {
826            errln("Error setting break iterator");
827            delete strsrch;
828        }
829        strsrch->reset();
830        if (!assertEqualWithStringSearch(strsrch, search)) {
831             infoln("Error at test number %d", count);
832        }
833        delete strsrch;
834        count += 2;
835    }
836    count = 0;
837    while (BREAKITERATOREXACT[count].text != NULL) {
838         if (!assertEqual(&BREAKITERATOREXACT[count])) {
839             infoln("Error at test number %d", count);
840         }
841         count ++;
842    }
843}
844
845#endif
846
847void StringSearchTest::TestVariable()
848{
849    int count = 0;
850    UErrorCode status = U_ZERO_ERROR;
851    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
852    if (U_FAILURE(status)) {
853        errln("Error setting collation alternate attribute %s",
854              u_errorName(status));
855    }
856    while (VARIABLE[count].text != NULL) {
857        logln("variable %d", count);
858        if (!assertEqual(&VARIABLE[count])) {
859            infoln("Error at test number %d", count);
860        }
861        count ++;
862    }
863    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
864                           status);
865}
866
867void StringSearchTest::TestOverlap()
868{
869    int count = 0;
870    while (OVERLAP[count].text != NULL) {
871        if (!assertEqualWithAttribute(&OVERLAP[count], USEARCH_OFF,
872                                      USEARCH_ON)) {
873            errln("Error at overlap test number %d", count);
874        }
875        count ++;
876    }
877    count = 0;
878    while (NONOVERLAP[count].text != NULL) {
879        if (!assertEqual(&NONOVERLAP[count])) {
880            errln("Error at non overlap test number %d", count);
881        }
882        count ++;
883    }
884
885    count = 0;
886    while (count < 1) {
887        const SearchData *search = &(OVERLAP[count]);
888              UChar       temp[128];
889        u_unescape(search->text, temp, 128);
890        UnicodeString text;
891        text.setTo(temp, u_strlen(temp));
892        u_unescape(search->pattern, temp, 128);
893        UnicodeString pattern;
894        pattern.setTo(temp, u_strlen(temp));
895
896        RuleBasedCollator *collator = getCollator(search->collator);
897        UErrorCode         status   = U_ZERO_ERROR;
898        StringSearch      *strsrch  = new StringSearch(pattern, text,
899                                                       collator, NULL,
900                                                       status);
901
902        strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
903        if (U_FAILURE(status) ||
904            strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
905            errln("Error setting overlap option");
906        }
907        if (!assertEqualWithStringSearch(strsrch, search)) {
908            delete strsrch;
909            return;
910        }
911
912        search = &(NONOVERLAP[count]);
913        strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
914        if (U_FAILURE(status) ||
915            strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
916            errln("Error setting overlap option");
917        }
918        strsrch->reset();
919        if (!assertEqualWithStringSearch(strsrch, search)) {
920            delete strsrch;
921            errln("Error at test number %d", count);
922         }
923
924        count ++;
925        delete strsrch;
926    }
927}
928
929void StringSearchTest::TestCollator()
930{
931    // test collator that thinks "o" and "p" are the same thing
932    UChar         temp[128];
933    u_unescape(COLLATOR[0].text, temp, 128);
934    UnicodeString text;
935    text.setTo(temp, u_strlen(temp));
936    u_unescape(COLLATOR[0].pattern, temp, 128);
937    UnicodeString pattern;
938    pattern.setTo(temp, u_strlen(temp));
939
940    UErrorCode    status = U_ZERO_ERROR;
941    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
942                                             status);
943    if (U_FAILURE(status)) {
944        errln("Error opening string search %s", u_errorName(status));
945        delete strsrch;
946        return;
947    }
948    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
949        delete strsrch;
950        return;
951    }
952
953    u_unescape(TESTCOLLATORRULE, temp, 128);
954    UnicodeString rules;
955    rules.setTo(temp, u_strlen(temp));
956    RuleBasedCollator *tailored = new RuleBasedCollator(rules, status);
957    tailored->setStrength(getECollationStrength(COLLATOR[1].strength));
958
959    if (U_FAILURE(status)) {
960        errln("Error opening rule based collator %s", u_errorName(status));
961        delete strsrch;
962        if (tailored != NULL) {
963            delete tailored;
964        }
965        return;
966    }
967
968    strsrch->setCollator(tailored, status);
969    if (U_FAILURE(status) || (*strsrch->getCollator()) != (*tailored)) {
970        errln("Error setting rule based collator");
971        delete strsrch;
972        if (tailored != NULL) {
973            delete tailored;
974        }
975    }
976    strsrch->reset();
977    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[1])) {
978        delete strsrch;
979        if (tailored != NULL) {
980            delete tailored;
981        }
982        return;
983    }
984
985    strsrch->setCollator(m_en_us_, status);
986    strsrch->reset();
987    if (U_FAILURE(status) || (*strsrch->getCollator()) != (*m_en_us_)) {
988        errln("Error setting rule based collator");
989        delete strsrch;
990        if (tailored != NULL) {
991            delete tailored;
992        }
993    }
994    if (!assertEqualWithStringSearch(strsrch, &COLLATOR[0])) {
995       errln("Error searching collator test");
996    }
997    delete strsrch;
998    if (tailored != NULL) {
999        delete tailored;
1000    }
1001}
1002
1003void StringSearchTest::TestPattern()
1004{
1005
1006    UChar temp[512];
1007    int templength;
1008    u_unescape(PATTERN[0].text, temp, 512);
1009    UnicodeString text;
1010    text.setTo(temp, u_strlen(temp));
1011    u_unescape(PATTERN[0].pattern, temp, 512);
1012    UnicodeString pattern;
1013    pattern.setTo(temp, u_strlen(temp));
1014
1015    m_en_us_->setStrength(getECollationStrength(PATTERN[0].strength));
1016    UErrorCode    status = U_ZERO_ERROR;
1017    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1018                                             status);
1019
1020    if (U_FAILURE(status)) {
1021        errln("Error opening string search %s", u_errorName(status));
1022        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1023        if (strsrch != NULL) {
1024            delete strsrch;
1025        }
1026        return;
1027    }
1028    if (strsrch->getPattern() != pattern) {
1029        errln("Error setting pattern");
1030    }
1031    if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1032        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1033        if (strsrch != NULL) {
1034            delete strsrch;
1035        }
1036        return;
1037    }
1038
1039    u_unescape(PATTERN[1].pattern, temp, 512);
1040    pattern.setTo(temp, u_strlen(temp));
1041    strsrch->setPattern(pattern, status);
1042    if (pattern != strsrch->getPattern()) {
1043        errln("Error setting pattern");
1044        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1045        if (strsrch != NULL) {
1046            delete strsrch;
1047        }
1048        return;
1049    }
1050    strsrch->reset();
1051    if (U_FAILURE(status)) {
1052        errln("Error setting pattern %s", u_errorName(status));
1053    }
1054    if (!assertEqualWithStringSearch(strsrch, &PATTERN[1])) {
1055        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1056        if (strsrch != NULL) {
1057            delete strsrch;
1058        }
1059        return;
1060    }
1061
1062    u_unescape(PATTERN[0].pattern, temp, 512);
1063    pattern.setTo(temp, u_strlen(temp));
1064    strsrch->setPattern(pattern, status);
1065    if (pattern != strsrch->getPattern()) {
1066        errln("Error setting pattern");
1067        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1068        if (strsrch != NULL) {
1069            delete strsrch;
1070        }
1071        return;
1072    }
1073    strsrch->reset();
1074    if (U_FAILURE(status)) {
1075        errln("Error setting pattern %s", u_errorName(status));
1076    }
1077    if (!assertEqualWithStringSearch(strsrch, &PATTERN[0])) {
1078        m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1079        if (strsrch != NULL) {
1080            delete strsrch;
1081        }
1082        return;
1083    }
1084    /* enormous pattern size to see if this crashes */
1085    for (templength = 0; templength != 512; templength ++) {
1086        temp[templength] = 0x61;
1087    }
1088    temp[511] = 0;
1089    pattern.setTo(temp, 511);
1090    strsrch->setPattern(pattern, status);
1091    if (U_FAILURE(status)) {
1092        errln("Error setting pattern with size 512, %s", u_errorName(status));
1093    }
1094    m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1095    if (strsrch != NULL) {
1096        delete strsrch;
1097    }
1098}
1099
1100void StringSearchTest::TestText()
1101{
1102    UChar temp[128];
1103    u_unescape(TEXT[0].text, temp, 128);
1104    UnicodeString text;
1105    text.setTo(temp, u_strlen(temp));
1106    u_unescape(TEXT[0].pattern, temp, 128);
1107    UnicodeString pattern;
1108    pattern.setTo(temp, u_strlen(temp));
1109
1110    UErrorCode status = U_ZERO_ERROR;
1111    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1112                                             status);
1113    if (U_FAILURE(status)) {
1114        errln("Error opening string search %s", u_errorName(status));
1115        return;
1116    }
1117    if (text != strsrch->getText()) {
1118        errln("Error setting text");
1119    }
1120    if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1121        delete strsrch;
1122        return;
1123    }
1124
1125    u_unescape(TEXT[1].text, temp, 128);
1126    text.setTo(temp, u_strlen(temp));
1127    strsrch->setText(text, status);
1128    if (text != strsrch->getText()) {
1129        errln("Error setting text");
1130        delete strsrch;
1131        return;
1132    }
1133    if (U_FAILURE(status)) {
1134        errln("Error setting text %s", u_errorName(status));
1135    }
1136    if (!assertEqualWithStringSearch(strsrch, &TEXT[1])) {
1137        delete strsrch;
1138        return;
1139    }
1140
1141    u_unescape(TEXT[0].text, temp, 128);
1142    text.setTo(temp, u_strlen(temp));
1143    StringCharacterIterator chariter(text);
1144    strsrch->setText(chariter, status);
1145    if (text != strsrch->getText()) {
1146        errln("Error setting text");
1147        delete strsrch;
1148        return;
1149    }
1150    if (U_FAILURE(status)) {
1151        errln("Error setting pattern %s", u_errorName(status));
1152    }
1153    if (!assertEqualWithStringSearch(strsrch, &TEXT[0])) {
1154        errln("Error searching within set text");
1155    }
1156    delete strsrch;
1157}
1158
1159void StringSearchTest::TestCompositeBoundaries()
1160{
1161    int count = 0;
1162    while (COMPOSITEBOUNDARIES[count].text != NULL) {
1163        logln("composite %d", count);
1164        if (!assertEqual(&COMPOSITEBOUNDARIES[count])) {
1165            errln("Error at test number %d", count);
1166        }
1167        count ++;
1168    }
1169}
1170
1171void StringSearchTest::TestGetSetOffset()
1172{
1173    UErrorCode     status  = U_ZERO_ERROR;
1174    UnicodeString  pattern("1234567890123456");
1175    UnicodeString  text("12345678901234567890123456789012");
1176    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_,
1177                                              NULL, status);
1178    /* testing out of bounds error */
1179    strsrch->setOffset(-1, status);
1180    if (U_SUCCESS(status)) {
1181        errln("Error expecting set offset error");
1182    }
1183    strsrch->setOffset(128, status);
1184    if (U_SUCCESS(status)) {
1185        errln("Error expecting set offset error");
1186    }
1187    int index   = 0;
1188    while (BASIC[index].text != NULL) {
1189        UErrorCode  status      = U_ZERO_ERROR;
1190        SearchData  search      = BASIC[index ++];
1191        UChar       temp[128];
1192
1193        u_unescape(search.text, temp, 128);
1194        text.setTo(temp, u_strlen(temp));
1195        u_unescape(search.pattern, temp, 128);
1196        pattern.setTo(temp, u_strlen(temp));
1197        strsrch->setText(text, status);
1198        strsrch->setPattern(pattern, status);
1199        strsrch->getCollator()->setStrength(getECollationStrength(
1200                                                          search.strength));
1201        strsrch->reset();
1202
1203        int count = 0;
1204        int32_t matchindex  = search.offset[count];
1205        while (U_SUCCESS(status) && matchindex >= 0) {
1206            int32_t matchlength = search.size[count];
1207            strsrch->next(status);
1208            if (matchindex != strsrch->getMatchedStart() ||
1209                matchlength != strsrch->getMatchedLength()) {
1210                char *str = toCharString(strsrch->getText());
1211                errln("Text: %s", str);
1212                str = toCharString(strsrch->getPattern());
1213                errln("Pattern: %s", str);
1214                errln("Error match found at %d %d",
1215                        strsrch->getMatchedStart(),
1216                        strsrch->getMatchedLength());
1217                return;
1218            }
1219            matchindex = search.offset[count + 1] == -1 ? -1 :
1220                         search.offset[count + 2];
1221            if (search.offset[count + 1] != -1) {
1222                strsrch->setOffset(search.offset[count + 1] + 1, status);
1223                if (strsrch->getOffset() != search.offset[count + 1] + 1) {
1224                    errln("Error setting offset\n");
1225                    return;
1226                }
1227            }
1228
1229            count += 2;
1230        }
1231        strsrch->next(status);
1232        if (strsrch->getMatchedStart() != USEARCH_DONE) {
1233            char *str = toCharString(strsrch->getText());
1234            errln("Text: %s", str);
1235            str = toCharString(strsrch->getPattern());
1236            errln("Pattern: %s", str);
1237            errln("Error match found at %d %d",
1238                        strsrch->getMatchedStart(),
1239                        strsrch->getMatchedLength());
1240            return;
1241        }
1242    }
1243    strsrch->getCollator()->setStrength(getECollationStrength(
1244                                                             UCOL_TERTIARY));
1245    delete strsrch;
1246}
1247
1248void StringSearchTest::TestGetSetAttribute()
1249{
1250    UErrorCode     status    = U_ZERO_ERROR;
1251    UnicodeString  pattern("pattern");
1252    UnicodeString  text("text");
1253    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1254                                              status);
1255    if (U_FAILURE(status)) {
1256        errln("Error opening search %s", u_errorName(status));
1257        return;
1258    }
1259
1260    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_DEFAULT, status);
1261    if (U_FAILURE(status) ||
1262        strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1263        errln("Error setting overlap to the default");
1264    }
1265    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1266    if (U_FAILURE(status) ||
1267        strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
1268        errln("Error setting overlap true");
1269    }
1270    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
1271    if (U_FAILURE(status) ||
1272        strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1273        errln("Error setting overlap false");
1274    }
1275    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ATTRIBUTE_VALUE_COUNT,
1276                          status);
1277    if (U_SUCCESS(status)) {
1278        errln("Error setting overlap to illegal value");
1279    }
1280    status = U_ZERO_ERROR;
1281    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT, status);
1282    if (U_FAILURE(status) ||
1283        strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF) {
1284        errln("Error setting canonical match to the default");
1285    }
1286    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1287    if (U_FAILURE(status) ||
1288        strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_ON) {
1289        errln("Error setting canonical match true");
1290    }
1291    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_OFF, status);
1292    if (U_FAILURE(status) ||
1293        strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF) {
1294        errln("Error setting canonical match false");
1295    }
1296    strsrch->setAttribute(USEARCH_CANONICAL_MATCH,
1297                          USEARCH_ATTRIBUTE_VALUE_COUNT, status);
1298    if (U_SUCCESS(status)) {
1299        errln("Error setting canonical match to illegal value");
1300    }
1301    status = U_ZERO_ERROR;
1302    strsrch->setAttribute(USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT, status);
1303    if (U_SUCCESS(status)) {
1304        errln("Error setting illegal attribute success");
1305    }
1306
1307    delete strsrch;
1308}
1309
1310void StringSearchTest::TestGetMatch()
1311{
1312    UChar      temp[128];
1313    SearchData search = MATCH[0];
1314    u_unescape(search.text, temp, 128);
1315    UnicodeString text;
1316    text.setTo(temp, u_strlen(temp));
1317    u_unescape(search.pattern, temp, 128);
1318    UnicodeString pattern;
1319    pattern.setTo(temp, u_strlen(temp));
1320
1321    UErrorCode    status  = U_ZERO_ERROR;
1322    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1323                                             status);
1324    if (U_FAILURE(status)) {
1325        errln("Error opening string search %s", u_errorName(status));
1326        if (strsrch != NULL) {
1327            delete strsrch;
1328        }
1329        return;
1330    }
1331
1332    int           count      = 0;
1333    int32_t   matchindex = search.offset[count];
1334    UnicodeString matchtext;
1335    while (U_SUCCESS(status) && matchindex >= 0) {
1336        int32_t matchlength = search.size[count];
1337        strsrch->next(status);
1338        if (matchindex != strsrch->getMatchedStart() ||
1339            matchlength != strsrch->getMatchedLength()) {
1340            char *str = toCharString(strsrch->getText());
1341            errln("Text: %s", str);
1342            str = toCharString(strsrch->getPattern());
1343            errln("Pattern: %s", str);
1344            errln("Error match found at %d %d", strsrch->getMatchedStart(),
1345                  strsrch->getMatchedLength());
1346            return;
1347        }
1348        count ++;
1349
1350        status = U_ZERO_ERROR;
1351        strsrch->getMatchedText(matchtext);
1352        if (matchtext.length() != matchlength || U_FAILURE(status)){
1353            errln("Error getting match text");
1354        }
1355        matchindex = search.offset[count];
1356    }
1357    status = U_ZERO_ERROR;
1358    strsrch->next(status);
1359    if (strsrch->getMatchedStart()  != USEARCH_DONE ||
1360        strsrch->getMatchedLength() != 0) {
1361        errln("Error end of match not found");
1362    }
1363    status = U_ZERO_ERROR;
1364    strsrch->getMatchedText(matchtext);
1365    if (matchtext.length() != 0) {
1366        errln("Error getting null matches");
1367    }
1368    delete strsrch;
1369}
1370
1371void StringSearchTest::TestSetMatch()
1372{
1373    int count = 0;
1374    while (MATCH[count].text != NULL) {
1375        SearchData     search = MATCH[count];
1376        UChar          temp[128];
1377        UErrorCode status = U_ZERO_ERROR;
1378        u_unescape(search.text, temp, 128);
1379        UnicodeString text;
1380        text.setTo(temp, u_strlen(temp));
1381        u_unescape(search.pattern, temp, 128);
1382        UnicodeString pattern;
1383        pattern.setTo(temp, u_strlen(temp));
1384
1385        StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1386                                                 NULL, status);
1387        if (U_FAILURE(status)) {
1388            errln("Error opening string search %s", u_errorName(status));
1389            if (strsrch != NULL) {
1390                delete strsrch;
1391            }
1392            return;
1393        }
1394
1395        int size = 0;
1396        while (search.offset[size] != -1) {
1397            size ++;
1398        }
1399
1400        if (strsrch->first(status) != search.offset[0] || U_FAILURE(status)) {
1401            errln("Error getting first match");
1402        }
1403        if (strsrch->last(status) != search.offset[size -1] ||
1404            U_FAILURE(status)) {
1405            errln("Error getting last match");
1406        }
1407
1408        int index = 0;
1409        while (index < size) {
1410            if (index + 2 < size) {
1411                if (strsrch->following(search.offset[index + 2] - 1, status)
1412                         != search.offset[index + 2] || U_FAILURE(status)) {
1413                    errln("Error getting following match at index %d",
1414                          search.offset[index + 2] - 1);
1415                }
1416            }
1417            if (index + 1 < size) {
1418                if (strsrch->preceding(search.offset[index + 1] +
1419                                                search.size[index + 1] + 1,
1420                                       status) != search.offset[index + 1] ||
1421                    U_FAILURE(status)) {
1422                    errln("Error getting preceeding match at index %d",
1423                          search.offset[index + 1] + 1);
1424                }
1425            }
1426            index += 2;
1427        }
1428        status = U_ZERO_ERROR;
1429        if (strsrch->following(text.length(), status) != USEARCH_DONE) {
1430            errln("Error expecting out of bounds match");
1431        }
1432        if (strsrch->preceding(0, status) != USEARCH_DONE) {
1433            errln("Error expecting out of bounds match");
1434        }
1435        count ++;
1436        delete strsrch;
1437    }
1438}
1439
1440void StringSearchTest::TestReset()
1441{
1442    UErrorCode     status  = U_ZERO_ERROR;
1443    UnicodeString  text("fish fish");
1444    UnicodeString  pattern("s");
1445    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1446                                              status);
1447    if (U_FAILURE(status)) {
1448        errln("Error opening string search %s", u_errorName(status));
1449        if (strsrch != NULL) {
1450            delete strsrch;
1451        }
1452        return;
1453    }
1454    strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1455    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1456    strsrch->setOffset(9, status);
1457    if (U_FAILURE(status)) {
1458        errln("Error setting attributes and offsets");
1459    }
1460    else {
1461        strsrch->reset();
1462        if (strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF ||
1463            strsrch->getAttribute(USEARCH_CANONICAL_MATCH) != USEARCH_OFF ||
1464            strsrch->getOffset() != 0 || strsrch->getMatchedLength() != 0 ||
1465            strsrch->getMatchedStart() != USEARCH_DONE) {
1466            errln("Error resetting string search");
1467        }
1468        strsrch->previous(status);
1469        if (strsrch->getMatchedStart() != 7 ||
1470            strsrch->getMatchedLength() != 1) {
1471            errln("Error resetting string search\n");
1472        }
1473    }
1474    delete strsrch;
1475}
1476
1477void StringSearchTest::TestSupplementary()
1478{
1479    int count = 0;
1480    while (SUPPLEMENTARY[count].text != NULL) {
1481        if (!assertEqual(&SUPPLEMENTARY[count])) {
1482            errln("Error at test number %d", count);
1483        }
1484        count ++;
1485    }
1486}
1487
1488void StringSearchTest::TestContraction()
1489{
1490    UChar      temp[128];
1491    UErrorCode status = U_ZERO_ERROR;
1492
1493    u_unescape(CONTRACTIONRULE, temp, 128);
1494    UnicodeString rules;
1495    rules.setTo(temp, u_strlen(temp));
1496    RuleBasedCollator *collator = new RuleBasedCollator(rules,
1497        getECollationStrength(UCOL_TERTIARY), UCOL_ON, status);
1498    if (U_FAILURE(status)) {
1499        errln("Error opening collator %s", u_errorName(status));
1500    }
1501    UnicodeString text("text");
1502    UnicodeString pattern("pattern");
1503    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1504                                             status);
1505    if (U_FAILURE(status)) {
1506        errln("Error opening string search %s", u_errorName(status));
1507    }
1508
1509    int count = 0;
1510    while (CONTRACTION[count].text != NULL) {
1511        u_unescape(CONTRACTION[count].text, temp, 128);
1512        text.setTo(temp, u_strlen(temp));
1513        u_unescape(CONTRACTION[count].pattern, temp, 128);
1514        pattern.setTo(temp, u_strlen(temp));
1515        strsrch->setText(text, status);
1516        strsrch->setPattern(pattern, status);
1517        if (!assertEqualWithStringSearch(strsrch, &CONTRACTION[count])) {
1518            errln("Error at test number %d", count);
1519        }
1520        count ++;
1521    }
1522    delete strsrch;
1523    delete collator;
1524}
1525
1526void StringSearchTest::TestIgnorable()
1527{
1528    UChar temp[128];
1529    u_unescape(IGNORABLERULE, temp, 128);
1530    UnicodeString rules;
1531    rules.setTo(temp, u_strlen(temp));
1532    UErrorCode status = U_ZERO_ERROR;
1533    int        count  = 0;
1534    RuleBasedCollator *collator = new RuleBasedCollator(rules,
1535                            getECollationStrength(IGNORABLE[count].strength),
1536                            UCOL_ON, status);
1537    if (U_FAILURE(status)) {
1538        errln("Error opening collator %s", u_errorName(status));
1539        return;
1540    }
1541    UnicodeString pattern("pattern");
1542    UnicodeString text("text");
1543    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
1544                                             status);
1545    if (U_FAILURE(status)) {
1546        errln("Error opening string search %s", u_errorName(status));
1547        delete collator;
1548        return;
1549    }
1550
1551    while (IGNORABLE[count].text != NULL) {
1552        u_unescape(IGNORABLE[count].text, temp, 128);
1553        text.setTo(temp, u_strlen(temp));
1554        u_unescape(IGNORABLE[count].pattern, temp, 128);
1555        pattern.setTo(temp, u_strlen(temp));
1556        strsrch->setText(text, status);
1557        strsrch->setPattern(pattern, status);
1558        if (!assertEqualWithStringSearch(strsrch, &IGNORABLE[count])) {
1559            errln("Error at test number %d", count);
1560        }
1561        count ++;
1562    }
1563    delete strsrch;
1564    delete collator;
1565}
1566
1567void StringSearchTest::TestDiacriticMatch()
1568{
1569	UChar temp[128];
1570    UErrorCode status = U_ZERO_ERROR;
1571    int        count  = 0;
1572    RuleBasedCollator* coll = NULL;
1573    StringSearch *strsrch = NULL;
1574
1575    UnicodeString pattern("pattern");
1576    UnicodeString text("text");
1577
1578    const SearchData *search;
1579
1580    search = &(DIACRITICMATCH[count]);
1581    while (search->text != NULL) {
1582   		coll = getCollator(search->collator);
1583    	coll->setStrength(getECollationStrength(search->strength));
1584    	strsrch = new StringSearch(pattern, text, coll, getBreakIterator(search->breaker), status);
1585    	if (U_FAILURE(status)) {
1586	        errln("Error opening string search %s", u_errorName(status));
1587	        return;
1588	    }
1589        u_unescape(search->text, temp, 128);
1590        text.setTo(temp, u_strlen(temp));
1591        u_unescape(search->pattern, temp, 128);
1592        pattern.setTo(temp, u_strlen(temp));
1593        strsrch->setText(text, status);
1594        strsrch->setPattern(pattern, status);
1595        if (!assertEqualWithStringSearch(strsrch, search)) {
1596            errln("Error at test number %d", count);
1597        }
1598        search = &(DIACRITICMATCH[++count]);
1599        delete strsrch;
1600    }
1601
1602}
1603
1604void StringSearchTest::TestCanonical()
1605{
1606    int count = 0;
1607    while (BASICCANONICAL[count].text != NULL) {
1608        if (!assertCanonicalEqual(&BASICCANONICAL[count])) {
1609            errln("Error at test number %d", count);
1610        }
1611        count ++;
1612    }
1613}
1614
1615void StringSearchTest::TestNormCanonical()
1616{
1617    UErrorCode status = U_ZERO_ERROR;
1618    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
1619    int count = 0;
1620    while (NORMCANONICAL[count].text != NULL) {
1621        if (!assertCanonicalEqual(&NORMCANONICAL[count])) {
1622            errln("Error at test number %d", count);
1623        }
1624        count ++;
1625    }
1626    m_en_us_->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
1627}
1628
1629void StringSearchTest::TestStrengthCanonical()
1630{
1631    int count = 0;
1632    while (STRENGTHCANONICAL[count].text != NULL) {
1633        if (!assertCanonicalEqual(&STRENGTHCANONICAL[count])) {
1634            errln("Error at test number %d", count);
1635        }
1636        count ++;
1637    }
1638}
1639
1640#if !UCONFIG_NO_BREAK_ITERATION
1641
1642void StringSearchTest::TestBreakIteratorCanonical()
1643{
1644    UErrorCode status = U_ZERO_ERROR;
1645    int        count  = 0;
1646
1647    while (count < 4) {
1648        // special purposes for tests numbers 0-3
1649              UChar           temp[128];
1650        const SearchData     *search   = &(BREAKITERATORCANONICAL[count]);
1651
1652        u_unescape(search->text, temp, 128);
1653        UnicodeString text;
1654        text.setTo(temp, u_strlen(temp));
1655        u_unescape(search->pattern, temp, 128);
1656        UnicodeString pattern;
1657        pattern.setTo(temp, u_strlen(temp));
1658        RuleBasedCollator *collator = getCollator(search->collator);
1659        collator->setStrength(getECollationStrength(search->strength));
1660
1661        BreakIterator *breaker = getBreakIterator(search->breaker);
1662        StringSearch  *strsrch = new StringSearch(pattern, text, collator,
1663                                                  breaker, status);
1664        if (U_FAILURE(status)) {
1665            errln("Error creating string search data");
1666            return;
1667        }
1668        strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1669        if (U_FAILURE(status) ||
1670            strsrch->getBreakIterator() != breaker) {
1671            errln("Error setting break iterator");
1672            delete strsrch;
1673            return;
1674        }
1675        if (!assertEqualWithStringSearch(strsrch, search)) {
1676            collator->setStrength(getECollationStrength(UCOL_TERTIARY));
1677            delete strsrch;
1678            return;
1679        }
1680        search  = &(BREAKITERATOREXACT[count + 1]);
1681        breaker = getBreakIterator(search->breaker);
1682        if (breaker == NULL) {
1683            errln("Error creating BreakIterator");
1684            return;
1685        }
1686        breaker->setText(strsrch->getText());
1687        strsrch->setBreakIterator(breaker, status);
1688        if (U_FAILURE(status) || strsrch->getBreakIterator() != breaker) {
1689            errln("Error setting break iterator");
1690            delete strsrch;
1691            return;
1692        }
1693        strsrch->reset();
1694        strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1695        if (!assertEqualWithStringSearch(strsrch, search)) {
1696             errln("Error at test number %d", count);
1697             return;
1698        }
1699        delete strsrch;
1700        count += 2;
1701    }
1702    count = 0;
1703    while (BREAKITERATORCANONICAL[count].text != NULL) {
1704         if (!assertEqual(&BREAKITERATORCANONICAL[count])) {
1705             errln("Error at test number %d", count);
1706             return;
1707         }
1708         count ++;
1709    }
1710}
1711
1712#endif
1713
1714void StringSearchTest::TestVariableCanonical()
1715{
1716    int count = 0;
1717    UErrorCode status = U_ZERO_ERROR;
1718    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
1719    if (U_FAILURE(status)) {
1720        errln("Error setting collation alternate attribute %s",
1721              u_errorName(status));
1722    }
1723    while (VARIABLE[count].text != NULL) {
1724        logln("variable %d", count);
1725        if (!assertCanonicalEqual(&VARIABLE[count])) {
1726            errln("Error at test number %d", count);
1727        }
1728        count ++;
1729    }
1730    m_en_us_->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE,
1731                           status);
1732}
1733
1734void StringSearchTest::TestOverlapCanonical()
1735{
1736    int count = 0;
1737    while (OVERLAPCANONICAL[count].text != NULL) {
1738        if (!assertEqualWithAttribute(&OVERLAPCANONICAL[count], USEARCH_ON,
1739                                      USEARCH_ON)) {
1740            errln("Error at overlap test number %d", count);
1741        }
1742        count ++;
1743    }
1744    count = 0;
1745    while (NONOVERLAP[count].text != NULL) {
1746        if (!assertCanonicalEqual(&NONOVERLAPCANONICAL[count])) {
1747            errln("Error at non overlap test number %d", count);
1748        }
1749        count ++;
1750    }
1751
1752    count = 0;
1753    while (count < 1) {
1754              UChar       temp[128];
1755        const SearchData *search = &(OVERLAPCANONICAL[count]);
1756              UErrorCode  status = U_ZERO_ERROR;
1757
1758        u_unescape(search->text, temp, 128);
1759        UnicodeString text;
1760        text.setTo(temp, u_strlen(temp));
1761        u_unescape(search->pattern, temp, 128);
1762        UnicodeString pattern;
1763        pattern.setTo(temp, u_strlen(temp));
1764        RuleBasedCollator *collator = getCollator(search->collator);
1765        StringSearch *strsrch = new StringSearch(pattern, text, collator,
1766                                                 NULL, status);
1767        strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1768        strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_ON, status);
1769        if (U_FAILURE(status) ||
1770            strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_ON) {
1771            errln("Error setting overlap option");
1772        }
1773        if (!assertEqualWithStringSearch(strsrch, search)) {
1774            delete strsrch;
1775            return;
1776        }
1777        search = &(NONOVERLAPCANONICAL[count]);
1778        strsrch->setAttribute(USEARCH_OVERLAP, USEARCH_OFF, status);
1779        if (U_FAILURE(status) ||
1780            strsrch->getAttribute(USEARCH_OVERLAP) != USEARCH_OFF) {
1781            errln("Error setting overlap option");
1782        }
1783        strsrch->reset();
1784        if (!assertEqualWithStringSearch(strsrch, search)) {
1785            delete strsrch;
1786            errln("Error at test number %d", count);
1787         }
1788
1789        count ++;
1790        delete strsrch;
1791    }
1792}
1793
1794void StringSearchTest::TestCollatorCanonical()
1795{
1796    /* test collator that thinks "o" and "p" are the same thing */
1797    UChar temp[128];
1798    u_unescape(COLLATORCANONICAL[0].text, temp, 128);
1799    UnicodeString text;
1800    text.setTo(temp, u_strlen(temp));
1801    u_unescape(COLLATORCANONICAL[0].pattern, temp, 128);
1802    UnicodeString pattern;
1803    pattern.setTo(temp, u_strlen(temp));
1804
1805    UErrorCode    status  = U_ZERO_ERROR;
1806    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_,
1807                                             NULL, status);
1808    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1809    if (U_FAILURE(status)) {
1810        errln("Error opening string search %s", u_errorName(status));
1811    }
1812    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1813        delete strsrch;
1814        return;
1815    }
1816
1817    u_unescape(TESTCOLLATORRULE, temp, 128);
1818    UnicodeString rules;
1819    rules.setTo(temp, u_strlen(temp));
1820    RuleBasedCollator *tailored = new RuleBasedCollator(rules,
1821        getECollationStrength(COLLATORCANONICAL[1].strength),
1822        UCOL_ON, status);
1823
1824    if (U_FAILURE(status)) {
1825        errln("Error opening rule based collator %s", u_errorName(status));
1826    }
1827
1828    strsrch->setCollator(tailored, status);
1829    if (U_FAILURE(status) || *(strsrch->getCollator()) != *tailored) {
1830        errln("Error setting rule based collator");
1831    }
1832    strsrch->reset();
1833    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1834    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[1])) {
1835        delete strsrch;
1836        if (tailored != NULL) {
1837            delete tailored;
1838        }
1839
1840        return;
1841    }
1842
1843    strsrch->setCollator(m_en_us_, status);
1844    strsrch->reset();
1845    if (U_FAILURE(status) || *(strsrch->getCollator()) != *m_en_us_) {
1846        errln("Error setting rule based collator");
1847    }
1848    if (!assertEqualWithStringSearch(strsrch, &COLLATORCANONICAL[0])) {
1849    }
1850    delete strsrch;
1851    if (tailored != NULL) {
1852        delete tailored;
1853    }
1854}
1855
1856void StringSearchTest::TestPatternCanonical()
1857{
1858
1859    UChar temp[128];
1860
1861    u_unescape(PATTERNCANONICAL[0].text, temp, 128);
1862    UnicodeString text;
1863    text.setTo(temp, u_strlen(temp));
1864    u_unescape(PATTERNCANONICAL[0].pattern, temp, 128);
1865    UnicodeString pattern;
1866    pattern.setTo(temp, u_strlen(temp));
1867
1868    m_en_us_->setStrength(
1869                      getECollationStrength(PATTERNCANONICAL[0].strength));
1870
1871    UErrorCode    status  = U_ZERO_ERROR;
1872    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1873                                             status);
1874    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1875    if (U_FAILURE(status)) {
1876        errln("Error opening string search %s", u_errorName(status));
1877        goto ENDTESTPATTERN;
1878    }
1879    if (pattern != strsrch->getPattern()) {
1880        errln("Error setting pattern");
1881    }
1882    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1883        goto ENDTESTPATTERN;
1884    }
1885
1886    u_unescape(PATTERNCANONICAL[1].pattern, temp, 128);
1887    pattern.setTo(temp, u_strlen(temp));
1888    strsrch->setPattern(pattern, status);
1889    if (pattern != strsrch->getPattern()) {
1890        errln("Error setting pattern");
1891        goto ENDTESTPATTERN;
1892    }
1893    strsrch->reset();
1894    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1895    if (U_FAILURE(status)) {
1896        errln("Error setting pattern %s", u_errorName(status));
1897    }
1898    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[1])) {
1899        goto ENDTESTPATTERN;
1900    }
1901
1902    u_unescape(PATTERNCANONICAL[0].pattern, temp, 128);
1903    pattern.setTo(temp, u_strlen(temp));
1904    strsrch->setPattern(pattern, status);
1905    if (pattern != strsrch->getPattern()) {
1906        errln("Error setting pattern");
1907        goto ENDTESTPATTERN;
1908    }
1909    strsrch->reset();
1910    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1911    if (U_FAILURE(status)) {
1912        errln("Error setting pattern %s", u_errorName(status));
1913    }
1914    if (!assertEqualWithStringSearch(strsrch, &PATTERNCANONICAL[0])) {
1915        goto ENDTESTPATTERN;
1916    }
1917ENDTESTPATTERN:
1918    m_en_us_->setStrength(getECollationStrength(UCOL_TERTIARY));
1919    if (strsrch != NULL) {
1920        delete strsrch;
1921    }
1922}
1923
1924void StringSearchTest::TestTextCanonical()
1925{
1926    UChar temp[128];
1927    u_unescape(TEXTCANONICAL[0].text, temp, 128);
1928    UnicodeString text;
1929    text.setTo(temp, u_strlen(temp));
1930    u_unescape(TEXTCANONICAL[0].pattern, temp, 128);
1931    UnicodeString pattern;
1932    pattern.setTo(temp, u_strlen(temp));
1933
1934    UErrorCode    status  = U_ZERO_ERROR;
1935    StringSearch *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
1936                                             status);
1937    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
1938
1939    if (U_FAILURE(status)) {
1940        errln("Error opening string search %s", u_errorName(status));
1941        goto ENDTESTPATTERN;
1942    }
1943    if (text != strsrch->getText()) {
1944        errln("Error setting text");
1945    }
1946    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1947        goto ENDTESTPATTERN;
1948    }
1949
1950    u_unescape(TEXTCANONICAL[1].text, temp, 128);
1951    text.setTo(temp, u_strlen(temp));
1952    strsrch->setText(text, status);
1953    if (text != strsrch->getText()) {
1954        errln("Error setting text");
1955        goto ENDTESTPATTERN;
1956    }
1957    if (U_FAILURE(status)) {
1958        errln("Error setting text %s", u_errorName(status));
1959    }
1960    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[1])) {
1961        goto ENDTESTPATTERN;
1962    }
1963
1964    u_unescape(TEXTCANONICAL[0].text, temp, 128);
1965    text.setTo(temp, u_strlen(temp));
1966    strsrch->setText(text, status);
1967    if (text != strsrch->getText()) {
1968        errln("Error setting text");
1969        goto ENDTESTPATTERN;
1970    }
1971    if (U_FAILURE(status)) {
1972        errln("Error setting pattern %s", u_errorName(status));
1973    }
1974    if (!assertEqualWithStringSearch(strsrch, &TEXTCANONICAL[0])) {
1975        goto ENDTESTPATTERN;
1976    }
1977ENDTESTPATTERN:
1978    if (strsrch != NULL) {
1979        delete strsrch;
1980    }
1981}
1982
1983void StringSearchTest::TestCompositeBoundariesCanonical()
1984{
1985    int count = 0;
1986    while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
1987        logln("composite %d", count);
1988        if (!assertCanonicalEqual(&COMPOSITEBOUNDARIESCANONICAL[count])) {
1989            errln("Error at test number %d", count);
1990        }
1991        count ++;
1992    }
1993}
1994
1995void StringSearchTest::TestGetSetOffsetCanonical()
1996{
1997
1998    UErrorCode     status  = U_ZERO_ERROR;
1999    UnicodeString  text("text");
2000    UnicodeString  pattern("pattern");
2001    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
2002                                              status);
2003    Collator *collator = strsrch->getCollator();
2004
2005    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
2006
2007    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
2008    /* testing out of bounds error */
2009    strsrch->setOffset(-1, status);
2010    if (U_SUCCESS(status)) {
2011        errln("Error expecting set offset error");
2012    }
2013    strsrch->setOffset(128, status);
2014    if (U_SUCCESS(status)) {
2015        errln("Error expecting set offset error");
2016    }
2017    int   index   = 0;
2018    UChar temp[128];
2019    while (BASICCANONICAL[index].text != NULL) {
2020        SearchData  search      = BASICCANONICAL[index ++];
2021        if (BASICCANONICAL[index].text == NULL) {
2022            /* skip the last one */
2023            break;
2024        }
2025
2026        u_unescape(search.text, temp, 128);
2027        text.setTo(temp, u_strlen(temp));
2028        u_unescape(search.pattern, temp, 128);
2029        pattern.setTo(temp, u_strlen(temp));
2030
2031        UErrorCode  status      = U_ZERO_ERROR;
2032        strsrch->setText(text, status);
2033
2034        strsrch->setPattern(pattern, status);
2035
2036        int         count       = 0;
2037        int32_t matchindex  = search.offset[count];
2038        while (U_SUCCESS(status) && matchindex >= 0) {
2039            int32_t matchlength = search.size[count];
2040            strsrch->next(status);
2041            if (matchindex != strsrch->getMatchedStart() ||
2042                matchlength != strsrch->getMatchedLength()) {
2043                char *str = toCharString(strsrch->getText());
2044                errln("Text: %s", str);
2045                str = toCharString(strsrch->getPattern());
2046                errln("Pattern: %s", str);
2047                errln("Error match found at %d %d",
2048                      strsrch->getMatchedStart(),
2049                      strsrch->getMatchedLength());
2050                goto bail;
2051            }
2052            matchindex = search.offset[count + 1] == -1 ? -1 :
2053                         search.offset[count + 2];
2054            if (search.offset[count + 1] != -1) {
2055                strsrch->setOffset(search.offset[count + 1] + 1, status);
2056                if (strsrch->getOffset() != search.offset[count + 1] + 1) {
2057                    errln("Error setting offset");
2058                    goto bail;
2059                }
2060            }
2061
2062            count += 2;
2063        }
2064        strsrch->next(status);
2065        if (strsrch->getMatchedStart() != USEARCH_DONE) {
2066            char *str = toCharString(strsrch->getText());
2067            errln("Text: %s", str);
2068            str = toCharString(strsrch->getPattern());
2069            errln("Pattern: %s", str);
2070            errln("Error match found at %d %d", strsrch->getMatchedStart(),
2071                   strsrch->getMatchedLength());
2072            goto bail;
2073        }
2074    }
2075
2076bail:
2077    collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status);
2078    delete strsrch;
2079}
2080
2081void StringSearchTest::TestSupplementaryCanonical()
2082{
2083    int count = 0;
2084    while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
2085        if (!assertCanonicalEqual(&SUPPLEMENTARYCANONICAL[count])) {
2086            errln("Error at test number %d", count);
2087        }
2088        count ++;
2089    }
2090}
2091
2092void StringSearchTest::TestContractionCanonical()
2093{
2094    UChar          temp[128];
2095
2096    u_unescape(CONTRACTIONRULE, temp, 128);
2097    UnicodeString rules;
2098    rules.setTo(temp, u_strlen(temp));
2099
2100    UErrorCode         status   = U_ZERO_ERROR;
2101    RuleBasedCollator *collator = new RuleBasedCollator(rules,
2102        getECollationStrength(UCOL_TERTIARY), UCOL_ON, status);
2103    if (U_FAILURE(status)) {
2104        errln("Error opening collator %s", u_errorName(status));
2105    }
2106    UnicodeString text("text");
2107    UnicodeString pattern("pattern");
2108    StringSearch *strsrch = new StringSearch(pattern, text, collator, NULL,
2109                                             status);
2110    strsrch->setAttribute(USEARCH_CANONICAL_MATCH, USEARCH_ON, status);
2111    if (U_FAILURE(status)) {
2112        errln("Error opening string search %s", u_errorName(status));
2113    }
2114
2115    int count = 0;
2116    while (CONTRACTIONCANONICAL[count].text != NULL) {
2117        u_unescape(CONTRACTIONCANONICAL[count].text, temp, 128);
2118        text.setTo(temp, u_strlen(temp));
2119        u_unescape(CONTRACTIONCANONICAL[count].pattern, temp, 128);
2120        pattern.setTo(temp, u_strlen(temp));
2121        strsrch->setText(text, status);
2122        strsrch->setPattern(pattern, status);
2123        if (!assertEqualWithStringSearch(strsrch,
2124                                             &CONTRACTIONCANONICAL[count])) {
2125            errln("Error at test number %d", count);
2126        }
2127        count ++;
2128    }
2129    delete strsrch;
2130    delete collator;
2131}
2132
2133void StringSearchTest::TestUClassID()
2134{
2135    char id = *((char *)StringSearch::getStaticClassID());
2136    if (id != 0) {
2137        errln("Static class id for StringSearch should be 0");
2138    }
2139    UErrorCode     status    = U_ZERO_ERROR;
2140    UnicodeString  text("text");
2141    UnicodeString  pattern("pattern");
2142    StringSearch  *strsrch = new StringSearch(pattern, text, m_en_us_, NULL,
2143                                              status);
2144    id = *((char *)strsrch->getDynamicClassID());
2145    if (id != 0) {
2146        errln("Dynamic class id for StringSearch should be 0");
2147    }
2148    delete strsrch;
2149}
2150
2151class TestSearch : public SearchIterator
2152{
2153public:
2154    TestSearch(const TestSearch &obj);
2155    TestSearch(const UnicodeString &text,
2156               BreakIterator *breakiter,
2157               const UnicodeString &pattern);
2158    ~TestSearch();
2159
2160    void        setOffset(int32_t position, UErrorCode &status);
2161    int32_t     getOffset() const;
2162    SearchIterator* safeClone() const;
2163
2164
2165    /**
2166     * ICU "poor man's RTTI", returns a UClassID for the actual class.
2167     *
2168     * @draft ICU 2.2
2169     */
2170    virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
2171
2172    /**
2173     * ICU "poor man's RTTI", returns a UClassID for this class.
2174     *
2175     * @draft ICU 2.2
2176     */
2177    static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
2178
2179    UBool operator!=(const TestSearch &that) const;
2180
2181    UnicodeString m_pattern_;
2182
2183protected:
2184    int32_t      handleNext(int32_t position, UErrorCode &status);
2185    int32_t      handlePrev(int32_t position, UErrorCode &status);
2186    TestSearch & operator=(const TestSearch &that);
2187
2188private:
2189
2190    /**
2191     * The address of this static class variable serves as this class's ID
2192     * for ICU "poor man's RTTI".
2193     */
2194    static const char fgClassID;
2195    uint32_t m_offset_;
2196};
2197
2198const char TestSearch::fgClassID=0;
2199
2200TestSearch::TestSearch(const TestSearch &obj) : SearchIterator(obj)
2201{
2202    m_offset_ = obj.m_offset_;
2203    m_pattern_ = obj.m_pattern_;
2204}
2205
2206TestSearch::TestSearch(const UnicodeString &text,
2207                       BreakIterator *breakiter,
2208                       const UnicodeString &pattern) : SearchIterator()
2209{
2210    m_breakiterator_ = breakiter;
2211    m_pattern_ = pattern;
2212    m_text_ = text;
2213    m_offset_ = 0;
2214    m_pattern_ = pattern;
2215}
2216
2217TestSearch::~TestSearch()
2218{
2219}
2220
2221
2222void TestSearch::setOffset(int32_t position, UErrorCode &status)
2223{
2224    if (position >= 0 && position <= m_text_.length()) {
2225        m_offset_ = position;
2226    }
2227    else {
2228        status = U_INDEX_OUTOFBOUNDS_ERROR;
2229    }
2230}
2231
2232int32_t TestSearch::getOffset() const
2233{
2234    return m_offset_;
2235}
2236
2237SearchIterator * TestSearch::safeClone() const
2238{
2239    return new TestSearch(m_text_, m_breakiterator_, m_pattern_);
2240}
2241
2242UBool TestSearch::operator!=(const TestSearch &that) const
2243{
2244    if (SearchIterator::operator !=(that)) {
2245        return FALSE;
2246    }
2247    return m_offset_ != that.m_offset_ || m_pattern_ != that.m_pattern_;
2248}
2249
2250int32_t TestSearch::handleNext(int32_t start, UErrorCode &status)
2251{
2252  if(U_SUCCESS(status)) {
2253    int match = m_text_.indexOf(m_pattern_, start);
2254    if (match < 0) {
2255        m_offset_ = m_text_.length();
2256        setMatchStart(m_offset_);
2257        setMatchLength(0);
2258        return USEARCH_DONE;
2259    }
2260    setMatchStart(match);
2261    m_offset_ = match;
2262    setMatchLength(m_pattern_.length());
2263    return match;
2264  } else {
2265    return USEARCH_DONE;
2266  }
2267}
2268
2269int32_t TestSearch::handlePrev(int32_t start, UErrorCode &status)
2270{
2271  if(U_SUCCESS(status)) {
2272    int match = m_text_.lastIndexOf(m_pattern_, 0, start);
2273    if (match < 0) {
2274        m_offset_ = 0;
2275        setMatchStart(m_offset_);
2276        setMatchLength(0);
2277        return USEARCH_DONE;
2278    }
2279    setMatchStart(match);
2280    m_offset_ = match;
2281    setMatchLength(m_pattern_.length());
2282    return match;
2283  } else {
2284    return USEARCH_DONE;
2285  }
2286}
2287
2288TestSearch & TestSearch::operator=(const TestSearch &that)
2289{
2290    SearchIterator::operator=(that);
2291    m_offset_ = that.m_offset_;
2292    m_pattern_ = that.m_pattern_;
2293    return *this;
2294}
2295
2296void StringSearchTest::TestSubclass()
2297{
2298    UnicodeString text("abc abcd abc");
2299    UnicodeString pattern("abc");
2300    TestSearch search(text, NULL, pattern);
2301    TestSearch search2(search);
2302    int expected[] = {0, 4, 9};
2303    UErrorCode status = U_ZERO_ERROR;
2304    int i;
2305    StringCharacterIterator chariter(text);
2306
2307    search.setText(text, status);
2308    if (search.getText() != search2.getText()) {
2309        errln("Error setting text");
2310    }
2311
2312    search.setText(chariter, status);
2313    if (search.getText() != search2.getText()) {
2314        errln("Error setting text");
2315    }
2316
2317    search.reset();
2318    // comparing constructors
2319
2320    for (i = 0; i < (int)(sizeof(expected) / sizeof(expected[0])); i ++) {
2321        if (search.next(status) != expected[i]) {
2322            errln("Error getting next match");
2323        }
2324        if (search.getMatchedLength() != search.m_pattern_.length()) {
2325            errln("Error getting next match length");
2326        }
2327    }
2328    if (search.next(status) != USEARCH_DONE) {
2329        errln("Error should have reached the end of the iteration");
2330    }
2331    for (i = sizeof(expected) / sizeof(expected[0]) - 1; i >= 0; i --) {
2332        if (search.previous(status) != expected[i]) {
2333            errln("Error getting previous match");
2334        }
2335        if (search.getMatchedLength() != search.m_pattern_.length()) {
2336            errln("Error getting previous match length");
2337        }
2338    }
2339    if (search.previous(status) != USEARCH_DONE) {
2340        errln("Error should have reached the start of the iteration");
2341    }
2342}
2343
2344class StubSearchIterator:public SearchIterator{
2345public:
2346    StubSearchIterator(){}
2347    virtual void setOffset(int32_t , UErrorCode &) {};
2348    virtual int32_t getOffset(void) const {return 0;};
2349    virtual SearchIterator* safeClone(void) const {return NULL;};
2350    virtual int32_t handleNext(int32_t , UErrorCode &){return 0;};
2351    virtual int32_t handlePrev(int32_t , UErrorCode &) {return 0;};
2352    virtual UClassID getDynamicClassID() const {
2353        static char classID = 0;
2354        return (UClassID)&classID;
2355    }
2356};
2357
2358void StringSearchTest::TestCoverage(){
2359    StubSearchIterator stub1, stub2;
2360    UErrorCode status = U_ZERO_ERROR;
2361
2362    if (stub1 != stub2){
2363        errln("new StubSearchIterator should be equal");
2364    }
2365
2366    stub2.setText(UnicodeString("ABC"), status);
2367    if (U_FAILURE(status)) {
2368        errln("Error: SearchIterator::SetText");
2369    }
2370
2371    stub1 = stub2;
2372    if (stub1 != stub2){
2373        errln("SearchIterator::operator =  assigned object should be equal");
2374    }
2375}
2376
2377#endif /* !UCONFIG_NO_BREAK_ITERATION */
2378
2379#endif /* #if !UCONFIG_NO_COLLATION */
2380