diff options
Diffstat (limited to 'tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp')
-rw-r--r-- | tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp | 331 |
1 files changed, 280 insertions, 51 deletions
diff --git a/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp index 66dfe3ce58..59362d010a 100644 --- a/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Do not include anything in this file. We are being #included with -// a bunch of defines that may break other legitimate code. +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// Do not include anything in this file. We are being #included in the unnamed namespace +// with a bunch of defines that may break other legitimate code. #define LITERAL "some literal" #define LITERAL_LEN (sizeof(LITERAL)-1) @@ -69,10 +44,207 @@ template <> QString toQString(const char16_t &c) { return QChar(c); } template <typename T> QByteArray toQByteArray(const T &t); template <> QByteArray toQByteArray(const QByteArray &b) { return b; } +template <> QByteArray toQByteArray(const QByteArrayView &bav) { return bav.toByteArray(); } template <> QByteArray toQByteArray(char * const &p) { return p; } template <size_t N> QByteArray toQByteArray(const char (&a)[N]) { return a; } template <> QByteArray toQByteArray(const char &c) { return QByteArray(&c, 1); } +template <typename String, typename Separator> +void checkItWorksWithFreeSpaceAtBegin(const String &chunk, const Separator &separator) +{ + // GIVEN: a String with freeSpaceAtBegin() and less than chunk.size() freeSpaceAtEnd() + String str; + + int prepends = 0; + const int max_prepends = 10; + while (str.data_ptr().freeSpaceAtBegin() < chunk.size() && prepends++ < max_prepends) + str.prepend(chunk); + QVERIFY(prepends < max_prepends); + + int appends = 0; + const int max_appends = 100; + while (str.data_ptr().freeSpaceAtEnd() >= chunk.size() && appends++ < max_appends) + str.append(chunk); + QVERIFY(appends < max_appends); + + QVERIFY(str.capacity() - str.size() >= chunk.size()); + QVERIFY(str.data_ptr().freeSpaceAtEnd() < chunk.size()); + + // WHEN: adding a QStringBuilder expression which exceeds freeSpaceAtEnd() + str += separator P chunk; + + // THEN: it doesn't crash (QTBUG-99330) + const String expected = chunk.repeated(prepends + appends) + separator + chunk; + QCOMPARE(str, expected); +} + +template <typename String> +void checkNullVsEmpty(const String &empty) +{ + String a; + String b; + QVERIFY(a.isNull()); + QVERIFY(b.isNull()); + String result = a P b; + QVERIFY(result.isNull()); + + String d = empty; + QVERIFY(d.isEmpty()); + QVERIFY(!d.isNull()); + result = a P d; + QVERIFY(result.isEmpty()); + QVERIFY(!result.isNull()); + + result = a P a P a; + QVERIFY(result.isNull()); +} + +namespace CheckAuto { +// T is cvref-qualified, using universal reference deduction rules. +template <typename T> struct Helper; + +// These specializations forward to the non-const ones, and add const on top. +template <typename T> struct Helper<const T> +{ + static const T create() { return Helper<T>::create(); } + static const T createNull() { return Helper<T>::createNull(); } +}; +template <typename T> struct Helper<const T &> +{ + static const T &create() { return Helper<T &>::create(); } + static const T &createNull() { return Helper<T &>::createNull(); } +}; + +template <> struct Helper<QString> +{ + static QString create() { return QString::fromUtf8("QString rvalue"); } + static QString createNull() { return QString(); } +}; + +template <> struct Helper<QString &> +{ + static QString &create() { static QString s = QString::fromUtf8("QString lvalue"); return s; } + static QString &createNull() { static QString s; return s; } +}; + +template <> struct Helper<QStringView> +{ + static QStringView create() { return QStringView(u"QStringView rvalue"); } + static QStringView createNull() { return QStringView(); } +}; + +template <> struct Helper<QStringView &> +{ + static QStringView &create() { static QStringView s = u"QStringView lvalue"; return s; } + static QStringView &createNull() { static QStringView s; return s; } +}; + +template <> struct Helper<QByteArray> +{ + static QByteArray create() { return QByteArray("QByteArray rvalue"); } + static QByteArray createNull() { return QByteArray(); } +}; + +template <> struct Helper<QByteArray &> +{ + static QByteArray &create() { static QByteArray ba = QByteArray("QByteArray lvalue"); return ba; } + static QByteArray &createNull() { static QByteArray ba; return ba; } +}; + +template <> struct Helper<QByteArrayView> +{ + static QByteArrayView create() { return QByteArrayView("QByteArrayView rvalue"); } + static QByteArrayView createNull() { return QByteArrayView(); } +}; + +template <> struct Helper<QByteArrayView &> +{ + static QByteArrayView &create() { static QByteArrayView ba = "QByteArrayView lvalue"; return ba; } + static QByteArrayView &createNull() { static QByteArrayView ba; return ba; } +}; + +template <> struct Helper<const char *> +{ + static const char *create() { return "const char * rvalue"; } + static const char *createNull() { return ""; } +}; + +template <> struct Helper<const char *&> +{ + static const char *&create() { static const char *s = "const char * lvalue"; return s; } + static const char *&createNull() { static const char *s = ""; return s; } +}; + +template <typename String1, typename String2, typename Result> +void checkAutoImpl3() +{ + { + auto result = Helper<String1>::create() P Helper<String2>::create(); + Result expected = result; + QCOMPARE(result, expected); + } + { + auto result = Helper<String2>::create() P Helper<String1>::create(); + Result expected = result; + QCOMPARE(result, expected); + } + { + auto result = Helper<String1>::create() P Helper<String2>::create() P Helper<String1>::create(); + Result expected = result; + QCOMPARE(result, expected); + } + { + auto result = Helper<String2>::create() P Helper<String1>::create() P Helper<String2>::create(); + Result expected = result; + QCOMPARE(result, expected); + } + { + auto result = Helper<String1>::createNull() P Helper<String2>::create(); + Result expected = result; + QCOMPARE(result, expected); + } + { + auto result = Helper<String1>::createNull() P Helper<String2>::createNull(); + Result expected = result; + QCOMPARE(result, expected); + } +} + +template <typename String1, typename String2, typename Result> +void checkAutoImpl2() +{ + checkAutoImpl3<String1 , String2 , Result>(); + checkAutoImpl3<String1 &, String2 , Result>(); + checkAutoImpl3<String1 , String2 &, Result>(); + checkAutoImpl3<String1 &, String2 &, Result>(); +} + +template <typename String1, typename String2, typename Result> +void checkAutoImpl() +{ + checkAutoImpl2< String1, String2, Result>(); + checkAutoImpl2<const String1, String2, Result>(); + checkAutoImpl2< String1, const String2, Result>(); + checkAutoImpl2<const String1, const String2, Result>(); +} + +} // namespace CheckAuto + +void checkAuto() +{ + CheckAuto::checkAutoImpl<QString, QString, QString>(); + CheckAuto::checkAutoImpl<QString, QStringView, QString>(); + + CheckAuto::checkAutoImpl<QByteArray, QByteArray, QByteArray>(); + CheckAuto::checkAutoImpl<QByteArray, const char *, QByteArray>(); + CheckAuto::checkAutoImpl<QByteArray, QByteArrayView, QByteArray>(); + +#ifndef QT_NO_CAST_FROM_ASCII + CheckAuto::checkAutoImpl<QString, const char *, QString>(); + CheckAuto::checkAutoImpl<QString, QByteArray, QString>(); +#endif +} + void runScenario() { // this code is latin1. TODO: replace it with the utf8 block below, once @@ -90,17 +262,16 @@ void runScenario() #define CHECK(QorP, a1, a2) \ do { \ - DO(QorP, a1, a2); \ - DO(QorP, a2, a1); \ + QCOMPARE(QString(a1 QorP a2), toQString(a1).append(toQString(a2))); \ + QCOMPARE(QString(a2 QorP a1), toQString(a2).append(toQString(a1))); \ } while (0) -#define DO(QorP, a1, a2) \ - QCOMPARE(QString(a1 QorP a2), \ - toQString(a1).append(toQString(a2))) \ - /* end */ - CHECK(P, l1string, l1string); CHECK(P, l1string, string); + CHECK(P, l1string, QString(string)); + CHECK(Q, l1string, string); + CHECK(Q, l1string, QString(string)); + CHECK(Q, l1string, stringview); CHECK(P, l1string, lchar); CHECK(P, l1string, qchar); @@ -111,20 +282,48 @@ void runScenario() CHECK(Q, l1string, u16charstar); CHECK(P, string, string); + CHECK(P, string, QString(string)); + CHECK(P, QString(string), QString(string)); + CHECK(Q, string, string); + CHECK(Q, string, QString(string)); + CHECK(Q, QString(string), QString(string)); + + CHECK(P, string, stringview); + CHECK(P, QString(string), stringview); CHECK(Q, string, stringview); + CHECK(Q, QString(string), stringview); + CHECK(P, string, lchar); + CHECK(P, QString(string), lchar); + CHECK(Q, string, lchar); + CHECK(Q, QString(string), lchar); + CHECK(P, string, qchar); + CHECK(P, QString(string), qchar); CHECK(P, string, special); + CHECK(P, QString(string), special); CHECK(P, string, QStringLiteral(LITERAL)); + CHECK(P, QString(string), QStringLiteral(LITERAL)); + CHECK(Q, string, qchar); + CHECK(Q, QString(string), qchar); + CHECK(Q, string, special); + CHECK(Q, QString(string), special); + CHECK(Q, string, QStringLiteral(LITERAL)); + CHECK(Q, QString(string), QStringLiteral(LITERAL)); + CHECK(Q, string, u16char); + CHECK(Q, QString(string), u16char); CHECK(Q, string, u16chararray); + CHECK(Q, QString(string), u16chararray); CHECK(Q, string, u16charstar); + CHECK(Q, QString(string), u16charstar); CHECK(Q, stringview, stringview); CHECK(Q, stringview, lchar); CHECK(Q, stringview, qchar); CHECK(Q, stringview, special); CHECK(P, stringview, QStringLiteral(LITERAL)); + CHECK(Q, stringview, QStringLiteral(LITERAL)); CHECK(Q, stringview, u16char); CHECK(Q, stringview, u16chararray); CHECK(Q, stringview, u16charstar); @@ -164,21 +363,34 @@ void runScenario() // CHECK(Q, u16charstar, u16charstar); // BUILTIN <-> BUILTIN cat't be overloaded -#undef DO +#undef CHECK -#define DO(QorP, a1, a2) \ - QCOMPARE(QByteArray(a1 QorP a2), \ - toQByteArray(a1).append(toQByteArray(a2))) \ - /* end */ +#define CHECK(QorP, a1, a2) \ + do { \ + QCOMPARE(QByteArray(a1 QorP a2), toQByteArray(a1).append(toQByteArray(a2))); \ + QCOMPARE(QByteArray(a2 QorP a1), toQByteArray(a2).append(toQByteArray(a1))); \ + } while (0) QByteArray bytearray = stringview.toUtf8(); + QByteArrayView baview = QByteArrayView(bytearray).mid(0, bytearray.size() - 2); char *charstar = bytearray.data(); char chararray[3] = { 'H', 'i', '\0' }; const char constchararray[3] = { 'H', 'i', '\0' }; char achar = 'a'; CHECK(P, bytearray, bytearray); + CHECK(P, QByteArray(bytearray), bytearray); + CHECK(P, QByteArray(bytearray), QByteArray(bytearray)); + CHECK(P, bytearray, baview); + CHECK(P, QByteArray(bytearray), baview); CHECK(P, bytearray, charstar); + CHECK(Q, bytearray, bytearray); + CHECK(Q, QByteArray(bytearray), bytearray); + CHECK(Q, QByteArray(bytearray), QByteArray(bytearray)); + CHECK(Q, bytearray, baview); + CHECK(Q, QByteArray(bytearray), baview); + CHECK(Q, bytearray, charstar); + #ifndef Q_CC_MSVC // see QTBUG-65359 CHECK(P, bytearray, chararray); #else @@ -186,6 +398,8 @@ void runScenario() #endif CHECK(P, bytearray, constchararray); CHECK(P, bytearray, achar); + CHECK(Q, bytearray, constchararray); + CHECK(Q, bytearray, achar); //CHECK(Q, charstar, charstar); // BUILTIN <-> BUILTIN cat't be overloaded //CHECK(Q, charstar, chararray); @@ -196,7 +410,6 @@ void runScenario() //CHECK(Q, achar, achar); // BUILTIN <-> BUILTIN cat't be overloaded -#undef DO #undef CHECK QString r2(QLatin1String(LITERAL LITERAL)); @@ -305,6 +518,10 @@ void runScenario() QCOMPARE(r, ba); r = zero P ba; QCOMPARE(r, ba); + + QByteArrayView qbav = LITERAL; + superba = qbav P qbav P LITERAL; + QCOMPARE(superba, QByteArray(LITERAL LITERAL LITERAL)); } //operator QString += @@ -325,6 +542,16 @@ void runScenario() QCOMPARE(str2, str2_e); } + checkItWorksWithFreeSpaceAtBegin(QString::fromUtf8(UTF8_LITERAL), + #ifdef QT_NO_CAST_FROM_ASCII + QLatin1String("1234") + #else + "1234" + #endif + ); + if (QTest::currentTestFailed()) + return; + //operator QByteArray += { QByteArray ba = UTF8_LITERAL; @@ -336,14 +563,16 @@ void runScenario() QByteArray ba2 = withZero; ba2 += ba2 P withZero; QCOMPARE(ba2, QByteArray(withZero + withZero + withZero)); - - // With space allocated in front, mirroring what happens with QHttpMultiPart in QNAM - QByteArray byteArray; - byteArray.reserve(70); - byteArray.insert(0, "multipart/"); - byteArray.insert(byteArray.size(), "mixed"); - byteArray += "; boundary=\"" P QByteArray(30, 'o') P '"'; - QCOMPARE(byteArray, "multipart/mixed; boundary=\"oooooooooooooooooooooooooooooo\""); } + // null vs. empty + checkNullVsEmpty(QStringLiteral("")); + checkNullVsEmpty(QByteArrayLiteral("")); + + // auto + checkAuto(); + + checkItWorksWithFreeSpaceAtBegin(QByteArray(UTF8_LITERAL), "1234"); + if (QTest::currentTestFailed()) + return; } |