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