1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 // activate the extra needed ctor
11 #define RTL_STRING_UNITTEST
13 #include <sal/config.h>
17 #include <sal/types.h>
18 #include <config_global.h>
19 #include <cppunit/TestFixture.h>
20 #include <cppunit/extensions/HelperMacros.h>
21 #include <rtl/string.h>
22 #include <rtl/ustring.hxx>
23 #include <rtl/ustrbuf.hxx>
25 extern bool rtl_string_unittest_const_literal
;
26 bool rtl_string_unittest_invalid_conversion
;
28 namespace test
{ namespace oustring
{
30 class StringLiterals
: public CppUnit::TestFixture
35 void checkExtraIntArgument();
36 void checkNonconstChar();
38 void checkOUStringLiteral();
39 void checkOUStringLiteral1();
42 void testcall( const char str
[] );
44 CPPUNIT_TEST_SUITE(StringLiterals
);
45 CPPUNIT_TEST(checkCtors
);
46 CPPUNIT_TEST(checkUsage
);
47 CPPUNIT_TEST(checkExtraIntArgument
);
48 CPPUNIT_TEST(checkNonconstChar
);
49 CPPUNIT_TEST(checkBuffer
);
50 CPPUNIT_TEST(checkOUStringLiteral
);
51 CPPUNIT_TEST(checkOUStringLiteral1
);
52 CPPUNIT_TEST(checkUtf16
);
53 CPPUNIT_TEST_SUITE_END();
56 // reset the flag, evaluate the expression and return
57 // whether the string literal ctor was used (i.e. whether the conversion was valid)
58 template<typename T
> bool VALID_CONVERSION( T
&& expression
)
60 rtl_string_unittest_invalid_conversion
= false;
61 // OK to std::forward expression twice; what is relevant in both ctor calls
62 // is not the content of the passed argument (which is ignored anyway by the
63 // special RTL_STRING_UNITTEST ctors) but only its type:
64 ( void ) rtl::OUString( std::forward
<T
>(expression
) );
65 ( void ) rtl::OUStringBuffer( std::forward
<T
>(expression
) );
66 return !rtl_string_unittest_invalid_conversion
;
68 template<typename T
> bool VALID_CONVERSION_CALL( T f
)
70 rtl_string_unittest_invalid_conversion
= false;
71 ( void ) rtl::OUString( f() );
72 ( void ) rtl::OUStringBuffer( f() );
73 return !rtl_string_unittest_invalid_conversion
;
76 void test::oustring::StringLiterals::checkCtors()
78 CPPUNIT_ASSERT( VALID_CONVERSION( "test" ));
79 const char good1
[] = "test";
80 CPPUNIT_ASSERT( VALID_CONVERSION( good1
));
82 CPPUNIT_ASSERT( !VALID_CONVERSION( static_cast<const char*>("test") ));
83 const char* bad1
= good1
;
84 CPPUNIT_ASSERT( !VALID_CONVERSION( bad1
));
86 CPPUNIT_ASSERT( !VALID_CONVERSION( bad2
));
88 CPPUNIT_ASSERT( !VALID_CONVERSION( bad3
));
89 const char* bad4
[] = { "test1" };
90 CPPUNIT_ASSERT( !VALID_CONVERSION( bad4
[ 0 ] ));
93 // This one is technically broken, since the first element is 6 characters test\0\0,
94 // but there does not appear a way to detect this by compile time (runtime will assert()).
95 // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
96 const char bad5
[][ 6 ] = { "test", "test2" };
97 // CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 0 ] ));
98 CPPUNIT_ASSERT( VALID_CONVERSION( bad5
[ 1 ] ));
100 // Check that contents are correct and equal to the case when RTL_CONSTASCII_USTRINGPARAM is used.
101 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "" ), rtl::OUString( "" ));
102 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "ab" ), rtl::OUString( "ab" ));
104 // Also check that embedded \0 is included.
105 // In fact, allowing this is probably just trouble, so this now asserts.
106 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "\0" ), rtl::OUString( "\0" ));
107 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "a\0b" ), rtl::OUString( "a\0b" ));
111 void test::oustring::StringLiterals::testcall( const char str
[] )
114 !VALID_CONVERSION_CALL([&str
]() { return rtl::OUString(str
); }));
117 void test::oustring::StringLiterals::checkUsage()
119 // simply check that all string literal based calls work as expected
120 // also check that they really use string literal overload and do not convert to OUString
121 rtl::OUString
foo( "foo" );
122 rtl::OUString
FoO( "FoO" );
123 rtl::OUString
foobarfoo( "foobarfoo" );
124 rtl::OUString
foobar( "foobar" );
125 rtl::OUString
FooBaRfoo( "FooBaRfoo" );
126 rtl::OUString
FooBaR( "FooBaR" );
127 rtl::OUString
bar( "bar" );
128 rtl::OUString
test( "test" );
130 rtl_string_unittest_const_literal
= false; // start checking for OUString conversions
131 CPPUNIT_ASSERT_EQUAL( foo
, rtl::OUString() = "foo" );
132 CPPUNIT_ASSERT( FoO
.equalsIgnoreAsciiCase( "fOo" ));
133 CPPUNIT_ASSERT( foobarfoo
.match( "bar", 3 ));
134 CPPUNIT_ASSERT( foobar
.match( "foo" ));
135 CPPUNIT_ASSERT( FooBaRfoo
.matchIgnoreAsciiCase( "bAr", 3 ));
136 CPPUNIT_ASSERT( FooBaR
.matchIgnoreAsciiCase( "fOo" ));
137 CPPUNIT_ASSERT( foobar
.startsWith( "foo" ));
138 CPPUNIT_ASSERT( FooBaR
.startsWithIgnoreAsciiCase( "foo" ));
139 CPPUNIT_ASSERT( foobar
.endsWith( "bar" ));
140 CPPUNIT_ASSERT( FooBaR
.endsWithIgnoreAsciiCase( "bar" ));
141 CPPUNIT_ASSERT( bool(foo
== "foo") );
142 CPPUNIT_ASSERT( bool("foo" == foo
) );
143 CPPUNIT_ASSERT( foo
!= "bar" );
144 CPPUNIT_ASSERT( "foo" != bar
);
145 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(6), foobarfoo
.indexOf( "foo", 1 ) );
146 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(6), foobarfoo
.lastIndexOf( "foo" ) );
147 CPPUNIT_ASSERT( bool(foobarfoo
.replaceFirst( "foo", test
) == "testbarfoo") );
148 CPPUNIT_ASSERT( bool(foobarfoo
.replaceFirst( "foo", "test" ) == "testbarfoo") );
149 CPPUNIT_ASSERT( bool(foobarfoo
.replaceAll( "foo", test
) == "testbartest") );
150 CPPUNIT_ASSERT( bool(foobarfoo
.replaceAll( "foo", "test" ) == "testbartest") );
151 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(0), foo
.reverseCompareTo( "foo" ) );
152 // if this is not true, some of the calls above converted to OUString
153 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal
);
156 void test::oustring::StringLiterals::checkExtraIntArgument()
158 // This makes sure that using by mistake RTL_CONSTASCII_STRINGPARAM does not trigger a different
159 // overload, i.e. the second argument to match() in this case is the indexFrom argument,
160 // but with the macro it would contain the length of the string. Therefore
161 // match( RTL_CONSTASCII_STRINGPARAM( "bar" )) would be match( "bar", 3 ), which would be
162 // true when called for OUString( "foobar" ). But this should not happen because of the
163 // &foo[0] trick in the RTL_CONSTASCII_STRINGPARAM macro.
164 CPPUNIT_ASSERT( !rtl::OUString("foobar").match( "bar" ));
165 CPPUNIT_ASSERT( !rtl::OUString("foobar").match( RTL_CONSTASCII_STRINGPARAM( "bar" )));
168 void test::oustring::StringLiterals::checkNonconstChar()
169 { // check that non-const char[] data do not trigger string literal overloads
170 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), rtl::OUString( "footest" ).replaceAll( "test", "bar" ));
171 char test
[] = "test";
173 const char consttest
[] = "test";
174 const char constbar
[] = "bar";
176 !VALID_CONVERSION_CALL(
178 return rtl::OUString("footest").replaceAll(test
, bar
); }));
180 !VALID_CONVERSION_CALL(
181 [&consttest
, &bar
]() {
182 return rtl::OUString("footest").replaceAll(consttest
, bar
); }));
185 [&test
, &constbar
]() {
186 return rtl::OUString("footest").replaceAll(test
, constbar
); }));
187 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), rtl::OUString( "footest" ).replaceAll( consttest
, constbar
));
190 void test::oustring::StringLiterals::checkBuffer()
192 rtl::OUStringBuffer buf
;
194 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foo" ), buf
.toString());
196 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), buf
.toString());
197 buf
.insert( 3, "baz" );
198 CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobazbar" ), buf
.toString());
200 CPPUNIT_ASSERT( !VALID_CONVERSION( buf
.append( rtl::OUString( d
))));
201 CPPUNIT_ASSERT( !VALID_CONVERSION( buf
.append( rtl::OUStringBuffer( d
))));
206 rtl::OUString
conditional(bool flag
) {
208 ? rtlunittest::OUStringLiteral("a")
209 : rtlunittest::OUStringLiteral("bb");
214 void test::oustring::StringLiterals::checkOUStringLiteral()
216 CPPUNIT_ASSERT(bool(conditional(true) == "a"));
217 CPPUNIT_ASSERT(bool(conditional(false) == "bb"));
219 rtl::OUString
s1(rtlunittest::OUStringLiteral("abc"));
220 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1
);
221 s1
= rtlunittest::OUStringLiteral("de");
222 CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1
);
223 s1
+= rtlunittest::OUStringLiteral("fde");
224 CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1
);
225 CPPUNIT_ASSERT_EQUAL(
227 s1
.reverseCompareTo(rtlunittest::OUStringLiteral("defde")));
229 s1
.equalsIgnoreAsciiCase(rtlunittest::OUStringLiteral("DEFDE")));
230 CPPUNIT_ASSERT(s1
.match(rtlunittest::OUStringLiteral("fde"), 2));
232 s1
.matchIgnoreAsciiCase(rtlunittest::OUStringLiteral("FDE"), 2));
234 CPPUNIT_ASSERT(s1
.startsWith(rtlunittest::OUStringLiteral("de"), &s2
));
235 CPPUNIT_ASSERT_EQUAL(rtl::OUString("fde"), s2
);
237 s1
.startsWithIgnoreAsciiCase(
238 rtlunittest::OUStringLiteral("DEFD"), &s2
));
239 CPPUNIT_ASSERT_EQUAL(rtl::OUString("e"), s2
);
240 CPPUNIT_ASSERT(s1
.endsWith(rtlunittest::OUStringLiteral("de"), &s2
));
241 CPPUNIT_ASSERT_EQUAL(rtl::OUString("def"), s2
);
243 s1
.endsWithIgnoreAsciiCase(rtlunittest::OUStringLiteral("EFDE"), &s2
));
244 CPPUNIT_ASSERT_EQUAL(rtl::OUString("d"), s2
);
245 CPPUNIT_ASSERT(bool(s1
== rtlunittest::OUStringLiteral("defde")));
246 CPPUNIT_ASSERT(bool(rtlunittest::OUStringLiteral("defde") == s1
));
247 CPPUNIT_ASSERT(s1
!= rtlunittest::OUStringLiteral("abc"));
248 CPPUNIT_ASSERT(rtlunittest::OUStringLiteral("abc") != s1
);
249 CPPUNIT_ASSERT_EQUAL(
250 sal_Int32(3), s1
.indexOf(rtlunittest::OUStringLiteral("de"), 1));
251 CPPUNIT_ASSERT_EQUAL(
252 sal_Int32(3), s1
.lastIndexOf(rtlunittest::OUStringLiteral("de")));
254 CPPUNIT_ASSERT_EQUAL(
255 rtl::OUString("abcfde"),
257 rtlunittest::OUStringLiteral("de"), rtl::OUString("abc"), &i
));
258 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
259 CPPUNIT_ASSERT_EQUAL(
260 rtl::OUString("abcfde"),
262 rtl::OUString("de"), rtlunittest::OUStringLiteral("abc"), &i
));
263 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
264 CPPUNIT_ASSERT_EQUAL(
265 rtl::OUString("abcfde"),
267 rtlunittest::OUStringLiteral("de"),
268 rtlunittest::OUStringLiteral("abc"), &i
));
269 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
270 CPPUNIT_ASSERT_EQUAL(
271 rtl::OUString("abcfde"),
272 s1
.replaceFirst(rtlunittest::OUStringLiteral("de"), "abc", &i
));
273 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
274 CPPUNIT_ASSERT_EQUAL(
275 rtl::OUString("abcfde"),
276 s1
.replaceFirst("de", rtlunittest::OUStringLiteral("abc"), &i
));
277 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
278 CPPUNIT_ASSERT_EQUAL(
279 rtl::OUString("abcfabc"),
281 rtlunittest::OUStringLiteral("de"), rtl::OUString("abc")));
282 CPPUNIT_ASSERT_EQUAL(
283 rtl::OUString("abcfabc"),
285 rtl::OUString("de"), rtlunittest::OUStringLiteral("abc")));
286 CPPUNIT_ASSERT_EQUAL(
287 rtl::OUString("abcfabc"),
289 rtlunittest::OUStringLiteral("de"),
290 rtlunittest::OUStringLiteral("abc")));
291 CPPUNIT_ASSERT_EQUAL(
292 rtl::OUString("abcfabc"),
293 s1
.replaceAll(rtlunittest::OUStringLiteral("de"), "abc"));
294 CPPUNIT_ASSERT_EQUAL(
295 rtl::OUString("abcfabc"),
296 s1
.replaceAll("de", rtlunittest::OUStringLiteral("abc")));
297 CPPUNIT_ASSERT_EQUAL(
298 rtl::OUString("abcdef"),
300 rtl::OUString("abc") + rtlunittest::OUStringLiteral("def")));
301 CPPUNIT_ASSERT_EQUAL(
302 rtl::OUString("abcdef"),
304 rtlunittest::OUStringLiteral("abc") + rtl::OUString("def")));
305 rtl::OUStringBuffer
b(rtlunittest::OUStringLiteral("abc"));
306 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b
.toString());
307 b
.append(rtlunittest::OUStringLiteral("def"));
308 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b
.toString());
309 b
.insert(2, rtlunittest::OUStringLiteral("gabab"));
310 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b
.toString());
311 CPPUNIT_ASSERT_EQUAL(
312 sal_Int32(3), b
.indexOf(rtlunittest::OUStringLiteral("ab"), 1));
313 CPPUNIT_ASSERT_EQUAL(
314 sal_Int32(5), b
.lastIndexOf(rtlunittest::OUStringLiteral("ab")));
317 void test::oustring::StringLiterals::checkOUStringLiteral1()
319 auto l1
= rtlunittest::OUStringLiteral1('A');
320 CPPUNIT_ASSERT_EQUAL(u
'A', l1
.c
);
323 auto l2
= rtlunittest::OUStringLiteral1(c2
);
324 CPPUNIT_ASSERT_EQUAL(u
'A', l2
.c
);
326 char c3
= 'A'; auto l3
= rtlunittest::OUStringLiteral1(c3
);
327 CPPUNIT_ASSERT_EQUAL(u
'A', l3
.c
);
329 auto l4
= rtlunittest::OUStringLiteral1(u
'A');
330 CPPUNIT_ASSERT_EQUAL(u
'A', l4
.c
);
332 sal_Unicode
const c5
= 0x100;
333 auto l5
= rtlunittest::OUStringLiteral1(c5
);
334 CPPUNIT_ASSERT_EQUAL(c5
, l5
.c
);
336 rtl::OUString s1
{rtlunittest::OUStringLiteral1('A')};
337 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), s1
.getLength());
338 CPPUNIT_ASSERT_EQUAL(u
'A', s1
[0]);
340 CPPUNIT_ASSERT_EQUAL(
341 true, rtl::OUString("A") == rtlunittest::OUStringLiteral1('A'));
342 CPPUNIT_ASSERT_EQUAL(
343 false, rtl::OUString("AB") == rtlunittest::OUStringLiteral1('A'));
344 CPPUNIT_ASSERT_EQUAL(
345 false, rtl::OUString("A") != rtlunittest::OUStringLiteral1('A'));
346 CPPUNIT_ASSERT_EQUAL(
347 true, rtl::OUString("AB") != rtlunittest::OUStringLiteral1('A'));
349 rtl::OUString
s2("A" + rtlunittest::OUStringLiteral1('b'));
350 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), s2
.getLength());
351 CPPUNIT_ASSERT_EQUAL(u
'A', s2
[0]);
352 CPPUNIT_ASSERT_EQUAL(u
'b', s2
[1]);
355 void test::oustring::StringLiterals::checkUtf16() {
356 rtl::OUString
s1(u
"abc");
357 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1
);
359 CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1
);
361 CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1
);
362 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), s1
.reverseCompareTo(u
"defde"));
363 CPPUNIT_ASSERT(s1
.equalsIgnoreAsciiCase(u
"DEFDE"));
364 CPPUNIT_ASSERT(s1
.match(u
"fde", 2));
365 CPPUNIT_ASSERT(s1
.matchIgnoreAsciiCase(u
"FDE", 2));
367 CPPUNIT_ASSERT(s1
.startsWith(u
"de", &s2
));
368 CPPUNIT_ASSERT_EQUAL(rtl::OUString(u
"fde"), s2
);
369 CPPUNIT_ASSERT(s1
.startsWithIgnoreAsciiCase(u
"DEFD", &s2
));
370 CPPUNIT_ASSERT_EQUAL(rtl::OUString(u
"e"), s2
);
371 CPPUNIT_ASSERT(s1
.endsWith(u
"de", &s2
));
372 CPPUNIT_ASSERT_EQUAL(rtl::OUString(u
"def"), s2
);
373 CPPUNIT_ASSERT(s1
.endsWithIgnoreAsciiCase(u
"EFDE", &s2
));
374 CPPUNIT_ASSERT_EQUAL(rtl::OUString(u
"d"), s2
);
375 CPPUNIT_ASSERT(bool(s1
== u
"defde"));
376 CPPUNIT_ASSERT(bool(u
"defde" == s1
));
377 CPPUNIT_ASSERT(s1
!= u
"abc");
378 CPPUNIT_ASSERT(u
"abc" != s1
);
379 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1
.indexOf(u
"de", 1));
380 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1
.lastIndexOf(u
"de"));
382 CPPUNIT_ASSERT_EQUAL(
383 rtl::OUString(u
"abcfde"),
384 s1
.replaceFirst(u
"de", rtl::OUString("abc"), &i
));
385 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
386 CPPUNIT_ASSERT_EQUAL(
387 rtl::OUString(u
"abcfde"),
388 s1
.replaceFirst(rtl::OUString("de"), u
"abc", &i
));
389 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
390 CPPUNIT_ASSERT_EQUAL(
391 rtl::OUString(u
"abcfde"), s1
.replaceFirst(u
"de", u
"abc", &i
));
392 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
393 CPPUNIT_ASSERT_EQUAL(
394 rtl::OUString(u
"abcfde"), s1
.replaceFirst(u
"de", "abc", &i
));
395 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
396 CPPUNIT_ASSERT_EQUAL(
397 rtl::OUString(u
"abcfde"), s1
.replaceFirst("de", u
"abc", &i
));
398 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i
);
399 CPPUNIT_ASSERT_EQUAL(
400 rtl::OUString(u
"abcfabc"), s1
.replaceAll(u
"de", rtl::OUString("abc")));
401 CPPUNIT_ASSERT_EQUAL(
402 rtl::OUString(u
"abcfabc"), s1
.replaceAll(rtl::OUString("de"), u
"abc"));
403 CPPUNIT_ASSERT_EQUAL(
404 rtl::OUString(u
"abcfabc"), s1
.replaceAll(u
"de", u
"abc"));
405 CPPUNIT_ASSERT_EQUAL(
406 rtl::OUString(u
"abcfabc"), s1
.replaceAll(u
"de", "abc"));
407 CPPUNIT_ASSERT_EQUAL(
408 rtl::OUString(u
"abcfabc"), s1
.replaceAll("de", u
"abc"));
409 CPPUNIT_ASSERT_EQUAL(
410 rtl::OUString("abcdef"), rtl::OUString(rtl::OUString("abc") + u
"def"));
411 CPPUNIT_ASSERT_EQUAL(
412 rtl::OUString("abcdef"), rtl::OUString(u
"abc" + rtl::OUString("def")));
413 rtl::OUStringBuffer
b(u
"abc");
414 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b
.toString());
416 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b
.toString());
417 b
.insert(2, u
"gabab");
418 CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b
.toString());
419 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), b
.indexOf(u
"ab", 1));
420 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), b
.lastIndexOf(u
"ab"));
425 CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals
);
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */