291 lines
13 KiB
C++
291 lines
13 KiB
C++
/* -*- 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 checkOstr();
|
|
|
|
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(checkOstr);
|
|
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()
|
|
{
|
|
static constinit 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 );
|
|
}
|
|
|
|
void test::ostring::StringLiterals::checkOstr() {
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ""_ostr.getLength());
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(6), "foobar"_ostr.getLength());
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(7), "foo\0bar"_ostr.getLength());
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), u8"\U00010000"_ostr.getLength());
|
|
CPPUNIT_ASSERT_EQUAL(""_ostr, rtl::OString(""_tstr));
|
|
CPPUNIT_ASSERT_EQUAL("foobar"_ostr, rtl::OString("foobar"_tstr));
|
|
CPPUNIT_ASSERT_EQUAL("foo\0bar"_ostr, rtl::OString("foo\0bar"_tstr));
|
|
}
|
|
|
|
#undef CONST_CTOR_USED
|
|
|
|
} // namespace
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(test::ostring::StringLiterals);
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|