Changeset 33563 in vbox for trunk/src/VBox/Runtime/testcase/tstIprtMiniString.cpp
- Timestamp:
- Oct 28, 2010 2:46:26 PM (14 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/testcase/tstIprtMiniString.cpp
r33487 r33563 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT Testcase - UTF-8 and UTF-16 string conversions.3 * IPRT Testcase - iprt::MiniString. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 * Header Files * 29 29 *******************************************************************************/ 30 #include <iprt/cpp/ministring.h> 31 32 #include <iprt/err.h> 33 #include <iprt/mem.h> 30 34 #include <iprt/string.h> 35 #include <iprt/test.h> 31 36 #include <iprt/uni.h> 32 #include <iprt/initterm.h> 33 #include <iprt/uuid.h> 34 #include <iprt/time.h> 35 #include <iprt/stream.h> 36 #include <iprt/alloc.h> 37 #include <iprt/assert.h> 38 #include <iprt/err.h> 39 #include <iprt/test.h> 40 #include <iprt/cpp/ministring.h> 41 42 #include <stdlib.h> /** @todo use our random. */ 43 44 45 46 /** 47 * Generate a random codepoint for simple UTF-16 encoding. 48 */ 49 static RTUTF16 GetRandUtf16(void) 50 { 51 RTUTF16 wc; 52 do 53 { 54 wc = (RTUTF16)((long long)rand() * 0xffff / RAND_MAX); 55 } while ((wc >= 0xd800 && wc <= 0xdfff) || wc == 0); 56 return wc; 57 } 58 59 60 /** 61 * 62 */ 37 38 39 63 40 static void test1(RTTEST hTest) 64 41 { 65 static const char s_szBadString1[] = "Bad \xe0\x13\x0"; 66 static const char s_szBadString2[] = "Bad \xef\xbf\xc3"; 67 int rc; 68 char *pszUtf8; 69 char *pszCurrent; 70 PRTUTF16 pwsz; 71 PRTUTF16 pwszRand; 72 73 /* 74 * Invalid UTF-8 to UCS-2 test. 75 */ 76 RTTestSub(hTest, "Feeding bad UTF-8 to RTStrToUtf16"); 77 rc = RTStrToUtf16(s_szBadString1, &pwsz); 78 RTTEST_CHECK_MSG(hTest, rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING, 79 (hTest, "Conversion of first bad UTF-8 string to UTF-16 apparantly succeeded. It shouldn't. rc=%Rrc\n", rc)); 80 rc = RTStrToUtf16(s_szBadString2, &pwsz); 81 RTTEST_CHECK_MSG(hTest, rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING, 82 (hTest, "Conversion of second bad UTF-8 strings to UTF-16 apparantly succeeded. It shouldn't. rc=%Rrc\n", rc)); 83 84 /* 85 * Test current CP convertion. 86 */ 87 RTTestSub(hTest, "Rand UTF-16 -> UTF-8 -> CP -> UTF-8"); 88 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 89 srand((unsigned)RTTimeNanoTS()); 90 for (int i = 0; i < 30; i++) 91 pwszRand[i] = GetRandUtf16(); 92 pwszRand[30] = 0; 93 94 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8); 95 if (rc == VINF_SUCCESS) 96 { 97 rc = RTStrUtf8ToCurrentCP(&pszCurrent, pszUtf8); 98 if (rc == VINF_SUCCESS) 99 { 100 rc = RTStrCurrentCPToUtf8(&pszUtf8, pszCurrent); 101 if (rc == VINF_SUCCESS) 102 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> Current -> UTF-8 successful.\n"); 103 else 104 RTTestFailed(hTest, "%d: The third part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.", 105 __LINE__, rc); 106 } 107 else if (rc == VERR_NO_TRANSLATION) 108 RTTestPassed(hTest, "The second part of random UTF-16 -> UTF-8 -> Current -> UTF-8 returned VERR_NO_TRANSLATION. This is probably as it should be.\n"); 109 else 110 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.", 111 __LINE__, rc); 112 } 113 else 114 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.", 115 __LINE__, rc); 116 117 /* 118 * Generate a new random string. 119 */ 120 RTTestSub(hTest, "Random UTF-16 -> UTF-8 -> UTF-16"); 121 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 122 srand((unsigned)RTTimeNanoTS()); 123 for (int i = 0; i < 30; i++) 124 pwszRand[i] = GetRandUtf16(); 125 pwszRand[30] = 0; 126 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8); 127 if (rc == VINF_SUCCESS) 128 { 129 rc = RTStrToUtf16(pszUtf8, &pwsz); 130 if (rc == VINF_SUCCESS) 131 { 132 int i; 133 for (i = 0; pwszRand[i] == pwsz[i] && pwsz[i] != 0; i++) 134 /* nothing */; 135 if (pwszRand[i] == pwsz[i] && pwsz[i] == 0) 136 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> UTF-16 successful.\n"); 137 else 138 { 139 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> UTF-16 failed.", __LINE__); 140 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz[i]); 141 } 142 } 143 else 144 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> UTF-16 failed with return value %Rrc.", 145 __LINE__, rc); 146 } 147 else 148 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> UTF-16 failed with return value %Rrc.", 149 __LINE__, rc); 150 151 /* 152 * Generate yet another random string and convert it to a buffer. 153 */ 154 RTTestSub(hTest, "Random RTUtf16ToUtf8Ex + RTStrToUtf16"); 155 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 156 srand((unsigned)RTTimeNanoTS()); 157 for (int i = 0; i < 30; i++) 158 pwszRand[i] = GetRandUtf16(); 159 pwszRand[30] = 0; 160 161 char szUtf8Array[120]; 162 char *pszUtf8Array = szUtf8Array; 163 rc = RTUtf16ToUtf8Ex(pwszRand, RTSTR_MAX, &pszUtf8Array, 120, NULL); 164 if (rc == 0) 165 { 166 rc = RTStrToUtf16(pszUtf8Array, &pwsz); 167 if (rc == 0) 168 { 169 int i; 170 for (i = 0; pwszRand[i] == pwsz[i] && pwsz[i] != 0; i++) 171 ; 172 if (pwsz[i] == 0 && i >= 8) 173 RTTestPassed(hTest, "Random UTF-16 -> fixed length UTF-8 -> UTF-16 successful.\n"); 174 else 175 { 176 RTTestFailed(hTest, "%d: Incorrect conversion of UTF-16 -> fixed length UTF-8 -> UTF-16.\n", __LINE__); 177 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz[i]); 178 } 179 } 180 else 181 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> fixed length UTF-8 -> UTF-16 failed with return value %Rrc.\n", __LINE__, rc); 182 } 183 else 184 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> fixed length UTF-8 -> UTF-16 failed with return value %Rrc.\n", __LINE__, rc); 185 186 /* 187 * And again. 188 */ 189 RTTestSub(hTest, "Random RTUtf16ToUtf8 + RTStrToUtf16Ex"); 190 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 191 srand((unsigned)RTTimeNanoTS()); 192 for (int i = 0; i < 30; i++) 193 pwszRand[i] = GetRandUtf16(); 194 pwszRand[30] = 0; 195 196 RTUTF16 wszBuf[70]; 197 PRTUTF16 pwsz2Buf = wszBuf; 198 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8); 199 if (rc == 0) 200 { 201 rc = RTStrToUtf16Ex(pszUtf8, RTSTR_MAX, &pwsz2Buf, 70, NULL); 202 if (rc == 0) 203 { 204 int i; 205 for (i = 0; pwszRand[i] == pwsz2Buf[i] && pwsz2Buf[i] != 0; i++) 206 ; 207 if (pwszRand[i] == 0 && pwsz2Buf[i] == 0) 208 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> fixed length UTF-16 successful.\n"); 209 else 210 { 211 RTTestFailed(hTest, "%d: Incorrect conversion of random UTF-16 -> UTF-8 -> fixed length UTF-16.\n", __LINE__); 212 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz2Buf[i]); 213 } 214 } 215 else 216 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n", __LINE__, rc); 217 } 218 else 219 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n", 220 __LINE__, rc); 221 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 222 srand((unsigned)RTTimeNanoTS()); 223 for (int i = 0; i < 30; i++) 224 pwszRand[i] = GetRandUtf16(); 225 pwszRand[30] = 0; 226 227 rc = RTUtf16ToUtf8Ex(pwszRand, RTSTR_MAX, &pszUtf8Array, 20, NULL); 228 if (rc == VERR_BUFFER_OVERFLOW) 229 RTTestPassed(hTest, "Random UTF-16 -> fixed length UTF-8 with too short buffer successfully rejected.\n"); 230 else 231 RTTestFailed(hTest, "%d: Random UTF-16 -> fixed length UTF-8 with too small buffer returned value %d instead of VERR_BUFFER_OVERFLOW.\n", 232 __LINE__, rc); 233 234 /* 235 * last time... 236 */ 237 RTTestSub(hTest, "Random RTUtf16ToUtf8 + RTStrToUtf16Ex"); 238 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz)); 239 srand((unsigned)RTTimeNanoTS()); 240 for (int i = 0; i < 30; i++) 241 pwszRand[i] = GetRandUtf16(); 242 pwszRand[30] = 0; 243 244 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8); 245 if (rc == VINF_SUCCESS) 246 { 247 rc = RTStrToUtf16Ex(pszUtf8, RTSTR_MAX, &pwsz2Buf, 20, NULL); 248 if (rc == VERR_BUFFER_OVERFLOW) 249 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> fixed length UTF-16 with too short buffer successfully rejected.\n"); 250 else 251 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> fixed length UTF-16 with too short buffer returned value %Rrc instead of VERR_BUFFER_OVERFLOW.\n", 252 __LINE__, rc); 253 } 254 else 255 RTTestFailed(hTest, "%d:The first part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n", 256 __LINE__, rc); 257 258 259 RTTestSubDone(hTest); 260 } 261 262 263 static RTUNICP g_uszAll[0x110000 - 1 - 0x800 - 2 + 1]; 264 static RTUTF16 g_wszAll[0xfffe - (0xe000 - 0xd800) + (0x110000 - 0x10000) * 2]; 265 static char g_szAll[0x7f + (0x800 - 0x80) * 2 + (0xfffe - 0x800 - (0xe000 - 0xd800))* 3 + (0x110000 - 0x10000) * 4 + 1]; 266 267 static void whereami(int cBits, size_t off) 268 { 269 if (cBits == 8) 270 { 271 if (off < 0x7f) 272 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", off + 1); 273 else if (off < 0xf7f) 274 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x7f) / 2 + 0x80); 275 else if (off < 0x27f7f) 276 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0xf7f) / 3 + 0x800); 277 else if (off < 0x2df79) 278 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x27f7f) / 3 + 0xe000); 279 else if (off < 0x42df79) 280 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x2df79) / 4 + 0x10000); 281 else 282 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 ???\n"); 283 } 284 else if (cBits == 16) 285 { 286 if (off < 0xd7ff*2) 287 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", off / 2 + 1); 288 else if (off < 0xf7fd*2) 289 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", (off - 0xd7ff*2) / 2 + 0xe000); 290 else if (off < 0x20f7fd) 291 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", (off - 0xf7fd*2) / 4 + 0x10000); 292 else 293 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 ???\n"); 294 } 295 else 296 { 297 if (off < (0xd800 - 1) * sizeof(RTUNICP)) 298 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 1); 299 else if (off < (0xfffe - 0x800 - 1) * sizeof(RTUNICP)) 300 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 0x800 + 1); 301 else 302 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 0x800 + 1 + 2); 303 } 304 } 305 306 int mymemcmp(const void *pv1, const void *pv2, size_t cb, int cBits) 307 { 308 const uint8_t *pb1 = (const uint8_t *)pv1; 309 const uint8_t *pb2 = (const uint8_t *)pv2; 310 for (size_t off = 0; off < cb; off++) 311 { 312 if (pb1[off] != pb2[off]) 313 { 314 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "mismatch at %#x: ", off); 315 whereami(cBits, off); 316 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off-1, pb1[off-1], pb2[off-1]); 317 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "*%#x: %02x != %02x!\n", off, pb1[off], pb2[off]); 318 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+1, pb1[off+1], pb2[off+1]); 319 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+2, pb1[off+2], pb2[off+2]); 320 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+3, pb1[off+3], pb2[off+3]); 321 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+4, pb1[off+4], pb2[off+4]); 322 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+5, pb1[off+5], pb2[off+5]); 323 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+6, pb1[off+6], pb2[off+6]); 324 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+7, pb1[off+7], pb2[off+7]); 325 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+8, pb1[off+8], pb2[off+8]); 326 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+9, pb1[off+9], pb2[off+9]); 327 return 1; 328 } 329 } 330 return 0; 331 } 332 333 334 void InitStrings() 335 { 336 /* 337 * Generate unicode string containing all the legal UTF-16 codepoints, both UTF-16 and UTF-8 version. 338 */ 339 /* the simple code point array first */ 340 unsigned i = 0; 341 RTUNICP uc = 1; 342 while (uc < 0xd800) 343 g_uszAll[i++] = uc++; 344 uc = 0xe000; 345 while (uc < 0xfffe) 346 g_uszAll[i++] = uc++; 347 uc = 0x10000; 348 while (uc < 0x110000) 349 g_uszAll[i++] = uc++; 350 g_uszAll[i++] = 0; 351 Assert(RT_ELEMENTS(g_uszAll) == i); 352 353 /* the utf-16 one */ 354 i = 0; 355 uc = 1; 356 //RTPrintf("tstUtf8: %#x=%#x", i, uc); 357 while (uc < 0xd800) 358 g_wszAll[i++] = uc++; 359 uc = 0xe000; 360 //RTPrintf(" %#x=%#x", i, uc); 361 while (uc < 0xfffe) 362 g_wszAll[i++] = uc++; 363 uc = 0x10000; 364 //RTPrintf(" %#x=%#x", i, uc); 365 while (uc < 0x110000) 366 { 367 g_wszAll[i++] = 0xd800 | ((uc - 0x10000) >> 10); 368 g_wszAll[i++] = 0xdc00 | ((uc - 0x10000) & 0x3ff); 369 uc++; 370 } 371 //RTPrintf(" %#x=%#x\n", i, uc); 372 g_wszAll[i++] = '\0'; 373 Assert(RT_ELEMENTS(g_wszAll) == i); 374 375 /* 376 * The utf-8 one 377 */ 378 i = 0; 379 uc = 1; 380 //RTPrintf("tstUtf8: %#x=%#x", i, uc); 381 while (uc < 0x80) 382 g_szAll[i++] = uc++; 383 //RTPrintf(" %#x=%#x", i, uc); 384 while (uc < 0x800) 385 { 386 g_szAll[i++] = 0xc0 | (uc >> 6); 387 g_szAll[i++] = 0x80 | (uc & 0x3f); 388 Assert(!((uc >> 6) & ~0x1f)); 389 uc++; 390 } 391 //RTPrintf(" %#x=%#x", i, uc); 392 while (uc < 0xd800) 393 { 394 g_szAll[i++] = 0xe0 | (uc >> 12); 395 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f); 396 g_szAll[i++] = 0x80 | (uc & 0x3f); 397 Assert(!((uc >> 12) & ~0xf)); 398 uc++; 399 } 400 uc = 0xe000; 401 //RTPrintf(" %#x=%#x", i, uc); 402 while (uc < 0xfffe) 403 { 404 g_szAll[i++] = 0xe0 | (uc >> 12); 405 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f); 406 g_szAll[i++] = 0x80 | (uc & 0x3f); 407 Assert(!((uc >> 12) & ~0xf)); 408 uc++; 409 } 410 uc = 0x10000; 411 //RTPrintf(" %#x=%#x", i, uc); 412 while (uc < 0x110000) 413 { 414 g_szAll[i++] = 0xf0 | (uc >> 18); 415 g_szAll[i++] = 0x80 | ((uc >> 12) & 0x3f); 416 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f); 417 g_szAll[i++] = 0x80 | (uc & 0x3f); 418 Assert(!((uc >> 18) & ~0x7)); 419 uc++; 420 } 421 //RTPrintf(" %#x=%#x\n", i, uc); 422 g_szAll[i++] = '\0'; 423 Assert(RT_ELEMENTS(g_szAll) == i); 424 } 425 426 427 void test2(RTTEST hTest) 428 { 429 /* 430 * Convert to UTF-8 and back. 431 */ 432 RTTestSub(hTest, "UTF-16 -> UTF-8 -> UTF-16"); 433 char *pszUtf8; 434 int rc = RTUtf16ToUtf8(&g_wszAll[0], &pszUtf8); 435 if (rc == VINF_SUCCESS) 436 { 437 if (mymemcmp(pszUtf8, g_szAll, sizeof(g_szAll), 8)) 438 RTTestFailed(hTest, "UTF-16 -> UTF-8 mismatch!"); 439 440 PRTUTF16 pwszUtf16; 441 rc = RTStrToUtf16(pszUtf8, &pwszUtf16); 442 if (rc == VINF_SUCCESS) 443 { 444 if (mymemcmp(pwszUtf16, g_wszAll, sizeof(g_wszAll), 16)) 445 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed compare!"); 446 RTUtf16Free(pwszUtf16); 447 } 448 else 449 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc); 450 RTStrFree(pszUtf8); 451 } 452 else 453 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed, rc=%Rrc.", rc); 454 455 456 /* 457 * Convert to UTF-16 and back. (just in case the above test fails) 458 */ 459 RTTestSub(hTest, "UTF-8 -> UTF-16 -> UTF-8"); 460 PRTUTF16 pwszUtf16; 461 rc = RTStrToUtf16(&g_szAll[0], &pwszUtf16); 462 if (rc == VINF_SUCCESS) 463 { 464 if (mymemcmp(pwszUtf16, g_wszAll, sizeof(g_wszAll), 16)) 465 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed compare!"); 466 467 rc = RTUtf16ToUtf8(pwszUtf16, &pszUtf8); 468 if (rc == VINF_SUCCESS) 469 { 470 if (mymemcmp(pszUtf8, g_szAll, sizeof(g_szAll), 8)) 471 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed compare!"); 472 RTStrFree(pszUtf8); 473 } 474 else 475 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed, rc=%Rrc.", rc); 476 RTUtf16Free(pwszUtf16); 477 } 478 else 479 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc); 480 481 /* 482 * Convert UTF-8 to CPs. 483 */ 484 RTTestSub(hTest, "UTF-8 -> UNI -> UTF-8"); 485 PRTUNICP paCps; 486 rc = RTStrToUni(g_szAll, &paCps); 487 if (rc == VINF_SUCCESS) 488 { 489 if (mymemcmp(paCps, g_uszAll, sizeof(g_uszAll), 32)) 490 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc); 491 492 size_t cCps; 493 rc = RTStrToUniEx(g_szAll, RTSTR_MAX, &paCps, RT_ELEMENTS(g_uszAll), &cCps); 494 if (rc == VINF_SUCCESS) 495 { 496 if (cCps != RT_ELEMENTS(g_uszAll) - 1) 497 RTTestFailed(hTest, "wrong Code Point count %zu, expected %zu\n", cCps, RT_ELEMENTS(g_uszAll) - 1); 498 } 499 else 500 RTTestFailed(hTest, "UTF-8 -> Code Points failed, rc=%Rrc.\n", rc); 501 502 /** @todo RTCpsToUtf8 or something. */ 503 } 504 else 505 RTTestFailed(hTest, "UTF-8 -> Code Points failed, rc=%Rrc.\n", rc); 506 507 /* 508 * Check the various string lengths. 509 */ 510 RTTestSub(hTest, "Lengths"); 511 size_t cuc1 = RTStrCalcUtf16Len(g_szAll); 512 size_t cuc2 = RTUtf16Len(g_wszAll); 513 if (cuc1 != cuc2) 514 RTTestFailed(hTest, "cuc1=%zu != cuc2=%zu\n", cuc1, cuc2); 515 //size_t cuc3 = RTUniLen(g_uszAll); 516 517 518 /* 519 * Enumerate the strings. 520 */ 521 RTTestSub(hTest, "Code Point Getters and Putters"); 522 char *pszPut1Base = (char *)RTMemAlloc(sizeof(g_szAll)); 523 AssertRelease(pszPut1Base); 524 char *pszPut1 = pszPut1Base; 525 PRTUTF16 pwszPut2Base = (PRTUTF16)RTMemAlloc(sizeof(g_wszAll)); 526 AssertRelease(pwszPut2Base); 527 PRTUTF16 pwszPut2 = pwszPut2Base; 528 const char *psz1 = g_szAll; 529 const char *psz2 = g_szAll; 530 PCRTUTF16 pwsz3 = g_wszAll; 531 PCRTUTF16 pwsz4 = g_wszAll; 532 for (;;) 533 { 534 /* 535 * getters 536 */ 537 RTUNICP uc1; 538 rc = RTStrGetCpEx(&psz1, &uc1); 539 if (RT_FAILURE(rc)) 540 { 541 RTTestFailed(hTest, "RTStrGetCpEx failed with rc=%Rrc at %.10Rhxs", rc, psz2); 542 whereami(8, psz2 - &g_szAll[0]); 543 break; 544 } 545 char *pszPrev1 = RTStrPrevCp(g_szAll, psz1); 546 if (pszPrev1 != psz2) 547 { 548 RTTestFailed(hTest, "RTStrPrevCp returned %p expected %p!", pszPrev1, psz2); 549 whereami(8, psz2 - &g_szAll[0]); 550 break; 551 } 552 RTUNICP uc2 = RTStrGetCp(psz2); 553 if (uc2 != uc1) 554 { 555 RTTestFailed(hTest, "RTStrGetCpEx and RTStrGetCp returned different CPs: %RTunicp != %RTunicp", uc2, uc1); 556 whereami(8, psz2 - &g_szAll[0]); 557 break; 558 } 559 psz2 = RTStrNextCp(psz2); 560 if (psz2 != psz1) 561 { 562 RTTestFailed(hTest, "RTStrGetCpEx and RTStrGetNext returned different next pointer!"); 563 whereami(8, psz2 - &g_szAll[0]); 564 break; 565 } 566 567 RTUNICP uc3; 568 rc = RTUtf16GetCpEx(&pwsz3, &uc3); 569 if (RT_FAILURE(rc)) 570 { 571 RTTestFailed(hTest, "RTUtf16GetCpEx failed with rc=%Rrc at %.10Rhxs", rc, pwsz4); 572 whereami(16, pwsz4 - &g_wszAll[0]); 573 break; 574 } 575 if (uc3 != uc2) 576 { 577 RTTestFailed(hTest, "RTUtf16GetCpEx and RTStrGetCp returned different CPs: %RTunicp != %RTunicp", uc3, uc2); 578 whereami(16, pwsz4 - &g_wszAll[0]); 579 break; 580 } 581 RTUNICP uc4 = RTUtf16GetCp(pwsz4); 582 if (uc3 != uc4) 583 { 584 RTTestFailed(hTest, "RTUtf16GetCpEx and RTUtf16GetCp returned different CPs: %RTunicp != %RTunicp", uc3, uc4); 585 whereami(16, pwsz4 - &g_wszAll[0]); 586 break; 587 } 588 pwsz4 = RTUtf16NextCp(pwsz4); 589 if (pwsz4 != pwsz3) 590 { 591 RTTestFailed(hTest, "RTUtf16GetCpEx and RTUtf16GetNext returned different next pointer!"); 592 whereami(8, pwsz4 - &g_wszAll[0]); 593 break; 594 } 595 596 597 /* 598 * putters 599 */ 600 pszPut1 = RTStrPutCp(pszPut1, uc1); 601 if (pszPut1 - pszPut1Base != psz1 - &g_szAll[0]) 602 { 603 RTTestFailed(hTest, "RTStrPutCp is not at the same offset! %p != %p", 604 pszPut1 - pszPut1Base, psz1 - &g_szAll[0]); 605 whereami(8, psz2 - &g_szAll[0]); 606 break; 607 } 608 609 pwszPut2 = RTUtf16PutCp(pwszPut2, uc3); 610 if (pwszPut2 - pwszPut2Base != pwsz3 - &g_wszAll[0]) 611 { 612 RTTestFailed(hTest, "RTStrPutCp is not at the same offset! %p != %p", 613 pwszPut2 - pwszPut2Base, pwsz3 - &g_wszAll[0]); 614 whereami(8, pwsz4 - &g_wszAll[0]); 615 break; 616 } 617 618 619 /* the end? */ 620 if (!uc1) 621 break; 622 } 623 624 /* check output if we seems to have made it thru it all. */ 625 if (psz2 == &g_szAll[sizeof(g_szAll)]) 626 { 627 if (mymemcmp(pszPut1Base, g_szAll, sizeof(g_szAll), 8)) 628 RTTestFailed(hTest, "RTStrPutCp encoded the string incorrectly."); 629 if (mymemcmp(pwszPut2Base, g_wszAll, sizeof(g_wszAll), 16)) 630 RTTestFailed(hTest, "RTUtf16PutCp encoded the string incorrectly."); 631 } 632 633 RTMemFree(pszPut1Base); 634 RTMemFree(pwszPut2Base); 635 636 RTTestSubDone(hTest); 637 } 638 639 640 /** 641 * Check case insensitivity. 642 */ 643 void test3(RTTEST hTest) 644 { 645 RTTestSub(hTest, "Case Sensitivitity"); 646 647 if ( RTUniCpToLower('a') != 'a' 648 || RTUniCpToLower('A') != 'a' 649 || RTUniCpToLower('b') != 'b' 650 || RTUniCpToLower('B') != 'b' 651 || RTUniCpToLower('Z') != 'z' 652 || RTUniCpToLower('z') != 'z' 653 || RTUniCpToUpper('c') != 'C' 654 || RTUniCpToUpper('C') != 'C' 655 || RTUniCpToUpper('z') != 'Z' 656 || RTUniCpToUpper('Z') != 'Z') 657 RTTestFailed(hTest, "RTUniToUpper/Lower failed basic tests.\n"); 658 659 if (RTUtf16ICmp(g_wszAll, g_wszAll)) 660 RTTestFailed(hTest, "RTUtf16ICmp failed the basic test.\n"); 661 662 if (RTUtf16Cmp(g_wszAll, g_wszAll)) 663 RTTestFailed(hTest, "RTUtf16Cmp failed the basic test.\n"); 664 665 static RTUTF16 s_wszTst1a[] = { 'a', 'B', 'c', 'D', 'E', 'f', 'g', 'h', 'i', 'j', 'K', 'L', 'm', 'N', 'o', 'P', 'q', 'r', 'S', 't', 'u', 'V', 'w', 'x', 'Y', 'Z', 0xc5, 0xc6, 0xf8, 0 }; 666 static RTUTF16 s_wszTst1b[] = { 'A', 'B', 'c', 'd', 'e', 'F', 'G', 'h', 'i', 'J', 'k', 'l', 'M', 'n', 'O', 'p', 'Q', 'R', 's', 't', 'U', 'v', 'w', 'X', 'y', 'z', 0xe5, 0xe6, 0xd8, 0 }; 667 if ( RTUtf16ICmp(s_wszTst1b, s_wszTst1b) 668 || RTUtf16ICmp(s_wszTst1a, s_wszTst1a) 669 || RTUtf16ICmp(s_wszTst1a, s_wszTst1b) 670 || RTUtf16ICmp(s_wszTst1b, s_wszTst1a) 671 ) 672 RTTestFailed(hTest, "RTUtf16ICmp failed the alphabet test.\n"); 673 674 if ( RTUtf16Cmp(s_wszTst1b, s_wszTst1b) 675 || RTUtf16Cmp(s_wszTst1a, s_wszTst1a) 676 || !RTUtf16Cmp(s_wszTst1a, s_wszTst1b) 677 || !RTUtf16Cmp(s_wszTst1b, s_wszTst1a) 678 ) 679 RTTestFailed(hTest, "RTUtf16Cmp failed the alphabet test.\n"); 680 681 RTTestSubDone(hTest); 682 } 683 684 685 /** 686 * Test the RTStr*Cmp functions. 687 */ 688 void TstRTStrXCmp(RTTEST hTest) 689 { 690 #define CHECK_DIFF(expr, op) \ 691 do \ 692 { \ 693 int iDiff = expr; \ 694 if (!(iDiff op 0)) \ 695 RTTestFailed(hTest, "%d: %d " #op " 0: %s\n", __LINE__, iDiff, #expr); \ 696 } while (0) 697 698 /** @todo test the non-ascii bits. */ 699 700 RTTestSub(hTest, "RTStrCmp"); 701 CHECK_DIFF(RTStrCmp(NULL, NULL), == ); 702 CHECK_DIFF(RTStrCmp(NULL, ""), < ); 703 CHECK_DIFF(RTStrCmp("", NULL), > ); 704 CHECK_DIFF(RTStrCmp("", ""), == ); 705 CHECK_DIFF(RTStrCmp("abcdef", "abcdef"), == ); 706 CHECK_DIFF(RTStrCmp("abcdef", "abcde"), > ); 707 CHECK_DIFF(RTStrCmp("abcde", "abcdef"), < ); 708 CHECK_DIFF(RTStrCmp("abcdeg", "abcdef"), > ); 709 CHECK_DIFF(RTStrCmp("abcdef", "abcdeg"), < ); 710 CHECK_DIFF(RTStrCmp("abcdeF", "abcdef"), < ); 711 CHECK_DIFF(RTStrCmp("abcdef", "abcdeF"), > ); 712 713 714 RTTestSub(hTest, "RTStrNCmp"); 715 CHECK_DIFF(RTStrNCmp(NULL, NULL, RTSTR_MAX), == ); 716 CHECK_DIFF(RTStrNCmp(NULL, "", RTSTR_MAX), < ); 717 CHECK_DIFF(RTStrNCmp("", NULL, RTSTR_MAX), > ); 718 CHECK_DIFF(RTStrNCmp("", "", RTSTR_MAX), == ); 719 CHECK_DIFF(RTStrNCmp("abcdef", "abcdef", RTSTR_MAX), == ); 720 CHECK_DIFF(RTStrNCmp("abcdef", "abcde", RTSTR_MAX), > ); 721 CHECK_DIFF(RTStrNCmp("abcde", "abcdef", RTSTR_MAX), < ); 722 CHECK_DIFF(RTStrNCmp("abcdeg", "abcdef", RTSTR_MAX), > ); 723 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeg", RTSTR_MAX), < ); 724 CHECK_DIFF(RTStrNCmp("abcdeF", "abcdef", RTSTR_MAX), < ); 725 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", RTSTR_MAX), > ); 726 727 CHECK_DIFF(RTStrNCmp("abcdef", "fedcba", 0), ==); 728 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", 5), ==); 729 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", 6), > ); 730 731 732 RTTestSub(hTest, "RTStrICmp"); 733 CHECK_DIFF(RTStrICmp(NULL, NULL), == ); 734 CHECK_DIFF(RTStrICmp(NULL, ""), < ); 735 CHECK_DIFF(RTStrICmp("", NULL), > ); 736 CHECK_DIFF(RTStrICmp("", ""), == ); 737 CHECK_DIFF(RTStrICmp("abcdef", "abcdef"), == ); 738 CHECK_DIFF(RTStrICmp("abcdef", "abcde"), > ); 739 CHECK_DIFF(RTStrICmp("abcde", "abcdef"), < ); 740 CHECK_DIFF(RTStrICmp("abcdeg", "abcdef"), > ); 741 CHECK_DIFF(RTStrICmp("abcdef", "abcdeg"), < ); 742 743 CHECK_DIFF(RTStrICmp("abcdeF", "abcdef"), ==); 744 CHECK_DIFF(RTStrICmp("abcdef", "abcdeF"), ==); 745 CHECK_DIFF(RTStrICmp("ABCDEF", "abcdef"), ==); 746 CHECK_DIFF(RTStrICmp("abcdef", "ABCDEF"), ==); 747 CHECK_DIFF(RTStrICmp("AbCdEf", "aBcDeF"), ==); 748 CHECK_DIFF(RTStrICmp("AbCdEg", "aBcDeF"), > ); 749 CHECK_DIFF(RTStrICmp("AbCdEG", "aBcDef"), > ); /* diff performed on the lower case cp. */ 750 751 752 753 RTTestSub(hTest, "RTStrNICmp"); 754 CHECK_DIFF(RTStrNICmp(NULL, NULL, RTSTR_MAX), == ); 755 CHECK_DIFF(RTStrNICmp(NULL, "", RTSTR_MAX), < ); 756 CHECK_DIFF(RTStrNICmp("", NULL, RTSTR_MAX), > ); 757 CHECK_DIFF(RTStrNICmp("", "", RTSTR_MAX), == ); 758 CHECK_DIFF(RTStrNICmp(NULL, NULL, 0), == ); 759 CHECK_DIFF(RTStrNICmp(NULL, "", 0), == ); 760 CHECK_DIFF(RTStrNICmp("", NULL, 0), == ); 761 CHECK_DIFF(RTStrNICmp("", "", 0), == ); 762 CHECK_DIFF(RTStrNICmp("abcdef", "abcdef", RTSTR_MAX), == ); 763 CHECK_DIFF(RTStrNICmp("abcdef", "abcde", RTSTR_MAX), > ); 764 CHECK_DIFF(RTStrNICmp("abcde", "abcdef", RTSTR_MAX), < ); 765 CHECK_DIFF(RTStrNICmp("abcdeg", "abcdef", RTSTR_MAX), > ); 766 CHECK_DIFF(RTStrNICmp("abcdef", "abcdeg", RTSTR_MAX), < ); 767 768 CHECK_DIFF(RTStrNICmp("abcdeF", "abcdef", RTSTR_MAX), ==); 769 CHECK_DIFF(RTStrNICmp("abcdef", "abcdeF", RTSTR_MAX), ==); 770 CHECK_DIFF(RTStrNICmp("ABCDEF", "abcdef", RTSTR_MAX), ==); 771 CHECK_DIFF(RTStrNICmp("abcdef", "ABCDEF", RTSTR_MAX), ==); 772 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDeF", RTSTR_MAX), ==); 773 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", RTSTR_MAX), > ); 774 CHECK_DIFF(RTStrNICmp("AbCdEG", "aBcDef", RTSTR_MAX), > ); /* diff performed on the lower case cp. */ 775 776 CHECK_DIFF(RTStrNICmp("ABCDEF", "fedcba", 0), ==); 777 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", 5), ==); 778 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDeF", 5), ==); 779 CHECK_DIFF(RTStrNICmp("AbCdE", "aBcDe", 5), ==); 780 CHECK_DIFF(RTStrNICmp("AbCdE", "aBcDeF", 5), ==); 781 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDe", 5), ==); 782 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", 6), > ); 783 CHECK_DIFF(RTStrNICmp("AbCdEG", "aBcDef", 6), > ); /* diff performed on the lower case cp. */ 784 /* We should continue using byte comparison when we hit the invalid CP. Will assert in debug builds. */ 785 // CHECK_DIFF(RTStrNICmp("AbCd\xff""eg", "aBcD\xff""eF", 6), ==); 786 787 RTTestSubDone(hTest); 788 } 789 790 791 792 /** 793 * Check case insensitivity. 794 */ 795 void TstRTStrPurgeEncoding(RTTEST hTest) 796 { 797 RTTestSub(hTest, "RTStrPurgeEncoding"); 798 799 /* 800 * Test some good strings. 801 */ 802 char sz1[] = "1234567890wertyuiopsdfghjklzxcvbnm"; 803 char sz1Copy[sizeof(sz1)]; 804 memcpy(sz1Copy, sz1, sizeof(sz1)); 805 806 RTTESTI_CHECK_RETV(RTStrPurgeEncoding(sz1) == 0); 807 RTTESTI_CHECK_RETV(!memcmp(sz1, sz1Copy, sizeof(sz1))); 808 809 char *pszAll = RTStrDup(g_szAll); 810 if (pszAll) 811 { 812 RTTESTI_CHECK(RTStrPurgeEncoding(pszAll) == 0); 813 RTTESTI_CHECK(!memcmp(pszAll, g_szAll, sizeof(g_szAll))); 814 RTStrFree(pszAll); 815 } 816 817 /* 818 * Test some bad stuff. 819 */ 820 struct 821 { 822 size_t cErrors; 823 unsigned char szIn[5]; 824 const char *pszExpect; 825 } aTests[] = 826 { 827 { 0, { '1', '2', '3', '4', '\0' }, "1234" }, 828 { 1, { 0x80, '2', '3', '4', '\0' }, "?234" }, 829 { 1, { '1', 0x80, '3', '4', '\0' }, "1?34" }, 830 { 1, { '1', '2', 0x80, '4', '\0' }, "12?4" }, 831 { 1, { '1', '2', '3', 0x80, '\0' }, "123?" }, 832 { 2, { 0x80, 0x81, '3', '4', '\0' }, "??34" }, 833 { 2, { '1', 0x80, 0x81, '4', '\0' }, "1??4" }, 834 { 2, { '1', '2', 0x80, 0x81, '\0' }, "12??" }, 835 }; 836 for (size_t i = 0; i < RT_ELEMENTS(aTests); i++) 837 { 838 size_t cErrors = RTStrPurgeEncoding((char *)aTests[i].szIn); 839 if (cErrors != aTests[i].cErrors) 840 RTTestFailed(hTest, "#%u: cErrors=%u expected %u\n", i, cErrors, aTests[i].cErrors); 841 else if (strcmp((char *)aTests[i].szIn, aTests[i].pszExpect)) 842 RTTestFailed(hTest, "#%u: %.5Rhxs expected %.5Rhxs (%s)\n", i, aTests[i].szIn, aTests[i].pszExpect, aTests[i].pszExpect); 843 } 844 845 RTTestSubDone(hTest); 846 } 847 848 849 /** 850 * Benchmark stuff. 851 */ 852 void Benchmarks(RTTEST hTest) 853 { 854 static union 855 { 856 RTUTF16 wszBuf[sizeof(g_wszAll)]; 857 char szBuf[sizeof(g_szAll)]; 858 } s_Buf; 859 860 RTTestSub(hTest, "Benchmarks"); 861 /** @todo add RTTest* methods for reporting benchmark results. */ 862 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Benchmarking RTStrToUtf16Ex: "); /** @todo figure this stuff into the test framework. */ 863 PRTUTF16 pwsz = &s_Buf.wszBuf[0]; 864 int rc = RTStrToUtf16Ex(&g_szAll[0], RTSTR_MAX, &pwsz, RT_ELEMENTS(s_Buf.wszBuf), NULL); 865 if (RT_SUCCESS(rc)) 866 { 867 int i; 868 uint64_t u64Start = RTTimeNanoTS(); 869 for (i = 0; i < 100; i++) 870 { 871 rc = RTStrToUtf16Ex(&g_szAll[0], RTSTR_MAX, &pwsz, RT_ELEMENTS(s_Buf.wszBuf), NULL); 872 if (RT_FAILURE(rc)) 873 { 874 RTTestFailed(hTest, "UTF-8 -> UTF-16 benchmark failed at i=%d, rc=%Rrc\n", i, rc); 875 break; 876 } 877 } 878 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start; 879 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d in %'RI64 ns\n", i, u64Elapsed); 880 } 881 882 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Benchmarking RTUtf16ToUtf8Ex: "); 883 char *psz = &s_Buf.szBuf[0]; 884 rc = RTUtf16ToUtf8Ex(&g_wszAll[0], RTSTR_MAX, &psz, RT_ELEMENTS(s_Buf.szBuf), NULL); 885 if (RT_SUCCESS(rc)) 886 { 887 int i; 888 uint64_t u64Start = RTTimeNanoTS(); 889 for (i = 0; i < 100; i++) 890 { 891 rc = RTUtf16ToUtf8Ex(&g_wszAll[0], RTSTR_MAX, &psz, RT_ELEMENTS(s_Buf.szBuf), NULL); 892 if (RT_FAILURE(rc)) 893 { 894 RTTestFailed(hTest, "UTF-16 -> UTF-8 benchmark failed at i=%d, rc=%Rrc\n", i, rc); 895 break; 896 } 897 } 898 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start; 899 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d in %'RI64 ns\n", i, u64Elapsed); 900 } 901 902 RTTestSubDone(hTest); 903 } 904 905 906 /** 907 * Tests RTStrEnd 908 */ 909 static void testStrEnd(RTTEST hTest) 910 { 911 RTTestSub(hTest, "RTStrEnd"); 912 913 static char const s_szEmpty[1] = ""; 914 RTTESTI_CHECK(RTStrEnd(s_szEmpty, 0) == NULL); 915 RTTESTI_CHECK(RTStrEnd(s_szEmpty, 1) == &s_szEmpty[0]); 916 for (size_t i = 0; i < _1M; i++) 917 RTTESTI_CHECK(RTStrEnd(s_szEmpty, ~i) == &s_szEmpty[0]); 918 919 } 920 921 922 /** 923 * Tests RTStrStr and RTStrIStr. 924 */ 925 static void testStrStr(RTTEST hTest) 926 { 927 #define CHECK_NULL(expr) \ 928 do { \ 929 const char *pszRet = expr; \ 930 if (pszRet != NULL) \ 931 RTTestFailed(hTest, "%d: %#x -> %s expected NULL", __LINE__, #expr, pszRet); \ 932 } while (0) 933 934 #define CHECK(expr, expect) \ 935 do { \ 936 const char *pszRet = expr; \ 937 if ( (pszRet != NULL && (expect) == NULL) \ 938 || (pszRet == NULL && (expect) != NULL) \ 939 || strcmp(pszRet, (expect)) \ 940 ) \ 941 RTTestFailed(hTest, "%d: %#x -> %s expected %s", __LINE__, #expr, pszRet, (expect)); \ 942 } while (0) 943 944 945 RTTestSub(hTest, "RTStrStr"); 946 CHECK(RTStrStr("abcdef", ""), "abcdef"); 947 CHECK_NULL(RTStrStr("abcdef", NULL)); 948 CHECK_NULL(RTStrStr(NULL, "")); 949 CHECK_NULL(RTStrStr(NULL, NULL)); 950 CHECK(RTStrStr("abcdef", "abcdef"), "abcdef"); 951 CHECK(RTStrStr("abcdef", "b"), "bcdef"); 952 CHECK(RTStrStr("abcdef", "bcdef"), "bcdef"); 953 CHECK(RTStrStr("abcdef", "cdef"), "cdef"); 954 CHECK(RTStrStr("abcdef", "cde"), "cdef"); 955 CHECK(RTStrStr("abcdef", "cd"), "cdef"); 956 CHECK(RTStrStr("abcdef", "c"), "cdef"); 957 CHECK(RTStrStr("abcdef", "f"), "f"); 958 CHECK(RTStrStr("abcdef", "ef"), "ef"); 959 CHECK(RTStrStr("abcdef", "e"), "ef"); 960 CHECK_NULL(RTStrStr("abcdef", "z")); 961 CHECK_NULL(RTStrStr("abcdef", "A")); 962 CHECK_NULL(RTStrStr("abcdef", "F")); 963 964 RTTestSub(hTest, "RTStrIStr"); 965 CHECK(RTStrIStr("abcdef", ""), "abcdef"); 966 CHECK_NULL(RTStrIStr("abcdef", NULL)); 967 CHECK_NULL(RTStrIStr(NULL, "")); 968 CHECK_NULL(RTStrIStr(NULL, NULL)); 969 CHECK(RTStrIStr("abcdef", "abcdef"), "abcdef"); 970 CHECK(RTStrIStr("abcdef", "Abcdef"), "abcdef"); 971 CHECK(RTStrIStr("abcdef", "ABcDeF"), "abcdef"); 972 CHECK(RTStrIStr("abcdef", "b"), "bcdef"); 973 CHECK(RTStrIStr("abcdef", "B"), "bcdef"); 974 CHECK(RTStrIStr("abcdef", "bcdef"), "bcdef"); 975 CHECK(RTStrIStr("abcdef", "BCdEf"), "bcdef"); 976 CHECK(RTStrIStr("abcdef", "bCdEf"), "bcdef"); 977 CHECK(RTStrIStr("abcdef", "bcdEf"), "bcdef"); 978 CHECK(RTStrIStr("abcdef", "BcdEf"), "bcdef"); 979 CHECK(RTStrIStr("abcdef", "cdef"), "cdef"); 980 CHECK(RTStrIStr("abcdef", "cde"), "cdef"); 981 CHECK(RTStrIStr("abcdef", "cd"), "cdef"); 982 CHECK(RTStrIStr("abcdef", "c"), "cdef"); 983 CHECK(RTStrIStr("abcdef", "f"), "f"); 984 CHECK(RTStrIStr("abcdeF", "F"), "F"); 985 CHECK(RTStrIStr("abcdef", "F"), "f"); 986 CHECK(RTStrIStr("abcdef", "ef"), "ef"); 987 CHECK(RTStrIStr("EeEef", "e"), "EeEef"); 988 CHECK(RTStrIStr("EeEef", "E"), "EeEef"); 989 CHECK(RTStrIStr("EeEef", "EE"), "EeEef"); 990 CHECK(RTStrIStr("EeEef", "EEE"), "EeEef"); 991 CHECK(RTStrIStr("EeEef", "EEEF"), "eEef"); 992 CHECK_NULL(RTStrIStr("EeEef", "z")); 993 994 #undef CHECK 995 #undef CHECK_NULL 996 RTTestSubDone(hTest); 997 } 998 999 1000 void testMinistring(RTTEST hTest) 1001 { 1002 RTTestSub(hTest, "class iprt::MiniString"); 1003 1004 #define CHECK(expr) \ 1005 do { \ 1006 if (!(expr)) \ 1007 RTTestFailed(hTest, "%d: FAILED %s", __LINE__, #expr); \ 1008 } while (0) 1009 42 RTTestSub(hTest, "Basics"); 43 44 #define CHECK(expr) RTTESTI_CHECK(expr) 1010 45 #define CHECK_DUMP(expr, value) \ 1011 46 do { \ … … 1030 65 sixbytes.append(iprt::MiniString("678")); 1031 66 CHECK(sixbytes.length() == 8); 1032 CHECK(sixbytes.capacity() == 9);67 CHECK(sixbytes.capacity() >= 9); 1033 68 1034 69 sixbytes.append("9a"); 1035 70 CHECK(sixbytes.length() == 10); 1036 CHECK(sixbytes.capacity() == 11);71 CHECK(sixbytes.capacity() >= 11); 1037 72 1038 73 char *psz = sixbytes.mutableRaw(); … … 1072 107 CHECK(iprt::MiniString("abc") == iprt::MiniString("abc")); 1073 108 109 CHECK(iprt::MiniString("abc") < "def"); 110 CHECK(iprt::MiniString("abc") != "def"); 111 CHECK_DUMP_I(iprt::MiniString("def") > "abc"); 112 CHECK(iprt::MiniString("abc") == "abc"); 113 114 CHECK(iprt::MiniString("abc").equals("abc")); 115 CHECK(!iprt::MiniString("abc").equals("def")); 116 CHECK(iprt::MiniString("abc").equalsIgnoreCase("Abc")); 117 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABc")); 118 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABC")); 119 CHECK(!iprt::MiniString("abc").equalsIgnoreCase("dBC")); 120 1074 121 copy2.setNull(); 1075 122 for (int i = 0; i < 100; ++i) … … 1094 141 1095 142 1096 void testUtf8Latin1(RTTEST hTest)143 static int mymemcmp(const char *psz1, const char *psz2, size_t cch) 1097 144 { 1098 RTTestSub(hTest, "Latin-1 <-> Utf-8 conversion functions"); 1099 1100 /* Test Utf8 -> Latin1 */ 1101 size_t cch_szAll = 0; 1102 size_t cbShort = RTStrCalcLatin1Len(g_szAll); 1103 RTTEST_CHECK(hTest, cbShort == 0); 1104 int rc = RTStrCalcLatin1LenEx(g_szAll, 383, &cch_szAll); 1105 RTTEST_CHECK(hTest, (cch_szAll == 255)); 1106 rc = RTStrCalcLatin1LenEx(g_szAll, RTSTR_MAX, &cch_szAll); 1107 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1108 char *psz = NULL; 1109 char szShort[256] = { 0 }; 1110 memcpy(szShort, g_szAll, 255); 1111 cbShort = RTStrCalcLatin1Len(szShort); 1112 RTTEST_CHECK(hTest, cbShort == 191); 1113 rc = RTStrToLatin1(szShort, &psz); 1114 RTTEST_CHECK_RC_OK(hTest, rc); 1115 if (RT_SUCCESS(rc)) 1116 { 1117 RTTEST_CHECK(hTest, (strlen(psz) == 191)); 1118 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j) 1119 if (psz[i] != (char) j) 1120 { 1121 RTTestFailed(hTest, "conversion of g_szAll to Latin1 failed at position %u\n", i); 1122 break; 1123 } 1124 } 1125 RTStrFree(psz); 1126 rc = RTStrToLatin1(g_szAll, &psz); 1127 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1128 char sz[512]; 1129 char *psz2 = &sz[0]; 1130 size_t cchActual = 0; 1131 rc = RTStrToLatin1Ex(g_szAll, sizeof(sz) - 1, &psz2, sizeof(sz), 1132 &cchActual); 1133 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1134 RTTEST_CHECK_MSG(hTest, cchActual == 0, 1135 (hTest, "cchActual=%lu\n", cchActual)); 1136 rc = RTStrToLatin1Ex(g_szAll, 383, &psz2, sizeof(sz), 1137 &cchActual); 1138 RTTEST_CHECK_RC_OK(hTest, rc); 1139 if (RT_SUCCESS(rc)) 1140 { 1141 RTTEST_CHECK(hTest, (cchActual == 255)); 1142 RTTEST_CHECK(hTest, (cchActual == strlen(sz))); 1143 for (unsigned i = 0, j = 1; psz2[i] != '\0'; ++i, ++j) 1144 if (psz2[i] != (char) j) 1145 { 1146 RTTestFailed(hTest, "second conversion of g_szAll to Latin1 failed at position %u\n", i); 1147 break; 1148 } 1149 } 1150 rc = RTStrToLatin1Ex(g_szAll, 129, &psz2, 128, &cchActual); 1151 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW); 1152 RTTEST_CHECK_MSG(hTest, cchActual == 128, 1153 (hTest, "cchActual=%lu\n", cchActual)); 1154 rc = RTStrToLatin1Ex(g_szAll, 383, &psz, 0, &cchActual); 1155 RTTEST_CHECK_RC_OK(hTest, rc); 1156 if (RT_SUCCESS(rc)) 1157 { 1158 RTTEST_CHECK(hTest, (cchActual == 255)); 1159 RTTEST_CHECK(hTest, (cchActual == strlen(psz))); 1160 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j) 1161 if ( ((j < 0x100) && (psz[i] != (char) j)) 1162 || ((j > 0xff) && psz[i] != '?')) 1163 { 1164 RTTestFailed(hTest, "third conversion of g_szAll to Latin1 failed at position %u\n", i); 1165 break; 1166 } 1167 } 1168 const char *pszBad = "Hello\xDC\xD8"; 1169 rc = RTStrToLatin1Ex(pszBad, RTSTR_MAX, &psz2, sizeof(sz), 1170 &cchActual); 1171 RTTEST_CHECK_RC(hTest, rc, VERR_INVALID_UTF8_ENCODING); 1172 RTStrFree(psz); 1173 1174 /* Test Latin1 -> Utf8 */ 1175 const char *pszLat1 = "\x01\x20\x40\x80\x81"; 1176 RTTEST_CHECK(hTest, RTLatin1CalcUtf8Len(pszLat1) == 7); 1177 rc = RTLatin1CalcUtf8LenEx(pszLat1, 3, &cchActual); 1178 RTTEST_CHECK_RC_OK(hTest, rc); 1179 if (RT_SUCCESS(rc)) 1180 RTTEST_CHECK(hTest, cchActual == 3); 1181 rc = RTLatin1CalcUtf8LenEx(pszLat1, RTSTR_MAX, &cchActual); 1182 RTTEST_CHECK_RC_OK(hTest, rc); 1183 if (RT_SUCCESS(rc)) 1184 RTTEST_CHECK(hTest, cchActual == 7); 1185 char *pch = NULL; 1186 char ch[8]; 1187 char *pch2 = &ch[0]; 1188 cchActual = 0; 1189 rc = RTLatin1ToUtf8(pszLat1, &pch); 1190 RTTEST_CHECK_RC_OK(hTest, rc); 1191 if (RT_SUCCESS(rc)) 1192 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81")); 1193 RTStrFree(pch); 1194 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch, 0, &cchActual); 1195 RTTEST_CHECK_RC_OK(hTest, rc); 1196 if (RT_SUCCESS(rc)) 1197 { 1198 RTTEST_CHECK(hTest, (cchActual == 7)); 1199 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81")); 1200 } 1201 RTStrFree(pch); 1202 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch, 0, NULL); 1203 RTTEST_CHECK_RC_OK(hTest, rc); 1204 if (RT_SUCCESS(rc)) 1205 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81")); 1206 RTStrFree(pch); 1207 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch2, RT_ELEMENTS(ch), 1208 &cchActual); 1209 RTTEST_CHECK_RC_OK(hTest, rc); 1210 if (RT_SUCCESS(rc)) 1211 { 1212 RTTEST_CHECK(hTest, (cchActual == 7)); 1213 RTTEST_CHECK(hTest, !strcmp(pch2, "\x01\x20\x40\xC2\x80\xC2\x81")); 1214 } 1215 rc = RTLatin1ToUtf8Ex(pszLat1, 3, &pch2, RT_ELEMENTS(ch), 1216 &cchActual); 1217 RTTEST_CHECK_RC_OK(hTest, rc); 1218 if (RT_SUCCESS(rc)) 1219 { 1220 RTTEST_CHECK(hTest, (cchActual == 3)); 1221 RTTEST_CHECK(hTest, !strcmp(pch2, "\x01\x20\x40")); 1222 } 1223 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch2, RT_ELEMENTS(ch) - 1, 1224 &cchActual); 1225 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW); 1226 RTTEST_CHECK(hTest, (cchActual == 7)); 1227 RTTestSubDone(hTest); 145 for (size_t off = 0; off < cch; off++) 146 if (psz1[off] != psz2[off]) 147 { 148 RTTestIFailed("off=%#x psz1=%.*Rhxs psz2=%.*Rhxs\n", off, 149 RT_MIN(cch - off, 8), &psz1[off], 150 RT_MIN(cch - off, 8), &psz2[off]); 151 return psz1[off] > psz2[off] ? 1 : -1; 152 } 153 return 0; 1228 154 } 1229 155 1230 1231 void testUtf16Latin1(RTTEST hTest) 156 static void test2(RTTEST hTest) 1232 157 { 1233 RTTestSub(hTest, "Latin-1 <-> Utf-16 conversion functions"); 1234 1235 /* Test Utf16 -> Latin1 */ 1236 size_t cch_szAll = 0; 1237 size_t cbShort = RTUtf16CalcLatin1Len(g_wszAll); 1238 RTTEST_CHECK(hTest, cbShort == 0); 1239 int rc = RTUtf16CalcLatin1LenEx(g_wszAll, 255, &cch_szAll); 1240 RTTEST_CHECK(hTest, (cch_szAll == 255)); 1241 rc = RTUtf16CalcLatin1LenEx(g_wszAll, RTSTR_MAX, &cch_szAll); 1242 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1243 char *psz = NULL; 1244 RTUTF16 wszShort[256] = { 0 }; 1245 for (unsigned i = 0; i < 255; ++i) 1246 wszShort[i] = i + 1; 1247 cbShort = RTUtf16CalcLatin1Len(wszShort); 1248 RTTEST_CHECK(hTest, cbShort == 255); 1249 rc = RTUtf16ToLatin1(wszShort, &psz); 1250 RTTEST_CHECK_RC_OK(hTest, rc); 1251 if (RT_SUCCESS(rc)) 1252 { 1253 RTTEST_CHECK(hTest, (strlen(psz) == 255)); 1254 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j) 1255 if (psz[i] != (char) j) 1256 { 1257 RTTestFailed(hTest, "conversion of g_wszAll to Latin1 failed at position %u\n", i); 1258 break; 1259 } 1260 } 1261 RTStrFree(psz); 1262 rc = RTUtf16ToLatin1(g_wszAll, &psz); 1263 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1264 char sz[512]; 1265 char *psz2 = &sz[0]; 1266 size_t cchActual = 0; 1267 rc = RTUtf16ToLatin1Ex(g_wszAll, sizeof(sz) - 1, &psz2, sizeof(sz), 1268 &cchActual); 1269 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION); 1270 RTTEST_CHECK_MSG(hTest, cchActual == 0, 1271 (hTest, "cchActual=%lu\n", cchActual)); 1272 rc = RTUtf16ToLatin1Ex(g_wszAll, 255, &psz2, sizeof(sz), 1273 &cchActual); 1274 RTTEST_CHECK_RC_OK(hTest, rc); 1275 if (RT_SUCCESS(rc)) 1276 { 1277 RTTEST_CHECK(hTest, (cchActual == 255)); 1278 RTTEST_CHECK(hTest, (cchActual == strlen(sz))); 1279 for (unsigned i = 0, j = 1; psz2[i] != '\0'; ++i, ++j) 1280 if (psz2[i] != (char) j) 1281 { 1282 RTTestFailed(hTest, "second conversion of g_wszAll to Latin1 failed at position %u\n", i); 1283 break; 1284 } 1285 } 1286 rc = RTUtf16ToLatin1Ex(g_wszAll, 128, &psz2, 128, &cchActual); 1287 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW); 1288 RTTEST_CHECK_MSG(hTest, cchActual == 128, 1289 (hTest, "cchActual=%lu\n", cchActual)); 1290 rc = RTUtf16ToLatin1Ex(g_wszAll, 255, &psz, 0, &cchActual); 1291 RTTEST_CHECK_RC_OK(hTest, rc); 1292 if (RT_SUCCESS(rc)) 1293 { 1294 RTTEST_CHECK(hTest, (cchActual == 255)); 1295 RTTEST_CHECK(hTest, (cchActual == strlen(psz))); 1296 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j) 1297 if ( ((j < 0x100) && (psz[i] != (char) j)) 1298 || ((j > 0xff) && psz[i] != '?')) 1299 { 1300 RTTestFailed(hTest, "third conversion of g_wszAll to Latin1 failed at position %u\n", i); 1301 break; 1302 } 1303 } 1304 const char *pszBad = "H\0e\0l\0l\0o\0\0\xDC\0\xD8\0"; 1305 rc = RTUtf16ToLatin1Ex((RTUTF16 *) pszBad, RTSTR_MAX, &psz2, sizeof(sz), 1306 &cchActual); 1307 RTTEST_CHECK_RC(hTest, rc, VERR_INVALID_UTF16_ENCODING); 1308 RTStrFree(psz); 1309 1310 /* Test Latin1 -> Utf16 */ 1311 const char *pszLat1 = "\x01\x20\x40\x80\x81"; 1312 RTTEST_CHECK(hTest, RTLatin1CalcUtf16Len(pszLat1) == 5); 1313 rc = RTLatin1CalcUtf16LenEx(pszLat1, 3, &cchActual); 1314 RTTEST_CHECK_RC_OK(hTest, rc); 1315 if (RT_SUCCESS(rc)) 1316 RTTEST_CHECK(hTest, cchActual == 3); 1317 rc = RTLatin1CalcUtf16LenEx(pszLat1, RTSTR_MAX, &cchActual); 1318 RTTEST_CHECK_RC_OK(hTest, rc); 1319 if (RT_SUCCESS(rc)) 1320 RTTEST_CHECK(hTest, cchActual == 5); 1321 RTUTF16 *pwc = NULL; 1322 RTUTF16 wc[6]; 1323 RTUTF16 *pwc2 = &wc[0]; 1324 size_t cwActual = 0; 1325 rc = RTLatin1ToUtf16(pszLat1, &pwc); 1326 RTTEST_CHECK_RC_OK(hTest, rc); 1327 if (RT_SUCCESS(rc)) 1328 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20) 1329 && (pwc[2] == 0x40) && (pwc[3] == 0x80) 1330 && (pwc[4] == 0x81) && (pwc[5] == '\0')); 1331 RTUtf16Free(pwc); 1332 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc, 0, &cwActual); 1333 RTTEST_CHECK_RC_OK(hTest, rc); 1334 if (RT_SUCCESS(rc)) 1335 { 1336 RTTEST_CHECK(hTest, (cwActual == 5)); 1337 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20) 1338 && (pwc[2] == 0x40) && (pwc[3] == 0x80) 1339 && (pwc[4] == 0x81) && (pwc[5] == '\0')); 1340 } 1341 RTUtf16Free(pwc); 1342 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc, 0, NULL); 1343 RTTEST_CHECK_RC_OK(hTest, rc); 1344 if (RT_SUCCESS(rc)) 1345 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20) 1346 && (pwc[2] == 0x40) && (pwc[3] == 0x80) 1347 && (pwc[4] == 0x81) && (pwc[5] == '\0')); 1348 RTUtf16Free(pwc); 1349 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc2, RT_ELEMENTS(wc), 1350 &cwActual); 1351 RTTEST_CHECK_RC_OK(hTest, rc); 1352 if (RT_SUCCESS(rc)) 1353 { 1354 RTTEST_CHECK(hTest, (cwActual == 5)); 1355 RTTEST_CHECK(hTest, (wc[0] == 1) && (wc[1] == 0x20) 1356 && (wc[2] == 0x40) && (wc[3] == 0x80) 1357 && (wc[4] == 0x81) && (wc[5] == '\0')); 1358 } 1359 rc = RTLatin1ToUtf16Ex(pszLat1, 3, &pwc2, RT_ELEMENTS(wc), 1360 &cwActual); 1361 RTTEST_CHECK_RC_OK(hTest, rc); 1362 if (RT_SUCCESS(rc)) 1363 { 1364 RTTEST_CHECK(hTest, (cwActual == 3)); 1365 RTTEST_CHECK(hTest, (wc[0] == 1) && (wc[1] == 0x20) 1366 && (wc[2] == 0x40) && (wc[3] == '\0')); 1367 } 1368 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc2, RT_ELEMENTS(wc) - 1, 1369 &cwActual); 1370 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW); 1371 RTTEST_CHECK(hTest, (cwActual == 5)); 1372 RTTestSubDone(hTest); 1373 } 1374 1375 1376 static void testNoTransation(RTTEST hTest) 1377 { 1378 1379 /* 1380 * Try trigger a VERR_NO_TRANSLATION error in convert to 1381 * current CP to latin-1. 1382 */ 1383 const RTUTF16 s_swzTest1[] = { 0x2358, 0x2242, 0x2357, 0x2359, 0x22f9, 0x2c4e, 0x0030, 0x0060, 1384 0x0092, 0x00c1, 0x00f2, 0x1f80, 0x0088, 0x2c38, 0x2c30, 0x0000 }; 1385 char *pszTest1; 1386 int rc = RTUtf16ToUtf8(s_swzTest1, &pszTest1); 1387 RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS); 1388 1389 RTTestSub(hTest, "VERR_NO_TRANSLATION/RTStrUtf8ToCurrentCP"); 1390 char *pszOut; 1391 rc = RTStrUtf8ToCurrentCP(&pszOut, pszTest1); 1392 if (RT_SUCCESS(rc)) 1393 { 1394 RTTESTI_CHECK(!strcmp(pszOut, pszTest1)); 1395 RTTestIPrintf(RTTESTLVL_ALWAYS, "CurrentCP is UTF-8 or similar\n"); 1396 RTStrFree(pszOut); 1397 } 1398 else 1399 RTTESTI_CHECK_RC(rc, VERR_NO_TRANSLATION); 1400 1401 RTTestSub(hTest, "VERR_NO_TRANSLATION/RTUtf16ToLatin1"); 1402 rc = RTUtf16ToLatin1(s_swzTest1, &pszOut); 1403 RTTESTI_CHECK_RC(rc, VERR_NO_TRANSLATION); 1404 if (RT_SUCCESS(rc)) 1405 RTStrFree(pszOut); 1406 1407 RTStrFree(pszTest1); 1408 RTTestSubDone(hTest); 158 RTTestSub(hTest, "UTF-8 upper/lower encoding assumption"); 159 160 #define CHECK_EQUAL(str1, str2) \ 161 do \ 162 { \ 163 RTTESTI_CHECK(strlen((str1).c_str()) == (str1).length()); \ 164 RTTESTI_CHECK((str1).length() == (str2).length()); \ 165 RTTESTI_CHECK(mymemcmp((str1).c_str(), (str2).c_str(), (str2).length() + 1) == 0); \ 166 } while (0) 167 168 iprt::MiniString strTmp; 169 char szDst[16]; 170 171 /* Collect all upper and lower case code points. */ 172 iprt::MiniString strLower(""); 173 strLower.reserve(_4M); 174 175 iprt::MiniString strUpper(""); 176 strUpper.reserve(_4M); 177 178 for (RTUNICP uc = 1; uc <= 0x10fffd; uc++) 179 { 180 if (RTUniCpIsLower(uc)) 181 { 182 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc)); 183 strLower.appendCodePoint(uc); 184 } 185 if (RTUniCpIsUpper(uc)) 186 { 187 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc)); 188 strUpper.appendCodePoint(uc); 189 } 190 } 191 RTTESTI_CHECK(strlen(strLower.c_str()) == strLower.length()); 192 RTTESTI_CHECK(strlen(strUpper.c_str()) == strUpper.length()); 193 194 /* Fold each code point in the lower case string and check that it encodes 195 into the same or less number of bytes. */ 196 size_t cch = 0; 197 const char *pszCur = strLower.c_str(); 198 iprt::MiniString strUpper2(""); 199 strUpper2.reserve(strLower.length() + 64); 200 for (;;) 201 { 202 RTUNICP ucLower; 203 const char * const pszPrev = pszCur; 204 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucLower), VINF_SUCCESS); 205 size_t const cchSrc = pszCur - pszPrev; 206 if (!ucLower) 207 break; 208 209 RTUNICP const ucUpper = RTUniCpToUpper(ucLower); 210 const char *pszDstEnd = RTStrPutCp(szDst, ucUpper); 211 size_t const cchDst = pszDstEnd - &szDst[0]; 212 RTTESTI_CHECK_MSG(cchSrc >= cchDst, 213 ("ucLower=%#x %u bytes; ucUpper=%#x %u bytes\n", 214 ucLower, cchSrc, ucUpper, cchDst)); 215 cch += cchDst; 216 strUpper2.appendCodePoint(ucUpper); 217 218 /* roundtrip stability */ 219 RTUNICP const ucUpper2 = RTUniCpToUpper(ucUpper); 220 RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper)); 221 222 RTUNICP const ucLower2 = RTUniCpToLower(ucUpper); 223 RTUNICP const ucUpper3 = RTUniCpToUpper(ucLower2); 224 RTTESTI_CHECK_MSG(ucUpper3 == ucUpper, ("ucUpper3=%#x ucUpper=%#x\n", ucUpper3, ucUpper)); 225 226 pszDstEnd = RTStrPutCp(szDst, ucLower2); 227 size_t const cchLower2 = pszDstEnd - &szDst[0]; 228 RTTESTI_CHECK_MSG(cchDst == cchLower2, 229 ("ucLower2=%#x %u bytes; ucUpper=%#x %u bytes\n", 230 ucLower2, cchLower2, ucUpper, cchDst)); 231 } 232 RTTESTI_CHECK(strlen(strUpper2.c_str()) == strUpper2.length()); 233 RTTESTI_CHECK_MSG(cch == strUpper2.length(), ("cch=%u length()=%u\n", cch, strUpper2.length())); 234 235 /* the toUpper method shall do the same thing. */ 236 strTmp = strLower; CHECK_EQUAL(strTmp, strLower); 237 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 238 239 /* Ditto for the upper case string. */ 240 cch = 0; 241 pszCur = strUpper.c_str(); 242 iprt::MiniString strLower2(""); 243 strLower2.reserve(strUpper.length() + 64); 244 for (;;) 245 { 246 RTUNICP ucUpper; 247 const char * const pszPrev = pszCur; 248 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucUpper), VINF_SUCCESS); 249 size_t const cchSrc = pszCur - pszPrev; 250 if (!ucUpper) 251 break; 252 253 RTUNICP const ucLower = RTUniCpToLower(ucUpper); 254 const char *pszDstEnd = RTStrPutCp(szDst, ucLower); 255 size_t const cchDst = pszDstEnd - &szDst[0]; 256 RTTESTI_CHECK_MSG(cchSrc >= cchDst, 257 ("ucUpper=%#x %u bytes; ucLower=%#x %u bytes\n", 258 ucUpper, cchSrc, ucLower, cchDst)); 259 260 cch += cchDst; 261 strLower2.appendCodePoint(ucLower); 262 263 /* roundtrip stability */ 264 RTUNICP const ucLower2 = RTUniCpToLower(ucLower); 265 RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower)); 266 267 RTUNICP const ucUpper2 = RTUniCpToUpper(ucLower); 268 RTUNICP const ucLower3 = RTUniCpToLower(ucUpper2); 269 RTTESTI_CHECK_MSG(ucLower3 == ucLower, ("ucLower3=%#x ucLower=%#x\n", ucLower3, ucLower)); 270 271 pszDstEnd = RTStrPutCp(szDst, ucUpper2); 272 size_t const cchUpper2 = pszDstEnd - &szDst[0]; 273 RTTESTI_CHECK_MSG(cchDst == cchUpper2, 274 ("ucUpper2=%#x %u bytes; ucLower=%#x %u bytes\n", 275 ucUpper2, cchUpper2, ucLower, cchDst)); 276 } 277 RTTESTI_CHECK(strlen(strLower2.c_str()) == strLower2.length()); 278 RTTESTI_CHECK_MSG(cch == strLower2.length(), ("cch=%u length()=%u\n", cch, strLower2.length())); 279 280 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); 281 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 282 283 /* Checks of folding stability when nothing shall change. */ 284 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); 285 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); 286 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); 287 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper); 288 289 strTmp = strUpper2; CHECK_EQUAL(strTmp, strUpper2); 290 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 291 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 292 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 293 294 strTmp = strLower; CHECK_EQUAL(strTmp, strLower); 295 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); 296 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); 297 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower); 298 299 strTmp = strLower2; CHECK_EQUAL(strTmp, strLower2); 300 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 301 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 302 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 303 304 /* Check folding stability for roundtrips. */ 305 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper); 306 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 307 strTmp.toUpper(); 308 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 309 strTmp.toUpper(); 310 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2); 311 312 strTmp = strLower; CHECK_EQUAL(strTmp, strLower); 313 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 314 strTmp.toLower(); 315 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 316 strTmp.toLower(); 317 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2); 1409 318 } 1410 319 … … 1412 321 int main() 1413 322 { 1414 /* 1415 * Init the runtime, test and say hello. 1416 */ 1417 RTTEST hTest; 1418 int rc = RTTestInitAndCreate("tstUtf8", &hTest); 1419 if (rc) 1420 return rc; 1421 RTTestBanner(hTest); 1422 1423 /* 1424 * Run the test. 1425 */ 1426 InitStrings(); 1427 test1(hTest); 1428 test2(hTest); 1429 test3(hTest); 1430 TstRTStrXCmp(hTest); 1431 TstRTStrPurgeEncoding(hTest); 1432 testStrEnd(hTest); 1433 testStrStr(hTest); 1434 testMinistring(hTest); 1435 testUtf8Latin1(hTest); 1436 testUtf16Latin1(hTest); 1437 testNoTransation(hTest); 1438 1439 Benchmarks(hTest); 1440 1441 /* 1442 * Summary 1443 */ 1444 return RTTestSummaryAndDestroy(hTest); 323 RTTEST hTest; 324 RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtMiniString", &hTest); 325 if (rcExit == RTEXITCODE_SUCCESS) 326 { 327 RTTestBanner(hTest); 328 329 test1(hTest); 330 test2(hTest); 331 332 rcExit = RTTestSummaryAndDestroy(hTest); 333 } 334 return rcExit; 1445 335 } 1446 336
Note:
See TracChangeset
for help on using the changeset viewer.