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
TEST_F(compare,compare_000)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
TEST_F(compare,compare_000_1)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 }
TEST_F(compare,compare_001)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
TEST_F(compare,compare_002)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
TEST_F(compare,compare_003)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
TEST_F(compareIgnoreAsciiCase,compare_000)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
TEST_F(compareIgnoreAsciiCase,compare_000_1)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 }
TEST_F(compareIgnoreAsciiCase,compare_001)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
TEST_F(compareIgnoreAsciiCase,compare_002)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
TEST_F(compareIgnoreAsciiCase,compare_002_1)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
TEST_F(compareIgnoreAsciiCase,compare_003)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_000)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_000_1)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 }
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_001)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_002)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_002_1)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_003)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
TEST_F(shortenedCompareIgnoreAsciiCase_WithLength,compare_004)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
TEST_F(hashCode,hashCode_000)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
TEST_F(hashCode,hashCode_001)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
TEST_F(hashCode,hashCode_002)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
TEST_F(hashCode,hashCode_003)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
TEST_F(indexOfChar,indexOfChar_000)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
TEST_F(indexOfChar,indexOfChar_001)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
TEST_F(indexOfChar,indexOfChar_002)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
TEST_F(lastIndexOfChar,lastIndexOfChar_000)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
TEST_F(lastIndexOfChar,lastIndexOfChar_001)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
TEST_F(lastIndexOfChar,lastIndexOfChar_002)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
TEST_F(indexOfStr,indexOfStr_000)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
TEST_F(indexOfStr,indexOfStr_000_1)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
TEST_F(indexOfStr,indexOfStr_001)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
TEST_F(indexOfStr,indexOfStr_002)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
TEST_F(lastIndexOfStr,lastIndexOfStr_000)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
TEST_F(lastIndexOfStr,lastIndexOfStr_000_1)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
TEST_F(lastIndexOfStr,lastIndexOfStr_001)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
TEST_F(lastIndexOfStr,lastIndexOfStr_002)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
TEST_F(lastIndexOfStr,lastIndexOfStr_003)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
TEST_F(replaceChar,replaceChar_000)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
TEST_F(replaceChar,replaceChar_001)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
TEST_F(replaceChar_WithLength,replaceChar_WithLength_000)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
TEST_F(replaceChar_WithLength,replaceChar_WithLength_000_1)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 }
TEST_F(replaceChar_WithLength,replaceChar_WithLength_001)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
TEST_F(toAsciiLowerCase,toAsciiLowerCase_000)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
TEST_F(toAsciiLowerCase,toAsciiLowerCase_001)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
TEST_F(toAsciiLowerCase_WithLength,toAsciiLowerCase_WithLength_000)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
TEST_F(toAsciiLowerCase_WithLength,toAsciiLowerCase_WithLength_001)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
TEST_F(toAsciiUpperCase,toAsciiUpperCase_000)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
TEST_F(toAsciiUpperCase,toAsciiUpperCase_001)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
TEST_F(toAsciiUpperCase_WithLength,toAsciiUpperCase_WithLength_000)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
TEST_F(toAsciiUpperCase_WithLength,toAsciiUpperCase_WithLength_001)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
TEST_F(trim_WithLength,trim_WithLength_000)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
TEST_F(trim_WithLength,trim_WithLength_000_1)679 TEST_F(trim_WithLength, trim_WithLength_000_1)
680 {
681 char pStr[] = { " trim this" };
682 rtl_str_trim_WithLength( pStr, 0 );
683 }
684
TEST_F(trim_WithLength,trim_WithLength_001)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
TEST_F(trim_WithLength,trim_WithLength_002)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
TEST_F(trim_WithLength,trim_WithLength_003)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
TEST_F(trim_WithLength,trim_WithLength_004)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
TEST_F(trim_WithLength,trim_WithLength_005)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
TEST_F(valueOfChar,valueOfChar_000)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 }
TEST_F(valueOfChar,valueOfChar_001)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
main(int argc,char ** argv)787 int main(int argc, char **argv)
788 {
789 ::testing::InitGoogleTest(&argc, argv);
790 return RUN_ALL_TESTS();
791 }
792