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