Home | History | Annotate | Download | only in intltest
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2009, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*   file name:  strtest.cpp
      7 *   encoding:   US-ASCII
      8 *   tab size:   8 (not used)
      9 *   indentation:4
     10 *
     11 *   created on: 1999nov22
     12 *   created by: Markus W. Scherer
     13 */
     14 
     15 #include "unicode/utypes.h"
     16 #include "unicode/putil.h"
     17 #include "intltest.h"
     18 #include "strtest.h"
     19 #include "unicode/ustring.h"
     20 #include "unicode/std_string.h"
     21 #include "unicode/stringpiece.h"
     22 #include <string.h>
     23 
     24 StringTest::~StringTest() {}
     25 
     26 void StringTest::TestEndian(void) {
     27     union {
     28         uint8_t byte;
     29         uint16_t word;
     30     } u;
     31     u.word=0x0100;
     32     if(U_IS_BIG_ENDIAN!=u.byte) {
     33         errln("TestEndian: U_IS_BIG_ENDIAN needs to be fixed in platform.h");
     34     }
     35 }
     36 
     37 void StringTest::TestSizeofTypes(void) {
     38     if(U_SIZEOF_WCHAR_T!=sizeof(wchar_t)) {
     39         errln("TestSizeofWCharT: U_SIZEOF_WCHAR_T!=sizeof(wchar_t) - U_SIZEOF_WCHAR_T needs to be fixed in platform.h");
     40     }
     41 #ifdef U_INT64_T_UNAVAILABLE
     42     errln("int64_t and uint64_t are undefined.");
     43 #else
     44     if(8!=sizeof(int64_t)) {
     45         errln("TestSizeofTypes: 8!=sizeof(int64_t) - int64_t needs to be fixed in platform.h");
     46     }
     47     if(8!=sizeof(uint64_t)) {
     48         errln("TestSizeofTypes: 8!=sizeof(uint64_t) - uint64_t needs to be fixed in platform.h");
     49     }
     50 #endif
     51     if(8!=sizeof(double)) {
     52         errln("8!=sizeof(double) - putil.c code may not work");
     53     }
     54     if(4!=sizeof(int32_t)) {
     55         errln("4!=sizeof(int32_t)");
     56     }
     57     if(4!=sizeof(uint32_t)) {
     58         errln("4!=sizeof(uint32_t)");
     59     }
     60     if(2!=sizeof(int16_t)) {
     61         errln("2!=sizeof(int16_t)");
     62     }
     63     if(2!=sizeof(uint16_t)) {
     64         errln("2!=sizeof(uint16_t)");
     65     }
     66     if(2!=sizeof(UChar)) {
     67         errln("2!=sizeof(UChar)");
     68     }
     69     if(1!=sizeof(int8_t)) {
     70         errln("1!=sizeof(int8_t)");
     71     }
     72     if(1!=sizeof(uint8_t)) {
     73         errln("1!=sizeof(uint8_t)");
     74     }
     75     if(1!=sizeof(UBool)) {
     76         errln("1!=sizeof(UBool)");
     77     }
     78 }
     79 
     80 void StringTest::TestCharsetFamily(void) {
     81     unsigned char c='A';
     82     if( U_CHARSET_FAMILY==U_ASCII_FAMILY && c!=0x41 ||
     83         U_CHARSET_FAMILY==U_EBCDIC_FAMILY && c!=0xc1
     84     ) {
     85         errln("TestCharsetFamily: U_CHARSET_FAMILY needs to be fixed in platform.h");
     86     }
     87 }
     88 
     89 U_STRING_DECL(ustringVar, "aZ0 -", 5);
     90 
     91 void StringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
     92     if(exec) {
     93         logln("TestSuite Character and String Test: ");
     94     }
     95     switch(index) {
     96     case 0:
     97         name="TestEndian";
     98         if(exec) {
     99             TestEndian();
    100         }
    101         break;
    102     case 1:
    103         name="TestSizeofTypes";
    104         if(exec) {
    105             TestSizeofTypes();
    106         }
    107         break;
    108     case 2:
    109         name="TestCharsetFamily";
    110         if(exec) {
    111             TestCharsetFamily();
    112         }
    113         break;
    114     case 3:
    115         name="Test_U_STRING";
    116         if(exec) {
    117             U_STRING_INIT(ustringVar, "aZ0 -", 5);
    118             if( sizeof(ustringVar)/sizeof(*ustringVar)!=6 ||
    119                 ustringVar[0]!=0x61 ||
    120                 ustringVar[1]!=0x5a ||
    121                 ustringVar[2]!=0x30 ||
    122                 ustringVar[3]!=0x20 ||
    123                 ustringVar[4]!=0x2d ||
    124                 ustringVar[5]!=0
    125             ) {
    126                 errln("Test_U_STRING: U_STRING_DECL with U_STRING_INIT does not work right! "
    127                       "See putil.h and utypes.h with platform.h.");
    128             }
    129         }
    130         break;
    131     case 4:
    132         name="Test_UNICODE_STRING";
    133         if(exec) {
    134             UnicodeString ustringVar=UNICODE_STRING("aZ0 -", 5);
    135             if( ustringVar.length()!=5 ||
    136                 ustringVar[0]!=0x61 ||
    137                 ustringVar[1]!=0x5a ||
    138                 ustringVar[2]!=0x30 ||
    139                 ustringVar[3]!=0x20 ||
    140                 ustringVar[4]!=0x2d
    141             ) {
    142                 errln("Test_UNICODE_STRING: UNICODE_STRING does not work right! "
    143                       "See unistr.h and utypes.h with platform.h.");
    144             }
    145         }
    146         break;
    147     case 5:
    148         name="Test_UNICODE_STRING_SIMPLE";
    149         if(exec) {
    150             UnicodeString ustringVar=UNICODE_STRING_SIMPLE("aZ0 -");
    151             if( ustringVar.length()!=5 ||
    152                 ustringVar[0]!=0x61 ||
    153                 ustringVar[1]!=0x5a ||
    154                 ustringVar[2]!=0x30 ||
    155                 ustringVar[3]!=0x20 ||
    156                 ustringVar[4]!=0x2d
    157             ) {
    158                 errln("Test_UNICODE_STRING_SIMPLE: UNICODE_STRING_SIMPLE does not work right! "
    159                       "See unistr.h and utypes.h with platform.h.");
    160             }
    161         }
    162         break;
    163     case 6:
    164         name="Test_UTF8_COUNT_TRAIL_BYTES";
    165         if(exec) {
    166             if(UTF8_COUNT_TRAIL_BYTES(0x7F) != 0
    167                 || UTF8_COUNT_TRAIL_BYTES(0xC0) != 1
    168                 || UTF8_COUNT_TRAIL_BYTES(0xE0) != 2
    169                 || UTF8_COUNT_TRAIL_BYTES(0xF0) != 3)
    170             {
    171                 errln("Test_UTF8_COUNT_TRAIL_BYTES: UTF8_COUNT_TRAIL_BYTES does not work right! "
    172                       "See utf8.h.");
    173             }
    174         }
    175         break;
    176     case 7:
    177         name="TestSTLCompatibility";
    178         if(exec) {
    179             TestSTLCompatibility();
    180         }
    181         break;
    182     case 8:
    183         name="TestStdNamespaceQualifier";
    184         if(exec) {
    185             TestStdNamespaceQualifier();
    186         }
    187         break;
    188     case 9:
    189         name="TestUsingStdNamespace";
    190         if(exec) {
    191             TestUsingStdNamespace();
    192         }
    193         break;
    194     case 10:
    195         name="TestStringPiece";
    196         if(exec) {
    197             TestStringPiece();
    198         }
    199         break;
    200     case 11:
    201         name="TestByteSink";
    202         if(exec) {
    203             TestByteSink();
    204         }
    205         break;
    206     case 12:
    207         name="TestCheckedArrayByteSink";
    208         if(exec) {
    209             TestCheckedArrayByteSink();
    210         }
    211         break;
    212     case 13:
    213         name="TestStringByteSink";
    214         if(exec) {
    215             TestStringByteSink();
    216         }
    217         break;
    218     default:
    219         name="";
    220         break;
    221     }
    222 }
    223 
    224 // Syntax check for the correct namespace qualifier for the standard string class.
    225 void
    226 StringTest::TestStdNamespaceQualifier() {
    227 #if U_HAVE_STD_STRING
    228     U_STD_NSQ string s="abc xyz";
    229     U_STD_NSQ string t="abc";
    230     t.append(" ");
    231     t.append("xyz");
    232     if(s!=t) {
    233         errln("standard string concatenation error: %s != %s", s.c_str(), t.c_str());
    234     }
    235 #endif
    236 }
    237 
    238 void
    239 StringTest::TestUsingStdNamespace() {
    240 #if U_HAVE_STD_STRING
    241     // Now test that "using namespace std;" is defined correctly.
    242     U_STD_NS_USE
    243 
    244     string s="abc xyz";
    245     string t="abc";
    246     t.append(" ");
    247     t.append("xyz");
    248     if(s!=t) {
    249         errln("standard string concatenation error: %s != %s", s.c_str(), t.c_str());
    250     }
    251 #endif
    252 }
    253 
    254 void
    255 StringTest::TestStringPiece() {
    256     // Default constructor.
    257     StringPiece empty;
    258     if(!empty.empty() || empty.data()!=NULL || empty.length()!=0 || empty.size()!=0) {
    259         errln("StringPiece() failed");
    260     }
    261     // Construct from NULL const char * pointer.
    262     StringPiece null(NULL);
    263     if(!null.empty() || null.data()!=NULL || null.length()!=0 || null.size()!=0) {
    264         errln("StringPiece(NULL) failed");
    265     }
    266     // Construct from const char * pointer.
    267     static const char *abc_chars="abc";
    268     StringPiece abc(abc_chars);
    269     if(abc.empty() || abc.data()!=abc_chars || abc.length()!=3 || abc.size()!=3) {
    270         errln("StringPiece(abc_chars) failed");
    271     }
    272     // Construct from const char * pointer and length.
    273     static const char *abcdefg_chars="abcdefg";
    274     StringPiece abcd(abcdefg_chars, 4);
    275     if(abcd.empty() || abcd.data()!=abcdefg_chars || abcd.length()!=4 || abcd.size()!=4) {
    276         errln("StringPiece(abcdefg_chars, 4) failed");
    277     }
    278 #if U_HAVE_STD_STRING
    279     // Construct from std::string.
    280     U_STD_NSQ string uvwxyz_string("uvwxyz");
    281     StringPiece uvwxyz(uvwxyz_string);
    282     if(uvwxyz.empty() || uvwxyz.data()!=uvwxyz_string.data() || uvwxyz.length()!=6 || uvwxyz.size()!=6) {
    283         errln("StringPiece(uvwxyz_string) failed");
    284     }
    285 #endif
    286     // Substring constructor with pos.
    287     StringPiece sp(abcd, -1);
    288     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    289         errln("StringPiece(abcd, -1) failed");
    290     }
    291     sp=StringPiece(abcd, 5);
    292     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    293         errln("StringPiece(abcd, 5) failed");
    294     }
    295     sp=StringPiece(abcd, 2);
    296     if(sp.empty() || sp.data()!=abcdefg_chars+2 || sp.length()!=2 || sp.size()!=2) {
    297         errln("StringPiece(abcd, -1) failed");
    298     }
    299     // Substring constructor with pos and len.
    300     sp=StringPiece(abcd, -1, 8);
    301     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    302         errln("StringPiece(abcd, -1, 8) failed");
    303     }
    304     sp=StringPiece(abcd, 5, 8);
    305     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    306         errln("StringPiece(abcd, 5, 8) failed");
    307     }
    308     sp=StringPiece(abcd, 2, 8);
    309     if(sp.empty() || sp.data()!=abcdefg_chars+2 || sp.length()!=2 || sp.size()!=2) {
    310         errln("StringPiece(abcd, -1) failed");
    311     }
    312     sp=StringPiece(abcd, 2, -1);
    313     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    314         errln("StringPiece(abcd, 5, -1) failed");
    315     }
    316     // static const npos
    317     const int32_t *ptr_npos=&StringPiece::npos;
    318     if(StringPiece::npos!=0x7fffffff || *ptr_npos!=0x7fffffff) {
    319         errln("StringPiece::npos!=0x7fffffff");
    320     }
    321     // substr() method with pos, using len=npos.
    322     sp=abcd.substr(-1);
    323     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    324         errln("abcd.substr(-1) failed");
    325     }
    326     sp=abcd.substr(5);
    327     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    328         errln("abcd.substr(5) failed");
    329     }
    330     sp=abcd.substr(2);
    331     if(sp.empty() || sp.data()!=abcdefg_chars+2 || sp.length()!=2 || sp.size()!=2) {
    332         errln("abcd.substr(-1) failed");
    333     }
    334     // substr() method with pos and len.
    335     sp=abcd.substr(-1, 8);
    336     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    337         errln("abcd.substr(-1, 8) failed");
    338     }
    339     sp=abcd.substr(5, 8);
    340     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    341         errln("abcd.substr(5, 8) failed");
    342     }
    343     sp=abcd.substr(2, 8);
    344     if(sp.empty() || sp.data()!=abcdefg_chars+2 || sp.length()!=2 || sp.size()!=2) {
    345         errln("abcd.substr(-1) failed");
    346     }
    347     sp=abcd.substr(2, -1);
    348     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    349         errln("abcd.substr(5, -1) failed");
    350     }
    351     // clear()
    352     sp=abcd;
    353     sp.clear();
    354     if(!sp.empty() || sp.data()!=NULL || sp.length()!=0 || sp.size()!=0) {
    355         errln("abcd.clear() failed");
    356     }
    357     // remove_prefix()
    358     sp=abcd;
    359     sp.remove_prefix(-1);
    360     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    361         errln("abcd.remove_prefix(-1) failed");
    362     }
    363     sp=abcd;
    364     sp.remove_prefix(2);
    365     if(sp.empty() || sp.data()!=abcdefg_chars+2 || sp.length()!=2 || sp.size()!=2) {
    366         errln("abcd.remove_prefix(2) failed");
    367     }
    368     sp=abcd;
    369     sp.remove_prefix(5);
    370     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    371         errln("abcd.remove_prefix(5) failed");
    372     }
    373     // remove_suffix()
    374     sp=abcd;
    375     sp.remove_suffix(-1);
    376     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
    377         errln("abcd.remove_suffix(-1) failed");
    378     }
    379     sp=abcd;
    380     sp.remove_suffix(2);
    381     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=2 || sp.size()!=2) {
    382         errln("abcd.remove_suffix(2) failed");
    383     }
    384     sp=abcd;
    385     sp.remove_suffix(5);
    386     if(!sp.empty() || sp.length()!=0 || sp.size()!=0) {
    387         errln("abcd.remove_suffix(5) failed");
    388     }
    389 }
    390 
    391 // Verify that ByteSink is subclassable and Flush() overridable.
    392 class SimpleByteSink : public ByteSink {
    393 public:
    394     SimpleByteSink(char *outbuf) : fOutbuf(outbuf), fLength(0) {}
    395     virtual void Append(const char *bytes, int32_t n) {
    396         if(fOutbuf != bytes) {
    397             memcpy(fOutbuf, bytes, n);
    398         }
    399         fOutbuf += n;
    400         fLength += n;
    401     }
    402     virtual void Flush() { Append("z", 1); }
    403     int32_t length() { return fLength; }
    404 private:
    405     char *fOutbuf;
    406     int32_t fLength;
    407 };
    408 
    409 // Test the ByteSink base class.
    410 void
    411 StringTest::TestByteSink() {
    412     char buffer[20];
    413     buffer[4] = '!';
    414     SimpleByteSink sink(buffer);
    415     sink.Append("abc", 3);
    416     sink.Flush();
    417     if(!(sink.length() == 4 && 0 == memcmp("abcz", buffer, 4) && buffer[4] == '!')) {
    418         errln("ByteSink (SimpleByteSink) did not Append() or Flush() as expected");
    419         return;
    420     }
    421     char scratch[20];
    422     int32_t capacity = -1;
    423     char *dest = sink.GetAppendBuffer(0, 50, scratch, (int32_t)sizeof(scratch), &capacity);
    424     if(dest != NULL || capacity != 0) {
    425         errln("ByteSink.GetAppendBuffer(min_capacity<1) did not properly return NULL[0]");
    426         return;
    427     }
    428     dest = sink.GetAppendBuffer(10, 50, scratch, 9, &capacity);
    429     if(dest != NULL || capacity != 0) {
    430         errln("ByteSink.GetAppendBuffer(scratch_capacity<min_capacity) did not properly return NULL[0]");
    431         return;
    432     }
    433     dest = sink.GetAppendBuffer(5, 50, scratch, (int32_t)sizeof(scratch), &capacity);
    434     if(dest != scratch || capacity != (int32_t)sizeof(scratch)) {
    435         errln("ByteSink.GetAppendBuffer() did not properly return the scratch buffer");
    436     }
    437 }
    438 
    439 void
    440 StringTest::TestCheckedArrayByteSink() {
    441     char buffer[20];  // < 26 for the test code to work
    442     buffer[3] = '!';
    443     CheckedArrayByteSink sink(buffer, (int32_t)sizeof(buffer));
    444     sink.Append("abc", 3);
    445     if(!(sink.NumberOfBytesWritten() == 3 && 0 == memcmp("abc", buffer, 3) && buffer[3] == '!')) {
    446         errln("CheckedArrayByteSink did not Append() as expected");
    447         return;
    448     }
    449     char scratch[10];
    450     int32_t capacity = -1;
    451     char *dest = sink.GetAppendBuffer(0, 50, scratch, (int32_t)sizeof(scratch), &capacity);
    452     if(dest != NULL || capacity != 0) {
    453         errln("CheckedArrayByteSink.GetAppendBuffer(min_capacity<1) did not properly return NULL[0]");
    454         return;
    455     }
    456     dest = sink.GetAppendBuffer(10, 50, scratch, 9, &capacity);
    457     if(dest != NULL || capacity != 0) {
    458         errln("CheckedArrayByteSink.GetAppendBuffer(scratch_capacity<min_capacity) did not properly return NULL[0]");
    459         return;
    460     }
    461     dest = sink.GetAppendBuffer(10, 50, scratch, (int32_t)sizeof(scratch), &capacity);
    462     if(dest != buffer + 3 || capacity != (int32_t)sizeof(buffer) - 3) {
    463         errln("CheckedArrayByteSink.GetAppendBuffer() did not properly return its own buffer");
    464         return;
    465     }
    466     memcpy(dest, "defghijklm", 10);
    467     sink.Append(dest, 10);
    468     if(!(sink.NumberOfBytesWritten() == 13 &&
    469          0 == memcmp("abcdefghijklm", buffer, 13) &&
    470          !sink.Overflowed())
    471     ) {
    472         errln("CheckedArrayByteSink did not Append(its own buffer) as expected");
    473         return;
    474     }
    475     dest = sink.GetAppendBuffer(10, 50, scratch, (int32_t)sizeof(scratch), &capacity);
    476     if(dest != scratch || capacity != (int32_t)sizeof(scratch)) {
    477         errln("CheckedArrayByteSink.GetAppendBuffer() did not properly return the scratch buffer");
    478     }
    479     memcpy(dest, "nopqrstuvw", 10);
    480     sink.Append(dest, 10);
    481     if(!(sink.NumberOfBytesWritten() == (int32_t)sizeof(buffer) &&
    482          0 == memcmp("abcdefghijklmnopqrstuvwxyz", buffer, (int32_t)sizeof(buffer)) &&
    483          sink.Overflowed())
    484     ) {
    485         errln("CheckedArrayByteSink did not Append(scratch buffer) as expected");
    486         return;
    487     }
    488 }
    489 
    490 void
    491 StringTest::TestStringByteSink() {
    492 #if U_HAVE_STD_STRING
    493     // Not much to test because only the constructor and Append()
    494     // are implemented, and trivially so.
    495     U_STD_NSQ string result("abc");  // std::string
    496     StringByteSink<U_STD_NSQ string> sink(&result);
    497     sink.Append("def", 3);
    498     if(result != "abcdef") {
    499         errln("StringByteSink did not Append() as expected");
    500     }
    501 #endif
    502 }
    503 
    504 #if defined(U_WINDOWS) && defined(_MSC_VER)
    505 #include <vector>
    506 #endif
    507 
    508 void
    509 StringTest::TestSTLCompatibility() {
    510 #if defined(U_WINDOWS) && defined(_MSC_VER)
    511     /* Just make sure that it compiles with STL's placement new usage. */
    512     std::vector<UnicodeString> myvect;
    513     myvect.push_back(UnicodeString("blah"));
    514 #endif
    515 }
    516