summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp')
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp331
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;
}