Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2012 Lubos Lunak <l.lunak@suse.cz> (initial developer)
17 : *
18 : * All Rights Reserved.
19 : *
20 : * For minor contributions see the git repository.
21 : *
22 : * Alternatively, the contents of this file may be used under the terms of
23 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : * instead of those above.
27 : */
28 :
29 : // activate the extra needed ctor
30 : #define RTL_STRING_UNITTEST
31 : bool rtl_string_unittest_const_literal;
32 : bool rtl_string_unittest_invalid_conversion;
33 : bool rtl_string_unittest_const_literal_function;
34 : bool rtl_string_unittest_non_const_literal_function;
35 :
36 : #include <sal/types.h>
37 : #include <cppunit/TestFixture.h>
38 : #include <cppunit/extensions/HelperMacros.h>
39 : #include "rtl/string.h"
40 : #include "rtl/string.hxx"
41 : #include "rtl/strbuf.hxx"
42 :
43 : namespace test { namespace ostring {
44 :
45 12 : class StringLiterals: public CppUnit::TestFixture
46 : {
47 : private:
48 : void checkCtors();
49 : void checkUsage();
50 : void checkNonConstUsage();
51 : void checkBuffer();
52 :
53 : void testcall( const char str[] );
54 :
55 : static const char bad5[];
56 : static char bad6[];
57 :
58 2 : CPPUNIT_TEST_SUITE(StringLiterals);
59 1 : CPPUNIT_TEST(checkCtors);
60 1 : CPPUNIT_TEST(checkUsage);
61 1 : CPPUNIT_TEST(checkNonConstUsage);
62 1 : CPPUNIT_TEST(checkBuffer);
63 2 : CPPUNIT_TEST_SUITE_END();
64 : };
65 :
66 : // reset the flag, call OString ctor with the given argument and return
67 : // whether the string literal ctor was used
68 : #define CONST_CTOR_USED( argument ) \
69 : ( \
70 : rtl_string_unittest_const_literal = false, \
71 : ( void ) rtl::OString( argument ), \
72 : result_tmp = rtl_string_unittest_const_literal, \
73 : rtl_string_unittest_const_literal = false, \
74 : ( void ) rtl::OStringBuffer( argument ), \
75 : rtl_string_unittest_const_literal && result_tmp )
76 :
77 1 : void test::ostring::StringLiterals::checkCtors()
78 : {
79 : // string literal ctors do not work with SFINAE broken and are disabled
80 : #ifndef HAVE_SFINAE_ANONYMOUS_BROKEN
81 : bool result_tmp;
82 1 : CPPUNIT_ASSERT( CONST_CTOR_USED( "test" ));
83 1 : const char good1[] = "test";
84 1 : CPPUNIT_ASSERT( CONST_CTOR_USED( good1 ));
85 :
86 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( (const char*) "test" ));
87 1 : const char* bad1 = good1;
88 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad1 ));
89 1 : char bad2[] = "test";
90 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad2 ));
91 1 : char* bad3 = bad2;
92 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad3 ));
93 1 : const char* bad4[] = { "test1" };
94 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad4[ 0 ] ));
95 1 : testcall( good1 );
96 : #ifndef _MSC_VER
97 : // this is actually not supposed to work (see discussion in stringutils.hxx),
98 : // but gcc and clang somehow manage, so keep it used, just in case some other problem
99 : // shows up somewhen in the future
100 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad5 )); // size is not known here
101 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad6 ));
102 : #endif
103 :
104 : // This one is technically broken, since the first element is 6 characters test\0\0,
105 : // but there does not appear a way to detect this by compile time (runtime will assert()).
106 : // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
107 1 : const char bad7[][ 6 ] = { "test", "test2" };
108 : // CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 0 ] ));
109 1 : CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 1 ] ));
110 :
111 : // Check that contents are correct and equal to the case when const char* ctor is used.
112 1 : CPPUNIT_ASSERT( rtl::OString( (const char*)"" ) == rtl::OString( "" ));
113 1 : CPPUNIT_ASSERT( rtl::OString( (const char*)"ab" ) == rtl::OString( "ab" ));
114 :
115 : // Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used.
116 1 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) == rtl::OString( "" ));
117 1 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) == rtl::OString( "ab" ));
118 : #if 0
119 : // This is currently disabled because it can't be consistent with HAVE_SFINAE_ANONYMOUS_BROKEN.
120 : // Since the situation wasn't quite consistent even before, there should be no big harm.
121 :
122 : // Check also that embedded \0 is included (RTL_CONSTASCII_STRINGPARAM does the same,
123 : // const char* ctor does not, but it seems to make more sense to include it when
124 : // it's explicitly mentioned in the string literal).
125 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "\0" )) == rtl::OString( "\0" ));
126 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "a\0b" )) == rtl::OString( "a\0b" ));
127 : #endif
128 : #endif
129 1 : }
130 :
131 : const char test::ostring::StringLiterals::bad5[] = "test";
132 : char test::ostring::StringLiterals::bad6[] = "test";
133 :
134 1 : void test::ostring::StringLiterals::testcall( const char str[] )
135 : {
136 : #ifndef _MSC_VER
137 : bool result_tmp;
138 1 : CPPUNIT_ASSERT( !CONST_CTOR_USED( str ));
139 : #else
140 : // MSVC just errors out on this for some reason, which is fine as well
141 : (void)str;
142 : #endif
143 1 : }
144 :
145 1 : void test::ostring::StringLiterals::checkUsage()
146 : {
147 : // simply check that all string literal based calls work as expected
148 : // also check that they really use string literal overload and do not convert to OString
149 1 : rtl::OString foo( "foo" );
150 1 : rtl::OString FoO( "FoO" );
151 1 : rtl::OString foobarfoo( "foobarfoo" );
152 1 : rtl::OString foobar( "foobar" );
153 1 : rtl::OString FooBaRfoo( "FooBaRfoo" );
154 1 : rtl::OString FooBaR( "FooBaR" );
155 1 : rtl::OString bar( "bar" );
156 :
157 1 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
158 1 : rtl_string_unittest_non_const_literal_function = false; // and check for non-const variants
159 1 : rtl_string_unittest_const_literal_function = false;
160 1 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = "foo" );
161 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
162 : #ifndef HAVE_SFINAE_ANONYMOUS_BROKEN
163 1 : rtl_string_unittest_const_literal_function = false;
164 1 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" ));
165 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
166 : #endif
167 1 : rtl_string_unittest_const_literal_function = false;
168 1 : CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 ));
169 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
170 1 : rtl_string_unittest_const_literal_function = false;
171 1 : CPPUNIT_ASSERT( foobar.match( "foo" ));
172 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
173 1 : rtl_string_unittest_const_literal_function = false;
174 1 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 ));
175 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
176 1 : rtl_string_unittest_const_literal_function = false;
177 1 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" ));
178 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
179 1 : rtl_string_unittest_const_literal_function = false;
180 1 : CPPUNIT_ASSERT( foobar.startsWith( "foo" ));
181 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
182 1 : rtl_string_unittest_const_literal_function = false;
183 1 : CPPUNIT_ASSERT( foobar.endsWith( "bar" ));
184 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
185 : // rtl_string_unittest_const_literal_function = false;
186 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
187 : // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
188 1 : rtl_string_unittest_const_literal_function = false;
189 1 : CPPUNIT_ASSERT( foo == "foo" );
190 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
191 1 : rtl_string_unittest_const_literal_function = false;
192 1 : CPPUNIT_ASSERT( "foo" == foo );
193 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
194 1 : rtl_string_unittest_const_literal_function = false;
195 1 : CPPUNIT_ASSERT( foo != "bar" );
196 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
197 1 : rtl_string_unittest_const_literal_function = false;
198 1 : CPPUNIT_ASSERT( "foo" != bar );
199 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
200 1 : rtl_string_unittest_const_literal_function = false;
201 1 : CPPUNIT_ASSERT( foobarfoo.indexOf( "foo", 1 ) == 6 );
202 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
203 : // rtl_string_unittest_const_literal_function = false;
204 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 );
205 : // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
206 : // if this is not true, some of the calls above converted to OString
207 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
208 : // if this is not true, some of the calls above used non-const variants
209 1 : CPPUNIT_ASSERT( rtl_string_unittest_non_const_literal_function == false );
210 1 : }
211 :
212 1 : void test::ostring::StringLiterals::checkNonConstUsage()
213 : {
214 : // check that (non-const) char[] overloads work and do not use const char[] overloads
215 1 : rtl::OString foo( "foo" );
216 1 : rtl::OString FoO( "FoO" );
217 1 : rtl::OString foobarfoo( "foobarfoo" );
218 1 : rtl::OString foobar( "foobar" );
219 1 : rtl::OString FooBaRfoo( "FooBaRfoo" );
220 1 : rtl::OString FooBaR( "FooBaR" );
221 1 : rtl::OString bar( "bar" );
222 1 : char foo_c[] = "foo";
223 1 : char bar_c[] = "bar";
224 1 : char fOo_c[] = "fOo";
225 1 : char bAr_c[] = "bAr";
226 :
227 1 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
228 1 : rtl_string_unittest_const_literal_function = false; // and check for const variants
229 1 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = (const char*)foo_c );
230 1 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = foo_c );
231 1 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( (const char*)fOo_c ));
232 1 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( fOo_c ));
233 1 : CPPUNIT_ASSERT( foobarfoo.match( (const char*)bar_c, 3 ));
234 1 : CPPUNIT_ASSERT( foobarfoo.match( bar_c, 3 ));
235 1 : CPPUNIT_ASSERT( foobar.match( (const char*)foo_c ));
236 1 : CPPUNIT_ASSERT( foobar.match( foo_c ));
237 1 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( (const char*)bAr_c, 3 ));
238 1 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( bAr_c, 3 ));
239 1 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( (const char*)fOo_c ));
240 1 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( fOo_c ));
241 1 : CPPUNIT_ASSERT( foobar.startsWith( (const char*)foo_c ));
242 1 : CPPUNIT_ASSERT( foobar.startsWith( foo_c ));
243 1 : CPPUNIT_ASSERT( foobar.endsWith( (const char*)bar_c ));
244 1 : CPPUNIT_ASSERT( foobar.endsWith( bar_c ));
245 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( (const char*)bar_c ));
246 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( bar_c ));
247 1 : CPPUNIT_ASSERT( foo == (const char*)foo_c );
248 1 : CPPUNIT_ASSERT( foo == foo_c );
249 1 : CPPUNIT_ASSERT( (const char*)foo_c == foo );
250 1 : CPPUNIT_ASSERT( foo_c == foo );
251 1 : CPPUNIT_ASSERT( foo != (const char*)bar_c );
252 1 : CPPUNIT_ASSERT( foo != bar_c );
253 1 : CPPUNIT_ASSERT( (const char*)foo_c != bar );
254 1 : CPPUNIT_ASSERT( foo_c != bar );
255 1 : CPPUNIT_ASSERT( foobarfoo.indexOf( (const char*)foo_c, 1 ) == 6 );
256 1 : CPPUNIT_ASSERT( foobarfoo.indexOf( foo_c, 1 ) == 6 );
257 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( (const char*)foo_c ) == 6 );
258 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( foo_c ) == 6 );
259 : // if this is not true, some of the calls above used const variants
260 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
261 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
262 1 : }
263 :
264 1 : void test::ostring::StringLiterals::checkBuffer()
265 : {
266 1 : rtl::OStringBuffer buf;
267 : #ifndef HAVE_SFINAE_ANONYMOUS_BROKEN
268 1 : rtl_string_unittest_const_literal_function = false;
269 1 : buf.append( "foo" );
270 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
271 1 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foo" ), buf.toString());
272 1 : rtl_string_unittest_const_literal_function = false;
273 1 : buf.append( "bar" );
274 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
275 1 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobar" ), buf.toString());
276 1 : rtl_string_unittest_const_literal_function = false;
277 1 : buf.insert( 3, "baz" );
278 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
279 1 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobazbar" ), buf.toString());
280 : #else
281 : buf.append( "foobazbar" );
282 : #endif
283 :
284 1 : rtl::OString foobazbard( "foobazbard" );
285 1 : rtl::OString foodbazbard( "foodbazbard" );
286 1 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
287 1 : rtl_string_unittest_const_literal_function = false; // and check for const variants
288 1 : char d[] = "d";
289 1 : CPPUNIT_ASSERT_EQUAL( foobazbard, buf.append( d ).toString());
290 1 : CPPUNIT_ASSERT_EQUAL( foodbazbard, buf.insert( 3, d ).toString() );
291 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
292 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
293 1 : }
294 :
295 : #undef CONST_CTOR_USED
296 :
297 : }} // namespace
298 :
299 3 : CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals);
300 :
301 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|