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/types.h>
14 #include <cppunit/TestFixture.h>
15 #include <cppunit/extensions/HelperMacros.h>
16 #include <rtl/string.h>
17 #include <rtl/string.hxx>
18 #include <rtl/strbuf.hxx>
20 bool rtl_string_unittest_const_literal
;
21 bool rtl_string_unittest_const_literal_function
;
22 static bool rtl_string_unittest_non_const_literal_function
;
24 namespace test::ostring
{
26 class StringLiterals
: public CppUnit::TestFixture
30 void checkConstexprCtor();
32 void checkNonConstUsage();
35 void testcall( const char str
[] );
37 static const char bad5
[];
40 // Check that OStringLiteral ctor is actually constexpr:
41 static constexpr rtlunittest::OStringLiteral dummy
{"dummy"};
43 CPPUNIT_TEST_SUITE(StringLiterals
);
44 CPPUNIT_TEST(checkCtors
);
45 CPPUNIT_TEST(checkConstexprCtor
);
46 CPPUNIT_TEST(checkUsage
);
47 CPPUNIT_TEST(checkNonConstUsage
);
48 CPPUNIT_TEST(checkBuffer
);
49 CPPUNIT_TEST_SUITE_END();
52 // reset the flag, call OString ctor with the given argument and return
53 // whether the string literal ctor was used
54 #define CONST_CTOR_USED( argument ) \
56 rtl_string_unittest_const_literal = false, \
57 ( void ) rtl::OString( argument ), \
58 result_tmp = rtl_string_unittest_const_literal, \
59 rtl_string_unittest_const_literal = false, \
60 ( void ) rtl::OStringBuffer( argument ), \
61 rtl_string_unittest_const_literal && result_tmp )
63 void test::ostring::StringLiterals::checkCtors()
66 CPPUNIT_ASSERT( CONST_CTOR_USED( "test" ));
67 const char good1
[] = "test";
68 CPPUNIT_ASSERT( CONST_CTOR_USED( good1
));
70 CPPUNIT_ASSERT( !CONST_CTOR_USED( static_cast<const char*>("test") ));
71 const char* bad1
= good1
;
72 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad1
));
74 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad2
));
76 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad3
));
77 const char* bad4
[] = { "test1" };
78 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad4
[ 0 ] ));
81 // this is actually not supposed to work (see discussion in stringutils.hxx),
82 // but gcc and clang somehow manage, so keep it used, just in case some other problem
83 // shows up somewhen in the future
84 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad5
)); // size is not known here
85 CPPUNIT_ASSERT( !CONST_CTOR_USED( bad6
));
88 // This one is technically broken, since the first element is 6 characters test\0\0,
89 // but there does not appear a way to detect this by compile time (runtime will assert()).
90 // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
91 const char bad7
[][ 6 ] = { "test", "test2" };
92 // CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 0 ] ));
93 CPPUNIT_ASSERT( CONST_CTOR_USED( bad7
[ 1 ] ));
95 // Check that contents are correct and equal to the case when const char* ctor is used.
96 CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( static_cast<const char*>("") ) );
97 CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( static_cast<const char*>("ab") ) );
99 // Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used.
100 CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) );
101 CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) );
104 const char test::ostring::StringLiterals::bad5
[] = "test";
105 char test::ostring::StringLiterals::bad6
[] = "test";
107 void test::ostring::StringLiterals::testcall( const char str
[] )
111 CPPUNIT_ASSERT( !CONST_CTOR_USED( str
));
113 // MSVC just errors out on this for some reason, which is fine as well
118 void test::ostring::StringLiterals::checkConstexprCtor()
120 #if __cplusplus >= 202002L
123 rtl::OString
s(dummy
);
124 CPPUNIT_ASSERT_EQUAL(oslInterlockedCount(0x40000000), s
.pData
->refCount
);
125 // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
126 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), s
.getLength());
127 CPPUNIT_ASSERT_EQUAL(rtl::OString("dummy"), s
);
128 CPPUNIT_ASSERT_EQUAL(
129 static_cast<void const *>(dummy
.getStr()), static_cast<void const *>(s
.getStr()));
132 void test::ostring::StringLiterals::checkUsage()
134 // simply check that all string literal based calls work as expected
135 // also check that they really use string literal overload and do not convert to OString
136 rtl::OString
foo( "foo" );
137 rtl::OString
FoO( "FoO" );
138 rtl::OString
foobarfoo( "foobarfoo" );
139 rtl::OString
foobar( "foobar" );
140 rtl::OString
FooBaRfoo( "FooBaRfoo" );
141 rtl::OString
FooBaR( "FooBaR" );
142 rtl::OString
bar( "bar" );
144 rtl_string_unittest_const_literal
= false; // start checking for OString conversions
145 rtl_string_unittest_non_const_literal_function
= false; // and check for non-const variants
146 rtl_string_unittest_const_literal_function
= false;
147 CPPUNIT_ASSERT_EQUAL( foo
, rtl::OString() = "foo" );
148 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
149 rtl_string_unittest_const_literal_function
= false;
150 CPPUNIT_ASSERT( FoO
.equalsIgnoreAsciiCase( "fOo" ));
151 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
152 rtl_string_unittest_const_literal_function
= false;
153 CPPUNIT_ASSERT( foobarfoo
.match( "bar", 3 ));
154 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
155 rtl_string_unittest_const_literal_function
= false;
156 CPPUNIT_ASSERT( foobar
.match( "foo" ));
157 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
158 rtl_string_unittest_const_literal_function
= false;
159 CPPUNIT_ASSERT( FooBaRfoo
.matchIgnoreAsciiCase( "bAr", 3 ));
160 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
161 rtl_string_unittest_const_literal_function
= false;
162 CPPUNIT_ASSERT( FooBaR
.matchIgnoreAsciiCase( "fOo" ));
163 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
164 rtl_string_unittest_const_literal_function
= false;
165 CPPUNIT_ASSERT( foobar
.startsWith( "foo" ));
166 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
167 rtl_string_unittest_const_literal_function
= false;
168 CPPUNIT_ASSERT( foobar
.endsWith( "bar" ));
169 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
170 // rtl_string_unittest_const_literal_function = false;
171 // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
172 // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
173 rtl_string_unittest_const_literal_function
= false;
174 CPPUNIT_ASSERT( bool(foo
== "foo") );
175 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
176 rtl_string_unittest_const_literal_function
= false;
177 CPPUNIT_ASSERT( bool("foo" == foo
) );
178 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
179 rtl_string_unittest_const_literal_function
= false;
180 CPPUNIT_ASSERT( foo
!= "bar" );
181 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
182 rtl_string_unittest_const_literal_function
= false;
183 CPPUNIT_ASSERT( "foo" != bar
);
184 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
185 rtl_string_unittest_const_literal_function
= false;
186 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(6), foobarfoo
.indexOf( "foo", 1 ) );
187 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
188 // rtl_string_unittest_const_literal_function = false;
189 // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 );
190 // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
191 // if this is not true, some of the calls above converted to OString
192 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal
);
193 // if this is not true, some of the calls above used non-const variants
194 CPPUNIT_ASSERT( !rtl_string_unittest_non_const_literal_function
);
197 void test::ostring::StringLiterals::checkNonConstUsage()
199 // check that (non-const) char[] overloads work and do not use const char[] overloads
200 rtl::OString
foo( "foo" );
201 rtl::OString
FoO( "FoO" );
202 rtl::OString
foobarfoo( "foobarfoo" );
203 rtl::OString
foobar( "foobar" );
204 rtl::OString
FooBaRfoo( "FooBaRfoo" );
205 rtl::OString
FooBaR( "FooBaR" );
206 rtl::OString
bar( "bar" );
207 char foo_c
[] = "foo";
208 char bar_c
[] = "bar";
209 char fOo_c
[] = "fOo";
210 char bAr_c
[] = "bAr";
212 rtl_string_unittest_const_literal
= false; // start checking for OString conversions
213 rtl_string_unittest_const_literal_function
= false; // and check for const variants
214 CPPUNIT_ASSERT_EQUAL( foo
, rtl::OString() = static_cast<const char*>(foo_c
) );
215 CPPUNIT_ASSERT_EQUAL( foo
, rtl::OString() = foo_c
);
216 CPPUNIT_ASSERT( FoO
.equalsIgnoreAsciiCase( static_cast<const char*>(fOo_c
) ));
217 CPPUNIT_ASSERT( FoO
.equalsIgnoreAsciiCase( fOo_c
));
218 CPPUNIT_ASSERT( foobarfoo
.match( static_cast<const char*>(bar_c
), 3 ));
219 CPPUNIT_ASSERT( foobarfoo
.match( bar_c
, 3 ));
220 CPPUNIT_ASSERT( foobar
.match( static_cast<const char*>(foo_c
) ));
221 CPPUNIT_ASSERT( foobar
.match( foo_c
));
222 CPPUNIT_ASSERT( FooBaRfoo
.matchIgnoreAsciiCase( static_cast<const char*>(bAr_c
), 3 ));
223 CPPUNIT_ASSERT( FooBaRfoo
.matchIgnoreAsciiCase( bAr_c
, 3 ));
224 CPPUNIT_ASSERT( FooBaR
.matchIgnoreAsciiCase( static_cast<const char*>(fOo_c
) ));
225 CPPUNIT_ASSERT( FooBaR
.matchIgnoreAsciiCase( fOo_c
));
226 CPPUNIT_ASSERT( foobar
.startsWith( static_cast<const char*>(foo_c
) ));
227 CPPUNIT_ASSERT( foobar
.startsWith( foo_c
));
228 CPPUNIT_ASSERT( foobar
.endsWith( static_cast<const char*>(bar_c
) ));
229 CPPUNIT_ASSERT( foobar
.endsWith( bar_c
));
230 // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( (const char*)bar_c ));
231 // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( bar_c ));
232 CPPUNIT_ASSERT( bool(foo
== static_cast<const char*>(foo_c
)) );
233 CPPUNIT_ASSERT( bool(foo
== foo_c
) );
234 CPPUNIT_ASSERT( bool(static_cast<const char*>(foo_c
) == foo
) );
235 CPPUNIT_ASSERT( bool(foo_c
== foo
) );
236 CPPUNIT_ASSERT( foo
!= static_cast<const char*>(bar_c
) );
237 CPPUNIT_ASSERT( foo
!= bar_c
);
238 CPPUNIT_ASSERT( static_cast<const char*>(foo_c
) != bar
);
239 CPPUNIT_ASSERT( foo_c
!= bar
);
240 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(6), foobarfoo
.indexOf( static_cast<const char*>(foo_c
), 1 ) );
241 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32
>(6), foobarfoo
.indexOf( foo_c
, 1 ) );
242 // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( (const char*)foo_c ) == 6 );
243 // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( foo_c ) == 6 );
244 // if this is not true, some of the calls above used const variants
245 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal
);
246 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function
);
249 void test::ostring::StringLiterals::checkBuffer()
251 rtl::OStringBuffer buf
;
252 rtl_string_unittest_const_literal_function
= false;
254 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
255 CPPUNIT_ASSERT_EQUAL( rtl::OString( "foo" ), buf
.toString());
256 rtl_string_unittest_const_literal_function
= false;
258 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
259 CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobar" ), buf
.toString());
260 rtl_string_unittest_const_literal_function
= false;
261 buf
.insert( 3, "baz" );
262 CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function
);
263 CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobazbar" ), buf
.toString());
265 rtl::OString
foobazbard( "foobazbard" );
266 rtl::OString
foodbazbard( "foodbazbard" );
267 rtl_string_unittest_const_literal
= false; // start checking for OString conversions
268 rtl_string_unittest_const_literal_function
= false; // and check for const variants
270 CPPUNIT_ASSERT_EQUAL( foobazbard
, buf
.append( d
).toString());
271 CPPUNIT_ASSERT_EQUAL( foodbazbard
, buf
.insert( 3, d
).toString() );
272 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal
);
273 CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function
);
276 #undef CONST_CTOR_USED
280 CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals
);
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */