summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp41
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp17
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp141
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro8
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp727
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp24
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp2
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp50
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp34
-rw-r--r--tests/auto/corelib/tools/qchar/tst_qchar.cpp29
-rw-r--r--tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp17
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp4
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp46
-rw-r--r--tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp211
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp9
-rw-r--r--tests/auto/corelib/tools/qstringview/.gitignore1
-rw-r--r--tests/auto/corelib/tools/qstringview/qstringview.pro6
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp446
-rw-r--r--tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp8
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp2
-rw-r--r--tests/auto/corelib/tools/tools.pro1
23 files changed, 1747 insertions, 79 deletions
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 7147405f3b..b43ea7cfa5 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -51,6 +51,7 @@ private slots:
void qDebugQChar() const;
void qDebugQString() const;
void qDebugQStringRef() const;
+ void qDebugQStringView() const;
void qDebugQLatin1String() const;
void qDebugQByteArray() const;
void qDebugQFlags() const;
@@ -492,6 +493,46 @@ void tst_QDebug::qDebugQStringRef() const
}
}
+void tst_QDebug::qDebugQStringView() const
+{
+ /* Use a basic string. */
+ {
+ QLatin1String file, function;
+ int line = 0;
+ const QStringView inView = QStringViewLiteral("input");
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << inView; }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = QLatin1String(__FILE__); line = __LINE__ - 2; function = QLatin1String(Q_FUNC_INFO);
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QLatin1String("\"input\""));
+ QCOMPARE(QLatin1String(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QLatin1String(s_function), function);
+ }
+
+ /* Use a null QStringView. */
+ {
+ QString file, function;
+ int line = 0;
+
+ const QStringView inView;
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << inView; }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QLatin1String("\"\""));
+ QCOMPARE(QLatin1String(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QLatin1String(s_function), function);
+ }
+}
+
void tst_QDebug::qDebugQLatin1String() const
{
QString file, function;
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index ebc240c285..1cbb7ad19c 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -1384,18 +1384,6 @@ void tst_QUrl::compat_constructor_01_data()
void tst_QUrl::compat_constructor_01()
{
- /* The following should work as expected:
- *
- * QUrlOperator op;
- * op.copy( QString( "Makefile" ),
- * QString("ftp://rms:grmpf12@nibbler/home/rms/tmp"),
- * false );
- *
- * as well as the following:
- *
- * QUrlOperator op;
- * op.copy(QString("ftp://ftp.qt-project.org/qt/INSTALL"), ".");
- */
QFETCH( QString, urlStr );
{
@@ -1425,11 +1413,6 @@ void tst_QUrl::compat_constructor_02_data()
void tst_QUrl::compat_constructor_02()
{
- /* The following should work as expected:
- *
- * QUrlOperator op( "ftp://ftp.qt-project.org/qt" );
- * op.copy(QString("INSTALL"), ".");
- */
QFETCH( QString, urlStr );
QFETCH( QString, fileName );
diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro
index c1d75cc2cb..a09f03a7b4 100644
--- a/tests/auto/corelib/itemmodels/itemmodels.pro
+++ b/tests/auto/corelib/itemmodels/itemmodels.pro
@@ -7,6 +7,7 @@ qtHaveModule(gui): SUBDIRS += \
qabstractproxymodel \
qidentityproxymodel \
qitemselectionmodel \
+ qsortfilterproxymodel_recursive \
qtHaveModule(widgets) {
SUBDIRS += \
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index bc8f0c1c51..54582ee4c3 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -148,6 +148,9 @@ private slots:
void sourceLayoutChangeLeavesValidPersistentIndexes();
void rowMoveLeavesValidPersistentIndexes();
+ void emitLayoutChangedOnlyIfSortingChanged_data();
+ void emitLayoutChangedOnlyIfSortingChanged();
+
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
@@ -2057,8 +2060,6 @@ static void checkSortedTableModel(const QAbstractItemModel *model, const QString
void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548()
{
- QSKIP("This test will fail, see QTBUG-1548");
-
// Check that emitting dataChanged from the source model
// for a change of a role which is not the sorting role
// doesn't alter the sorting. In this case, we sort on the DisplayRole,
@@ -3568,6 +3569,13 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
parentItem = item;
}
}
+ // item 0
+ // item 10
+ // - item 1
+ // - item 11
+ // - item 2
+ // - item 12
+ // ...
QSortFilterProxyModel proxy;
proxy.sort(0, Qt::AscendingOrder);
@@ -3609,11 +3617,12 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
QVERIFY(proxy2ParentsChangedSpy.isValid());
QStandardItem *item = model.invisibleRootItem()->child(1)->child(1);
+ QCOMPARE(item->text(), QStringLiteral("item 11"));
// Ensure mapped:
proxy.mapFromSource(model.indexFromItem(item));
- item->setData("Changed");
+ item->setText("Changed");
QCOMPARE(dataChangedSpy.size(), 1);
QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
@@ -4026,7 +4035,7 @@ public:
}
- QModelIndex mapToSource(const QModelIndex &proxyIndex) const
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
{
Q_ASSERT(sourceModel());
return QSortFilterProxyModel::mapToSource(proxyIndex);
@@ -4353,5 +4362,129 @@ void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
QVERIFY(persistentIndex.parent().isValid());
}
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data()
+{
+ QTest::addColumn<int>("changedRow");
+ QTest::addColumn<Qt::ItemDataRole>("changedRole");
+ QTest::addColumn<QString>("newData");
+ QTest::addColumn<QString>("expectedSourceRowTexts");
+ QTest::addColumn<QString>("expectedProxyRowTexts");
+ QTest::addColumn<int>("expectedLayoutChanged");
+
+ // Starting point:
+ // a source model with 8,7,6,5,4,3,2,1
+ // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8
+
+ // When setData changes ordering, layoutChanged should be emitted
+ QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1;
+
+ // When setData on visible row doesn't change ordering, layoutChanged should not be emitted
+ QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0;
+
+ // When setData happens on a filtered out row, layoutChanged should not be emitted
+ QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0;
+
+ // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead)
+ QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0;
+
+ // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead)
+ QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0;
+
+ // When setData happens on an unrelated role, layoutChanged should not be emitted
+ QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0;
+
+ // When many changes happen together... and trigger removal, insertion, and layoutChanged
+ QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1;
+
+ // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged
+ QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0;
+}
+
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
+{
+ QFETCH(int, changedRow);
+ QFETCH(QString, newData);
+ QFETCH(Qt::ItemDataRole, changedRole);
+ QFETCH(QString, expectedSourceRowTexts);
+ QFETCH(QString, expectedProxyRowTexts);
+ QFETCH(int, expectedLayoutChanged);
+
+ // Custom version of QStringListModel which supports emitting dataChanged for many rows at once
+ class CustomStringListModel : public QAbstractListModel
+ {
+ public:
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override
+ {
+ if (index.row() >= 0 && index.row() < lst.size()
+ && (role == Qt::EditRole || role == Qt::DisplayRole)) {
+ lst.replace(index.row(), value.toString());
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
+ return true;
+ }
+ return false;
+ }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return lst.at(index.row());
+ return QVariant();
+ }
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return lst.count();
+ }
+
+ void replaceData(const QStringList &newData)
+ {
+ lst = newData;
+ emit dataChanged(index(0, 0), index(rowCount()-1, 0), {Qt::DisplayRole, Qt::EditRole});
+ }
+
+ void emitDecorationChangedSignal()
+ {
+ const QModelIndex idx = index(0, 0);
+ emit dataChanged(idx, idx, {Qt::DecorationRole});
+ }
+ private:
+ QStringList lst;
+ };
+ CustomStringListModel model;
+ QStringList strings;
+ for (auto i = 8; i >= 1; --i)
+ strings.append(QString::number(i));
+ model.replaceData(strings);
+ QCOMPARE(rowTexts(&model), QStringLiteral("87654321"));
+
+ class FilterEvenRowsProxyModel : public QSortFilterProxyModel
+ {
+ public:
+ bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
+ {
+ return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0;
+ }
+ };
+
+ FilterEvenRowsProxyModel proxy;
+ proxy.sort(0);
+ proxy.setSourceModel(&model);
+ QCOMPARE(rowTexts(&proxy), QStringLiteral("2468"));
+
+ QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged);
+ QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+
+ if (changedRole == Qt::DecorationRole)
+ model.emitDecorationChangedSignal();
+ else if (changedRow == -1)
+ model.replaceData(newData.split(QLatin1Char(',')));
+ else
+ model.setData(model.index(changedRow, 0), newData, changedRole);
+
+ QCOMPARE(rowTexts(&model), expectedSourceRowTexts);
+ QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts);
+ QCOMPARE(modelDataChangedSpy.size(), 1);
+ QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged);
+}
+
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore
new file mode 100644
index 0000000000..2007aaabbd
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_recursive
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro
new file mode 100644
index 0000000000..a8b793dbc6
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+CONFIG += parallel_test
+TARGET = tst_qsortfilterproxymodel_recursive
+
+QT += testlib
+
+SOURCES += tst_qsortfilterproxymodel_recursive.cpp
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
new file mode 100644
index 0000000000..54c79e0893
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
@@ -0,0 +1,727 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, authors Filipe Azevedo <filipe.azevedo@kdab.com> and David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTest>
+#include <QSignalSpy>
+
+#include <QtCore/QSortFilterProxyModel>
+#include <QtGui/QStandardItem>
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class ModelSignalSpy : public QObject {
+ Q_OBJECT
+public:
+ explicit ModelSignalSpy(QAbstractItemModel &model) {
+ connect(&model, &QAbstractItemModel::rowsInserted, this, &ModelSignalSpy::onRowsInserted);
+ connect(&model, &QAbstractItemModel::rowsRemoved, this, &ModelSignalSpy::onRowsRemoved);
+ connect(&model, &QAbstractItemModel::rowsAboutToBeInserted, this, &ModelSignalSpy::onRowsAboutToBeInserted);
+ connect(&model, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ModelSignalSpy::onRowsAboutToBeRemoved);
+ connect(&model, &QAbstractItemModel::rowsMoved, this, &ModelSignalSpy::onRowsMoved);
+ connect(&model, &QAbstractItemModel::dataChanged, this, &ModelSignalSpy::onDataChanged);
+ connect(&model, &QAbstractItemModel::layoutChanged, this, &ModelSignalSpy::onLayoutChanged);
+ connect(&model, &QAbstractItemModel::modelReset, this, &ModelSignalSpy::onModelReset);
+ }
+
+ QStringList mSignals;
+
+private Q_SLOTS:
+ void onRowsInserted(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsInserted(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsRemoved(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsRemoved(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsAboutToBeInserted(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsAboutToBeInserted(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsAboutToBeRemoved(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsAboutToBeRemoved(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsMoved(QModelIndex,int,int,QModelIndex,int) {
+ mSignals << QStringLiteral("rowsMoved");
+ }
+ void onDataChanged(const QModelIndex &from, const QModelIndex& ) {
+ mSignals << QStringLiteral("dataChanged(%1)").arg(from.data().toString());
+ }
+ void onLayoutChanged() {
+ mSignals << QStringLiteral("layoutChanged");
+ }
+ void onModelReset() {
+ mSignals << QStringLiteral("modelReset");
+ }
+private:
+ QString textForRowSpy(const QModelIndex &parent, int start, int end)
+ {
+ QString txt = parent.data().toString();
+ if (!txt.isEmpty())
+ txt += QLatin1Char('.');
+ txt += QString::number(start+1);
+ if (start != end)
+ txt += QLatin1Char('-') + QString::number(end+1);
+ return txt;
+ }
+};
+
+class TestModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ TestModel(QAbstractItemModel *sourceModel)
+ : QSortFilterProxyModel()
+ {
+ setRecursiveFiltering(true);
+ setSourceModel(sourceModel);
+ }
+
+ virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
+ {
+ return sourceModel()->index(sourceRow, 0, sourceParent).data(Qt::UserRole +1).toBool()
+ && QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
+ }
+};
+
+// Represents this tree
+// - A
+// - - B
+// - - - C
+// - - - D
+// - - E
+// as a single string, englobing children in brackets, like this:
+// [A[B[C D] E]]
+// In addition, items that match the filtering (data(UserRole+1) == true) have a * after their value.
+static QString treeAsString(const QAbstractItemModel &model, const QModelIndex &parent = QModelIndex())
+{
+ QString ret;
+ const int rowCount = model.rowCount(parent);
+ if (rowCount > 0) {
+ ret += QLatin1Char('[');
+ for (int row = 0 ; row < rowCount; ++row) {
+ if (row > 0) {
+ ret += ' ';
+ }
+ const QModelIndex child = model.index(row, 0, parent);
+ ret += child.data().toString();
+ if (child.data(Qt::UserRole+1).toBool())
+ ret += QLatin1Char('*');
+ ret += treeAsString(model, child);
+ }
+ ret += QLatin1Char(']');
+ }
+ return ret;
+}
+
+// Fill a tree model based on a string representation (see treeAsString)
+static void fillModel(QStandardItemModel &model, const QString &str)
+{
+ QCOMPARE(str.count('['), str.count(']'));
+ QStandardItem *item = 0;
+ QString data;
+ for ( int i = 0 ; i < str.length() ; ++i ) {
+ const QChar ch = str.at(i);
+ if ((ch == '[' || ch == ']' || ch == ' ') && !data.isEmpty()) {
+ if (data.endsWith('*')) {
+ item->setData(true, Qt::UserRole + 1);
+ data.chop(1);
+ }
+ item->setText(data);
+ data.clear();
+ }
+ if (ch == '[') {
+ // Create new child
+ QStandardItem *child = new QStandardItem;
+ if (item)
+ item->appendRow(child);
+ else
+ model.appendRow(child);
+ item = child;
+ } else if (ch == ']') {
+ // Go up to parent
+ item = item->parent();
+ } else if (ch == ' ') {
+ // Create new sibling
+ QStandardItem *child = new QStandardItem;
+ QStandardItem *parent = item->parent();
+ if (parent)
+ parent->appendRow(child);
+ else
+ model.appendRow(child);
+ item = child;
+ } else {
+ data += ch;
+ }
+ }
+}
+
+class tst_QSortFilterProxyModel_Recursive : public QObject
+{
+ Q_OBJECT
+private:
+private Q_SLOTS:
+ void testInitialFiltering_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("proxyStr");
+
+ QTest::newRow("empty") << "[]" << "";
+ QTest::newRow("no") << "[1]" << "";
+ QTest::newRow("yes") << "[1*]" << "[1*]";
+ QTest::newRow("second") << "[1 2*]" << "[2*]";
+ QTest::newRow("child_yes") << "[1 2[2.1*]]" << "[2[2.1*]]";
+ QTest::newRow("grandchild_yes") << "[1 2[2.1[2.1.1*]]]" << "[2[2.1[2.1.1*]]]";
+ // 1, 3.1 and 4.2.1 match, so their parents are in the model
+ QTest::newRow("more") << "[1* 2[2.1] 3[3.1*] 4[4.1 4.2[4.2.1*]]]" << "[1* 3[3.1*] 4[4.2[4.2.1*]]]";
+ }
+
+ void testInitialFiltering()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, proxyStr);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), proxyStr);
+ }
+
+ // Test changing a role that is unrelated to the filtering.
+ void testUnrelatedDataChange()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1*]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+
+ // When changing the text on the item
+ item_1_1_1->setText(QStringLiteral("ME"));
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[ME*]]]"));
+
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("dataChanged(ME)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+ }
+
+ // Test changing a role that is unrelated to the filtering, in a hidden item.
+ void testHiddenDataChange()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+
+ // When changing the text on a hidden item
+ item_1_1_1->setText(QStringLiteral("ME"));
+
+ QCOMPARE(treeAsString(proxy), QString());
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ // Test that we properly react to a data-changed signal in a descendant and include all required rows
+ void testDataChangeIn_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("add"); // set the flag on this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ QTest::newRow("toplevel") << "[1]" << "" << "1" << "[1*]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeInserted(1)") << QStringLiteral("rowsInserted(1)"));
+ QTest::newRow("show_parents") << "[1[1.1[1.1.1]]]" << "" << "1.1.1" << "[1[1.1[1.1.1*]]]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeInserted(1)") << QStringLiteral("rowsInserted(1)"));
+
+ const QStringList insert_1_1_1 = QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.1)")
+ << QStringLiteral("rowsInserted(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)")
+ ;
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1]]]" << "[1[1.1*]]" << "1.1.1" << "[1[1.1*[1.1.1*]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("sibling_visible") << "[1[1.1[1.1.1 1.1.2*]]]" << "[1[1.1[1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.1* 1.1.2*]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("show_parent") << "[1[1.1[1.1.1 1.1.2] 1.2*]]" << "[1[1.2*]]" << "1.1.1" << "[1[1.1[1.1.1*] 1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1)")
+ << QStringLiteral("rowsInserted(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "1.1.1" << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]"
+ << (QStringList()
+ << QStringLiteral("dataChanged(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ }
+
+ void testDataChangeIn()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, add);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+ // When changing the data on the designated item to show this row
+ QStandardItem *itemToChange = itemByText(model, add);
+ QVERIFY(!itemToChange->data().toBool());
+ itemToChange->setData(true);
+
+ // The proxy should update as expected
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testDataChangeOut_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("remove"); // unset the flag on this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ const QStringList remove1_1_1 = (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("toplevel") << "[1*]" << "[1*]" << "1" << ""
+ << (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1)") << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("hide_parent") << "[1[1.1[1.1.1*]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << "" <<
+ (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1*]]]" << "[1[1.1*[1.1.1*]]]" << "1.1.1" << "[1[1.1*]]"
+ << remove1_1_1;
+
+ QTest::newRow("visible") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.2*]]]"
+ << remove1_1_1;
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.2[1.1.2.1*]]]]"
+ << remove1_1_1;
+
+ // The following tests trigger the removal of an ascendant.
+ QTest::newRow("remove_parent") << "[1[1.1[1.1.1* 1.1.2] 1.2*]]" << "[1[1.1[1.1.1*] 1.2*]]" << "1.1.1" << "[1[1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]" << "1.1.1" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]"
+ << (QStringList()
+ << QStringLiteral("dataChanged(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("last_visible") << "[1[1.1[1.1.1* 1.1.2]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << ""
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ }
+
+ void testDataChangeOut()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, remove);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+
+ // When changing the data on the designated item to exclude this row again
+ QStandardItem *itemToChange = itemByText(model, remove);
+ QVERIFY(itemToChange->data().toBool());
+ itemToChange->setData(false);
+
+ // The proxy should update as expected
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testInsert()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ item_1_1_1->appendRow(item_1_1_1_1);
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*]]]]"));
+
+ QCOMPARE(spy.mSignals, QStringList() << QStringLiteral("rowsAboutToBeInserted(1)")
+ << QStringLiteral("rowsInserted(1)"));
+ }
+
+ // Start from [1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]
+ // where 1.1.1 is hidden but 1.1 is shown, we want to insert a shown child in 1.1.1.
+ // The proxy ensures dataChanged is called on 1.1,
+ // so that 1.1.1 and 1.1.1.1 are included in the model.
+ void testInsertCousin()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.2[1.1.2.1*]]]]"));
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+ item_1_1_1->appendRow(item_1_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*] 1.1.2[1.1.2.1*]]]]"));
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.1)")
+ << QStringLiteral("rowsInserted(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+ }
+
+ void testInsertWithChildren()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem(QStringLiteral("1.1.1"));
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ item_1_1_1->appendRow(item_1_1_1_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*]]]]"));
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1)")
+ << QStringLiteral("rowsInserted(1)"));
+ }
+
+ void testInsertIntoVisibleWithChildren()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1*]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_2 = new QStandardItem(QStringLiteral("1.1.2"));
+ QStandardItem *item_1_1_2_1 = new QStandardItem(QStringLiteral("1.1.2.1"));
+ item_1_1_2_1->setData(true);
+ item_1_1_2->appendRow(item_1_1_2_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_2);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]"));
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.2)")
+ << QStringLiteral("rowsInserted(1.1.2)"));
+ }
+
+ void testInsertBefore()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = "[1[1.1[1.1.2*]]]";
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem("1.1.1");
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->insertRow(0, item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QString("[1[1.1[1.1.2*]]]"));
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ void testInsertHidden() // inserting filtered-out rows shouldn't emit anything
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem(QStringLiteral("1.1.1"));
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1->appendRow(item_1_1_1_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QString());
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ void testConsecutiveInserts_data()
+ {
+ testInitialFiltering_data();
+ }
+
+ void testConsecutiveInserts()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, proxyStr);
+
+ QStandardItemModel model;
+ TestModel proxy(&model); // this time the proxy listens to the model while we fill it
+
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+ QCOMPARE(treeAsString(proxy), proxyStr);
+ }
+
+ void testRemove_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("remove"); // remove this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ const QStringList remove1_1_1 = (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1.1.1)") << QStringLiteral("rowsRemoved(1.1.1)"));
+
+ QTest::newRow("toplevel") << "[1* 2* 3*]" << "[1* 2* 3*]" << "1" << "[2* 3*]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1)") << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("remove_hidden") << "[1 2* 3*]" << "[2* 3*]" << "1" << "[2* 3*]" << QStringList();
+
+ QTest::newRow("parent_hidden") << "[1[1.1[1.1.1]]]" << "" << "1.1.1" << "" << QStringList();
+
+ QTest::newRow("child_hidden") << "[1[1.1*[1.1.1]]]" << "[1[1.1*]]" << "1.1.1" << "[1[1.1*]]" << QStringList();
+
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1*]]]" << "[1[1.1*[1.1.1*]]]" << "1.1.1" << "[1[1.1*]]"
+ << remove1_1_1;
+
+ QTest::newRow("visible") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.2*]]]"
+ << remove1_1_1;
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.2[1.1.2.1*]]]]"
+ << remove1_1_1;
+
+ // The following tests trigger the removal of an ascendant.
+ // We could optimize the rows{AboutToBe,}Removed(1.1.1) away...
+
+ QTest::newRow("remove_parent") << "[1[1.1[1.1.1* 1.1.2] 1.2*]]" << "[1[1.1[1.1.1*] 1.2*]]" << "1.1.1" << "[1[1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "1.1.1" << "[2*]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("last_visible") << "[1[1.1[1.1.1* 1.1.2]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << ""
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+
+ }
+
+ void testRemove()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, remove);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *itemToRemove = itemByText(model, remove);
+ QVERIFY(itemToRemove);
+ if (itemToRemove->parent())
+ itemToRemove->parent()->removeRow(itemToRemove->row());
+ else
+ model.removeRow(itemToRemove->row());
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testStandardFiltering_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<QString>("expectedProxyStr");
+
+ QTest::newRow("select_child") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]"
+ << "1.1.2" << "[1[1.1[1.1.2*]]]";
+
+ QTest::newRow("filter_all_out") << "[1[1.1[1.1.1*]]]" << "[1[1.1[1.1.1*]]]"
+ << "test" << "";
+
+ QTest::newRow("select_parent") << "[1[1.1[1.1.1*[child*] 1.1.2*]]]" << "[1[1.1[1.1.1*[child*] 1.1.2*]]]"
+ << "1.1.1" << "[1[1.1[1.1.1*]]]";
+
+ }
+
+ void testStandardFiltering()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, filter);
+ QFETCH(QString, expectedProxyStr);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+
+ //qDebug() << "setFilterFixedString";
+ proxy.setFilterFixedString(filter);
+
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ }
+
+private:
+ QStandardItem *itemByText(const QStandardItemModel& model, const QString &text) const {
+ QModelIndexList list = model.match(model.index(0, 0), Qt::DisplayRole, text, 1, Qt::MatchRecursive);
+ return list.isEmpty() ? 0 : model.itemFromIndex(list.first());
+ }
+};
+
+QTEST_GUILESS_MAIN(tst_QSortFilterProxyModel_Recursive)
+#include "tst_qsortfilterproxymodel_recursive.moc"
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 143bf2f95d..28c5c53744 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -155,7 +155,9 @@ void tst_QMetaType::defined()
QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0);
QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1);
QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1);
+ QCOMPARE(int(QMetaTypeId2<CustomGadget*>::Defined), 1);
QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined);
+ QVERIFY(!QMetaTypeId2<GadgetDerived*>::Defined);
QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined));
QVERIFY(!QMetaTypeId2<CustomQObject>::Defined);
QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
@@ -397,6 +399,7 @@ void tst_QMetaType::typeName_data()
QTest::newRow("CustomQObject*") << ::qMetaTypeId<CustomQObject*>() << QString::fromLatin1("CustomQObject*");
QTest::newRow("CustomGadget") << ::qMetaTypeId<CustomGadget>() << QString::fromLatin1("CustomGadget");
+ QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*");
QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId<CustomQObject::CustomQEnum>() << QString::fromLatin1("CustomQObject::CustomQEnum");
QTest::newRow("Qt::ArrowType") << ::qMetaTypeId<Qt::ArrowType>() << QString::fromLatin1("Qt::ArrowType");
}
@@ -1684,6 +1687,7 @@ public:
};
Q_DECLARE_METATYPE(MyGadget);
+Q_DECLARE_METATYPE(MyGadget*);
Q_DECLARE_METATYPE(const QMetaObject *);
Q_DECLARE_METATYPE(Qt::ScrollBarPolicy);
Q_DECLARE_METATYPE(MyGadget::MyEnum);
@@ -1693,16 +1697,18 @@ void tst_QMetaType::metaObject_data()
QTest::addColumn<int>("type");
QTest::addColumn<const QMetaObject*>("result");
QTest::addColumn<bool>("isGadget");
+ QTest::addColumn<bool>("isGadgetPtr");
QTest::addColumn<bool>("isQObjectPtr");
- QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << true;
- QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << true;
- QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << true;
- QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false;
- QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false;
- QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false;
- QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false;
- QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false;
+ QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << false << true;
+ QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << false << true;
+ QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << false << true;
+ QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false << false;
+ QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false << false;
+ QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false << false;
+ QTest::newRow("MyGadget*") << ::qMetaTypeId<MyGadget*>() << &MyGadget::staticMetaObject << false << true << false;
+ QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false << false;
+ QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false << false;
}
@@ -1711,12 +1717,14 @@ void tst_QMetaType::metaObject()
QFETCH(int, type);
QFETCH(const QMetaObject *, result);
QFETCH(bool, isGadget);
+ QFETCH(bool, isGadgetPtr);
QFETCH(bool, isQObjectPtr);
QCOMPARE(QMetaType::metaObjectForType(type), result);
QMetaType mt(type);
QCOMPARE(mt.metaObject(), result);
QCOMPARE(!!(mt.flags() & QMetaType::IsGadget), isGadget);
+ QCOMPARE(!!(mt.flags() & QMetaType::PointerToGadget), isGadgetPtr);
QCOMPARE(!!(mt.flags() & QMetaType::PointerToQObject), isQObjectPtr);
}
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index a546cad225..37b052bf1d 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -1205,8 +1205,6 @@ void tst_QFuture::pause()
Interface.reportFinished();
}
-const int resultCount = 1000;
-
class ResultObject : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index 2970b2e118..ba470a77c9 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -42,6 +42,7 @@ private slots:
void tryAcquireWithTimeout();
void tryAcquireWithTimeoutStarvation();
void producerConsumer();
+ void raii();
};
static QSemaphore *semaphore = 0;
@@ -417,5 +418,54 @@ void tst_QSemaphore::producerConsumer()
consumer.wait();
}
+void tst_QSemaphore::raii()
+{
+ QSemaphore sem;
+
+ QCOMPARE(sem.available(), 0);
+
+ // basic operation:
+ {
+ QSemaphoreReleaser r0;
+ const QSemaphoreReleaser r1(sem);
+ const QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(r0.semaphore(), nullptr);
+ QCOMPARE(r1.semaphore(), &sem);
+ QCOMPARE(r2.semaphore(), &sem);
+ }
+
+ QCOMPARE(sem.available(), 3);
+
+ // cancel:
+ {
+ const QSemaphoreReleaser r1(sem);
+ QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(r2.cancel(), &sem);
+ QCOMPARE(r2.semaphore(), nullptr);
+ }
+
+ QCOMPARE(sem.available(), 4);
+
+ // move-assignment:
+ {
+ const QSemaphoreReleaser r1(sem);
+ QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(sem.available(), 4);
+
+ r2 = QSemaphoreReleaser();
+
+ QCOMPARE(sem.available(), 6);
+
+ r2 = QSemaphoreReleaser(sem, 42);
+
+ QCOMPARE(sem.available(), 6);
+ }
+
+ QCOMPARE(sem.available(), 49);
+}
+
QTEST_MAIN(tst_QSemaphore)
#include "tst_qsemaphore.moc"
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index fdc4ecb5c8..1dcd642023 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -961,21 +961,6 @@ void tst_QThreadPool::cancel()
QSemaphore sem(0);
QSemaphore startedThreads(0);
- class SemaphoreReleaser
- {
- QSemaphore &sem;
- int n;
- Q_DISABLE_COPY(SemaphoreReleaser)
- public:
- explicit SemaphoreReleaser(QSemaphore &sem, int n)
- : sem(sem), n(n) {}
-
- ~SemaphoreReleaser()
- {
- sem.release(n);
- }
- };
-
class BlockingRunnable : public QRunnable
{
public:
@@ -1014,7 +999,7 @@ void tst_QThreadPool::cancel()
// ensure that the QThreadPool doesn't deadlock if any of the checks fail
// and cause an early return:
- const SemaphoreReleaser semReleaser(sem, runs);
+ const QSemaphoreReleaser semReleaser(sem, runs);
count.store(0);
QAtomicInt dtorCounter = 0;
@@ -1048,21 +1033,6 @@ void tst_QThreadPool::tryTake()
QSemaphore sem(0);
QSemaphore startedThreads(0);
- class SemaphoreReleaser
- {
- QSemaphore &sem;
- int n;
- Q_DISABLE_COPY(SemaphoreReleaser)
- public:
- explicit SemaphoreReleaser(QSemaphore &sem, int n)
- : sem(sem), n(n) {}
-
- ~SemaphoreReleaser()
- {
- sem.release(n);
- }
- };
-
class BlockingRunnable : public QRunnable
{
public:
@@ -1101,7 +1071,7 @@ void tst_QThreadPool::tryTake()
// ensure that the QThreadPool doesn't deadlock if any of the checks fail
// and cause an early return:
- const SemaphoreReleaser semReleaser(sem, Runs);
+ const QSemaphoreReleaser semReleaser(sem, Runs);
count.store(0);
QAtomicInt dtorCounter = 0;
diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
index e5a6e953d3..76309d914b 100644
--- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
@@ -36,6 +36,8 @@ class tst_QChar : public QObject
{
Q_OBJECT
private slots:
+ void fromChar16_t();
+ void fromWchar_t();
void operator_eqeq_null();
void operators_data();
void operators();
@@ -72,6 +74,33 @@ private slots:
void unicodeVersion();
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
+void tst_QChar::fromChar16_t()
+{
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+ QChar aUmlaut = u'\u00E4'; // German small letter a-umlaut
+ QCOMPARE(aUmlaut, QChar(0xE4));
+ QChar replacementCharacter = u'\uFFFD';
+ QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler.");
+#endif
+}
+
+void tst_QChar::fromWchar_t()
+{
+#if defined(Q_OS_WIN)
+ QChar aUmlaut = L'\u00E4'; // German small letter a-umlaut
+ QCOMPARE(aUmlaut, QChar(0xE4));
+ QChar replacementCharacter = L'\uFFFD';
+ QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
+#else
+ QSKIP("This is a Windows-only test.");
+#endif
+}
+
void tst_QChar::operator_eqeq_null()
{
{
diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
index a68671d899..c8373b6ae9 100644
--- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
+++ b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
@@ -48,6 +48,7 @@ private Q_SLOTS:
void midLeftRight();
void nullString();
void emptyString();
+ void iterators();
void relationalOperators_data();
void relationalOperators();
};
@@ -155,6 +156,22 @@ void tst_QLatin1String::emptyString()
}
}
+void tst_QLatin1String::iterators()
+{
+ QLatin1String hello("hello");
+ QLatin1String olleh("olleh");
+
+ QVERIFY(std::equal(hello.begin(), hello.end(),
+ olleh.rbegin()));
+ QVERIFY(std::equal(hello.rbegin(), hello.rend(),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(olleh.begin(), olleh.size())));
+
+ QVERIFY(std::equal(hello.cbegin(), hello.cend(),
+ olleh.rbegin()));
+ QVERIFY(std::equal(hello.crbegin(), hello.crend(),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(olleh.begin(), olleh.size())));
+}
+
void tst_QLatin1String::relationalOperators_data()
{
QTest::addColumn<QLatin1StringContainer>("lhs");
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index 5d13d9e454..9248970c96 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -2450,8 +2450,8 @@ void tst_QLocale::textDirection_data()
default:
break;
}
- QString testName = QLocalePrivate::languageToCode(QLocale::Language(language));
- QTest::newRow(testName.toLatin1().constData()) << language << int(QLocale::AnyScript) << rightToLeft;
+ const QLatin1String testName = QLocalePrivate::languageToCode(QLocale::Language(language));
+ QTest::newRow(qPrintable(testName)) << language << int(QLocale::AnyScript) << rightToLeft;
}
QTest::newRow("pa_Arab") << int(QLocale::Punjabi) << int(QLocale::ArabicScript) << true;
QTest::newRow("uz_Arab") << int(QLocale::Uzbek) << int(QLocale::ArabicScript) << true;
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 03436375dd..3f118d04ce 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -6067,14 +6067,6 @@ void tst_QString::compare_data()
lower += QChar(QChar::lowSurrogate(0x10428));
QTest::newRow("data8") << upper << lower << -1 << 0;
- QTest::newRow("vectorized-boundaries-7") << QString("1234567") << QString("abcdefg") << -1 << -1;
- QTest::newRow("vectorized-boundaries-8") << QString("12345678") << QString("abcdefgh") << -1 << -1;
- QTest::newRow("vectorized-boundaries-9") << QString("123456789") << QString("abcdefghi") << -1 << -1;
-
- QTest::newRow("vectorized-boundaries-15") << QString("123456789012345") << QString("abcdefghiklmnop") << -1 << -1;
- QTest::newRow("vectorized-boundaries-16") << QString("1234567890123456") << QString("abcdefghiklmnopq") << -1 << -1;
- QTest::newRow("vectorized-boundaries-17") << QString("12345678901234567") << QString("abcdefghiklmnopqr") << -1 << -1;
-
// embedded nulls
// These don't work as of now. It's OK that these don't work since \0 is not a valid unicode
/*QTest::newRow("data10") << QString(QByteArray("\0", 1)) << QString(QByteArray("\0", 1)) << 0 << 0;
@@ -6083,6 +6075,44 @@ void tst_QString::compare_data()
QTest::newRow("data13") << QString("ab\0c") << QString(QByteArray("ab\0c", 4)) << 0 << 0;
QTest::newRow("data14") << QString(QByteArray("ab\0c", 4)) << QString("abc") << -1 << -1;
QTest::newRow("data15") << QString("abc") << QString(QByteArray("ab\0c", 4)) << 1 << 1;*/
+
+ // All tests below (generated by the 3 for-loops) are meant to excercise the vectorized versions
+ // of ucstrncmp.
+
+ QString in1, in2;
+ for (int i = 0; i < 70; ++i) {
+ in1 += QString::number(i % 10);
+ in2 += QString::number((70 - i + 1) % 10);
+ }
+ Q_ASSERT(in1.length() == in2.length());
+ Q_ASSERT(in1 != in2);
+ Q_ASSERT(in1.at(0) < in2.at(0));
+ for (int i = 0; i < in1.length(); ++i) {
+ Q_ASSERT(in1.at(i) != in2.at(i));
+ }
+
+ for (int i = 1; i <= 65; ++i) {
+ QString inp1 = in1.left(i);
+ QString inp2 = in2.left(i);
+ QTest::addRow("all-different-%d", i) << inp1 << inp2 << -1 << -1;
+ }
+
+ for (int i = 1; i <= 65; ++i) {
+ QString start(i - 1, 'a');
+
+ QString in = start + QLatin1Char('a');
+ QTest::addRow("all-same-%d", i) << in << in << 0 << 0;
+
+ QString in2 = start + QLatin1Char('b');
+ QTest::addRow("last-different-%d", i) << in << in2 << -1 << -1;
+ }
+
+ for (int i = 0; i < 16; ++i) {
+ QString in1(16, 'a');
+ QString in2 = in1;
+ in2[i] = 'b';
+ QTest::addRow("all-same-except-char-%d", i) << in1 << in2 << -1 << -1;
+ }
}
static bool isLatin(const QString &s)
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 9d9b47b61e..36f479ca01 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -160,6 +160,45 @@ private Q_SLOTS:
//void compare_const_char_star_const_char_star_data() { compare_data(); }
//void compare_const_char_star_const_char_star() { compare_impl<const char *, const char *>(); }
+private:
+ void mid_data();
+ template <typename String> void mid_impl();
+
+ void left_data();
+ template <typename String> void left_impl();
+
+ void right_data();
+ template <typename String> void right_impl();
+
+private Q_SLOTS:
+
+ void mid_QString_data() { mid_data(); }
+ void mid_QString() { mid_impl<QString>(); }
+ void mid_QStringRef_data() { mid_data(); }
+ void mid_QStringRef() { mid_impl<QStringRef>(); }
+ void mid_QLatin1String_data() { mid_data(); }
+ void mid_QLatin1String() { mid_impl<QLatin1String>(); }
+ void mid_QByteArray_data() { mid_data(); }
+ void mid_QByteArray() { mid_impl<QByteArray>(); }
+
+ void left_QString_data() { left_data(); }
+ void left_QString() { left_impl<QString>(); }
+ void left_QStringRef_data() { left_data(); }
+ void left_QStringRef() { left_impl<QStringRef>(); }
+ void left_QLatin1String_data() { left_data(); }
+ void left_QLatin1String() { left_impl<QLatin1String>(); }
+ void left_QByteArray_data() { left_data(); }
+ void left_QByteArray() { left_impl<QByteArray>(); }
+
+ void right_QString_data() { right_data(); }
+ void right_QString() { right_impl<QString>(); }
+ void right_QStringRef_data() { right_data(); }
+ void right_QStringRef() { right_impl<QStringRef>(); }
+ void right_QLatin1String_data() { right_data(); }
+ void right_QLatin1String() { right_impl<QLatin1String>(); }
+ void right_QByteArray_data() { right_data(); }
+ void right_QByteArray() { right_impl<QByteArray>(); }
+
//
// UTF-16-only checks:
//
@@ -300,6 +339,178 @@ void tst_QStringApiSymmetry::compare_impl() const
#undef CHECK
}
+static QString empty = QLatin1String("");
+// the tests below rely on the fact that these objects' names match their contents:
+static QString a = QStringLiteral("a");
+static QString b = QStringLiteral("b");
+static QString c = QStringLiteral("c");
+static QString ab = QStringLiteral("ab");
+static QString bc = QStringLiteral("bc");
+static QString abc = QStringLiteral("abc");
+
+void tst_QStringApiSymmetry::mid_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("pos");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+ QTest::addColumn<QStringRef>("result2");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << 0 << QStringRef() << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << 0 << QStringRef(&empty) << QStringRef(&empty);
+
+ // Some classes' mid() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, p, n, r1, r2) \
+ QTest::addRow("%s%d%d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2)
+
+ ROW(a, 0, 0, a, empty);
+ ROW(a, 0, 1, a, a);
+ ROW(a, 1, 0, empty, empty);
+
+ ROW(ab, 0, 0, ab, empty);
+ ROW(ab, 0, 1, ab, a);
+ ROW(ab, 0, 2, ab, ab);
+ ROW(ab, 1, 0, b, empty);
+ ROW(ab, 1, 1, b, b);
+ ROW(ab, 2, 0, empty, empty);
+
+ ROW(abc, 0, 0, abc, empty);
+ ROW(abc, 0, 1, abc, a);
+ ROW(abc, 0, 2, abc, ab);
+ ROW(abc, 0, 3, abc, abc);
+ ROW(abc, 1, 0, bc, empty);
+ ROW(abc, 1, 1, bc, b);
+ ROW(abc, 1, 2, bc, bc);
+ ROW(abc, 2, 0, c, empty);
+ ROW(abc, 2, 1, c, c);
+ ROW(abc, 3, 0, empty, empty);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::mid_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, pos);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+ QFETCH(const QStringRef, result2);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ const auto mid = s.mid(pos);
+ const auto mid2 = s.mid(pos, n);
+
+ QVERIFY(mid == result);
+ QCOMPARE(mid.isNull(), result.isNull());
+ QCOMPARE(mid.isEmpty(), result.isEmpty());
+
+ QVERIFY(mid2 == result2);
+ QCOMPARE(mid2.isNull(), result2.isNull());
+ QCOMPARE(mid2.isEmpty(), result2.isEmpty());
+}
+
+void tst_QStringApiSymmetry::left_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty);
+
+ // Some classes' left() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, n, res) \
+ QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
+
+ ROW(a, 0, empty);
+ ROW(a, 1, a);
+
+ ROW(ab, 0, empty);
+ ROW(ab, 1, a);
+ ROW(ab, 2, ab);
+
+ ROW(abc, 0, empty);
+ ROW(abc, 1, a);
+ ROW(abc, 2, ab);
+ ROW(abc, 3, abc);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::left_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ const auto left = s.left(n);
+
+ QVERIFY(left == result);
+ QCOMPARE(left.isNull(), result.isNull());
+ QCOMPARE(left.isEmpty(), result.isEmpty());
+}
+
+void tst_QStringApiSymmetry::right_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty);
+
+ // Some classes' right() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, n, res) \
+ QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
+
+ ROW(a, 0, empty);
+ ROW(a, 1, a);
+
+ ROW(ab, 0, empty);
+ ROW(ab, 1, b);
+ ROW(ab, 2, ab);
+
+ ROW(abc, 0, empty);
+ ROW(abc, 1, c);
+ ROW(abc, 2, bc);
+ ROW(abc, 3, abc);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::right_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ const auto right = s.right(n);
+
+ QVERIFY(right == result);
+ QCOMPARE(right.isNull(), result.isNull());
+ QCOMPARE(right.isEmpty(), result.isEmpty());
+}
+
//
//
// UTF-16-only checks:
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
index 2385aa992c..9f054190e5 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
@@ -264,6 +264,15 @@ void tst_QStringList::contains()
QVERIFY(list.contains("ARTHUR", Qt::CaseInsensitive));
QVERIFY(list.contains("dent", Qt::CaseInsensitive));
QVERIFY(!list.contains("hans", Qt::CaseInsensitive));
+
+ QVERIFY(list.contains(QLatin1String("arthur")));
+ QVERIFY(!list.contains(QLatin1String("ArthuR")));
+ QVERIFY(!list.contains(QLatin1String("Hans")));
+ QVERIFY(list.contains(QLatin1String("arthur"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("ArthuR"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("ARTHUR"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("dent"), Qt::CaseInsensitive));
+ QVERIFY(!list.contains(QLatin1String("hans"), Qt::CaseInsensitive));
}
void tst_QStringList::removeDuplicates_data()
diff --git a/tests/auto/corelib/tools/qstringview/.gitignore b/tests/auto/corelib/tools/qstringview/.gitignore
new file mode 100644
index 0000000000..5f757d448a
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/.gitignore
@@ -0,0 +1 @@
+tst_qstringview
diff --git a/tests/auto/corelib/tools/qstringview/qstringview.pro b/tests/auto/corelib/tools/qstringview/qstringview.pro
new file mode 100644
index 0000000000..e0e9973c91
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/qstringview.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+TARGET = tst_qstringview
+QT = core testlib
+contains(QT_CONFIG, c++14):CONFIG *= c++14
+contains(QT_CONFIG, c++1z):CONFIG *= c++1z
+SOURCES += tst_qstringview.cpp
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
new file mode 100644
index 0000000000..2e671040dc
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QStringView>
+#include <QString>
+#include <QChar>
+#include <QStringRef>
+
+#include <QTest>
+
+#include <string>
+
+template <typename T>
+using CanConvert = std::is_convertible<T, QStringView>;
+
+//
+// QChar
+//
+
+Q_STATIC_ASSERT(CanConvert< QString >::value);
+Q_STATIC_ASSERT(CanConvert<const QString >::value);
+Q_STATIC_ASSERT(CanConvert< QString&>::value);
+Q_STATIC_ASSERT(CanConvert<const QString&>::value);
+
+Q_STATIC_ASSERT(CanConvert< QStringRef >::value);
+Q_STATIC_ASSERT(CanConvert<const QStringRef >::value);
+Q_STATIC_ASSERT(CanConvert< QStringRef&>::value);
+Q_STATIC_ASSERT(CanConvert<const QStringRef&>::value);
+
+
+//
+// ushort
+//
+
+Q_STATIC_ASSERT(CanConvert< ushort*>::value);
+Q_STATIC_ASSERT(CanConvert<const ushort*>::value);
+
+
+//
+// char16_t
+//
+
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+
+Q_STATIC_ASSERT(CanConvert< char16_t*>::value);
+Q_STATIC_ASSERT(CanConvert<const char16_t*>::value);
+
+#endif
+
+#ifdef Q_COMPILER_UNICODE_STRINGS
+
+Q_STATIC_ASSERT(CanConvert< std::u16string >::value);
+Q_STATIC_ASSERT(CanConvert<const std::u16string >::value);
+Q_STATIC_ASSERT(CanConvert< std::u16string&>::value);
+Q_STATIC_ASSERT(CanConvert<const std::u16string&>::value);
+
+#endif
+
+
+//
+// wchar_t
+//
+
+Q_CONSTEXPR bool CanConvertFromWCharT =
+#ifdef Q_OS_WIN
+ true
+#else
+ false
+#endif
+ ;
+
+Q_STATIC_ASSERT(CanConvert< wchar_t*>::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const wchar_t*>::value == CanConvertFromWCharT);
+
+Q_STATIC_ASSERT(CanConvert< std::wstring >::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const std::wstring >::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert< std::wstring&>::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const std::wstring&>::value == CanConvertFromWCharT);
+
+
+class tst_QStringView : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void constExpr() const;
+ void basics() const;
+ void at() const;
+
+ void fromQString() const;
+ void fromQStringRef() const;
+
+ void fromQCharStar() const
+ {
+ const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromLiteral(str);
+ }
+
+ void fromUShortStar() const
+ {
+ const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromLiteral(str);
+ }
+
+ void fromChar16TStar() const
+ {
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+ fromLiteral(u"Hello, World!");
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler");
+#endif
+ }
+
+ void fromWCharTStar() const
+ {
+#ifdef Q_OS_WIN
+ fromLiteral(L"Hello, World!");
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+
+ // std::basic_string
+ void fromStdStringWCharT() const
+ {
+#ifdef Q_OS_WIN
+ fromStdString<wchar_t>();
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+ void fromStdStringChar16T() const
+ {
+#ifdef Q_COMPILER_UNICODE_STRINGS
+ fromStdString<char16_t>();
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in compiler & stdlib");
+#endif
+ }
+
+private:
+ template <typename String>
+ void conversion_tests(String arg) const;
+ template <typename Char>
+ void fromLiteral(const Char *arg) const;
+ template <typename Char, typename Container>
+ void fromContainer() const;
+ template <typename Char>
+ void fromStdString() const { fromContainer<Char, std::basic_string<Char> >(); }
+};
+
+void tst_QStringView::constExpr() const
+{
+ // compile-time checks
+#ifdef Q_COMPILER_CONSTEXPR
+ {
+ constexpr QStringView sv;
+ Q_STATIC_ASSERT(sv.size() == 0);
+ Q_STATIC_ASSERT(sv.isNull());
+ Q_STATIC_ASSERT(sv.empty());
+ Q_STATIC_ASSERT(sv.isEmpty());
+ Q_STATIC_ASSERT(sv.utf16() == nullptr);
+ }
+ {
+ constexpr QStringView sv = QStringViewLiteral("");
+ Q_STATIC_ASSERT(sv.size() == 0);
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(sv.empty());
+ Q_STATIC_ASSERT(sv.isEmpty());
+ Q_STATIC_ASSERT(sv.utf16() != nullptr);
+ }
+ {
+ constexpr QStringView sv = QStringViewLiteral("Hello");
+ Q_STATIC_ASSERT(sv.size() == 5);
+ Q_STATIC_ASSERT(!sv.empty());
+ Q_STATIC_ASSERT(!sv.isEmpty());
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(*sv.utf16() == 'H');
+ Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+ }
+#endif
+}
+
+void tst_QStringView::basics() const
+{
+ QStringView sv1;
+
+ // a default-constructed QStringView is null:
+ QVERIFY(sv1.isNull());
+ // which implies it's empty();
+ QVERIFY(sv1.isEmpty());
+}
+
+void tst_QStringView::at() const
+{
+ QString hello("Hello");
+ QStringView sv(hello);
+ QCOMPARE(sv.at(0), QChar('H')); QCOMPARE(sv[0], QChar('H'));
+ QCOMPARE(sv.at(1), QChar('e')); QCOMPARE(sv[1], QChar('e'));
+ QCOMPARE(sv.at(2), QChar('l')); QCOMPARE(sv[2], QChar('l'));
+ QCOMPARE(sv.at(3), QChar('l')); QCOMPARE(sv[3], QChar('l'));
+ QCOMPARE(sv.at(4), QChar('o')); QCOMPARE(sv[4], QChar('o'));
+}
+
+void tst_QStringView::fromQString() const
+{
+ QString null;
+ QString empty = "";
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(QString("Hello World!"));
+}
+
+void tst_QStringView::fromQStringRef() const
+{
+ QStringRef null;
+ QString emptyS = "";
+ QStringRef empty(&emptyS);
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(QString("Hello World!").midRef(6));
+}
+
+template <typename Char>
+void tst_QStringView::fromLiteral(const Char *arg) const
+{
+ const Char *null = nullptr;
+ const Char empty[] = { 0 };
+
+ QCOMPARE(QStringView(null).size(), QStringView::size_type(0));
+ QCOMPARE(QStringView(null).data(), nullptr);
+ QCOMPARE(QStringView(empty).size(), QStringView::size_type(0));
+ QCOMPARE(static_cast<const void*>(QStringView(empty).data()),
+ static_cast<const void*>(empty));
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(arg);
+}
+
+template <typename Char, typename Container>
+void tst_QStringView::fromContainer() const
+{
+ const QString s = "Hello World!";
+
+ Container c;
+ // unspecified whether empty containers make null QStringViews
+ QVERIFY(QStringView(c).isEmpty());
+
+ QCOMPARE(sizeof(Char), sizeof(QChar));
+
+ const auto *data = reinterpret_cast<const Char *>(s.utf16());
+ std::copy(data, data + s.size(), std::back_inserter(c));
+ conversion_tests(std::move(c));
+}
+
+namespace help {
+template <typename T>
+size_t size(const T &t) { return size_t(t.size()); }
+template <typename T>
+size_t size(const T *t)
+{
+ size_t result = 0;
+ if (t) {
+ while (*t++)
+ ++result;
+ }
+ return result;
+}
+size_t size(const QChar *t)
+{
+ size_t result = 0;
+ if (t) {
+ while (!t++->isNull())
+ ++result;
+ }
+ return result;
+}
+
+template <typename T>
+typename T::const_iterator cbegin(const T &t) { return t.cbegin(); }
+template <typename T>
+const T * cbegin(const T *t) { return t; }
+
+template <typename T>
+typename T::const_iterator cend(const T &t) { return t.cend(); }
+template <typename T>
+const T * cend(const T *t) { return t + size(t); }
+
+template <typename T>
+typename T::const_reverse_iterator crbegin(const T &t) { return t.crbegin(); }
+template <typename T>
+std::reverse_iterator<const T*> crbegin(const T *t) { return std::reverse_iterator<const T*>(cend(t)); }
+
+template <typename T>
+typename T::const_reverse_iterator crend(const T &t) { return t.crend(); }
+template <typename T>
+std::reverse_iterator<const T*> crend(const T *t) { return std::reverse_iterator<const T*>(cbegin(t)); }
+
+} // namespace help
+
+template <typename String>
+void tst_QStringView::conversion_tests(String string) const
+{
+ // copy-construct:
+ {
+ QStringView sv = string;
+
+ QCOMPARE(help::size(sv), help::size(string));
+
+ // check iterators:
+
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.cbegin(), sv.size())));
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.begin(), sv.size())));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.crbegin()));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.rbegin()));
+ }
+
+ QStringView sv;
+
+ // copy-assign:
+ {
+ sv = string;
+
+ QCOMPARE(help::size(sv), help::size(string));
+
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.cbegin(), sv.size())));
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.begin(), sv.size())));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.crbegin()));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.rbegin()));
+ }
+
+ // copy-construct from rvalue (QStringView never assumes ownership):
+ {
+ QStringView sv2 = std::move(string);
+
+ QCOMPARE(help::size(sv2), help::size(string));
+
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.cbegin(), sv2.size())));
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.begin(), sv2.size())));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv2.crbegin()));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv2.rbegin()));
+
+ QCOMPARE(help::size(sv2), help::size(sv));
+
+ QVERIFY(std::equal(help::cbegin(sv), help::cend(sv),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.cbegin(), sv2.size())));
+ QVERIFY(std::equal(help::cbegin(sv), help::cend(sv),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.begin(), sv2.size())));
+ QVERIFY(std::equal(help::crbegin(sv), help::crend(sv),
+ sv2.crbegin()));
+ QVERIFY(std::equal(help::crbegin(sv), help::crend(sv),
+ sv2.rbegin()));
+ }
+
+ // copy-assign from rvalue (QStringView never assumes ownership):
+ {
+ QStringView sv2;
+ sv2 = std::move(string);
+
+ QCOMPARE(help::size(sv2), help::size(string));
+
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.cbegin(), sv2.size())));
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.begin(), sv2.size())));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv2.crbegin()));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv2.rbegin()));
+
+ QCOMPARE(help::size(sv2), help::size(sv));
+
+ QVERIFY(std::equal(help::cbegin(sv), help::cend(sv),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.cbegin(), sv2.size())));
+ QVERIFY(std::equal(help::cbegin(sv), help::cend(sv),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv2.begin(), sv2.size())));
+ QVERIFY(std::equal(help::crbegin(sv), help::crend(sv),
+ sv2.crbegin()));
+ QVERIFY(std::equal(help::crbegin(sv), help::crend(sv),
+ sv2.rbegin()));
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_QStringView)
+#include "tst_qstringview.moc"
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
index c1f2822b74..2cebe1fb6f 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
@@ -740,7 +740,7 @@ void tst_QTimeZone::icuTest()
void tst_QTimeZone::tzTest()
{
-#if defined QT_BUILD_INTERNAL && defined Q_OS_UNIX && !defined Q_OS_MAC
+#if defined QT_BUILD_INTERNAL && defined Q_OS_UNIX && !defined Q_OS_DARWIN
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -903,12 +903,12 @@ void tst_QTimeZone::tzTest()
QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC);
QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07"));
}
-#endif // Q_OS_UNIX
+#endif // QT_BUILD_INTERNAL && Q_OS_UNIX && !Q_OS_DARWIN
}
void tst_QTimeZone::macTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined (Q_OS_MAC)
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_DARWIN)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -955,7 +955,7 @@ void tst_QTimeZone::macTest()
}
testCetPrivate(tzp);
-#endif // Q_OS_MAC
+#endif // QT_BUILD_INTERNAL && Q_OS_DARWIN
}
void tst_QTimeZone::darwinTypes()
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 0806ad1318..3971353cbb 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -30,8 +30,6 @@
#include <qvarlengtharray.h>
#include <qvariant.h>
-const int N = 1;
-
class tst_QVarLengthArray : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index e45771a704..e16648c15f 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -56,6 +56,7 @@ SUBDIRS=\
qstringlist \
qstringmatcher \
qstringref \
+ qstringview \
qtextboundaryfinder \
qtime \
qtimezone \