diff options
Diffstat (limited to 'sal/qa/rtl/strings')
-rw-r--r-- | sal/qa/rtl/strings/compile-oustring.cxx | 45 | ||||
-rw-r--r-- | sal/qa/rtl/strings/nonconstarray.cxx | 94 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_ostring.cxx | 123 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_ostring_concat.cxx | 206 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_ostring_stringliterals.cxx | 282 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_ostringbuffer.cxx | 56 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_compare.cxx | 97 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_concat.cxx | 213 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_convert.cxx | 177 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_endswith.cxx | 113 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_startswith.cxx | 38 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_oustring_stringliterals.cxx | 432 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_strings_defaultstringview.cxx | 118 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_strings_replace.cxx | 339 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_strings_toint.cxx | 72 | ||||
-rw-r--r-- | sal/qa/rtl/strings/test_strings_valuex.cxx | 115 |
16 files changed, 2520 insertions, 0 deletions
diff --git a/sal/qa/rtl/strings/compile-oustring.cxx b/sal/qa/rtl/strings/compile-oustring.cxx new file mode 100644 index 000000000..667a52324 --- /dev/null +++ b/sal/qa/rtl/strings/compile-oustring.cxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <rtl/string.h> +#include <rtl/ustring.hxx> + +// expected-note@rtl/ustring.hxx:* 1+ {{}} + +void checkExtraIntArgument() +{ + // This makes sure that using by mistake RTL_CONSTASCII_STRINGPARAM does not trigger a different + // overload, i.e. the second argument to match() in this case is the indexFrom argument, + // but with the macro it would contain the length of the string. Therefore + // match( RTL_CONSTASCII_STRINGPARAM( "bar" )) would be match( "bar", 3 ), which would be + // true when called for OUString( "foobar" ). But this should not happen because of the + // &foo[0] trick in the RTL_CONSTASCII_STRINGPARAM macro. + // expected-error@+1 {{}} + OUString("foobar").match(RTL_CONSTASCII_STRINGPARAM("bar")); +} + +void checkNonconstChar() +{ + // check that non-const char[] data do not trigger string literal overloads + char test[] = "test"; + char bar[] = "bar"; + const char consttest[] = "test"; + const char constbar[] = "bar"; + // expected-error@+1 {{}} + (void)OUString("footest").replaceAll(test, bar); + // expected-error@+1 {{}} + (void)OUString("footest").replaceAll(consttest, bar); + // expected-error@+1 {{}} + (void)OUString("footest").replaceAll(test, constbar); + (void)OUString("footest").replaceAll(consttest, constbar); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/qa/rtl/strings/nonconstarray.cxx b/sal/qa/rtl/strings/nonconstarray.cxx new file mode 100644 index 000000000..4b66e4e31 --- /dev/null +++ b/sal/qa/rtl/strings/nonconstarray.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +namespace +{ +class Test : public CppUnit::TestFixture +{ +private: + void testOString() + { + struct S + { + char a[4]; + }; + S s{ "x\0y" }; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OString(s.a).getLength()); + // Ideally, the below would work the same as the above. However, the const reference makes + // the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick in, so that the + // call to OString(r.a) would fire the ConstCharArrayDetector<T>::isValid assert (and in + // NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1): + if ((false)) + { + S const& r = s; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OString(r.a).getLength()); + } + } + + void testOUStringChar() + { + struct S + { + char a[4]; + }; + S s{ "x\0y" }; + // This would fail to compile, as there is no OUString ctor taking a + // NonConstCharArrayDetector char array: +#if 0 + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(s.a).getLength()); +#endif + // Ideally, the below would fail to compile the same as the above. However, the const + // reference makes the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick + // in, so that the call to OUString(r.a) would fire the ConstCharArrayDetector<T>::isValid + // assert (and in NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1): + if ((false)) + { + S const& r = s; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(r.a).getLength()); + } + } + + void testOUStringChar16t() + { + struct S + { + char16_t a[4]; + }; + S s{ u"x\0y" }; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(s.a).getLength()); + // Ideally, the below would work the same as the above. However, the const reference makes + // the ConstCharArrayDetector instead of the NonConstCharArrayDetector kick in, so that the + // call to OUString(r.a) would fire the ConstCharArrayDetector<T>::isValid assert (and in + // NDEBUG builds the CPPUNIT_ASSERT_EQUAL would fail with 3 != 1):: + if ((false)) + { + S const& r = s; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), OUString(r.a).getLength()); + } + } + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testOString); + CPPUNIT_TEST(testOUStringChar); + CPPUNIT_TEST(testOUStringChar16t); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/qa/rtl/strings/test_ostring.cxx b/sal/qa/rtl/strings/test_ostring.cxx new file mode 100644 index 000000000..b4fb201ca --- /dev/null +++ b/sal/qa/rtl/strings/test_ostring.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.hxx> + +namespace { + +class Test: public CppUnit::TestFixture { +private: + void testStartsWithIgnoreAsciiCase(); + void testCompareTo(); + void testUtf8StringLiterals(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testStartsWithIgnoreAsciiCase); + CPPUNIT_TEST(testCompareTo); + CPPUNIT_TEST(testUtf8StringLiterals); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::testStartsWithIgnoreAsciiCase() { + { + OString r; + CPPUNIT_ASSERT(OString().startsWithIgnoreAsciiCase(std::string_view(), &r)); + CPPUNIT_ASSERT(r.isEmpty()); + } + { + OString r; + CPPUNIT_ASSERT(OString("foo").startsWithIgnoreAsciiCase(std::string_view(), &r)); + CPPUNIT_ASSERT_EQUAL(OString("foo"), r); + } + { + OString r; + CPPUNIT_ASSERT( + OString("foo").startsWithIgnoreAsciiCase("F", &r)); + CPPUNIT_ASSERT_EQUAL(OString("oo"), r); + } + { + OString r("other"); + CPPUNIT_ASSERT( + !OString("foo").startsWithIgnoreAsciiCase("bar", &r)); + CPPUNIT_ASSERT_EQUAL(OString("other"), r); + } + { + OString r("other"); + CPPUNIT_ASSERT( + !OString("foo").startsWithIgnoreAsciiCase("foobar", &r)); + CPPUNIT_ASSERT_EQUAL(OString("other"), r); + } + + { + OString r; + CPPUNIT_ASSERT(OString().startsWithIgnoreAsciiCase("", &r)); + CPPUNIT_ASSERT(r.isEmpty()); + } + { + OString r; + CPPUNIT_ASSERT(OString("foo").startsWithIgnoreAsciiCase("", &r)); + CPPUNIT_ASSERT_EQUAL(OString("foo"), r); + } + { + OString r; + CPPUNIT_ASSERT( + OString("foo").startsWithIgnoreAsciiCase("F", &r)); + CPPUNIT_ASSERT_EQUAL(OString("oo"), r); + } + { + OString r("other"); + CPPUNIT_ASSERT( + !OString("foo").startsWithIgnoreAsciiCase("bar", &r)); + CPPUNIT_ASSERT_EQUAL(OString("other"), r); + } + { + OString r("other"); + CPPUNIT_ASSERT( + !OString("foo").startsWithIgnoreAsciiCase("foobar", &r)); + CPPUNIT_ASSERT_EQUAL(OString("other"), r); + } +} + +void Test::testCompareTo() +{ + // test that embedded NUL does not stop the compare + char str1[2] = { '\0', 'x' }; + char str2[2] = { '\0', 'y' }; + + OString s1(str1, 2); + OString s2(str2, 2); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s1.compareTo(s1)); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s2.compareTo(s2)); + CPPUNIT_ASSERT(s1.compareTo(s2) < 0); + CPPUNIT_ASSERT(s2.compareTo(s1) > 0); + CPPUNIT_ASSERT(s1.compareTo(OString(s2 + "y")) < 0); + CPPUNIT_ASSERT(s2.compareTo(OString(s1 + "x")) > 0); + CPPUNIT_ASSERT(OString(s1 + "x").compareTo(s2) < 0); + CPPUNIT_ASSERT(OString(s2 + "y").compareTo(s1) > 0); +} + +void Test::testUtf8StringLiterals() +{ + const OString sIn(u8"ßa"); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sIn.getLength()); + CPPUNIT_ASSERT_EQUAL(195, int(static_cast<unsigned char>(sIn[0]))); + CPPUNIT_ASSERT_EQUAL(159, int(static_cast<unsigned char>(sIn[1]))); + CPPUNIT_ASSERT_EQUAL(97, int(static_cast<unsigned char>(sIn[2]))); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_ostring_concat.cxx b/sal/qa/rtl/strings/test_ostring_concat.cxx new file mode 100644 index 000000000..853f97564 --- /dev/null +++ b/sal/qa/rtl/strings/test_ostring_concat.cxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// activate support for detecting errors instead of getting compile errors +#define RTL_STRING_UNITTEST_CONCAT + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <string> +#include <typeinfo> + +bool rtl_string_unittest_invalid_concat = false; + +using namespace rtl; + +namespace CppUnit +{ +template<> struct assertion_traits<std::type_info> +{ + static bool equal(std::type_info const & x, std::type_info const & y) { return x == y; } + + static std::string toString(std::type_info const & x) { return x.name(); } +}; +} // namespace + +namespace test::ostring { + +class StringConcat : public CppUnit::TestFixture +{ +private: + void checkConcat(); + void checkEnsureCapacity(); + void checkAppend(); + void checkInvalid(); + +CPPUNIT_TEST_SUITE(StringConcat); +CPPUNIT_TEST(checkConcat); +CPPUNIT_TEST(checkEnsureCapacity); +CPPUNIT_TEST(checkAppend); +CPPUNIT_TEST(checkInvalid); +CPPUNIT_TEST_SUITE_END(); +}; + +void test::ostring::StringConcat::checkConcat() +{ +// All the extra () are to protect commas against being treated as separators of macro arguments. + CPPUNIT_ASSERT_EQUAL( OString(), OString(OString() + OString())); + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString( "foo" ) + OString( "bar" ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OString > )), typeid( OString( "foo" ) + OString( "bar" ))); + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char[ 4 ] > )), typeid( OString( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), OString( OString( "foo" ) + "bar" + "baz" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OString, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString( "foo" ) + "bar" + "baz" )); + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringBuffer( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringBuffer, const char[ 4 ] > )), typeid( OStringBuffer( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + "bar" )); +#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__ + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char[ 4 ] > )), typeid( OStringLiteral<4>( "foo" ) + "bar" )); + // the explicit OStringLiteral<4> template argument in the unevaluated typeid context + // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878> + // "Failed class template argument deduction in unevaluated, parenthesized context" +#else + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char[ 4 ] > )), typeid( OStringLiteral( "foo" ) + "bar" )); +#endif + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + static_cast<const char*>("bar") )); +#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__ + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char* > )), typeid( OStringLiteral<4>( "foo" ) + static_cast<const char*>("bar") )); + // the explicit OStringLiteral<4> template argument in the unevaluated typeid context + // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878> + // "Failed class template argument deduction in unevaluated, parenthesized context" +#else + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char* > )), typeid( OStringLiteral( "foo" ) + static_cast<const char*>("bar") )); +#endif + const char d1[] = "xyz"; + char d2[] = "abc"; + const char* d3 = d1; + char* d4 = d2; + CPPUNIT_ASSERT_EQUAL( OString( "fooxyz" ), OString( OString( "foo" ) + d1 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char[ 4 ] > )), typeid( OString( "foo" ) + d1 )); + CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d2 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char[ 4 ] > )), typeid( OString( "foo" ) + d2 )); + CPPUNIT_ASSERT_EQUAL( OString( "fooxyz" ), OString( OString( "foo" ) + d3 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, const char* > )), typeid( OString( "foo" ) + d3 )); + CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 )); + CPPUNIT_ASSERT_EQUAL( OString( "fooabc" ), OString( OString( "foo" ) + d4 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, char* > )), typeid( OString( "foo" ) + d4 )); + CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OString::Concat( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "xyzbar" ), OString( OString::Concat( d1 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( d1 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "abcbar" ), OString( OString::Concat( d2 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, char[ 4 ] >, const char[ 4 ] > )), typeid( OString::Concat( d2 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "xyzbar" ), OString( OString::Concat( d3 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, const char* >, const char[ 4 ] > )), typeid( OString::Concat( d3 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OString( "abcbar" ), OString( OString::Concat( d4 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringConcat< OStringConcatMarker, char* >, const char[ 4 ] > )), typeid( OString::Concat( d4 ) + "bar" )); + + CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10 ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< int > > )), typeid( OString( "num" ) + OString::number( 10 ))); + CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10L ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< long long > > )), typeid( OString( "num" ) + OString::number( 10L ))); + CPPUNIT_ASSERT_EQUAL( OString( "num10" ), OString( OString( "num" ) + OString::number( 10ULL ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< unsigned long long > > )), typeid( OString( "num" ) + OString::number( 10ULL ))); + CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5f ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< float > > )), typeid( OString( "num" ) + OString::number( 10.5f ))); + CPPUNIT_ASSERT_EQUAL( OString( "num10.5" ), OString( OString( "num" ) + OString::number( 10.5 ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OString, OStringNumber< double > > )), typeid( OString( "num" ) + OString::number( 10.5 ))); +} + +void test::ostring::StringConcat::checkEnsureCapacity() +{ + rtl_String* str = nullptr; + rtl_string_newFromLiteral( &str, "test", strlen( "test" ), 0 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + + rtl_String* oldStr = str; + rtl_string_ensureCapacity( &str, 4 ); // should be no-op + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + CPPUNIT_ASSERT_EQUAL( str, oldStr ); + + rtl_string_acquire( oldStr ); + CPPUNIT_ASSERT_EQUAL( 2, int( str->refCount )); + rtl_string_ensureCapacity( &str, 4 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + // a copy was forced because of refcount + CPPUNIT_ASSERT( oldStr != str ); + CPPUNIT_ASSERT_EQUAL( 0, strcmp( oldStr->buffer, str->buffer ) ); + CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount )); + rtl_string_release( str ); + str = oldStr; + + rtl_string_acquire( oldStr ); + rtl_string_ensureCapacity( &str, 1024 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4 + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + CPPUNIT_ASSERT( oldStr != str ); + CPPUNIT_ASSERT_EQUAL( 0, strcmp( oldStr->buffer, str->buffer ) ); + CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount )); + strcpy( str->buffer, "01234567890123456789" ); // but there should be extra capacity + str->length += 20; + rtl_string_release( str ); + rtl_string_release( oldStr ); +} + +void test::ostring::StringConcat::checkAppend() +{ + OString str( "foo" ); + str += OStringLiteral( "bar" ) + "baz"; + CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), str ); + OStringBuffer buf( "foo" ); + buf.append( OStringLiteral( "bar" ) + "baz" ); + CPPUNIT_ASSERT_EQUAL( OString( "foobarbaz" ), buf.makeStringAndClear()); +} + +#define INVALID_CONCAT( expression ) \ + ( \ + rtl_string_unittest_invalid_concat = false, \ + ( void ) OString( expression ), \ + rtl_string_unittest_invalid_concat ) + +void test::ostring::StringConcat::checkInvalid() +{ + CPPUNIT_ASSERT( !INVALID_CONCAT( OString() + OString())); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUStringBuffer( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUStringLiteral( u"b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString::Concat( u"b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + 1 )); + rtl_String* rs = nullptr; + rtl_uString* rus = nullptr; + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs )); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus )); + CPPUNIT_ASSERT( INVALID_CONCAT( OString( "a" ) + OUString::number( 10 ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OString::number( 0 ) + OUString::number( 10 ))); + +#if 0 + // Should fail to compile, to avoid use of OStringConcat lvalues that + // contain dangling references to temporaries: + auto const conc = OStringLiteral("foo") + "bar"; + (void) OString(conc); +#endif +} + +} // namespace + +CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringConcat); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx new file mode 100644 index 000000000..ec0faec94 --- /dev/null +++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// activate the extra needed ctor +#define RTL_STRING_UNITTEST + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.h> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> + +bool rtl_string_unittest_const_literal; +bool rtl_string_unittest_const_literal_function; +static bool rtl_string_unittest_non_const_literal_function; + +namespace test::ostring { + +class StringLiterals: public CppUnit::TestFixture +{ +private: + void checkCtors(); + void checkConstexprCtor(); + void checkUsage(); + void checkNonConstUsage(); + void checkBuffer(); + + void testcall( const char str[] ); + + static const char bad5[]; + static char bad6[]; + + // Check that OStringLiteral ctor is actually constexpr: + static constexpr rtlunittest::OStringLiteral dummy{"dummy"}; + +CPPUNIT_TEST_SUITE(StringLiterals); +CPPUNIT_TEST(checkCtors); +CPPUNIT_TEST(checkConstexprCtor); +CPPUNIT_TEST(checkUsage); +CPPUNIT_TEST(checkNonConstUsage); +CPPUNIT_TEST(checkBuffer); +CPPUNIT_TEST_SUITE_END(); +}; + +// reset the flag, call OString ctor with the given argument and return +// whether the string literal ctor was used +#define CONST_CTOR_USED( argument ) \ + ( \ + rtl_string_unittest_const_literal = false, \ + ( void ) rtl::OString( argument ), \ + result_tmp = rtl_string_unittest_const_literal, \ + rtl_string_unittest_const_literal = false, \ + ( void ) rtl::OStringBuffer( argument ), \ + rtl_string_unittest_const_literal && result_tmp ) + +void test::ostring::StringLiterals::checkCtors() +{ + bool result_tmp; + CPPUNIT_ASSERT( CONST_CTOR_USED( "test" )); + const char good1[] = "test"; + CPPUNIT_ASSERT( CONST_CTOR_USED( good1 )); + + CPPUNIT_ASSERT( !CONST_CTOR_USED( static_cast<const char*>("test") )); + const char* bad1 = good1; + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad1 )); + char bad2[] = "test"; + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad2 )); + char* bad3 = bad2; + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad3 )); + const char* bad4[] = { "test1" }; + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad4[ 0 ] )); + testcall( good1 ); +#ifndef _MSC_VER + // this is actually not supposed to work (see discussion in stringutils.hxx), + // but gcc and clang somehow manage, so keep it used, just in case some other problem + // shows up somewhen in the future + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad5 )); // size is not known here + CPPUNIT_ASSERT( !CONST_CTOR_USED( bad6 )); +#endif + +// This one is technically broken, since the first element is 6 characters test\0\0, +// but there does not appear a way to detect this by compile time (runtime will assert()). +// RTL_CONSTASCII_USTRINGPARAM() has the same flaw. + const char bad7[][ 6 ] = { "test", "test2" }; +// CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 0 ] )); + CPPUNIT_ASSERT( CONST_CTOR_USED( bad7[ 1 ] )); + +// Check that contents are correct and equal to the case when const char* ctor is used. + CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( static_cast<const char*>("") ) ); + CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( static_cast<const char*>("ab") ) ); + +// Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used. + CPPUNIT_ASSERT_EQUAL( rtl::OString( "" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) ); + CPPUNIT_ASSERT_EQUAL( rtl::OString( "ab" ), rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) ); +} + +const char test::ostring::StringLiterals::bad5[] = "test"; +char test::ostring::StringLiterals::bad6[] = "test"; + +void test::ostring::StringLiterals::testcall( const char str[] ) +{ +#ifndef _MSC_VER + bool result_tmp; + CPPUNIT_ASSERT( !CONST_CTOR_USED( str )); +#else + // MSVC just errors out on this for some reason, which is fine as well + (void)str; +#endif +} + +void test::ostring::StringLiterals::checkConstexprCtor() +{ +#if __cplusplus >= 202002L + static constinit +#endif + rtl::OString s(dummy); + CPPUNIT_ASSERT_EQUAL(oslInterlockedCount(0x40000000), s.pData->refCount); + // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx) + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), s.getLength()); + CPPUNIT_ASSERT_EQUAL(rtl::OString("dummy"), s); + CPPUNIT_ASSERT_EQUAL( + static_cast<void const *>(dummy.getStr()), static_cast<void const *>(s.getStr())); +} + +void test::ostring::StringLiterals::checkUsage() +{ +// simply check that all string literal based calls work as expected +// also check that they really use string literal overload and do not convert to OString + rtl::OString foo( "foo" ); + rtl::OString FoO( "FoO" ); + rtl::OString foobarfoo( "foobarfoo" ); + rtl::OString foobar( "foobar" ); + rtl::OString FooBaRfoo( "FooBaRfoo" ); + rtl::OString FooBaR( "FooBaR" ); + rtl::OString bar( "bar" ); + + rtl_string_unittest_const_literal = false; // start checking for OString conversions + rtl_string_unittest_non_const_literal_function = false; // and check for non-const variants + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = "foo" ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( foobar.match( "foo" )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( foobar.startsWith( "foo" )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( foobar.endsWith( "bar" )); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); +// rtl_string_unittest_const_literal_function = false; +// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" )); +// CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( bool(foo == "foo") ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( bool("foo" == foo) ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( foo != "bar" ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT( "foo" != bar ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + rtl_string_unittest_const_literal_function = false; + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( "foo", 1 ) ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); +// rtl_string_unittest_const_literal_function = false; +// CPPUNIT_ASSERT( foobarfoo.lastIndexOf( "foo" ) == 6 ); +// CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function == true ); + // if this is not true, some of the calls above converted to OString + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal ); + // if this is not true, some of the calls above used non-const variants + CPPUNIT_ASSERT( !rtl_string_unittest_non_const_literal_function ); +} + +void test::ostring::StringLiterals::checkNonConstUsage() +{ +// check that (non-const) char[] overloads work and do not use const char[] overloads + rtl::OString foo( "foo" ); + rtl::OString FoO( "FoO" ); + rtl::OString foobarfoo( "foobarfoo" ); + rtl::OString foobar( "foobar" ); + rtl::OString FooBaRfoo( "FooBaRfoo" ); + rtl::OString FooBaR( "FooBaR" ); + rtl::OString bar( "bar" ); + char foo_c[] = "foo"; + char bar_c[] = "bar"; + char fOo_c[] = "fOo"; + char bAr_c[] = "bAr"; + + rtl_string_unittest_const_literal = false; // start checking for OString conversions + rtl_string_unittest_const_literal_function = false; // and check for const variants + CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = static_cast<const char*>(foo_c) ); + CPPUNIT_ASSERT_EQUAL( foo, rtl::OString() = foo_c ); + CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( static_cast<const char*>(fOo_c) )); + CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( fOo_c )); + CPPUNIT_ASSERT( foobarfoo.match( static_cast<const char*>(bar_c), 3 )); + CPPUNIT_ASSERT( foobarfoo.match( bar_c, 3 )); + CPPUNIT_ASSERT( foobar.match( static_cast<const char*>(foo_c) )); + CPPUNIT_ASSERT( foobar.match( foo_c )); + CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( static_cast<const char*>(bAr_c), 3 )); + CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( bAr_c, 3 )); + CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( static_cast<const char*>(fOo_c) )); + CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( fOo_c )); + CPPUNIT_ASSERT( foobar.startsWith( static_cast<const char*>(foo_c) )); + CPPUNIT_ASSERT( foobar.startsWith( foo_c )); + CPPUNIT_ASSERT( foobar.endsWith( static_cast<const char*>(bar_c) )); + CPPUNIT_ASSERT( foobar.endsWith( bar_c )); +// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( (const char*)bar_c )); +// CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( bar_c )); + CPPUNIT_ASSERT( bool(foo == static_cast<const char*>(foo_c)) ); + CPPUNIT_ASSERT( bool(foo == foo_c) ); + CPPUNIT_ASSERT( bool(static_cast<const char*>(foo_c) == foo) ); + CPPUNIT_ASSERT( bool(foo_c == foo) ); + CPPUNIT_ASSERT( foo != static_cast<const char*>(bar_c) ); + CPPUNIT_ASSERT( foo != bar_c ); + CPPUNIT_ASSERT( static_cast<const char*>(foo_c) != bar ); + CPPUNIT_ASSERT( foo_c != bar ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( static_cast<const char*>(foo_c), 1 ) ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( foo_c, 1 ) ); +// CPPUNIT_ASSERT( foobarfoo.lastIndexOf( (const char*)foo_c ) == 6 ); +// CPPUNIT_ASSERT( foobarfoo.lastIndexOf( foo_c ) == 6 ); + // if this is not true, some of the calls above used const variants + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal ); + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function ); +} + +void test::ostring::StringLiterals::checkBuffer() +{ + rtl::OStringBuffer buf; + rtl_string_unittest_const_literal_function = false; + buf.append( "foo" ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + CPPUNIT_ASSERT_EQUAL( rtl::OString( "foo" ), buf.toString()); + rtl_string_unittest_const_literal_function = false; + buf.append( "bar" ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobar" ), buf.toString()); + rtl_string_unittest_const_literal_function = false; + buf.insert( 3, "baz" ); + CPPUNIT_ASSERT( rtl_string_unittest_const_literal_function ); + CPPUNIT_ASSERT_EQUAL( rtl::OString( "foobazbar" ), buf.toString()); + + rtl::OString foobazbard( "foobazbard" ); + rtl::OString foodbazbard( "foodbazbard" ); + rtl_string_unittest_const_literal = false; // start checking for OString conversions + rtl_string_unittest_const_literal_function = false; // and check for const variants + char d[] = "d"; + CPPUNIT_ASSERT_EQUAL( foobazbard, buf.append( d ).toString()); + CPPUNIT_ASSERT_EQUAL( foodbazbard, buf.insert( 3, d ).toString() ); + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal ); + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal_function ); +} + +#undef CONST_CTOR_USED + +} // namespace + +CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_ostringbuffer.cxx b/sal/qa/rtl/strings/test_ostringbuffer.cxx new file mode 100644 index 000000000..292e24310 --- /dev/null +++ b/sal/qa/rtl/strings/test_ostringbuffer.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <string_view> + +#include <cppunit/TestFixture.h> +#include <cppunit/TestAssert.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <rtl/strbuf.hxx> +#include <rtl/stringutils.hxx> +#include <sal/types.h> + +namespace +{ +class Test : public CppUnit::TestFixture +{ +private: + void testStringView() + { + OStringBuffer b("foobar"); + b = std::string_view("abc").substr( + 0, 2); // avoid the string_view accidentally being NUL-terminated + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), b.getLength()); + CPPUNIT_ASSERT_EQUAL('a', b.getStr()[0]); + CPPUNIT_ASSERT_EQUAL('b', b.getStr()[1]); + CPPUNIT_ASSERT_EQUAL('\0', b.getStr()[2]); + } + + void testOStringChar() + { + OStringBuffer b("foobar"); + b = OStringChar('a'); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), b.getLength()); + CPPUNIT_ASSERT_EQUAL('a', b.getStr()[0]); + CPPUNIT_ASSERT_EQUAL('\0', b.getStr()[1]); + } + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testStringView); + CPPUNIT_TEST(testOStringChar); + CPPUNIT_TEST_SUITE_END(); +}; +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/qa/rtl/strings/test_oustring_compare.cxx b/sal/qa/rtl/strings/test_oustring_compare.cxx new file mode 100644 index 000000000..e55d4d3d9 --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_compare.cxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.h> +#include <rtl/ustring.hxx> + +namespace test::oustring { + +class Compare: public CppUnit::TestFixture +{ +private: + void equalsIgnoreAsciiCaseAscii(); + void compareToIgnoreAsciiCase(); + void compareTo(); + +CPPUNIT_TEST_SUITE(Compare); +CPPUNIT_TEST(equalsIgnoreAsciiCaseAscii); +CPPUNIT_TEST(compareToIgnoreAsciiCase); +CPPUNIT_TEST(compareTo); +CPPUNIT_TEST_SUITE_END(); +}; + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::Compare); + +void test::oustring::Compare::equalsIgnoreAsciiCaseAscii() +{ + const char* const abc = "abc"; + const char* const abcd = "abcd"; + const char* const empty = ""; + CPPUNIT_ASSERT(!OUString().equalsIgnoreAsciiCaseAscii(abc)); + CPPUNIT_ASSERT(!OUString().equalsIgnoreAsciiCaseAsciiL(abc,3)); + CPPUNIT_ASSERT(!OUString("abc"). + equalsIgnoreAsciiCaseAscii(empty)); + CPPUNIT_ASSERT(!OUString("abc"). + equalsIgnoreAsciiCaseAsciiL(empty,0)); + + CPPUNIT_ASSERT(OUString("abc"). + equalsIgnoreAsciiCaseAscii(abc)); + CPPUNIT_ASSERT(!OUString("abcd"). + equalsIgnoreAsciiCaseAscii(abc)); + CPPUNIT_ASSERT(!OUString("abc"). + equalsIgnoreAsciiCaseAscii(abcd)); +} + +void test::oustring::Compare::compareToIgnoreAsciiCase() +{ + CPPUNIT_ASSERT_EQUAL( + sal_Int32(0), + OUString("abc").compareToIgnoreAsciiCase(u"ABC")); + CPPUNIT_ASSERT( + OUString("ABC").compareToIgnoreAsciiCase(u"abcdef") + < 0); + CPPUNIT_ASSERT( + OUString("A").compareToIgnoreAsciiCase(u"_") > 0); +} + +void test::oustring::Compare::compareTo() +{ + // test that embedded NUL does not stop the compare + // this sort of thing is how we assign shape ids in oox + sal_Unicode str1[2] = { '\0', 'x' }; + sal_Unicode str2[2] = { '\0', 'y' }; + + OUString s1(str1, 2); + OUString s2(str2, 2); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s1.compareTo(s1)); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), s2.compareTo(s2)); + CPPUNIT_ASSERT(s1.compareTo(s2) < 0); + CPPUNIT_ASSERT(s2.compareTo(s1) > 0); + CPPUNIT_ASSERT(s1.compareTo(OUStringConcatenation(s2 + "y")) < 0); + CPPUNIT_ASSERT(s2.compareTo(OUStringConcatenation(s1 + "x")) > 0); + CPPUNIT_ASSERT(OUString(s1 + "x").compareTo(s2) < 0); + CPPUNIT_ASSERT(OUString(s2 + "y").compareTo(s1) > 0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_concat.cxx b/sal/qa/rtl/strings/test_oustring_concat.cxx new file mode 100644 index 000000000..5a11da892 --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_concat.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// activate support for detecting errors instead of getting compile errors +#define RTL_STRING_UNITTEST_CONCAT +extern bool rtl_string_unittest_invalid_concat; + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> + +#include <string> +#include <typeinfo> + +using namespace rtl; + +namespace CppUnit +{ +template<> struct assertion_traits<std::type_info> +{ + static bool equal(std::type_info const & x, std::type_info const & y) { return x == y; } + + static std::string toString(std::type_info const & x) { return x.name(); } +}; +} // namespace + +namespace test::oustring { + +class StringConcat : public CppUnit::TestFixture +{ +private: + void checkConcat(); + void checkConcatAsciiL(); + void checkEnsureCapacity(); + void checkAppend(); + void checkInvalid(); + +CPPUNIT_TEST_SUITE(StringConcat); +CPPUNIT_TEST(checkConcat); +CPPUNIT_TEST(checkConcatAsciiL); +CPPUNIT_TEST(checkEnsureCapacity); +CPPUNIT_TEST(checkAppend); +CPPUNIT_TEST(checkInvalid); +CPPUNIT_TEST_SUITE_END(); +}; + +void test::oustring::StringConcat::checkConcat() +{ +// All the extra () are to protect commas against being treated as separators of macro arguments. + CPPUNIT_ASSERT_EQUAL( OUString(), OUString(OUString() + OUString())); + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString( "foo" ) + OUString( "bar" ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUString > )), typeid( OUString( "foo" ) + OUString( "bar" ))); + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), OUString( OUString( "foo" ) + "bar" + "baz" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< OUString, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString( "foo" ) + "bar" + "baz" )); + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUStringBuffer( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringBuffer, const char[ 4 ] > )), typeid( OUStringBuffer( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUStringLiteral( u"foo" ) + "bar" )); +#if defined __GNUC__ && __GNUC__ <= 11 && !defined __clang__ + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringLiteral<4>, const char[ 4 ] > )), typeid( OUStringLiteral<4>( u"foo" ) + "bar" )); + // the explicit OUStringLiteral<4> template argument in the unevaluated typeid context + // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878> + // "Failed class template argument deduction in unevaluated, parenthesized context" +#else + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringLiteral<4>, const char[ 4 ] > )), typeid( OUStringLiteral( u"foo" ) + "bar" )); +#endif + const char d1[] = "xyz"; + CPPUNIT_ASSERT_EQUAL( OUString( "fooxyz" ), OUString( OUString( "foo" ) + d1 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const char[ 4 ] > )), typeid( OUString( "foo" ) + d1 )); + const sal_Unicode* d2 = u"xyz"; + CPPUNIT_ASSERT_EQUAL( OUString( "fooxyz" ), OUString( OUString( "foo" ) + d2 )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, const sal_Unicode* > )), typeid( OUString( "foo" ) + d2 )); + const sal_Unicode d3[] = u"xyz"; + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString::Concat( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( "foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d1 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const char[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( d1 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "foobar" ), OUString( OUString::Concat( u"foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( u"foo" ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d2 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode* >, const char[ 4 ] > )), typeid( OUString::Concat( d2 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL( OUString( "xyzbar" ), OUString( OUString::Concat( d3 ) + "bar" )); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUStringConcat< rtl::OUStringConcatMarker, const sal_Unicode[ 4 ] >, const char[ 4 ] > )), typeid( OUString::Concat( d3 ) + "bar" )); + + CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10 ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< int > > )), typeid( OUString( "num" ) + OUString::number( 10 ))); + CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10L ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< long long > > )), typeid( OUString( "num" ) + OUString::number( 10L ))); + CPPUNIT_ASSERT_EQUAL( OUString( "num10" ), OUString( OUString( "num" ) + OUString::number( 10ULL ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< unsigned long long > > )), typeid( OUString( "num" ) + OUString::number( 10ULL ))); + CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5f ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< float > > )), typeid( OUString( "num" ) + OUString::number( 10.5f ))); + CPPUNIT_ASSERT_EQUAL( OUString( "num10.5" ), OUString( OUString( "num" ) + OUString::number( 10.5 ))); + CPPUNIT_ASSERT_EQUAL(( typeid( OUStringConcat< OUString, OUStringNumber< double > > )), typeid( OUString( "num" ) + OUString::number( 10.5 ))); +} + +void test::oustring::StringConcat::checkConcatAsciiL() +{ + { + OUString s("foo"); + s += ""; + CPPUNIT_ASSERT_EQUAL(OUString("foo"), s); + } + { + OUString s("foo"); + s += "bar"; + CPPUNIT_ASSERT_EQUAL(OUString("foobar"), s); + } +} + +void test::oustring::StringConcat::checkEnsureCapacity() +{ + rtl_uString* str = nullptr; + rtl_uString_newFromLiteral( &str, "test", strlen( "test" ), 0 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + + rtl_uString* oldStr = str; + rtl_uString_ensureCapacity( &str, 4 ); // should be no-op + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + CPPUNIT_ASSERT_EQUAL( str, oldStr ); + + rtl_uString_acquire( oldStr ); + CPPUNIT_ASSERT_EQUAL( 2, int( str->refCount )); + rtl_uString_ensureCapacity( &str, 4 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + // a copy was forced because of refcount + CPPUNIT_ASSERT( oldStr != str ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), rtl_ustr_compare( oldStr->buffer, str->buffer ) ); + CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount )); + rtl_uString_release( str ); + str = oldStr; + + rtl_uString_acquire( oldStr ); + rtl_uString_ensureCapacity( &str, 1024 ); + CPPUNIT_ASSERT_EQUAL( sal_Int32( 4 ), str->length ); // size is still 4 + CPPUNIT_ASSERT_EQUAL( 1, int( str->refCount )); + CPPUNIT_ASSERT( oldStr != str ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), rtl_ustr_compare( oldStr->buffer, str->buffer ) ); + CPPUNIT_ASSERT_EQUAL( 1, int( oldStr->refCount )); + // but there should be extra capacity + for( int i = 0; + i < 20; + ++i ) + str->buffer[ str->length + i ] = '0'; + str->length += 20; + rtl_uString_release( str ); + rtl_uString_release( oldStr ); +} + +void test::oustring::StringConcat::checkAppend() +{ + OUString str( "foo" ); + str += OUStringLiteral( u"bar" ) + "baz"; + CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), str ); + OUStringBuffer buf( "foo" ); + buf.append( OUStringLiteral( u"bar" ) + "baz" ); + CPPUNIT_ASSERT_EQUAL( OUString( "foobarbaz" ), buf.makeStringAndClear()); +} + +#define INVALID_CONCAT( expression ) \ + ( \ + rtl_string_unittest_invalid_concat = false, \ + ( void ) OUString( expression ), \ + rtl_string_unittest_invalid_concat ) + +void test::oustring::StringConcat::checkInvalid() +{ + CPPUNIT_ASSERT( !INVALID_CONCAT( OUString() + OUString())); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OStringBuffer( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + static_cast<const char*>("b") )); + char d[] = "b"; + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + d )); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + static_cast<char*>(d) )); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OStringLiteral( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString::Concat( "b" ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + 1 )); + rtl_String* rs = nullptr; + rtl_uString* rus = nullptr; + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs )); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus )); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "a" ) + OString::number( 10 ))); + CPPUNIT_ASSERT( INVALID_CONCAT( OUString::number( 0 ) + OString::number( 10 ))); + +#if 0 + // Should fail to compile, to avoid use of OUStringConcat lvalues that + // contain dangling references to temporaries: + auto const conc = OUStringLiteral("foo") + "bar"; + (void) OUString(conc); +#endif +} + +} // namespace + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringConcat); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_convert.cxx b/sal/qa/rtl/strings/test_oustring_convert.cxx new file mode 100644 index 000000000..da930a03f --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_convert.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/macros.h> + +namespace test::oustring { + +class Convert: public CppUnit::TestFixture +{ +private: + void convertToString(); + + CPPUNIT_TEST_SUITE(Convert); + CPPUNIT_TEST(convertToString); + CPPUNIT_TEST_SUITE_END(); +}; + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::Convert); + +namespace { + +struct TestConvertToString +{ + sal_Unicode aSource[100]; + sal_Int32 nLength; + rtl_TextEncoding nEncoding; + sal_uInt32 nFlags; + char const * pStrict; + char const * pRelaxed; +}; + +void testConvertToString(TestConvertToString const & rTest) +{ + const OUString aSource(rTest.aSource, rTest.nLength); + OString aStrict(RTL_CONSTASCII_STRINGPARAM("12345")); + bool bSuccess = aSource.convertToString(&aStrict, rTest.nEncoding, + rTest.nFlags); + OString aRelaxed(OUStringToOString(aSource, rTest.nEncoding, + rTest.nFlags)); + + OStringBuffer aPrefix; + aPrefix.append("{"); + for (sal_Int32 i = 0; i < rTest.nLength; ++i) + { + aPrefix.append("U+"); + aPrefix.append(static_cast< sal_Int32 >(rTest.aSource[i]), 16); + if (i + 1 < rTest.nLength) + aPrefix.append(","); + } + aPrefix.append("}, "); + aPrefix.append(static_cast< sal_Int32 >(rTest.nEncoding)); + aPrefix.append(", 0x"); + aPrefix.append(static_cast< sal_Int32 >(rTest.nFlags), 16); + aPrefix.append(" -> "); + + if (bSuccess) + { + if (rTest.pStrict == nullptr || aStrict != rTest.pStrict) + { + OStringBuffer aMessage(aPrefix); + aMessage.append("strict = \""); + aMessage.append(aStrict); + aMessage.append("\""); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false); + } + } + else + { + if (aStrict != "12345") + { + OStringBuffer aMessage(aPrefix); + aMessage.append("modified output"); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false); + } + if (rTest.pStrict != nullptr) + { + OStringBuffer aMessage(aPrefix); + aMessage.append("failed"); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false); + } + } + if (aRelaxed != rTest.pRelaxed) + { + OStringBuffer aMessage(aPrefix); + aMessage.append("relaxed = \""); + aMessage.append(aRelaxed); + aMessage.append("\""); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), false); + } +} + +} + +void test::oustring::Convert::convertToString() +{ + TestConvertToString const aTests[] + = { { { 0 }, + 0, + RTL_TEXTENCODING_ASCII_US, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR, + "", + "" }, + { { 0 }, + 0, + RTL_TEXTENCODING_ASCII_US, + OUSTRING_TO_OSTRING_CVTFLAGS, + "", + "" }, + { { 0x0041,0x0042,0x0043 }, + 3, + RTL_TEXTENCODING_ASCII_US, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR, + "ABC", + "ABC" }, + { { 0x0041,0x0042,0x0043 }, + 3, + RTL_TEXTENCODING_ASCII_US, + OUSTRING_TO_OSTRING_CVTFLAGS, + "ABC", + "ABC" }, + { { 0xB800 }, + 1, + RTL_TEXTENCODING_ISO_2022_JP, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR, + nullptr, + "" }, + { { 0x3001, 0xB800 }, + 2, + RTL_TEXTENCODING_ISO_2022_JP, + OUSTRING_TO_OSTRING_CVTFLAGS, + "\x1b\x24\x42\x21\x22\x1b\x28\x42\x3f", + "\x1b\x24\x42\x21\x22\x1b\x28\x42\x3f" }, + { { 0x0041,0x0100,0x0042 }, + 3, + RTL_TEXTENCODING_ISO_8859_1, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR, + nullptr, + "A" }, + { { 0x0041,0x0100,0x0042 }, + 3, + RTL_TEXTENCODING_ISO_8859_1, + OUSTRING_TO_OSTRING_CVTFLAGS, + "A?B", + "A?B" } }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i) + testConvertToString(aTests[i]); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_endswith.cxx b/sal/qa/rtl/strings/test_oustring_endswith.cxx new file mode 100644 index 000000000..bf01577e2 --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_endswith.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/strbuf.hxx> +#include <rtl/string.h> +#include <rtl/string.hxx> +#include <rtl/textenc.h> +#include <rtl/ustring.hxx> +#include <sal/macros.h> + +namespace test::oustring { + +class EndsWith: public CppUnit::TestFixture +{ +private: + void endsWith(); + + CPPUNIT_TEST_SUITE(EndsWith); + CPPUNIT_TEST(endsWith); + CPPUNIT_TEST_SUITE_END(); +}; + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::EndsWith); + +namespace { + +void appendString(OStringBuffer & buffer, OString const & string) +{ + buffer.append('"'); + for (int i = 0; i < string.getLength(); ++i) { + char c = string[i]; + if (c < ' ' || c == '"' || c == '\\' || c > '~') { + buffer.append('\\'); + sal_Int32 n = static_cast< sal_Int32 >( + static_cast< unsigned char >(c)); + if (n < 16) { + buffer.append('0'); + } + buffer.append(n, 16); + } else { + buffer.append(c); + } + } + buffer.append('"'); +} + +} + +void test::oustring::EndsWith::endsWith() +{ + struct Data { + char const * str1; + sal_Int32 str1Len; + char const * str2; + sal_Int32 str2Len; + bool endsWith; + }; + Data const data[] = { + { RTL_CONSTASCII_STRINGPARAM(""), RTL_CONSTASCII_STRINGPARAM(""), + true }, + { RTL_CONSTASCII_STRINGPARAM("abc"), RTL_CONSTASCII_STRINGPARAM(""), + true }, + { RTL_CONSTASCII_STRINGPARAM(""), RTL_CONSTASCII_STRINGPARAM("abc"), + false }, + { RTL_CONSTASCII_STRINGPARAM("ABC"), RTL_CONSTASCII_STRINGPARAM("abc"), + true }, + { RTL_CONSTASCII_STRINGPARAM("abcd"), RTL_CONSTASCII_STRINGPARAM("bcd"), + true }, + { RTL_CONSTASCII_STRINGPARAM("bcd"), RTL_CONSTASCII_STRINGPARAM("abcd"), + false }, + { RTL_CONSTASCII_STRINGPARAM("a\0b\0c"), + RTL_CONSTASCII_STRINGPARAM("b\0c"), true }, + { RTL_CONSTASCII_STRINGPARAM("a\0b\0c"), + RTL_CONSTASCII_STRINGPARAM("b"), false } }; + for (size_t i = 0; i < SAL_N_ELEMENTS(data); ++i) { + OStringBuffer msg; + appendString(msg, OString(data[i].str1, data[i].str1Len)); + msg.append(".endsWithIgnoreAsciiCaseAsciiL("); + appendString(msg, OString(data[i].str2, data[i].str2Len)); + msg.append(") == "); + msg.append(data[i].endsWith); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + msg.getStr(), + data[i].endsWith, + OUString( + data[i].str1, data[i].str1Len, + RTL_TEXTENCODING_ASCII_US).endsWithIgnoreAsciiCaseAsciiL( + data[i].str2, data[i].str2Len)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_startswith.cxx b/sal/qa/rtl/strings/test_oustring_startswith.cxx new file mode 100644 index 000000000..a74671e6e --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_startswith.cxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/ustring.hxx> + +namespace test::oustring { + +class StartsWith: public CppUnit::TestFixture +{ +private: + void startsWith(); + + CPPUNIT_TEST_SUITE(StartsWith); + CPPUNIT_TEST(startsWith); + CPPUNIT_TEST_SUITE_END(); +}; + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StartsWith); + +void test::oustring::StartsWith::startsWith() +{ + CPPUNIT_ASSERT( OUString( "foobar" ).startsWith( "foo" )); + CPPUNIT_ASSERT( !OUString( "foo" ).startsWith( "foobar" )); + CPPUNIT_ASSERT( !OUString( "foobar" ).startsWith( "oo" )); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_oustring_stringliterals.cxx b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx new file mode 100644 index 000000000..0caa3fc03 --- /dev/null +++ b/sal/qa/rtl/strings/test_oustring_stringliterals.cxx @@ -0,0 +1,432 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// activate the extra needed ctor +#define RTL_STRING_UNITTEST + +#include <sal/config.h> + +#include <string> +#include <string_view> +#include <utility> + +#include <o3tl/cppunittraitshelper.hxx> +#include <sal/types.h> +#include <config_global.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +extern bool rtl_string_unittest_const_literal; +bool rtl_string_unittest_invalid_conversion; + +namespace test::oustring { + +class StringLiterals: public CppUnit::TestFixture +{ +private: + void checkCtors(); + void checkConstexprCtor(); + void checkUsage(); + void checkBuffer(); + void checkOUStringLiteral(); + void checkOUStringChar(); + void checkUtf16(); + void checkEmbeddedNul(); + + void testcall( const char str[] ); + + // Check that OUStringLiteral ctor is actually constexpr: + static constexpr rtlunittest::OUStringLiteral dummy{u"dummy"}; + +CPPUNIT_TEST_SUITE(StringLiterals); +CPPUNIT_TEST(checkCtors); +CPPUNIT_TEST(checkConstexprCtor); +CPPUNIT_TEST(checkUsage); +CPPUNIT_TEST(checkBuffer); +CPPUNIT_TEST(checkOUStringLiteral); +CPPUNIT_TEST(checkOUStringChar); +CPPUNIT_TEST(checkUtf16); +CPPUNIT_TEST(checkEmbeddedNul); +CPPUNIT_TEST_SUITE_END(); +}; + +// reset the flag, evaluate the expression and return +// whether the string literal ctor was used (i.e. whether the conversion was valid) +template<typename T> static bool VALID_CONVERSION( T && expression ) +{ + rtl_string_unittest_invalid_conversion = false; + // OK to std::forward expression twice; what is relevant in both ctor calls + // is not the content of the passed argument (which is ignored anyway by the + // special RTL_STRING_UNITTEST ctors) but only its type: + ( void ) rtl::OUString( std::forward<T>(expression) ); + ( void ) rtl::OUStringBuffer( std::forward<T>(expression) ); + return !rtl_string_unittest_invalid_conversion; +} +template<typename T> static bool VALID_CONVERSION_CALL( T f ) +{ + rtl_string_unittest_invalid_conversion = false; + ( void ) rtl::OUString( f() ); + ( void ) rtl::OUStringBuffer( f() ); + return !rtl_string_unittest_invalid_conversion; +} + +void test::oustring::StringLiterals::checkCtors() +{ + CPPUNIT_ASSERT( VALID_CONVERSION( "test" )); + const char good1[] = "test"; + CPPUNIT_ASSERT( VALID_CONVERSION( good1 )); + + CPPUNIT_ASSERT( !VALID_CONVERSION( static_cast<const char*>("test") )); + const char* bad1 = good1; + CPPUNIT_ASSERT( !VALID_CONVERSION( bad1 )); + char bad2[] = "test"; + CPPUNIT_ASSERT( !VALID_CONVERSION( bad2 )); + char* bad3 = bad2; + CPPUNIT_ASSERT( !VALID_CONVERSION( bad3 )); + const char* bad4[] = { "test1" }; + CPPUNIT_ASSERT( !VALID_CONVERSION( bad4[ 0 ] )); + testcall( good1 ); + +// This one is technically broken, since the first element is 6 characters test\0\0, +// but there does not appear a way to detect this by compile time (runtime will assert()). +// RTL_CONSTASCII_USTRINGPARAM() has the same flaw. + const char bad5[][ 6 ] = { "test", "test2" }; +// CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 0 ] )); + CPPUNIT_ASSERT( VALID_CONVERSION( bad5[ 1 ] )); + +// Check that contents are correct and equal to the case when RTL_CONSTASCII_USTRINGPARAM is used. + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "" ), rtl::OUString( "" )); + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "ab" ), rtl::OUString( "ab" )); +#if 0 +// Also check that embedded \0 is included. +// In fact, allowing this is probably just trouble, so this now asserts. + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "\0" ), rtl::OUString( "\0" )); + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "a\0b" ), rtl::OUString( "a\0b" )); +#endif +} + +void test::oustring::StringLiterals::testcall( const char str[] ) +{ + CPPUNIT_ASSERT( + !VALID_CONVERSION_CALL([&str]() { return rtl::OUString(str); })); +} + +void test::oustring::StringLiterals::checkConstexprCtor() +{ +#if __cplusplus >= 202002L + static constinit +#endif + rtl::OUString s(dummy); + CPPUNIT_ASSERT_EQUAL(oslInterlockedCount(0x40000000), s.pData->refCount); + // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx) + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), s.getLength()); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("dummy"), s); + CPPUNIT_ASSERT_EQUAL( + static_cast<void const *>(dummy.getStr()), static_cast<void const *>(s.getStr())); +} + +void test::oustring::StringLiterals::checkUsage() +{ +// simply check that all string literal based calls work as expected +// also check that they really use string literal overload and do not convert to OUString + rtl::OUString foo( "foo" ); + rtl::OUString FoO( "FoO" ); + rtl::OUString foobarfoo( "foobarfoo" ); + rtl::OUString foobar( "foobar" ); + rtl::OUString FooBaRfoo( "FooBaRfoo" ); + rtl::OUString FooBaR( "FooBaR" ); + rtl::OUString bar( "bar" ); + rtl::OUString test( "test" ); + + rtl_string_unittest_const_literal = false; // start checking for OUString conversions + CPPUNIT_ASSERT_EQUAL( foo, rtl::OUString() = "foo" ); + CPPUNIT_ASSERT( FoO.equalsIgnoreAsciiCase( "fOo" )); + CPPUNIT_ASSERT( foobarfoo.match( "bar", 3 )); + CPPUNIT_ASSERT( foobar.match( "foo" )); + CPPUNIT_ASSERT( FooBaRfoo.matchIgnoreAsciiCase( "bAr", 3 )); + CPPUNIT_ASSERT( FooBaR.matchIgnoreAsciiCase( "fOo" )); + CPPUNIT_ASSERT( foobar.startsWith( "foo" )); + CPPUNIT_ASSERT( FooBaR.startsWithIgnoreAsciiCase( "foo" )); + CPPUNIT_ASSERT( foobar.endsWith( "bar" )); + CPPUNIT_ASSERT( FooBaR.endsWithIgnoreAsciiCase( "bar" )); + CPPUNIT_ASSERT( bool(foo == "foo") ); + CPPUNIT_ASSERT( bool("foo" == foo) ); + CPPUNIT_ASSERT( foo != "bar" ); + CPPUNIT_ASSERT( "foo" != bar ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.indexOf( "foo", 1 ) ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(6), foobarfoo.lastIndexOf( "foo" ) ); + CPPUNIT_ASSERT( bool(foobarfoo.replaceFirst( "foo", test ) == "testbarfoo") ); + CPPUNIT_ASSERT( bool(foobarfoo.replaceFirst( "foo", "test" ) == "testbarfoo") ); + CPPUNIT_ASSERT( bool(foobarfoo.replaceAll( "foo", test ) == "testbartest") ); + CPPUNIT_ASSERT( bool(foobarfoo.replaceAll( "foo", "test" ) == "testbartest") ); + CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(0), foo.reverseCompareTo( "foo" ) ); + // if this is not true, some of the calls above converted to OUString + CPPUNIT_ASSERT( !rtl_string_unittest_const_literal ); +} + +void test::oustring::StringLiterals::checkBuffer() +{ + rtl::OUStringBuffer buf; + buf.append( "foo" ); + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foo" ), buf.toString()); + buf.append( "bar" ); + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobar" ), buf.toString()); + buf.insert( 3, "baz" ); + CPPUNIT_ASSERT_EQUAL( rtl::OUString( "foobazbar" ), buf.toString()); + char d[] = "d"; + CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUString( d )))); + CPPUNIT_ASSERT( !VALID_CONVERSION( buf.append( rtl::OUStringBuffer( d )))); +} + +namespace { + +rtl::OUString conditional(bool flag) { + return rtl::OUString::Concat(flag ? std::u16string_view(u"a") : std::u16string_view(u"bb")) + + "c"; +} + +} + +void test::oustring::StringLiterals::checkOUStringLiteral() +{ + CPPUNIT_ASSERT(bool(conditional(true) == "ac")); + CPPUNIT_ASSERT(bool(conditional(false) == "bbc")); + + static constexpr rtlunittest::OUStringLiteral s1lit(u"abc"); + rtl::OUString s1(s1lit); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1); + static constexpr rtlunittest::OUStringLiteral de(u"de"); + s1 = de; + CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1); + s1 += rtlunittest::OUStringLiteral(u"fde"); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1); + CPPUNIT_ASSERT_EQUAL( + sal_Int32(0), + s1.reverseCompareTo(rtlunittest::OUStringLiteral(u"defde"))); + CPPUNIT_ASSERT( + s1.equalsIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"DEFDE"))); + CPPUNIT_ASSERT(s1.match(rtlunittest::OUStringLiteral(u"fde"), 2)); + CPPUNIT_ASSERT( + s1.matchIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"FDE"), 2)); + rtl::OUString s2; + CPPUNIT_ASSERT(s1.startsWith(rtlunittest::OUStringLiteral(u"de"), &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("fde"), s2); + CPPUNIT_ASSERT( + s1.startsWithIgnoreAsciiCase( + rtlunittest::OUStringLiteral(u"DEFD"), &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("e"), s2); + CPPUNIT_ASSERT(s1.endsWith(rtlunittest::OUStringLiteral(u"de"), &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("def"), s2); + CPPUNIT_ASSERT( + s1.endsWithIgnoreAsciiCase(rtlunittest::OUStringLiteral(u"EFDE"), &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("d"), s2); + static constexpr rtlunittest::OUStringLiteral defde(u"defde"); + CPPUNIT_ASSERT(bool(s1 == defde)); + CPPUNIT_ASSERT(bool(defde == s1)); + static constexpr rtlunittest::OUStringLiteral abc(u"abc"); + CPPUNIT_ASSERT(s1 != abc); + CPPUNIT_ASSERT(abc != s1); + CPPUNIT_ASSERT_EQUAL( + sal_Int32(3), s1.indexOf(rtlunittest::OUStringLiteral(u"de"), 1)); + CPPUNIT_ASSERT_EQUAL( + sal_Int32(3), s1.lastIndexOf(rtlunittest::OUStringLiteral(u"de"))); + sal_Int32 i = 0; + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfde"), + s1.replaceFirst( + rtlunittest::OUStringLiteral(u"de"), rtl::OUString("abc"), &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfde"), + s1.replaceFirst( + rtl::OUString("de"), rtlunittest::OUStringLiteral(u"abc"), &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfde"), + s1.replaceFirst( + rtlunittest::OUStringLiteral(u"de"), + rtlunittest::OUStringLiteral(u"abc"), &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfde"), + s1.replaceFirst(rtlunittest::OUStringLiteral(u"de"), "abc", &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfde"), + s1.replaceFirst("de", rtlunittest::OUStringLiteral(u"abc"), &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfabc"), + s1.replaceAll( + rtlunittest::OUStringLiteral(u"de"), rtl::OUString("abc"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfabc"), + s1.replaceAll( + rtl::OUString("de"), rtlunittest::OUStringLiteral(u"abc"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfabc"), + s1.replaceAll( + rtlunittest::OUStringLiteral(u"de"), + rtlunittest::OUStringLiteral(u"abc"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfabc"), + s1.replaceAll(rtlunittest::OUStringLiteral(u"de"), "abc")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcfabc"), + s1.replaceAll("de", rtlunittest::OUStringLiteral(u"abc"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcdef"), + rtl::OUString( + rtl::OUString("abc") + rtlunittest::OUStringLiteral(u"def"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcdef"), + rtl::OUString( + rtlunittest::OUStringLiteral(u"abc") + rtl::OUString("def"))); + rtl::OUStringBuffer b(rtlunittest::OUStringLiteral(u"abc")); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b.toString()); + b.append(rtlunittest::OUStringLiteral(u"def")); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b.toString()); + b.insert(2, rtlunittest::OUStringLiteral(u"gabab")); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b.toString()); + CPPUNIT_ASSERT_EQUAL( + sal_Int32(3), b.indexOf(rtlunittest::OUStringLiteral(u"ab"), 1)); + CPPUNIT_ASSERT_EQUAL( + sal_Int32(5), b.lastIndexOf(rtlunittest::OUStringLiteral(u"ab"))); +} + +void test::oustring::StringLiterals::checkOUStringChar() +{ + auto l1 = rtlunittest::OUStringChar('A'); + CPPUNIT_ASSERT_EQUAL(u'A', l1.c); + + char const c2 = 'A'; + auto l2 = rtlunittest::OUStringChar(c2); + CPPUNIT_ASSERT_EQUAL(u'A', l2.c); + + char c3 = 'A'; auto l3 = rtlunittest::OUStringChar(c3); + CPPUNIT_ASSERT_EQUAL(u'A', l3.c); + + auto l4 = rtlunittest::OUStringChar(u'A'); + CPPUNIT_ASSERT_EQUAL(u'A', l4.c); + + sal_Unicode const c5 = 0x100; + auto l5 = rtlunittest::OUStringChar(c5); + CPPUNIT_ASSERT_EQUAL(c5, l5.c); + + rtl::OUString s1{rtlunittest::OUStringChar('A')}; + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), s1.getLength()); + CPPUNIT_ASSERT_EQUAL(u'A', s1[0]); + + CPPUNIT_ASSERT_EQUAL( + true, rtl::OUString("A") == rtlunittest::OUStringChar('A')); + CPPUNIT_ASSERT_EQUAL( + false, rtl::OUString("AB") == rtlunittest::OUStringChar('A')); + CPPUNIT_ASSERT_EQUAL( + false, rtl::OUString("A") != rtlunittest::OUStringChar('A')); + CPPUNIT_ASSERT_EQUAL( + true, rtl::OUString("AB") != rtlunittest::OUStringChar('A')); + + rtl::OUString s2("A" + rtlunittest::OUStringChar('b')); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), s2.getLength()); + CPPUNIT_ASSERT_EQUAL(u'A', s2[0]); + CPPUNIT_ASSERT_EQUAL(u'b', s2[1]); +} + +void test::oustring::StringLiterals::checkUtf16() { + rtl::OUString s1(u"abc"); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), s1); + s1 = u"de"; + CPPUNIT_ASSERT_EQUAL(rtl::OUString("de"), s1); + s1 += u"fde"; + CPPUNIT_ASSERT_EQUAL(rtl::OUString("defde"), s1); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), s1.reverseCompareTo(u"defde")); + CPPUNIT_ASSERT(s1.equalsIgnoreAsciiCase(u"DEFDE")); + CPPUNIT_ASSERT(s1.match(u"fde", 2)); + CPPUNIT_ASSERT(s1.matchIgnoreAsciiCase(u"FDE", 2)); + rtl::OUString s2; + CPPUNIT_ASSERT(s1.startsWith(u"de", &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"fde"), s2); + CPPUNIT_ASSERT(s1.startsWithIgnoreAsciiCase(u"DEFD", &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"e"), s2); + CPPUNIT_ASSERT(s1.endsWith(u"de", &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"def"), s2); + CPPUNIT_ASSERT(s1.endsWithIgnoreAsciiCase(u"EFDE", &s2)); + CPPUNIT_ASSERT_EQUAL(rtl::OUString(u"d"), s2); + CPPUNIT_ASSERT(bool(s1 == u"defde")); + CPPUNIT_ASSERT(bool(u"defde" == s1)); + CPPUNIT_ASSERT(s1 != u"abc"); + CPPUNIT_ASSERT(u"abc" != s1); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1.indexOf(u"de", 1)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), s1.lastIndexOf(u"de")); + sal_Int32 i = 0; + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfde"), + s1.replaceFirst(u"de", rtl::OUString("abc"), &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfde"), + s1.replaceFirst(rtl::OUString("de"), u"abc", &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfde"), s1.replaceFirst(u"de", u"abc", &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfde"), s1.replaceFirst(u"de", "abc", &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfde"), s1.replaceFirst("de", u"abc", &i)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), i); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", rtl::OUString("abc"))); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfabc"), s1.replaceAll(rtl::OUString("de"), u"abc")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", u"abc")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfabc"), s1.replaceAll(u"de", "abc")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString(u"abcfabc"), s1.replaceAll("de", u"abc")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcdef"), rtl::OUString(rtl::OUString("abc") + u"def")); + CPPUNIT_ASSERT_EQUAL( + rtl::OUString("abcdef"), rtl::OUString(u"abc" + rtl::OUString("def"))); + rtl::OUStringBuffer b(u"abc"); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abc"), b.toString()); + b.append(u"def"); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abcdef"), b.toString()); + b.insert(2, u"gabab"); + CPPUNIT_ASSERT_EQUAL(rtl::OUString("abgababcdef"), b.toString()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), b.indexOf(u"ab", 1)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), b.lastIndexOf(u"ab")); +} + +void test::oustring::StringLiterals::checkEmbeddedNul() { + using namespace std::literals; + rtl::OUString const s("foobar"); + constexpr char16_t const a[] = u"foo\0hidden"; + char16_t const * const p = a; + CPPUNIT_ASSERT(s.startsWith(a)); + CPPUNIT_ASSERT(s.startsWith(p)); + CPPUNIT_ASSERT(s.startsWith(u"foo\0hidden")); + CPPUNIT_ASSERT(!s.startsWith(u"foo\0hidden"s)); + CPPUNIT_ASSERT(!s.startsWith(u"foo\0hidden"sv)); +/*TODO:*/ + CPPUNIT_ASSERT(!s.startsWith(rtlunittest::OUStringLiteral(a))); + CPPUNIT_ASSERT(!s.startsWith(rtlunittest::OUStringLiteral(u"foo\0hidden"))); +/*TODO*/ +} + +} // namespace + +CPPUNIT_TEST_SUITE_REGISTRATION(test::oustring::StringLiterals); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_strings_defaultstringview.cxx b/sal/qa/rtl/strings/test_strings_defaultstringview.cxx new file mode 100644 index 000000000..591688b31 --- /dev/null +++ b/sal/qa/rtl/strings/test_strings_defaultstringview.cxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <string_view> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> + +namespace +{ +class Test : public CppUnit::TestFixture +{ + void string() { CPPUNIT_ASSERT_EQUAL(OString(), OString(std::string_view())); } + + void stringbuffer() + { + // No functions related to OStringBuffer that take a std::string_view or std::u16string_view + // argument. + } + + void ustring() + { + CPPUNIT_ASSERT_EQUAL(OUString(), OUString(std::u16string_view())); + OUString s1("foo"); + s1 = std::u16string_view(); + CPPUNIT_ASSERT_EQUAL(OUString(), s1); + OUString s2("foo"); + s2 += std::u16string_view(); + CPPUNIT_ASSERT_EQUAL(OUString("foo"), s2); + CPPUNIT_ASSERT_GREATER(sal_Int32(0), + OUString("foo").reverseCompareTo(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(false, OUString("foo").equalsIgnoreAsciiCase(std::u16string_view())); + CPPUNIT_ASSERT_GREATER(sal_Int32(0), + OUString("foo").compareToIgnoreAsciiCase(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, OUString("foo").match(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, OUString("foo").matchIgnoreAsciiCase(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, OUString("foo").startsWith(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, + OUString("foo").startsWithIgnoreAsciiCase(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, OUString("foo").endsWith(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(true, OUString("foo").endsWithIgnoreAsciiCase(std::u16string_view())); + OUString const foo("foo"); // avoid loplugin:stringconstant, loplugin:stringview + CPPUNIT_ASSERT_EQUAL(false, foo == std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(true, foo != std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(false, foo < std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(false, foo <= std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(true, foo > std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(true, foo >= std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() == foo); + CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() != foo); + CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() < foo); + CPPUNIT_ASSERT_EQUAL(true, std::u16string_view() <= foo); + CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() > foo); + CPPUNIT_ASSERT_EQUAL(false, std::u16string_view() >= foo); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").indexOf(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").lastIndexOf(std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), OUString("foo").lastIndexOf(std::u16string_view(), 3)); + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(std::u16string_view(), std::u16string_view())); + CPPUNIT_ASSERT_EQUAL( + OUString("barfoo"), + OUString("foobarfoo").replaceFirst(std::u16string_view(u"foo"), std::u16string_view())); + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(std::u16string_view(), std::u16string_view(u"baz"))); + CPPUNIT_ASSERT_EQUAL(OUString("barfoo"), + OUString("foobarfoo").replaceFirst("foo", std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(std::u16string_view(), "baz")); + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceAll(std::u16string_view(), std::u16string_view())); + CPPUNIT_ASSERT_EQUAL( + OUString("bar"), + OUString("foobarfoo").replaceAll(std::u16string_view(u"foo"), std::u16string_view())); + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceAll(std::u16string_view(), std::u16string_view(u"baz"))); + CPPUNIT_ASSERT_EQUAL(OUString("bar"), + OUString("foobarfoo").replaceAll("foo", std::u16string_view())); + CPPUNIT_ASSERT_EQUAL(OUString("foobarfoo"), + OUString("foobarfoo").replaceAll(std::u16string_view(), "baz")); + CPPUNIT_ASSERT_EQUAL(OUString(), OUString::createFromAscii(std::string_view())); + } + + void ustringbuffer() + { + OUStringBuffer b("foo"); + b.append(std::u16string_view()); + CPPUNIT_ASSERT_EQUAL(OUString("foo"), b.toString()); + } + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(string); + CPPUNIT_TEST(stringbuffer); + CPPUNIT_TEST(ustring); + CPPUNIT_TEST(ustringbuffer); + CPPUNIT_TEST_SUITE_END(); +}; +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/qa/rtl/strings/test_strings_replace.cxx b/sal/qa/rtl/strings/test_strings_replace.cxx new file mode 100644 index 000000000..3be6e176a --- /dev/null +++ b/sal/qa/rtl/strings/test_strings_replace.cxx @@ -0,0 +1,339 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.h> +#include <rtl/string.hxx> +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> + +namespace { + +OUString s_empty; +OUString s_bar("bar"); +OUString s_bars("bars"); +OUString s_foo("foo"); +OUString s_other("other"); +OUString s_xa("xa"); +OUString s_xx("xx"); + +class Test: public CppUnit::TestFixture { +private: + void stringReplaceFirst(); + + void stringReplaceAll(); + + void ustringReplaceFirst(); + + void ustringReplaceFirstAsciiL(); + + void ustringReplaceFirstToAsciiL(); + + void ustringReplaceFirstAsciiLAsciiL(); + + void ustringReplaceAll(); + + void ustringReplaceAllAsciiL(); + + void ustringReplaceAllToAsciiL(); + + void ustringReplaceAllAsciiLAsciiL(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(stringReplaceFirst); + CPPUNIT_TEST(stringReplaceAll); + CPPUNIT_TEST(ustringReplaceFirst); + CPPUNIT_TEST(ustringReplaceFirstAsciiL); + CPPUNIT_TEST(ustringReplaceFirstToAsciiL); + CPPUNIT_TEST(ustringReplaceFirstAsciiLAsciiL); + CPPUNIT_TEST(ustringReplaceAll); + CPPUNIT_TEST(ustringReplaceAllAsciiL); + CPPUNIT_TEST(ustringReplaceAllToAsciiL); + CPPUNIT_TEST(ustringReplaceAllAsciiLAsciiL); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::stringReplaceFirst() { + CPPUNIT_ASSERT_EQUAL( + OString("otherbarfoo"), + OString("foobarfoo").replaceFirst("foo", "other")); + + CPPUNIT_ASSERT_EQUAL( + OString("foobarfoo"), + OString("foobarfoo").replaceFirst("bars", "other")); + + { + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL( + OString("otherbarfoo"), + OString("foobarfoo").replaceFirst("foo", "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n); + } + + { + sal_Int32 n = 1; + CPPUNIT_ASSERT_EQUAL( + OString("foobarother"), + OString("foobarfoo").replaceFirst("foo", "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n); + } + + { + sal_Int32 n = 4; + CPPUNIT_ASSERT_EQUAL( + OString("foobarfoo"), + OString("foobarfoo").replaceFirst("bar", "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n); + } +} + +void Test::stringReplaceAll() { + CPPUNIT_ASSERT_EQUAL( + OString("otherbarother"), + OString("foobarfoo").replaceAll("foo", "other")); + + CPPUNIT_ASSERT_EQUAL( + OString("foobarfoo"), + OString("foobarfoo").replaceAll("bars", "other")); + + CPPUNIT_ASSERT_EQUAL( + OString("xxa"), OString("xaa").replaceAll("xa", "xx")); +} + +void Test::ustringReplaceFirst() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst(s_foo, s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(s_bars, s_other)); + + { + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst(s_foo, s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n); + } + + { + sal_Int32 n = 1; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarother"), + OUString("foobarfoo").replaceFirst(s_foo, s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n); + } + + { + sal_Int32 n = 4; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(s_bar, s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n); + } +} + +void Test::ustringReplaceFirstAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst("foo", s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst("bars", s_other)); + + { + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst("foo", s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n); + } + + { + sal_Int32 n = 1; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarother"), + OUString("foobarfoo").replaceFirst("foo", s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n); + } + + { + sal_Int32 n = 4; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst("bar", s_other, &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n); + } + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceFirst("xa", s_empty)); +} + +void Test::ustringReplaceFirstToAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst(s_foo, "other")); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(s_bars, "other")); + + { + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + OUString("foobarfoo").replaceFirst(s_foo, "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n); + } + + { + sal_Int32 n = 1; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarother"), + OUString("foobarfoo").replaceFirst(s_foo, "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n); + } + + { + sal_Int32 n = 4; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceFirst(s_bar, "other", &n)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n); + } + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceFirst(s_xa, "")); +} + +void Test::ustringReplaceFirstAsciiLAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + (OUString("foobarfoo"). + replaceFirst("foo", "other"))); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + (OUString("foobarfoo"). + replaceFirst("bars", "other"))); + + { + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarfoo"), + (OUString("foobarfoo"). + replaceFirst("foo", "other", &n))); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), n); + } + + { + sal_Int32 n = 1; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarother"), + (OUString("foobarfoo"). + replaceFirst("foo", "other", &n))); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), n); + } + + { + sal_Int32 n = 4; + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + (OUString("foobarfoo"). + replaceFirst("bar", "other", &n))); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), n); + } + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceFirst("xa", "")); +} + +void Test::ustringReplaceAll() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarother"), + OUString("foobarfoo").replaceAll(s_foo, s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceAll(s_bars, s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("xxa"), + OUString("xaa").replaceAll(s_xa, s_xx)); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarbaz"), OUString("foobarfoo").replaceAll(u"foo", u"baz", 1)); +} + +void Test::ustringReplaceAllAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarother"), + OUString("foobarfoo").replaceAll("foo", s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceAll("bars", s_other)); + + CPPUNIT_ASSERT_EQUAL( + OUString("xxa"), + OUString("xaa").replaceAll("xa", s_xx)); + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceAll("xa", s_empty)); +} + +void Test::ustringReplaceAllToAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarother"), + OUString("foobarfoo").replaceAll(s_foo, "other")); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + OUString("foobarfoo").replaceAll(s_bars, "other")); + + CPPUNIT_ASSERT_EQUAL( + OUString("xxa"), + OUString("xaa").replaceAll(s_xa, "xx")); + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceAll(s_xa, "")); +} + +void Test::ustringReplaceAllAsciiLAsciiL() { + CPPUNIT_ASSERT_EQUAL( + OUString("otherbarother"), + (OUString("foobarfoo"). + replaceAll("foo", "other"))); + + CPPUNIT_ASSERT_EQUAL( + OUString("foobarfoo"), + (OUString("foobarfoo"). + replaceAll("bars", "other"))); + + CPPUNIT_ASSERT_EQUAL( + OUString("xxa"), + (OUString("xaa"). + replaceAll("xa", "xx"))); + + CPPUNIT_ASSERT_EQUAL( + OUString(), OUString("xa").replaceAll("xa", "")); +} + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_strings_toint.cxx b/sal/qa/rtl/strings/test_strings_toint.cxx new file mode 100644 index 000000000..d81525b94 --- /dev/null +++ b/sal/qa/rtl/strings/test_strings_toint.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +namespace { + +template< typename T > class Test: public CppUnit::TestFixture { +private: + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testToInt32Overflow); + CPPUNIT_TEST(testToUInt32Overflow); + CPPUNIT_TEST(testToInt64Overflow); + CPPUNIT_TEST(testToUInt64Overflow); + CPPUNIT_TEST_SUITE_END(); + + void testToInt32Overflow() { + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("-2147483649").toInt32()); + CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32, T("-2147483648").toInt32()); + CPPUNIT_ASSERT_EQUAL(SAL_MIN_INT32 + 1, T("-2147483647").toInt32()); + CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32 - 1, T("2147483646").toInt32()); + CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT32, T("2147483647").toInt32()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), T("2147483648").toInt32()); + } + + void testToUInt32Overflow() { + CPPUNIT_ASSERT_EQUAL(SAL_MAX_UINT32 - 1, T("4294967294").toUInt32()); + CPPUNIT_ASSERT_EQUAL(SAL_MAX_UINT32, T("4294967295").toUInt32()); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), T("4294967296").toUInt32()); + } + + void testToInt64Overflow() { + CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("-9223372036854775809").toInt64()); + CPPUNIT_ASSERT_EQUAL( + SAL_MIN_INT64, T("-9223372036854775808").toInt64()); + CPPUNIT_ASSERT_EQUAL( + SAL_MIN_INT64 + 1, T("-9223372036854775807").toInt64()); + CPPUNIT_ASSERT_EQUAL( + SAL_MAX_INT64 - 1, T("9223372036854775806").toInt64()); + CPPUNIT_ASSERT_EQUAL(SAL_MAX_INT64, T("9223372036854775807").toInt64()); + CPPUNIT_ASSERT_EQUAL(sal_Int64(0), T("9223372036854775808").toInt64()); + } + + void testToUInt64Overflow() { + CPPUNIT_ASSERT_EQUAL( + SAL_MAX_UINT64 - 1, T("18446744073709551614").toUInt64()); + CPPUNIT_ASSERT_EQUAL( + SAL_MAX_UINT64, T("18446744073709551615").toUInt64()); + CPPUNIT_ASSERT_EQUAL( + sal_uInt64(0), T("18446744073709551616").toUInt64()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(Test< OString >); +CPPUNIT_TEST_SUITE_REGISTRATION(Test< OUString >); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/qa/rtl/strings/test_strings_valuex.cxx b/sal/qa/rtl/strings/test_strings_valuex.cxx new file mode 100644 index 000000000..6c9c83644 --- /dev/null +++ b/sal/qa/rtl/strings/test_strings_valuex.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <rtl/ustring.hxx> +#include <iostream> + +namespace test::strings { + +class valueX : public CppUnit::TestFixture { +public: + void testOBoolean(); + void testOUBoolean(); + void testOUInt(); + void testOInt(); + void testOUFloat(); + void testOFloat(); + + CPPUNIT_TEST_SUITE(valueX); + CPPUNIT_TEST(testOBoolean); + CPPUNIT_TEST(testOUBoolean); + CPPUNIT_TEST(testOUInt); + CPPUNIT_TEST(testOInt); + CPPUNIT_TEST(testOUFloat); + CPPUNIT_TEST(testOFloat); + CPPUNIT_TEST_SUITE_END(); +}; + +} + +CPPUNIT_TEST_SUITE_REGISTRATION(test::strings::valueX); + +namespace { + +template< typename T > +void testBoolean() { + CPPUNIT_ASSERT_EQUAL( T( "false" ), T::boolean( false ) ); + CPPUNIT_ASSERT_EQUAL( T( "true" ), T::boolean( true ) ); +} + +} + +void test::strings::valueX::testOBoolean() { + testBoolean<OString>(); +} + +void test::strings::valueX::testOUBoolean() { + testBoolean<OUString>(); +} + +template< typename T > +static void testInt() { + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( 30039062 ))); + + // test the overloading resolution + + CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< signed char >( 30 )))); + CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< unsigned char >( 30 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< short >( 30039 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< unsigned short >( 30039 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< int >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned int >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< long long >( 30039062 )))); + // The highest bit set in unsigned long long may not actually work. + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< unsigned long long >( 30039062 )))); + + CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_Int8 >( 30 )))); + CPPUNIT_ASSERT_EQUAL( T( "30" ), T( T::number( static_cast< sal_uInt8 >( 30 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_Int16 >( 30039 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039" ), T( T::number( static_cast< sal_uInt16 >( 30039 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int32 >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt32 >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_Int64 >( 30039062 )))); + CPPUNIT_ASSERT_EQUAL( T( "30039062" ), T( T::number( static_cast< sal_uInt64 >( 30039062 )))); + + // The implementation internally uses sal_Int64 etc. types, so check ranges. + assert( sizeof( int ) <= sizeof( sal_Int32 )); + assert( sizeof( long ) <= sizeof( sal_Int64 )); + assert( sizeof( long long ) <= sizeof( sal_Int64 )); + assert( sizeof( unsigned int ) < sizeof( sal_Int64 )); +} + +void test::strings::valueX::testOUInt() { + testInt<OUString>(); +} + +void test::strings::valueX::testOInt() { + testInt<OString>(); +} + +template< typename T > +static void testFloat() { + CPPUNIT_ASSERT_EQUAL( T( "39062.2" ), T( T::number( 39062.2f ))); + CPPUNIT_ASSERT_EQUAL( T( "30039062.2" ), T( T::number( 30039062.2 ))); + // long double not supported +} + +void test::strings::valueX::testOUFloat() { + testFloat<OUString>(); +} + +void test::strings::valueX::testOFloat() { + testFloat<OString>(); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |