Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
10 : // activate the extra needed ctor
11 : #define RTL_STRING_UNITTEST
12 : bool rtl_string_unittest_const_literal;
13 : bool rtl_string_unittest_invalid_conversion;
14 : bool rtl_string_unittest_const_literal_function;
15 : bool rtl_string_unittest_non_const_literal_function;
16 :
17 : #include <sal/types.h>
18 : #include <cppunit/TestFixture.h>
19 : #include <cppunit/extensions/HelperMacros.h>
20 : #include "rtl/string.h"
21 : #include "rtl/string.hxx"
22 : #include "rtl/strbuf.hxx"
23 :
24 : namespace test { namespace ostring {
25 :
26 24 : class StringLiterals: public CppUnit::TestFixture
27 : {
28 : private:
29 : void checkCtors();
30 : void checkUsage();
31 : void checkNonConstUsage();
32 : void checkBuffer();
33 :
34 : void testcall( const char str[] );
35 :
36 : static const char bad5[];
37 : static char bad6[];
38 :
39 4 : CPPUNIT_TEST_SUITE(StringLiterals);
40 2 : CPPUNIT_TEST(checkCtors);
41 2 : CPPUNIT_TEST(checkUsage);
42 2 : CPPUNIT_TEST(checkNonConstUsage);
43 2 : CPPUNIT_TEST(checkBuffer);
44 4 : CPPUNIT_TEST_SUITE_END();
45 : };
46 :
47 : // reset the flag, call OString ctor with the given argument and return
48 : // whether the string literal ctor was used
49 : #define CONST_CTOR_USED( argument ) \
50 : ( \
51 : rtl_string_unittest_const_literal = false, \
52 : ( void ) rtl::OString( argument ), \
53 : result_tmp = rtl_string_unittest_const_literal, \
54 : rtl_string_unittest_const_literal = false, \
55 : ( void ) rtl::OStringBuffer( argument ), \
56 : rtl_string_unittest_const_literal && result_tmp )
57 :
58 2 : void test::ostring::StringLiterals::checkCtors()
59 : {
60 : bool result_tmp;
61 2 : CPPUNIT_ASSERT( CONST_CTOR_USED( "test" ));
62 2 : const char good1[] = "test";
63 2 : CPPUNIT_ASSERT( CONST_CTOR_USED( good1 ));
64 :
65 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( (const char*) "test" ));
66 2 : const char* bad1 = good1;
67 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad1 ));
68 2 : char bad2[] = "test";
69 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad2 ));
70 2 : char* bad3 = bad2;
71 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad3 ));
72 2 : const char* bad4[] = { "test1" };
73 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad4[ 0 ] ));
74 2 : testcall( good1 );
75 : #ifndef _MSC_VER
76 : // this is actually not supposed to work (see discussion in stringutils.hxx),
77 : // but gcc and clang somehow manage, so keep it used, just in case some other problem
78 : // shows up somewhen in the future
79 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad5 )); // size is not known here
80 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( bad6 ));
81 : #endif
82 :
83 : // This one is technically broken, since the first element is 6 characters test\0\0,
84 : // but there does not appear a way to detect this by compile time (runtime will assert()).
85 : // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
86 2 : const char bad7[][ 6 ] = { "test", "test2" };
87 : // CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 0 ] ));
88 2 : CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 1 ] ));
89 :
90 : // Check that contents are correct and equal to the case when const char* ctor is used.
91 2 : CPPUNIT_ASSERT( rtl::OString( (const char*)"" ) == rtl::OString( "" ));
92 2 : CPPUNIT_ASSERT( rtl::OString( (const char*)"ab" ) == rtl::OString( "ab" ));
93 :
94 : // Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used.
95 2 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) == rtl::OString( "" ));
96 2 : CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) == rtl::OString( "ab" ));
97 2 : }
98 :
99 : const char test::ostring::StringLiterals::bad5[] = "test";
100 : char test::ostring::StringLiterals::bad6[] = "test";
101 :
102 2 : void test::ostring::StringLiterals::testcall( const char str[] )
103 : {
104 : #ifndef _MSC_VER
105 : bool result_tmp;
106 2 : CPPUNIT_ASSERT( !CONST_CTOR_USED( str ));
107 : #else
108 : // MSVC just errors out on this for some reason, which is fine as well
109 : (void)str;
110 : #endif
111 2 : }
112 :
113 2 : void test::ostring::StringLiterals::checkUsage()
114 : {
115 : // simply check that all string literal based calls work as expected
116 : // also check that they really use string literal overload and do not convert to OString
117 2 : rtl::OString foo( "foo" );
118 4 : rtl::OString FoO( "FoO" );
119 4 : rtl::OString foobarfoo( "foobarfoo" );
120 4 : rtl::OString foobar( "foobar" );
121 4 : rtl::OString FooBaRfoo( "FooBaRfoo" );
122 4 : rtl::OString FooBaR( "FooBaR" );
123 4 : rtl::OString bar( "bar" );
124 :
125 2 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
126 2 : rtl_string_unittest_non_const_literal_function = false; // and check for non-const variants
127 2 : rtl_string_unittest_const_literal_function = false;
128 2 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = "foo" );
129 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
130 2 : rtl_string_unittest_const_literal_function = false;
131 2 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" ));
132 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
133 2 : rtl_string_unittest_const_literal_function = false;
134 2 : CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 ));
135 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
136 2 : rtl_string_unittest_const_literal_function = false;
137 2 : CPPUNIT_ASSERT( foobar.match( "foo" ));
138 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
139 2 : rtl_string_unittest_const_literal_function = false;
140 2 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 ));
141 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
142 2 : rtl_string_unittest_const_literal_function = false;
143 2 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" ));
144 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
145 2 : rtl_string_unittest_const_literal_function = false;
146 2 : CPPUNIT_ASSERT( foobar.startsWith( "foo" ));
147 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
148 2 : rtl_string_unittest_const_literal_function = false;
149 2 : CPPUNIT_ASSERT( foobar.endsWith( "bar" ));
150 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
151 : // rtl_string_unittest_const_literal_function = false;
152 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
153 : // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
154 2 : rtl_string_unittest_const_literal_function = false;
155 2 : CPPUNIT_ASSERT( foo == "foo" );
156 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
157 2 : rtl_string_unittest_const_literal_function = false;
158 2 : CPPUNIT_ASSERT( "foo" == foo );
159 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
160 2 : rtl_string_unittest_const_literal_function = false;
161 2 : CPPUNIT_ASSERT( foo != "bar" );
162 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
163 2 : rtl_string_unittest_const_literal_function = false;
164 2 : CPPUNIT_ASSERT( "foo" != bar );
165 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
166 2 : rtl_string_unittest_const_literal_function = false;
167 2 : CPPUNIT_ASSERT( foobarfoo.indexOf( "foo", 1 ) == 6 );
168 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
169 : // rtl_string_unittest_const_literal_function = false;
170 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 );
171 : // CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
172 : // if this is not true, some of the calls above converted to OString
173 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
174 : // if this is not true, some of the calls above used non-const variants
175 4 : CPPUNIT_ASSERT( rtl_string_unittest_non_const_literal_function == false );
176 2 : }
177 :
178 2 : void test::ostring::StringLiterals::checkNonConstUsage()
179 : {
180 : // check that (non-const) char[] overloads work and do not use const char[] overloads
181 2 : rtl::OString foo( "foo" );
182 4 : rtl::OString FoO( "FoO" );
183 4 : rtl::OString foobarfoo( "foobarfoo" );
184 4 : rtl::OString foobar( "foobar" );
185 4 : rtl::OString FooBaRfoo( "FooBaRfoo" );
186 4 : rtl::OString FooBaR( "FooBaR" );
187 4 : rtl::OString bar( "bar" );
188 2 : char foo_c[] = "foo";
189 2 : char bar_c[] = "bar";
190 2 : char fOo_c[] = "fOo";
191 2 : char bAr_c[] = "bAr";
192 :
193 2 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
194 2 : rtl_string_unittest_const_literal_function = false; // and check for const variants
195 2 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = (const char*)foo_c );
196 2 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = foo_c );
197 2 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( (const char*)fOo_c ));
198 2 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( fOo_c ));
199 2 : CPPUNIT_ASSERT( foobarfoo.match( (const char*)bar_c, 3 ));
200 2 : CPPUNIT_ASSERT( foobarfoo.match( bar_c, 3 ));
201 2 : CPPUNIT_ASSERT( foobar.match( (const char*)foo_c ));
202 2 : CPPUNIT_ASSERT( foobar.match( foo_c ));
203 2 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( (const char*)bAr_c, 3 ));
204 2 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( bAr_c, 3 ));
205 2 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( (const char*)fOo_c ));
206 2 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( fOo_c ));
207 2 : CPPUNIT_ASSERT( foobar.startsWith( (const char*)foo_c ));
208 2 : CPPUNIT_ASSERT( foobar.startsWith( foo_c ));
209 2 : CPPUNIT_ASSERT( foobar.endsWith( (const char*)bar_c ));
210 2 : CPPUNIT_ASSERT( foobar.endsWith( bar_c ));
211 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( (const char*)bar_c ));
212 : // CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( bar_c ));
213 2 : CPPUNIT_ASSERT( foo == (const char*)foo_c );
214 2 : CPPUNIT_ASSERT( foo == foo_c );
215 2 : CPPUNIT_ASSERT( (const char*)foo_c == foo );
216 2 : CPPUNIT_ASSERT( foo_c == foo );
217 2 : CPPUNIT_ASSERT( foo != (const char*)bar_c );
218 2 : CPPUNIT_ASSERT( foo != bar_c );
219 2 : CPPUNIT_ASSERT( (const char*)foo_c != bar );
220 2 : CPPUNIT_ASSERT( foo_c != bar );
221 2 : CPPUNIT_ASSERT( foobarfoo.indexOf( (const char*)foo_c, 1 ) == 6 );
222 2 : CPPUNIT_ASSERT( foobarfoo.indexOf( foo_c, 1 ) == 6 );
223 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( (const char*)foo_c ) == 6 );
224 : // CPPUNIT_ASSERT( foobarfoo.lastIndexOf( foo_c ) == 6 );
225 : // if this is not true, some of the calls above used const variants
226 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
227 4 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
228 2 : }
229 :
230 2 : void test::ostring::StringLiterals::checkBuffer()
231 : {
232 2 : rtl::OStringBuffer buf;
233 2 : rtl_string_unittest_const_literal_function = false;
234 2 : buf.append( "foo" );
235 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
236 2 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foo" ), buf.toString());
237 2 : rtl_string_unittest_const_literal_function = false;
238 2 : buf.append( "bar" );
239 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
240 2 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobar" ), buf.toString());
241 2 : rtl_string_unittest_const_literal_function = false;
242 2 : buf.insert( 3, "baz" );
243 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true );
244 2 : CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobazbar" ), buf.toString());
245 :
246 4 : rtl::OString foobazbard( "foobazbard" );
247 4 : rtl::OString foodbazbard( "foodbazbard" );
248 2 : rtl_string_unittest_const_literal = false; // start checking for OString conversions
249 2 : rtl_string_unittest_const_literal_function = false; // and check for const variants
250 2 : char d[] = "d";
251 2 : CPPUNIT_ASSERT_EQUAL( foobazbard, buf.append( d ).toString());
252 2 : CPPUNIT_ASSERT_EQUAL( foodbazbard, buf.insert( 3, d ).toString() );
253 2 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
254 4 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == false );
255 2 : }
256 :
257 : #undef CONST_CTOR_USED
258 :
259 : }} // namespace
260 :
261 6 : CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals);
262 :
263 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|