diff options
Diffstat (limited to 'sal/qa/rtl/strings/test_ostring_stringliterals.cxx')
-rw-r--r-- | sal/qa/rtl/strings/test_ostring_stringliterals.cxx | 282 |
1 files changed, 282 insertions, 0 deletions
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: */ |