xref: /trunk/main/sal/qa/rtl/ostring/rtl_str.cxx (revision f0853378f1a90e669189f0f58595ee993d034643)
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