1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 25 // MARKER(update_precomp.py): autogen include statement, do not remove 26 #include "precompiled_sal.hxx" 27 #include "gtest/gtest.h" 28 #include <rtl/string.hxx> 29 30 namespace rtl_str 31 { 32 33 class compare : public ::testing::Test 34 { 35 public: 36 }; // class compare 37 38 TEST_F(compare, compare_000) 39 { 40 // A former version of this test passed (NULL, NULL). rtl_str_compare 41 // documents that both strings must be null-terminated, so NULL is 42 // undefined behaviour (the implementation unconditionally dereferences 43 // both pointers). 44 // Instead verify the ordering-sign contract, which had no coverage: 45 // a value < 0 / > 0 depending on which string is "less". 46 rtl::OString aStr1 = "abc"; 47 rtl::OString aStr2 = "abd"; 48 49 ASSERT_TRUE(rtl_str_compare( aStr1.getStr(), aStr2.getStr()) < 0) 50 << "\"abc\" must compare less than \"abd\"."; 51 ASSERT_TRUE(rtl_str_compare( aStr2.getStr(), aStr1.getStr()) > 0) 52 << "\"abd\" must compare greater than \"abc\"."; 53 } 54 55 TEST_F(compare, compare_000_1) 56 { 57 // A former version of this test passed (validStr, NULL) which is 58 // undefined behaviour. 59 // Verify the empty-string boundary instead (the valid analogue of an 60 // "absent" string): a non-empty string is greater than the empty one. 61 rtl::OString aStr1 = "Line must be equal."; 62 rtl::OString aEmpty = ""; 63 64 ASSERT_TRUE(rtl_str_compare( aStr1.getStr(), aEmpty.getStr()) > 0) 65 << "a non-empty string must be greater than the empty string."; 66 ASSERT_TRUE(rtl_str_compare( aEmpty.getStr(), aStr1.getStr()) < 0) 67 << "the empty string must be less than a non-empty string."; 68 } 69 TEST_F(compare, compare_001) 70 { 71 rtl::OString aStr1 = ""; 72 rtl::OString aStr2 = ""; 73 74 sal_Int32 nValue = rtl_str_compare( aStr1.getStr(), aStr2.getStr()); 75 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 76 } 77 78 TEST_F(compare, compare_002) 79 { 80 rtl::OString aStr1 = "Line must be equal."; 81 rtl::OString aStr2 = "Line must be equal."; 82 83 sal_Int32 nValue = rtl_str_compare( aStr1.getStr(), aStr2.getStr()); 84 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 85 } 86 87 TEST_F(compare, compare_003) 88 { 89 rtl::OString aStr1 = "Line must differ."; 90 rtl::OString aStr2 = "Line foo bar, ok, differ."; 91 92 sal_Int32 nValue = rtl_str_compare( aStr1.getStr(), aStr2.getStr()); 93 ASSERT_TRUE(nValue != 0) << "compare failed, strings differ."; 94 } 95 96 class compareIgnoreAsciiCase : public ::testing::Test 97 { 98 public: 99 }; // class compareIgnoreAsciiCase 100 101 TEST_F(compareIgnoreAsciiCase, compare_000) 102 { 103 // Former test passed (NULL, NULL) -> undefined behaviour. Verify the 104 // case-insensitive ordering-sign contract instead. 105 rtl::OString aStr1 = "abc"; 106 rtl::OString aStr2 = "ABD"; 107 108 ASSERT_TRUE(rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aStr2.getStr()) < 0) 109 << "\"abc\" must compare less than \"ABD\" ignoring case."; 110 ASSERT_TRUE(rtl_str_compareIgnoreAsciiCase( aStr2.getStr(), aStr1.getStr()) > 0) 111 << "\"ABD\" must compare greater than \"abc\" ignoring case."; 112 } 113 114 TEST_F(compareIgnoreAsciiCase, compare_000_1) 115 { 116 // Former test passed (validStr, NULL) -> undefined behaviour. 117 // Verify the empty-string boundary instead. 118 rtl::OString aStr1 = "Line must be equal."; 119 rtl::OString aEmpty = ""; 120 121 ASSERT_TRUE(rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aEmpty.getStr()) > 0) 122 << "a non-empty string must be greater than the empty string."; 123 } 124 TEST_F(compareIgnoreAsciiCase, compare_001) 125 { 126 rtl::OString aStr1 = ""; 127 rtl::OString aStr2 = ""; 128 129 sal_Int32 nValue = rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aStr2.getStr()); 130 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 131 } 132 133 TEST_F(compareIgnoreAsciiCase, compare_002) 134 { 135 rtl::OString aStr1 = "Line must be equal."; 136 rtl::OString aStr2 = "Line must be equal."; 137 138 sal_Int32 nValue = rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aStr2.getStr()); 139 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 140 } 141 142 TEST_F(compareIgnoreAsciiCase, compare_002_1) 143 { 144 rtl::OString aStr1 = "Line must be equal."; 145 rtl::OString aStr2 = "LINE MUST BE EQUAL."; 146 147 sal_Int32 nValue = rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aStr2.getStr()); 148 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal (if case insensitive)."; 149 } 150 151 TEST_F(compareIgnoreAsciiCase, compare_003) 152 { 153 rtl::OString aStr1 = "Line must differ."; 154 rtl::OString aStr2 = "Line foo bar, ok, differ."; 155 156 sal_Int32 nValue = rtl_str_compareIgnoreAsciiCase( aStr1.getStr(), aStr2.getStr()); 157 ASSERT_TRUE(nValue != 0) << "compare failed, strings differ."; 158 } 159 // ----------------------------------------------------------------------------- 160 161 class shortenedCompareIgnoreAsciiCase_WithLength : public ::testing::Test 162 { 163 public: 164 }; // class compare 165 166 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_000) 167 { 168 // The _WithLength variant is length-bounded, so NULL data with length 0 169 // is well-defined (the loop body never runs) and must return 0. 170 // Keep the NULL+0 call as a regression guard, but actually assert it. 171 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( NULL, 0, NULL, 0, 0); 172 ASSERT_TRUE(nValue == 0) << "zero-length comparison must return 0, even for NULL data."; 173 } 174 175 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_000_1) 176 { 177 // First string has data, second is a zero-length string (NULL data, len 0). 178 // Nothing is dereferenced; the function returns the length difference. 179 rtl::OString aStr1 = "Line must be equal."; 180 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), NULL, 0, 1); 181 ASSERT_TRUE(nValue == aStr1.getLength()) 182 << "comparing against a zero-length string must yield the length difference."; 183 } 184 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_001) 185 { 186 rtl::OString aStr1 = ""; 187 rtl::OString aStr2 = ""; 188 189 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), aStr2.getStr(), aStr2.getLength(), aStr1.getLength()); 190 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 191 } 192 193 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_002) 194 { 195 rtl::OString aStr1 = "Line must be equal."; 196 rtl::OString aStr2 = "Line must be equal."; 197 198 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), 199 aStr2.getStr(), aStr2.getLength(), 200 aStr1.getLength()); 201 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal."; 202 } 203 204 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_002_1) 205 { 206 rtl::OString aStr1 = "Line must be equal."; 207 rtl::OString aStr2 = "LINE MUST BE EQUAL."; 208 209 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), 210 aStr2.getStr(), aStr2.getLength(), 211 aStr1.getLength()); 212 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal (if case insensitive)."; 213 } 214 215 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_003) 216 { 217 rtl::OString aStr1 = "Line must differ."; 218 rtl::OString aStr2 = "Line foo bar, ok, differ."; 219 220 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), 221 aStr2.getStr(), aStr2.getLength(), 222 5); 223 ASSERT_TRUE(nValue == 0) << "compare failed, strings are equal first 5 characters."; 224 } 225 226 TEST_F(shortenedCompareIgnoreAsciiCase_WithLength, compare_004) 227 { 228 rtl::OString aStr1 = "Line must differ."; 229 rtl::OString aStr2 = "Line foo bar, ok, differ."; 230 231 sal_Int32 nValue = rtl_str_shortenedCompareIgnoreAsciiCase_WithLength( aStr1.getStr(), aStr1.getLength(), 232 aStr2.getStr(), aStr2.getLength(), 233 aStr1.getLength()); 234 ASSERT_TRUE(nValue != 0) << "compare failed, strings differ."; 235 } 236 237 // ----------------------------------------------------------------------------- 238 239 class hashCode : public ::testing::Test 240 { 241 public: 242 }; // class compare 243 244 TEST_F(hashCode, hashCode_000) 245 { 246 // Former test passed NULL -> getLength(NULL) dereferences NULL (UB). 247 // Verify the empty-string boundary: hashCode("") is defined and 0. 248 rtl::OString aStr1 = ""; 249 sal_Int32 nHashCode = rtl_str_hashCode( aStr1.getStr() ); 250 ASSERT_TRUE(nHashCode == 0) << "the hashCode of an empty string must be 0."; 251 } 252 253 TEST_F(hashCode, hashCode_001) 254 { 255 rtl::OString aStr1 = "Line for a hashCode."; 256 sal_Int32 nHashCode = rtl_str_hashCode( aStr1.getStr() ); 257 printf("hashcode: %d\n", nHashCode); 258 // ASSERT_TRUE(nValue == 0) << "failed."; 259 } 260 261 TEST_F(hashCode, hashCode_002) 262 { 263 rtl::OString aStr1 = "Line for a hashCode."; 264 sal_Int32 nHashCode1 = rtl_str_hashCode( aStr1.getStr() ); 265 266 rtl::OString aStr2 = "Line for a hashCode."; 267 sal_Int32 nHashCode2 = rtl_str_hashCode( aStr2.getStr() ); 268 269 ASSERT_TRUE(nHashCode1 == nHashCode2) << "hashcodes must be equal."; 270 } 271 272 TEST_F(hashCode, hashCode_003) 273 { 274 rtl::OString aStr1 = "Line for a hashCode."; 275 sal_Int32 nHashCode1 = rtl_str_hashCode( aStr1.getStr() ); 276 277 rtl::OString aStr2 = "Line for an other hashcode."; 278 sal_Int32 nHashCode2 = rtl_str_hashCode( aStr2.getStr() ); 279 280 ASSERT_TRUE(nHashCode1 != nHashCode2) << "hashcodes must differ."; 281 } 282 283 // ----------------------------------------------------------------------------- 284 285 class indexOfChar : public ::testing::Test 286 { 287 public: 288 }; // class compare 289 290 TEST_F(indexOfChar, indexOfChar_000) 291 { 292 // Former test passed NULL -> while(*pStr) dereferences NULL (UB). 293 // Verify the empty-string boundary: nothing is ever found -> -1. 294 rtl::OString aStr1 = ""; 295 sal_Int32 nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'x' ); 296 ASSERT_TRUE(nIndex == -1) << "searching an empty string must return -1."; 297 } 298 299 TEST_F(indexOfChar, indexOfChar_001) 300 { 301 rtl::OString aStr1 = "Line for a indexOfChar."; 302 303 sal_Int32 nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'L' ); 304 ASSERT_TRUE(nIndex == 0) << "index is wrong."; 305 306 /* sal_Int32 */ nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'i' ); 307 ASSERT_TRUE(nIndex == 1) << "index is wrong."; 308 309 /* sal_Int32 */ nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'n' ); 310 ASSERT_TRUE(nIndex == 2) << "index is wrong."; 311 312 /* sal_Int32 */ nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'e' ); 313 ASSERT_TRUE(nIndex == 3) << "index is wrong."; 314 } 315 316 TEST_F(indexOfChar, indexOfChar_002) 317 { 318 rtl::OString aStr1 = "Line for a indexOfChar."; 319 sal_Int32 nIndex = rtl_str_indexOfChar( aStr1.getStr(), 'y' ); 320 321 ASSERT_TRUE(nIndex == -1) << "index is wrong."; 322 } 323 324 // ----------------------------------------------------------------------------- 325 class lastIndexOfChar : public ::testing::Test 326 { 327 public: 328 }; // class lastIndexOfChar 329 330 TEST_F(lastIndexOfChar, lastIndexOfChar_000) 331 { 332 // Former test passed NULL -> getLength(NULL) dereferences NULL (UB). 333 // Verify the empty-string boundary instead. 334 rtl::OString aStr1 = ""; 335 sal_Int32 nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'x' ); 336 ASSERT_TRUE(nIndex == -1) << "searching an empty string must return -1."; 337 } 338 339 TEST_F(lastIndexOfChar, lastIndexOfChar_001) 340 { 341 rtl::OString aStr1 = "Line for a lastIndexOfChar."; 342 343 sal_Int32 nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'C' ); 344 ASSERT_TRUE(nIndex == 22) << "index is wrong."; 345 346 /* sal_Int32 */ nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'h' ); 347 ASSERT_TRUE(nIndex == 23) << "index is wrong."; 348 349 /* sal_Int32 */ nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'a' ); 350 ASSERT_TRUE(nIndex == 24) << "index is wrong."; 351 352 /* sal_Int32 */ nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'r' ); 353 ASSERT_TRUE(nIndex == 25) << "index is wrong."; 354 } 355 356 TEST_F(lastIndexOfChar, lastIndexOfChar_002) 357 { 358 rtl::OString aStr1 = "Line for a lastIndexOfChar."; 359 sal_Int32 nIndex = rtl_str_lastIndexOfChar( aStr1.getStr(), 'y' ); 360 361 ASSERT_TRUE(nIndex == -1) << "index is wrong."; 362 } 363 364 // ----------------------------------------------------------------------------- 365 366 class indexOfStr : public ::testing::Test 367 { 368 public: 369 }; // class compare 370 371 TEST_F(indexOfStr, indexOfStr_000) 372 { 373 // Former test passed (NULL, NULL) -> getLength(NULL) dereferences NULL (UB). 374 // Verify the empty-haystack boundary: nothing is found -> -1. 375 rtl::OString aStr1 = ""; 376 sal_Int32 nIndex = rtl_str_indexOfStr( aStr1.getStr(), "x" ); 377 ASSERT_TRUE(nIndex == -1) << "searching in an empty string must return -1."; 378 } 379 380 TEST_F(indexOfStr, indexOfStr_000_1) 381 { 382 // Former test passed a NULL needle -> getLength(NULL) (UB). 383 // Verify the empty-needle boundary: an empty search string is never found. 384 rtl::OString aStr1 = "Line for a indexOfStr."; 385 sal_Int32 nIndex = rtl_str_indexOfStr( aStr1.getStr(), "" ); 386 ASSERT_TRUE(nIndex == -1) << "an empty search string is never found -> -1."; 387 } 388 389 TEST_F(indexOfStr, indexOfStr_001) 390 { 391 rtl::OString aStr1 = "Line for a indexOfStr."; 392 393 sal_Int32 nIndex = rtl_str_indexOfStr( aStr1.getStr(), "Line" ); 394 ASSERT_TRUE(nIndex == 0) << "index is wrong."; 395 396 /* sal_Int32 */ nIndex = rtl_str_indexOfStr( aStr1.getStr(), "for" ); 397 ASSERT_TRUE(nIndex == 5) << "index is wrong."; 398 399 /* sal_Int32 */ nIndex = rtl_str_indexOfStr( aStr1.getStr(), "a" ); 400 ASSERT_TRUE(nIndex == 9) << "index is wrong."; 401 402 /* sal_Int32 */ nIndex = rtl_str_indexOfStr( aStr1.getStr(), "a index" ); 403 ASSERT_TRUE(nIndex ==9) << "index is wrong."; 404 } 405 406 TEST_F(indexOfStr, indexOfStr_002) 407 { 408 rtl::OString aStr1 = "Line for a indexOfStr."; 409 sal_Int32 nIndex = rtl_str_indexOfStr( aStr1.getStr(), "not exist" ); 410 411 ASSERT_TRUE(nIndex == -1) << "index is wrong."; 412 } 413 414 // ----------------------------------------------------------------------------- 415 416 417 class lastIndexOfStr : public ::testing::Test 418 { 419 public: 420 }; // class lastIndexOfStr 421 422 TEST_F(lastIndexOfStr, lastIndexOfStr_000) 423 { 424 // Former test passed (NULL, NULL) -> getLength(NULL) dereferences NULL (UB). 425 // Verify the empty-haystack boundary instead. 426 rtl::OString aStr1 = ""; 427 sal_Int32 nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), "Line" ); 428 ASSERT_TRUE(nIndex == -1) << "searching in an empty string must return -1."; 429 } 430 431 TEST_F(lastIndexOfStr, lastIndexOfStr_000_1) 432 { 433 // Former test passed a NULL needle -> getLength(NULL) (UB). 434 // Verify the empty-needle boundary: an empty search string is never found. 435 rtl::OString aStr1 = "Line for a lastIndexOfStr."; 436 sal_Int32 nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), "" ); 437 ASSERT_TRUE(nIndex == -1) << "an empty search string is never found -> -1."; 438 } 439 440 TEST_F(lastIndexOfStr, lastIndexOfStr_001) 441 { 442 rtl::OString aStr1 = "Line for a lastIndexOfStr."; 443 rtl::OString aSearchStr = "Index"; 444 445 sal_Int32 nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), aSearchStr.getStr() ); 446 ASSERT_TRUE(nIndex == 15) << "index is wrong."; 447 448 /* rtl::OString */ aSearchStr = "Line"; 449 /* sal_Int32 */ nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), aSearchStr.getStr() ); 450 ASSERT_TRUE(nIndex == 0) << "index is wrong."; 451 452 /* rtl::OString */ aSearchStr = ""; 453 /* sal_Int32 */ nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), aSearchStr.getStr() ); 454 ASSERT_TRUE(nIndex == -1) << "index is wrong."; 455 } 456 457 TEST_F(lastIndexOfStr, lastIndexOfStr_002) 458 { 459 rtl::OString aStr1 = "Line for a lastIndexOfStr."; 460 rtl::OString aSearchStr = "foo"; 461 sal_Int32 nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), aSearchStr.getStr() ); 462 463 ASSERT_TRUE(nIndex == -1) << "index is wrong."; 464 } 465 466 TEST_F(lastIndexOfStr, lastIndexOfStr_003) 467 { 468 rtl::OString aStr1 = "Line for a lastIndexOfStr."; 469 rtl::OString aSearchStr = "O"; 470 sal_Int32 nIndex = rtl_str_lastIndexOfStr( aStr1.getStr(), aSearchStr.getStr() ); 471 472 ASSERT_TRUE(nIndex == 20) << "index is wrong."; 473 } 474 475 // ----------------------------------------------------------------------------- 476 477 class replaceChar : public ::testing::Test 478 { 479 public: 480 }; // class replaceChar 481 482 TEST_F(replaceChar, replaceChar_000) 483 { 484 // Former test passed NULL -> while(*pStr) dereferences NULL (UB). 485 // Verify the empty-string boundary: replacing in "" is a no-op. 486 sal_Char pStr[] = ""; 487 rtl_str_replaceChar( pStr, 'a', 'b' ); 488 ASSERT_TRUE(pStr[0] == 0) << "replacing in an empty string must leave it empty."; 489 } 490 491 TEST_F(replaceChar, replaceChar_001) 492 { 493 rtl::OString aStr1 = "replace char."; 494 rtl::OString aShouldStr1 = "ruplacu char."; 495 496 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 497 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 498 strcpy(pStr, aStr1.getStr()); 499 500 rtl_str_replaceChar( pStr, 'e', 'u' ); 501 502 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "replace failed"; 503 free(pStr); 504 } 505 506 // ----------------------------------------------------------------------------- 507 508 class replaceChar_WithLength : public ::testing::Test 509 { 510 public: 511 }; // class replaceChar 512 513 TEST_F(replaceChar_WithLength, replaceChar_WithLength_000) 514 { 515 // Length-bounded: NULL data with length 0 never dereferences -> no-op. 516 // Keep the NULL+0 call as a regression guard for that tolerance. 517 rtl_str_replaceChar_WithLength( NULL, 0, 0, 0 ); 518 SUCCEED() << "NULL data with zero length must be tolerated (no dereference)."; 519 } 520 521 TEST_F(replaceChar_WithLength, replaceChar_WithLength_000_1) 522 { 523 // Former test passed (NULL, 1, ...) -> the loop runs once and 524 // dereferences NULL (UB). Verify the length bound instead: only the 525 // first nLen characters are touched, the rest are left intact. 526 sal_Char pStr[] = "aaaa"; 527 rtl_str_replaceChar_WithLength( pStr, 2, 'a', 'b' ); 528 ASSERT_TRUE(rtl::OString(pStr).equals(rtl::OString("bbaa")) == sal_True) 529 << "only the first nLen characters must be replaced."; 530 } 531 TEST_F(replaceChar_WithLength, replaceChar_WithLength_001) 532 { 533 rtl::OString aStr1 = "replace char."; 534 rtl::OString aShouldStr1 = "ruplace char."; 535 536 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 537 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 538 strcpy(pStr, aStr1.getStr()); 539 540 rtl_str_replaceChar_WithLength( pStr, 6, 'e', 'u' ); 541 542 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "replace failed"; 543 free(pStr); 544 } 545 546 // ----------------------------------------------------------------------------- 547 548 class toAsciiLowerCase : public ::testing::Test 549 { 550 public: 551 }; // class replaceChar 552 553 TEST_F(toAsciiLowerCase, toAsciiLowerCase_000) 554 { 555 // Former test passed NULL -> while(*pStr) dereferences NULL (UB). 556 // Verify the empty-string boundary: lowercasing "" is a no-op. 557 sal_Char pStr[] = ""; 558 rtl_str_toAsciiLowerCase( pStr ); 559 ASSERT_TRUE(pStr[0] == 0) << "lowercasing an empty string must leave it empty."; 560 } 561 562 TEST_F(toAsciiLowerCase, toAsciiLowerCase_001) 563 { 564 rtl::OString aStr1 = "CHANGE THIS TO ASCII LOWER CASE."; 565 rtl::OString aShouldStr1 = "change this to ascii lower case."; 566 567 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 568 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 569 strcpy(pStr, aStr1.getStr()); 570 571 rtl_str_toAsciiLowerCase( pStr ); 572 573 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "failed"; 574 free(pStr); 575 } 576 577 class toAsciiLowerCase_WithLength : public ::testing::Test 578 { 579 public: 580 }; // class replaceChar 581 582 TEST_F(toAsciiLowerCase_WithLength, toAsciiLowerCase_WithLength_000) 583 { 584 // Length-bounded: NULL data with length 0 never dereferences -> no-op. 585 rtl_str_toAsciiLowerCase_WithLength( NULL, 0 ); 586 SUCCEED() << "NULL data with zero length must be tolerated (no dereference)."; 587 } 588 589 TEST_F(toAsciiLowerCase_WithLength, toAsciiLowerCase_WithLength_001) 590 { 591 rtl::OString aStr1 = "CHANGE THIS TO ASCII LOWER CASE."; 592 rtl::OString aShouldStr1 = "change thiS TO ASCII LOWER CASE."; 593 594 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 595 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 596 strcpy(pStr, aStr1.getStr()); 597 598 rtl_str_toAsciiLowerCase_WithLength( pStr, 10 ); 599 600 printf("Lowercase with length: '%s'\n", pStr); 601 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "failed"; 602 free(pStr); 603 } 604 605 // ----------------------------------------------------------------------------- 606 607 class toAsciiUpperCase : public ::testing::Test 608 { 609 public: 610 }; // class replaceChar 611 612 TEST_F(toAsciiUpperCase, toAsciiUpperCase_000) 613 { 614 // Former test passed NULL -> while(*pStr) dereferences NULL (UB). 615 // Verify the empty-string boundary: uppercasing "" is a no-op. 616 sal_Char pStr[] = ""; 617 rtl_str_toAsciiUpperCase( pStr ); 618 ASSERT_TRUE(pStr[0] == 0) << "uppercasing an empty string must leave it empty."; 619 } 620 621 TEST_F(toAsciiUpperCase, toAsciiUpperCase_001) 622 { 623 rtl::OString aStr1 = "change this to ascii upper case."; 624 rtl::OString aShouldStr1 = "CHANGE THIS TO ASCII UPPER CASE."; 625 626 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 627 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 628 strcpy(pStr, aStr1.getStr()); 629 630 rtl_str_toAsciiUpperCase( pStr ); 631 632 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "failed"; 633 free(pStr); 634 } 635 636 class toAsciiUpperCase_WithLength : public ::testing::Test 637 { 638 public: 639 }; // class replaceChar 640 641 TEST_F(toAsciiUpperCase_WithLength, toAsciiUpperCase_WithLength_000) 642 { 643 // Length-bounded: NULL data with length 0 never dereferences -> no-op. 644 rtl_str_toAsciiUpperCase_WithLength( NULL, 0 ); 645 SUCCEED() << "NULL data with zero length must be tolerated (no dereference)."; 646 } 647 648 TEST_F(toAsciiUpperCase_WithLength, toAsciiUpperCase_WithLength_001) 649 { 650 rtl::OString aStr1 = "change this to ascii lower case."; 651 rtl::OString aShouldStr1 = "CHANGE THIs to ascii lower case."; 652 653 sal_Char* pStr = (sal_Char*) malloc(aStr1.getLength() + 1); 654 ASSERT_TRUE(pStr != NULL) << "can't get memory for test"; 655 656 strcpy(pStr, aStr1.getStr()); 657 rtl_str_toAsciiUpperCase_WithLength( pStr, 10 ); 658 659 printf("Uppercase with length: '%s'\n", aStr1.getStr()); 660 ASSERT_TRUE(aShouldStr1.equals(rtl::OString(pStr)) == sal_True) << "failed"; 661 free(pStr); 662 } 663 664 // ----------------------------------------------------------------------------- 665 666 class trim_WithLength : public ::testing::Test 667 { 668 public: 669 }; 670 671 TEST_F(trim_WithLength, trim_WithLength_000) 672 { 673 // Length-bounded: NULL data with length 0 never dereferences and 674 // returns the resulting length 0. 675 sal_Int32 nLen = rtl_str_trim_WithLength(NULL, 0); 676 ASSERT_TRUE(nLen == 0) << "trimming a zero-length string must return 0 (and not GPF)."; 677 } 678 679 TEST_F(trim_WithLength, trim_WithLength_000_1) 680 { 681 char pStr[] = { " trim this" }; 682 rtl_str_trim_WithLength( pStr, 0 ); 683 } 684 685 TEST_F(trim_WithLength, trim_WithLength_001) 686 { 687 char const *pStr = " trim this"; 688 sal_Char *pStr2 = (sal_Char*)malloc(strlen(pStr) + 1); 689 if (pStr2) 690 { 691 strcpy(pStr2, pStr); 692 rtl_str_trim_WithLength( pStr2, 2 ); 693 694 ASSERT_TRUE(strlen(pStr2) == 0) << "string should be empty"; 695 free(pStr2); 696 } 697 } 698 699 TEST_F(trim_WithLength, trim_WithLength_002) 700 { 701 char const *pStr = "trim this"; 702 sal_Char *pStr2 = (sal_Char*)malloc(strlen(pStr) + 1); 703 if (pStr2) 704 { 705 strcpy(pStr2, pStr); 706 rtl_str_trim_WithLength( pStr2, 5 ); 707 708 ASSERT_TRUE(strlen(pStr2) == 4) << "string should contain 'trim'"; 709 free(pStr2); 710 } 711 } 712 713 TEST_F(trim_WithLength, trim_WithLength_003) 714 { 715 char const *pStr = " trim this"; 716 sal_Char *pStr2 = (sal_Char*)malloc(strlen(pStr) + 1); 717 if (pStr2) 718 { 719 strcpy(pStr2, pStr); 720 rtl_str_trim_WithLength( pStr2, 11 ); 721 722 ASSERT_TRUE(strlen(pStr2) == 4) << "string should contain 'trim'"; 723 free(pStr2); 724 } 725 } 726 727 TEST_F(trim_WithLength, trim_WithLength_004) 728 { 729 char const *pStr = "\r\n\t \n\r trim \n this"; 730 sal_Char *pStr2 = (sal_Char*)malloc(strlen(pStr) + 1); 731 if (pStr2) 732 { 733 strcpy(pStr2, pStr); 734 rtl_str_trim_WithLength( pStr2, 17 ); 735 736 ASSERT_TRUE(strlen(pStr2) == 4) << "string should contain 'trim'"; 737 free(pStr2); 738 } 739 } 740 741 TEST_F(trim_WithLength, trim_WithLength_005) 742 { 743 char const *pStr = "\r\n\t \n\r trim \t this \n\r\t\t "; 744 sal_Char *pStr2 = (sal_Char*)malloc(strlen(pStr) + 1); 745 if (pStr2) 746 { 747 strcpy(pStr2, pStr); 748 rtl_str_trim_WithLength( pStr2, strlen(pStr2) ); 749 ASSERT_TRUE(strlen(pStr2) == 11) << "string should contain 'trim'"; 750 free(pStr2); 751 } 752 } 753 754 // ----------------------------------------------------------------------------- 755 756 class valueOfChar : public ::testing::Test 757 { 758 public: 759 }; 760 761 TEST_F(valueOfChar, valueOfChar_000) 762 { 763 // Former test passed NULL -> the function writes through NULL (UB); 764 // the "should not GPF" comment was wrong, it always did. 765 // Verify the documented behaviour on a real buffer: writes the char 766 // and a terminating NUL, returns 1. 767 sal_Char pStr[RTL_STR_MAX_VALUEOFCHAR]; 768 sal_Int32 nLen = rtl_str_valueOfChar(pStr, 'Z'); 769 ASSERT_TRUE(nLen == 1) << "valueOfChar must return 1."; 770 ASSERT_TRUE(pStr[0] == 'Z') << "valueOfChar must write the character."; 771 ASSERT_TRUE(pStr[1] == 0) << "valueOfChar must NUL-terminate."; 772 } 773 TEST_F(valueOfChar, valueOfChar_001) 774 { 775 sal_Char *pStr = (sal_Char*)malloc(RTL_STR_MAX_VALUEOFCHAR); 776 if (pStr) 777 { 778 rtl_str_valueOfChar(pStr, 'A'); 779 780 ASSERT_TRUE(pStr[0] == 'A') << "string should contain 'A'"; 781 free(pStr); 782 } 783 } 784 785 } // namespace rtl_str 786 787 int main(int argc, char **argv) 788 { 789 ::testing::InitGoogleTest(&argc, argv); 790 return RUN_ALL_TESTS(); 791 } 792