diff options
Diffstat (limited to 'tests')
72 files changed, 3850 insertions, 874 deletions
diff --git a/tests/auto/corelib/global/qglobal/qglobal.pro b/tests/auto/corelib/global/qglobal/qglobal.pro index a40cb9a288..b105769430 100644 --- a/tests/auto/corelib/global/qglobal/qglobal.pro +++ b/tests/auto/corelib/global/qglobal/qglobal.pro @@ -2,3 +2,4 @@ CONFIG += testcase TARGET = tst_qglobal QT = core testlib SOURCES = tst_qglobal.cpp qglobal.c +contains(QT_CONFIG, c++1z): CONFIG += c++1z diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 78b954f373..56da047147 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -126,6 +126,46 @@ void tst_QGlobal::for_each() QCOMPARE(i, counter++); } QCOMPARE(counter, list.count()); + + // Should also work with an existing variable + int local; + counter = 0; + foreach (local, list) { + QCOMPARE(local, counter++); + } + QCOMPARE(counter, list.count()); + QCOMPARE(local, counter - 1); + + // Test the macro does not mess if/else conditions + counter = 0; + if (true) + foreach (int i, list) + QCOMPARE(i, counter++); + else + QFAIL("If/Else mismatch"); + QCOMPARE(counter, list.count()); + + counter = 0; + if (false) + foreach (int i, list) + if (i) QFAIL("If/Else mismatch"); + else QFAIL("If/Else mismatch"); + else + foreach (int i, list) + if (false) { } + else QCOMPARE(i, counter++); + QCOMPARE(counter, list.count()); + + // break and continue + counter = 0; + foreach (int i, list) { + if (i == 0) + continue; + QCOMPARE(i, (counter++) + 1); + if (i == 3) + break; + } + QCOMPARE(counter, 3); } void tst_QGlobal::qassert() diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 017eebe153..3e29475636 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -95,6 +95,38 @@ inline bool qIsLikelyToBeNfs(const QString &path) #endif } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE // MinGW +# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2) +# endif + +static DWORD createSymbolicLink(const QString &symLinkName, const QString &target, + QString *errorMessage) +{ + DWORD result = ERROR_SUCCESS; + const QString nativeSymLinkName = QDir::toNativeSeparators(symLinkName); + const QString nativeTarget = QDir::toNativeSeparators(target); + DWORD flags = 0; + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14972)) + flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + if (QFileInfo(target).isDir()) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + if (CreateSymbolicLink(reinterpret_cast<const wchar_t*>(nativeSymLinkName.utf16()), + reinterpret_cast<const wchar_t*>(nativeTarget.utf16()), flags) == FALSE) { + result = GetLastError(); + QTextStream(errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", " + << nativeTarget << ", 0x" << hex << flags << dec << ") failed with error " << result + << ": " << qt_error_string(int(result)); + } + return result; +} + +static QByteArray msgInsufficientPrivileges(const QString &errorMessage) +{ + return "Insufficient privileges (" + errorMessage.toLocal8Bit() + ')'; +} +#endif // Q_OS_WIN && !Q_OS_WINRT + static QString seedAndTemplate() { QString base; @@ -704,19 +736,14 @@ void tst_QFileInfo::canonicalFilePath() #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) { - // CreateSymbolicLink can return TRUE & still fail to create the link, - // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314) - SetLastError(0); + QString errorMessage; const QString linkTarget = QStringLiteral("res"); - BOOL ret = CreateSymbolicLink((wchar_t*)linkTarget.utf16(), (wchar_t*)m_resourcesDir.utf16(), 1); - DWORD dwErr = GetLastError(); - if (!ret) - QSKIP("Symbolic links aren't supported by FS"); + const DWORD dwErr = createSymbolicLink(linkTarget, m_resourcesDir, &errorMessage); + if (dwErr == ERROR_PRIVILEGE_NOT_HELD) + QSKIP(msgInsufficientPrivileges(errorMessage)); + QVERIFY2(dwErr == ERROR_SUCCESS, qPrintable(errorMessage)); QString currentPath = QDir::currentPath(); - bool is_res_Current = QDir::setCurrent(linkTarget); - if (!is_res_Current && dwErr == 1314) - QSKIP("Not enough privilages to create Symbolic links"); - QCOMPARE(is_res_Current, true); + QVERIFY(QDir::setCurrent(linkTarget)); const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath(); QVERIFY(QDir::setCurrent(currentPath)); QCOMPARE(actualCanonicalPath, m_resourcesDir + QStringLiteral("/file1")); @@ -1455,8 +1482,24 @@ void tst_QFileInfo::refresh() } #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + +struct NtfsTestResource { + + enum Type { None, SymLink, Junction }; + + explicit NtfsTestResource(Type tp = None, const QString &s = QString(), const QString &t = QString()) + : source(s), target(t), type(tp) {} + + QString source; + QString target; + Type type; +}; + +Q_DECLARE_METATYPE(NtfsTestResource) + void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() { + QTest::addColumn<NtfsTestResource>("resource"); QTest::addColumn<QString>("path"); QTest::addColumn<bool>("isSymLink"); QTest::addColumn<QString>("linkTarget"); @@ -1479,32 +1522,20 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QString fileInSymlink(absSymlink); fileInSymlink.append("\\file"); QFile file(fileInTarget); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); file.close(); - DWORD err = ERROR_SUCCESS ; - if (!pwd.exists("abs_symlink")) - if (!CreateSymbolicLink((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)) - err = GetLastError(); - if (err == ERROR_SUCCESS && !pwd.exists(relSymlink)) - if (!CreateSymbolicLink((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)) - err = GetLastError(); - if (err != ERROR_SUCCESS) { - wchar_t errstr[0x100]; - DWORD count = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, - 0, err, 0, errstr, 0x100, 0); - QString error(QString::fromWCharArray(errstr, count)); - qWarning() << error; - //we need at least one data set for the test not to assert fail when skipping _data function - QDir target("target"); - QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); - QSKIP("link not supported by FS or insufficient privilege"); - } QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData()); - QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); - QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); - QTest::newRow("file in symlink dir") << fileInSymlink << false << "" << target.canonicalPath().append("/file"); + QTest::newRow("absolute dir symlink") + << NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget) + << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); + QTest::newRow("relative dir symlink") + << NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget) + << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); + QTest::newRow("file in symlink dir") + << NtfsTestResource() + << fileInSymlink << false << "" << target.canonicalPath().append("/file"); } { //File symlinks @@ -1517,33 +1548,41 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QString relSymlink = "rel_symlink.cpp"; QString relToRelTarget = QDir::toNativeSeparators(relativeDir.relativeFilePath(target.absoluteFilePath())); QString relToRelSymlink = "relative/rel_symlink"; - QVERIFY(pwd.exists("abs_symlink.cpp") || CreateSymbolicLink((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0)); - QVERIFY(pwd.exists(relSymlink) || CreateSymbolicLink((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0)); - QVERIFY(pwd.exists(relToRelSymlink) || CreateSymbolicLink((wchar_t*)relToRelSymlink.utf16(), (wchar_t*)relToRelTarget.utf16(),0x0)); - QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); - QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); - QTest::newRow("relative to relative file symlink") << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); + + QTest::newRow("absolute file symlink") + << NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget) + << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); + QTest::newRow("relative file symlink") + << NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget) + << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); + QTest::newRow("relative to relative file symlink") + << NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget) + << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); } //Junctions QString target = "target"; QString junction = "junction_pwd"; - FileSystem::createNtfsJunction(target, junction); QFileInfo targetInfo(target); - QTest::newRow("junction_pwd") << junction << false << QString() << QString(); + QTest::newRow("junction_pwd") + << NtfsTestResource(NtfsTestResource::Junction, junction, target) + << junction << false << QString() << QString(); QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file")); QFile file(fileInJunction.absoluteFilePath()); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); file.close(); QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData()); - QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath(); + QTest::newRow("file in junction") + << NtfsTestResource() + << fileInJunction.absoluteFilePath() << false << QString() << fileInJunction.canonicalFilePath(); target = QDir::rootPath(); junction = "junction_root"; - FileSystem::createNtfsJunction(target, junction); targetInfo.setFile(target); - QTest::newRow("junction_root") << junction << false << QString() << QString(); + QTest::newRow("junction_root") + << NtfsTestResource(NtfsTestResource::Junction, junction, target) + << junction << false << QString() << QString(); //Mountpoint wchar_t buffer[MAX_PATH]; @@ -1552,17 +1591,38 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QString rootVolume = QString::fromWCharArray(buffer); junction = "mountpoint"; rootVolume.replace("\\\\?\\","\\??\\"); - FileSystem::createNtfsJunction(rootVolume, junction); - QTest::newRow("mountpoint") << junction << false << QString() << QString(); + QTest::newRow("mountpoint") + << NtfsTestResource(NtfsTestResource::Junction, junction, rootVolume) + << junction << false << QString() << QString(); } void tst_QFileInfo::ntfsJunctionPointsAndSymlinks() { + QFETCH(NtfsTestResource, resource); QFETCH(QString, path); QFETCH(bool, isSymLink); QFETCH(QString, linkTarget); QFETCH(QString, canonicalFilePath); + QString errorMessage; + DWORD creationResult = ERROR_SUCCESS; + switch (resource.type) { + case NtfsTestResource::None: + break; + case NtfsTestResource::SymLink: + creationResult = createSymbolicLink(resource.source, resource.target, &errorMessage); + break; + case NtfsTestResource::Junction: + creationResult = FileSystem::createNtfsJunction(resource.target, resource.source, &errorMessage); + if (creationResult == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive + QSKIP(qPrintable(errorMessage)); + break; + } + + if (creationResult == ERROR_PRIVILEGE_NOT_HELD) + QSKIP(msgInsufficientPrivileges(errorMessage)); + QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage)); + QFileInfo fi(path); const bool actualIsSymLink = fi.isSymLink(); const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString(); diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro index cca350ad43..b27938e0c0 100644 --- a/tests/auto/corelib/itemmodels/itemmodels.pro +++ b/tests/auto/corelib/itemmodels/itemmodels.pro @@ -5,6 +5,7 @@ SUBDIRS = qstringlistmodel qtHaveModule(gui): SUBDIRS += \ qabstractitemmodel \ qabstractproxymodel \ + qconcatenatetablesproxymodel \ qidentityproxymodel \ qitemselectionmodel \ qsortfilterproxymodel_recursive \ diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro new file mode 100644 index 0000000000..ee4ea28b5b --- /dev/null +++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +TARGET = tst_qconcatenatetablesproxymodel +QT = core gui testlib + +SOURCES = tst_qconcatenatetablesproxymodel.cpp diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp new file mode 100644 index 0000000000..40617c1f7d --- /dev/null +++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp @@ -0,0 +1,823 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QSignalSpy> +#include <QSortFilterProxyModel> +#include <QTest> +#include <QStandardItemModel> +#include <QIdentityProxyModel> +#include <QItemSelectionModel> +#include <QMimeData> +#include <QStringListModel> +#include <QAbstractItemModelTester> + +#include <qconcatenatetablesproxymodel.h> + +Q_DECLARE_METATYPE(QModelIndex) + +// Extracts a full row from a model as a string +// Works best if every cell contains only one character +static QString extractRowTexts(QAbstractItemModel *model, int row, const QModelIndex &parent = QModelIndex()) +{ + QString result; + const int colCount = model->columnCount(); + for (int col = 0; col < colCount; ++col) { + const QString txt = model->index(row, col, parent).data().toString(); + result += txt.isEmpty() ? QStringLiteral(" ") : txt; + } + return result; +} + +// Extracts a full column from a model as a string +// Works best if every cell contains only one character +static QString extractColumnTexts(QAbstractItemModel *model, int column, const QModelIndex &parent = QModelIndex()) +{ + QString result; + const int rowCount = model->rowCount(); + for (int row = 0; row < rowCount; ++row) { + const QString txt = model->index(row, column, parent).data().toString(); + result += txt.isEmpty() ? QStringLiteral(" ") : txt; + } + return result; +} + +static QString rowSpyToText(const QSignalSpy &spy) +{ + if (!spy.isValid()) + return QStringLiteral("THE SIGNALSPY IS INVALID!"); + QString str; + for (int i = 0; i < spy.count(); ++i) { + str += spy.at(i).at(1).toString() + QLatin1Char(',') + spy.at(i).at(2).toString(); + if (i + 1 < spy.count()) + str += QLatin1Char(';'); + } + return str; +} + +class tst_QConcatenateTablesProxyModel : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void init(); + void shouldAggregateTwoModelsCorrectly(); + void shouldAggregateThenRemoveTwoEmptyModelsCorrectly(); + void shouldAggregateTwoEmptyModelsWhichThenGetFilled(); + void shouldHandleDataChanged(); + void shouldHandleSetData(); + void shouldHandleSetItemData(); + void shouldHandleRowInsertionAndRemoval(); + void shouldAggregateAnotherModelThenRemoveModels(); + void shouldUseSmallestColumnCount(); + void shouldIncreaseColumnCountWhenRemovingFirstModel(); + void shouldHandleColumnInsertionAndRemoval(); + void shouldPropagateLayoutChanged(); + void shouldReactToModelReset(); + void shouldUpdateColumnsOnModelReset(); + void shouldPropagateDropOnItem_data(); + void shouldPropagateDropOnItem(); + void shouldPropagateDropBetweenItems(); + void shouldPropagateDropBetweenItemsAtModelBoundary(); + void shouldPropagateDropAfterLastRow_data(); + void shouldPropagateDropAfterLastRow(); + +private: + QStandardItemModel mod; + QStandardItemModel mod2; + QStandardItemModel mod3; +}; + +void tst_QConcatenateTablesProxyModel::init() +{ + // Prepare some source models to use later on + mod.clear(); + mod.appendRow({ new QStandardItem(QStringLiteral("A")), new QStandardItem(QStringLiteral("B")), new QStandardItem(QStringLiteral("C")) }); + mod.setHorizontalHeaderLabels(QStringList() << QStringLiteral("H1") << QStringLiteral("H2") << QStringLiteral("H3")); + mod.setVerticalHeaderLabels(QStringList() << QStringLiteral("One")); + + mod2.clear(); + mod2.appendRow({ new QStandardItem(QStringLiteral("D")), new QStandardItem(QStringLiteral("E")), new QStandardItem(QStringLiteral("F")) }); + mod2.setHorizontalHeaderLabels(QStringList() << QStringLiteral("H1") << QStringLiteral("H2") << QStringLiteral("H3")); + mod2.setVerticalHeaderLabels(QStringList() << QStringLiteral("Two")); + + mod3.clear(); + mod3.appendRow({ new QStandardItem(QStringLiteral("1")), new QStandardItem(QStringLiteral("2")), new QStandardItem(QStringLiteral("3")) }); + mod3.appendRow({ new QStandardItem(QStringLiteral("4")), new QStandardItem(QStringLiteral("5")), new QStandardItem(QStringLiteral("6")) }); +} + +void tst_QConcatenateTablesProxyModel::shouldAggregateTwoModelsCorrectly() +{ + // Given a combining proxy + QConcatenateTablesProxyModel pm; + + // When adding two source models + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + + // Then the proxy should show 2 rows + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + + // ... and correct headers + QCOMPARE(pm.headerData(0, Qt::Horizontal).toString(), QStringLiteral("H1")); + QCOMPARE(pm.headerData(1, Qt::Horizontal).toString(), QStringLiteral("H2")); + QCOMPARE(pm.headerData(2, Qt::Horizontal).toString(), QStringLiteral("H3")); + QCOMPARE(pm.headerData(0, Qt::Vertical).toString(), QStringLiteral("One")); + QCOMPARE(pm.headerData(1, Qt::Vertical).toString(), QStringLiteral("Two")); + + QVERIFY(!pm.canFetchMore(QModelIndex())); +} + +void tst_QConcatenateTablesProxyModel::shouldAggregateThenRemoveTwoEmptyModelsCorrectly() +{ + // Given a combining proxy + QConcatenateTablesProxyModel pm; + + // When adding two empty models + QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QIdentityProxyModel i1, i2; + pm.addSourceModel(&i1); + pm.addSourceModel(&i2); + + // Then the proxy should still be empty (and no signals emitted) + QCOMPARE(pm.rowCount(), 0); + QCOMPARE(pm.columnCount(), 0); + QCOMPARE(rowATBISpy.count(), 0); + QCOMPARE(rowInsertedSpy.count(), 0); + + // When removing the empty models + pm.removeSourceModel(&i1); + pm.removeSourceModel(&i2); + + // Then the proxy should still be empty (and no signals emitted) + QCOMPARE(pm.rowCount(), 0); + QCOMPARE(pm.columnCount(), 0); + QCOMPARE(rowATBRSpy.count(), 0); + QCOMPARE(rowRemovedSpy.count(), 0); +} + +void tst_QConcatenateTablesProxyModel::shouldAggregateTwoEmptyModelsWhichThenGetFilled() +{ + // Given a combining proxy with two empty models + QConcatenateTablesProxyModel pm; + QIdentityProxyModel i1, i2; + pm.addSourceModel(&i1); + pm.addSourceModel(&i2); + + // When filling them afterwards + i1.setSourceModel(&mod); + i2.setSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + + // Then the proxy should show 2 rows + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(pm.columnCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + + // ... and correct headers + QCOMPARE(pm.headerData(0, Qt::Horizontal).toString(), QStringLiteral("H1")); + QCOMPARE(pm.headerData(1, Qt::Horizontal).toString(), QStringLiteral("H2")); + QCOMPARE(pm.headerData(2, Qt::Horizontal).toString(), QStringLiteral("H3")); + QCOMPARE(pm.headerData(0, Qt::Vertical).toString(), QStringLiteral("One")); + QCOMPARE(pm.headerData(1, Qt::Vertical).toString(), QStringLiteral("Two")); + + QVERIFY(!pm.canFetchMore(QModelIndex())); +} + +void tst_QConcatenateTablesProxyModel::shouldHandleDataChanged() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + + // When a cell in a source model changes + mod.item(0, 0)->setData("a", Qt::EditRole); + + // Then the change should be notified to the proxy + QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC")); + + // Same test with the other model + mod2.item(0, 2)->setData("f", Qt::EditRole); + + QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf")); +} + +void tst_QConcatenateTablesProxyModel::shouldHandleSetData() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + + // When changing a cell using setData + pm.setData(pm.index(0, 0), "a"); + + // Then the change should be notified to the proxy + QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC")); + + // Same test with the other model + pm.setData(pm.index(1, 2), "f"); + + QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf")); +} + +void tst_QConcatenateTablesProxyModel::shouldHandleSetItemData() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + + // When changing a cell using setData + pm.setItemData(pm.index(0, 0), QMap<int, QVariant>{ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("X")), + std::make_pair<int, QVariant>(Qt::UserRole, 88) }); + + // Then the change should be notified to the proxy + QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0)); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("XBC")); + QCOMPARE(pm.index(0, 0).data(Qt::UserRole).toInt(), 88); + + // Same test with the other model + pm.setItemData(pm.index(1, 2), QMap<int, QVariant>{ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("Y")), + std::make_pair<int, QVariant>(Qt::UserRole, 89) }); + + QCOMPARE(dataChangedSpy.count(), 2); + QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2)); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEY")); + QCOMPARE(pm.index(1, 2).data(Qt::UserRole).toInt(), 89); +} + +void tst_QConcatenateTablesProxyModel::shouldHandleRowInsertionAndRemoval() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int))); + + // When a source model inserts a new row + QList<QStandardItem *> row; + row.append(new QStandardItem(QStringLiteral("1"))); + row.append(new QStandardItem(QStringLiteral("2"))); + row.append(new QStandardItem(QStringLiteral("3"))); + mod2.insertRow(0, row); + + // Then the proxy should notify its users and show changes + QCOMPARE(rowSpyToText(rowATBISpy), QStringLiteral("1,1")); + QCOMPARE(rowSpyToText(rowInsertedSpy), QStringLiteral("1,1")); + QCOMPARE(pm.rowCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF")); + + // When removing that row + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + mod2.removeRow(0); + + // Then the proxy should notify its users and show changes + QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); + QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + + // When removing the last row from mod2 + rowATBRSpy.clear(); + rowRemovedSpy.clear(); + mod2.removeRow(0); + + // Then the proxy should notify its users and show changes + QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); + QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); + QCOMPARE(pm.rowCount(), 1); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); +} + +void tst_QConcatenateTablesProxyModel::shouldAggregateAnotherModelThenRemoveModels() +{ + // Given two models combined, and a third model + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + + QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int))); + + // When adding the new source model + pm.addSourceModel(&mod3); + + // Then the proxy should notify its users about the two rows inserted + QCOMPARE(rowSpyToText(rowATBISpy), QStringLiteral("2,3")); + QCOMPARE(rowSpyToText(rowInsertedSpy), QStringLiteral("2,3")); + QCOMPARE(pm.rowCount(), 4); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("456")); + + // When removing that source model again + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + pm.removeSourceModel(&mod3); + + // Then the proxy should notify its users about the row removed + QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 2); + QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 3); + QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 2); + QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 3); + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + + // When removing model 2 + rowATBRSpy.clear(); + rowRemovedSpy.clear(); + pm.removeSourceModel(&mod2); + QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1); + QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1); + QCOMPARE(pm.rowCount(), 1); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + + // When removing model 1 + rowATBRSpy.clear(); + rowRemovedSpy.clear(); + pm.removeSourceModel(&mod); + QCOMPARE(rowATBRSpy.count(), 1); + QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 0); + QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 0); + QCOMPARE(rowRemovedSpy.count(), 1); + QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 0); + QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 0); + QCOMPARE(pm.rowCount(), 0); +} + +void tst_QConcatenateTablesProxyModel::shouldUseSmallestColumnCount() +{ + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + pm.addSourceModel(&mod2); + mod2.setColumnCount(1); + pm.addSourceModel(&mod3); + QAbstractItemModelTester modelTest(&pm, this); + + QCOMPARE(pm.rowCount(), 4); + QCOMPARE(pm.columnCount(), 1); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("A")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("D")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("1")); + QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("4")); + + const QModelIndex indexA = pm.mapFromSource(mod.index(0, 0)); + QVERIFY(indexA.isValid()); + QCOMPARE(indexA, pm.index(0, 0)); + + const QModelIndex indexB = pm.mapFromSource(mod.index(0, 1)); + QVERIFY(!indexB.isValid()); + + const QModelIndex indexD = pm.mapFromSource(mod2.index(0, 0)); + QVERIFY(indexD.isValid()); + QCOMPARE(indexD, pm.index(1, 0)); +} + +void tst_QConcatenateTablesProxyModel::shouldIncreaseColumnCountWhenRemovingFirstModel() +{ + // Given a model with 2 columns and one with 3 columns + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + QAbstractItemModelTester modelTest(&pm, this); + mod.setColumnCount(2); + pm.addSourceModel(&mod2); + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(pm.columnCount(), 2); + + QSignalSpy colATBISpy(&pm, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy colInsertedSpy(&pm, SIGNAL(columnsInserted(QModelIndex,int,int))); + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + + // When removing the first source model + pm.removeSourceModel(&mod); + + // Then the proxy should notify its users about the row removed, and the column added + QCOMPARE(pm.rowCount(), 1); + QCOMPARE(pm.columnCount(), 3); + QCOMPARE(rowSpyToText(rowATBRSpy), QStringLiteral("0,0")); + QCOMPARE(rowSpyToText(rowRemovedSpy), QStringLiteral("0,0")); + QCOMPARE(rowSpyToText(colATBISpy), QStringLiteral("2,2")); + QCOMPARE(rowSpyToText(colInsertedSpy), QStringLiteral("2,2")); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("DEF")); +} + +void tst_QConcatenateTablesProxyModel::shouldHandleColumnInsertionAndRemoval() +{ + // Given two models combined, one with 2 columns and one with 3 + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + QAbstractItemModelTester modelTest(&pm, this); + mod.setColumnCount(2); + pm.addSourceModel(&mod2); + QSignalSpy colATBISpy(&pm, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy colInsertedSpy(&pm, SIGNAL(columnsInserted(QModelIndex,int,int))); + QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int))); + + // When the first source model inserts a new column + QCOMPARE(mod.columnCount(), 2); + mod.setColumnCount(3); + + // Then the proxy should notify its users and show changes + QCOMPARE(rowSpyToText(colATBISpy), QStringLiteral("2,2")); + QCOMPARE(rowSpyToText(colInsertedSpy), QStringLiteral("2,2")); + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(pm.columnCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("AB ")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + + // And when removing two columns + mod.setColumnCount(1); + + // Then the proxy should notify its users and show changes + QCOMPARE(rowSpyToText(colATBRSpy), QStringLiteral("1,2")); + QCOMPARE(rowSpyToText(colRemovedSpy), QStringLiteral("1,2")); + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(pm.columnCount(), 1); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("A")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("D")); +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateLayoutChanged() +{ + // Given two source models, the second one being a QSFPM + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + QAbstractItemModelTester modelTest(&pm, this); + + QSortFilterProxyModel qsfpm; + qsfpm.setSourceModel(&mod3); + pm.addSourceModel(&qsfpm); + + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456")); + + // And a selection (row 1) + QItemSelectionModel selection(&pm); + selection.select(pm.index(1, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + const QModelIndexList lst = selection.selectedIndexes(); + QCOMPARE(lst.count(), 3); + for (int col = 0; col < lst.count(); ++col) { + QCOMPARE(lst.at(col).row(), 1); + QCOMPARE(lst.at(col).column(), col); + } + + QSignalSpy layoutATBCSpy(&pm, SIGNAL(layoutAboutToBeChanged())); + QSignalSpy layoutChangedSpy(&pm, SIGNAL(layoutChanged())); + + // When changing the sorting in the QSFPM + qsfpm.sort(0, Qt::DescendingOrder); + + // Then the proxy should emit the layoutChanged signals, and show re-sorted data + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123")); + QCOMPARE(layoutATBCSpy.count(), 1); + QCOMPARE(layoutChangedSpy.count(), 1); + + // And the selection should be updated accordingly (it became row 2) + const QModelIndexList lstAfter = selection.selectedIndexes(); + QCOMPARE(lstAfter.count(), 3); + for (int col = 0; col < lstAfter.count(); ++col) { + QCOMPARE(lstAfter.at(col).row(), 2); + QCOMPARE(lstAfter.at(col).column(), col); + } +} + +void tst_QConcatenateTablesProxyModel::shouldReactToModelReset() +{ + // Given two source models, the second one being a QSFPM + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod); + QAbstractItemModelTester modelTest(&pm, this); + + QSortFilterProxyModel qsfpm; + qsfpm.setSourceModel(&mod3); + pm.addSourceModel(&qsfpm); + + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456")); + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int))); + QSignalSpy modelATBResetSpy(&pm, SIGNAL(modelAboutToBeReset())); + QSignalSpy modelResetSpy(&pm, SIGNAL(modelReset())); + + // When changing the source model of the QSFPM + qsfpm.setSourceModel(&mod2); + + // Then the proxy should emit the reset signals, and show the new data + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + QCOMPARE(rowATBRSpy.count(), 0); + QCOMPARE(rowRemovedSpy.count(), 0); + QCOMPARE(rowATBISpy.count(), 0); + QCOMPARE(rowInsertedSpy.count(), 0); + QCOMPARE(colATBRSpy.count(), 0); + QCOMPARE(colRemovedSpy.count(), 0); + QCOMPARE(modelATBResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); +} + +void tst_QConcatenateTablesProxyModel::shouldUpdateColumnsOnModelReset() +{ + // Given two source models, the first one being a QSFPM + QConcatenateTablesProxyModel pm; + + QSortFilterProxyModel qsfpm; + qsfpm.setSourceModel(&mod3); + pm.addSourceModel(&qsfpm); + pm.addSourceModel(&mod); + QAbstractItemModelTester modelTest(&pm, this); + + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("ABC")); + + // ... and a model with only 2 columns + QStandardItemModel mod2Columns; + mod2Columns.appendRow({ new QStandardItem(QStringLiteral("W")), new QStandardItem(QStringLiteral("X")) }); + + QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); + QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int))); + QSignalSpy modelATBResetSpy(&pm, SIGNAL(modelAboutToBeReset())); + QSignalSpy modelResetSpy(&pm, SIGNAL(modelReset())); + + // When changing the source model of the QSFPM + qsfpm.setSourceModel(&mod2Columns); + + // Then the proxy should reset, and show the new data + QCOMPARE(modelATBResetSpy.count(), 1); + QCOMPARE(modelResetSpy.count(), 1); + QCOMPARE(rowATBRSpy.count(), 0); + QCOMPARE(rowRemovedSpy.count(), 0); + QCOMPARE(rowATBISpy.count(), 0); + QCOMPARE(rowInsertedSpy.count(), 0); + QCOMPARE(colATBRSpy.count(), 0); + QCOMPARE(colRemovedSpy.count(), 0); + + QCOMPARE(pm.rowCount(), 2); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("WX")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("AB")); +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropOnItem_data() +{ + QTest::addColumn<int>("sourceRow"); + QTest::addColumn<int>("destRow"); + QTest::addColumn<QString>("expectedResult"); + + QTest::newRow("0-3") << 0 << 3 << QStringLiteral("ABCA"); + QTest::newRow("1-2") << 1 << 2 << QStringLiteral("ABBD"); + QTest::newRow("2-1") << 2 << 1 << QStringLiteral("ACCD"); + QTest::newRow("3-0") << 3 << 0 << QStringLiteral("DBCD"); + +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropOnItem() +{ + // Given two source models who handle drops + + // Note: QStandardItemModel handles drop onto items by inserting child rows, + // which is good for QTreeView but not for QTableView or QConcatenateTablesProxyModel. + // So we use QStringListModel here instead. + QConcatenateTablesProxyModel pm; + QStringListModel model1({QStringLiteral("A"), QStringLiteral("B")}); + QStringListModel model2({QStringLiteral("C"), QStringLiteral("D")}); + pm.addSourceModel(&model1); + pm.addSourceModel(&model2); + QAbstractItemModelTester modelTest(&pm, this); + QCOMPARE(extractColumnTexts(&pm, 0), QStringLiteral("ABCD")); + + // When dragging one item + QFETCH(int, sourceRow); + QMimeData* mimeData = pm.mimeData({pm.index(sourceRow, 0)}); + QVERIFY(mimeData); + + // and dropping onto another item + QFETCH(int, destRow); + QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, -1, -1, pm.index(destRow, 0))); + QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, -1, -1, pm.index(destRow, 0))); + delete mimeData; + + // Then the result should be as expected + QFETCH(QString, expectedResult); + QCOMPARE(extractColumnTexts(&pm, 0), expectedResult); +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropBetweenItems() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod3); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QCOMPARE(pm.rowCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF")); + + // When dragging the last row + QModelIndexList indexes; + indexes.reserve(pm.columnCount()); + for (int col = 0; col < pm.columnCount(); ++col) { + indexes.append(pm.index(2, col)); + } + QMimeData* mimeData = pm.mimeData(indexes); + QVERIFY(mimeData); + + // and dropping it before row 1 + const int destRow = 1; + QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + delete mimeData; + + // Then a new row should be inserted + QCOMPARE(pm.rowCount(), 4); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("DEF")); +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropBetweenItemsAtModelBoundary() +{ + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod3); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QCOMPARE(pm.rowCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF")); + + // When dragging the first row + QModelIndexList indexes; + indexes.reserve(pm.columnCount()); + for (int col = 0; col < pm.columnCount(); ++col) { + indexes.append(pm.index(0, col)); + } + QMimeData* mimeData = pm.mimeData(indexes); + QVERIFY(mimeData); + + // and dropping it before row 2 + const int destRow = 2; + QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + delete mimeData; + + // Then a new row should be inserted + QCOMPARE(pm.rowCount(), 4); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("DEF")); + + // and it should be part of the second model + QCOMPARE(mod2.rowCount(), 2); +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow_data() +{ + QTest::addColumn<int>("destRow"); + + // Dropping after the last row is documented to be done with destRow == -1. + QTest::newRow("-1") << -1; + // However, sometimes QTreeView calls dropMimeData with destRow == rowCount... + // Not sure if that's a bug or not, but let's support it in the model, just in case. + QTest::newRow("3") << 3; +} + +void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow() +{ + QFETCH(int, destRow); + + // Given two models combined + QConcatenateTablesProxyModel pm; + pm.addSourceModel(&mod3); + pm.addSourceModel(&mod2); + QAbstractItemModelTester modelTest(&pm, this); + QCOMPARE(pm.rowCount(), 3); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF")); + + // When dragging the second row + QModelIndexList indexes; + indexes.reserve(pm.columnCount()); + for (int col = 0; col < pm.columnCount(); ++col) { + indexes.append(pm.index(1, col)); + } + QMimeData* mimeData = pm.mimeData(indexes); + QVERIFY(mimeData); + + // and dropping it after the last row + QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex())); + delete mimeData; + + // Then a new row should be inserted at the end + QCOMPARE(pm.rowCount(), 4); + QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123")); + QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456")); + QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF")); + QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("456")); + +} + +QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel) + +#include "tst_qconcatenatetablesproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp index 9a54c0a70d..16e5170a47 100644 --- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp +++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp @@ -82,8 +82,116 @@ private slots: void setData_emits_both_roles(); void supportedDragDropActions(); + + void moveRows_data(); + void moveRows(); + void moveRowsInvalid_data(); + void moveRowsInvalid(); + + void itemData(); + void setItemData(); }; +void tst_QStringListModel::moveRowsInvalid_data() +{ + QTest::addColumn<QStringListModel*>("baseModel"); + QTest::addColumn<QModelIndex>("startParent"); + QTest::addColumn<int>("startRow"); + QTest::addColumn<int>("count"); + QTest::addColumn<QModelIndex>("destinationParent"); + QTest::addColumn<int>("destination"); + + QStringListModel* tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("destination_equal_source") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << 1; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("count_equal_0") << tempModel << QModelIndex() << 0 << 0 << QModelIndex() << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("move_child") << tempModel << tempModel->index(0, 0) << 0 << 1 << QModelIndex() << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("move_to_child") << tempModel << QModelIndex() << 0 << 1 << tempModel->index(0, 0) << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("negative_count") << tempModel << QModelIndex() << 0 << -1 << QModelIndex() << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("negative_source_row") << tempModel << QModelIndex() << -1 << 1 << QModelIndex() << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("negative_destination_row") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << -1; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("source_row_equal_rowCount") << tempModel << QModelIndex() << tempModel->rowCount() << 1 << QModelIndex() << 1; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("destination_row_greater_rowCount") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << tempModel->rowCount() + 1; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("move_row_within_source_range") << tempModel << QModelIndex() << 0 << 3 << QModelIndex() << 2; + tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this); + QTest::addRow("destination_row_before_0") << tempModel << QModelIndex() << 1 << 1 << QModelIndex() << 0; +} + +void tst_QStringListModel::moveRowsInvalid() +{ + QFETCH(QStringListModel* const, baseModel); + QFETCH(const QModelIndex, startParent); + QFETCH(const int, startRow); + QFETCH(const int, count); + QFETCH(const QModelIndex, destinationParent); + QFETCH(const int, destination); + + QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved); + QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved); + QVERIFY(rowMovedSpy.isValid()); + QVERIFY(rowAboutMovedSpy.isValid()); + QVERIFY(!baseModel->moveRows(startParent, startRow, count, destinationParent, destination)); + QCOMPARE(rowMovedSpy.size(), 0); + QCOMPARE(rowAboutMovedSpy.size(), 0); + delete baseModel; +} + +void tst_QStringListModel::moveRows_data() +{ + QTest::addColumn<int>("startRow"); + QTest::addColumn<int>("count"); + QTest::addColumn<int>("destination"); + QTest::addColumn<QStringList>("expected"); + + QTest::newRow("1_Item_from_top_to_middle") << 0 << 1 << 3 << QStringList{"B", "C", "A", "D", "E", "F"}; + QTest::newRow("1_Item_from_top_to_bottom") << 0 << 1 << 6 << QStringList{"B", "C", "D", "E", "F", "A"}; + QTest::newRow("1_Item_from_middle_to_top") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("1_Item_from_bottom_to_middle") << 5 << 1 << 3 << QStringList{"A", "B", "F", "C", "D", "E"}; + QTest::newRow("1_Item_from_bottom to_top") << 5 << 1 << 1 << QStringList{"F", "A", "B", "C", "D", "E"}; + QTest::newRow("1_Item_from_middle_to_bottom") << 2 << 1 << 6 << QStringList{"A", "B", "D", "E", "F", "C"}; + QTest::newRow("1_Item_from_middle_to_middle_before") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("1_Item_from_middle_to_middle_after") << 2 << 1 << 4 << QStringList{"A", "B", "D", "C", "E", "F"}; + + QTest::newRow("2_Items_from_top_to_middle") << 0 << 2 << 3 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("2_Items_from_top_to_bottom") << 0 << 2 << 6 << QStringList{"C", "D", "E", "F", "A", "B"}; + QTest::newRow("2_Items_from_middle_to_top") << 2 << 2 << 1 << QStringList{"C", "D", "A", "B", "E", "F"}; + QTest::newRow("2_Items_from_bottom_to_middle") << 4 << 2 << 3 << QStringList{"A", "B", "E", "F", "C", "D"}; + QTest::newRow("2_Items_from_bottom_to_top") << 4 << 2 << 1 << QStringList{"E", "F", "A", "B", "C", "D"}; + QTest::newRow("2_Items_from_middle_to_bottom") << 2 << 2 << 6 << QStringList{"A", "B", "E", "F", "C", "D"}; + QTest::newRow("2_Items_from_middle_to_middle_before") << 3 << 2 << 2 << QStringList{"A", "D", "E", "B", "C", "F"}; + QTest::newRow("2_Items_from_middle_to_middle_after") << 1 << 2 << 5 << QStringList{"A", "D", "E", "B", "C", "F"}; +} + +void tst_QStringListModel::moveRows() +{ + QFETCH(const int, startRow); + QFETCH(const int, count); + QFETCH(const int, destination); + QFETCH(const QStringList, expected); + QStringListModel baseModel(QStringList{"A", "B", "C", "D", "E", "F"}); + QSignalSpy rowMovedSpy(&baseModel, &QAbstractItemModel::rowsMoved); + QSignalSpy rowAboutMovedSpy(&baseModel, &QAbstractItemModel::rowsAboutToBeMoved); + QVERIFY(baseModel.moveRows(QModelIndex(), startRow, count, QModelIndex(), destination)); + QCOMPARE(baseModel.stringList(), expected); + QCOMPARE(rowMovedSpy.size(), 1); + QCOMPARE(rowAboutMovedSpy.size(), 1); + for (const QList<QVariant> &signalArgs : {rowMovedSpy.first(), rowAboutMovedSpy.first()}){ + QVERIFY(!signalArgs.at(0).value<QModelIndex>().isValid()); + QCOMPARE(signalArgs.at(1).toInt(), startRow); + QCOMPARE(signalArgs.at(2).toInt(), startRow + count - 1); + QVERIFY(!signalArgs.at(3).value<QModelIndex>().isValid()); + QCOMPARE(signalArgs.at(4).toInt(), destination); + } +} + void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved_data() { QTest::addColumn<QStringList>("input"); @@ -246,6 +354,74 @@ void tst_QStringListModel::setData_emits_both_roles() expected); } +void tst_QStringListModel::itemData() +{ + QStringListModel testModel{ QStringList { + QStringLiteral("One"), + QStringLiteral("Two"), + QStringLiteral("Three"), + QStringLiteral("Four"), + QStringLiteral("Five") + }}; + QMap<int, QVariant> compareMap; + QCOMPARE(testModel.itemData(QModelIndex()), compareMap); + compareMap.insert(Qt::DisplayRole, QStringLiteral("Two")); + compareMap.insert(Qt::EditRole, QStringLiteral("Two")); + QCOMPARE(testModel.itemData(testModel.index(1, 0)), compareMap); +} + +void tst_QStringListModel::setItemData() +{ + QStringListModel testModel{ QStringList { + QStringLiteral("One"), + QStringLiteral("Two"), + QStringLiteral("Three"), + QStringLiteral("Four"), + QStringLiteral("Five") + }}; + QSignalSpy dataChangedSpy(&testModel, &QAbstractItemModel::dataChanged); + QModelIndex changeIndex = testModel.index(1, 0); + const QVector<int> changeRoles{Qt::DisplayRole, Qt::EditRole}; + const QString changedString("Changed"); + QMap<int, QVariant> newItemData{std::make_pair<int>(Qt::DisplayRole, changedString)}; + // invalid index does nothing and returns false + QVERIFY(!testModel.setItemData(QModelIndex(), newItemData)); + // valid data is set, return value is true and dataChanged is emitted once + QVERIFY(testModel.setItemData(changeIndex, newItemData)); + QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString); + QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString); + QCOMPARE(dataChangedSpy.size(), 1); + QVariantList dataChangedArguments = dataChangedSpy.takeFirst(); + QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex); + QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex); + QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles); + // Unsupported roles do nothing return false + newItemData.clear(); + newItemData.insert(Qt::UserRole, changedString); + QVERIFY(!testModel.setItemData(changeIndex, newItemData)); + QCOMPARE(dataChangedSpy.size(), 0); + // If some but not all the roles are supported it returns false and does nothing + newItemData.insert(Qt::EditRole, changedString); + changeIndex = testModel.index(2, 0); + QVERIFY(!testModel.setItemData(changeIndex, newItemData)); + QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), QStringLiteral("Three")); + QCOMPARE(changeIndex.data(Qt::EditRole).toString(), QStringLiteral("Three")); + QCOMPARE(dataChangedSpy.size(), 0); + // Qt::EditRole and Qt::DisplayRole are both set, Qt::EditRole takes precedence + newItemData.clear(); + newItemData.insert(Qt::EditRole, changedString); + newItemData.insert(Qt::DisplayRole, QStringLiteral("Ignored")); + changeIndex = testModel.index(3, 0); + QVERIFY(testModel.setItemData(changeIndex, newItemData)); + QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString); + QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString); + QCOMPARE(dataChangedSpy.size(), 1); + dataChangedArguments = dataChangedSpy.takeFirst(); + QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex); + QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex); + QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles); +} + void tst_QStringListModel::supportedDragDropActions() { QStringListModel model; diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 5d9b5ca95c..0c328dff58 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -73,6 +73,7 @@ private slots: void defined(); void threadSafety(); void namespaces(); + void id(); void qMetaTypeId(); void properties(); void normalizedTypes(); @@ -475,6 +476,12 @@ void tst_QMetaType::namespaces() QCOMPARE(QMetaType::typeName(qungTfuId), "TestSpace::QungTfu"); } +void tst_QMetaType::id() +{ + QCOMPARE(QMetaType(QMetaType::QString).id(), QMetaType::QString); + QCOMPARE(QMetaType(::qMetaTypeId<TestSpace::Foo>()).id(), ::qMetaTypeId<TestSpace::Foo>()); +} + void tst_QMetaType::qMetaTypeId() { QCOMPARE(::qMetaTypeId<QString>(), int(QMetaType::QString)); @@ -1814,13 +1821,6 @@ DECLARE_NONSTREAMABLE(void) DECLARE_NONSTREAMABLE(void*) DECLARE_NONSTREAMABLE(QModelIndex) DECLARE_NONSTREAMABLE(QPersistentModelIndex) -DECLARE_NONSTREAMABLE(QJsonValue) -DECLARE_NONSTREAMABLE(QJsonObject) -DECLARE_NONSTREAMABLE(QJsonArray) -DECLARE_NONSTREAMABLE(QJsonDocument) -DECLARE_NONSTREAMABLE(QCborValue) -DECLARE_NONSTREAMABLE(QCborArray) -DECLARE_NONSTREAMABLE(QCborMap) DECLARE_NONSTREAMABLE(QObject*) DECLARE_NONSTREAMABLE(QWidget*) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index effc82261b..936cbd3894 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -285,104 +285,100 @@ static void playWithObjects() void tst_QObject::disconnect() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; - connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); + connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1())); - connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) ); - connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) ); - connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) ); + connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2())); + connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3())); + connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4())); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); - QVERIFY(r1->called(1)); - QVERIFY(r1->called(2)); - QVERIFY(r1->called(3)); - QVERIFY(r1->called(4)); - r1->reset(); + QVERIFY(r1.called(1)); + QVERIFY(r1.called(2)); + QVERIFY(r1.called(3)); + QVERIFY(r1.called(4)); + r1.reset(); // usual disconnect with all parameters given - bool ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); + bool ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1())); - s->emitSignal1(); + s.emitSignal1(); - QVERIFY(!r1->called(1)); - r1->reset(); + QVERIFY(!r1.called(1)); + r1.reset(); QVERIFY(ret); - ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); + ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1())); QVERIFY(!ret); // disconnect all signals from s from all slots from r1 - QObject::disconnect( s, 0, r1, 0 ); + QObject::disconnect(&s, 0, &r1, 0); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); - QVERIFY(!r1->called(2)); - QVERIFY(!r1->called(3)); - QVERIFY(!r1->called(4)); - r1->reset(); + QVERIFY(!r1.called(2)); + QVERIFY(!r1.called(3)); + QVERIFY(!r1.called(4)); + r1.reset(); - connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); - connect( s, SIGNAL(signal1()), r1, SLOT(slot2()) ); - connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) ); - connect( s, SIGNAL(signal2()), r1, SLOT(slot4()) ); + connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1())); + connect(&s, SIGNAL(signal1()), &r1, SLOT(slot2())); + connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3())); + connect(&s, SIGNAL(signal2()), &r1, SLOT(slot4())); // disconnect s's signal1() from all slots of r1 - QObject::disconnect( s, SIGNAL(signal1()), r1, 0 ); + QObject::disconnect(&s, SIGNAL(signal1()), &r1, 0); - s->emitSignal1(); - s->emitSignal2(); + s.emitSignal1(); + s.emitSignal2(); - QVERIFY(!r1->called(1)); - QVERIFY(!r1->called(2)); - QVERIFY(!r1->called(3)); - QVERIFY(r1->called(4)); - r1->reset(); + QVERIFY(!r1.called(1)); + QVERIFY(!r1.called(2)); + QVERIFY(!r1.called(3)); + QVERIFY(r1.called(4)); + r1.reset(); // make sure all is disconnected again - QObject::disconnect( s, 0, r1, 0 ); + QObject::disconnect(&s, 0, &r1, 0); - connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); - connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) ); - connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) ); - connect( s, SIGNAL(signal2()), r2, SLOT(slot2()) ); - connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) ); - connect( s, SIGNAL(signal3()), r2, SLOT(slot3()) ); + connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1())); + connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1())); + connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2())); + connect(&s, SIGNAL(signal2()), &r2, SLOT(slot2())); + connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3())); + connect(&s, SIGNAL(signal3()), &r2, SLOT(slot3())); // disconnect signal1() from all receivers - QObject::disconnect( s, SIGNAL(signal1()), 0, 0 ); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); + QObject::disconnect(&s, SIGNAL(signal1()), 0, 0); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); - QVERIFY(!r1->called(1)); - QVERIFY(!r2->called(1)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); + QVERIFY(!r1.called(1)); + QVERIFY(!r2.called(1)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); // disconnect all signals of s from all receivers - QObject::disconnect( s, 0, 0, 0 ); + QObject::disconnect(&s, 0, 0, 0); - QVERIFY(!r1->called(2)); - QVERIFY(!r2->called(2)); - QVERIFY(!r1->called(2)); - QVERIFY(!r2->called(2)); - - delete r2; - delete r1; - delete s; + QVERIFY(!r1.called(2)); + QVERIFY(!r2.called(2)); + QVERIFY(!r1.called(2)); + QVERIFY(!r2.called(2)); } class AutoConnectSender : public QObject @@ -798,192 +794,197 @@ void tst_QObject::connectDisconnectNotify_data() void tst_QObject::connectDisconnectNotify() { - NotifyObject *s = new NotifyObject; - NotifyObject *r = new NotifyObject; + NotifyObject s; + NotifyObject r; QFETCH(QString, a_signal); QFETCH(QString, a_slot); // Obtaining meta methods - int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal( + int signalIndx = ((SenderObject &)s).metaObject()->indexOfSignal( QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData()); - int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod( + int methodIndx = ((ReceiverObject &)r).metaObject()->indexOfMethod( QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData()); - QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx); - QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx); + QMetaMethod signal = ((SenderObject &)s).metaObject()->method(signalIndx); + QMetaMethod method = ((ReceiverObject &)r).metaObject()->method(methodIndx); QVERIFY(signal.isValid()); QVERIFY(method.isValid()); // Test connectNotify - QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), + (ReceiverObject *)&r, a_slot.toLatin1())); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify - QVERIFY(QObject::disconnect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), signal); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(QObject::disconnect((SenderObject *)&s, a_signal.toLatin1(), + (ReceiverObject *)&r, a_slot.toLatin1())); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), signal); + QCOMPARE(s.connectedSignals.size(), 1); // Reconnect - s->clearNotifications(); - QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + s.clearNotifications(); + QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), + (ReceiverObject *)&r, a_slot.toLatin1())); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify for a complete disconnect - QVERIFY(((SenderObject*)s)->disconnect((ReceiverObject*)r)); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod()); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(((SenderObject *)&s)->disconnect((ReceiverObject *)&r)); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod()); + QCOMPARE(s.connectedSignals.size(), 1); // Test connectNotify when connecting by QMetaMethod - s->clearNotifications(); - QVERIFY(QObject::connect((SenderObject*)s, signal, (ReceiverObject*)r, method)); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + s.clearNotifications(); + QVERIFY(QObject::connect((SenderObject *)&s, signal, (ReceiverObject *)&r, method)); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by QMetaMethod - QVERIFY(QObject::disconnect((SenderObject*)s, signal, (ReceiverObject*)r, method)); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), signal); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(QObject::disconnect((SenderObject *)&s, signal, (ReceiverObject *)&r, method)); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), signal); + QCOMPARE(s.connectedSignals.size(), 1); // Reconnect - s->clearNotifications(); - QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); + s.clearNotifications(); + QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), + (ReceiverObject *)&r, a_slot.toLatin1())); // Test disconnectNotify for a complete disconnect by QMetaMethod - QVERIFY(QObject::disconnect((SenderObject*)s, QMetaMethod(), 0, QMetaMethod())); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod()); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(QObject::disconnect((SenderObject *)&s, QMetaMethod(), 0, QMetaMethod())); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod()); + QCOMPARE(s.connectedSignals.size(), 1); // Test connectNotify when connecting by index - s->clearNotifications(); - QVERIFY(QMetaObject::connect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx)); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + s.clearNotifications(); + QVERIFY(QMetaObject::connect((SenderObject *)&s, signalIndx, (ReceiverObject *)&r, methodIndx)); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by index - QVERIFY(QMetaObject::disconnect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx)); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), signal); - QCOMPARE(s->connectedSignals.size(), 1); - - delete s; - delete r; + QVERIFY(QMetaObject::disconnect((SenderObject *)&s, signalIndx, + (ReceiverObject *)&r, methodIndx)); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), signal); + QCOMPARE(s.connectedSignals.size(), 1); } static void connectDisconnectNotifyTestSlot() {} void tst_QObject::connectDisconnectNotifyPMF() { - NotifyObject *s = new NotifyObject; - NotifyObject *r = new NotifyObject; + NotifyObject s; + NotifyObject r; QMetaMethod signal = QMetaMethod::fromSignal(&SenderObject::signal1); // Test connectNotify - QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, + (ReceiverObject *)&r, &ReceiverObject::slot1)); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify - QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), signal); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1, + (ReceiverObject *)&r, &ReceiverObject::slot1)); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), signal); + QCOMPARE(s.connectedSignals.size(), 1); // Reconnect - s->clearNotifications(); - QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); + s.clearNotifications(); + QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, + (ReceiverObject *)&r, &ReceiverObject::slot1)); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify with wildcard slot - QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, 0)); - QCOMPARE(s->disconnectedSignals.size(), 1); - QCOMPARE(s->disconnectedSignals.at(0), signal); - QCOMPARE(s->connectedSignals.size(), 1); + QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1, + (ReceiverObject *)&r, 0)); + QCOMPARE(s.disconnectedSignals.size(), 1); + QCOMPARE(s.disconnectedSignals.at(0), signal); + QCOMPARE(s.connectedSignals.size(), 1); // Reconnect - s->clearNotifications(); - QMetaObject::Connection conn = connect((SenderObject*)s, &SenderObject::signal1, - (ReceiverObject*)r, &ReceiverObject::slot1); + s.clearNotifications(); + QMetaObject::Connection conn = connect((SenderObject *)&s, &SenderObject::signal1, + (ReceiverObject *)&r, &ReceiverObject::slot1); QVERIFY(conn); // Test disconnectNotify when disconnecting by QMetaObject::Connection QVERIFY(QObject::disconnect(conn)); - QVERIFY(!s->disconnectedSignals.isEmpty()); + QVERIFY(!s.disconnectedSignals.isEmpty()); // Test connectNotify when connecting by function pointer - s->clearNotifications(); - QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, connectDisconnectNotifyTestSlot)); - QCOMPARE(s->connectedSignals.size(), 1); - QCOMPARE(s->connectedSignals.at(0), signal); - QVERIFY(s->disconnectedSignals.isEmpty()); - - delete s; - delete r; + s.clearNotifications(); + QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, + connectDisconnectNotifyTestSlot)); + QCOMPARE(s.connectedSignals.size(), 1); + QCOMPARE(s.connectedSignals.at(0), signal); + QVERIFY(s.disconnectedSignals.isEmpty()); } void tst_QObject::disconnectNotify_receiverDestroyed() { - NotifyObject *s = new NotifyObject; - NotifyObject *r = new NotifyObject; - - QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal1()), (ReceiverObject*)r, SLOT(slot1()))); - - delete r; - QCOMPARE(s->disconnectedSignals.count(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); + NotifyObject s; - s->disconnectedSignals.clear(); - r = new NotifyObject; + { + NotifyObject r; + QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal1()), + (ReceiverObject *)&r, SLOT(slot1()))); + } + QCOMPARE(s.disconnectedSignals.count(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); - QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal3()), (ReceiverObject*)r, SLOT(slot3()))); + s.disconnectedSignals.clear(); - delete r; - QCOMPARE(s->disconnectedSignals.count(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3)); + { + NotifyObject r; + QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal3()), + (ReceiverObject *)&r, SLOT(slot3()))); + } - s->disconnectedSignals.clear(); - r = new NotifyObject; + QCOMPARE(s.disconnectedSignals.count(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3)); - QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(destroyed()), (ReceiverObject*)r, SLOT(slot3()))); + s.disconnectedSignals.clear(); - delete r; - QCOMPARE(s->disconnectedSignals.count(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed)); + { + NotifyObject r; + QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(destroyed()), (ReceiverObject *)&r, SLOT(slot3()))); + } - delete s; + QCOMPARE(s.disconnectedSignals.count(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed)); } void tst_QObject::disconnectNotify_metaObjConnection() { - NotifyObject *s = new NotifyObject; - NotifyObject *r = new NotifyObject; - - QMetaObject::Connection c = QObject::connect((SenderObject*)s, SIGNAL(signal1()), - (ReceiverObject*)r, SLOT(slot1())); - QVERIFY(c); - QVERIFY(QObject::disconnect(c)); + NotifyObject s; + { + NotifyObject r; - QCOMPARE(s->disconnectedSignals.count(), 1); - QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); + QMetaObject::Connection c = QObject::connect((SenderObject *)&s, SIGNAL(signal1()), + (ReceiverObject *)&r, SLOT(slot1())); + QVERIFY(c); + QVERIFY(QObject::disconnect(c)); - delete r; - QCOMPARE(s->disconnectedSignals.count(), 1); + QCOMPARE(s.disconnectedSignals.count(), 1); + QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); - delete s; + QCOMPARE(s.disconnectedSignals.count(), 1); + } } class ConnectByNameNotifySenderObject : public QObject @@ -3463,130 +3464,131 @@ void tst_QObject::qobjectConstCast() void tst_QObject::uniqConnection() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; - r1->reset(); - r2->reset(); + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) , Qt::UniqueConnection) ); - QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) , Qt::UniqueConnection) ); - QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) , Qt::UniqueConnection) ); - QVERIFY( connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) , Qt::UniqueConnection) ); + QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()) , Qt::UniqueConnection) ); + QVERIFY(connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()) , Qt::UniqueConnection) ); + QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()) , Qt::UniqueConnection) ); + QVERIFY(connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()) , Qt::UniqueConnection) ); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 2 ); - QCOMPARE( r1->count_slot4, 0 ); - QCOMPARE( r2->count_slot1, 1 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); - QCOMPARE( r2->count_slot4, 0 ); - QCOMPARE( r1->sequence_slot1, 1 ); - QCOMPARE( r2->sequence_slot1, 2 ); - QCOMPARE( r1->sequence_slot3, 4 ); - - r1->reset(); - r2->reset(); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 2); + QCOMPARE(r1.count_slot4, 0); + QCOMPARE(r2.count_slot1, 1); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + QCOMPARE(r2.count_slot4, 0); + QCOMPARE(r1.sequence_slot1, 1); + QCOMPARE(r2.sequence_slot1, 2); + QCOMPARE(r1.sequence_slot3, 4); + + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - QVERIFY( connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) ); - QVERIFY( connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); - QVERIFY(!connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); - QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); - QVERIFY(!connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) ); + QVERIFY( connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection)); + QVERIFY( connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); + QVERIFY(!connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); + QVERIFY( connect(&s, SIGNAL(signal1()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); + QVERIFY(!connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection)); - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 1 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 1 ); - QCOMPARE( r2->sequence_slot4, 2 ); + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 1); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 1); + QCOMPARE(r2.sequence_slot4, 2); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) ); - - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 2 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 3 ); - QCOMPARE( r2->sequence_slot4, 2 ); + connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4())); - delete s; - delete r1; - delete r2; + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 2); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 3); + QCOMPARE(r2.sequence_slot4, 2); } void tst_QObject::uniqConnectionPtr() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; - r1->reset(); - r2->reset(); + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) ); - QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) ); - QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) ); - QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) ); + QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1 , + Qt::UniqueConnection)); + QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot1 , + Qt::UniqueConnection)); + QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot3 , + Qt::UniqueConnection)); + QVERIFY(connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3 , + Qt::UniqueConnection)); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 2 ); - QCOMPARE( r1->count_slot4, 0 ); - QCOMPARE( r2->count_slot1, 1 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); - QCOMPARE( r2->count_slot4, 0 ); - QCOMPARE( r1->sequence_slot1, 1 ); - QCOMPARE( r2->sequence_slot1, 2 ); - QCOMPARE( r1->sequence_slot3, 4 ); - - r1->reset(); - r2->reset(); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 2); + QCOMPARE(r1.count_slot4, 0); + QCOMPARE(r2.count_slot1, 1); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + QCOMPARE(r2.count_slot4, 0); + QCOMPARE(r1.sequence_slot1, 1); + QCOMPARE(r2.sequence_slot1, 2); + QCOMPARE(r1.sequence_slot3, 4); + + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) ); - QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); - QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); - QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); - QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) ); + QVERIFY( connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 , + Qt::UniqueConnection)); + QVERIFY( connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 , + Qt::UniqueConnection)); + QVERIFY(!connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 , + Qt::UniqueConnection)); + QVERIFY( connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4 , + Qt::UniqueConnection)); + QVERIFY(!connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 , + Qt::UniqueConnection)); - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 1 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 1 ); - QCOMPARE( r2->sequence_slot4, 2 ); + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 1); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 1); + QCOMPARE(r2.sequence_slot4, 2); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ); + connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4); - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 2 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 3 ); - QCOMPARE( r2->sequence_slot4, 2 ); - - delete s; - delete r1; - delete r2; + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 2); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 3); + QCOMPARE(r2.sequence_slot4, 2); } void tst_QObject::interfaceIid() @@ -3890,217 +3892,214 @@ void tst_QObject::isSignalConnectedAfterDisconnection() void tst_QObject::qMetaObjectConnect() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; - r1->reset(); - r2->reset(); - ReceiverObject::sequence = 0; - - int signal1Index = s->metaObject()->indexOfSignal("signal1()"); - int signal3Index = s->metaObject()->indexOfSignal("signal3()"); - int slot1Index = r1->metaObject()->indexOfSlot("slot1()"); - int slot2Index = r1->metaObject()->indexOfSlot("slot2()"); - int slot3Index = r1->metaObject()->indexOfSlot("slot3()"); - - QVERIFY(slot1Index > 0); - QVERIFY(slot2Index > 0); - QVERIFY(slot3Index > 0); - - QVERIFY( QMetaObject::connect( s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::connect( s, signal3Index, r2, slot3Index) ); - QVERIFY( QMetaObject::connect( s, -1, r2, slot2Index) ); - - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 0 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); - - s->emitSignal1(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 0 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 1 ); - QCOMPARE( r2->count_slot3, 0 ); - - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 0 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 4 ); - QCOMPARE( r2->count_slot3, 1 ); - - QVERIFY( QMetaObject::disconnect( s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::disconnect( s, signal3Index, r2, slot3Index) ); - QVERIFY( QMetaObject::disconnect( s, -1, r2, slot2Index) ); - - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 0 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 4 ); - QCOMPARE( r2->count_slot3, 1 ); - - //some "dynamic" signal - QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 20, r1, slot3Index) ); - QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 35, r2, slot1Index) ); - QVERIFY( QMetaObject::connect( s, -1, r1, slot2Index) ); - - r1->reset(); - r2->reset(); - - void *args[] = { 0 , 0 }; - QMetaObject::activate(s, s->metaObject()->methodOffset() + 20, args); - QMetaObject::activate(s, s->metaObject()->methodOffset() + 48, args); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 2 ); - QCOMPARE( r1->count_slot3, 1 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); - - QMetaObject::activate(s, s->metaObject()->methodOffset() + 35, args); - s->emitSignal1(); - s->emitSignal2(); - - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 5 ); - QCOMPARE( r1->count_slot3, 1 ); - QCOMPARE( r2->count_slot1, 1 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); + ReceiverObject r1; + ReceiverObject r2; + int slot1Index, slot2Index, slot3Index; + { + SenderObject s; + r1.reset(); + r2.reset(); + ReceiverObject::sequence = 0; + + int signal1Index = s.metaObject()->indexOfSignal("signal1()"); + int signal3Index = s.metaObject()->indexOfSignal("signal3()"); + slot1Index = r1.metaObject()->indexOfSlot("slot1()"); + slot2Index = r1.metaObject()->indexOfSlot("slot2()"); + slot3Index = r1.metaObject()->indexOfSlot("slot3()"); + + QVERIFY(slot1Index > 0); + QVERIFY(slot2Index > 0); + QVERIFY(slot3Index > 0); + + QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index)); + QVERIFY(QMetaObject::connect(&s, signal3Index, &r2, slot3Index)); + QVERIFY(QMetaObject::connect(&s, -1, &r2, slot2Index)); + + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 0); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + + s.emitSignal1(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 0); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 1); + QCOMPARE(r2.count_slot3, 0); + + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 0); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 4); + QCOMPARE(r2.count_slot3, 1); + + QVERIFY(QMetaObject::disconnect(&s, signal1Index, &r1, slot1Index)); + QVERIFY(QMetaObject::disconnect(&s, signal3Index, &r2, slot3Index)); + QVERIFY(QMetaObject::disconnect(&s, -1, &r2, slot2Index)); + + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 0); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 4); + QCOMPARE(r2.count_slot3, 1); + + //some "dynamic" signal + QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 20, &r1, slot3Index)); + QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 35, &r2, slot1Index)); + QVERIFY(QMetaObject::connect(&s, -1, &r1, slot2Index)); + + r1.reset(); + r2.reset(); + + void *args[] = { 0 , 0 }; + QMetaObject::activate(&s, s.metaObject()->methodOffset() + 20, args); + QMetaObject::activate(&s, s.metaObject()->methodOffset() + 48, args); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 2); + QCOMPARE(r1.count_slot3, 1); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + + QMetaObject::activate(&s, s.metaObject()->methodOffset() + 35, args); + s.emitSignal1(); + s.emitSignal2(); + + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 5); + QCOMPARE(r1.count_slot3, 1); + QCOMPARE(r2.count_slot1, 1); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + } - delete s; - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); #define SIGNAL_INDEX(S) obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S)) OverloadObject obj1; QObject obj2, obj3; - QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , r1, slot1Index); - QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , r2, slot1Index); + QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , &r1, slot1Index); + QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , + &r2, slot1Index); - QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r1, slot2Index); - QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , r2, slot2Index); - QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , r1, slot3Index); + QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , + &r1, slot2Index); + QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , &r2, slot2Index); + QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , &r1, slot3Index); emit obj1.sig(0.5); //connected to nothing emit obj1.sig(1, 'a'); //connected to nothing - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 0 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 0); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); emit obj1.sig(1); //this signal is connected emit obj1.sig(&obj2); - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 1 ); - QCOMPARE( r2->count_slot1, 0 ); - QCOMPARE( r2->count_slot2, 1 ); - QCOMPARE( r2->count_slot3, 0 ); + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 1); + QCOMPARE(r2.count_slot1, 0); + QCOMPARE(r2.count_slot2, 1); + QCOMPARE(r2.count_slot3, 0); emit obj1.sig(&obj2, &obj3); //this signal is connected - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 1 ); - QCOMPARE( r1->count_slot3, 1 ); - QCOMPARE( r2->count_slot1, 1 ); - QCOMPARE( r2->count_slot2, 1 ); - QCOMPARE( r2->count_slot3, 0 ); - - delete r1; - delete r2; - + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 1); + QCOMPARE(r1.count_slot3, 1); + QCOMPARE(r2.count_slot1, 1); + QCOMPARE(r2.count_slot2, 1); + QCOMPARE(r2.count_slot3, 0); } void tst_QObject::qMetaObjectDisconnectOne() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; + SenderObject s; + ReceiverObject r1; - int signal1Index = s->metaObject()->indexOfSignal("signal1()"); - int signal3Index = s->metaObject()->indexOfSignal("signal3()"); - int slot1Index = r1->metaObject()->indexOfSlot("slot1()"); - int slot2Index = r1->metaObject()->indexOfSlot("slot2()"); + int signal1Index = s.metaObject()->indexOfSignal("signal1()"); + int signal3Index = s.metaObject()->indexOfSignal("signal3()"); + int slot1Index = r1.metaObject()->indexOfSlot("slot1()"); + int slot2Index = r1.metaObject()->indexOfSlot("slot2()"); QVERIFY(signal1Index > 0); QVERIFY(signal3Index > 0); QVERIFY(slot1Index > 0); QVERIFY(slot2Index > 0); - QVERIFY( QMetaObject::connect(s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); - QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); - QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); - - r1->reset(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index)); + QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); + QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); + QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); - s->emitSignal1(); - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); + r1.reset(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); - s->emitSignal3(); - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 3 ); + s.emitSignal1(); + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); - r1->reset(); - QVERIFY( QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); + s.emitSignal3(); + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 3); - s->emitSignal1(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + r1.reset(); + QVERIFY(QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); + QVERIFY(QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); - s->emitSignal3(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 2 ); + s.emitSignal1(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); - r1->reset(); - QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); + s.emitSignal3(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 2); - s->emitSignal1(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + r1.reset(); + QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); + QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); - s->emitSignal3(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 1 ); + s.emitSignal1(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); - r1->reset(); - QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); - QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); + s.emitSignal3(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 1); - s->emitSignal1(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + r1.reset(); + QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); + QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); - s->emitSignal3(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + s.emitSignal1(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); - delete s; - delete r1; + s.emitSignal3(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); } class ConfusingObject : public SenderObject @@ -4222,106 +4221,95 @@ void tst_QObject::connectConstructorByMetaMethod() void tst_QObject::disconnectByMetaMethod() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; - - QMetaMethod signal1 = s->metaObject()->method( - s->metaObject()->indexOfMethod("signal1()")); - QMetaMethod signal2 = s->metaObject()->method( - s->metaObject()->indexOfMethod("signal2()")); - QMetaMethod signal3 = s->metaObject()->method( - s->metaObject()->indexOfMethod("signal3()")); - - QMetaMethod slot1 = r1->metaObject()->method( - r1->metaObject()->indexOfMethod("slot1()")); - QMetaMethod slot2 = r1->metaObject()->method( - r1->metaObject()->indexOfMethod("slot2()")); - QMetaMethod slot3 = r1->metaObject()->method( - r1->metaObject()->indexOfMethod("slot3()")); - QMetaMethod slot4 = r1->metaObject()->method( - r1->metaObject()->indexOfMethod("slot4()")); - - connect(s, signal1, r1, slot1); + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; - s->emitSignal1(); + QMetaMethod signal1 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal1()")); + QMetaMethod signal2 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal2()")); + QMetaMethod signal3 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal3()")); + + QMetaMethod slot1 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot1()")); + QMetaMethod slot2 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot2()")); + QMetaMethod slot3 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot3()")); + QMetaMethod slot4 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot4()")); + + connect(&s, signal1, &r1, slot1); - QVERIFY(r1->called(1)); - r1->reset(); + s.emitSignal1(); + + QVERIFY(r1.called(1)); + r1.reset(); // usual disconnect with all parameters given - bool ret = QObject::disconnect(s, signal1, r1, slot1); + bool ret = QObject::disconnect(&s, signal1, &r1, slot1); - s->emitSignal1(); + s.emitSignal1(); - QVERIFY(!r1->called(1)); - r1->reset(); + QVERIFY(!r1.called(1)); + r1.reset(); QVERIFY(ret); - ret = QObject::disconnect(s, signal1, r1, slot1); + ret = QObject::disconnect(&s, signal1, &r1, slot1); QVERIFY(!ret); - r1->reset(); + r1.reset(); - connect( s, signal1, r1, slot1 ); - connect( s, signal1, r1, slot2 ); - connect( s, signal1, r1, slot3 ); - connect( s, signal2, r1, slot4 ); + connect(&s, signal1, &r1, slot1); + connect(&s, signal1, &r1, slot2); + connect(&s, signal1, &r1, slot3); + connect(&s, signal2, &r1, slot4); // disconnect s's signal1() from all slots of r1 - QObject::disconnect(s, signal1, r1, QMetaMethod()); + QObject::disconnect(&s, signal1, &r1, QMetaMethod()); - s->emitSignal1(); - s->emitSignal2(); + s.emitSignal1(); + s.emitSignal2(); - QVERIFY(!r1->called(1)); - QVERIFY(!r1->called(2)); - QVERIFY(!r1->called(3)); - QVERIFY(r1->called(4)); - r1->reset(); + QVERIFY(!r1.called(1)); + QVERIFY(!r1.called(2)); + QVERIFY(!r1.called(3)); + QVERIFY(r1.called(4)); + r1.reset(); // make sure all is disconnected again - QObject::disconnect(s, 0, r1, 0); + QObject::disconnect(&s, 0, &r1, 0); - connect(s, signal1, r1, slot1); - connect(s, signal1, r2, slot1); - connect(s, signal2, r1, slot2); - connect(s, signal2, r2, slot2); - connect(s, signal3, r1, slot3); - connect(s, signal3, r2, slot3); + connect(&s, signal1, &r1, slot1); + connect(&s, signal1, &r2, slot1); + connect(&s, signal2, &r1, slot2); + connect(&s, signal2, &r2, slot2); + connect(&s, signal3, &r1, slot3); + connect(&s, signal3, &r2, slot3); // disconnect signal1() from all receivers - QObject::disconnect(s, signal1, 0, QMetaMethod()); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); + QObject::disconnect(&s, signal1, 0, QMetaMethod()); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); - QVERIFY(!r1->called(1)); - QVERIFY(!r2->called(1)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); + QVERIFY(!r1.called(1)); + QVERIFY(!r2.called(1)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); // disconnect all signals of s from all receivers - QObject::disconnect( s, 0, 0, 0 ); + QObject::disconnect(&s, 0, 0, 0); - connect( s, signal1, r1, slot1 ); - connect( s, signal1, r2, slot1 ); + connect(&s, signal1, &r1, slot1); + connect(&s, signal1, &r2, slot1); // disconnect all signals from slot1 of r1 - QObject::disconnect(s, QMetaMethod(), r1, slot1); + QObject::disconnect(&s, QMetaMethod(), &r1, slot1); - s->emitSignal1(); - - QVERIFY(!r1->called(1)); - QVERIFY(r2->called(1)); + s.emitSignal1(); - delete r2; - delete r1; - delete s; + QVERIFY(!r1.called(1)); + QVERIFY(r2.called(1)); } void tst_QObject::disconnectNotSignalMetaMethod() @@ -4459,63 +4447,64 @@ void tst_QObject::baseDestroyed() void tst_QObject::pointerConnect() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; - r1->reset(); - r2->reset(); + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; QTimer timer; - QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot1 ) ); - QVERIFY( connect( s, &SenderObject::signal1 , r2, &ReceiverObject::slot1 ) ); - QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot3 ) ); - QVERIFY( connect( s, &SenderObject::signal3 , r1, &ReceiverObject::slot3 ) ); - QVERIFY2( connect( &timer, &QTimer::timeout, r1, &ReceiverObject::deleteLater ), - "Signal connection failed most likely due to failing comparison of pointers to member functions caused by problems with -reduce-relocations on this platform."); + QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot1)); + QVERIFY(connect(&s, &SenderObject::signal1 , &r2, &ReceiverObject::slot1)); + QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot3)); + QVERIFY(connect(&s, &SenderObject::signal3 , &r1, &ReceiverObject::slot3)); + QVERIFY2(connect(&timer, &QTimer::timeout, &r1, &ReceiverObject::deleteLater), + "Signal connection failed most likely due to failing comparison of pointers to member " + "functions caused by problems with -reduce-relocations on this platform."); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); - - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); - QCOMPARE( r1->count_slot3, 2 ); - QCOMPARE( r1->count_slot4, 0 ); - QCOMPARE( r2->count_slot1, 1 ); - QCOMPARE( r2->count_slot2, 0 ); - QCOMPARE( r2->count_slot3, 0 ); - QCOMPARE( r2->count_slot4, 0 ); - QCOMPARE( r1->sequence_slot1, 1 ); - QCOMPARE( r2->sequence_slot1, 2 ); - QCOMPARE( r1->sequence_slot3, 4 ); - - r1->reset(); - r2->reset(); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); + + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); + QCOMPARE(r1.count_slot3, 2); + QCOMPARE(r1.count_slot4, 0); + QCOMPARE(r2.count_slot1, 1); + QCOMPARE(r2.count_slot2, 0); + QCOMPARE(r2.count_slot3, 0); + QCOMPARE(r2.count_slot4, 0); + QCOMPARE(r1.sequence_slot1, 1); + QCOMPARE(r2.sequence_slot1, 2); + QCOMPARE(r1.sequence_slot3, 4); + + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ) ); - QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 ) ); - QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 ) ); + QVERIFY(connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4)); + QVERIFY(connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4)); + QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4)); - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 1 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 1 ); - QCOMPARE( r2->sequence_slot4, 2 ); + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 1); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 1); + QCOMPARE(r2.sequence_slot4, 2); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); ReceiverObject::sequence = 0; - connect( s, &SenderObject::signal4 , r1, &ReceiverObject::slot4 ); + connect(&s, &SenderObject::signal4 , &r1, &ReceiverObject::slot4); - s->emitSignal4(); - QCOMPARE( r1->count_slot4, 2 ); - QCOMPARE( r2->count_slot4, 1 ); - QCOMPARE( r1->sequence_slot4, 3 ); - QCOMPARE( r2->sequence_slot4, 2 ); + s.emitSignal4(); + QCOMPARE(r1.count_slot4, 2); + QCOMPARE(r2.count_slot4, 1); + QCOMPARE(r1.sequence_slot4, 3); + QCOMPARE(r2.sequence_slot4, 2); QMetaObject::Connection con; QVERIFY(!con); @@ -4523,116 +4512,107 @@ void tst_QObject::pointerConnect() //connect a slot to a signal (== error) QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject"); - con = connect(r1, &ReceiverObject::slot4 , s, &SenderObject::signal4 ); + con = connect(&r1, &ReceiverObject::slot4 , &s, &SenderObject::signal4); QVERIFY(!con); QVERIFY(!QObject::disconnect(con)); - - delete s; - delete r1; - delete r2; } void tst_QObject::pointerDisconnect() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; - ReceiverObject *r2 = new ReceiverObject; + SenderObject s; + ReceiverObject r1; + ReceiverObject r2; - connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); + connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); - connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 ); - connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 ); - connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ); + connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot2); + connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3); + connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); - QVERIFY(r1->called(1)); - QVERIFY(r1->called(2)); - QVERIFY(r1->called(3)); - QVERIFY(r1->called(4)); - r1->reset(); + QVERIFY(r1.called(1)); + QVERIFY(r1.called(2)); + QVERIFY(r1.called(3)); + QVERIFY(r1.called(4)); + r1.reset(); // usual disconnect with all parameters given - bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); + bool ret = QObject::disconnect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); - s->emitSignal1(); + s.emitSignal1(); - QVERIFY(!r1->called(1)); - r1->reset(); + QVERIFY(!r1.called(1)); + r1.reset(); QVERIFY(ret); - ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); + ret = QObject::disconnect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); QVERIFY(!ret); // disconnect all signals from s from all slots from r1 - QObject::disconnect( s, 0, r1, 0 ); + QObject::disconnect(&s, 0, &r1, 0); - s->emitSignal2(); - s->emitSignal3(); - s->emitSignal4(); + s.emitSignal2(); + s.emitSignal3(); + s.emitSignal4(); - QVERIFY(!r1->called(2)); - QVERIFY(!r1->called(3)); - QVERIFY(!r1->called(4)); - r1->reset(); + QVERIFY(!r1.called(2)); + QVERIFY(!r1.called(3)); + QVERIFY(!r1.called(4)); + r1.reset(); - connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); - connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 ); - connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 ); - connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 ); + connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); + connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot2); + connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot3); + connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot4); // disconnect s's signal1() from all slots of r1 - QObject::disconnect( s, &SenderObject::signal1, r1, 0 ); + QObject::disconnect(&s, &SenderObject::signal1, &r1, 0); - s->emitSignal1(); - s->emitSignal2(); + s.emitSignal1(); + s.emitSignal2(); - QVERIFY(!r1->called(1)); - QVERIFY(!r1->called(2)); - QVERIFY(!r1->called(3)); - QVERIFY(r1->called(4)); - r1->reset(); + QVERIFY(!r1.called(1)); + QVERIFY(!r1.called(2)); + QVERIFY(!r1.called(3)); + QVERIFY(r1.called(4)); + r1.reset(); // make sure all is disconnected again - QObject::disconnect( s, 0, r1, 0 ); + QObject::disconnect(&s, 0, &r1, 0); - connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); - connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 ); - connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 ); - connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 ); - connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 ); - connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 ); + connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); + connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot1); + connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot2); + connect(&s, &SenderObject::signal2, &r2, &ReceiverObject::slot2); + connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3); + connect(&s, &SenderObject::signal3, &r2, &ReceiverObject::slot3); // disconnect signal1() from all receivers - QObject::disconnect( s, &SenderObject::signal1, 0, 0 ); - s->emitSignal1(); - s->emitSignal2(); - s->emitSignal3(); + QObject::disconnect(&s, &SenderObject::signal1, 0, 0); + s.emitSignal1(); + s.emitSignal2(); + s.emitSignal3(); - QVERIFY(!r1->called(1)); - QVERIFY(!r2->called(1)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); - QVERIFY(r1->called(2)); - QVERIFY(r2->called(2)); + QVERIFY(!r1.called(1)); + QVERIFY(!r2.called(1)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); + QVERIFY(r1.called(2)); + QVERIFY(r2.called(2)); - r1->reset(); - r2->reset(); + r1.reset(); + r2.reset(); // disconnect all signals of s from all receivers - QObject::disconnect( s, 0, 0, 0 ); - - QVERIFY(!r1->called(2)); - QVERIFY(!r2->called(2)); - QVERIFY(!r1->called(2)); - QVERIFY(!r2->called(2)); - - delete r2; - delete r1; - delete s; + QObject::disconnect(&s, 0, 0, 0); + QVERIFY(!r1.called(2)); + QVERIFY(!r2.called(2)); + QVERIFY(!r1.called(2)); + QVERIFY(!r2.called(2)); } @@ -4756,35 +4736,32 @@ void tst_QObject::customTypesPointer() void tst_QObject::connectCxx0x() { - SenderObject *s = new SenderObject; - ReceiverObject *r1 = new ReceiverObject; + SenderObject s; + ReceiverObject r1; - QObject::connect(s, &SenderObject::signal1, r1, &ReceiverObject::slot1); - QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); - QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); - QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); + QObject::connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1); + QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2); + QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2); + QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2); - r1->reset(); - QCOMPARE( r1->count_slot1, 0 ); - QCOMPARE( r1->count_slot2, 0 ); + r1.reset(); + QCOMPARE(r1.count_slot1, 0); + QCOMPARE(r1.count_slot2, 0); - s->emitSignal1(); - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 0 ); + s.emitSignal1(); + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 0); - s->emitSignal3(); - QCOMPARE( r1->count_slot1, 1 ); - QCOMPARE( r1->count_slot2, 3 ); + s.emitSignal3(); + QCOMPARE(r1.count_slot1, 1); + QCOMPARE(r1.count_slot2, 3); // connect signal to signal - QObject::connect(s, &SenderObject::signal2, s, &SenderObject::signal1); + QObject::connect(&s, &SenderObject::signal2, &s, &SenderObject::signal1); - r1->reset(); - s->emitSignal2(); - QCOMPARE( r1->count_slot1, 1 ); - - delete s; - delete r1; + r1.reset(); + s.emitSignal2(); + QCOMPARE(r1.count_slot1, 1); } int receivedCount; diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro index 541e73636c..5efe68f4af 100644 --- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro +++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro @@ -3,6 +3,7 @@ TEMPLATE = subdirs tst.depends = lib theplugin SUBDIRS = lib \ + staticplugin \ theplugin \ tst !android:!win32:!darwin { diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore b/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore new file mode 100644 index 0000000000..26f7ecd506 --- /dev/null +++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore @@ -0,0 +1,3 @@ +*staticplugin.prl +libstaticplugin.a +staticplugin.lib diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp new file mode 100644 index 0000000000..d891839b1e --- /dev/null +++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Intel Corporation. +** 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$ +** +****************************************************************************/ +#include <QtPlugin> +#include <QObject> + +class StaticPlugin : public QObject +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "SomeIID") +public: + StaticPlugin() {} +}; + +#include "main.moc" diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro b/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro new file mode 100644 index 0000000000..ff65ab728c --- /dev/null +++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro @@ -0,0 +1,7 @@ +TEMPLATE = lib +CONFIG += plugin static +SOURCES = main.cpp +QT = core + +# Add extra metadata to the plugin +QMAKE_MOC_OPTIONS += -M ExtraMetaData=StaticPlugin -M ExtraMetaData=foo diff --git a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro index c20e56ba4c..a3885f4134 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro +++ b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro @@ -8,9 +8,14 @@ HEADERS = ../theplugin/plugininterface.h win32 { CONFIG(debug, debug|release) { TARGET = ../../debug/tst_qpluginloader + LIBS += -L../staticplugin/debug } else { TARGET = ../../release/tst_qpluginloader + LIBS += -L../staticplugin/release } +} else { + LIBS += -L../staticplugin } +LIBS += -lstaticplugin TESTDATA += ../elftest ../machtest diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp index c517c0809a..4316ea14ea 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -121,8 +121,11 @@ private slots: void reloadPlugin(); void preloadedPlugin_data(); void preloadedPlugin(); + void staticPlugins(); }; +Q_IMPORT_PLUGIN(StaticPlugin) + void tst_QPluginLoader::cleanup() { // check if the library/plugin was leaked @@ -520,5 +523,37 @@ void tst_QPluginLoader::preloadedPlugin() QVERIFY(lib.unload()); } +void tst_QPluginLoader::staticPlugins() +{ + const QObjectList instances = QPluginLoader::staticInstances(); + QVERIFY(instances.size()); + + bool found = false; + for (QObject *obj : instances) { + found = obj->metaObject()->className() == QLatin1String("StaticPlugin"); + if (found) + break; + } + QVERIFY(found); + + const auto plugins = QPluginLoader::staticPlugins(); + QCOMPARE(plugins.size(), instances.size()); + + // find the metadata + QJsonObject metaData; + for (const auto &p : plugins) { + metaData = p.metaData(); + found = metaData.value("className").toString() == QLatin1String("StaticPlugin"); + if (found) + break; + } + QVERIFY(found); + + QCOMPARE(metaData.value("version").toInt(), QT_VERSION); + QCOMPARE(metaData.value("IID").toString(), "SomeIID"); + QCOMPARE(metaData.value("ExtraMetaData"), QJsonArray({ "StaticPlugin", "foo" })); +} + + QTEST_MAIN(tst_QPluginLoader) #include "tst_qpluginloader.moc" diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index 4651258ef3..083e78375a 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -153,6 +153,17 @@ private Q_SLOTS: void implicitValueType(); void implicitDocumentType(); + void streamSerializationQJsonDocument_data(); + void streamSerializationQJsonDocument(); + void streamSerializationQJsonArray_data(); + void streamSerializationQJsonArray(); + void streamSerializationQJsonObject_data(); + void streamSerializationQJsonObject(); + void streamSerializationQJsonValue_data(); + void streamSerializationQJsonValue(); + void streamSerializationQJsonValueEmpty(); + void streamVariantSerialization(); + private: QString testDataDir; }; @@ -3011,5 +3022,164 @@ void tst_QtJson::implicitDocumentType() QCOMPARE(arrayDocument[-1].toInt(123), 123); } +void tst_QtJson::streamSerializationQJsonDocument_data() +{ + QTest::addColumn<QJsonDocument>("document"); + QTest::newRow("empty") << QJsonDocument(); + QTest::newRow("object") << QJsonDocument(QJsonObject{{"value", 42}}); +} + +void tst_QtJson::streamSerializationQJsonDocument() +{ + // Check interface only, implementation is tested through to and from + // json functions. + QByteArray buffer; + QFETCH(QJsonDocument, document); + QJsonDocument output; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << document; + QDataStream load(buffer); + load >> output; + QCOMPARE(output, document); +} + +void tst_QtJson::streamSerializationQJsonArray_data() +{ + QTest::addColumn<QJsonArray>("array"); + QTest::newRow("empty") << QJsonArray(); + QTest::newRow("values") << QJsonArray{665, 666, 667}; +} + +void tst_QtJson::streamSerializationQJsonArray() +{ + // Check interface only, implementation is tested through to and from + // json functions. + QByteArray buffer; + QFETCH(QJsonArray, array); + QJsonArray output; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << array; + QDataStream load(buffer); + load >> output; + QCOMPARE(output, array); +} + +void tst_QtJson::streamSerializationQJsonObject_data() +{ + QTest::addColumn<QJsonObject>("object"); + QTest::newRow("empty") << QJsonObject(); + QTest::newRow("non-empty") << QJsonObject{{"foo", 665}, {"bar", 666}}; +} + +void tst_QtJson::streamSerializationQJsonObject() +{ + // Check interface only, implementation is tested through to and from + // json functions. + QByteArray buffer; + QFETCH(QJsonObject, object); + QJsonObject output; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << object; + QDataStream load(buffer); + load >> output; + QCOMPARE(output, object); +} + +void tst_QtJson::streamSerializationQJsonValue_data() +{ + QTest::addColumn<QJsonValue>("value"); + QTest::newRow("double") << QJsonValue{665}; + QTest::newRow("bool") << QJsonValue{true}; + QTest::newRow("string") << QJsonValue{QStringLiteral("bum")}; + QTest::newRow("array") << QJsonValue{QJsonArray{12,1,5,6,7}}; + QTest::newRow("object") << QJsonValue{QJsonObject{{"foo", 665}, {"bar", 666}}}; +} + +void tst_QtJson::streamSerializationQJsonValue() +{ + QByteArray buffer; + QFETCH(QJsonValue, value); + QJsonValue output; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << value; + QDataStream load(buffer); + load >> output; + QCOMPARE(output, value); +} + +void tst_QtJson::streamSerializationQJsonValueEmpty() +{ + QByteArray buffer; + { + QJsonValue undef{QJsonValue::Undefined}; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << undef; + QDataStream load(buffer); + QJsonValue output; + load >> output; + QVERIFY(output.isUndefined()); + } + { + QJsonValue null{QJsonValue::Null}; + QDataStream save(&buffer, QIODevice::WriteOnly); + save << null; + QDataStream load(buffer); + QJsonValue output; + load >> output; + QVERIFY(output.isNull()); + } +} + +void tst_QtJson::streamVariantSerialization() +{ + // Check interface only, implementation is tested through to and from + // json functions. + QByteArray buffer; + { + QJsonDocument objectDoc(QJsonArray{665, 666, 667}); + QVariant output; + QVariant variant(objectDoc); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QJsonDocument); + QCOMPARE(output.toJsonDocument(), objectDoc); + } + { + QJsonArray array{665, 666, 667}; + QVariant output; + QVariant variant(array); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QJsonArray); + QCOMPARE(output.toJsonArray(), array); + } + { + QJsonObject obj{{"foo", 42}}; + QVariant output; + QVariant variant(obj); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QJsonObject); + QCOMPARE(output.toJsonObject(), obj); + } + { + QJsonValue value{42}; + QVariant output; + QVariant variant(value); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QJsonValue); + QCOMPARE(output.toJsonValue(), value); + } +} + QTEST_MAIN(tst_QtJson) #include "tst_qtjson.moc" diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index 4b753eab6b..c609aa6621 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -97,6 +97,10 @@ private slots: void validation(); void toDiagnosticNotation_data(); void toDiagnosticNotation(); + + void datastreamSerialization_data(); + void datastreamSerialization(); + void streamVariantSerialization(); }; // Get the validation data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp) @@ -1690,6 +1694,83 @@ void tst_QCborValue::toDiagnosticNotation() QCOMPARE(result, expected); } + +void tst_QCborValue::datastreamSerialization_data() +{ + addCommonCborData(); +} + +void tst_QCborValue::datastreamSerialization() +{ + QFETCH(QCborValue, v); + QByteArray buffer; + { + QDataStream save(&buffer, QIODevice::WriteOnly); + save << v; + QDataStream load(buffer); + QCborValue output; + load >> output; + QCOMPARE(output, v); + } + if (v.isArray()) { + QCborArray array = v.toArray(); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << array; + QDataStream load(buffer); + QCborValue output; + load >> output; + QCOMPARE(output, array); + } else if (v.isMap()) { + QCborMap map = v.toMap(); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << map; + QDataStream load(buffer); + QCborValue output; + load >> output; + QCOMPARE(output, map); + } +} + +void tst_QCborValue::streamVariantSerialization() +{ + // Check interface only, implementation is tested through to and from + // cbor functions. + QByteArray buffer; + { + QCborArray array{665, 666, 667}; + QVariant output; + QVariant variant = QVariant::fromValue(array); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QCborArray); + QCOMPARE(qvariant_cast<QCborArray>(output), array); + } + { + QCborMap obj{{"foo", 42}}; + QVariant output; + QVariant variant = QVariant::fromValue(obj); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QCborMap); + QCOMPARE(qvariant_cast<QCborMap>(output), obj); + } + { + QCborValue value{42}; + QVariant output; + QVariant variant = QVariant::fromValue(value); + QDataStream save(&buffer, QIODevice::WriteOnly); + save << variant; + QDataStream load(buffer); + load >> output; + QCOMPARE(output.userType(), QMetaType::QCborValue); + QCOMPARE(qvariant_cast<QCborValue>(output), value); + } +} + QTEST_MAIN(tst_QCborValue) #include "tst_qcborvalue.moc" diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index 011a0e1a85..d204727bbd 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -135,6 +135,15 @@ private slots: void stream_QByteArray2(); + void stream_QJsonDocument(); + void stream_QJsonArray(); + void stream_QJsonObject(); + void stream_QJsonValue(); + + void stream_QCborArray(); + void stream_QCborMap(); + void stream_QCborValue(); + void setVersion_data(); void setVersion(); @@ -2095,6 +2104,138 @@ void tst_QDataStream::stream_QByteArray2() } } +void tst_QDataStream::stream_QJsonDocument() +{ + QByteArray buffer; + { + QDataStream save(&buffer, QIODevice::WriteOnly); + save << QByteArrayLiteral("invalidJson"); + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonDocument doc; + load >> doc; + QVERIFY(doc.isEmpty()); + QVERIFY(load.status() != QDataStream::Ok); + QCOMPARE(load.status(), QDataStream::ReadCorruptData); + } + { + QDataStream save(&buffer, QIODevice::WriteOnly); + QJsonDocument docSave(QJsonArray{1,2,3}); + save << docSave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonDocument docLoad; + load >> docLoad; + QCOMPARE(docLoad, docSave); + } +} + +void tst_QDataStream::stream_QJsonArray() +{ + QByteArray buffer; + { + QDataStream save(&buffer, QIODevice::WriteOnly); + save << QByteArrayLiteral("invalidJson"); + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonArray array; + load >> array; + QVERIFY(array.isEmpty()); + QVERIFY(load.status() != QDataStream::Ok); + QCOMPARE(load.status(), QDataStream::ReadCorruptData); + } + { + QDataStream save(&buffer, QIODevice::WriteOnly); + QJsonArray arraySave(QJsonArray{1,2,3}); + save << arraySave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonArray arrayLoad; + load >> arrayLoad; + QCOMPARE(arrayLoad, arraySave); + } +} + +void tst_QDataStream::stream_QJsonObject() +{ + QByteArray buffer; + { + QDataStream save(&buffer, QIODevice::WriteOnly); + save << QByteArrayLiteral("invalidJson"); + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonObject object; + load >> object; + QVERIFY(object.isEmpty()); + QVERIFY(load.status() != QDataStream::Ok); + QCOMPARE(load.status(), QDataStream::ReadCorruptData); + } + { + QDataStream save(&buffer, QIODevice::WriteOnly); + QJsonObject objSave{{"foo", 1}, {"bar", 2}}; + save << objSave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonObject objLoad; + load >> objLoad; + QCOMPARE(objLoad, objSave); + } +} + +void tst_QDataStream::stream_QJsonValue() +{ + QByteArray buffer; + { + QDataStream save(&buffer, QIODevice::WriteOnly); + save << quint8(42); + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonValue value; + load >> value; + QVERIFY(value.isUndefined()); + QVERIFY(load.status() != QDataStream::Ok); + QCOMPARE(load.status(), QDataStream::ReadCorruptData); + } + { + QDataStream save(&buffer, QIODevice::WriteOnly); + QJsonValue valueSave{42}; + save << valueSave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QJsonValue valueLoad; + load >> valueLoad; + QCOMPARE(valueLoad, valueSave); + } +} + +void tst_QDataStream::stream_QCborArray() +{ + QByteArray buffer; + QDataStream save(&buffer, QIODevice::WriteOnly); + QCborArray arraySave({1, 2, 3}); + save << arraySave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QCborArray arrayLoad; + load >> arrayLoad; + QCOMPARE(arrayLoad, arraySave); +} + +void tst_QDataStream::stream_QCborMap() +{ + QByteArray buffer; + QDataStream save(&buffer, QIODevice::WriteOnly); + QCborMap objSave{{"foo", 1}, {"bar", 2}}; + save << objSave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QCborMap objLoad; + load >> objLoad; + QCOMPARE(objLoad, objSave); +} + +void tst_QDataStream::stream_QCborValue() +{ + QByteArray buffer; + QDataStream save(&buffer, QIODevice::WriteOnly); + QCborValue valueSave{42}; + save << valueSave; + QDataStream load(&buffer, QIODevice::ReadOnly); + QCborValue valueLoad; + load >> valueLoad; + QCOMPARE(valueLoad, valueSave); +} + void tst_QDataStream::setVersion_data() { QTest::addColumn<int>("vers"); diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp index edea4713a1..1c1631760b 100644 --- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp @@ -2662,28 +2662,30 @@ void tst_QTextStream::useCase2() // ------------------------------------------------------------------------------ void tst_QTextStream::manipulators_data() { - QTest::addColumn<int>("flags"); + QTest::addColumn<int>("base"); + QTest::addColumn<int>("alignFlag"); + QTest::addColumn<int>("numberFlag"); QTest::addColumn<int>("width"); QTest::addColumn<double>("realNumber"); QTest::addColumn<int>("intNumber"); QTest::addColumn<QString>("textData"); QTest::addColumn<QByteArray>("result"); - QTest::newRow("no flags") << 0 << 0 << 5.0 << 5 << QString("five") << QByteArray("55five"); - QTest::newRow("rightadjust") << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray(" 5 5 five"); - - // ### FIX -// QTest::newRow("leftadjust") << int(QTextStream::left) << 10 << 5.0 << 5 << QString("five") << QByteArray("5 5 five "); -// QTest::newRow("showpos") << int(QTextStream::showpos) << 10 << 5.0 << 5 << QString("five") << QByteArray(" +5 +5 five"); -// QTest::newRow("showpos2") << int(QTextStream::showpos) << 5 << 3.14 << -5 << QString("five") << QByteArray("+3.14 -5 five"); -// QTest::newRow("hex") << int(QTextStream::hex | QTextStream::showbase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0x5 five"); -// QTest::newRow("hex uppercase") << int(QTextStream::hex | QTextStream::uppercase | QTextStream::showbase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0X5 five"); + QTest::newRow("no flags") << 10 << 0 << 0 << 0 << 5.0 << 5 << QString("five") << QByteArray("55five"); + QTest::newRow("rightadjust") << 10 << int(QTextStream::AlignRight) << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray(" 5 5 five"); + QTest::newRow("leftadjust") << 10 << int(QTextStream::AlignLeft) << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray("5 5 five "); + QTest::newRow("showpos") << 10 << int(QTextStream::AlignRight) << int(QTextStream::ForceSign) << 10 << 5.0 << 5 << QString("five") << QByteArray(" +5 +5 five"); + QTest::newRow("showpos2") << 10 << int(QTextStream::AlignRight) << int(QTextStream::ForceSign) << 5 << 3.14 << -5 << QString("five") << QByteArray("+3.14 -5 five"); + QTest::newRow("hex") << 16 << int(QTextStream::AlignRight) << int(QTextStream::ShowBase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0x5 five"); + QTest::newRow("hex") << 16 << int(QTextStream::AlignRight) << int(QTextStream::ShowBase | QTextStream::UppercaseBase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0X5 five"); } // ------------------------------------------------------------------------------ void tst_QTextStream::manipulators() { -// QFETCH(int, flags); + QFETCH(int, base); + QFETCH(int, alignFlag); + QFETCH(int, numberFlag); QFETCH(int, width); QFETCH(double, realNumber); QFETCH(int, intNumber); @@ -2697,14 +2699,16 @@ void tst_QTextStream::manipulators() stream.setCodec(QTextCodec::codecForName("ISO-8859-1")); stream.setAutoDetectUnicode(true); -// stream.setFlags(flags); + stream.setIntegerBase(base); + stream.setFieldAlignment(QTextStream::FieldAlignment(alignFlag)); + stream.setNumberFlags(QTextStream::NumberFlag(numberFlag)); stream.setFieldWidth(width); stream << realNumber; stream << intNumber; stream << textData; stream.flush(); - QCOMPARE(buffer.data().constData(), result.constData()); + QCOMPARE(buffer.data(), result); } void tst_QTextStream::generateBOM() diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 943805e228..56792f38fb 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -37,9 +37,6 @@ #ifdef Q_OS_WIN # include <qt_windows.h> -# if defined(Q_OS_WINRT) -# define tzset() -# endif #endif class tst_QDateTime : public QObject @@ -145,9 +142,7 @@ private slots: void isDaylightTime() const; void daylightTransitions() const; void timeZones() const; -#if defined(Q_OS_UNIX) void systemTimeZoneChange() const; -#endif void invalid() const; @@ -174,7 +169,7 @@ private: void reset(const QByteArray &zone) { qputenv("TZ", zone.constData()); - tzset(); + qTzSet(); } ~TimeZoneRollback() { @@ -182,7 +177,7 @@ private: qunsetenv("TZ"); else qputenv("TZ", prior.constData()); - tzset(); + qTzSet(); } }; }; @@ -3412,33 +3407,10 @@ void tst_QDateTime::timeZones() const QCOMPARE(future.offsetFromUtc(), 28800); } -#if defined(Q_OS_UNIX) -// Currently disabled on Windows as adjusting the timezone -// requires additional privileges that aren't normally -// enabled for a process. This can be achieved by calling -// AdjustTokenPrivileges() and then SetTimeZoneInformation(), -// which will require linking to a different library to access that API. -static void setTimeZone(const QByteArray &tz) -{ - qputenv("TZ", tz); - ::tzset(); - -// following left for future reference, see comment above -// #if defined(Q_OS_WIN32) -// ::_tzset(); -// #endif -} - void tst_QDateTime::systemTimeZoneChange() const { - struct ResetTZ { - QByteArray original; - ResetTZ() : original(qgetenv("TZ")) {} - ~ResetTZ() { setTimeZone(original); } - } scopedReset; - // Set the timezone to Brisbane time - setTimeZone(QByteArray("AEST-10:00")); + TimeZoneRollback useZone(QByteArray("AEST-10:00")); QDateTime localDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime); QDateTime utcDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC); @@ -3451,16 +3423,18 @@ void tst_QDateTime::systemTimeZoneChange() const QVERIFY(tzDate.timeZone().isValid()); // Change to Indian time - setTimeZone(QByteArray("IST-05:30")); + useZone.reset(QByteArray("IST-05:30")); QCOMPARE(localDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime)); +#ifdef Q_OS_WINRT + QEXPECT_FAIL("", "WinRT gets this wrong, QTBUG-71185", Continue); +#endif QVERIFY(localMsecs != localDate.toMSecsSinceEpoch()); QCOMPARE(utcDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC)); QCOMPARE(utcDate.toMSecsSinceEpoch(), utcMsecs); QCOMPARE(tzDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane"))); QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs); } -#endif void tst_QDateTime::invalid() const { diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 261689d401..ff36beadcb 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -1869,9 +1869,11 @@ static void setWinLocaleInfo(LCTYPE type, const QString &value) # define LOCALE_SSHORTTIME 0x00000079 #endif -class RestoreLocaleHelper { +class RestoreLocaleHelper +{ public: - RestoreLocaleHelper() { + RestoreLocaleHelper() + { m_decimal = getWinLocaleInfo(LOCALE_SDECIMAL); m_thousand = getWinLocaleInfo(LOCALE_STHOUSAND); m_sdate = getWinLocaleInfo(LOCALE_SSHORTDATE); @@ -1879,7 +1881,8 @@ public: m_time = getWinLocaleInfo(LOCALE_SSHORTTIME); } - ~RestoreLocaleHelper() { + ~RestoreLocaleHelper() + { // restore these, or the user will get a surprise setWinLocaleInfo(LOCALE_SDECIMAL, m_decimal); setWinLocaleInfo(LOCALE_STHOUSAND, m_thousand); @@ -1887,12 +1890,10 @@ public: setWinLocaleInfo(LOCALE_SLONGDATE, m_ldate); setWinLocaleInfo(LOCALE_SSHORTTIME, m_time); - // make sure QLocale::system() gets updated - QLocalePrivate::updateSystemPrivate(); + QSystemLocale dummy; // to provoke a refresh of the system locale } QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; - }; void tst_QLocale::windowsDefaultLocale() @@ -1908,8 +1909,7 @@ void tst_QLocale::windowsDefaultLocale() const QString shortTimeFormat = QStringLiteral("h^m^s"); setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat); - // make sure QLocale::system() gets updated - QLocalePrivate::updateSystemPrivate(); + QSystemLocale dummy; // to provoke a refresh of the system locale QLocale locale = QLocale::system(); // make sure we are seeing the system's format strings @@ -2650,9 +2650,11 @@ void tst_QLocale::textDirection_data() case QLocale::Sabaean: case QLocale::Samaritan: case QLocale::Sindhi: + case QLocale::SouthernKurdish: case QLocale::Syriac: case QLocale::Uighur: case QLocale::Urdu: + case QLocale::WesternBalochi: case QLocale::Yiddish: // false if there is no locale data for language: rightToLeft = (QLocale(QLocale::Language(language)).language() diff --git a/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro b/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro new file mode 100644 index 0000000000..c8e6a8e05a --- /dev/null +++ b/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro @@ -0,0 +1,6 @@ +CONFIG += testcase +TARGET = tst_qoffsetstringarray +QT = core testlib core-private +CONFIG += c++11 +CONFIG += strict_c++ +SOURCES = $$PWD/tst_qoffsetstringarray.cpp diff --git a/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp new file mode 100644 index 0000000000..dfa0450b18 --- /dev/null +++ b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <private/qoffsetstringarray_p.h> + + +class tst_QOffsetStringArray : public QObject +{ + Q_OBJECT + +private slots: + void init(); + void access(); +}; + + +constexpr const auto messages = qOffsetStringArray( + "level - 0", + "level - 1", + "level - 2", + "level - 3", + "level - 4", + "" +); + +constexpr const auto messages257 = qOffsetStringArray( + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "end" +); + +constexpr const auto messagesBigOffsets = qOffsetStringArray( + " 10 20 30 40 50 60 70 80 90", + " 10 20 30 40 50 60 70 80 90", + " 10 20 30 40 50 60 70 80 90", + " 10 20 30 40 50 60 70 80 90" +); + +void tst_QOffsetStringArray::init() +{ + static_assert(messages.sizeString == 51, "message.sizeString"); + static_assert(messages.sizeOffsets == 6, "message.sizeOffsets"); + static_assert(std::is_same<decltype(messages)::Type, quint8>::value, "messages::Type != quint8"); + + static_assert(messages257.sizeOffsets == 257, "messages257.sizeOffsets"); + static_assert(messages257.sizeString == 260, "messages257.sizeString"); + static_assert(std::is_same<decltype(messages257)::Type, quint16>::value, + "messages257::Type != quint16"); + + static_assert(messagesBigOffsets.sizeOffsets == 4, "messagesBigOffsets.sizeOffsets"); + static_assert(messagesBigOffsets.sizeString == 364, "messagesBigOffsets.sizeString"); + static_assert(std::is_same<decltype(messagesBigOffsets)::Type, quint16>::value, + "messagesBigOffsets::Type != quint16"); +} + +void tst_QOffsetStringArray::access() +{ + QCOMPARE(messages[0], "level - 0"); + QCOMPARE(messages[1], "level - 1"); + QCOMPARE(messages[2], "level - 2"); + QCOMPARE(messages[3], "level - 3"); + QCOMPARE(messages[4], "level - 4"); + QCOMPARE(messages[5], ""); + QCOMPARE(messages[6], ""); +} + + +QTEST_APPLESS_MAIN(tst_QOffsetStringArray) +#include "tst_qoffsetstringarray.moc" diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index f28cf21b8b..2a975e67d1 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -35,6 +35,7 @@ SUBDIRS=\ qmap_strictiterators \ qmargins \ qmessageauthenticationcode \ + qoffsetstringarray \ qpair \ qpoint \ qpointf \ diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp index cca0e95c29..b2572188b9 100644 --- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -49,6 +49,8 @@ private slots: void construct(); void constructCopy_data(); void constructCopy(); + void saveAndLoadBuiltin_data(); + void saveAndLoadBuiltin(); }; #define FOR_EACH_GUI_METATYPE_BASE(F) \ @@ -442,5 +444,49 @@ FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION) TypeTestFunctionGetter::get(type)(); } +template <typename T> +struct StreamingTraits +{ + // Streamable by default, as currently all gui built-in types are streamable + enum { isStreamable = 1 }; +}; + +void tst_QGuiMetaType::saveAndLoadBuiltin_data() +{ + QTest::addColumn<int>("type"); + QTest::addColumn<bool>("isStreamable"); + +#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ + QTest::newRow(#RealType) << MetaTypeId << bool(StreamingTraits<RealType>::isStreamable); + QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) +#undef ADD_METATYPE_TEST_ROW +} + +void tst_QGuiMetaType::saveAndLoadBuiltin() +{ + QFETCH(int, type); + QFETCH(bool, isStreamable); + + void *value = QMetaType::create(type); + + QByteArray ba; + QDataStream stream(&ba, QIODevice::ReadWrite); + QCOMPARE(QMetaType::save(stream, type, value), isStreamable); + QCOMPARE(stream.status(), QDataStream::Ok); + + if (isStreamable) + QVERIFY(QMetaType::load(stream, type, value)); + + stream.device()->seek(0); + stream.resetStatus(); + QCOMPARE(QMetaType::load(stream, type, value), isStreamable); + QCOMPARE(stream.status(), QDataStream::Ok); + + if (isStreamable) + QVERIFY(QMetaType::load(stream, type, value)); + + QMetaType::destroy(type, value); +} + QTEST_MAIN(tst_QGuiMetaType) #include "tst_qguimetatype.moc" diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp index cfd24a8701..7dbeb13aa7 100644 --- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp +++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp @@ -835,17 +835,32 @@ void tst_QCssParser::colorValue_data() QTest::newRow("hexcolor") << "color: #12af0e" << QColor(0x12, 0xaf, 0x0e); QTest::newRow("functional1") << "color: rgb(21, 45, 73)" << QColor(21, 45, 73); QTest::newRow("functional2") << "color: rgb(100%, 0%, 100%)" << QColor(0xff, 0, 0xff); + QTest::newRow("rgb") << "color: rgb(10, 20, 30)" << QColor(10, 20, 30); QTest::newRow("rgba") << "color: rgba(10, 20, 30, 40)" << QColor(10, 20, 30, 40); QTest::newRow("rgbaf") << "color: rgba(10, 20, 30, 0.5)" << QColor(10, 20, 30, 127); - QTest::newRow("rgb") << "color: rgb(10, 20, 30, 40)" << QColor(10, 20, 30, 40); - QTest::newRow("hsl") << "color: hsv(10, 20, 30)" << QColor::fromHsv(10, 20, 30, 255); - QTest::newRow("hsla") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40); + QTest::newRow("hsv") << "color: hsv(10, 20, 30)" << QColor::fromHsv(10, 20, 30); + QTest::newRow("hsva") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40); + // the percent and float values are well chosen to not get in trouble due to rounding errors + QTest::newRow("hsva-percent") << "color: hsva(100%, 20%, 40%, 60%)" << QColor::fromHsv(359, 51, 102, 153); + QTest::newRow("hsva-float") << "color: hsva(180, 20%, 40%, 0.6)" << QColor::fromHsvF(0.5, 0.2, 0.4, 0.6); + QTest::newRow("hsl") << "color: hsl(60, 100%, 50%)" << QColor::fromHsl(60., 255, 127); + QTest::newRow("hsla") << "color: hsla(240, 255, 127, 192)" << QColor::fromHsl(240, 255, 127, 192); + QTest::newRow("hsla-percent") << "color: hsla(100%, 80%, 40%, 0%)" << QColor::fromHsl(359, 204, 102, 0); + QTest::newRow("hsla-float") << "color: hsla(252, 40%, 60%, 0.2)" << QColor::fromHslF(0.7, 0.4, 0.6, 0.2); QTest::newRow("invalid1") << "color: rgb(why, does, it, always, rain, on, me)" << QColor(); QTest::newRow("invalid2") << "color: rgba(i, meant, norway)" << QColor(); QTest::newRow("invalid3") << "color: rgb(21)" << QColor(); + QTest::newRow("invalid4") << "color: rgbx(1, 2, 3)" << QColor(); + QTest::newRow("invalid5") << "color: rgbax(1, 2, 3, 4)" << QColor(); + QTest::newRow("invalid6") << "color: hsv(360, 0, 0)" << QColor(); + QTest::newRow("invalid7") << "color: hsla(1, a, 1, 21)" << QColor(); QTest::newRow("role") << "color: palette(base)" << qApp->palette().color(QPalette::Base); QTest::newRow("role2") << "color: palette( window-text ) " << qApp->palette().color(QPalette::WindowText); QTest::newRow("transparent") << "color: transparent" << QColor(Qt::transparent); + + // ### Qt6: no longer valid + QTest::newRow("rgb-invalid") << "color: rgb(10, 20, 30, 40)" << QColor(10, 20, 30, 40); + QTest::newRow("rgba-invalid") << "color: rgba(10, 20, 30)" << QColor(10, 20, 30, 255); } void tst_QCssParser::colorValue() diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp index b7f014d0e2..1429e4cb7f 100644 --- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp +++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp @@ -491,10 +491,6 @@ void tst_QGlyphRun::drawMultiScriptText2() drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png"); #endif -#ifdef Q_OS_OSX - if (drawGlyphs.toImage() != textLayoutDraw.toImage()) - QEXPECT_FAIL("", "See QTBUG-32690", Continue); -#endif // Q_OS_OSX QCOMPARE(drawGlyphs, textLayoutDraw); } diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h index a3c318420f..4225ff11c7 100644 --- a/tests/auto/network-settings.h +++ b/tests/auto/network-settings.h @@ -176,7 +176,7 @@ public: static QString ftpServerName() { -#ifdef QT_TEST_SERVER +#ifdef QT_TEST_SERVER_NAME return QString("vsftpd.") % serverDomainName(); #else return serverName(); @@ -184,7 +184,7 @@ public: } static QString ftpProxyServerName() { -#ifdef QT_TEST_SERVER +#ifdef QT_TEST_SERVER_NAME return QString("ftp-proxy.") % serverDomainName(); #else return serverName(); @@ -192,7 +192,7 @@ public: } static QString httpServerName() { -#ifdef QT_TEST_SERVER +#ifdef QT_TEST_SERVER_NAME return QString("apache2.") % serverDomainName(); #else return serverName(); @@ -200,7 +200,7 @@ public: } static QString httpProxyServerName() { -#ifdef QT_TEST_SERVER +#ifdef QT_TEST_SERVER_NAME return QString("squid.") % serverDomainName(); #else return serverName(); @@ -208,7 +208,7 @@ public: } static QString socksProxyServerName() { -#ifdef QT_TEST_SERVER +#ifdef QT_TEST_SERVER_NAME return QString("danted.") % serverDomainName(); #else return serverName(); diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index 8b49679042..6c3443a735 100644 --- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -35,7 +35,9 @@ #include <QtNetwork/QNetworkCookieJar> #include <QtNetwork/QNetworkCookie> #include <QtNetwork/QNetworkRequest> +#if QT_CONFIG(topleveldomain) #include "private/qtldurl_p.h" +#endif class tst_QNetworkCookieJar: public QObject { @@ -47,7 +49,7 @@ private slots: void setCookiesFromUrl(); void cookiesForUrl_data(); void cookiesForUrl(); -#ifdef QT_BUILD_INTERNAL +#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(topleveldomain) void effectiveTLDs_data(); void effectiveTLDs(); #endif @@ -398,7 +400,7 @@ void tst_QNetworkCookieJar::cookiesForUrl() } // This test requires private API. -#ifdef QT_BUILD_INTERNAL +#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(topleveldomain) void tst_QNetworkCookieJar::effectiveTLDs_data() { QTest::addColumn<QString>("domain"); diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index b759aed074..72b5d06dd5 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1345,10 +1345,10 @@ void tst_QSslSocket::protocolServerSide() // to quit due to a socket error, and investigate the culprit. if (server.socket->error() != QAbstractSocket::UnknownSocketError) { QVERIFY(client.error() == QAbstractSocket::UnknownSocketError); - QCOMPARE(int(server.socket->state()), int(expectedState)); + QCOMPARE(server.socket->state(), expectedState); } else if (client.error() != QAbstractSocket::UnknownSocketError) { QVERIFY(server.socket->error() == QAbstractSocket::UnknownSocketError); - QCOMPARE(int(client.state()), int(expectedState)); + QCOMPARE(client.state(), expectedState); } QCOMPARE(client.isEncrypted(), works); } @@ -3271,10 +3271,10 @@ void tst_QSslSocket::verifyClientCertificate_data() validCerts += QSslCertificate::fromPath(testDataDir + "certs/bogus-ca.crt"); QCOMPARE(validCerts.size(), 2); - QTest::newRow("ValidClientCert:AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << validCerts << validKey << true; - QTest::newRow("ValidClientCert:QueryPeer") << QSslSocket::QueryPeer << validCerts << validKey << true; - QTest::newRow("ValidClientCert:VerifyNone") << QSslSocket::VerifyNone << validCerts << validKey << true; - QTest::newRow("ValidClientCert:VerifyPeer") << QSslSocket::VerifyPeer << validCerts << validKey << true; + QTest::newRow("ValidChainedClientCert:AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << validCerts << validKey << true; + QTest::newRow("ValidChainedClientCert:QueryPeer") << QSslSocket::QueryPeer << validCerts << validKey << true; + QTest::newRow("ValidChainedClientCert:VerifyNone") << QSslSocket::VerifyNone << validCerts << validKey << true; + QTest::newRow("ValidChainedClientCert:VerifyPeer") << QSslSocket::VerifyPeer << validCerts << validKey << true; } void tst_QSslSocket::verifyClientCertificate() @@ -3330,7 +3330,7 @@ void tst_QSslSocket::verifyClientCertificate() // check server socket QVERIFY(server.socket); - QCOMPARE(int(server.socket->state()), int(expectedState)); + QCOMPARE(server.socket->state(), expectedState); QCOMPARE(server.socket->isEncrypted(), works); if (peerVerifyMode == QSslSocket::VerifyNone || clientCerts.isEmpty()) { @@ -3342,7 +3342,7 @@ void tst_QSslSocket::verifyClientCertificate() } // check client socket - QCOMPARE(int(client.state()), int(expectedState)); + QCOMPARE(client.state(), expectedState); QCOMPARE(client.isEncrypted(), works); } diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp index 8cf43e243b..bdfa957083 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp @@ -199,6 +199,9 @@ private slots: void sqlite_openError(); + void sqlite_check_json1_data() { generic_data("QSQLITE"); } + void sqlite_check_json1(); + private: void createTestTables(QSqlDatabase db); void dropTestTables(QSqlDatabase db); @@ -2350,6 +2353,30 @@ void tst_QSqlDatabase::sqlite_openError() QCOMPARE(error.databaseText(), "unable to open database file"); } +void tst_QSqlDatabase::sqlite_check_json1() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType != QSqlDriver::SQLite) + QSKIP("SQLite3 specific test"); + + QSqlQuery q(db); + const QString json1("{\"id\":1}"); + const QString tableName(qTableName("sqlite_check_json1", __FILE__, db)); + tst_Databases::safeDropTable(db, tableName); + QVERIFY_SQL(q, exec(QString("CREATE TABLE %1(text TEXT)").arg(tableName))); + QVERIFY_SQL(q, exec(QString("INSERT INTO %1 VALUES(json('%2'))").arg(tableName, json1))); + QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES(?)").arg(tableName))); + q.addBindValue("json('{\"id\":2}')"); + QVERIFY_SQL(q, prepare(QString("SELECT * from %1 WHERE text = json('%2')").arg(tableName, json1))); + QVERIFY_SQL(q, exec()); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toString(), json1); + QFAIL_SQL(q, next()); +} + void tst_QSqlDatabase::cloneDatabase() { QFETCH(QString, dbName); diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri index b2f593235f..7dd32db0af 100644 --- a/tests/auto/testserver.pri +++ b/tests/auto/testserver.pri @@ -51,7 +51,6 @@ # 2. testserver_clean - Clean up server containers/images and tidy away related # files. -TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml TESTSERVER_VERSION = $$system(docker-compose --version) equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) { @@ -59,30 +58,59 @@ equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) { message("testserver: qt-test-server.qt-test-net") } else { # Make check with test servers - message("testserver:" $$TESTSERVER_VERSION) + equals(QMAKE_HOST.os, Darwin) { + # There is no docker bridge on macOS. It is impossible to ping a container. + # Docker docs recommends using port mapping to connect to a container; + # but it causes a port conflict if the user is running a service that + # binds the same port on the host. An alternative solution is to deploy + # the docker environment into VirtualBox using docker-machine. + TESTSERVER_COMPOSE_FILE = \ + $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-macOS.yml + + # The connection configuration for the target machine + MACHINE_CONFIG = $(shell docker-machine config qt-test-server) + + # The environment variables passed to the docker-compose file + TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)' + } else { + TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml + DEFINES += QT_TEST_SERVER_NAME + } # Ensure that the docker-compose file is provided. It is a configuration # file which is mandatory for all docker-compose commands. You can get more # detail from the description of TESTSERVER_COMPOSE_FILE above. There is # also an example showing how to configure it manually. FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set" - testserver_pretest.commands = $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG)) + testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION) + testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG)) + + # Make sure docker-machine is both created and running. The docker_machine + # script is used to deploy the docker environment into VirtualBox. + # Example: qt5/coin/provisioning/common/shared/testserver/docker_machine.sh + !isEmpty(MACHINE_CONFIG) { + MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server$" + MACHINE_LIST_MSG = "Docker machine qt-test-server not found" + testserver_pretest.commands += \ + $(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG)) + + MACHINE_STATE_CMD = \ + docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server$" + MACHINE_START_CMD = docker-machine start qt-test-server + testserver_pretest.commands += \ + $(if $(shell $$MACHINE_STATE_CMD),,$(shell $$MACHINE_START_CMD > /dev/null)) + } # Before starting the test servers, it requires the user to run the setup # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance. - IMAGE_PRETEST_CMD = docker images -aq "qt-test-server-*" + IMAGE_PRETEST_CMD = docker $$MACHINE_CONFIG images -aq "qt-test-server-*" IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found" testserver_pretest.commands += $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG)) # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem). DNSDOMAIN = test-net.qt.local - TEST_ENV += TESTSERVER_DOMAIN=$$DNSDOMAIN DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\") - # There is no docker bridge on macOS. It is impossible to ping a container. - # Docker docs recommends using port mapping to connect to a container. - equals(QMAKE_HOST.os, Darwin): TEST_ENV += TESTSERVER_BIND_LOCAL=1 - # Rename the check target of testcase feature check.target = check_network testserver_test.target = check @@ -91,18 +119,19 @@ equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) { testserver_test.depends = testserver_pretest # Bring up test servers and make sure the services are ready. - testserver_test.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE up -d \ - --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && + !isEmpty(TEST_ENV): testserver_test.commands = env $$TEST_ENV + testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \ + --detach --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && # Check test cases with docker-based test servers. testserver_test.commands += $(MAKE) check_network; # Stop and remove test servers after testing. - testserver_test.commands += $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \ + testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \ --timeout 1 # Destroy test servers and tidy away related files. - testserver_clean.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \ + testserver_clean.commands = docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \ --rmi all QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 92a94055a4..f1888aebab 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -682,6 +682,7 @@ private slots: void finalClasses(); void explicitOverrideControl_data(); void explicitOverrideControl(); + void overloadedAddressOperator(); void autoPropertyMetaTypeRegistration(); void autoMethodArgumentMetaTypeRegistration(); void autoSignalSpyMetaTypeRegistration(); @@ -2939,6 +2940,34 @@ void tst_Moc::explicitOverrideControl() #endif } +class OverloadedAddressOperator : public QObject +{ + Q_OBJECT +public: + void* operator&() { return nullptr; } +signals: + void self(OverloadedAddressOperator&); +public slots: + void assertSelf(OverloadedAddressOperator &o) + { + QCOMPARE(std::addressof(o), this); + testResult = (std::addressof(o) == this); + } +public: + bool testResult = false; +}; + +void tst_Moc::overloadedAddressOperator() +{ + OverloadedAddressOperator o; + OverloadedAddressOperator *p = std::addressof(o); + QCOMPARE(&o, nullptr); + QVERIFY(p); + QObject::connect(p, &OverloadedAddressOperator::self, p, &OverloadedAddressOperator::assertSelf); + emit o.self(o); + QVERIFY(o.testResult); +} + class CustomQObject : public QObject { Q_OBJECT diff --git a/tests/auto/tools/rcc/data/sizes/data/data-0.txt b/tests/auto/tools/rcc/data/sizes/data/data-0.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/data/data-0.txt diff --git a/tests/auto/tools/rcc/data/sizes/data/data-1.txt b/tests/auto/tools/rcc/data/sizes/data/data-1.txt new file mode 100644 index 0000000000..b516b2c489 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/data/data-1.txt @@ -0,0 +1 @@ +@
\ No newline at end of file diff --git a/tests/auto/tools/rcc/data/sizes/data/data-2.txt b/tests/auto/tools/rcc/data/sizes/data/data-2.txt new file mode 100644 index 0000000000..a616ad491b --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/data/data-2.txt @@ -0,0 +1 @@ +01
\ No newline at end of file diff --git a/tests/auto/tools/rcc/data/sizes/data/data-35.txt b/tests/auto/tools/rcc/data/sizes/data/data-35.txt new file mode 100644 index 0000000000..19a8036a15 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/data/data-35.txt @@ -0,0 +1 @@ +0123456789 0123456789 0123456789 12
\ No newline at end of file diff --git a/tests/auto/tools/rcc/data/sizes/size-0.expected b/tests/auto/tools/rcc/data/sizes/size-0.expected new file mode 100644 index 0000000000..e862310153 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-0.expected @@ -0,0 +1,88 @@ +/**************************************************************************** +** Resource object code +** +IGNORE: ** Created by: The Resource Compiler for Qt version 5.11.2 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +static const unsigned char qt_resource_data[] = { +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-0.txt + 0x0,0x0,0x0,0x0, + + +}; + +static const unsigned char qt_resource_name[] = { + // data + 0x0,0x4, + 0x0,0x6,0xa8,0xa1, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61, + // data-0.txt + 0x0,0xa, + 0x4,0xe,0xa,0xb4, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x30,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data/data-0.txt + 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, +TIMESTAMP:data/data-0.txt + +}; + +#ifdef QT_NAMESPACE +# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name +# define QT_RCC_MANGLE_NAMESPACE0(x) x +# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b +# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b) +# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \ + QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE)) +#else +# define QT_RCC_PREPEND_NAMESPACE(name) name +# define QT_RCC_MANGLE_NAMESPACE(name) name +#endif + +#ifdef QT_NAMESPACE +namespace QT_NAMESPACE { +#endif + +bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +#ifdef QT_NAMESPACE +} +#endif + +int QT_RCC_MANGLE_NAMESPACE(qInitResources)(); +int QT_RCC_MANGLE_NAMESPACE(qInitResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +namespace { + struct initializer { + initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); } + ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); } + } dummy; +} diff --git a/tests/auto/tools/rcc/data/sizes/size-0.qrc b/tests/auto/tools/rcc/data/sizes/size-0.qrc new file mode 100644 index 0000000000..9f47732fe2 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-0.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>data/data-0.txt</file> +</qresource> +</RCC> diff --git a/tests/auto/tools/rcc/data/sizes/size-1.expected b/tests/auto/tools/rcc/data/sizes/size-1.expected new file mode 100644 index 0000000000..9e5161272a --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-1.expected @@ -0,0 +1,89 @@ +/**************************************************************************** +** Resource object code +** +IGNORE:** Created by: The Resource Compiler for Qt version 5.11.2 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +static const unsigned char qt_resource_data[] = { +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-1.txt + 0x0,0x0,0x0,0x1, + 0x40, + + +}; + +static const unsigned char qt_resource_name[] = { + // data + 0x0,0x4, + 0x0,0x6,0xa8,0xa1, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61, + // data-1.txt + 0x0,0xa, + 0x4,0x11,0xa,0xb4, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x31,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data/data-1.txt + 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, +TIMESTAMP:data/data-1.txt + +}; + +#ifdef QT_NAMESPACE +# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name +# define QT_RCC_MANGLE_NAMESPACE0(x) x +# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b +# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b) +# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \ + QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE)) +#else +# define QT_RCC_PREPEND_NAMESPACE(name) name +# define QT_RCC_MANGLE_NAMESPACE(name) name +#endif + +#ifdef QT_NAMESPACE +namespace QT_NAMESPACE { +#endif + +bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +#ifdef QT_NAMESPACE +} +#endif + +int QT_RCC_MANGLE_NAMESPACE(qInitResources)(); +int QT_RCC_MANGLE_NAMESPACE(qInitResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +namespace { + struct initializer { + initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); } + ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); } + } dummy; +} diff --git a/tests/auto/tools/rcc/data/sizes/size-1.qrc b/tests/auto/tools/rcc/data/sizes/size-1.qrc new file mode 100644 index 0000000000..9fde9a1722 --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-1.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>data/data-1.txt</file> +</qresource> +</RCC> diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected new file mode 100644 index 0000000000..0fc953351a --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected @@ -0,0 +1,126 @@ +/**************************************************************************** +** Resource object code +** +IGNORE: ** Created by: The Resource Compiler for Qt version 5.11.2 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +static const unsigned char qt_resource_data[] = { +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-2.txt + 0x0,0x0,0x0,0x2, + 0x30, + 0x31, +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-35.txt + 0x0,0x0,0x0,0x23, + 0x30, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20,0x30,0x31,0x32,0x33,0x34,0x35, + 0x36,0x37,0x38,0x39,0x20,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20, + 0x31,0x32, +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-1.txt + 0x0,0x0,0x0,0x1, + 0x40, + +IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-0.txt + 0x0,0x0,0x0,0x0, + + +}; + +static const unsigned char qt_resource_name[] = { + // data + 0x0,0x4, + 0x0,0x6,0xa8,0xa1, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61, + // data-2.txt + 0x0,0xa, + 0x4,0x8,0xa,0xb4, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x32,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + // data-35.txt + 0x0,0xb, + 0x0,0xb5,0x4f,0x74, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x33,0x0,0x35,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + // data-1.txt + 0x0,0xa, + 0x4,0x11,0xa,0xb4, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x31,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + // data-0.txt + 0x0,0xa, + 0x4,0xe,0xa,0xb4, + 0x0,0x64, + 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x30,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + // :/data/data-35.txt + 0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x6, +TIMESTAMP:data/data-35.txt + // :/data/data-2.txt + 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, +TIMESTAMP:data/data-2.txt + // :/data/data-0.txt + 0x0,0x0,0x0,0x5e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x32, +TIMESTAMP:data/data-0.txt + // :/data/data-1.txt + 0x0,0x0,0x0,0x44,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2d, +TIMESTAMP:data/data-1.txt + +}; + +#ifdef QT_NAMESPACE +# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name +# define QT_RCC_MANGLE_NAMESPACE0(x) x +# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b +# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b) +# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \ + QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE)) +#else +# define QT_RCC_PREPEND_NAMESPACE(name) name +# define QT_RCC_MANGLE_NAMESPACE(name) name +#endif + +#ifdef QT_NAMESPACE +namespace QT_NAMESPACE { +#endif + +bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *); + +#ifdef QT_NAMESPACE +} +#endif + +int QT_RCC_MANGLE_NAMESPACE(qInitResources)(); +int QT_RCC_MANGLE_NAMESPACE(qInitResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); +int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)() +{ + QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x2, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +namespace { + struct initializer { + initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); } + ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); } + } dummy; +} diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc new file mode 100644 index 0000000000..039c9203ff --- /dev/null +++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>data/data-2.txt</file> + <file>data/data-0.txt</file> + <file>data/data-35.txt</file> + <file>data/data-1.txt</file> +</qresource> +</RCC> diff --git a/tests/auto/tools/rcc/rcc.pro b/tests/auto/tools/rcc/rcc.pro index 264b8ecc66..3fdc4132a7 100644 --- a/tests/auto/tools/rcc/rcc.pro +++ b/tests/auto/tools/rcc/rcc.pro @@ -3,3 +3,10 @@ QT = core testlib TARGET = tst_rcc SOURCES += tst_rcc.cpp + +RESOURCES += \ + $$PWD/data/images/images.qrc \ + $$PWD/data/sizes/size-0.qrc \ + $$PWD/data/sizes/size-2-0-35-1.qrc \ + $$PWD/data/sizes/size-1.qrc + diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp index 54a2854ede..0876af6759 100644 --- a/tests/auto/tools/rcc/tst_rcc.cpp +++ b/tests/auto/tools/rcc/tst_rcc.cpp @@ -55,9 +55,13 @@ private slots: void rcc_data(); void rcc(); + void binary_data(); void binary(); + void readback_data(); + void readback(); + void cleanupTestCase(); private: @@ -126,6 +130,13 @@ void tst_rcc::rcc_data() if (dataPath.isEmpty()) QFAIL("data path not found"); QTest::newRow("images") << dataPath << "images.qrc" << "images.expected"; + + QString sizesPath = QFINDTESTDATA("data/sizes/"); + if (sizesPath.isEmpty()) + QFAIL("data path not found"); + QTest::newRow("size-0") << sizesPath << "size-0.qrc" << "size-0.expected"; + QTest::newRow("size-1") << sizesPath << "size-1.qrc" << "size-1.expected"; + QTest::newRow("size-2-0-35-1") << sizesPath << "size-2-0-35-1.qrc" << "size-2-0-35-1.expected"; } void tst_rcc::rcc() @@ -353,6 +364,42 @@ void tst_rcc::binary() QLocale::setDefault(oldDefaultLocale); } +void tst_rcc::readback_data() +{ + QTest::addColumn<QString>("resourceName"); + QTest::addColumn<QString>("fileSystemName"); + + QTest::newRow("data-0") << ":data/data-0.txt" << "sizes/data/data-0.txt"; + QTest::newRow("data-1") << ":data/data-1.txt" << "sizes/data/data-1.txt"; + QTest::newRow("data-2") << ":data/data-2.txt" << "sizes/data/data-2.txt"; + QTest::newRow("data-35") << ":data/data-35.txt" << "sizes/data/data-35.txt"; + QTest::newRow("circle") << ":images/circle.png" << "images/images/circle.png"; + QTest::newRow("square") << ":images/square.png" << "images/images/square.png"; + QTest::newRow("triangle") << ":images/subdir/triangle.png" + << "images/images/subdir/triangle.png"; +} + +void tst_rcc::readback() +{ + QFETCH(QString, resourceName); + QFETCH(QString, fileSystemName); + + QString dataPath = QFINDTESTDATA("data/"); + if (dataPath.isEmpty()) + QFAIL("data path not found"); + + QFile resourceFile(resourceName); + QVERIFY(resourceFile.open(QIODevice::ReadOnly)); + QByteArray resourceData = resourceFile.readAll(); + resourceFile.close(); + + QFile fileSystemFile(dataPath + fileSystemName); + QVERIFY(fileSystemFile.open(QIODevice::ReadOnly)); + QByteArray fileSystemData = fileSystemFile.readAll(); + fileSystemFile.close(); + + QCOMPARE(resourceData, fileSystemData); +} void tst_rcc::cleanupTestCase() { diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index a8f6906056..adedace8b2 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -1215,7 +1215,7 @@ void tst_QItemDelegate::editorEvent() option.checkState = Qt::CheckState(checkState); const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1; - QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200); + QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200); QEvent *event = new QMouseEvent((QEvent::Type)type, pos, @@ -1371,7 +1371,7 @@ void tst_QItemDelegate::QTBUG4435_keepSelectionOnCheck() option.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator; option.checkState = Qt::CheckState(model.index(0, 0).data(Qt::CheckStateRole).toInt()); const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1; - QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint pos = qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pos); QTRY_VERIFY(view.selectionModel()->isColumnSelected(0, QModelIndex())); diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 5227db64ec..433b9e55e1 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -873,6 +873,10 @@ void tst_QListView::setCurrentIndex() } } } + while (model.rowCount()) { + view.setCurrentIndex(model.index(model.rowCount() - 1, 0)); + model.removeRow(model.rowCount() - 1); + } } class PublicListView : public QListView diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp index 98b44fe8aa..d8e14df353 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp @@ -31,6 +31,7 @@ #include <QtGui/QtGui> #include <QtWidgets/QtWidgets> #include <qlist.h> +#include <QSignalSpy> #include <qlistwidget.h> #include <private/qlistwidget_p.h> @@ -116,6 +117,14 @@ private slots: void QTBUG14363_completerWithAnyKeyPressedEditTriggers(); void mimeData(); void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void clearItemData(); +#endif + + void moveRows_data(); + void moveRows(); + void moveRowsInvalid_data(); + void moveRowsInvalid(); protected slots: void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) @@ -148,6 +157,108 @@ private: }; +void tst_QListWidget::moveRowsInvalid_data() +{ + QTest::addColumn<QListWidget*>("baseWidget"); + QTest::addColumn<QModelIndex>("startParent"); + QTest::addColumn<int>("startRow"); + QTest::addColumn<int>("count"); + QTest::addColumn<QModelIndex>("destinationParent"); + QTest::addColumn<int>("destination"); + + const auto createWidget = []() -> QListWidget* { + QListWidget* result = new QListWidget; + result->addItems(QStringList{"A", "B", "C", "D", "E", "F"}); + return result; + }; + + QTest::addRow("destination_equal_source") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << 1; + QTest::addRow("count_equal_0") << createWidget() << QModelIndex() << 0 << 0 << QModelIndex() << 2; + QListWidget* tempWidget = createWidget(); + QTest::addRow("move_child") << tempWidget << tempWidget->model()->index(0, 0) << 0 << 1 << QModelIndex() << 2; + tempWidget = createWidget(); + QTest::addRow("move_to_child") << tempWidget << QModelIndex() << 0 << 1 << tempWidget->model()->index(0, 0) << 2; + QTest::addRow("negative_count") << createWidget() << QModelIndex() << 0 << -1 << QModelIndex() << 2; + QTest::addRow("negative_source_row") << createWidget() << QModelIndex() << -1 << 1 << QModelIndex() << 2; + QTest::addRow("negative_destination_row") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << -1; + QTest::addRow("source_row_equal_rowCount") << createWidget() << QModelIndex() << 6 << 1 << QModelIndex() << 1; + QTest::addRow("destination_row_greater_rowCount") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << 6 + 1; + QTest::addRow("move_row_within_source_range") << createWidget() << QModelIndex() << 0 << 3 << QModelIndex() << 2; + QTest::addRow("destination_row_before_0") << createWidget() << QModelIndex() << 1 << 1 << QModelIndex() << 0; +} + +void tst_QListWidget::moveRowsInvalid() +{ + QFETCH(QListWidget* const, baseWidget); + QFETCH(const QModelIndex, startParent); + QFETCH(const int, startRow); + QFETCH(const int, count); + QFETCH(const QModelIndex, destinationParent); + QFETCH(const int, destination); + QAbstractItemModel *baseModel = baseWidget->model(); + QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved); + QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved); + QVERIFY(rowMovedSpy.isValid()); + QVERIFY(rowAboutMovedSpy.isValid()); + QVERIFY(!baseModel->moveRows(startParent, startRow, count, destinationParent, destination)); + QCOMPARE(rowMovedSpy.size(), 0); + QCOMPARE(rowAboutMovedSpy.size(), 0); + delete baseWidget; +} + +void tst_QListWidget::moveRows_data() +{ + QTest::addColumn<int>("startRow"); + QTest::addColumn<int>("count"); + QTest::addColumn<int>("destination"); + QTest::addColumn<QStringList>("expected"); + + QTest::newRow("1_Item_from_top_to_middle") << 0 << 1 << 3 << QStringList{"B", "C", "A", "D", "E", "F"}; + QTest::newRow("1_Item_from_top_to_bottom") << 0 << 1 << 6 << QStringList{"B", "C", "D", "E", "F", "A"}; + QTest::newRow("1_Item_from_middle_to_top") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("1_Item_from_bottom_to_middle") << 5 << 1 << 3 << QStringList{"A", "B", "F", "C", "D", "E"}; + QTest::newRow("1_Item_from_bottom to_top") << 5 << 1 << 1 << QStringList{"F", "A", "B", "C", "D", "E"}; + QTest::newRow("1_Item_from_middle_to_bottom") << 2 << 1 << 6 << QStringList{"A", "B", "D", "E", "F", "C"}; + QTest::newRow("1_Item_from_middle_to_middle_before") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("1_Item_from_middle_to_middle_after") << 2 << 1 << 4 << QStringList{"A", "B", "D", "C", "E", "F"}; + + QTest::newRow("2_Items_from_top_to_middle") << 0 << 2 << 3 << QStringList{"C", "A", "B", "D", "E", "F"}; + QTest::newRow("2_Items_from_top_to_bottom") << 0 << 2 << 6 << QStringList{"C", "D", "E", "F", "A", "B"}; + QTest::newRow("2_Items_from_middle_to_top") << 2 << 2 << 1 << QStringList{"C", "D", "A", "B", "E", "F"}; + QTest::newRow("2_Items_from_bottom_to_middle") << 4 << 2 << 3 << QStringList{"A", "B", "E", "F", "C", "D"}; + QTest::newRow("2_Items_from_bottom_to_top") << 4 << 2 << 1 << QStringList{"E", "F", "A", "B", "C", "D"}; + QTest::newRow("2_Items_from_middle_to_bottom") << 2 << 2 << 6 << QStringList{"A", "B", "E", "F", "C", "D"}; + QTest::newRow("2_Items_from_middle_to_middle_before") << 3 << 2 << 2 << QStringList{"A", "D", "E", "B", "C", "F"}; + QTest::newRow("2_Items_from_middle_to_middle_after") << 1 << 2 << 5 << QStringList{"A", "D", "E", "B", "C", "F"}; +} + +void tst_QListWidget::moveRows() +{ + QFETCH(const int, startRow); + QFETCH(const int, count); + QFETCH(const int, destination); + QFETCH(const QStringList, expected); + QListWidget baseWidget; + baseWidget.addItems(QStringList{"A", "B", "C", "D", "E", "F"}); + QAbstractItemModel *baseModel = baseWidget.model(); + QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved); + QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved); + QVERIFY(baseModel->moveRows(QModelIndex(), startRow, count, QModelIndex(), destination)); + QCOMPARE(baseModel->rowCount(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + QCOMPARE(baseModel->index(i, 0).data().toString(), expected.at(i)); + QCOMPARE(rowMovedSpy.size(), 1); + QCOMPARE(rowAboutMovedSpy.size(), 1); + for (const QList<QVariant> &signalArgs : {rowMovedSpy.first(), rowAboutMovedSpy.first()}){ + QVERIFY(!signalArgs.at(0).value<QModelIndex>().isValid()); + QCOMPARE(signalArgs.at(1).toInt(), startRow); + QCOMPARE(signalArgs.at(2).toInt(), startRow + count - 1); + QVERIFY(!signalArgs.at(3).value<QModelIndex>().isValid()); + QCOMPARE(signalArgs.at(4).toInt(), destination); + } +} + + typedef QList<int> IntList; tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rcLast(8,0) @@ -1743,5 +1854,27 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet() } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void tst_QListWidget::clearItemData() +{ + QListWidget list; + for (int i = 0 ; i < 4; ++i) + new QListWidgetItem(QString::number(i), &list); + QSignalSpy dataChangeSpy(list.model(), &QAbstractItemModel::dataChanged); + QVERIFY(dataChangeSpy.isValid()); + QVERIFY(!list.model()->clearItemData(QModelIndex())); + QCOMPARE(dataChangeSpy.size(), 0); + QVERIFY(list.model()->clearItemData(list.model()->index(0, 0))); + QVERIFY(!list.model()->index(0, 0).data().isValid()); + QCOMPARE(dataChangeSpy.size(), 1); + const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst(); + QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), list.model()->index(0, 0)); + QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), list.model()->index(0, 0)); + QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty()); + QVERIFY(list.model()->clearItemData(list.model()->index(0, 0))); + QCOMPARE(dataChangeSpy.size(), 0); +} +#endif + QTEST_MAIN(tst_QListWidget) #include "tst_qlistwidget.moc" diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index ab746dfee8..228d03350a 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -2506,7 +2506,6 @@ void tst_QTableView::columnViewportPosition() view.horizontalScrollBar()->setValue(horizontalScrollValue); #ifdef Q_OS_WINRT - QEXPECT_FAIL("column 1, scroll per item, 1", "Fails on WinRT - QTBUG-68297", Abort); QEXPECT_FAIL("column 5, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort); QEXPECT_FAIL("column 9, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort); QEXPECT_FAIL("column 1, scroll per pixel 1", "Fails on WinRT - QTBUG-68297", Abort); diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp index 4155ff1ec6..5f013a28d0 100644 --- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp +++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp @@ -83,12 +83,17 @@ private slots: void setItemData(); void cellWidget(); void cellWidgetGeometry(); + void sizeHint_data(); + void sizeHint(); void task231094(); void task219380_removeLastRow(); void task262056_sortDuplicate(); void itemWithHeaderItems(); void mimeData(); void selectedRowAfterSorting(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void clearItemData(); +#endif private: QTableWidget *testWidget; @@ -1454,6 +1459,56 @@ void tst_QTableWidget::cellWidgetGeometry() QCOMPARE(tw.visualItemRect(item).top(), le->geometry().top()); } +void tst_QTableWidget::sizeHint_data() +{ + QTest::addColumn<int>("scrollBarPolicy"); + QTest::addColumn<QSize>("viewSize"); + QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize(); + QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize(); + // make sure the scrollbars are shown by resizing the view to 40x40 + QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40); + QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000); +} + +void tst_QTableWidget::sizeHint() +{ + QFETCH(int, scrollBarPolicy); + QFETCH(QSize, viewSize); + + QTableWidget view(2, 2); + view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy)); + view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy)); + for (int r = 0 ; r < view.rowCount(); ++r) + for (int c = 0 ; c < view.columnCount(); ++c) + view.setItem(r, c, new QTableWidgetItem(QString("%1/%2").arg(r).arg(c))); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + if (viewSize.isValid()) { + view.resize(viewSize); + view.setColumnWidth(0, 100); + view.setRowHeight(0, 100); + QTRY_COMPARE(view.size(), viewSize); + } + + auto sizeHint = view.sizeHint(); + view.hide(); + QCOMPARE(view.sizeHint(), sizeHint); + + view.horizontalHeader()->hide(); + view.show(); + sizeHint = view.sizeHint(); + view.hide(); + QCOMPARE(view.sizeHint(), sizeHint); + + view.verticalHeader()->hide(); + view.show(); + sizeHint = view.sizeHint(); + view.hide(); + QCOMPARE(view.sizeHint(), sizeHint); +} + void tst_QTableWidget::task231094() { QTableWidget tw(5, 3); @@ -1617,5 +1672,28 @@ void tst_QTableWidget::selectedRowAfterSorting() } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void tst_QTableWidget::clearItemData() +{ + QTableWidget table(3,3); + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0"))); + QSignalSpy dataChangeSpy(table.model(), &QAbstractItemModel::dataChanged); + QVERIFY(dataChangeSpy.isValid()); + QVERIFY(!table.model()->clearItemData(QModelIndex())); + QCOMPARE(dataChangeSpy.size(), 0); + QVERIFY(table.model()->clearItemData(table.model()->index(0, 0))); + QVERIFY(!table.model()->index(0, 0).data().isValid()); + QCOMPARE(dataChangeSpy.size(), 1); + const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst(); + QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), table.model()->index(0, 0)); + QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), table.model()->index(0, 0)); + QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty()); + QVERIFY(table.model()->clearItemData(table.model()->index(0, 0))); + QCOMPARE(dataChangeSpy.size(), 0); +} +#endif + QTEST_MAIN(tst_QTableWidget) #include "tst_qtablewidget.moc" diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 8f9afeea4d..f4a73b8b4a 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -2435,6 +2435,8 @@ void tst_QTreeView::selection() for (int i = 0;i < 10; ++i) m.setData(m.index(i, 0), i); treeView.setModel(&m); + treeView.show(); + QVERIFY(QTest::qWaitForWindowExposed(&treeView)); treeView.setSelectionBehavior(QAbstractItemView::SelectRows); treeView.setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -2446,6 +2448,13 @@ void tst_QTreeView::selection() QTest::mousePress(treeView.viewport(), Qt::LeftButton, 0, treeView.visualRect(m.index(1, 0)).center()); QTest::keyPress(treeView.viewport(), Qt::Key_Down); + auto selectedRows = treeView.selectionModel()->selectedRows(); + QCOMPARE(selectedRows.size(), 1); + QCOMPARE(selectedRows.first(), m.index(2, 0, QModelIndex())); + QTest::keyPress(treeView.viewport(), Qt::Key_5); + selectedRows = treeView.selectionModel()->selectedRows(); + QCOMPARE(selectedRows.size(), 1); + QCOMPARE(selectedRows.first(), m.index(5, 0, QModelIndex())); } //From task 151686 QTreeView ExtendedSelection selects hidden rows diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp index 8c93df9073..c5ccbc0d0b 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp @@ -115,6 +115,8 @@ private slots: void changeDataWithSorting(); void changeDataWithStableSorting_data(); void changeDataWithStableSorting(); + void sizeHint_data(); + void sizeHint(); void sortedIndexOfChild_data(); void sortedIndexOfChild(); @@ -161,6 +163,9 @@ private slots: void getMimeDataWithInvalidItem(); void testVisualItemRect(); void reparentHiddenItem(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void clearItemData(); +#endif public slots: void itemSelectionChanged(); @@ -2618,6 +2623,50 @@ void tst_QTreeWidget::changeDataWithStableSorting() QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0); } +void tst_QTreeWidget::sizeHint_data() +{ + QTest::addColumn<int>("scrollBarPolicy"); + QTest::addColumn<QSize>("viewSize"); + QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize(); + QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize(); + // make sure the scrollbars are shown by resizing the view to 40x40 + QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40); + QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000); +} + +void tst_QTreeWidget::sizeHint() +{ + QFETCH(int, scrollBarPolicy); + QFETCH(QSize, viewSize); + + QTreeWidget view; + view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy)); + view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy)); + view.setColumnCount(2); + for (int i = 0 ; i < view.columnCount(); ++i) + view.addTopLevelItem(new QTreeWidgetItem(QStringList{"foo","bar"})); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + if (viewSize.isValid()) { + view.resize(viewSize); + view.setColumnWidth(0, 100); + QTRY_COMPARE(view.size(), viewSize); + } + + auto sizeHint = view.sizeHint(); + view.hide(); + QCOMPARE(view.sizeHint(), sizeHint); + + view.header()->hide(); + view.show(); + sizeHint = view.sizeHint(); + view.hide(); + QCOMPARE(view.sizeHint(), sizeHint); +} + void tst_QTreeWidget::itemOperatorLessThan() { QTreeWidget tw; @@ -3004,7 +3053,7 @@ void tst_QTreeWidget::task191552_rtl() opt.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator; opt.checkState = Qt::Checked; opt.widget = &tw; - const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, &tw); + const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, &tw); QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, checkRect.center()); QCOMPARE(item->checkState(0), Qt::Unchecked); @@ -3218,7 +3267,7 @@ void tst_QTreeWidget::nonEditableTristate() option.checkState = item->checkState(0); const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1; - QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0); + QPoint pos = qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0); QTest::mouseClick(tree->viewport(), Qt::LeftButton, Qt::NoModifier, pos); QCOMPARE(int(item->checkState(0)), int(Qt::Checked)); @@ -3529,5 +3578,43 @@ void tst_QTreeWidget::reparentHiddenItem() QVERIFY(grandChild->isHidden()); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void tst_QTreeWidget::clearItemData() +{ + QTreeWidget tree; + QAbstractItemModel* model = tree.model(); + QVERIFY(model->insertColumn(0)); + QVERIFY(model->insertRow(0)); + const QModelIndex parentIdx = model->index(0, 0); + QVERIFY(model->insertColumn(0, parentIdx)); + QVERIFY(model->insertRow(0, parentIdx)); + const QModelIndex childIdx = model->index(0, 0, parentIdx); + model->setData(parentIdx, QStringLiteral("parent")); + model->setData(parentIdx, QStringLiteral("parent"), Qt::UserRole); + model->setData(childIdx, QStringLiteral("child")); + QSignalSpy dataChangeSpy(model, &QAbstractItemModel::dataChanged); + QVERIFY(dataChangeSpy.isValid()); + QVERIFY(!model->clearItemData(QModelIndex())); + QCOMPARE(dataChangeSpy.size(), 0); + QVERIFY(model->clearItemData(parentIdx)); + QVERIFY(!model->data(parentIdx).isValid()); + QVERIFY(!model->data(parentIdx, Qt::UserRole).isValid()); + QCOMPARE(dataChangeSpy.size(), 1); + QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst(); + QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), parentIdx); + QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), parentIdx); + QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty()); + QVERIFY(model->clearItemData(parentIdx)); + QCOMPARE(dataChangeSpy.size(), 0); + QVERIFY(model->clearItemData(childIdx)); + QVERIFY(!model->data(childIdx).isValid()); + QCOMPARE(dataChangeSpy.size(), 1); + dataChangeArgs = dataChangeSpy.takeFirst(); + QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), childIdx); + QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), childIdx); + QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty()); +} +#endif + QTEST_MAIN(tst_QTreeWidget) #include "tst_qtreewidget.moc" diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index d2a244b762..d06baed322 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -240,6 +240,7 @@ void tst_QApplication::staticSetup() QVERIFY(style); QApplication::setStyle(style); + bool palette_changed = false; QPalette pal; QApplication::setPalette(pal); @@ -247,7 +248,11 @@ void tst_QApplication::staticSetup() QApplication::setFont(font);*/ int argc = 0; - QApplication app(argc, 0); + QApplication app(argc, nullptr); + QObject::connect(&app, &QApplication::paletteChanged, [&palette_changed]{ palette_changed = true; }); + QVERIFY(!palette_changed); + qApp->setPalette(QPalette(Qt::red)); + QVERIFY(palette_changed); } diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 360e6986f6..67b326e7ee 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -7655,9 +7655,6 @@ void tst_QWidget::updateWhileMinimized() // Restore window. widget.showNormal(); - QTest::qWait(30); - if (m_platform == QStringLiteral("xcb")) - QSKIP("QTBUG-26424"); QTRY_COMPARE(widget.numPaintEvents, 1); QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50)); } diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp index 077e8de328..06522b2bd3 100644 --- a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp +++ b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp @@ -41,6 +41,8 @@ public: private slots: void metaObject(); + void saveAndLoadBuiltin_data(); + void saveAndLoadBuiltin(); }; class CustomWidget : public QWidget @@ -68,5 +70,50 @@ void tst_QWidgetMetaType::metaObject() QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<QSizePolicy>()), &QSizePolicy::staticMetaObject); } +template <typename T> +struct StreamingTraits +{ + // Streamable by default, as currently all widgets built-in types are streamable + enum { isStreamable = 1 }; +}; + +void tst_QWidgetMetaType::saveAndLoadBuiltin_data() +{ + QTest::addColumn<int>("type"); + QTest::addColumn<bool>("isStreamable"); + +#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ + QTest::newRow(#RealType) << MetaTypeId << bool(StreamingTraits<RealType>::isStreamable); + QT_FOR_EACH_STATIC_WIDGETS_CLASS(ADD_METATYPE_TEST_ROW) +#undef ADD_METATYPE_TEST_ROW +} + +void tst_QWidgetMetaType::saveAndLoadBuiltin() +{ + QFETCH(int, type); + QFETCH(bool, isStreamable); + + void *value = QMetaType::create(type); + + QByteArray ba; + QDataStream stream(&ba, QIODevice::ReadWrite); + QCOMPARE(QMetaType::save(stream, type, value), isStreamable); + QCOMPARE(stream.status(), QDataStream::Ok); + + if (isStreamable) + QVERIFY(QMetaType::load(stream, type, value)); + + stream.device()->seek(0); + stream.resetStatus(); + QCOMPARE(QMetaType::load(stream, type, value), isStreamable); + QCOMPARE(stream.status(), QDataStream::Ok); + + if (isStreamable) + QVERIFY(QMetaType::load(stream, type, value)); + + QMetaType::destroy(type, value); +} + + QTEST_MAIN(tst_QWidgetMetaType) #include "tst_qwidgetmetatype.moc" diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index f5d9433f70..bfef9d2ac4 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -159,7 +159,7 @@ void tst_QStyleSheetStyle::numinstances() QCOMPARE(QStyleSheetStyle::numinstances, 0); qApp->setStyleSheet("* { color: red; }"); QCOMPARE(QStyleSheetStyle::numinstances, 1); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(QStyleSheetStyle::numinstances, 0); // set and unset application stylesheet+widget @@ -168,9 +168,9 @@ void tst_QStyleSheetStyle::numinstances() QCOMPARE(QStyleSheetStyle::numinstances, 2); w.setStyle(style); QCOMPARE(QStyleSheetStyle::numinstances, 2); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(QStyleSheetStyle::numinstances, 1); - w.setStyleSheet(""); + w.setStyleSheet(QString()); QCOMPARE(QStyleSheetStyle::numinstances, 0); // set and unset widget stylesheet @@ -179,7 +179,7 @@ void tst_QStyleSheetStyle::numinstances() QCOMPARE(QStyleSheetStyle::numinstances, 1); c.setStyle(style); QCOMPARE(QStyleSheetStyle::numinstances, 2); - w.setStyleSheet(""); + w.setStyleSheet(QString()); QCOMPARE(QStyleSheetStyle::numinstances, 0); } @@ -192,9 +192,9 @@ void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet() QCOMPARE(COLOR(w1), red); w1.setStyleSheet("color: white"); QCOMPARE(COLOR(w1), white); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(COLOR(w1), white); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); } @@ -217,17 +217,17 @@ void tst_QStyleSheetStyle::widgetsAfterAppStyleSheet() QCOMPARE(COLOR(w1), white); QCOMPARE(COLOR(spin), red); QCOMPARE(COLOR(*spin.lineEdit()), red); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), red); QCOMPARE(COLOR(spin), red); QCOMPARE(COLOR(*spin.lineEdit()), red); w1.setStyleSheet("color: white"); QCOMPARE(COLOR(w1), white); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(COLOR(w1), white); QCOMPARE(COLOR(spin), APPCOLOR(spin)); QCOMPARE(COLOR(*spin.lineEdit()), APPCOLOR(*spin.lineEdit())); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); // QCOMPARE(FONTSIZE(w1), APPFONTSIZE(w1)); //### task 244261 QCOMPARE(FONTSIZE(spin), APPFONTSIZE(spin)); @@ -243,7 +243,7 @@ void tst_QStyleSheetStyle::applicationStyleSheet() QCOMPARE(COLOR(w1), red); qApp->setStyleSheet("* { color: white; }"); QCOMPARE(COLOR(w1), white); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); qApp->setStyleSheet("* { color: red }"); QCOMPARE(COLOR(w1), red); @@ -254,21 +254,21 @@ void tst_QStyleSheetStyle::windowStyleSheet() const QColor red(Qt::red); const QColor white(Qt::white); QPushButton w1; - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); w1.setStyleSheet("* { color: red; }"); QCOMPARE(COLOR(w1), red); w1.setStyleSheet("* { color: white; }"); QCOMPARE(COLOR(w1), white); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); w1.setStyleSheet("* { color: red }"); QCOMPARE(COLOR(w1), red); qApp->setStyleSheet("* { color: green }"); QCOMPARE(COLOR(w1), red); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), QColor("green")); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); } @@ -281,7 +281,7 @@ void tst_QStyleSheetStyle::widgetStyleSheet() QPushButton *pb = new QPushButton(&w1); QPushButton &w2 = *pb; - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); w1.setStyleSheet("* { color: red }"); QCOMPARE(COLOR(w1), red); QCOMPARE(COLOR(w2), red); @@ -293,11 +293,11 @@ void tst_QStyleSheetStyle::widgetStyleSheet() QCOMPARE(COLOR(w1), blue); QCOMPARE(COLOR(w2), white); - w1.setStyleSheet(""); + w1.setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); QCOMPARE(COLOR(w2), white); - w2.setStyleSheet(""); + w2.setStyleSheet(QString()); QCOMPARE(COLOR(w1), APPCOLOR(w1)); QCOMPARE(COLOR(w2), APPCOLOR(w2)); } @@ -311,7 +311,7 @@ void tst_QStyleSheetStyle::reparentWithNoChildStyleSheet() QPushButton *pb = new QPushButton(&p1); QPushButton &c1 = *pb; // child with no stylesheet - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); p1.setStyleSheet("* { color: red }"); QCOMPARE(COLOR(c1), red); c1.setParent(&p2); @@ -333,7 +333,7 @@ void tst_QStyleSheetStyle::reparentWithChildStyleSheet() { const QColor gray("gray"); const QColor white(Qt::white); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QPushButton p1, p2; QPushButton *pb = new QPushButton(&p1); QPushButton &c1 = *pb; @@ -353,7 +353,7 @@ void tst_QStyleSheetStyle::repolish() { const QColor red(Qt::red); const QColor white(Qt::white); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QPushButton p1; p1.setStyleSheet("color: red; background: white"); QCOMPARE(BACKGROUND(p1), white); @@ -362,14 +362,14 @@ void tst_QStyleSheetStyle::repolish() p1.setStyleSheet("color: red"); QCOMPARE(COLOR(p1), red); QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1)); - p1.setStyleSheet(""); + p1.setStyleSheet(QString()); QCOMPARE(COLOR(p1), APPCOLOR(p1)); QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1)); } void tst_QStyleSheetStyle::widgetStyle() { - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QWidget *window1 = new QWidget; window1->setObjectName("window1"); @@ -429,7 +429,7 @@ void tst_QStyleSheetStyle::widgetStyle() // Remove the stylesheet proxy = (QStyleSheetStyle *)window1->style(); - window1->setStyleSheet(""); + window1->setStyleSheet(QString()); QVERIFY(proxy.isNull()); // should have disappeared QCOMPARE(window1->style(), style1.data()); // its restored @@ -457,7 +457,7 @@ void tst_QStyleSheetStyle::widgetStyle() QCOMPARE(proxy->baseStyle(), style1.data()); // Style Sheet propagation on a child widget with a custom style already set - window2->setStyleSheet(""); + window2->setStyleSheet(QString()); QCOMPARE(window2->style(), style2.data()); QCOMPARE(widget2->style(), style1.data()); widget2->setStyle(0); @@ -470,9 +470,9 @@ void tst_QStyleSheetStyle::widgetStyle() // clean everything out window1->setStyle(0); - window1->setStyleSheet(""); + window1->setStyleSheet(QString()); window2->setStyle(0); - window2->setStyleSheet(""); + window2->setStyleSheet(QString()); qApp->setStyle(0); qApp->setStyleSheet("may_insanity_prevail { }"); // app has stylesheet @@ -489,14 +489,14 @@ void tst_QStyleSheetStyle::widgetStyle() QCOMPARE(proxy->baseStyle(), newStyle); // magic ;) the widget still follows the application QCOMPARE(static_cast<QStyle *>(proxy), widget1->style()); // child still follows... - window1->setStyleSheet(""); // remove stylesheet + window1->setStyleSheet(QString()); // remove stylesheet QCOMPARE(window1->style(), qApp->style()); // is this cool or what QCOMPARE(widget1->style(), qApp->style()); // annoying child follows... QScopedPointer<QStyle> wndStyle(QStyleFactory::create("Windows")); window1->setStyle(wndStyle.data()); QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // auto wraps it QCOMPARE(widget1->style(), window1->style()); // and auto propagates to child - qApp->setStyleSheet(""); // remove the app stylesheet + qApp->setStyleSheet(QString()); // remove the app stylesheet QCOMPARE(window1->style(), wndStyle.data()); // auto dewrap QCOMPARE(widget1->style(), qApp->style()); // and child state is restored window1->setStyle(0); // let sanity prevail @@ -511,7 +511,7 @@ void tst_QStyleSheetStyle::widgetStyle() void tst_QStyleSheetStyle::appStyle() { - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); // qApp style can never be 0 QVERIFY(QApplication::style() != 0); QPointer<QStyle> style1 = QStyleFactory::create("Windows"); @@ -544,11 +544,11 @@ void tst_QStyleSheetStyle::appStyle() QCOMPARE(sss->baseStyle(), style1.data()); // Revert the stylesheet - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QVERIFY(sss.isNull()); // should have disappeared QCOMPARE(QApplication::style(), style1.data()); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QCOMPARE(QApplication::style(), style1.data()); } @@ -744,7 +744,7 @@ void tst_QStyleSheetStyle::fontPropagation() window.setStyleSheet("* { font-size: 10pt }"); pb.setParent(&window); QCOMPARE(FONTSIZE(pb), 10); - window.setStyleSheet(""); + window.setStyleSheet(QString()); QCOMPARE(FONTSIZE(pb), buttonFontSize); QTabWidget tw; @@ -757,7 +757,7 @@ void tst_QStyleSheetStyle::fontPropagation() void tst_QStyleSheetStyle::onWidgetDestroyed() { - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); QLabel *l = new QLabel; l->setStyleSheet("QLabel { color: red }"); QPointer<QStyleSheetStyle> ss = (QStyleSheetStyle *) l->style(); @@ -778,14 +778,14 @@ void tst_QStyleSheetStyle::fontPrecedence() font.setPointSize(16); edit.setFont(font); QCOMPARE(FONTSIZE(edit), 22); - edit.setStyleSheet(""); + edit.setStyleSheet(QString()); QCOMPARE(FONTSIZE(edit), 16); font.setPointSize(18); edit.setFont(font); QCOMPARE(FONTSIZE(edit), 18); edit.setStyleSheet("QLineEdit { font-size: 20pt; }"); QCOMPARE(FONTSIZE(edit), 20); - edit.setStyleSheet(""); + edit.setStyleSheet(QString()); QCOMPARE(FONTSIZE(edit), 18); edit.hide(); @@ -1189,7 +1189,7 @@ void tst_QStyleSheetStyle::transparent() QPushButton *p3=new QPushButton(&w); p1->setStyleSheet("background:transparent"); p2->setStyleSheet("background-color:transparent"); - p3->setStyleSheet("background:rgb(0,0,0,0)"); + p3->setStyleSheet("background:rgba(0,0,0,0)"); QCOMPARE(BACKGROUND(*p1) , QColor(0,0,0,0)); QCOMPARE(BACKGROUND(*p2) , QColor(0,0,0,0)); QCOMPARE(BACKGROUND(*p3) , QColor(0,0,0,0)); @@ -2051,7 +2051,7 @@ void tst_QStyleSheetStyle::styleSheetTargetAttribute() QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), true); QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false); - qApp->setStyleSheet(""); + qApp->setStyleSheet(QString()); gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished(); QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false); @@ -2066,7 +2066,7 @@ void tst_QStyleSheetStyle::unpolish() w.setStyleSheet("QWidget { min-width: 100; }"); w.ensurePolished(); QCOMPARE(w.minimumWidth(), 100); - w.setStyleSheet(""); + w.setStyleSheet(QString()); QCOMPARE(w.minimumWidth(), 0); } diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index a88fd8d19c..634e258250 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -1143,8 +1143,16 @@ void tst_QMenu::QTBUG7411_submenus_activate() QTRY_VERIFY(sub1.isVisible()); } +static bool isPlatformWayland() +{ + return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive); +} + void tst_QMenu::QTBUG30595_rtl_submenu() { + if (isPlatformWayland()) + QSKIP("Creating xdg_popups on Wayland requires real input events. Positions would be off."); + QMenu menu("Test Menu"); menu.setLayoutDirection(Qt::RightToLeft); QMenu sub("&sub"); @@ -1179,6 +1187,9 @@ void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger() #ifndef Q_OS_MACOS void tst_QMenu::click_while_dismissing_submenu() { + if (isPlatformWayland()) + QSKIP("Wayland: Creating (grabbing) popups requires real mouse events."); + QMenu menu("Test Menu"); QAction *action = menu.addAction("action"); QMenu sub("&sub"); diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index cfa2ddc4cc..be19cbc9d1 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -140,6 +140,11 @@ private slots: void findBackwardWithRegExp(); void findWithRegExpReturnsFalseIfNoMoreResults(); #endif +#if QT_CONFIG(regularexpression) + void findWithRegularExpression(); + void findBackwardWithRegularExpression(); + void findWithRegularExpressionReturnsFalseIfNoMoreResults(); +#endif void layoutAfterMultiLineRemove(); void undoCommandRemovesAndReinsertsBlock(); void taskQTBUG_43562_lineCountCrash(); @@ -147,6 +152,9 @@ private slots: void contextMenu(); #endif void inputMethodCursorRect(); +#if QT_CONFIG(scrollbar) + void updateAfterChangeCenterOnScroll(); +#endif private: void createSelection(); @@ -1579,6 +1587,45 @@ void tst_QPlainTextEdit::findWithRegExpReturnsFalseIfNoMoreResults() } #endif +#if QT_CONFIG(regularexpression) +void tst_QPlainTextEdit::findWithRegularExpression() +{ + ed->setPlainText(QStringLiteral("arbitrary text")); + QRegularExpression rx("\\w{2}xt"); + + bool found = ed->find(rx); + + QVERIFY(found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text")); +} + +void tst_QPlainTextEdit::findBackwardWithRegularExpression() +{ + ed->setPlainText(QStringLiteral("arbitrary text")); + QTextCursor cursor = ed->textCursor(); + cursor.movePosition(QTextCursor::End); + ed->setTextCursor(cursor); + QRegularExpression rx("a\\w*t"); + + bool found = ed->find(rx, QTextDocument::FindBackward); + + QVERIFY(found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("arbit")); +} + +void tst_QPlainTextEdit::findWithRegularExpressionReturnsFalseIfNoMoreResults() +{ + ed->setPlainText(QStringLiteral("arbitrary text")); + QRegularExpression rx("t.xt"); + ed->find(rx); + + bool found = ed->find(rx); + + QVERIFY(!found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text")); +} +#endif + void tst_QPlainTextEdit::layoutAfterMultiLineRemove() { ed->setVisible(true); // The widget must be visible to reproduce this bug. @@ -1727,5 +1774,20 @@ void tst_QPlainTextEdit::inputMethodCursorRect() QCOMPARE(cursorRectV.toRect(), cursorRect.toRect()); } +#if QT_CONFIG(scrollbar) +// QTBUG-64730: Verify that the scrollbar is updated after center on scroll was set +void tst_QPlainTextEdit::updateAfterChangeCenterOnScroll() +{ + ed->setPlainText("Line1\nLine2Line3\nLine3"); + ed->show(); + ed->setCenterOnScroll(true); + const int maxWithCenterOnScroll = ed->verticalScrollBar()->maximum(); + ed->setCenterOnScroll(false); + const int maxWithoutCenterOnScroll = ed->verticalScrollBar()->maximum(); + QVERIFY(maxWithCenterOnScroll > maxWithoutCenterOnScroll); +} + +#endif + QTEST_MAIN(tst_QPlainTextEdit) #include "tst_qplaintextedit.moc" diff --git a/tests/auto/widgets/widgets/qsplitter/BLACKLIST b/tests/auto/widgets/widgets/qsplitter/BLACKLIST deleted file mode 100644 index 1352805cd7..0000000000 --- a/tests/auto/widgets/widgets/qsplitter/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[replaceWidget:visible, not collapsed] -xcb diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index 6a2ae4951b..5f5cd78215 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -199,6 +199,12 @@ private slots: void findWithRegExpReturnsFalseIfNoMoreResults(); #endif +#if QT_CONFIG(regularexpression) + void findWithRegularExpression(); + void findBackwardWithRegularExpression(); + void findWithRegularExpressionReturnsFalseIfNoMoreResults(); +#endif + #if QT_CONFIG(wheelevent) void wheelEvent(); #endif @@ -2572,6 +2578,45 @@ void tst_QTextEdit::findWithRegExpReturnsFalseIfNoMoreResults() } #endif +#if QT_CONFIG(regularexpression) +void tst_QTextEdit::findWithRegularExpression() +{ + ed->setHtml(QStringLiteral("arbitrary te<span style=\"color:#ff0000\">xt</span>")); + QRegularExpression rx("\\w{2}xt"); + + bool found = ed->find(rx); + + QVERIFY(found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text")); +} + +void tst_QTextEdit::findBackwardWithRegularExpression() +{ + ed->setPlainText(QStringLiteral("arbitrary text")); + QTextCursor cursor = ed->textCursor(); + cursor.movePosition(QTextCursor::End); + ed->setTextCursor(cursor); + QRegularExpression rx("a\\w*t"); + + bool found = ed->find(rx, QTextDocument::FindBackward); + + QVERIFY(found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("arbit")); +} + +void tst_QTextEdit::findWithRegularExpressionReturnsFalseIfNoMoreResults() +{ + ed->setPlainText(QStringLiteral("arbitrary text")); + QRegularExpression rx("t.xt"); + ed->find(rx); + + bool found = ed->find(rx); + + QVERIFY(!found); + QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text")); +} +#endif + #if QT_CONFIG(wheelevent) class TextEdit : public QTextEdit diff --git a/tests/benchmarks/corelib/io/qfileinfo/main.cpp b/tests/benchmarks/corelib/io/qfileinfo/main.cpp index 5180e7c29e..104c01d118 100644 --- a/tests/benchmarks/corelib/io/qfileinfo/main.cpp +++ b/tests/benchmarks/corelib/io/qfileinfo/main.cpp @@ -94,7 +94,9 @@ void qfileinfo::symLinkTargetPerformanceMounpoint() QString rootVolume = QString::fromWCharArray(buffer); QString mountpoint = "mountpoint"; rootVolume.replace("\\\\?\\","\\??\\"); - FileSystem::createNtfsJunction(rootVolume, mountpoint); + QString errorMessage; + QVERIFY2(FileSystem::createNtfsJunction(rootVolume, mountpoint, &errorMessage) == ERROR_SUCCESS, + qPrintable(errorMessage)); QFileInfo info(mountpoint); info.setCaching(false); diff --git a/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp b/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp index 704119b921..1b432f3b3e 100644 --- a/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp +++ b/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp @@ -35,6 +35,7 @@ class tst_QMimeDatabase: public QObject private slots: void inheritsPerformance(); + void benchMimeTypeForName(); }; void tst_QMimeDatabase::inheritsPerformance() @@ -70,5 +71,15 @@ void tst_QMimeDatabase::inheritsPerformance() // parsing XML, and then keeps being around 4.5 MB for all the in-memory hashes. } +void tst_QMimeDatabase::benchMimeTypeForName() +{ + QMimeDatabase db; + + QBENCHMARK { + const auto s = db.mimeTypeForName(QStringLiteral("text/plain")); + QVERIFY(s.isValid()); + } +} + QTEST_MAIN(tst_QMimeDatabase) #include "main.moc" diff --git a/tests/benchmarks/widgets/itemviews/itemviews.pro b/tests/benchmarks/widgets/itemviews/itemviews.pro index a23cdf7b97..0c3256f307 100644 --- a/tests/benchmarks/widgets/itemviews/itemviews.pro +++ b/tests/benchmarks/widgets/itemviews/itemviews.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ qtableview \ - qheaderview + qheaderview \ + qlistview diff --git a/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro b/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro new file mode 100644 index 0000000000..68537d09ea --- /dev/null +++ b/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro @@ -0,0 +1,7 @@ +QT += widgets testlib + +TEMPLATE = app +TARGET = tst_bench_qlistview + +SOURCES += tst_qlistview.cpp + diff --git a/tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp new file mode 100644 index 0000000000..01496743c2 --- /dev/null +++ b/tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QListView> +#include <QStandardItemModel> + + +class tst_QListView : public QObject +{ + Q_OBJECT + +public: + tst_QListView() = default; + virtual ~tst_QListView() = default; + +private slots: + void benchSetCurrentIndex(); +}; + +void tst_QListView::benchSetCurrentIndex() +{ + QStandardItemModel sm(50000, 1); + QListView lv; + lv.setModel(&sm); + const int rc = lv.model()->rowCount(); + for (int i = 0; i < rc; i+= 100) + lv.setRowHidden(i, true); + lv.setCurrentIndex(lv.model()->index(0, 0, QModelIndex())); + lv.show(); + QVERIFY(QTest::qWaitForWindowExposed(&lv)); + + QBENCHMARK_ONCE { + while (lv.currentIndex().row() < rc - 20) + lv.setCurrentIndex(lv.model()->index(lv.currentIndex().row() + 17, + lv.currentIndex().column(), + QModelIndex())); + } +} + + +QTEST_MAIN(tst_QListView) +#include "tst_qlistview.moc" diff --git a/tests/manual/widgets/itemviews/itemviews.pro b/tests/manual/widgets/itemviews/itemviews.pro index 53f658d54d..8884cc3aae 100644 --- a/tests/manual/widgets/itemviews/itemviews.pro +++ b/tests/manual/widgets/itemviews/itemviews.pro @@ -1,2 +1,8 @@ TEMPLATE = subdirs -SUBDIRS = delegate qheaderview qtreeview qtreewidget tableview-span-navigation +SUBDIRS = delegate \ + qconcatenatetablesproxymodel \ + qheaderview \ + qtreeview \ + qtreewidget \ + tableview-span-navigation \ + diff --git a/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp new file mode 100644 index 0000000000..2c1825f29f --- /dev/null +++ b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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$ +** +****************************************************************************/ + +#include <QApplication> +#include <QConcatenateTablesProxyModel> +#include <QStandardItemModel> +#include <QTableView> +#include <QTreeView> + +static void prepareModel(const QString &prefix, QStandardItemModel *model) +{ + for (int row = 0; row < model->rowCount(); ++row) { + for (int column = 0; column < model->columnCount(); ++column) { + QStandardItem *item = new QStandardItem(prefix + QString(" %1,%2").arg(row).arg(column)); + item->setDragEnabled(true); + item->setDropEnabled(true); + model->setItem(row, column, item); + } + } +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QStandardItemModel firstModel(4, 4); + prepareModel("First", &firstModel); + QStandardItemModel secondModel(2, 2); + + QConcatenateTablesProxyModel proxy; + proxy.addSourceModel(&firstModel); + proxy.addSourceModel(&secondModel); + + prepareModel("Second", &secondModel); + + QTableView tableView; + tableView.setWindowTitle("concat proxy, in QTableView"); + tableView.setDragDropMode(QAbstractItemView::DragDrop); + tableView.setModel(&proxy); + tableView.show(); + + QTreeView treeView; + treeView.setWindowTitle("concat proxy, in QTreeView"); + treeView.setDragDropMode(QAbstractItemView::DragDrop); + treeView.setModel(&proxy); + treeView.show(); + + // For comparison, views on top on QStandardItemModel + + QTableView tableViewTest; + tableViewTest.setWindowTitle("first model, in QTableView"); + tableViewTest.setDragDropMode(QAbstractItemView::DragDrop); + tableViewTest.setModel(&firstModel); + tableViewTest.show(); + + QTreeView treeViewTest; + treeViewTest.setWindowTitle("first model, in QTreeView"); + treeViewTest.setDragDropMode(QAbstractItemView::DragDrop); + treeViewTest.setModel(&firstModel); + treeViewTest.show(); + + return app.exec(); +} diff --git a/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro new file mode 100644 index 0000000000..19904212a7 --- /dev/null +++ b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro @@ -0,0 +1,8 @@ + +TEMPLATE = app +TARGET = qconcatenatetablesproxymodel +INCLUDEPATH += . + +QT += widgets + +SOURCES += main.cpp diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 73d7d6523c..9f4527a992 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -80,7 +80,7 @@ public: } #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - static void createNtfsJunction(QString target, QString linkName) + static DWORD createNtfsJunction(QString target, QString linkName, QString *errorMessage) { typedef struct { DWORD ReparseTag; @@ -97,14 +97,22 @@ public: DWORD returnedLength; wchar_t fileSystem[MAX_PATH] = L""; PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer; + DWORD result = ERROR_SUCCESS; QFileInfo junctionInfo(linkName); linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath()); - - GetVolumeInformationW( (wchar_t*)linkName.left(3).utf16(), NULL, 0, NULL, NULL, NULL, - fileSystem, sizeof(fileSystem)/sizeof(WCHAR)); - if(QString().fromWCharArray(fileSystem) != "NTFS") - QSKIP("This seems not to be an NTFS volume. Junctions are not allowed."); + const QString drive = linkName.left(3); + if (GetVolumeInformationW(reinterpret_cast<const wchar_t *>(drive.utf16()), + NULL, 0, NULL, NULL, NULL, + fileSystem, sizeof(fileSystem)/sizeof(WCHAR)) == FALSE) { + result = GetLastError(); + *errorMessage = "GetVolumeInformationW() failed: " + qt_error_string(int(result)); + return result; + } + if (QString::fromWCharArray(fileSystem) != "NTFS") { + *errorMessage = "This seems not to be an NTFS volume. Junctions are not allowed."; + return ERROR_NOT_SUPPORTED; + } if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) { QFileInfo targetInfo(target); @@ -116,7 +124,11 @@ public: QDir().mkdir(linkName); hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL ); - QVERIFY(hFile != INVALID_HANDLE_VALUE ); + if (hFile == INVALID_HANDLE_VALUE) { + result = GetLastError(); + *errorMessage = "CreateFileW(" + linkName + ") failed: " + qt_error_string(int(result)); + return result; + } memset( reparseInfo, 0, sizeof( *reparseInfo )); reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; @@ -128,8 +140,12 @@ public: bool ioc = DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo, reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE, NULL, 0, &returnedLength, NULL); + if (!ioc) { + result = GetLastError(); + *errorMessage = "DeviceIoControl() failed: " + qt_error_string(int(result)); + } CloseHandle( hFile ); - QVERIFY(ioc); + return result; } #endif diff --git a/tests/testserver/danted/danted.sh b/tests/testserver/danted/danted.sh index bf3d154f33..97e2142401 100755 --- a/tests/testserver/danted/danted.sh +++ b/tests/testserver/danted/danted.sh @@ -39,6 +39,25 @@ useradd -d /dev/null -s /bin/false qsockstest; echo "qsockstest:$PASS" | chpassw # install configurations and test data cp $TESTDATA/danted{,-authenticating}.conf /etc/ +# Use the input environment variables to overwrite the default value of internal interfaces. +if [ "$danted_internal" -a "$danted_internal" != eth0 ] +then sed -i "s,internal: eth0 port = 1080,internal: $danted_internal port = 1080," /etc/danted.conf +fi + +if [ "$danted_auth_internal" -a "$danted_auth_internal" != eth0 ] +then sed -i "s,internal: eth0 port = 1081,internal: $danted_auth_internal port = 1081," \ + /etc/danted-authenticating.conf +fi + +# Use the input environment variables to overwrite the default value of external interfaces. +if [ "$danted_external" -a "$danted_external" != eth0 ] +then sed -i "s,external: eth0,external: $danted_external," /etc/danted.conf +fi + +if [ "$danted_auth_external" -a "$danted_auth_external" != eth0 ] +then sed -i "s,external: eth0,external: $danted_auth_external," /etc/danted-authenticating.conf +fi + # enable service with installed configurations service danted start service danted-authenticating start diff --git a/tests/testserver/docker-compose-for-macOS.yml b/tests/testserver/docker-compose-for-macOS.yml new file mode 100644 index 0000000000..f5d812511d --- /dev/null +++ b/tests/testserver/docker-compose-for-macOS.yml @@ -0,0 +1,80 @@ +version: '3.4' + +# The tag of images is used by docker compose file to launch the corresponding +# docker containers. The value of tag comes from the provisioning script +# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1 +# of each server context as the tag of docker images. If one of the server +# contexts gets changes, please make sure to update this compose file as well. +# You can run command 'docker images' to list all the tags of test server images. +# For example: +# REPOSITORY TAG IMAGE ID +# qt-test-server-apache2 cc9ea678b92bdda33acb9fa0159bb4ad0f3cd947 2ad5c8720317 + +services: + apache2: + image: qt-test-server-apache2:cc9ea678b92bdda33acb9fa0159bb4ad0f3cd947 + container_name: qt-test-server-apache2 + domainname: test-net.qt.local + volumes: + - ./common:/common:ro + - ./apache2:/service:ro + entrypoint: common/startup.sh + command: [common/ssl.sh, service/apache2.sh] + network_mode: "host" + + squid: + image: qt-test-server-squid:577d99307eea9a8cccfec944d25be2bce2fe99cc + container_name: qt-test-server-squid + domainname: test-net.qt.local + depends_on: + - apache2 + volumes: + - ./common:/common:ro + - ./squid:/service:ro + entrypoint: common/startup.sh + command: service/squid.sh + network_mode: "host" + + vsftpd: + image: qt-test-server-vsftpd:18896604c7e90b543e56d80c8a8aabdb65a590d0 + container_name: qt-test-server-vsftpd + domainname: test-net.qt.local + volumes: + - ./common:/common:ro + - ./vsftpd:/service:ro + entrypoint: common/startup.sh + command: service/vsftpd.sh + network_mode: "host" + + ftp-proxy: + image: qt-test-server-ftp-proxy:2c6c8f1ab6a364b540c43d705fb6f15a585cb2af + container_name: qt-test-server-ftp-proxy + domainname: test-net.qt.local + depends_on: + - vsftpd + volumes: + - ./common:/common:ro + - ./ftp-proxy:/service:ro + entrypoint: common/startup.sh + command: service/ftp-proxy.sh + network_mode: "host" + + danted: + image: qt-test-server-danted:2d5eea7356dd0ba25f3c12d1cba00d70770da1b0 + container_name: qt-test-server-danted + domainname: test-net.qt.local + depends_on: + - apache2 + - vsftpd + - ftp-proxy + volumes: + - ./common:/common:ro + - ./danted:/service:ro + entrypoint: common/startup.sh + command: service/danted.sh + network_mode: "host" + environment: + - danted_internal=${MACHINE_IP:-eth0} + - danted_external=${MACHINE_IP:-eth0} + - danted_auth_internal=${MACHINE_IP:-eth0} + - danted_auth_external=${MACHINE_IP:-eth0} diff --git a/tests/testserver/vsftpd/vsftpd.sh b/tests/testserver/vsftpd/vsftpd.sh index 1ba1a8c347..845c576534 100755 --- a/tests/testserver/vsftpd/vsftpd.sh +++ b/tests/testserver/vsftpd/vsftpd.sh @@ -43,7 +43,7 @@ cp $TESTDATA/vsftpd.{conf,user_list} /etc/ # Resolve error message "vsftpd failed - probably invalid config" during boot command='start-stop-daemon --start --background -m --oknodo --pidfile /var/run/vsftpd/vsftpd.pid' command+=' --exec ${DAEMON}' -sed -i "s,$command.*$,$command; sleep 1," /etc/init.d/vsftpd +sed -i "s,$command.*$,$command; sleep 10," /etc/init.d/vsftpd # Populate the FTP sites: su $USER -c "cp -r $TESTDATA/ftp ~/ftp" |