bump product version to 4.1.6.2
[LibreOffice.git] / comphelper / qa / string / test_string.cxx
blobf89db16f16cadabd912a91d9cbe0ee5801600422
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <cppuhelper/implbase1.hxx>
22 #include <com/sun/star/i18n/CharType.hpp>
24 #include "cppunit/TestAssert.h"
25 #include "cppunit/TestFixture.h"
26 #include "cppunit/extensions/HelperMacros.h"
27 #include "cppunit/plugin/TestPlugIn.h"
28 #include "rtl/string.hxx"
29 #include "rtl/ustring.hxx"
31 namespace {
33 class TestString: public CppUnit::TestFixture
35 public:
36 void testNatural();
37 void testRemove();
38 void testStripStart();
39 void testStripEnd();
40 void testStrip();
41 void testToken();
42 void testTokenCount();
43 void testDecimalStringToNumber();
44 void testIsdigitAsciiString();
45 void testReverseString();
46 void testEqualsString();
48 CPPUNIT_TEST_SUITE(TestString);
49 CPPUNIT_TEST(testNatural);
50 CPPUNIT_TEST(testRemove);
51 CPPUNIT_TEST(testStripStart);
52 CPPUNIT_TEST(testStripEnd);
53 CPPUNIT_TEST(testStrip);
54 CPPUNIT_TEST(testToken);
55 CPPUNIT_TEST(testTokenCount);
56 CPPUNIT_TEST(testDecimalStringToNumber);
57 CPPUNIT_TEST(testIsdigitAsciiString);
58 CPPUNIT_TEST(testReverseString);
59 CPPUNIT_TEST(testEqualsString);
60 CPPUNIT_TEST_SUITE_END();
63 void TestString::testDecimalStringToNumber()
65 OUString s1("1234");
66 CPPUNIT_ASSERT_EQUAL((sal_uInt32)1234, comphelper::string::decimalStringToNumber(s1));
67 s1 += OUString(static_cast<sal_Unicode>(0x07C6));
68 CPPUNIT_ASSERT_EQUAL((sal_uInt32)12346, comphelper::string::decimalStringToNumber(s1));
69 // Codepoints on 2 16bits words
70 sal_uInt32 utf16String[] = { 0x1D7FE /* 8 */, 0x1D7F7 /* 1 */};
71 s1 = OUString(utf16String, 2);
72 CPPUNIT_ASSERT_EQUAL((sal_uInt32)81, comphelper::string::decimalStringToNumber(s1));
75 void TestString::testIsdigitAsciiString()
77 OString s1("1234");
78 CPPUNIT_ASSERT_EQUAL(comphelper::string::isdigitAsciiString(s1), true);
80 OString s2("1A34");
81 CPPUNIT_ASSERT_EQUAL(comphelper::string::isdigitAsciiString(s2), false);
83 OString s3;
84 CPPUNIT_ASSERT_EQUAL(comphelper::string::isdigitAsciiString(s3), true);
87 using namespace ::com::sun::star;
89 class testCollator : public cppu::WeakImplHelper1< i18n::XCollator >
91 public:
92 virtual sal_Int32 SAL_CALL compareSubstring(
93 const OUString& str1, sal_Int32 off1, sal_Int32 len1,
94 const OUString& str2, sal_Int32 off2, sal_Int32 len2) throw(uno::RuntimeException)
96 return str1.copy(off1, len1).compareTo(str2.copy(off2, len2));
98 virtual sal_Int32 SAL_CALL compareString(
99 const OUString& str1,
100 const OUString& str2) throw(uno::RuntimeException)
102 return str1.compareTo(str2);
104 virtual sal_Int32 SAL_CALL loadDefaultCollator(const lang::Locale&, sal_Int32)
105 throw(uno::RuntimeException) {return 0;}
106 virtual sal_Int32 SAL_CALL loadCollatorAlgorithm(const OUString&,
107 const lang::Locale&, sal_Int32) throw(uno::RuntimeException) {return 0;}
108 virtual void SAL_CALL loadCollatorAlgorithmWithEndUserOption(const OUString&,
109 const lang::Locale&, const uno::Sequence< sal_Int32 >&) throw(uno::RuntimeException) {}
110 virtual uno::Sequence< OUString > SAL_CALL listCollatorAlgorithms(const lang::Locale&)
111 throw(uno::RuntimeException)
113 return uno::Sequence< OUString >();
115 virtual uno::Sequence< sal_Int32 > SAL_CALL listCollatorOptions(const OUString&)
116 throw(uno::RuntimeException)
118 return uno::Sequence< sal_Int32 >();
122 #define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57)))
124 class testBreakIterator : public cppu::WeakImplHelper1< i18n::XBreakIterator >
126 public:
127 virtual sal_Int32 SAL_CALL nextCharacters( const OUString&, sal_Int32,
128 const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& )
129 throw(uno::RuntimeException) {return -1;}
130 virtual sal_Int32 SAL_CALL previousCharacters( const OUString&, sal_Int32,
131 const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& )
132 throw(uno::RuntimeException) {return -1;}
134 virtual i18n::Boundary SAL_CALL previousWord( const OUString&, sal_Int32,
135 const lang::Locale&, sal_Int16) throw(uno::RuntimeException)
136 { return i18n::Boundary(); }
137 virtual i18n::Boundary SAL_CALL nextWord( const OUString&, sal_Int32,
138 const lang::Locale&, sal_Int16) throw(uno::RuntimeException)
139 { return i18n::Boundary(); }
140 virtual i18n::Boundary SAL_CALL getWordBoundary( const OUString&, sal_Int32,
141 const lang::Locale&, sal_Int16, sal_Bool )
142 throw(uno::RuntimeException)
143 { return i18n::Boundary(); }
145 virtual sal_Bool SAL_CALL isBeginWord( const OUString&, sal_Int32,
146 const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException)
147 { return false; }
148 virtual sal_Bool SAL_CALL isEndWord( const OUString&, sal_Int32,
149 const lang::Locale& , sal_Int16 ) throw(uno::RuntimeException)
150 { return false; }
151 virtual sal_Int16 SAL_CALL getWordType( const OUString&, sal_Int32,
152 const lang::Locale& ) throw(uno::RuntimeException)
153 { return 0; }
155 virtual sal_Int32 SAL_CALL beginOfSentence( const OUString&, sal_Int32,
156 const lang::Locale& ) throw(uno::RuntimeException)
157 { return 0; }
158 virtual sal_Int32 SAL_CALL endOfSentence( const OUString& rText, sal_Int32,
159 const lang::Locale& ) throw(uno::RuntimeException)
160 { return rText.getLength(); }
162 virtual i18n::LineBreakResults SAL_CALL getLineBreak( const OUString&, sal_Int32,
163 const lang::Locale&, sal_Int32,
164 const i18n::LineBreakHyphenationOptions&,
165 const i18n::LineBreakUserOptions&)
166 throw(uno::RuntimeException)
168 return i18n::LineBreakResults();
171 virtual sal_Int16 SAL_CALL getScriptType( const OUString&, sal_Int32 )
172 throw(uno::RuntimeException) { return -1; }
173 virtual sal_Int32 SAL_CALL beginOfScript( const OUString&, sal_Int32,
174 sal_Int16 ) throw(uno::RuntimeException) { return -1; }
175 virtual sal_Int32 SAL_CALL endOfScript( const OUString&, sal_Int32,
176 sal_Int16 ) throw(uno::RuntimeException) { return -1; }
177 virtual sal_Int32 SAL_CALL previousScript( const OUString&, sal_Int32,
178 sal_Int16 ) throw(uno::RuntimeException) { return -1; }
179 virtual sal_Int32 SAL_CALL nextScript( const OUString&, sal_Int32,
180 sal_Int16 ) throw(uno::RuntimeException) { return -1; }
182 virtual sal_Int32 SAL_CALL beginOfCharBlock( const OUString&, sal_Int32,
183 const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException) { return -1; }
184 virtual sal_Int32 SAL_CALL endOfCharBlock( const OUString& rText, sal_Int32 nStartPos,
185 const lang::Locale&, sal_Int16 CharType ) throw(uno::RuntimeException)
187 const sal_Unicode *pStr = rText.getStr()+nStartPos;
188 for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI)
190 if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr))
191 return nI;
192 else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr))
193 return nI;
194 ++pStr;
196 return -1;
198 virtual sal_Int32 SAL_CALL previousCharBlock( const OUString&, sal_Int32,
199 const lang::Locale&, sal_Int16 ) throw(uno::RuntimeException) { return -1; }
200 virtual sal_Int32 SAL_CALL nextCharBlock( const OUString& rText, sal_Int32 nStartPos,
201 const lang::Locale&, sal_Int16 CharType ) throw(uno::RuntimeException)
203 const sal_Unicode *pStr = rText.getStr()+nStartPos;
204 for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI)
206 if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr))
207 return nI;
208 else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr))
209 return nI;
210 ++pStr;
212 return -1;
216 void TestString::testNatural()
218 using namespace comphelper::string;
220 uno::Reference< i18n::XCollator > xCollator(new testCollator);
221 uno::Reference< i18n::XBreakIterator > xBI(new testBreakIterator);
223 // --- Some generic tests to ensure we do not alter original behavior
224 // outside what we want
225 CPPUNIT_ASSERT(
226 compareNatural("ABC", "ABC", xCollator, xBI, lang::Locale()) == 0
228 // Case sensitivity
229 CPPUNIT_ASSERT(
230 compareNatural("ABC", "abc", xCollator, xBI, lang::Locale()) < 0
232 // Reverse
233 CPPUNIT_ASSERT(
234 compareNatural("abc", "ABC", xCollator, xBI, lang::Locale()) > 0
236 // First shorter
237 CPPUNIT_ASSERT(
238 compareNatural("alongstring", "alongerstring", xCollator, xBI, lang::Locale()) > 0
240 // Second shorter
241 CPPUNIT_ASSERT(
242 compareNatural("alongerstring", "alongstring", xCollator, xBI, lang::Locale()) < 0
244 // -- Here we go on natural order, each one is followed by classic compare and the reverse comparison
245 // That's why we originally made the patch
246 CPPUNIT_ASSERT(
247 compareNatural("Heading 9", "Heading 10", xCollator, xBI, lang::Locale()) < 0
249 // Original behavior
250 CPPUNIT_ASSERT(
251 OUString("Heading 9").compareTo("Heading 10") > 0
253 CPPUNIT_ASSERT(
254 compareNatural("Heading 10", "Heading 9", xCollator, xBI, lang::Locale()) > 0
256 // Harder
257 CPPUNIT_ASSERT(
258 compareNatural("July, the 4th", "July, the 10th", xCollator, xBI, lang::Locale()) < 0
260 CPPUNIT_ASSERT(
261 OUString("July, the 4th").compareTo("July, the 10th") > 0
263 CPPUNIT_ASSERT(
264 compareNatural("July, the 10th", "July, the 4th", xCollator, xBI, lang::Locale()) > 0
266 // Hardest
267 CPPUNIT_ASSERT(
268 compareNatural("abc08", "abc010", xCollator, xBI, lang::Locale()) < 0
270 CPPUNIT_ASSERT(
271 OUString("abc08").compareTo("abc010") > 0
273 CPPUNIT_ASSERT(
274 compareNatural("abc010", "abc08", xCollator, xBI, lang::Locale()) > 0
276 CPPUNIT_ASSERT(
277 compareNatural("apple10apple", "apple10apple", xCollator, xBI, lang::Locale()) == 0
281 void TestString::testRemove()
283 OString aIn("abc");
284 OString aOut;
286 aOut = ::comphelper::string::remove(aIn, 'b');
287 CPPUNIT_ASSERT(aOut == "ac");
289 aIn = "aaa";
291 aOut = ::comphelper::string::remove(aIn, 'a');
292 CPPUNIT_ASSERT(aOut.isEmpty());
295 void TestString::testStripStart()
297 OString aIn("abc");
298 OString aOut;
300 aOut = ::comphelper::string::stripStart(aIn, 'b');
301 CPPUNIT_ASSERT(aOut == "abc");
303 aOut = ::comphelper::string::stripStart(aIn, 'a');
304 CPPUNIT_ASSERT(aOut == "bc");
306 aIn = "aaa";
307 aOut = ::comphelper::string::stripStart(aIn, 'a');
308 CPPUNIT_ASSERT(aOut.isEmpty());
310 aIn = "aba";
311 aOut = ::comphelper::string::stripStart(aIn, 'a');
312 CPPUNIT_ASSERT(aOut == "ba");
315 void TestString::testStripEnd()
317 OString aIn("abc");
318 OString aOut;
320 aOut = ::comphelper::string::stripEnd(aIn, 'b');
321 CPPUNIT_ASSERT(aOut == "abc");
323 aOut = ::comphelper::string::stripEnd(aIn, 'c');
324 CPPUNIT_ASSERT(aOut == "ab");
326 aIn = "aaa";
327 aOut = ::comphelper::string::stripEnd(aIn, 'a');
328 CPPUNIT_ASSERT(aOut.isEmpty());
330 aIn = "aba";
331 aOut = ::comphelper::string::stripEnd(aIn, 'a');
332 CPPUNIT_ASSERT(aOut == "ab");
335 void TestString::testStrip()
337 OString aIn("abc");
338 OString aOut;
340 aOut = ::comphelper::string::strip(aIn, 'b');
341 CPPUNIT_ASSERT(aOut == "abc");
343 aOut = ::comphelper::string::strip(aIn, 'c');
344 CPPUNIT_ASSERT(aOut == "ab");
346 aIn = "aaa";
347 aOut = ::comphelper::string::strip(aIn, 'a');
348 CPPUNIT_ASSERT(aOut.isEmpty());
350 aIn = "aba";
351 aOut = ::comphelper::string::strip(aIn, 'a');
352 CPPUNIT_ASSERT(aOut == "b");
355 void TestString::testToken()
357 OString aIn("10.11.12");
358 OString aOut;
360 aOut = ::comphelper::string::getToken(aIn, -1, '.');
361 CPPUNIT_ASSERT(aOut.isEmpty());
363 aOut = ::comphelper::string::getToken(aIn, 0, '.');
364 CPPUNIT_ASSERT(aOut == "10");
366 aOut = ::comphelper::string::getToken(aIn, 1, '.');
367 CPPUNIT_ASSERT(aOut == "11");
369 aOut = ::comphelper::string::getToken(aIn, 2, '.');
370 CPPUNIT_ASSERT(aOut == "12");
372 aOut = ::comphelper::string::getToken(aIn, 3, '.');
373 CPPUNIT_ASSERT(aOut.isEmpty());
376 void TestString::testTokenCount()
378 OString aIn("10.11.12");
379 sal_Int32 nOut;
381 nOut = ::comphelper::string::getTokenCount(aIn, '.');
382 CPPUNIT_ASSERT(nOut == 3);
384 nOut = ::comphelper::string::getTokenCount(aIn, 'X');
385 CPPUNIT_ASSERT(nOut == 1);
387 nOut = ::comphelper::string::getTokenCount(OString(), 'X');
388 CPPUNIT_ASSERT(nOut == 0);
391 void TestString::testReverseString()
393 OString aIn("ABC");
394 OString aOut = ::comphelper::string::reverseString(aIn);
396 CPPUNIT_ASSERT(aOut == "CBA");
399 void TestString::testEqualsString()
401 OString aIn("A");
402 CPPUNIT_ASSERT(::comphelper::string::equals(aIn, 'A'));
403 CPPUNIT_ASSERT(!::comphelper::string::equals(aIn, 'B'));
404 aIn = OString("AA");
405 CPPUNIT_ASSERT(!::comphelper::string::equals(aIn, 'A'));
406 aIn = OString();
407 CPPUNIT_ASSERT(!::comphelper::string::equals(aIn, 'A'));
410 CPPUNIT_TEST_SUITE_REGISTRATION(TestString);
414 CPPUNIT_PLUGIN_IMPLEMENT();
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */