1 /****************************************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2014, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  * Modification History:
6  *
7  *   Date          Name        Description
8  *   05/22/2000    Madhu       Added tests for testing new API for utf16 support and more
9  ****************************************************************************************/
10 
11 #include <string.h>
12 #include "utypeinfo.h"  // for 'typeid' to work
13 
14 #include "unicode/chariter.h"
15 #include "unicode/ustring.h"
16 #include "unicode/unistr.h"
17 #include "unicode/schriter.h"
18 #include "unicode/uchriter.h"
19 #include "unicode/uiter.h"
20 #include "unicode/putil.h"
21 #include "unicode/utf16.h"
22 #include "citrtest.h"
23 #include "cmemory.h"
24 
25 
26 class  SCharacterIterator : public CharacterIterator {
27 public:
SCharacterIterator(const UnicodeString & textStr)28     SCharacterIterator(const UnicodeString& textStr){
29         text = textStr;
30         pos=0;
31         textLength = textStr.length();
32         begin = 0;
33         end=textLength;
34 
35     }
36 
~SCharacterIterator()37     virtual ~SCharacterIterator(){};
38 
39 
setText(const UnicodeString & newText)40     void setText(const UnicodeString& newText){
41         text = newText;
42     }
43 
getText(UnicodeString & result)44     virtual void getText(UnicodeString& result) {
45         text.extract(0,text.length(),result);
46     }
getStaticClassID(void)47     static UClassID getStaticClassID(void){
48         return (UClassID)(&fgClassID);
49     }
getDynamicClassID(void) const50     virtual UClassID getDynamicClassID(void) const{
51         return getStaticClassID();
52     }
53 
operator ==(const ForwardCharacterIterator &) const54     virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{
55         return TRUE;
56     }
57 
clone(void) const58     virtual CharacterIterator* clone(void) const {
59         return NULL;
60     }
hashCode(void) const61     virtual int32_t hashCode(void) const{
62         return DONE;
63     }
nextPostInc(void)64     virtual UChar nextPostInc(void){ return text.charAt(pos++);}
next32PostInc(void)65     virtual UChar32 next32PostInc(void){return text.char32At(pos++);}
hasNext()66     virtual UBool hasNext() { return TRUE;};
first()67     virtual UChar first(){return DONE;};
first32()68     virtual UChar32 first32(){return DONE;};
last()69     virtual UChar last(){return DONE;};
last32()70     virtual UChar32 last32(){return DONE;};
setIndex(int32_t)71     virtual UChar setIndex(int32_t /*pos*/){return DONE;};
setIndex32(int32_t)72     virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;};
current() const73     virtual UChar current() const{return DONE;};
current32() const74     virtual UChar32 current32() const{return DONE;};
next()75     virtual UChar next(){return DONE;};
next32()76     virtual UChar32 next32(){return DONE;};
previous()77     virtual UChar previous(){return DONE;};
previous32()78     virtual UChar32 previous32(){return DONE;};
move(int32_t delta,CharacterIterator::EOrigin origin)79     virtual int32_t move(int32_t delta,CharacterIterator::EOrigin origin){
80         switch(origin) {
81         case kStart:
82             pos = begin + delta;
83             break;
84         case kCurrent:
85             pos += delta;
86             break;
87         case kEnd:
88             pos = end + delta;
89             break;
90         default:
91             break;
92         }
93 
94         if(pos < begin) {
95             pos = begin;
96         } else if(pos > end) {
97             pos = end;
98         }
99 
100         return pos;
101     };
move32(int32_t delta,CharacterIterator::EOrigin origin)102     virtual int32_t move32(int32_t delta, CharacterIterator::EOrigin origin){
103         switch(origin) {
104         case kStart:
105             pos = begin;
106             if(delta > 0) {
107                 U16_FWD_N(text, pos, end, delta);
108             }
109             break;
110         case kCurrent:
111             if(delta > 0) {
112                 U16_FWD_N(text, pos, end, delta);
113             } else {
114                 U16_BACK_N(text, begin, pos, -delta);
115             }
116             break;
117         case kEnd:
118             pos = end;
119             if(delta < 0) {
120                 U16_BACK_N(text, begin, pos, -delta);
121             }
122             break;
123         default:
124             break;
125         }
126 
127         return pos;
128     };
hasPrevious()129     virtual UBool hasPrevious() {return TRUE;};
130 
operator =(const SCharacterIterator & that)131   SCharacterIterator&  operator=(const SCharacterIterator&    that){
132      text = that.text;
133      return *this;
134   }
135 
136 
137 private:
138     UnicodeString text;
139     static const char fgClassID;
140 };
141 const char SCharacterIterator::fgClassID=0;
142 
CharIterTest()143 CharIterTest::CharIterTest()
144 {
145 }
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)146 void CharIterTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
147 {
148     if (exec) logln("TestSuite CharIterTest: ");
149     switch (index) {
150         case 0: name = "TestConstructionAndEquality"; if (exec) TestConstructionAndEquality(); break;
151         case 1: name = "TestConstructionAndEqualityUChariter"; if (exec) TestConstructionAndEqualityUChariter(); break;
152         case 2: name = "TestIteration"; if (exec) TestIteration(); break;
153         case 3: name = "TestIterationUChar32"; if (exec) TestIterationUChar32(); break;
154         case 4: name = "TestUCharIterator"; if (exec) TestUCharIterator(); break;
155         case 5: name = "TestCoverage"; if(exec) TestCoverage(); break;
156         case 6: name = "TestCharIteratorSubClasses"; if (exec) TestCharIteratorSubClasses(); break;
157         default: name = ""; break; //needed to end loop
158     }
159 }
160 
TestCoverage()161 void CharIterTest::TestCoverage(){
162     UnicodeString  testText("Now is the time for all good men to come to the aid of their country.");
163     UnicodeString testText2("\\ud800\\udc01deadbeef");
164     testText2 = testText2.unescape();
165     SCharacterIterator* test = new SCharacterIterator(testText);
166     if(test->firstPostInc()!= 0x004E){
167         errln("Failed: firstPostInc() failed");
168     }
169     if(test->getIndex()!=1){
170         errln("Failed: getIndex().");
171     }
172     if(test->getLength()!=testText.length()){
173         errln("Failed: getLength()");
174     }
175     test->setToStart();
176     if(test->getIndex()!=0){
177         errln("Failed: setToStart().");
178     }
179     test->setToEnd();
180     if(test->getIndex()!=testText.length()){
181         errln("Failed: setToEnd().");
182     }
183     if(test->startIndex() != 0){
184         errln("Failed: startIndex()");
185     }
186     test->setText(testText2);
187     if(test->first32PostInc()!= testText2.char32At(0)){
188         errln("Failed: first32PostInc() failed");
189     }
190 
191     delete test;
192 
193 }
TestConstructionAndEquality()194 void CharIterTest::TestConstructionAndEquality() {
195     UnicodeString  testText("Now is the time for all good men to come to the aid of their country.");
196     UnicodeString  testText2("Don't bother using this string.");
197     UnicodeString result1, result2, result3;
198 
199     CharacterIterator* test1 = new StringCharacterIterator(testText);
200     CharacterIterator* test1b= new StringCharacterIterator(testText, -1);
201     CharacterIterator* test1c= new StringCharacterIterator(testText, 100);
202     CharacterIterator* test1d= new StringCharacterIterator(testText, -2, 100, 5);
203     CharacterIterator* test1e= new StringCharacterIterator(testText, 100, 20, 5);
204     CharacterIterator* test2 = new StringCharacterIterator(testText, 5);
205     CharacterIterator* test3 = new StringCharacterIterator(testText, 2, 20, 5);
206     CharacterIterator* test4 = new StringCharacterIterator(testText2);
207     CharacterIterator* test5 = test1->clone();
208 
209     if (test1d->startIndex() < 0)
210         errln("Construction failed: startIndex is negative");
211     if (test1d->endIndex() > testText.length())
212         errln("Construction failed: endIndex is greater than the text length");
213     if (test1d->getIndex() < test1d->startIndex() || test1d->endIndex() < test1d->getIndex())
214         errln("Construction failed: index is invalid");
215 
216     if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4)
217         errln("Construction or operator== failed: Unequal objects compared equal");
218     if (*test1 != *test5)
219         errln("clone() or equals() failed: Two clones tested unequal");
220 
221     if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode()
222                     || test1->hashCode() == test4->hashCode())
223         errln("hashCode() failed:  different objects have same hash code");
224 
225     if (test1->hashCode() != test5->hashCode())
226         errln("hashCode() failed:  identical objects have different hash codes");
227 
228     if(test1->getLength() != testText.length()){
229         errln("getLength of CharacterIterator failed");
230     }
231     test1->getText(result1);
232     test1b->getText(result2);
233     test1c->getText(result3);
234     if(result1 != result2 ||  result1 != result3)
235         errln("construction failed or getText() failed");
236 
237 
238     test1->setIndex(5);
239     if (*test1 != *test2 || *test1 == *test5)
240         errln("setIndex() failed");
241 
242     *((StringCharacterIterator*)test1) = *((StringCharacterIterator*)test3);
243     if (*test1 != *test3 || *test1 == *test5)
244         errln("operator= failed");
245 
246     delete test2;
247     delete test3;
248     delete test4;
249     delete test5;
250     delete test1b;
251     delete test1c;
252     delete test1d;
253     delete test1e;
254 
255 
256     StringCharacterIterator* testChar1=new StringCharacterIterator(testText);
257     StringCharacterIterator* testChar2=new StringCharacterIterator(testText2);
258     StringCharacterIterator* testChar3=(StringCharacterIterator*)test1->clone();
259 
260     testChar1->getText(result1);
261     testChar2->getText(result2);
262     testChar3->getText(result3);
263     if(result1 != result3 || result1 == result2)
264         errln("getText() failed");
265     testChar3->setText(testText2);
266     testChar3->getText(result3);
267     if(result1 == result3 || result2 != result3)
268         errln("setText() or getText() failed");
269     testChar3->setText(testText);
270     testChar3->getText(result3);
271     if(result1 != result3 || result1 == result2)
272         errln("setText() or getText() round-trip failed");
273 
274     delete testChar1;
275     delete testChar2;
276     delete testChar3;
277     delete test1;
278 
279 }
TestConstructionAndEqualityUChariter()280 void CharIterTest::TestConstructionAndEqualityUChariter() {
281     U_STRING_DECL(testText, "Now is the time for all good men to come to the aid of their country.", 69);
282     U_STRING_DECL(testText2, "Don't bother using this string.", 31);
283 
284     U_STRING_INIT(testText, "Now is the time for all good men to come to the aid of their country.", 69);
285     U_STRING_INIT(testText2, "Don't bother using this string.", 31);
286 
287     UnicodeString result, result4, result5;
288 
289     UCharCharacterIterator* test1 = new UCharCharacterIterator(testText, u_strlen(testText));
290     UCharCharacterIterator* test2 = new UCharCharacterIterator(testText, u_strlen(testText), 5);
291     UCharCharacterIterator* test3 = new UCharCharacterIterator(testText, u_strlen(testText), 2, 20, 5);
292     UCharCharacterIterator* test4 = new UCharCharacterIterator(testText2, u_strlen(testText2));
293     UCharCharacterIterator* test5 = (UCharCharacterIterator*)test1->clone();
294     UCharCharacterIterator* test6 = new UCharCharacterIterator(*test1);
295 
296     // j785: length=-1 will use u_strlen()
297     UCharCharacterIterator* test7a = new UCharCharacterIterator(testText, -1);
298     UCharCharacterIterator* test7b = new UCharCharacterIterator(testText, -1);
299     UCharCharacterIterator* test7c = new UCharCharacterIterator(testText, -1, 2, 20, 5);
300 
301     // Bad parameters.
302     UCharCharacterIterator* test8a = new UCharCharacterIterator(testText, -1, -1, 20, 5);
303     UCharCharacterIterator* test8b = new UCharCharacterIterator(testText, -1, 2, 100, 5);
304     UCharCharacterIterator* test8c = new UCharCharacterIterator(testText, -1, 2, 20, 100);
305 
306     if (test8a->startIndex() < 0)
307         errln("Construction failed: startIndex is negative");
308     if (test8b->endIndex() != u_strlen(testText))
309         errln("Construction failed: endIndex is different from the text length");
310     if (test8c->getIndex() < test8c->startIndex() || test8c->endIndex() < test8c->getIndex())
311         errln("Construction failed: index is invalid");
312 
313     if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4 )
314         errln("Construction or operator== failed: Unequal objects compared equal");
315     if (*test1 != *test5 )
316         errln("clone() or equals() failed: Two clones tested unequal");
317 
318     if (*test6 != *test1 )
319         errln("copy construction or equals() failed: Two copies tested unequal");
320 
321     if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode()
322                     || test1->hashCode() == test4->hashCode())
323         errln("hashCode() failed:  different objects have same hash code");
324 
325     if (test1->hashCode() != test5->hashCode())
326         errln("hashCode() failed:  identical objects have different hash codes");
327 
328     test7a->getText(result);
329     test7b->getText(result4);
330     test7c->getText(result5);
331 
332     if(result != UnicodeString(testText) || result4 != result || result5 != result)
333         errln("error in construction");
334 
335     test1->getText(result);
336     test4->getText(result4);
337     test5->getText(result5);
338     if(result != result5 || result == result4)
339         errln("getText() failed");
340     test5->setText(testText2, u_strlen(testText2));
341     test5->getText(result5);
342     if(result == result5 || result4 != result5)
343         errln("setText() or getText() failed");
344     test5->setText(testText, u_strlen(testText));
345     test5->getText(result5);
346     if(result != result5 || result == result4)
347         errln("setText() or getText() round-trip failed");
348 
349 
350     test1->setIndex(5);
351     if (*test1 != *test2 || *test1 == *test5)
352         errln("setIndex() failed");
353     test8b->setIndex32(5);
354     if (test8b->getIndex()!=5)
355         errln("setIndex32() failed");
356 
357     *test1 = *test3;
358     if (*test1 != *test3 || *test1 == *test5)
359         errln("operator= failed");
360 
361     delete test1;
362     delete test2;
363     delete test3;
364     delete test4;
365     delete test5;
366     delete test6;
367     delete test7a;
368     delete test7b;
369     delete test7c;
370     delete test8a;
371     delete test8b;
372     delete test8c;
373 }
374 
375 
TestIteration()376 void CharIterTest::TestIteration() {
377     UnicodeString text("Now is the time for all good men to come to the aid of their country.");
378 
379     UChar c;
380     int32_t i;
381     {
382         StringCharacterIterator   iter(text, 5);
383 
384         UnicodeString iterText;
385         iter.getText(iterText);
386         if (iterText != text)
387           errln("iter.getText() failed");
388 
389         if (iter.current() != text[(int32_t)5])
390             errln("Iterator didn't start out in the right place.");
391 
392         c = iter.first();
393         i = 0;
394 
395         if (iter.startIndex() != 0 || iter.endIndex() != text.length())
396             errln("startIndex() or endIndex() failed");
397 
398         logln("Testing forward iteration...");
399         do {
400             if (c == CharacterIterator::DONE && i != text.length())
401                 errln("Iterator reached end prematurely");
402             else if (c != text[i])
403                 errln((UnicodeString)"Character mismatch at position " + i +
404                                     ", iterator has " + UCharToUnicodeString(c) +
405                                     ", string has " + UCharToUnicodeString(text[i]));
406 
407             if (iter.current() != c)
408                 errln("current() isn't working right");
409             if (iter.getIndex() != i)
410                 errln("getIndex() isn't working right");
411 
412             if (c != CharacterIterator::DONE) {
413                 c = iter.next();
414                 i++;
415             }
416         } while (c != CharacterIterator::DONE);
417         c=iter.next();
418         if(c!= CharacterIterator::DONE)
419             errln("next() didn't return DONE at the end");
420         c=iter.setIndex(text.length()+1);
421         if(c!= CharacterIterator::DONE)
422             errln("setIndex(len+1) didn't return DONE");
423 
424         c = iter.last();
425         i = text.length() - 1;
426 
427         logln("Testing backward iteration...");
428         do {
429             if (c == CharacterIterator::DONE && i >= 0)
430                 errln("Iterator reached end prematurely");
431             else if (c != text[i])
432                 errln((UnicodeString)"Character mismatch at position " + i +
433                                     ", iterator has " + UCharToUnicodeString(c) +
434                                     ", string has " + UCharToUnicodeString(text[i]));
435 
436             if (iter.current() != c)
437                 errln("current() isn't working right");
438             if (iter.getIndex() != i)
439                 errln("getIndex() isn't working right");
440             if(iter.setIndex(i) != c)
441                 errln("setIndex() isn't working right");
442 
443             if (c != CharacterIterator::DONE) {
444                 c = iter.previous();
445                 i--;
446             }
447         } while (c != CharacterIterator::DONE);
448 
449         c=iter.previous();
450         if(c!= CharacterIterator::DONE)
451             errln("previous didn't return DONE at the beginning");
452 
453 
454         //testing firstPostInc, nextPostInc, setTostart
455         i = 0;
456         c=iter.firstPostInc();
457         if(c != text[i])
458             errln((UnicodeString)"firstPostInc failed.  Expected->" +
459                          UCharToUnicodeString(text[i]) + " Got->" + UCharToUnicodeString(c));
460         if(iter.getIndex() != i+1)
461             errln((UnicodeString)"getIndex() after firstPostInc() failed");
462 
463         iter.setToStart();
464         i=0;
465         if (iter.startIndex() != 0)
466             errln("setToStart failed");
467 
468         logln("Testing forward iteration...");
469         do {
470             if (c != CharacterIterator::DONE)
471                 c = iter.nextPostInc();
472 
473             if(c != text[i])
474                 errln((UnicodeString)"Character mismatch at position " + i +
475                                     (UnicodeString)", iterator has " + UCharToUnicodeString(c) +
476                                     (UnicodeString)", string has " + UCharToUnicodeString(text[i]));
477 
478             i++;
479             if(iter.getIndex() != i)
480                 errln("getIndex() aftr nextPostInc() isn't working right");
481             if(iter.current() != text[i])
482                 errln("current() after nextPostInc() isn't working right");
483         } while (iter.hasNext());
484         c=iter.nextPostInc();
485         if(c!= CharacterIterator::DONE)
486             errln("nextPostInc() didn't return DONE at the beginning");
487     }
488 
489     {
490         StringCharacterIterator iter(text, 5, 15, 10);
491         if (iter.startIndex() != 5 || iter.endIndex() != 15)
492             errln("creation of a restricted-range iterator failed");
493 
494         if (iter.getIndex() != 10 || iter.current() != text[(int32_t)10])
495             errln("starting the iterator in the middle didn't work");
496 
497         c = iter.first();
498         i = 5;
499 
500         logln("Testing forward iteration over a range...");
501         do {
502             if (c == CharacterIterator::DONE && i != 15)
503                 errln("Iterator reached end prematurely");
504             else if (c != text[i])
505                 errln((UnicodeString)"Character mismatch at position " + i +
506                                     ", iterator has " + UCharToUnicodeString(c) +
507                                     ", string has " + UCharToUnicodeString(text[i]));
508 
509             if (iter.current() != c)
510                 errln("current() isn't working right");
511             if (iter.getIndex() != i)
512                 errln("getIndex() isn't working right");
513             if(iter.setIndex(i) != c)
514                 errln("setIndex() isn't working right");
515 
516             if (c != CharacterIterator::DONE) {
517                 c = iter.next();
518                 i++;
519             }
520         } while (c != CharacterIterator::DONE);
521 
522         c = iter.last();
523         i = 14;
524 
525         logln("Testing backward iteration over a range...");
526         do {
527             if (c == CharacterIterator::DONE && i >= 5)
528                 errln("Iterator reached end prematurely");
529             else if (c != text[i])
530                 errln((UnicodeString)"Character mismatch at position " + i +
531                                     ", iterator has " + UCharToUnicodeString(c) +
532                                     ", string has " + UCharToUnicodeString(text[i]));
533 
534             if (iter.current() != c)
535                 errln("current() isn't working right");
536             if (iter.getIndex() != i)
537                 errln("getIndex() isn't working right");
538 
539             if (c != CharacterIterator::DONE) {
540                 c = iter.previous();
541                 i--;
542             }
543         } while (c != CharacterIterator::DONE);
544 
545 
546     }
547 }
548 
549 //Tests for new API for utf-16 support
TestIterationUChar32()550 void CharIterTest::TestIterationUChar32() {
551     UChar textChars[]={ 0x0061, 0x0062, 0xd841, 0xdc02, 0x20ac, 0xd7ff, 0xd842, 0xdc06, 0xd801, 0xdc00, 0x0061, 0x0000};
552     UnicodeString text(textChars);
553     UChar32 c;
554     int32_t i;
555     {
556         StringCharacterIterator   iter(text, 1);
557 
558         UnicodeString iterText;
559         iter.getText(iterText);
560         if (iterText != text)
561           errln("iter.getText() failed");
562 
563         if (iter.current32() != text[(int32_t)1])
564             errln("Iterator didn't start out in the right place.");
565 
566         c=iter.setToStart();
567         i=0;
568         i=iter.move32(1, CharacterIterator::kStart);
569         c=iter.current32();
570         if(c != text.char32At(1) || i!=1)
571             errln("move32(1, kStart) didn't work correctly expected %X got %X", c, text.char32At(1) );
572 
573         i=iter.move32(2, CharacterIterator::kCurrent);
574         c=iter.current32();
575         if(c != text.char32At(4) || i!=4)
576             errln("move32(2, kCurrent) didn't work correctly expected %X got %X i=%ld", c, text.char32At(4), i);
577 
578         i=iter.move32(-2, CharacterIterator::kCurrent);
579         c=iter.current32();
580         if(c != text.char32At(1) || i!=1)
581             errln("move32(-2, kCurrent) didn't work correctly expected %X got %X i=%d", c, text.char32At(1), i);
582 
583 
584         i=iter.move32(-2, CharacterIterator::kEnd);
585         c=iter.current32();
586         if(c != text.char32At((text.length()-3)) || i!=(text.length()-3))
587             errln("move32(-2, kEnd) didn't work correctly expected %X got %X i=%d", c, text.char32At((text.length()-3)), i);
588 
589 
590         c = iter.first32();
591         i = 0;
592 
593         if (iter.startIndex() != 0 || iter.endIndex() != text.length())
594             errln("startIndex() or endIndex() failed");
595 
596         logln("Testing forward iteration...");
597         do {
598             /* logln("c=%d i=%d char32At=%d", c, i, text.char32At(i)); */
599             if (c == CharacterIterator::DONE && i != text.length())
600                 errln("Iterator reached end prematurely");
601             else if(iter.hasNext() == FALSE && i != text.length())
602                 errln("Iterator reached end prematurely.  Failed at hasNext");
603             else if (c != text.char32At(i))
604                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
605 
606             if (iter.current32() != c)
607                 errln("current32() isn't working right");
608             if(iter.setIndex32(i) != c)
609                 errln("setIndex32() isn't working right");
610             if (c != CharacterIterator::DONE) {
611                 c = iter.next32();
612                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
613             }
614         } while (c != CharacterIterator::DONE);
615         if(iter.hasNext() == TRUE)
616            errln("hasNext() returned true at the end of the string");
617 
618 
619 
620         c=iter.setToEnd();
621         if(iter.getIndex() != text.length() || iter.hasNext() != FALSE)
622             errln("setToEnd failed");
623 
624         c=iter.next32();
625         if(c!= CharacterIterator::DONE)
626             errln("next32 didn't return DONE at the end");
627         c=iter.setIndex32(text.length()+1);
628         if(c!= CharacterIterator::DONE)
629             errln("setIndex32(len+1) didn't return DONE");
630 
631 
632         c = iter.last32();
633         i = text.length()-1;
634         logln("Testing backward iteration...");
635         do {
636             if (c == CharacterIterator::DONE && i >= 0)
637                 errln((UnicodeString)"Iterator reached start prematurely for i=" + i);
638             else if(iter.hasPrevious() == FALSE && i>0)
639                 errln((UnicodeString)"Iterator reached start prematurely for i=" + i);
640             else if (c != text.char32At(i))
641                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
642 
643             if (iter.current32() != c)
644                 errln("current32() isn't working right");
645             if(iter.setIndex32(i) != c)
646                 errln("setIndex32() isn't working right");
647             if (iter.getIndex() != i)
648                 errln("getIndex() isn't working right");
649             if (c != CharacterIterator::DONE) {
650                 c = iter.previous32();
651                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1;
652             }
653         } while (c != CharacterIterator::DONE);
654         if(iter.hasPrevious() == TRUE)
655             errln("hasPrevious returned true after reaching the start");
656 
657         c=iter.previous32();
658         if(c!= CharacterIterator::DONE)
659             errln("previous32 didn't return DONE at the beginning");
660 
661 
662 
663 
664         //testing first32PostInc, next32PostInc, setTostart
665         i = 0;
666         c=iter.first32PostInc();
667         if(c != text.char32At(i))
668             errln("first32PostInc failed.  Expected->%X Got->%X", text.char32At(i), c);
669         if(iter.getIndex() != U16_LENGTH(c) + i)
670             errln((UnicodeString)"getIndex() after first32PostInc() failed");
671 
672         iter.setToStart();
673         i=0;
674         if (iter.startIndex() != 0)
675             errln("setToStart failed");
676 
677         logln("Testing forward iteration...");
678         do {
679             if (c != CharacterIterator::DONE)
680                 c = iter.next32PostInc();
681 
682             if(c != text.char32At(i))
683                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
684 
685             i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
686             if(iter.getIndex() != i)
687                 errln("getIndex() aftr next32PostInc() isn't working right");
688             if(iter.current32() != text.char32At(i))
689                 errln("current() after next32PostInc() isn't working right");
690         } while (iter.hasNext());
691         c=iter.next32PostInc();
692         if(c!= CharacterIterator::DONE)
693             errln("next32PostInc() didn't return DONE at the beginning");
694 
695 
696     }
697 
698     {
699         StringCharacterIterator iter(text, 1, 11, 10);
700         if (iter.startIndex() != 1 || iter.endIndex() != 11)
701             errln("creation of a restricted-range iterator failed");
702 
703         if (iter.getIndex() != 10 || iter.current32() != text.char32At(10))
704             errln("starting the iterator in the middle didn't work");
705 
706         c = iter.first32();
707 
708         i = 1;
709 
710         logln("Testing forward iteration over a range...");
711         do {
712             if (c == CharacterIterator::DONE && i != 11)
713                 errln("Iterator reached end prematurely");
714             else if(iter.hasNext() == FALSE)
715                 errln("Iterator reached end prematurely");
716             else if (c != text.char32At(i))
717                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
718 
719             if (iter.current32() != c)
720                 errln("current32() isn't working right");
721             if(iter.setIndex32(i) != c)
722                 errln("setIndex32() isn't working right");
723 
724             if (c != CharacterIterator::DONE) {
725                 c = iter.next32();
726                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1;
727             }
728         } while (c != CharacterIterator::DONE);
729         c=iter.next32();
730         if(c != CharacterIterator::DONE)
731             errln("error in next32()");
732 
733 
734 
735         c=iter.last32();
736         i = 10;
737         logln("Testing backward iteration over a range...");
738         do {
739             if (c == CharacterIterator::DONE && i >= 5)
740                 errln("Iterator reached start prematurely");
741             else if(iter.hasPrevious() == FALSE && i > 5)
742                 errln("Iterator reached start prematurely");
743             else if (c != text.char32At(i))
744                 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i));
745             if (iter.current32() != c)
746                 errln("current32() isn't working right");
747             if (iter.getIndex() != i)
748                 errln("getIndex() isn't working right");
749             if(iter.setIndex32(i) != c)
750                 errln("setIndex32() isn't working right");
751 
752             if (c != CharacterIterator::DONE) {
753                 c = iter.previous32();
754                 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1;
755             }
756 
757         } while (c != CharacterIterator::DONE);
758         c=iter.previous32();
759         if(c!= CharacterIterator::DONE)
760             errln("error on previous32");
761 
762 
763     }
764 }
765 
TestUCharIterator(UCharIterator * iter,CharacterIterator & ci,const char * moves,const char * which)766 void CharIterTest::TestUCharIterator(UCharIterator *iter, CharacterIterator &ci,
767                                      const char *moves, const char *which) {
768     int32_t m;
769     UChar32 c, c2;
770     UBool h, h2;
771 
772     for(m=0;; ++m) {
773         // move both iter and s[index]
774         switch(moves[m]) {
775         case '0':
776             h=iter->hasNext(iter);
777             h2=ci.hasNext();
778             c=iter->current(iter);
779             c2=ci.current();
780             break;
781         case '|':
782             h=iter->hasNext(iter);
783             h2=ci.hasNext();
784             c=uiter_current32(iter);
785             c2=ci.current32();
786             break;
787 
788         case '+':
789             h=iter->hasNext(iter);
790             h2=ci.hasNext();
791             c=iter->next(iter);
792             c2=ci.nextPostInc();
793             break;
794         case '>':
795             h=iter->hasNext(iter);
796             h2=ci.hasNext();
797             c=uiter_next32(iter);
798             c2=ci.next32PostInc();
799             break;
800 
801         case '-':
802             h=iter->hasPrevious(iter);
803             h2=ci.hasPrevious();
804             c=iter->previous(iter);
805             c2=ci.previous();
806             break;
807         case '<':
808             h=iter->hasPrevious(iter);
809             h2=ci.hasPrevious();
810             c=uiter_previous32(iter);
811             c2=ci.previous32();
812             break;
813 
814         case '2':
815             h=h2=FALSE;
816             c=(UChar32)iter->move(iter, 2, UITER_CURRENT);
817             c2=(UChar32)ci.move(2, CharacterIterator::kCurrent);
818             break;
819 
820         case '8':
821             h=h2=FALSE;
822             c=(UChar32)iter->move(iter, -2, UITER_CURRENT);
823             c2=(UChar32)ci.move(-2, CharacterIterator::kCurrent);
824             break;
825 
826         case 0:
827             return;
828         default:
829             errln("error: unexpected move character '%c' in \"%s\"", moves[m], moves);
830             return;
831         }
832 
833         // compare results
834         if(c2==0xffff) {
835             c2=(UChar32)-1;
836         }
837         if(c!=c2 || h!=h2 || ci.getIndex()!=iter->getIndex(iter, UITER_CURRENT)) {
838             errln("error: UCharIterator(%s) misbehaving at \"%s\"[%d]='%c'", which, moves, m, moves[m]);
839         }
840     }
841 }
842 
TestUCharIterator()843 void CharIterTest::TestUCharIterator() {
844     // test string of length 8
845     UnicodeString s=UnicodeString("a \\U00010001b\\U0010fffdz", "").unescape();
846     const char *const moves=
847         "0+++++++++" // 10 moves per line
848         "----0-----"
849         ">>|>>>>>>>"
850         "<<|<<<<<<<"
851         "22+>8>-8+2";
852 
853     StringCharacterIterator sci(s), compareCI(s);
854 
855     UCharIterator sIter, cIter, rIter;
856 
857     uiter_setString(&sIter, s.getBuffer(), s.length());
858     uiter_setCharacterIterator(&cIter, &sci);
859     uiter_setReplaceable(&rIter, &s);
860 
861     TestUCharIterator(&sIter, compareCI, moves, "uiter_setString");
862     compareCI.setIndex(0);
863     TestUCharIterator(&cIter, compareCI, moves, "uiter_setCharacterIterator");
864     compareCI.setIndex(0);
865     TestUCharIterator(&rIter, compareCI, moves, "uiter_setReplaceable");
866 
867     // test move & getIndex some more
868     sIter.start=2;
869     sIter.index=3;
870     sIter.limit=5;
871     if( sIter.getIndex(&sIter, UITER_ZERO)!=0 ||
872         sIter.getIndex(&sIter, UITER_START)!=2 ||
873         sIter.getIndex(&sIter, UITER_CURRENT)!=3 ||
874         sIter.getIndex(&sIter, UITER_LIMIT)!=5 ||
875         sIter.getIndex(&sIter, UITER_LENGTH)!=s.length()
876     ) {
877         errln("error: UCharIterator(string).getIndex returns wrong index");
878     }
879 
880     if( sIter.move(&sIter, 4, UITER_ZERO)!=4 ||
881         sIter.move(&sIter, 1, UITER_START)!=3 ||
882         sIter.move(&sIter, 3, UITER_CURRENT)!=5 ||
883         sIter.move(&sIter, -1, UITER_LIMIT)!=4 ||
884         sIter.move(&sIter, -5, UITER_LENGTH)!=3 ||
885         sIter.move(&sIter, 0, UITER_CURRENT)!=sIter.getIndex(&sIter, UITER_CURRENT) ||
886         sIter.getIndex(&sIter, UITER_CURRENT)!=3
887     ) {
888         errln("error: UCharIterator(string).move sets/returns wrong index");
889     }
890 
891     sci=StringCharacterIterator(s, 2, 5, 3);
892     uiter_setCharacterIterator(&cIter, &sci);
893     if( cIter.getIndex(&cIter, UITER_ZERO)!=0 ||
894         cIter.getIndex(&cIter, UITER_START)!=2 ||
895         cIter.getIndex(&cIter, UITER_CURRENT)!=3 ||
896         cIter.getIndex(&cIter, UITER_LIMIT)!=5 ||
897         cIter.getIndex(&cIter, UITER_LENGTH)!=s.length()
898     ) {
899         errln("error: UCharIterator(character iterator).getIndex returns wrong index");
900     }
901 
902     if( cIter.move(&cIter, 4, UITER_ZERO)!=4 ||
903         cIter.move(&cIter, 1, UITER_START)!=3 ||
904         cIter.move(&cIter, 3, UITER_CURRENT)!=5 ||
905         cIter.move(&cIter, -1, UITER_LIMIT)!=4 ||
906         cIter.move(&cIter, -5, UITER_LENGTH)!=3 ||
907         cIter.move(&cIter, 0, UITER_CURRENT)!=cIter.getIndex(&cIter, UITER_CURRENT) ||
908         cIter.getIndex(&cIter, UITER_CURRENT)!=3
909     ) {
910         errln("error: UCharIterator(character iterator).move sets/returns wrong index");
911     }
912 
913 
914     if(cIter.getIndex(&cIter, (enum UCharIteratorOrigin)-1) != -1)
915     {
916         errln("error: UCharIterator(char iter).getIndex did not return error value");
917     }
918 
919     if(cIter.move(&cIter, 0, (enum UCharIteratorOrigin)-1) != -1)
920     {
921         errln("error: UCharIterator(char iter).move did not return error value");
922     }
923 
924 
925     if(rIter.getIndex(&rIter, (enum UCharIteratorOrigin)-1) != -1)
926     {
927         errln("error: UCharIterator(repl iter).getIndex did not return error value");
928     }
929 
930     if(rIter.move(&rIter, 0, (enum UCharIteratorOrigin)-1) != -1)
931     {
932         errln("error: UCharIterator(repl iter).move did not return error value");
933     }
934 
935 
936     if(sIter.getIndex(&sIter, (enum UCharIteratorOrigin)-1) != -1)
937     {
938         errln("error: UCharIterator(string iter).getIndex did not return error value");
939     }
940 
941     if(sIter.move(&sIter, 0, (enum UCharIteratorOrigin)-1) != -1)
942     {
943         errln("error: UCharIterator(string iter).move did not return error value");
944     }
945 
946     /* Testing function coverage on bad input */
947     UErrorCode status = U_ZERO_ERROR;
948     uiter_setString(&sIter, NULL, 1);
949     uiter_setState(&sIter, 1, &status);
950     if (status != U_UNSUPPORTED_ERROR) {
951         errln("error: uiter_setState returned %s instead of U_UNSUPPORTED_ERROR", u_errorName(status));
952     }
953     status = U_ZERO_ERROR;
954     uiter_setState(NULL, 1, &status);
955     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
956         errln("error: uiter_setState returned %s instead of U_ILLEGAL_ARGUMENT_ERROR", u_errorName(status));
957     }
958     if (uiter_getState(&sIter) != UITER_NO_STATE) {
959         errln("error: uiter_getState did not return UITER_NO_STATE on bad input");
960     }
961 }
962 
963 // subclass test, and completing API coverage -------------------------------
964 
965 class SubCharIter : public CharacterIterator {
966 public:
967     // public default constructor, to get coverage of CharacterIterator()
SubCharIter()968     SubCharIter() : CharacterIterator() {
969         textLength=end=UPRV_LENGTHOF(s);
970         s[0]=0x61;      // 'a'
971         s[1]=0xd900;    // U+50400
972         s[2]=0xdd00;
973         s[3]=0x2029;    // PS
974     }
975 
976     // useful stuff, mostly dummy but testing coverage and subclassability
nextPostInc()977     virtual UChar nextPostInc() {
978         if(pos<UPRV_LENGTHOF(s)) {
979             return s[pos++];
980         } else {
981             return DONE;
982         }
983     }
984 
next32PostInc()985     virtual UChar32 next32PostInc() {
986         if(pos<UPRV_LENGTHOF(s)) {
987             UChar32 c;
988             U16_NEXT(s, pos, UPRV_LENGTHOF(s), c);
989             return c;
990         } else {
991             return DONE;
992         }
993     }
994 
hasNext()995     virtual UBool hasNext() {
996         return pos<UPRV_LENGTHOF(s);
997     }
998 
first()999     virtual UChar first() {
1000         pos=0;
1001         return s[0];
1002     }
1003 
first32()1004     virtual UChar32 first32() {
1005         UChar32 c;
1006         pos=0;
1007         U16_NEXT(s, pos, UPRV_LENGTHOF(s), c);
1008         pos=0;
1009         return c;
1010     }
1011 
setIndex(int32_t position)1012     virtual UChar setIndex(int32_t position) {
1013         if(0<=position && position<=UPRV_LENGTHOF(s)) {
1014             pos=position;
1015             if(pos<UPRV_LENGTHOF(s)) {
1016                 return s[pos];
1017             }
1018         }
1019         return DONE;
1020     }
1021 
setIndex32(int32_t position)1022     virtual UChar32 setIndex32(int32_t position) {
1023         if(0<=position && position<=UPRV_LENGTHOF(s)) {
1024             pos=position;
1025             if(pos<UPRV_LENGTHOF(s)) {
1026                 UChar32 c;
1027                 U16_GET(s, 0, pos, UPRV_LENGTHOF(s), c);
1028                 return c;
1029             }
1030         }
1031         return DONE;
1032     }
1033 
current() const1034     virtual UChar current() const {
1035         if(pos<UPRV_LENGTHOF(s)) {
1036             return s[pos];
1037         } else {
1038             return DONE;
1039         }
1040     }
1041 
current32() const1042     virtual UChar32 current32() const {
1043         if(pos<UPRV_LENGTHOF(s)) {
1044             UChar32 c;
1045             U16_GET(s, 0, pos, UPRV_LENGTHOF(s), c);
1046             return c;
1047         } else {
1048             return DONE;
1049         }
1050     }
1051 
next()1052     virtual UChar next() {
1053         if(pos<UPRV_LENGTHOF(s) && ++pos<UPRV_LENGTHOF(s)) {
1054             return s[pos];
1055         } else {
1056             return DONE;
1057         }
1058     }
1059 
next32()1060     virtual UChar32 next32() {
1061         if(pos<UPRV_LENGTHOF(s)) {
1062             U16_FWD_1(s, pos, UPRV_LENGTHOF(s));
1063         }
1064         if(pos<UPRV_LENGTHOF(s)) {
1065             UChar32 c;
1066             int32_t i=pos;
1067             U16_NEXT(s, i, UPRV_LENGTHOF(s), c);
1068             return c;
1069         } else {
1070             return DONE;
1071         }
1072     }
1073 
hasPrevious()1074     virtual UBool hasPrevious() {
1075         return pos>0;
1076     }
1077 
getText(UnicodeString & result)1078     virtual void getText(UnicodeString &result) {
1079         result.setTo(s, UPRV_LENGTHOF(s));
1080     }
1081 
1082     // dummy implementations of other pure virtual base class functions
operator ==(const ForwardCharacterIterator & that) const1083     virtual UBool operator==(const ForwardCharacterIterator &that) const {
1084         return
1085             this==&that ||
1086             (typeid(*this)==typeid(that) && pos==((SubCharIter &)that).pos);
1087     }
1088 
hashCode() const1089     virtual int32_t hashCode() const {
1090         return 2;
1091     }
1092 
clone() const1093     virtual CharacterIterator *clone() const {
1094         return NULL;
1095     }
1096 
last()1097     virtual UChar last() {
1098         return 0;
1099     }
1100 
last32()1101     virtual UChar32 last32() {
1102         return 0;
1103     }
1104 
previous()1105     virtual UChar previous() {
1106         return 0;
1107     }
1108 
previous32()1109     virtual UChar32 previous32() {
1110         return 0;
1111     }
1112 
move(int32_t,EOrigin)1113     virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) {
1114         return 0;
1115     }
1116 
move32(int32_t,EOrigin)1117     virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) {
1118         return 0;
1119     }
1120 
1121     // RTTI
getStaticClassID()1122     static UClassID getStaticClassID() {
1123         return (UClassID)(&fgClassID);
1124     }
1125 
getDynamicClassID() const1126     virtual UClassID getDynamicClassID() const {
1127         return getStaticClassID();
1128     }
1129 
1130 private:
1131     // dummy string data
1132     UChar s[4];
1133 
1134     static const char fgClassID;
1135 };
1136 
1137 const char SubCharIter::fgClassID = 0;
1138 
1139 class SubStringCharIter : public StringCharacterIterator {
1140 public:
SubStringCharIter()1141     SubStringCharIter() {
1142         setText(UNICODE_STRING("abc", 3));
1143     }
1144 };
1145 
1146 class SubUCharCharIter : public UCharCharacterIterator {
1147 public:
SubUCharCharIter()1148     SubUCharCharIter() {
1149         setText(u, 3);
1150     }
1151 
1152 private:
1153     static const UChar u[3];
1154 };
1155 
1156 const UChar SubUCharCharIter::u[3]={ 0x61, 0x62, 0x63 };
1157 
TestCharIteratorSubClasses()1158 void CharIterTest::TestCharIteratorSubClasses() {
1159     SubCharIter *p;
1160 
1161     // coverage - call functions that are not otherwise tested
1162     // first[32]PostInc() are default implementations that are overridden
1163     // in ICU's own CharacterIterator subclasses
1164     p=new SubCharIter;
1165     if(p->firstPostInc()!=0x61) {
1166         errln("SubCharIter.firstPosInc() failed\n");
1167     }
1168     delete p;
1169 
1170     p=new SubCharIter[2];
1171     if(p[1].first32PostInc()!=0x61) {
1172         errln("SubCharIter.first32PosInc() failed\n");
1173     }
1174     delete [] p;
1175 
1176     // coverage: StringCharacterIterator default constructor
1177     SubStringCharIter sci;
1178     if(sci.firstPostInc()!=0x61) {
1179         errln("SubStringCharIter.firstPostInc() failed\n");
1180     }
1181 
1182     // coverage: UCharCharacterIterator default constructor
1183     SubUCharCharIter uci;
1184     if(uci.firstPostInc()!=0x61) {
1185         errln("SubUCharCharIter.firstPostInc() failed\n");
1186     }
1187 }
1188