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