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 : extern bool rtl_string_unittest_const_literal;
32 : extern bool rtl_string_unittest_invalid_conversion;
33 : extern bool rtl_string_unittest_const_literal_function;
34 : extern 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/ustring.hxx"
41 : #include "rtl/ustrbuf.hxx"
42 :
43 : namespace test { namespace oustring {
44 :
45 15 : class StringLiterals: public CppUnit::TestFixture
46 : {
47 : private:
48 : void checkCtors();
49 : void checkUsage();
50 : void checkExtraIntArgument();
51 : void checkNonconstChar();
52 : void checkBuffer();
53 :
54 : void testcall( const char str[] );
55 :
56 2 : CPPUNIT_TEST_SUITE(StringLiterals);
57 1 : CPPUNIT_TEST(checkCtors);
58 1 : CPPUNIT_TEST(checkUsage);
59 1 : CPPUNIT_TEST(checkExtraIntArgument);
60 1 : CPPUNIT_TEST(checkNonconstChar);
61 1 : CPPUNIT_TEST(checkBuffer);
62 2 : CPPUNIT_TEST_SUITE_END();
63 : };
64 :
65 : // reset the flag, evaluate the expression and return
66 : // whether the string literal ctor was used (i.e. whether the conversion was valid)
67 : #define VALID_CONVERSION( expression ) \
68 : ( \
69 : rtl_string_unittest_invalid_conversion = false, \
70 : ( void ) rtl::OUString( expression ), \
71 : ( void ) rtl::OUStringBuffer( expression ), \
72 : !rtl_string_unittest_invalid_conversion )
73 :
74 1 : void test::oustring::StringLiterals::checkCtors()
75 : {
76 1 : CPPUNIT_ASSERT( VALID_CONVERSION( "test" ));
77 1 : const char good1[] = "test";
78 1 : CPPUNIT_ASSERT( VALID_CONVERSION( good1 ));
79 :
80 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( (const char*) "test" ));
81 1 : const char* bad1 = good1;
82 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( bad1 ));
83 1 : char bad2[] = "test";
84 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( bad2 ));
85 1 : char* bad3 = bad2;
86 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( bad3 ));
87 1 : const char* bad4[] = { "test1" };
88 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( bad4[ 0 ] ));
89 1 : testcall( good1 );
90 :
91 : // This one is technically broken, since the first element is 6 characters test\0\0,
92 : // but there does not appear a way to detect this by compile time (runtime will assert()).
93 : // RTL_CONSTASCII_USTRINGPARAM() has the same flaw.
94 1 : const char bad5[][ 6 ] = { "test", "test2" };
95 : // CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 0 ] ));
96 1 : CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 1 ] ));
97 :
98 : // Check that contents are correct and equal to the case when RTL_CONSTASCII_USTRINGPARAM is used.
99 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "" ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "" )));
100 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "ab" ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ab" )));
101 : #if 0
102 : // Also check that embedded \0 is included.
103 : // In fact, allowing this is probably just trouble, so this now asserts.
104 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "\0" ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\0" )));
105 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "a\0b" ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "a\0b" )));
106 : #endif
107 1 : }
108 :
109 1 : void test::oustring::StringLiterals::testcall( const char str[] )
110 : {
111 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( str )));
112 1 : }
113 :
114 1 : void test::oustring::StringLiterals::checkUsage()
115 : {
116 : // simply check that all string literal based calls work as expected
117 : // also check that they really use string literal overload and do not convert to OUString
118 1 : rtl::OUString foo( "foo" );
119 1 : rtl::OUString FoO( "FoO" );
120 1 : rtl::OUString foobarfoo( "foobarfoo" );
121 1 : rtl::OUString foobar( "foobar" );
122 1 : rtl::OUString FooBaRfoo( "FooBaRfoo" );
123 1 : rtl::OUString FooBaR( "FooBaR" );
124 1 : rtl::OUString bar( "bar" );
125 1 : rtl::OUString test( "test" );
126 :
127 1 : rtl_string_unittest_const_literal = false; // start checking for OUString conversions
128 1 : CPPUNIT_ASSERT_EQUAL( foo, rtl::OUString() = "foo" );
129 1 : CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" ));
130 1 : CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 ));
131 1 : CPPUNIT_ASSERT( foobar.match( "foo" ));
132 1 : CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 ));
133 1 : CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" ));
134 1 : CPPUNIT_ASSERT( foobar.startsWith( "foo" ));
135 1 : CPPUNIT_ASSERT( FooBaR.startsWithIgnoreAsciiCase( "foo" ));
136 1 : CPPUNIT_ASSERT( foobar.endsWith( "bar" ));
137 1 : CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" ));
138 1 : CPPUNIT_ASSERT( foo == "foo" );
139 1 : CPPUNIT_ASSERT( "foo" == foo );
140 1 : CPPUNIT_ASSERT( foo != "bar" );
141 1 : CPPUNIT_ASSERT( "foo" != bar );
142 1 : CPPUNIT_ASSERT( foobarfoo.indexOf( "foo", 1 ) == 6 );
143 1 : CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 );
144 1 : CPPUNIT_ASSERT( foobarfoo.replaceFirst( "foo", test ) == "testbarfoo" );
145 1 : CPPUNIT_ASSERT( foobarfoo.replaceFirst( "foo", "test" ) == "testbarfoo" );
146 1 : CPPUNIT_ASSERT( foobarfoo.replaceAll( "foo", test ) == "testbartest" );
147 1 : CPPUNIT_ASSERT( foobarfoo.replaceAll( "foo", "test" ) == "testbartest" );
148 1 : CPPUNIT_ASSERT( foo.reverseCompareTo( "foo" ) == 0 );
149 : // if this is not true, some of the calls above converted to OUString
150 1 : CPPUNIT_ASSERT( rtl_string_unittest_const_literal == false );
151 1 : }
152 :
153 1 : void test::oustring::StringLiterals::checkExtraIntArgument()
154 : {
155 : // This makes sure that using by mistake RTL_CONSTASCII_STRINGPARAM does not trigger a different
156 : // overload, i.e. the second argument to match() in this case is the indexFrom argument,
157 : // but with the macro it would contain the length of the string. Therefore
158 : // match( RTL_CONSTASCII_STRINGPARAM( "bar" )) would be match( "bar", 3 ), which would be
159 : // true when called for OUString( "foobar" ). But this should not happen because of the
160 : // &foo[0] trick in the RTL_CONSTASCII_STRINGPARAM macro.
161 1 : CPPUNIT_ASSERT( !rtl::OUString("foobar").match( "bar" ));
162 1 : CPPUNIT_ASSERT( !rtl::OUString("foobar").match( RTL_CONSTASCII_STRINGPARAM( "bar" )));
163 1 : }
164 :
165 1 : void test::oustring::StringLiterals::checkNonconstChar()
166 : { // check that non-const char[] data do not trigger string literal overloads
167 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), rtl::OUString( "footest" ).replaceAll( "test", "bar" ));
168 1 : char test[] = "test";
169 1 : char bar[] = "bar";
170 1 : const char consttest[] = "test";
171 1 : const char constbar[] = "bar";
172 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( test, bar )));
173 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( consttest, bar )));
174 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( rtl::OUString( "footest" ).replaceAll( test, constbar )));
175 1 : CPPUNIT_ASSERT( rtl::OUString( "foobar" ) == rtl::OUString( "footest" ).replaceAll( consttest, constbar ));
176 1 : }
177 :
178 1 : void test::oustring::StringLiterals::checkBuffer()
179 : {
180 1 : rtl::OUStringBuffer buf;
181 1 : buf.append( "foo" );
182 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foo" ), buf.toString());
183 1 : buf.append( "bar" );
184 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), buf.toString());
185 1 : buf.insert( 3, "baz" );
186 1 : CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobazbar" ), buf.toString());
187 1 : char d[] = "d";
188 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUString( d ))));
189 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUStringBuffer( d ))));
190 1 : CPPUNIT_ASSERT( !VALID_CONVERSION( buf.insert( 0, d )));
191 1 : }
192 :
193 : }} // namespace
194 :
195 3 : CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals);
196 :
197 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|