diff options
Diffstat (limited to 'tests')
137 files changed, 2605 insertions, 263 deletions
diff --git a/tests/auto/installer/appendfileoperation/data/repository/Updates.xml b/tests/auto/installer/appendfileoperation/data/repository/Updates.xml index a1c8f6aa2..f12d387a1 100644 --- a/tests/auto/installer/appendfileoperation/data/repository/Updates.xml +++ b/tests/auto/installer/appendfileoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,6 +10,7 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>750eda14d867849aeb2f47d620f6e5f32134f375</SHA1> <DownloadableArchives>content.7z</DownloadableArchives> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp b/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp index 9eb1e2401..743e4c625 100644 --- a/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp +++ b/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp @@ -81,8 +81,7 @@ private slots: QVERIFY(!op.performOperation()); QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); - QCOMPARE(op.errorString(), QString("Invalid arguments in AppendFile: " - "0 arguments given, exactly 2 arguments expected.")); + QCOMPARE(op.errorString(), QString("Invalid arguments in AppendFile: 0 arguments given, 2 to 4 arguments expected in the form: <filename> <text to apply> [UNDOOPERATION, \"\"].")); op.setArguments(QStringList() << "" << ""); QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified"); @@ -98,10 +97,14 @@ private slots: QTest::addColumn<QString>("source"); QTest::addColumn<QString>("append"); QTest::addColumn<QString>("expected"); + QTest::addColumn<bool>("overrideUndo"); QTest::newRow("newline") << "Line1\nLine2\nLine3\n" << "AppendedText" - << "Line1\nLine2\nLine3\nAppendedText"; + << "Line1\nLine2\nLine3\nAppendedText" << false; QTest::newRow("no newline") << "Lorem ipsum " << "dolore sit amet" - << "Lorem ipsum dolore sit amet"; + << "Lorem ipsum dolore sit amet" << false; + + QTest::newRow("no undo") << "Lorem ipsum " << "dolore sit amet" + << "Lorem ipsum dolore sit amet" << true; } void testAppendText() @@ -109,6 +112,7 @@ private slots: QFETCH(QString, source); QFETCH(QString, append); QFETCH(QString, expected); + QFETCH(bool, overrideUndo); QFile file(m_testFilePath); QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); @@ -117,20 +121,29 @@ private slots: stream << source << Qt::flush; file.close(); - AppendFileOperation op; - op.setArguments(QStringList() << m_testFilePath << append); + AppendFileOperation *op = new AppendFileOperation(); + op->setArguments(QStringList() << m_testFilePath << append); + if (overrideUndo) + op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION")); - op.backup(); - QVERIFY(QFileInfo(op.value("backupOfFile").toString()).exists()); + op->backup(); + QVERIFY(QFileInfo(op->value("backupOfFile").toString()).exists()); - QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(op->performOperation(), op->errorString().toLatin1()); QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); QCOMPARE(stream.readAll(), expected); file.close(); - QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); + QVERIFY2(op->undoOperation(), op->errorString().toLatin1()); QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); - QCOMPARE(stream.readAll(), source); + if (overrideUndo) + QCOMPARE(stream.readAll(), expected); + else + QCOMPARE(stream.readAll(), source); + QString backupFileName = op->value("backupOfFile").toString(); + delete op; + QVERIFY(!QFileInfo::exists(backupFileName)); + file.close(); QVERIFY(file.remove()); diff --git a/tests/auto/installer/binaryformat/tst_binaryformat.cpp b/tests/auto/installer/binaryformat/tst_binaryformat.cpp index 7e0f5ed24..2fcad0b38 100644 --- a/tests/auto/installer/binaryformat/tst_binaryformat.cpp +++ b/tests/auto/installer/binaryformat/tst_binaryformat.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -26,6 +26,8 @@ ** **************************************************************************/ +#include "../shared/packagemanager.h" + #include <binarycontent.h> #include <binaryformat.h> #include <errors.h> @@ -51,8 +53,8 @@ struct Layout : public QInstaller::BinaryLayout class TestOperation : public KDUpdater::UpdateOperation { public: - explicit TestOperation(const QString &name) - : KDUpdater::UpdateOperation(nullptr) + explicit TestOperation(const QString &name, PackageManagerCore *core = nullptr) + : KDUpdater::UpdateOperation(core) { setName(name); } virtual void backup() {} @@ -392,6 +394,45 @@ private slots: resource->close(); } + void testXmlDocumentParsing() + { + PackageManagerCore core; + core.setValue(scTargetDir, QLatin1String("relocatable_targetdir")); + + TestOperation op(QLatin1String("Operation 3"), &core); + QStringList stringListValue = (QStringList() << QLatin1String("list_value1") << QLatin1String("list_value2")); + op.setValue(QLatin1String("string_list"), stringListValue); + + const QString stringValue = core.value(scTargetDir) + QLatin1String(", string_value1"); + op.setValue(QLatin1String("string"), stringValue); + + QVariantMap map; + map.insert(QLatin1String("key1"), 1); + map.insert(QLatin1String("key2"), QLatin1String("map_value2")); + op.setValue(QLatin1String("variant_map"), map); + + QDomDocument document = op.toXml(); + QVERIFY2(document.toString().contains(QLatin1String("@RELOCATABLE_PATH@")), + "TargetDir not replaced with @RELOCATABLE_PATH@"); + + op.fromXml(document); // Resets the operation values from written QDomDocuments + + QCOMPARE(op.value(QLatin1String("string_list")), stringListValue); + QVERIFY2(!op.value(QLatin1String("string")).toString().contains(QLatin1String("@RELOCATABLE_PATH@")), + "@RELOCATABLE@ not replaced with TargetDir"); + QCOMPARE(op.value(QLatin1String("variant_map")), map); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QCOMPARE(op.value(QLatin1String("string_list")).metaType().id(), QMetaType::QStringList); + QCOMPARE(op.value(QLatin1String("string")).metaType().id(), QMetaType::QString); + QCOMPARE(op.value(QLatin1String("variant_map")).metaType().id(), QMetaType::QVariantMap); +#else + QCOMPARE(op.value(QLatin1String("string_list")).type(), QMetaType::QStringList); + QCOMPARE(op.value(QLatin1String("string")).type(), QMetaType::QString); + QCOMPARE(op.value(QLatin1String("variant_map")).type(), QMetaType::QVariantMap); +#endif + } + void cleanupTestCase() { m_manager.clear(); diff --git a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp index 43bd15288..5978b3bb2 100644 --- a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp +++ b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -125,7 +125,7 @@ private slots: const QString debugMessage = QString("Exception while loading the component script"); const QRegularExpression re(debugMessage); QTest::ignoreMessage(QtWarningMsg, re); - invalidScriptComponent->loadComponentScript(":///data/broken_script.qs"); + invalidScriptComponent->evaluateComponentScript(":///data/broken_script.qs"); model->reset(components); testModelState(model, m_checkedComponentsWithBrokenScript, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithBrokenScript); @@ -145,7 +145,7 @@ private slots: Component *componentDependingOnMissingDependency = core.componentByName("componentd"); componentDependingOnMissingDependency->addDependency("componentmissingdependency"); - core.componentsToInstallNeedsRecalculation(); + core.recalculateAllComponents(); model->reset(components); testModelState(model, m_checkedComponentsWithMissingDependency, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithMissingDependency); @@ -157,6 +157,7 @@ private: { UpdatesInfo updatesInfo; updatesInfo.setFileName(":///data/updates.xml"); + updatesInfo.parseFile(); const QList<UpdateInfo> updateInfos = updatesInfo.updatesInfo(); QList <Component*> components; diff --git a/tests/auto/installer/clientserver/BLACKLIST b/tests/auto/installer/clientserver/BLACKLIST deleted file mode 100644 index a328d26e7..000000000 --- a/tests/auto/installer/clientserver/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[testQProcessWrapper] -rhel-7.6 ci diff --git a/tests/auto/installer/clientserver/tst_clientserver.cpp b/tests/auto/installer/clientserver/tst_clientserver.cpp index 5aa40a5a3..7b3e65c4a 100644 --- a/tests/auto/installer/clientserver/tst_clientserver.cpp +++ b/tests/auto/installer/clientserver/tst_clientserver.cpp @@ -369,7 +369,6 @@ private slots: QCOMPARE(settings.contains("key"), false); const QDateTime dateTime = QDateTime::currentDateTimeUtc(); - QCOMPARE(settings.iniCodec(), nullptr); // The wrapper does not support this method, but assume: // QCOMPARE(wrapper.iniCodec(), QTextCodec::codecForName("UTF-8")); wrapper.setValue("dateTime", dateTime); @@ -468,6 +467,9 @@ private slots: void testQProcessWrapper() { + #ifdef Q_OS_LINUX + QSKIP("This test failes in CI redhat"); + #endif RemoteServer server; QString socketName = QUuid::createUuid().toString(); server.init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Production); diff --git a/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml index 72b7938d9..7957cde4e 100644 --- a/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml +++ b/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>4b124046df83fcd12fb7126b795a8b5a62602806</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml index 81831ed5b..3b5e22cc0 100644 --- a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml +++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml @@ -170,4 +170,14 @@ <DownloadableArchives>content.7z</DownloadableArchives> <Virtual>true</Virtual> </PackageUpdate> + <PackageUpdate> + <Name>componentJ</Name> + <DisplayName>component J</DisplayName> + <Description>This component has post install script.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>50</SortingPriority> + <DownloadableArchives>content.7z</DownloadableArchives> + <Script postLoad="True">postLoadscript.js</Script> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..58ff52baa --- /dev/null +++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z Binary files differnew file mode 100644 index 000000000..be99410a8 --- /dev/null +++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z diff --git a/tests/auto/installer/commandlineinstall/settings.qrc b/tests/auto/installer/commandlineinstall/settings.qrc index 824517e1e..992dbfd58 100644 --- a/tests/auto/installer/commandlineinstall/settings.qrc +++ b/tests/auto/installer/commandlineinstall/settings.qrc @@ -14,6 +14,8 @@ <file>data/installPackagesRepository/componentG/1.0.0content.7z</file> <file>data/installPackagesRepository/componentH/1.0.0content.7z</file> <file>data/installPackagesRepository/componentI/1.0.0content.7z</file> + <file>data/installPackagesRepository/componentJ/1.0.0content.7z</file> + <file>data/installPackagesRepository/componentJ/1.0.0meta.7z</file> <file>data/installPackagesRepository/componentG/1.0.0meta.7z</file> <file>data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z</file> diff --git a/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp index 89f6153ed..4dfadbad6 100644 --- a/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp +++ b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -34,9 +34,7 @@ #include <QLoggingCategory> #include <QTest> #include <QRegularExpression> - -#include <iostream> -#include <sstream> +#include <QSignalSpy> using namespace QInstaller; @@ -47,20 +45,30 @@ class tst_CommandLineInstall : public QObject { Q_OBJECT +public: + void ignoreAvailablePackagesMissingMessages() + { + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Searching packages with regular expression:")); + QTest::ignoreMessage(QtDebugMsg, "No matching packages found."); + } + + void ignoreInstallPackageFailsMessages(const QRegularExpression ®Exp) + { + QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information..."); + QTest::ignoreMessage(QtDebugMsg, regExp); + } + private slots: void testListAvailablePackages() { QString loggingRules = (QLatin1String("ifw.* = false\n")); - QTest::ignoreMessage(QtDebugMsg, "Operations sanity check succeeded."); - + QLoggingCategory::setFilterRules(loggingRules); QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager (m_installDir, ":///data/repository")); - QLoggingCategory::setFilterRules(loggingRules); auto func = &PackageManagerCore::listAvailablePackages; - - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n" " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n" @@ -68,29 +76,29 @@ private slots: " <package name=\"C\" displayname=\"C\" version=\"1.0.0-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("."), QHash<QString, QString>()); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n" " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("A"), QHash<QString, QString>()); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n" " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("A.*"), QHash<QString, QString>()); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("^B"), QHash<QString, QString>()); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("^B.*"), QHash<QString, QString>()); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"C\" displayname=\"C\" version=\"1.0.0-1\"/>\n" "</availablepackages>\n"), func, QLatin1String("^C"), QHash<QString, QString>()); @@ -100,7 +108,7 @@ private slots: { "Version", "1.0.2" }, { "DisplayName", "A" } }; - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n" " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n" @@ -108,18 +116,16 @@ private slots: searchHash.clear(); searchHash.insert("Default", "false"); - verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n" "<availablepackages>\n" " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n" "</availablepackages>\n"), func, QString(), searchHash); - // Need to change rules here to catch messages QLoggingCategory::setFilterRules("ifw.* = true\n"); - - QTest::ignoreMessage(QtDebugMsg, "No matching packages found."); + ignoreAvailablePackagesMissingMessages(); core->listAvailablePackages(QLatin1String("C.virt")); - QTest::ignoreMessage(QtDebugMsg, "No matching packages found."); + ignoreAvailablePackagesMissingMessages(); core->listAvailablePackages(QLatin1String("C.virt.subcomponent")); } @@ -128,37 +134,31 @@ private slots: QString loggingRules = (QLatin1String("ifw.* = false\n" "ifw.installer.installlog = true\n")); + QLoggingCategory::setFilterRules(loggingRules); + QTest::ignoreMessage(QtDebugMsg, "Operations sanity check succeeded."); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Using metadata cache from ")); QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager (m_installDir, ":///data/uninstallableComponentsRepository")); - QLoggingCategory::setFilterRules(loggingRules); - - QTest::ignoreMessage(QtDebugMsg, "Preparing meta information download..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install component A. Component " - "is installed only as automatic dependency to autoDep.\n")); + ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component A. Component " + "is installed only as automatic dependency to autoDep.\n")); QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList() << QLatin1String("A"))); - QTest::ignoreMessage(QtDebugMsg, "Preparing meta information download..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install component AB. Component " - "is not checkable, meaning you have to select one of the subcomponents.\n")); + ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component AB. Component " + "is not checkable, meaning you have to select one of the subcomponents.\n")); QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList() << QLatin1String("AB"))); - QTest::ignoreMessage(QtDebugMsg, "Preparing meta information download..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install B. Component is virtual.\n")); + ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B. Component is virtual.\n")); QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList() << QLatin1String("B"))); - QTest::ignoreMessage(QtDebugMsg, "Preparing meta information download..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install B.subcomponent. Component " - "is a descendant of a virtual component B.\n")); + ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B.subcomponent. Component " + "is a descendant of a virtual component B.\n")); QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList() << QLatin1String("B.subcomponent"))); - QTest::ignoreMessage(QtDebugMsg, "Preparing meta information download..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Cannot install MissingComponent. " - "Component not found.\n")); QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList() << QLatin1String("MissingComponent"))); QCOMPARE(PackageManagerCore::Canceled, core->status()); @@ -169,8 +169,6 @@ private slots: QString loggingRules = (QLatin1String("ifw.installer.installog = true\n")); PackageManagerCore core; core.setPackageManager(); - QString appFilePath = QCoreApplication::applicationFilePath(); - core.setAllowedRunningProcesses(QStringList() << appFilePath); QLoggingCategory::setFilterRules(loggingRules); QVERIFY(QFile::copy(":/data/componentsFromInstallPackagesRepository.xml", m_installDir + "/components.xml")); @@ -209,13 +207,13 @@ private slots: core.setValue(scTargetDir, testDirectory); - verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n" "<localpackages>\n" " <package name=\"A\" displayname=\"A Title\" version=\"1.0.2-1\"/>\n" " <package name=\"B\" displayname=\"B Title\" version=\"1.0.0-1\"/>\n" "</localpackages>\n"), func, QString()); - verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n" + VerifyInstaller::verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n" "<localpackages>\n" " <package name=\"A\" displayname=\"A Title\" version=\"1.0.2-1\"/>\n" "</localpackages>\n"), func, QLatin1String("A")); @@ -224,6 +222,57 @@ private slots: QVERIFY(dir.removeRecursively()); } + void testCategoryInstall_data() + { + QTest::addColumn<QString>("repository"); + QTest::addColumn<QStringList>("installComponents"); + QTest::addColumn<PackageManagerCore::Status>("status"); + + + QTest::newRow("Category installation") + << ":///data/installPackagesRepository" + << (QStringList() << "componentE") + << PackageManagerCore::Success; + } + + void testCategoryInstall() + { + QFETCH(QString, repository); + QFETCH(QStringList, installComponents); + QFETCH(PackageManagerCore::Status, status); + + + QString loggingRules = (QLatin1String("ifw.* = true\n")); + QLoggingCategory::setFilterRules(loggingRules); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir)); + + RepositoryCategory category; + category.setEnabled(false); + category.setDisplayName(QLatin1String("category")); + + Repository repo = Repository::fromUserInput(repository); + category.addRepository(repo); + + QSet<RepositoryCategory> categories; + categories.insert(category); + + core->settings().addRepositoryCategories(categories); + + QSignalSpy spy(core.data(), &PackageManagerCore::statusChanged); + QCOMPARE(core->installSelectedComponentsSilently(QStringList() << installComponents), status); + + QList<int> statusArguments; + + for (qsizetype i = 0; i < spy.size(); ++i) { + QList<QVariant> tempList = spy.at(i); + statusArguments << tempList.at(0).toInt(); + } + + QVERIFY(statusArguments.contains(PackageManagerCore::NoPackagesFound)); + QVERIFY(statusArguments.contains(PackageManagerCore::Success)); + } + void testInstall_data() { QTest::addColumn<QString>("repository"); @@ -722,6 +771,21 @@ private slots: QVERIFY(file.remove()); } + void testPostScript() + { + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/installPackagesRepository")); + QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << QLatin1String("componentJ"))); + VerifyInstaller::verifyInstallerResources(m_installDir, "componentJ", "1.0.0content.txt"); //Selected + VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt"); //Dependency for componentG + VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); //ForcedInstall + VerifyInstaller::verifyInstallerResources(m_installDir, "componentG", "1.0.0content.txt"); //Default + + //componentJ is extracted to "extractToAnotherPath" -folder in post install script + bool fileExists = QFileInfo::exists(m_installDir + QDir::separator() + "extractToAnotherPath" + QDir::separator() + "installcontentJ.txt"); + QVERIFY2(fileExists, QString("File \"%1\" does not exist.").arg("installcontentJ.txt").toLatin1()); + } + void init() { m_installDir = QInstaller::generateTemporaryFileName(); @@ -740,21 +804,6 @@ private slots: } private: - template <typename Func, typename... Args> - void verifyListPackagesMessage(PackageManagerCore *core, const QString &message, - Func func, Args... args) - { - std::ostringstream stream; - std::streambuf *buf = std::cout.rdbuf(); - std::cout.rdbuf(stream.rdbuf()); - - (core->*func)(std::forward<Args>(args)...); - - std::cout.rdbuf(buf); - QVERIFY(stream && stream.str() == message.toStdString()); - } - -private: QString m_installDir; }; diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml index 9e01f1800..de6e66525 100644 --- a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml @@ -160,4 +160,20 @@ <ForcedUpdate>true</ForcedUpdate> <DownloadableArchives>content.7z</DownloadableArchives> </PackageUpdate> + <PackageUpdate> + <Name>qt.tools.qtcreator</Name> + <DisplayName>Component qtcreator. Depends on virtual component</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <Dependencies>qt.tools.qtcreator.enterprise.plugins</Dependencies> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> + <PackageUpdate> + <Name>qt.tools.qtcreator.enterprise.plugins</Name> + <DisplayName>enterprise plugin component</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <DownloadableArchives>content.7z</DownloadableArchives> + <Virtual>true</Virtual> + </PackageUpdate> </Updates> diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..5c7c4f37d --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..e5e4178a4 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml new file mode 100644 index 000000000..f55998c48 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml @@ -0,0 +1,32 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>qt.tools.qtcreator</Name> + <DisplayName>Component qtcreator. Dependency removed</DisplayName> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> + <PackageUpdate> + <Name>qt.tools.qtcreator_gui</Name> + <DisplayName>Component K. Autodepends on componentJ</DisplayName> + <Description>Component K. Autodepends on componentJ</Description> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <AutoDependOn>qt.tools.qtcreator</AutoDependOn> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> + <PackageUpdate> + <Name>qt.tools.qtcreator_gui.enterprise.plugins</Name> + <DisplayName>enterprise plugins, replaces another component</DisplayName> + <Version>2.0.0</Version> + <ReleaseDate>2018-03-14</ReleaseDate> + <Virtual>true</Virtual> + <Replaces>qt.tools.qtcreator.enterprise.plugins</Replaces> + <AutoDependOn>qt.tools.qtcreator</AutoDependOn> + <UpdateFile UncompressedSize="99" OS="Any" CompressedSize="305"/> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..f2b69fc13 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..03d191cb5 --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..515c3a5cf --- /dev/null +++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z diff --git a/tests/auto/installer/commandlineupdate/settings.qrc b/tests/auto/installer/commandlineupdate/settings.qrc index d398abe30..c8f328d6b 100644 --- a/tests/auto/installer/commandlineupdate/settings.qrc +++ b/tests/auto/installer/commandlineupdate/settings.qrc @@ -17,6 +17,8 @@ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file> <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file> + <file>data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z</file> + <file>data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/Updates.xml</file> <file>data/installPackagesRepositoryUpdate/componentA/1.0.0content.7z</file> <file>data/installPackagesRepositoryUpdate/componentB/2.0.0content.7z</file> @@ -52,5 +54,9 @@ <file>data/repositoryWithDependencyToEssential/Updates.xml</file> <file>data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7z</file> <file>data/repositoryWithDependencyToEssential/componentA/3.0.0content.7z</file> + <file>data/repositoryUpdateWithReplacements/Updates.xml</file> + <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z</file> + <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z</file> + <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp index 338157cba..0faeecf74 100644 --- a/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp +++ b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp @@ -295,7 +295,7 @@ private slots: componentResourcesAfterUpdate.append(ComponentResource("componentA", "1.0.0content.txt")); componentResourcesAfterUpdate.append(ComponentResource("componentB", "2.0.0content.txt")); componentResourcesAfterUpdate.append(ComponentResource("componentD", "2.0.0content.txt"));//AutodepenOn componentA,componentB - componentResourcesAfterUpdate.append(ComponentResource("componentE", "2.0.0content.txt"));//ForcedInstall + componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt"));//ForcedInstall, not updated without user selection componentResourcesAfterUpdate.append(ComponentResource("componentG", "1.0.0content.txt")); deletedComponentResources.clear(); @@ -316,8 +316,38 @@ private slots: << componentResourcesAfterUpdate << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt" << "installcontentD_update.txt" << "installcontentB_update.txt" - << "installcontentE_update.txt" << "installcontentG.txt") + << "installcontentE.txt" << "installcontentG.txt") << deletedComponentResources; + + /*********** Update packages with replacements **********/ + componentResources.clear(); + componentResources.append(ComponentResource("qt.tools.qtcreator", "1.0.0content.txt")); + componentResources.append(ComponentResource("qt.tools.qtcreator.enterprise.plugins", "1.0.0content.txt")); + componentResources.append(ComponentResource("componentE", "1.0.0content.txt")); + + componentResourcesAfterUpdate.clear(); + componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator", "2.0.0content.txt")); + componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator_gui", "2.0.0content.txt")); + componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator_gui.enterprise.plugins", "2.0.0content.txt")); + componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt")); + + deletedComponentResources.clear(); + deletedComponentResources.append(ComponentResource("qt.tools.qtcreator.enterprise.plugins", "1.0.0content.txt")); + + QTest::newRow("Update packages with replacements") + << ":///data/installPackagesRepository" + << (QStringList()<< "qt.tools.qtcreator") + << PackageManagerCore::Success + << componentResources + << (QStringList() << "components.xml" << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt" + << "installcontent.txt" << "qtcreator.txt" << "plugins.txt") + << ":///data/repositoryUpdateWithReplacements" + << (QStringList() << "qt.tools.qtcreator") + << PackageManagerCore::Success + << componentResourcesAfterUpdate + << (QStringList() << "components.xml" << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt" + << "installcontent.txt" << "gui.txt" << "qtcreator2.txt" << "gui_plugins.txt") + << deletedComponentResources; } void testUpdate() diff --git a/tests/auto/installer/componentalias/componentalias.pro b/tests/auto/installer/componentalias/componentalias.pro new file mode 100644 index 000000000..efbc0268f --- /dev/null +++ b/tests/auto/installer/componentalias/componentalias.pro @@ -0,0 +1,8 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +SOURCES = tst_componentalias.cpp + +RESOURCES += settings.qrc diff --git a/tests/auto/installer/componentalias/data/aliases-optional.xml b/tests/auto/installer/componentalias/data/aliases-optional.xml new file mode 100644 index 000000000..bc16013b7 --- /dev/null +++ b/tests/auto/installer/componentalias/data/aliases-optional.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Aliases> + <Alias> + <Name>set-A</Name> + <DisplayName>Installation A (optional component requirement)</DisplayName> + <Description>Installs component A</Description> + <Version>2.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>A</RequiredComponents> + <OptionalComponents>component-nonexistent,B</OptionalComponents> + </Alias> + <Alias> + <Name>set-full</Name> + <DisplayName>Full installation (optional alias requirement)</DisplayName> + <Description>Installs all components</Description> + <Version>2.0.0</Version> + <Virtual>false</Virtual> + <OptionalAliases>set-A,set-nonexistent</OptionalAliases> + </Alias> + <Alias> + <Name>set-optional-broken</Name> + <DisplayName>Optionally requires broken alias</DisplayName> + <Description>Optionally requires broken alias</Description> + <Version>2.0.0</Version> + <Virtual>false</Virtual> + <OptionalAliases>set-broken</OptionalAliases> + </Alias> + <Alias> + <Name>set-broken</Name> + <DisplayName>Requires non-existent alias</DisplayName> + <Description>Requires non-existent alias</Description> + <Version>2.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-nonexistent</RequiredAliases> + </Alias> +</Aliases> diff --git a/tests/auto/installer/componentalias/data/aliases-priority.xml b/tests/auto/installer/componentalias/data/aliases-priority.xml new file mode 100644 index 000000000..f90d006b2 --- /dev/null +++ b/tests/auto/installer/componentalias/data/aliases-priority.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Aliases> + <Alias> + <Name>set-A</Name> + <DisplayName>Installation A (priority)</DisplayName> + <Description>Installs component A</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>A</RequiredComponents> + </Alias> + <Alias> + <Name>set-B</Name> + <DisplayName>Virtual installation B (priority)</DisplayName> + <Description>Installs component B</Description> + <Version>1.0.0</Version> + <Virtual>true</Virtual> + <RequiredComponents>B</RequiredComponents> + </Alias> + <Alias> + <Name>set-D</Name> + <DisplayName>Installation D (Unstable) (priority)</DisplayName> + <Description>Installs missing component D</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>D</RequiredComponents> + </Alias> + <Alias> + <Name>set-full</Name> + <DisplayName>Full installation (priority)</DisplayName> + <Description>Installs all components</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-A,set-B</RequiredAliases> + <RequiredComponents>C</RequiredComponents> + </Alias> +</Aliases> diff --git a/tests/auto/installer/componentalias/data/aliases-versions.xml b/tests/auto/installer/componentalias/data/aliases-versions.xml new file mode 100644 index 000000000..993e14673 --- /dev/null +++ b/tests/auto/installer/componentalias/data/aliases-versions.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Aliases> + <Alias> + <Name>set-A</Name> + <DisplayName>Installation A (updated)</DisplayName> + <Description>Installs component A</Description> + <Version>2.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>A</RequiredComponents> + </Alias> + <Alias> + <Name>set-B</Name> + <DisplayName>Virtual installation B (updated)</DisplayName> + <Description>Installs component B</Description> + <Version>1.1.0</Version> + <Virtual>true</Virtual> + <RequiredComponents>B</RequiredComponents> + </Alias> + <Alias> + <Name>set-D</Name> + <DisplayName>Installation D (Unstable) (updated)</DisplayName> + <Description>Installs missing component D</Description> + <Version>1.2.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>D</RequiredComponents> + </Alias> + <Alias> + <Name>set-full</Name> + <DisplayName>Full installation (updated)</DisplayName> + <Description>Installs all components</Description> + <Version>3.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-A,set-B</RequiredAliases> + <RequiredComponents>C</RequiredComponents> + </Alias> +</Aliases> diff --git a/tests/auto/installer/componentalias/data/aliases.json b/tests/auto/installer/componentalias/data/aliases.json new file mode 100644 index 000000000..4c78e20d2 --- /dev/null +++ b/tests/auto/installer/componentalias/data/aliases.json @@ -0,0 +1,38 @@ +{ + "alias-packages": [ + { + "Description": "Installs component A", + "DisplayName": "Installation A (JSON)", + "Name": "set-A-json", + "RequiredComponents": [ + "A" + ], + "Version": "1.0.0", + "Virtual": false + }, + { + "Description": "Installs component B", + "DisplayName": "Virtual installation B (JSON)", + "Name": "set-B-json", + "RequiredComponents": [ + "B" + ], + "Version": "1.0.0", + "Virtual": true + }, + { + "Description": "Installs all components", + "DisplayName": "Full installation (JSON)", + "Name": "set-full-json", + "RequiredAliases": [ + "set-A-json", + "set-B-json" + ], + "RequiredComponents": [ + "C" + ], + "Version": "1.0.0", + "Virtual": false + } + ] +} diff --git a/tests/auto/installer/componentalias/data/repository/Updates.xml b/tests/auto/installer/componentalias/data/repository/Updates.xml new file mode 100644 index 000000000..e128590dc --- /dev/null +++ b/tests/auto/installer/componentalias/data/repository/Updates.xml @@ -0,0 +1,43 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>true</Checksum> + <PackageUpdate> + <Name>A</Name> + <DisplayName>A</DisplayName> + <Description>Example component A</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + </PackageUpdate> + <PackageUpdate> + <Name>B</Name> + <DisplayName>B</DisplayName> + <Description>Example component B</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + </PackageUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + </PackageUpdate> + <PackageUpdate> + <Name>C.subcomponent</Name> + <DisplayName>Subcomponent of C</DisplayName> + <Description>Example subcomponent</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + </PackageUpdate> + <PackageUpdate> + <Name>C.subcomponent.subcomponent</Name> + <DisplayName>Subcomponent of subcomponent component</DisplayName> + <Description>Example subcomponent of subcomponent</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml b/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml new file mode 100644 index 000000000..278ae918b --- /dev/null +++ b/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<Aliases> + <Alias> + <Name>set-A</Name> + <DisplayName>Installation A</DisplayName> + <Description>Installs component A</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>A</RequiredComponents> + </Alias> + <Alias> + <Name>set-B</Name> + <DisplayName>Virtual installation B</DisplayName> + <Description>Installs component B</Description> + <Version>1.0.0</Version> + <Virtual>true</Virtual> + <RequiredComponents>B</RequiredComponents> + </Alias> + <Alias> + <Name>set-D</Name> + <DisplayName>Installation D (Unstable)</DisplayName> + <Description>Installs missing component D</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredComponents>D</RequiredComponents> + </Alias> + <Alias> + <Name>set-E</Name> + <DisplayName>Installation E (Requires unstable)</DisplayName> + <Description>Installs set E</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-D</RequiredAliases> + </Alias> + <Alias> + <Name>set-F</Name> + <DisplayName>Installation F (Requires alias that refers another unstable)</DisplayName> + <Description>Installs set F</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-E</RequiredAliases> + </Alias> + <Alias> + <Name>set-full</Name> + <DisplayName>Full installation</DisplayName> + <Description>Installs all components</Description> + <Version>1.0.0</Version> + <Virtual>false</Virtual> + <RequiredAliases>set-A,set-B</RequiredAliases> + <RequiredComponents>C</RequiredComponents> + </Alias> +</Aliases> diff --git a/tests/auto/installer/componentalias/metadata/installer-config/config.xml b/tests/auto/installer/componentalias/metadata/installer-config/config.xml new file mode 100644 index 000000000..9e2b5af55 --- /dev/null +++ b/tests/auto/installer/componentalias/metadata/installer-config/config.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<Installer> + <Name>test</Name> + <Version>1.0.0</Version> + <AliasDefinitionsFile>aliases.xml</AliasDefinitionsFile> +</Installer> diff --git a/tests/auto/installer/componentalias/settings.qrc b/tests/auto/installer/componentalias/settings.qrc new file mode 100644 index 000000000..771586edd --- /dev/null +++ b/tests/auto/installer/componentalias/settings.qrc @@ -0,0 +1,11 @@ +<RCC> + <qresource prefix="/"> + <file>data/repository/Updates.xml</file> + <file>data/aliases.json</file> + <file>data/aliases-priority.xml</file> + <file>data/aliases-versions.xml</file> + <file>data/aliases-optional.xml</file> + <file>metadata/installer-config/config.xml</file> + <file>metadata/installer-config/aliases.xml</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/componentalias/tst_componentalias.cpp b/tests/auto/installer/componentalias/tst_componentalias.cpp new file mode 100644 index 000000000..f6742af1f --- /dev/null +++ b/tests/auto/installer/componentalias/tst_componentalias.cpp @@ -0,0 +1,269 @@ +/************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $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 "../shared/packagemanager.h" +#include "../shared/verifyinstaller.h" + +#include <packagemanagercore.h> +#include <componentalias.h> + +#include <QTest> +#include <QLoggingCategory> + +using namespace QInstaller; + +class tst_ComponentAlias : public QObject +{ + Q_OBJECT + +private slots: + void init() + { + m_installDir = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(m_installDir)); + } + + void cleanup() + { + QDir dir(m_installDir); + QVERIFY(dir.removeRecursively()); + } + + void testSearchAlias() + { + QString loggingRules = (QLatin1String("ifw.* = false\n")); + + QLoggingCategory::setFilterRules(loggingRules); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager + (m_installDir, ":///data/repository")); + + core->setCommandLineInstance(true); + + auto listMethod = &PackageManagerCore::listAvailableAliases; + + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n" + "Name: set-A\n" + "Display name: Installation A\n" + "Description: Installs component A\n" + "Version: 1.0.0\n" + "Components: A\n" + "Required aliases: \n" + "Optional components: \n" + "Optional aliases: \n" + "========================================\n" + "Name: set-full\n" + "Display name: Full installation\n" + "Description: Installs all components\n" + "Version: 1.0.0\n" + "Components: C\n" + "Required aliases: set-A,set-B\n" + "Optional components: \n" + "Optional aliases: \n"), listMethod, QString()); + + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n" + "Name: set-A\n" + "Display name: Installation A\n" + "Description: Installs component A\n" + "Version: 1.0.0\n" + "Components: A\n" + "Required aliases: \n" + "Optional components: \n" + "Optional aliases: \n"), listMethod, QLatin1String("A")); + } + + void testAliasSourceWithPriority() + { + QString loggingRules = (QLatin1String("ifw.* = false\n")); + + QLoggingCategory::setFilterRules(loggingRules); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager + (m_installDir, ":///data/repository")); + + core->setCommandLineInstance(true); + core->addAliasSource(AliasSource(AliasSource::SourceFileFormat::Xml, + ":///data/aliases-priority.xml", 1)); + + auto listMethod = &PackageManagerCore::listAvailableAliases; + + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n" + "Name: set-A\n" + "Display name: Installation A (priority)\n" + "Description: Installs component A\n" + "Version: 1.0.0\n" + "Components: A\n" + "Required aliases: \n" + "Optional components: \n" + "Optional aliases: \n" + "========================================\n" + "Name: set-full\n" + "Display name: Full installation (priority)\n" + "Description: Installs all components\n" + "Version: 1.0.0\n" + "Components: C\n" + "Required aliases: set-A,set-B\n" + "Optional components: \n" + "Optional aliases: \n"), listMethod, QString()); + } + + void testAliasSourceWithVersionCompare() + { + QString loggingRules = (QLatin1String("ifw.* = false\n")); + + QLoggingCategory::setFilterRules(loggingRules); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager + (m_installDir, ":///data/repository")); + + core->setCommandLineInstance(true); + core->addAliasSource(AliasSource(AliasSource::SourceFileFormat::Xml, + ":///data/aliases-versions.xml", -1)); + + auto listMethod = &PackageManagerCore::listAvailableAliases; + + VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n" + "Name: set-A\n" + "Display name: Installation A (updated)\n" + "Description: Installs component A\n" + "Version: 2.0.0\n" + "Components: A\n" + "Required aliases: \n" + "Optional components: \n" + "Optional aliases: \n" + "========================================\n" + "Name: set-full\n" + "Display name: Full installation (updated)\n" + "Description: Installs all components\n" + "Version: 3.0.0\n" + "Components: C\n" + "Required aliases: set-A,set-B\n" + "Optional components: \n" + "Optional aliases: \n"), listMethod, QString()); + } + + void testInstallAlias_data() + { + QTest::addColumn<AliasSource>("additionalSource"); + QTest::addColumn<QStringList>("selectedAliases"); + QTest::addColumn<PackageManagerCore::Status>("status"); + QTest::addColumn<QStringList>("installedComponents"); + + QTest::newRow("Simple alias") + << AliasSource() + << (QStringList() << "set-A") + << PackageManagerCore::Success + << (QStringList() << "A"); + + QTest::newRow("Alias with dependencies") + << AliasSource() + << (QStringList() << "set-full") + << PackageManagerCore::Success + << (QStringList() << "A" << "B" << "C" << "C.subcomponent" << "C.subcomponent.subcomponent"); + + QTest::newRow("Alias with dependencies (JSON source)") + << AliasSource(AliasSource::SourceFileFormat::Json, ":///data/aliases.json", -1) + << (QStringList() << "set-full-json") + << PackageManagerCore::Success + << (QStringList() << "A" << "B" << "C" << "C.subcomponent" << "C.subcomponent.subcomponent"); + + QTest::newRow("Alias with optional components (existent and non-existent)") + << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1) + << (QStringList() << "set-A") + << PackageManagerCore::Success + << (QStringList() << "A" << "B"); + + QTest::newRow("Alias with optional aliases (existent and non-existent)") + << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1) + << (QStringList() << "set-full") + << PackageManagerCore::Success + << (QStringList() << "A" << "B"); + + QTest::newRow("Alias with optional broken alias (will not install)") + << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1) + << (QStringList() << "set-optional-broken") + << PackageManagerCore::Canceled + << QStringList(); + } + + void testInstallAlias() + { + QFETCH(AliasSource, additionalSource); + QFETCH(QStringList, selectedAliases); + QFETCH(PackageManagerCore::Status, status); + QFETCH(QStringList, installedComponents); + + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/repository")); + + core->setCommandLineInstance(true); + + if (!additionalSource.filename.isEmpty()) + core->addAliasSource(additionalSource); + + QCOMPARE(core->installSelectedComponentsSilently(selectedAliases), status); + + for (const QString &component : installedComponents) + QVERIFY(core->componentByName(component)->isInstalled()); + } + + void testInstallAliasFails_data() + { + QTest::addColumn<QStringList>("selectedAliases"); + QTest::addColumn<PackageManagerCore::Status>("status"); + + QTest::newRow("Virtual alias") + << (QStringList() << "set-B") + << PackageManagerCore::Canceled; + + QTest::newRow("Unstable alias") + << (QStringList() << "set-D") + << PackageManagerCore::Canceled; + + QTest::newRow("Nested reference to unstable alias") + << (QStringList() << "set-F") + << PackageManagerCore::Canceled; + } + + void testInstallAliasFails() + { + QFETCH(QStringList, selectedAliases); + QFETCH(PackageManagerCore::Status, status); + + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, ":///data/repository")); + + core->setCommandLineInstance(true); + + QCOMPARE(status, core->installSelectedComponentsSilently(selectedAliases)); + } + +private: + QString m_installDir; +}; + +QTEST_GUILESS_MAIN(tst_ComponentAlias) + +#include "tst_componentalias.moc" diff --git a/tests/auto/installer/componentmodel/data/updates.xml b/tests/auto/installer/componentmodel/data/updates.xml index 3a6139446..cc2da0f8e 100644 --- a/tests/auto/installer/componentmodel/data/updates.xml +++ b/tests/auto/installer/componentmodel/data/updates.xml @@ -8,6 +8,8 @@ <DisplayName xml:lang="ru_RU">Корневая компонента</DisplayName> <DisplayName xml:lang="de_DE">Wurzel Komponente</DisplayName> <Description>Install this example.</Description> + <Description xml:lang="ru_RU">Установите этот пример.</Description> + <Description xml:lang="de_DE">Installieren Sie dieses Beispiel.</Description> <Version>0.1.0-1</Version> <ReleaseDate>2010-09-21</ReleaseDate> <Default>true</Default> diff --git a/tests/auto/installer/componentmodel/tst_componentmodel.cpp b/tests/auto/installer/componentmodel/tst_componentmodel.cpp index 463485d96..276292233 100644 --- a/tests/auto/installer/componentmodel/tst_componentmodel.cpp +++ b/tests/auto/installer/componentmodel/tst_componentmodel.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -59,6 +59,12 @@ static const QMap<QString, QString> rootComponentDisplayNames = { {"de_de", QString::fromUtf8("Wurzel Komponente")} }; +static const QMap<QString, QString> rootComponentDescriptions = { + {"", QLatin1String("Install this example.")}, + {"ru_ru", QString::fromUtf8("Установите этот пример.")}, + {"de_de", QString::fromUtf8("Installieren Sie dieses Beispiel.")} +}; + class tst_ComponentModel : public QObject { Q_OBJECT @@ -367,11 +373,19 @@ private slots: { QStringList localesToTest = { "en_US", "ru_RU", "de_DE", "fr_FR" }; foreach (const QString &localeToTest, localesToTest) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QLocale::setDefault(QLocale(localeToTest)); +#else QLocale::setDefault(localeToTest); +#endif QString expectedName = rootComponentDisplayNames.contains(localeToTest.toLower()) ? rootComponentDisplayNames[localeToTest.toLower()] : rootComponentDisplayNames[QString()]; + QString expectedDescription = rootComponentDescriptions.contains(localeToTest.toLower()) + ? rootComponentDescriptions[localeToTest.toLower()] + : rootComponentDescriptions[QString()]; + setPackageManagerOptions(NoFlags); QList<Component*> rootComponents = loadComponents(); @@ -384,6 +398,9 @@ private slots: const QModelIndex root = model.indexFromComponentName(vendorProduct); QCOMPARE(model.data(root, Qt::DisplayRole).toString(), expectedName); + Component *comp = model.componentFromIndex(root); + QCOMPARE(comp->value("Description"), expectedDescription); + qDeleteAll(rootComponents); } } @@ -513,6 +530,7 @@ private: { UpdatesInfo updatesInfo; updatesInfo.setFileName(":///data/updates.xml"); + updatesInfo.parseFile(); const QList<UpdateInfo> updateInfos = updatesInfo.updatesInfo(); QHash<QString, Component*> components; @@ -529,6 +547,7 @@ private: component->setValue("Virtual", info.data.value("Virtual").toString()); component->setValue("DisplayName", info.data.value("DisplayName").toString()); component->setValue("Checkable", info.data.value("Checkable").toString()); + component->setValue("Description", info.data.value("Description").toString()); QString forced = info.data.value("ForcedInstallation", scFalse).toString().toLower(); if (m_core.noForceInstallation()) diff --git a/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml b/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml index 6b1856d51..1c3caf7be 100644 --- a/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml +++ b/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml @@ -10,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>4da14562d6515590d145678d21990faa817832bb</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/contentsha1check/contentsha1check.pro b/tests/auto/installer/contentsha1check/contentsha1check.pro new file mode 100644 index 000000000..dd659bffa --- /dev/null +++ b/tests/auto/installer/contentsha1check/contentsha1check.pro @@ -0,0 +1,9 @@ +include(../../qttest.pri) + +QT += qml + +SOURCES += tst_contentsha1check.cpp + +RESOURCES += \ + settings.qrc \ + ../shared/config.qrc diff --git a/tests/auto/installer/contentsha1check/data/config.xml b/tests/auto/installer/contentsha1check/data/config.xml new file mode 100644 index 000000000..041ce5062 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/config.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Installer> + <Name>Your application</Name> + <Version>1.2.3</Version> + <MaintenanceToolName></MaintenanceToolName> + <MaintenanceToolIniFile></MaintenanceToolIniFile> + <TargetConfigurationFile></TargetConfigurationFile> +</Installer> diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z Binary files differnew file mode 100644 index 000000000..9109d284f --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1 new file mode 100644 index 000000000..564e8290b --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1 @@ -0,0 +1 @@ +eb5a464ab1a33bd1484e9b8f22b2c5f97abdfdf6
\ No newline at end of file diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z Binary files differnew file mode 100644 index 000000000..947979354 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1 new file mode 100644 index 000000000..0f2144f0c --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1 @@ -0,0 +1 @@ +7e592e4b96adcefc77f2613100a3bd5e8835cce0
\ No newline at end of file diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z Binary files differnew file mode 100644 index 000000000..c14f55e4a --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml new file mode 100644 index 000000000..1d2fb780b --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml @@ -0,0 +1,27 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>true</Checksum> + <PackageUpdate> + <Name>A</Name> + <DisplayName>A</DisplayName> + <Description>Example component A</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile UncompressedSize="74" CompressedSize="215" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>dec2797a059da9303fec87cc0c1dfb0866afeb8f</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>B</Name> + <DisplayName>B</DisplayName> + <Description>Example component B</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile UncompressedSize="74" CompressedSize="215" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>2370e0b7dae861088c056d2de40c7ab7051bda13</SHA1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z Binary files differnew file mode 100644 index 000000000..793ce161c --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1 new file mode 100644 index 000000000..641396e0f --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1 @@ -0,0 +1 @@ +2c185d45cb84cec7a71e317f8cfc64dd23094c32
\ No newline at end of file diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z Binary files differnew file mode 100644 index 000000000..4feab5c34 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z Binary files differnew file mode 100644 index 000000000..f53a705dd --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1 new file mode 100644 index 000000000..daf89acba --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1 @@ -0,0 +1 @@ +d33a5fb638047372e9793b48d6c5ff85da560595
\ No newline at end of file diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z Binary files differnew file mode 100644 index 000000000..9931c0a7f --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml new file mode 100644 index 000000000..bda013684 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml @@ -0,0 +1,27 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>true</Checksum> + <PackageUpdate> + <Name>E</Name> + <DisplayName>E</DisplayName> + <Description>Example component E, invalid checksum</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile CompressedSize="215" OS="Any" UncompressedSize="74"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>db7e010425aaaaaaeebc6281a9d4c91e5666fd8f</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>F</Name> + <DisplayName>F</DisplayName> + <Description>Example component F</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile CompressedSize="215" OS="Any" UncompressedSize="74"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>b69b864cef5d0aecb496273374dd24bb8cba83bd</SHA1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z Binary files differnew file mode 100644 index 000000000..f96bfa9a3 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z Binary files differnew file mode 100644 index 000000000..976c57b43 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z Binary files differnew file mode 100644 index 000000000..015670af0 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z Binary files differnew file mode 100644 index 000000000..0b36609d7 --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml new file mode 100644 index 000000000..ae2ba911a --- /dev/null +++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml @@ -0,0 +1,27 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile OS="Any" UncompressedSize="74" CompressedSize="215"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>f82e1d1bbfd252715ace26db8c62595252e28a3b</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>D</Name> + <DisplayName>D</DisplayName> + <Description>Example component D</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile OS="Any" UncompressedSize="74" CompressedSize="215"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>402f299ec90f215db390b150c9429101344cf1ea</SHA1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentsha1check/settings.qrc b/tests/auto/installer/contentsha1check/settings.qrc new file mode 100644 index 000000000..e150ea61e --- /dev/null +++ b/tests/auto/installer/contentsha1check/settings.qrc @@ -0,0 +1,18 @@ +<RCC> + <qresource prefix="/"> + <file>data/config.xml</file> + <file>data/repositorywithchecksumcheck/Updates.xml</file> + <file>data/repositorywithchecksumcheck/A/1.0.2-1content.7z</file> + <file>data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1</file> + <file>data/repositorywithchecksumcheck/B/1.0.0-1content.7z</file> + <file>data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1</file> + <file>data/repositorywithnochecksumcheck/Updates.xml</file> + <file>data/repositorywithnochecksumcheck/C/1.0.2-1content.7z</file> + <file>data/repositorywithnochecksumcheck/D/1.0.0-1content.7z</file> + <file>data/repositorywithinvalidchecksum/Updates.xml</file> + <file>data/repositorywithinvalidchecksum/E/1.0.2-1content.7z</file> + <file>data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1</file> + <file>data/repositorywithinvalidchecksum/F/1.0.0-1content.7z</file> + <file>data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp b/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp new file mode 100644 index 000000000..e587d3011 --- /dev/null +++ b/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp @@ -0,0 +1,181 @@ +/************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $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 "../shared/packagemanager.h" +#include "../shared/verifyinstaller.h" + +#include <component.h> +#include <packagemanagercore.h> + +#include <QLoggingCategory> +#include <QTest> +#include <QMessageBox> + +using namespace QInstaller; + +typedef QList<QPair<QString, QString> > ComponentResourceHash; +typedef QPair<QString, QString> ComponentResource; + +static QStringList expectedMessages; + +void downloadingArchiveOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + Q_UNUSED(type) + Q_UNUSED(context) + QByteArray localMsg = msg.toLocal8Bit(); + if (!msg.startsWith("Downloading archive")) + return; + if (expectedMessages.contains(msg)) + expectedMessages.removeOne(msg); +} + +class tst_ContentSha1Check : public QObject +{ + Q_OBJECT + +private slots: + + void testInstall_data() + { + QTest::addColumn<QString>("repository"); + QTest::addColumn<QStringList>("installComponents"); + QTest::addColumn<PackageManagerCore::Status>("status"); + QTest::addColumn<ComponentResourceHash>("componentResources"); + QTest::addColumn<QStringList >("installedFiles"); + QTest::addColumn<QStringList >("expectedDownloadingArchiveMessages"); + + /*********** Install with checksum check **********/ + ComponentResourceHash componentResources; + componentResources.append(ComponentResource("A", "1.0.2-1content.txt")); + componentResources.append(ComponentResource("B", "1.0.0-1content.txt")); + + QTest::newRow("Check checksum") + << ":///data/repositorywithchecksumcheck" + << (QStringList() << "A" << "B") + << PackageManagerCore::Success + << componentResources + << (QStringList() << "components.xml" << "A.txt" << "B.txt") + << (QStringList() << "Downloading archive \"1.0.2-1content.7z.sha1\" for component A." + << "Downloading archive \"1.0.2-1content.7z\" for component A." + << "Downloading archive \"1.0.0-1content.7z.sha1\" for component B." + << "Downloading archive \"1.0.0-1content.7z\" for component B."); + + /*********** Install with and without checksum check **********/ + componentResources.clear(); + componentResources.append(ComponentResource("C", "1.0.2-1content.txt")); + componentResources.append(ComponentResource("D", "1.0.0-1content.txt")); + + QTest::newRow("Without checksum check") + << ":///data/repositorywithnochecksumcheck" + << (QStringList() << "C" << "D") + << PackageManagerCore::Success + << componentResources + << (QStringList() << "components.xml" << "C.txt" << "D.txt") + << (QStringList() << "Downloading archive \"1.0.2-1content.7z\" for component C." + << "Downloading archive \"1.0.0-1content.7z\" for component D."); + + } + + void testInstallWithInvalidChecksum_data() + { + QTest::addColumn<QString>("repository"); + QTest::addColumn<QStringList>("installComponents"); + QTest::addColumn<PackageManagerCore::Status>("status"); + QTest::addColumn<ComponentResourceHash>("componentResources"); + QTest::addColumn<QStringList >("installedFiles"); + + /*********** Install with checksum check **********/ + ComponentResourceHash componentResources; + + QTest::newRow("Invalid checksum") + << ":///data/repositorywithinvalidchecksum" + << (QStringList() << "E" << "F") + << PackageManagerCore::Failure + << componentResources + << (QStringList()); + } + + void testInstall() + { + QFETCH(QString, repository); + QFETCH(QStringList, installComponents); + QFETCH(PackageManagerCore::Status, status); + QFETCH(ComponentResourceHash, componentResources); + QFETCH(QStringList, installedFiles); + QFETCH(QStringList, expectedDownloadingArchiveMessages); + + expectedMessages = expectedDownloadingArchiveMessages; + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, repository)); + qInstallMessageHandler(downloadingArchiveOutput); + + QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents)); + for (const ComponentResource &resource : componentResources) + VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second); + VerifyInstaller::verifyFileExistence(m_installDir, installedFiles); + + QVERIFY(expectedMessages.isEmpty()); + } + + void testInstallWithInvalidChecksum() + { + QFETCH(QString, repository); + QFETCH(QStringList, installComponents); + QFETCH(PackageManagerCore::Status, status); + QFETCH(ComponentResourceHash, componentResources); + QFETCH(QStringList, installedFiles); + + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_installDir, repository)); + core->setMessageBoxAutomaticAnswer("DownloadError", QMessageBox::Cancel); + core->setMessageBoxAutomaticAnswer("installationError", QMessageBox::Ok); + + QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents)); + QVERIFY(!QDir().exists(m_installDir)); + } + + void init() + { + m_installDir = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(m_installDir)); + } + + void cleanup() + { + QDir dir(m_installDir); + QVERIFY(dir.removeRecursively()); + } + +private: + QString m_installDir; + QStringList m_expectedMessages; +}; + + +QTEST_MAIN(tst_ContentSha1Check) + +#include "tst_contentsha1check.moc" diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml new file mode 100644 index 000000000..fe5dc4dec --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml @@ -0,0 +1,28 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>componentA</Name> + <DisplayName>Component A</DisplayName> + <Description>Component A.</Description> + <Version>0.1.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>100</SortingPriority> + <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>5</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentEssential</Name> + <DisplayName>Component Essential</DisplayName> + <Description>Component Essential</Description> + <Essential>true</Essential> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z Binary files differnew file mode 100644 index 000000000..bdbabc7fd --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..9c86042c0 --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml new file mode 100644 index 000000000..f76c03faa --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml @@ -0,0 +1,27 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>componentA</Name> + <DisplayName>Component A</DisplayName> + <Description>This component does not depend on any other component.</Description> + <Version>1.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>100</SortingPriority> + <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <ContentSha1>10</ContentSha1> + </PackageUpdate> + <PackageUpdate> + <Name>componentEssential</Name> + <DisplayName>Component Essential</DisplayName> + <Description>Component Essential</Description> + <Essential>true</Essential> + <Version>2.0.0</Version> + <ReleaseDate>2014-08-25</ReleaseDate> + <SortingPriority>80</SortingPriority> + <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..46a9f1d1e --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z Binary files differnew file mode 100644 index 000000000..435f260ee --- /dev/null +++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z diff --git a/tests/auto/installer/contentshaupdate/settings.qrc b/tests/auto/installer/contentshaupdate/settings.qrc index a5d045f46..e3426be92 100644 --- a/tests/auto/installer/contentshaupdate/settings.qrc +++ b/tests/auto/installer/contentshaupdate/settings.qrc @@ -5,10 +5,16 @@ <file>data/repository/componentB/1.0.0content.7z</file> <file>data/repository/componentC/1.0.0content.7z</file> <file>data/repository/componentD/1.0.0content.7z</file> + <file>data/repositoryWithEssential/Updates.xml</file> + <file>data/repositoryWithEssential/componentA/1.0.0content.7z</file> + <file>data/repositoryWithEssential/componentEssential/2.0.0content.7z</file> <file>data/repositoryUpdate/Updates.xml</file> <file>data/repositoryUpdate/componentA/0.1.0content.7z</file> <file>data/repositoryUpdate/componentB/0.1.0content.7z</file> <file>data/repositoryUpdate/componentC/2.0.0content.7z</file> <file>data/repositoryUpdate/componentD/2.0.0content.7z</file> + <file>data/repositoryUpdateWithEssential/Updates.xml</file> + <file>data/repositoryUpdateWithEssential/componentA/0.1.0content.7z</file> + <file>data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp index d8d2f5377..5d282fe38 100644 --- a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp +++ b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp @@ -58,34 +58,50 @@ private slots: void updateWithContentSha1_data() { + QTest::addColumn<QString>("repository"); + QTest::addColumn<QString>("repositoryForUpdate"); QTest::addColumn<QString>("component"); QTest::addColumn<QString>("content"); QTest::addColumn<QString>("updatedContent"); QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterInstall"); QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterUpdate"); - QTest::newRow("ContentSha1Change") << "componentA" << "1.0.0content.txt" << "0.1.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; - QTest::newRow("NewContentSha1") << "componentB" << "1.0.0content.txt" << "0.1.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; - QTest::newRow("SameContentSha1") << "componentC" << "1.0.0content.txt" << "1.0.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Canceled; - QTest::newRow("Sha1RemovedFromRepo") << "componentD" << "1.0.0content.txt" << "2.0.0content.txt" << PackageManagerCore::Success << PackageManagerCore::Success; + QTest::newRow("Sha1UpdateForEssential") + << ":///data/repositoryWithEssential" << ":///data/repositoryUpdateWithEssential" + << "componentEssential" << "2.0.0content.txt" << "1.0.0content.txt" + << PackageManagerCore::Success << PackageManagerCore::EssentialUpdated; + QTest::newRow("ContentSha1Change") + << ":///data/repository" << ":///data/repositoryUpdate" << "componentA" << "1.0.0content.txt" << "0.1.0content.txt" + << PackageManagerCore::Success << PackageManagerCore::Success; + QTest::newRow("NewContentSha1") + << ":///data/repository" << ":///data/repositoryUpdate" << "componentB" << "1.0.0content.txt" << "0.1.0content.txt" + << PackageManagerCore::Success << PackageManagerCore::Success; + QTest::newRow("SameContentSha1") + << ":///data/repository" << ":///data/repositoryUpdate" << "componentC" << "1.0.0content.txt" << "1.0.0content.txt" + << PackageManagerCore::Success << PackageManagerCore::Canceled; + QTest::newRow("Sha1RemovedFromRepo") + << ":///data/repository" << ":///data/repositoryUpdate" << "componentD" << "1.0.0content.txt" << "2.0.0content.txt" + << PackageManagerCore::Success << PackageManagerCore::Success; } void updateWithContentSha1() { + QFETCH(QString, repository); + QFETCH(QString, repositoryForUpdate); QFETCH(QString, component); QFETCH(QString, content); QFETCH(QString, updatedContent); QFETCH(PackageManagerCore::Status, expectedStatusAfterInstall); QFETCH(PackageManagerCore::Status, expectedStatusAfterUpdate); - setRepository(":///data/repository"); + setRepository(repository); QCOMPARE(expectedStatusAfterInstall, core->installSelectedComponentsSilently(QStringList() << component)); QCOMPARE(expectedStatusAfterInstall, core->status()); VerifyInstaller::verifyInstallerResources(m_installDir, component, content); core->commitSessionOperations(); core->setPackageManager(); - setRepository(":///data/repositoryUpdate"); + setRepository(repositoryForUpdate); QCOMPARE(expectedStatusAfterUpdate, core->updateComponentsSilently(QStringList())); VerifyInstaller::verifyInstallerResources(m_installDir, component, updatedContent); } diff --git a/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml b/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml index a1c8f6aa2..fb8c9cf1c 100644 --- a/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml +++ b/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,6 +10,7 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>4fd4dd023111fcbbdd1221032c2984d249f4cad1</SHA1> <DownloadableArchives>content.7z</DownloadableArchives> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml index 90b26a387..b495f3307 100644 --- a/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml +++ b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -8,6 +9,7 @@ <Version>1.0.2-1</Version> <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> + <SHA1>4fd4dd023111fcbbdd1221032c2984d249f4cad1</SHA1> <DownloadableArchives>content.7z</DownloadableArchives> <Operations> <Operation name="Mkdir"> diff --git a/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp index d41853eee..692fd86d9 100644 --- a/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp +++ b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp @@ -87,37 +87,48 @@ private slots: QVERIFY(!op.performOperation()); QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); - QCOMPARE(op.errorString(), QString("Invalid arguments in Copy: " - "0 arguments given, exactly 2 arguments expected.")); - + QCOMPARE(op.errorString(), QString("Invalid arguments in Copy: 0 arguments given, " + "2 to 4 arguments expected in the form: <source filename> <destination filename> [UNDOOPERATION, \"\"].")); } void testCopySomething_data() { - QTest::addColumn<QString>("source"); - QTest::addColumn<QString>("destination"); - QTest::newRow("full path syntax") << qApp->applicationFilePath() << m_testDestinationFilePath; - QTest::newRow("short destination syntax") << qApp->applicationFilePath() << m_testDestinationPath; - QTest::newRow("short destination syntax with ending separator") << qApp->applicationFilePath() - << m_testDestinationPath + QDir::separator(); + QTest::addColumn<QString>("source"); + QTest::addColumn<QString>("destination"); + QTest::addColumn<bool>("overrideUndo"); + QTest::newRow("full path syntax") << qApp->applicationFilePath() << m_testDestinationFilePath << false; + QTest::newRow("short destination syntax") << qApp->applicationFilePath() << m_testDestinationPath << false; + QTest::newRow("short destination syntax with ending separator") << qApp->applicationFilePath() + << m_testDestinationPath + QDir::separator() << false; + QTest::newRow("override undo") << qApp->applicationFilePath() << m_testDestinationFilePath << true; } void testCopySomething() { QFETCH(QString, source); QFETCH(QString, destination); + QFETCH(bool, overrideUndo); - QVERIFY2(QFileInfo(source).exists(), QString("Source file \"%1\" does not exist.").arg(source).toLatin1()); - CopyOperation op; - op.setArguments(QStringList() << source << destination); - op.backup(); - QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(QFileInfo::exists(source), QString("Source file \"%1\" does not exist.").arg(source).toLatin1()); + CopyOperation *op = new CopyOperation(); + op->setArguments(QStringList() << source << destination); + if (overrideUndo) + op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION")); + op->backup(); + QVERIFY2(op->performOperation(), op->errorString().toLatin1()); - QVERIFY2(QFileInfo(m_testDestinationFilePath).exists(), QString("Copying from \"%1\" to \"%2\" was " + QVERIFY2(QFileInfo::exists(m_testDestinationFilePath), QString("Copying from \"%1\" to \"%2\" was " "not working: '%3' does not exist").arg(source, destination, m_testDestinationFilePath).toLatin1()); - QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); - QVERIFY2(!QFileInfo(m_testDestinationFilePath).exists(), QString("Undo of copying from \"%1\" to " - "\"%2\" was not working.").toLatin1()); + QVERIFY2(op->undoOperation(), op->errorString().toLatin1()); + if (!overrideUndo) { + QVERIFY2(!QFileInfo::exists(m_testDestinationFilePath), QString("Undo of copying from \"%1\" to " + "\"%2\" was not working.").toLatin1()); + } else { + QVERIFY(QFileInfo::exists(m_testDestinationFilePath)); + } + QString backupFileName = op->value("backupOfExistingDestination").toString(); + delete op; + QVERIFY(!QFileInfo::exists(backupFileName)); } void testCopyIfDestinationExist_data() diff --git a/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml b/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml index 77b5a9956..ad6c49c81 100644 --- a/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml +++ b/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>0746c8292e3799aac4a534a0a1a58d42ef24ed43</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/createoffline/tst_createoffline.cpp b/tests/auto/installer/createoffline/tst_createoffline.cpp index 123f37a5b..607f9b7cc 100644 --- a/tests/auto/installer/createoffline/tst_createoffline.cpp +++ b/tests/auto/installer/createoffline/tst_createoffline.cpp @@ -93,7 +93,7 @@ private slots: << PackageManagerCore::Canceled; QTest::newRow("Invalid repository") << ":///data/repository-invalid" << "a.dummy.component" - << PackageManagerCore::Failure; + << PackageManagerCore::Canceled; } void testCreateOfflineInstaller() @@ -136,13 +136,13 @@ private slots: << true << PackageManagerCore::Canceled; QTest::newRow("Disallow unstable | Missing dependency with selected component") << ":///data/repository-missingdependency" << "example.with.unstable.dependency" - << false << PackageManagerCore::Failure; + << false << PackageManagerCore::Canceled; QTest::newRow("Allow unstable | Missing dependency with other component") << ":///data/repository-missingdependency" << "example.without.unstable.dependency" << true << PackageManagerCore::Success; QTest::newRow("Disallow unstable | Missing dependency with other component") << ":///data/repository-missingdependency" << "example.without.unstable.dependency" - << false << PackageManagerCore::Failure; + << false << PackageManagerCore::Canceled; } void testCreateOfflineWithUnstableComponent() diff --git a/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml b/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml index 0826afae8..d1909d355 100644 --- a/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml +++ b/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml @@ -5,7 +5,7 @@ <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> - <Description>Example component A</Description> + <Description>Example component for CreateShortcutOperation</Description> <Version>1.0.2-1</Version> <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> diff --git a/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp b/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp index baf954a44..a08567d64 100644 --- a/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp +++ b/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp @@ -53,10 +53,9 @@ private: { QInstaller::init(); QScopedPointer<PackageManagerCore> core(new PackageManagerCore(BinaryContent::MagicInstallerMarker, - QList<OperationBlob> (), QString(), Protocol::DefaultAuthorizationKey, + QList<OperationBlob> (), QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, QHash<QString, QString>(), true)); - core->setAllowedRunningProcesses(QStringList() << QCoreApplication::applicationFilePath()); core->disableWriteMaintenanceTool(); core->setAutoConfirmCommand(); QSet<Repository> repoList; diff --git a/tests/auto/installer/deleteoperation/data/repository/Updates.xml b/tests/auto/installer/deleteoperation/data/repository/Updates.xml index 77b5a9956..5a8b28f38 100644 --- a/tests/auto/installer/deleteoperation/data/repository/Updates.xml +++ b/tests/auto/installer/deleteoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>e8b8ce98862d463c855609ed8e139eda17092cc6</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp b/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp index 807d03498..43ea52407 100644 --- a/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp +++ b/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp @@ -75,8 +75,7 @@ private slots: QVERIFY(!op.performOperation()); QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); - QCOMPARE(op.errorString(), QString("Invalid arguments in Delete: " - "0 arguments given, exactly 1 arguments expected.")); + QCOMPARE(op.errorString(), QString("Invalid arguments in Delete: 0 arguments given, 1 to 3 arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"].")); op.setArguments(QStringList() << ""); QTest::ignoreMessage(QtWarningMsg, "QFile::copy: Empty or null file name"); @@ -92,13 +91,16 @@ private slots: void testDeleteRestore_data() { QTest::addColumn<QString>("path"); - QTest::newRow("relative") << "test"; - QTest::newRow("absolute") << qApp->applicationDirPath() + QDir::toNativeSeparators("/test"); + QTest::addColumn<bool>("overrideUndo"); + QTest::newRow("relative") << "test" << false; + QTest::newRow("absolute") << qApp->applicationDirPath() + QDir::toNativeSeparators("/test") << false; + QTest::newRow("no undo") << "test" << true; } void testDeleteRestore() { QFETCH(QString, path); + QFETCH(bool, overrideUndo); QByteArray testString("Generated by QTest\n"); QFile testFile(path); @@ -107,23 +109,32 @@ private slots: out << testString; testFile.close(); - QVERIFY(QFileInfo(path).exists()); + QVERIFY(QFileInfo::exists(path)); QByteArray testFileHash = QInstaller::calculateHash(path, QCryptographicHash::Sha1); - DeleteOperation op; - op.setArguments(QStringList() << path); - - op.backup(); - QVERIFY(QFileInfo(op.value("backupOfExistingFile").toString()).exists()); - - QVERIFY2(op.performOperation(), op.errorString().toLatin1()); - QVERIFY(!QFileInfo(path).exists()); - - QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); - QByteArray restoredFileHash = QInstaller::calculateHash(path, QCryptographicHash::Sha1); - QVERIFY(testFileHash == restoredFileHash); - - QVERIFY(QFile(path).remove()); + DeleteOperation *op = new DeleteOperation(); + op->setArguments(QStringList() << path); + if (overrideUndo) + op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION")); + + op->backup(); + QVERIFY(QFileInfo::exists(op->value("backupOfExistingFile").toString())); + + QVERIFY2(op->performOperation(), op->errorString().toLatin1()); + QVERIFY(!QFileInfo::exists(path)); + + QVERIFY2(op->undoOperation(), op->errorString().toLatin1()); + if (!overrideUndo) { + QByteArray restoredFileHash = QInstaller::calculateHash(path, QCryptographicHash::Sha1); + QVERIFY(testFileHash == restoredFileHash); + } else { + QVERIFY(!QFileInfo::exists(path)); + } + + QString backupFileName = op->value("backupOfExistingFile").toString(); + delete op; + QVERIFY(!QFileInfo::exists(backupFileName)); + QCOMPARE(QFile(path).remove(), !overrideUndo); } void testDeleteFromScript() diff --git a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp index aa2849559..ef185a5cf 100644 --- a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp +++ b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -46,12 +46,12 @@ private slots: m_core.setValue(QLatin1String("QMAKE_BINARY"), QUOTE(QMAKE_BINARY)); m_core.setValue(QLatin1String("QMAKE_BINARY_OLD"), QLatin1String("FAKE_QMAKE")); ElevatedExecuteOperation operation(&m_core); - operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE")); + operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE") << QLatin1String("-v")); - QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"\""); - QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1"; + QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"-v\""); + QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1, -v"; QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY)))); - message = "\"%1\" started, arguments: \"\""; + message = "\"%1\" started, arguments: \"-v\""; QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY)))); QCOMPARE(operation.undoOperation(), true); diff --git a/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml b/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml index 6b1856d51..5bcd58c69 100644 --- a/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml +++ b/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml @@ -10,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>4b7b52af2d838389a7404c553da74705fc106493</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/extractarchiveoperationtest/data.qrc b/tests/auto/installer/extractarchiveoperationtest/data.qrc index 974c0c6f7..87f648568 100644 --- a/tests/auto/installer/extractarchiveoperationtest/data.qrc +++ b/tests/auto/installer/extractarchiveoperationtest/data.qrc @@ -2,6 +2,7 @@ <qresource prefix="/"> <file>data/valid.7z</file> <file>data/invalid.7z</file> + <file>data/subdirs.7z</file> <file>data/xmloperationrepository/Updates.xml</file> <file>data/xmloperationrepository/A/1.0.0content.7z</file> <file>data/xmloperationrepository/A/1.0.0content1.tar.gz</file> @@ -10,5 +11,8 @@ <file>data/xmloperationrepository/A/1.0.0content4.zip</file> <file>data/xmloperationrepository/A/1.0.0anothercontent.7z</file> <file>data/xmloperationrepository/A/1.0.0default.7z</file> + <file>data/installerbaserepository/Updates.xml</file> + <file>data/installerbaserepository/A/1.0.0content.7z</file> + <file>data/installerbaserepository/A/1.0.0installerbase.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..585f58296 --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z Binary files differnew file mode 100644 index 000000000..c3b6aec9c --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml new file mode 100644 index 000000000..887300c97 --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml @@ -0,0 +1,13 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <PackageUpdate> + <Name>A</Name> + <DisplayName>InstallerBase</DisplayName> + <Description>Example component InstallerBase</Description> + <Version>1.0.0</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <DownloadableArchives>installerbase.7z,content.7z</DownloadableArchives> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z Binary files differnew file mode 100644 index 000000000..7f93fe106 --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z diff --git a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp index 8ceaa76c7..a8a65e983 100644 --- a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp +++ b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp @@ -28,6 +28,7 @@ #include "../shared/packagemanager.h" +#include "concurrentoperationrunner.h" #include "init.h" #include "extractarchiveoperation.h" @@ -86,6 +87,57 @@ private slots: QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError); } + void testConcurrentExtractWithCompetingData() + { + // Suppress warnings about already deleted installerResources file + qInstallMessageHandler(silentTestMessageHandler); + + const QString testDirectory = generateTemporaryFileName() + + "/subdir1/subdir2/subdir3/subdir4/subdir5/"; + + QStringList created7zList; + + OperationList operations; + for (int i = 0; i < 100; ++i) { + ExtractArchiveOperation *op = new ExtractArchiveOperation(nullptr); + // We add the same data multiple times, and extract to same directory. + // Can't open the same archive multiple times however so it needs to + // be copied to unique files. + const QString new7zPath = generateTemporaryFileName() + ".7z"; + QFile old7z(":///data/subdirs.7z"); + QVERIFY(old7z.copy(new7zPath)); + + op->setArguments(QStringList() << new7zPath << testDirectory); + operations.append(op); + } + ConcurrentOperationRunner runner(&operations, Operation::Backup); + + const QHash<Operation *, bool> backupResults = runner.run(); + const OperationList backupOperations = backupResults.keys(); + + for (auto *operation : backupOperations) + QVERIFY2((backupResults.value(operation) && operation->error() == Operation::NoError), + operation->errorString().toLatin1()); + + runner.setType(Operation::Perform); + const QHash<Operation *, bool> results = runner.run(); + const OperationList performedOperations = results.keys(); + + for (auto *operation : performedOperations) + QVERIFY2((results.value(operation) && operation->error() == Operation::NoError), + operation->errorString().toLatin1()); + + for (auto *operation : operations) + QVERIFY(operation->undoOperation()); + + qDeleteAll(operations); + + for (const QString &archive : created7zList) + QFile::remove(archive); + + QDir().rmdir(testDirectory); + } + void testExtractArchiveFromXML() { m_testDirectory = QInstaller::generateTemporaryFileName(); @@ -125,6 +177,39 @@ private slots: QVERIFY(dir.removeRecursively()); } + void testInstallerBaseBinaryExtraction() + { + m_testDirectory = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(m_testDirectory)); + QVERIFY(QDir(m_testDirectory).exists()); + + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (m_testDirectory, ":///data/installerbaserepository")); + core->setInstallerBaseBinary(m_testDirectory + QDir::separator() + "testInstallerBase.txt"); + core->installDefaultComponentsSilently(); + + QFile contentResourceFile(m_testDirectory + QDir::separator() + "installerResources" + QDir::separator() + "A" + QDir::separator() + "1.0.0content.txt"); + QVERIFY2(contentResourceFile.open(QIODevice::ReadOnly | QIODevice::Text), "Could not open content resource file for reading."); + QTextStream fileStream(&contentResourceFile); + QString line = fileStream.readLine(); + QVERIFY2(!line.isEmpty(), "Content not written to resource file."); + contentResourceFile.close(); + + QFile installerBaseResourceFile(m_testDirectory + QDir::separator() + "installerResources" + QDir::separator() + "A" + QDir::separator() + "1.0.0installerbase.txt"); + QVERIFY2(installerBaseResourceFile.open(QIODevice::ReadOnly | QIODevice::Text), "Could not open installerbase resource file for reading."); + QTextStream fileStream2(&installerBaseResourceFile); + line = installerBaseResourceFile.readLine(); + QVERIFY2(line.isEmpty(), "Installerbase falsly written to resource file."); + installerBaseResourceFile.close(); + + core->setPackageManager(); + core->commitSessionOperations(); + + QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently(QStringList() << "A")); + QDir dir(m_testDirectory); + QVERIFY(dir.removeRecursively()); + } + private: QString m_testDirectory; }; diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro index 5d93f2132..b2eb57790 100644 --- a/tests/auto/installer/installer.pro +++ b/tests/auto/installer/installer.pro @@ -15,6 +15,7 @@ SUBDIRS += \ scriptengine \ consumeoutputoperationtest \ mkdiroperationtest \ + rmdiroperationtest \ copyoperationtest \ solver \ binaryformat \ @@ -29,6 +30,7 @@ SUBDIRS += \ linereplaceoperation \ metadatajob \ appendfileoperation \ + prependfileoperation \ simplemovefileoperation \ deleteoperation \ copydirectoryoperation \ @@ -41,7 +43,10 @@ SUBDIRS += \ treename \ createoffline \ contentshaupdate \ - componentreplace + componentreplace \ + metadatacache \ + contentsha1check \ + componentalias CONFIG(libarchive) { SUBDIRS += libarchivearchive diff --git a/tests/auto/installer/installiconsoperation/data/repository/Updates.xml b/tests/auto/installer/installiconsoperation/data/repository/Updates.xml index a1c8f6aa2..201e23c2d 100644 --- a/tests/auto/installer/installiconsoperation/data/repository/Updates.xml +++ b/tests/auto/installer/installiconsoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -10,5 +11,6 @@ <Default>true</Default> <Script>script.qs</Script> <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>13c9e7e67c26e7fbf49cc30887d87140b65e11b5</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/licenseagreement/data/repository/Updates.xml b/tests/auto/installer/licenseagreement/data/repository/Updates.xml index 2afd2a741..c57918162 100644 --- a/tests/auto/installer/licenseagreement/data/repository/Updates.xml +++ b/tests/auto/installer/licenseagreement/data/repository/Updates.xml @@ -9,6 +9,7 @@ <Version>1.0.2-1</Version> <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> + <SHA1>f46c677db8bc779d70d0c72fae264a321caea6f8</SHA1> <Licenses> <License name="GNU GENERAL PUBLIC LICENSE Version 3" file="gpl3.txt"/> </Licenses> diff --git a/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml b/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml index 77b5a9956..f92211497 100644 --- a/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml +++ b/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>c8eb49045188859100716ab084452b32fca38d5d</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml b/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml index 77b5a9956..0781dcfc5 100644 --- a/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml +++ b/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>ad3157ed059e3369c094e154319de1d255865de5</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp index 464e1eef7..5db79cc55 100644 --- a/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp +++ b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp @@ -93,9 +93,8 @@ private slots: QInstaller::init(); //This will eat debug output core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (), - QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, + QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, QHash<QString, QString>(), true); - core->setAllowedRunningProcesses(QStringList() << QCoreApplication::applicationFilePath()); core->disableWriteMaintenanceTool(); core->setAutoConfirmCommand(); m_installDir = QInstaller::generateTemporaryFileName(); @@ -196,7 +195,7 @@ private slots: setRepository(":///data/missingarchive"); core->autoAcceptMessageBoxes(); core->installSelectedComponentsSilently(QStringList () << "C"); - QCOMPARE(PackageManagerCore::Canceled, core->status()); + QCOMPARE(PackageManagerCore::Failure, core->status()); // Fails after retrying } void messageBoxFromScriptDefaultAnswer() diff --git a/tests/auto/installer/metadatacache/data/existing-cache/manifest.json b/tests/auto/installer/metadatacache/data/existing-cache/manifest.json new file mode 100644 index 000000000..7f30e0fc0 --- /dev/null +++ b/tests/auto/installer/metadatacache/data/existing-cache/manifest.json @@ -0,0 +1,7 @@ +{ + "items": [ + "placeholder_sha1" + ], + "type": "Metadata", + "version": "1.2.0" +} diff --git a/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml new file mode 100644 index 000000000..b0b30c9d4 --- /dev/null +++ b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml @@ -0,0 +1,19 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>true</Checksum> + <RepositoryUpdate> + <Repository action="remove" url="../repository"/> + </RepositoryUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.0-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt new file mode 100644 index 000000000..7224edd52 --- /dev/null +++ b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt @@ -0,0 +1 @@ +/example-repository diff --git a/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt b/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt new file mode 100644 index 000000000..1ffdcc8df --- /dev/null +++ b/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt @@ -0,0 +1 @@ +Example license file diff --git a/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml b/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml new file mode 100644 index 000000000..03e54572d --- /dev/null +++ b/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml @@ -0,0 +1,17 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>A</Name> + <DisplayName>A</DisplayName> + <Description>Example component A</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <SHA1>f46c677db8bc779d70d0c72fae264a321caea6f8</SHA1> + <Licenses> + <License name="Example license" file="example-license.txt"/> + </Licenses> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/metadatacache/metadatacache.pro b/tests/auto/installer/metadatacache/metadatacache.pro new file mode 100644 index 000000000..df1542dc7 --- /dev/null +++ b/tests/auto/installer/metadatacache/metadatacache.pro @@ -0,0 +1,8 @@ +include(../../qttest.pri) + +QT += qml + +SOURCES += tst_metadatacache.cpp + +RESOURCES += \ + settings.qrc diff --git a/tests/auto/installer/metadatacache/settings.qrc b/tests/auto/installer/metadatacache/settings.qrc new file mode 100644 index 000000000..96383fdcb --- /dev/null +++ b/tests/auto/installer/metadatacache/settings.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>data/local-temp-repository/Updates.xml</file> + <file>data/local-temp-repository/A/example-license.txt</file> + <file>data/existing-cache/manifest.json</file> + <file>data/existing-cache/placeholder_sha1/repository.txt</file> + <file>data/existing-cache/placeholder_sha1/Updates.xml</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/metadatacache/tst_metadatacache.cpp b/tests/auto/installer/metadatacache/tst_metadatacache.cpp new file mode 100644 index 000000000..ce97de9da --- /dev/null +++ b/tests/auto/installer/metadatacache/tst_metadatacache.cpp @@ -0,0 +1,381 @@ +/************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $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 "../shared/packagemanager.h" + +#include <errors.h> +#include <fileutils.h> +#include <metadatacache.h> +#include <metadata.h> +#include <repository.h> + +#include <QCryptographicHash> +#include <QDir> +#include <QFileInfo> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QObject> +#include <QTest> + +#define QUOTE_(x) #x +#define QUOTE(x) QUOTE_(x) + +using namespace QInstaller; + +static const QByteArray scPlaceholderSha1("placeholder_sha1"); + +class tst_metadatacache : public QObject +{ + Q_OBJECT + +private: + void copyExistingCacheFromResourceTree() + { + try { + QInstaller::copyDirectoryContents(":/data/existing-cache/", m_cachePath); + + // We need to modify the test data here because the checksums of + // files may differ on Windows and Unix platforms. + QVERIFY(QDir().rename(m_cachePath + QDir::separator() + scPlaceholderSha1, + m_cachePath + QDir::separator() + m_oldMetadataItemChecksum)); + + QFile manifestFile(m_cachePath + QDir::separator() + "manifest.json"); + // The file lost the write bit after copying from resource + QInstaller::setDefaultFilePermissions(&manifestFile, QInstaller::NonExecutable); + QVERIFY2(manifestFile.open(QIODevice::ReadWrite), qPrintable(manifestFile.errorString())); + + const QByteArray manifestData = manifestFile.readAll(); + QJsonDocument manifestJsonDoc(QJsonDocument::fromJson(manifestData)); + QJsonObject docJsonObject = manifestJsonDoc.object(); + + QJsonArray itemsJsonArray; + itemsJsonArray.append(QJsonValue(QLatin1String(m_oldMetadataItemChecksum))); + + docJsonObject.insert(QLatin1String("items"), itemsJsonArray); + manifestJsonDoc.setObject(docJsonObject); + + manifestFile.seek(0); + QVERIFY(manifestFile.write(manifestJsonDoc.toJson()) != -1); + + } catch (const Error &e) { + QVERIFY2(false, QString::fromLatin1("Error while copying item to path %1: %2") + .arg(m_cachePath, e.message()).toLatin1()); + } + } + + QStringList itemsFromManifest(const QString &manifestPath) + { + QFile manifestFile(manifestPath); + if (!manifestFile.open(QIODevice::ReadOnly)) + return QStringList(); + + const QByteArray manifestData = manifestFile.readAll(); + const QJsonDocument manifestJsonDoc(QJsonDocument::fromJson(manifestData)); + const QJsonObject docJsonObject = manifestJsonDoc.object(); + const QJsonArray itemsJsonArray = docJsonObject.value(QLatin1String("items")).toArray(); + + QStringList items; + for (const auto &itemJsonValue : itemsJsonArray) + items << itemJsonValue.toString(); + + return items; + } + + QByteArray checksumFromUpdateFile(const QString &directory) + { + QFile updateFile(directory + QDir::separator() + QLatin1String("Updates.xml")); + if (!updateFile.open(QIODevice::ReadOnly)) + return QByteArray(); + + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(&updateFile); + return hash.result().toHex(); + } + +private slots: + void init() + { + m_cachePath = generateTemporaryFileName(); + } + + void cleanup() + { + if (QFileInfo::exists(m_cachePath)) + QInstaller::removeDirectory(m_cachePath, true); + } + + void initTestCase() + { + m_newMetadataItemChecksum = checksumFromUpdateFile(":/data/local-temp-repository"); + m_oldMetadataItemChecksum = checksumFromUpdateFile(":/data/existing-cache/" + + QLatin1String(scPlaceholderSha1)); + + QVERIFY(!m_newMetadataItemChecksum.isEmpty()); + QVERIFY(!m_oldMetadataItemChecksum.isEmpty()); + + qInstallMessageHandler(silentTestMessageHandler); + } + + void testRegisterItemToEmptyCache() + { + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + + QVERIFY(cache.registerItem(metadata)); + metadata = cache.itemByChecksum(m_newMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + QVERIFY(!QFileInfo::exists(m_cachePath + "/manifest.json")); + QVERIFY(cache.sync()); + QVERIFY(itemsFromManifest(m_cachePath + "/manifest.json").contains(QLatin1String(m_newMetadataItemChecksum))); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testRegisterItemToExistingCache() + { + copyExistingCacheFromResourceTree(); + + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + QVERIFY(itemsFromManifest(m_cachePath + "/manifest.json").contains(QLatin1String(m_oldMetadataItemChecksum))); + + QVERIFY(cache.registerItem(metadata)); + metadata = cache.itemByChecksum(m_newMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + QVERIFY(cache.sync()); + const QStringList manifestItems = itemsFromManifest(m_cachePath + "/manifest.json"); + QVERIFY(manifestItems.contains(QLatin1String(m_oldMetadataItemChecksum))); + QVERIFY(manifestItems.contains(QLatin1String(m_newMetadataItemChecksum))); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testRegisterItemFails() + { + // 1. Test fail due to invalidated cache + MetadataCache cache; + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + + QVERIFY(!cache.registerItem(metadata)); + QCOMPARE(cache.errorString(), "Cannot register item to invalidated cache."); + + delete metadata; + metadata = nullptr; + + // 2. Test fail due to null metadata + cache.setPath(m_cachePath); + cache.setType("Metadata"); + cache.setVersion(QUOTE(IFW_CACHE_FORMAT_VERSION)); + QVERIFY(cache.initialize()); + + QVERIFY(!cache.registerItem(metadata)); + QCOMPARE(cache.errorString(), "Cannot register null item."); + + // 3. Test fail due to invalid metadata + metadata = new Metadata; + QVERIFY(!cache.registerItem(metadata)); + QCOMPARE(cache.errorString(), "Cannot register invalid item with checksum "); + + // 4. Test fail due to duplicate metadata item + metadata->setPath(":/data/local-temp-repository/"); + QVERIFY(cache.registerItem(metadata)); + QVERIFY(cache.itemByChecksum(m_newMetadataItemChecksum)->isValid()); + QVERIFY(!cache.registerItem(metadata)); + QCOMPARE(cache.errorString(), QString::fromLatin1("Cannot register item with checksum " + "%1. An item with the same checksum already exists in cache.") + .arg(QString::fromLatin1(m_newMetadataItemChecksum)).toLatin1()); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testInitializeExistingCache() + { + copyExistingCacheFromResourceTree(); + + MetadataCache cache(m_cachePath); + Metadata *metadata = cache.itemByChecksum(m_oldMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testInitializeForeignCache_data() + { + QTest::addColumn<QString>("type"); + QTest::addColumn<QString>("version"); + + QTest::newRow("Type mismatch") << "MyCacheableType" << QUOTE(IFW_CACHE_FORMAT_VERSION); + QTest::newRow("Version mismatch") << "Metadata" << "0.9.1"; + } + + void testInitializeForeignCache() + { + QFETCH(QString, type); + QFETCH(QString, version); + + copyExistingCacheFromResourceTree(); + + MetadataCache cache; + cache.setType(type); + cache.setVersion(version); + cache.setPath(m_cachePath); + QVERIFY(cache.initialize()); + + QVERIFY(cache.isValid()); + QVERIFY(!cache.itemByChecksum(m_oldMetadataItemChecksum)); + + QVERIFY(cache.clear()); + // The 'foreign' entry prevents removing the directory + QVERIFY(QFileInfo::exists(m_cachePath)); + } + + void testInitializeCacheFails() + { + MetadataCache cache; + QVERIFY(!cache.initialize()); + QCOMPARE(cache.errorString(), "Cannot initialize cache with empty path."); + } + + void testRemoveItemFromCache() + { + copyExistingCacheFromResourceTree(); + + MetadataCache cache(m_cachePath); + Metadata *metadata = cache.itemByChecksum(m_oldMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + QVERIFY(cache.removeItem(m_oldMetadataItemChecksum)); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testRemoveItemFails() + { + copyExistingCacheFromResourceTree(); + + MetadataCache cache(m_cachePath); + QVERIFY(!cache.removeItem("12345")); + QCOMPARE(cache.errorString(), "Cannot remove item specified by checksum 12345: no such item exists."); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testRetrieveItemFromCache() + { + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + + QVERIFY(cache.registerItem(metadata)); + metadata = cache.itemByChecksum(m_newMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + + metadata = cache.itemByPath(metadata->path()); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testRetrieveItemFails() + { + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + const QString metadataPath = metadata->path(); + + QVERIFY(cache.registerItem(metadata)); + QVERIFY(cache.clear()); + + QVERIFY(!cache.itemByChecksum(m_newMetadataItemChecksum)); + QVERIFY(!cache.itemByPath(metadataPath)); + QCOMPARE(cache.errorString(), "Cannot retrieve item from invalidated cache."); + + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testItemObsoletesOther() + { + copyExistingCacheFromResourceTree(); + + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + + QVERIFY(cache.registerItem(metadata)); + metadata->setRepository(Repository(QUrl("file:///example-repository"), true)); + metadata->setPersistentRepositoryPath(QUrl("file:///example-repository")); + QVERIFY(metadata->isActive()); + + metadata = cache.itemByChecksum(m_newMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + + metadata = cache.itemByChecksum(m_oldMetadataItemChecksum); + QVERIFY(metadata); + QVERIFY(metadata->isValid()); + + Metadata *obsolete = cache.obsoleteItems().first(); + QVERIFY(!obsolete->isActive()); + QCOMPARE(obsolete->checksum(), m_oldMetadataItemChecksum); + + QVERIFY(cache.clear()); + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + + void testClearCacheFails() + { + MetadataCache cache(m_cachePath); + Metadata *metadata = new Metadata(":/data/local-temp-repository/"); + + QVERIFY(cache.registerItem(metadata)); + QVERIFY(cache.clear()); + QVERIFY(!cache.clear()); + QCOMPARE(cache.errorString(), "Cannot clear invalidated cache."); + + QVERIFY(!QFileInfo::exists(m_cachePath)); + } + +private: + QString m_cachePath; + QByteArray m_newMetadataItemChecksum; + QByteArray m_oldMetadataItemChecksum; +}; + +QTEST_MAIN(tst_metadatacache) + +#include "tst_metadatacache.moc" diff --git a/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z b/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z Binary files differnew file mode 100644 index 000000000..df1f72b51 --- /dev/null +++ b/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z diff --git a/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z b/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z Binary files differnew file mode 100644 index 000000000..6afaae497 --- /dev/null +++ b/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z diff --git a/tests/auto/installer/metadatajob/settings.qrc b/tests/auto/installer/metadatajob/settings.qrc index 6e56a7854..5df3befd9 100644 --- a/tests/auto/installer/metadatajob/settings.qrc +++ b/tests/auto/installer/metadatajob/settings.qrc @@ -3,5 +3,7 @@ <file>data/repository/Updates.xml</file> <file>data/repositoryActionAdd/Updates.xml</file> <file>data/repositoryActionRemove/Updates.xml</file> + <file>data/repositoryZipped/repositoryZipped.7z</file> + <file>data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/metadatajob/tst_metadatajob.cpp b/tests/auto/installer/metadatajob/tst_metadatajob.cpp index 54609ab95..cb974e7ad 100644 --- a/tests/auto/installer/metadatajob/tst_metadatajob.cpp +++ b/tests/auto/installer/metadatajob/tst_metadatajob.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -97,6 +97,49 @@ private slots: metadata.waitForFinished(); QCOMPARE(metadata.metadata().count(), 1); } + + void testZippedRepository_data() + { + QTest::addColumn<QStringList>("repositories"); + QTest::addColumn<int>("metacount"); + QTest::addColumn<bool>("allowUnstable"); + + QStringList repositories; + repositories << ":///data/repositoryZipped/repositoryZipped.7z"; + QTest::newRow("7z repository") << repositories << 1 << true; + + repositories.clear(); + repositories << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z"; + QTest::newRow("7z with invalid meta sha1") << repositories << 0 << true; + + repositories.clear(); + repositories << ":///data/repositoryZipped/repositoryZipped.7z" << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z"; + QTest::newRow("7z with one valid repository") << repositories << 1 << true; + + repositories.clear(); + repositories << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z" << ":///data/repositoryZipped/repositoryZipped.7z"; + QTest::newRow("7z with one valid repository") << repositories << 0 << false; + } + + void testZippedRepository() + { + QFETCH(QStringList, repositories); + QFETCH(int, metacount); + QFETCH(bool, allowUnstable); + + PackageManagerCore core; + core.setInstaller(); + core.setTemporaryRepositories(repositories, false, true); + core.settings().setAllowUnstableComponents(allowUnstable); + + MetadataJob metadata; + metadata.setPackageManagerCore(&core); + metadata.addDownloadType(DownloadType::CompressedPackage); + metadata.setAutoDelete(true); + metadata.start(); + metadata.waitForFinished(); + QCOMPARE(metadata.metadata().count(), metacount); + } }; diff --git a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp index f52c27d0f..e41ba8049 100644 --- a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp +++ b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -60,32 +60,42 @@ private slots: QVERIFY(!op.performOperation()); QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); - QCOMPARE(op.errorString(), QString("Invalid arguments in Mkdir: " - "0 arguments given, exactly 1 arguments expected.")); - + QCOMPARE(op.errorString(), QString("Invalid arguments in Mkdir: 0 arguments given, 1 to 3 " + "arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"].")); } void testCreateDirectory_data() { - QTest::addColumn<QString>("directory"); - QTest::newRow("/test") << "/test"; - QTest::newRow("/test/test") << "/test/test"; - QTest::newRow("/test/test/test") << "/test/test/test"; + QTest::addColumn<QString>("directory"); + QTest::addColumn<bool>("overrideUndo"); + QTest::newRow("/test") << "/test" << false; + QTest::newRow("/test/test") << "/test/test" << false; + QTest::newRow("/test/test/test") << "/test/test/test" << false; + QTest::newRow("no undo") << "/test" << true; } void testCreateDirectory() { QFETCH(QString, directory); + QFETCH(bool, overrideUndo); + QString path = QDir::current().path() + QDir::toNativeSeparators(directory); QVERIFY2(!QDir(path).exists(), path.toLatin1()); MkdirOperation op; op.setArguments(QStringList() << path); + if (overrideUndo) + op.setArguments(op.arguments() << QLatin1String("UNDOOPERATION")); op.backup(); QVERIFY2(op.performOperation(), op.errorString().toLatin1()); QVERIFY2(QDir(path).exists(), path.toLatin1()); QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); - QVERIFY2(!QDir(path).exists(), path.toLatin1()); + if (overrideUndo) { + QVERIFY2(QDir(path).exists(), path.toLatin1()); + QVERIFY(QDir(path).removeRecursively()); + } else { + QVERIFY2(!QDir(path).exists(), path.toLatin1()); + } } void testCreateDirectory_customFile_data() diff --git a/tests/auto/installer/moveoperation/data/repository/Updates.xml b/tests/auto/installer/moveoperation/data/repository/Updates.xml index 6b1856d51..5cdad4e45 100644 --- a/tests/auto/installer/moveoperation/data/repository/Updates.xml +++ b/tests/auto/installer/moveoperation/data/repository/Updates.xml @@ -10,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>badc75810d399a35bae6f6b2cd8acfc1d5b1ccd2</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/moveoperation/tst_moveoperation.cpp b/tests/auto/installer/moveoperation/tst_moveoperation.cpp index 136eb1e45..bb391efee 100644 --- a/tests/auto/installer/moveoperation/tst_moveoperation.cpp +++ b/tests/auto/installer/moveoperation/tst_moveoperation.cpp @@ -86,8 +86,8 @@ private slots: QVERIFY(!op.performOperation()); QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); - QCOMPARE(op.errorString(), QString("Invalid arguments in Move: " - "0 arguments given, exactly 2 arguments expected.")); + QCOMPARE(op.errorString(), QString("Invalid arguments in Move: 0 arguments given, 2 to 4 arguments " + "expected in the form: <complete source file name> <complete destination file name> [UNDOOPERATION, \"\"].")); } void testMoveFile() diff --git a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp index aa74d8dbe..410bfb01c 100644 --- a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp +++ b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -260,7 +260,6 @@ private slots: root->setInstalled(); child1->setInstalled(); child2->setUninstalled(); - core.componentsToInstallNeedsRecalculation(); core.calculateComponentsToInstall(); QCOMPARE(core.requiredDiskSpace(), 250ULL); } @@ -288,58 +287,12 @@ private slots: QVERIFY(QDir().rmdir(testDirectory)); } - void testAllowRunningProcess() - { - #ifdef Q_OS_MACOS - QSKIP("In macOS the app path and maintenancetool differ, not possible to test running processes."); - #endif - PackageManagerCore core; - core.setPackageManager(); - const QString testDirectory = QInstaller::generateTemporaryFileName(); - QVERIFY(QDir().mkpath(testDirectory)); - core.setValue(scTargetDir, testDirectory); - - QString appFilePath = QCoreApplication::applicationFilePath(); - core.setAllowedRunningProcesses(QStringList() << appFilePath); - const QString warningMessage = QString("Failure to read packages from "); - const QRegularExpression re(warningMessage); - QTest::ignoreMessage(QtWarningMsg, re); - QTest::ignoreMessage(QtDebugMsg, "No updates available."); - - QCOMPARE(PackageManagerCore::Canceled, core.updateComponentsSilently(QStringList())); - QVERIFY(QDir().rmdir(testDirectory)); - } - - void testDisallowRunningProcess() - { - #ifdef Q_OS_MACOS - QSKIP("In macOS the app path and maintenancetool differ, not possible to test running processes."); - #endif - PackageManagerCore core; - core.setPackageManager(); - const QString testDirectory = QInstaller::generateTemporaryFileName(); - QVERIFY(QDir().mkpath(testDirectory)); - core.setValue(scTargetDir, testDirectory); - - const QString warningMessageUp = QString("Unable to update components. Please stop these processes: "); - const QRegularExpression reUp(warningMessageUp); - QTest::ignoreMessage(QtWarningMsg, reUp); - QVERIFY_EXCEPTION_THROWN(core.updateComponentsSilently(QStringList()), Error); - - const QString warningMessageRm = QString("Unable to remove components. Please stop these processes: "); - const QRegularExpression reRm(warningMessageRm); - QTest::ignoreMessage(QtWarningMsg, reRm); - QVERIFY_EXCEPTION_THROWN(core.removeInstallationSilently(), Error); - - QVERIFY(QDir().rmdir(testDirectory)); - } - void testCoreDataValues() { QHash<QString, QString> userValues; PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (), - QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, + QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, userValues, true); QCOMPARE(core->value("AllUsers"), QLatin1String("")); QCOMPARE(core->value("ProductName"), QLatin1String("Unit Test Application")); @@ -361,7 +314,7 @@ private slots: userValues.insert("RootDir", "Overwritten RootDir"); PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (), - QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, + QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, userValues, true); QCOMPARE(core->value("AllUsers"), QLatin1String("true")); QCOMPARE(core->value("ProductName"), QLatin1String("Overwritten ProductName")); diff --git a/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z Binary files differnew file mode 100644 index 000000000..543aab656 --- /dev/null +++ b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z diff --git a/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z Binary files differnew file mode 100644 index 000000000..a59f269e7 --- /dev/null +++ b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z diff --git a/tests/auto/installer/prependfileoperation/data/repository/Updates.xml b/tests/auto/installer/prependfileoperation/data/repository/Updates.xml new file mode 100644 index 000000000..e61d2445f --- /dev/null +++ b/tests/auto/installer/prependfileoperation/data/repository/Updates.xml @@ -0,0 +1,16 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> + <PackageUpdate> + <Name>B</Name> + <DisplayName>A</DisplayName> + <Description>Example component B</Description> + <Version>1.0.2-1</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>true</Default> + <Script>script.qs</Script> + <SHA1>750eda14d867849aeb2f47d620f6e5f32134f375</SHA1> + <DownloadableArchives>content.7z</DownloadableArchives> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z Binary files differnew file mode 100644 index 000000000..d936db354 --- /dev/null +++ b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z diff --git a/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml new file mode 100644 index 000000000..379fe865f --- /dev/null +++ b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml @@ -0,0 +1,20 @@ +<Updates> + <ApplicationName>{AnyApplication}</ApplicationName> + <ApplicationVersion>1.0.0</ApplicationVersion> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.0</Version> + <ReleaseDate>2020-01-01</ReleaseDate> + <Default>true</Default> + <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/> + <DownloadableArchives>content.7z</DownloadableArchives> + <Operations> + <Operation name="PrependFile"> + <Argument>@TargetDir@/C.txt</Argument> + <Argument>Prepended text: </Argument> + </Operation> + </Operations> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/prependfileoperation/prependfileoperation.pro b/tests/auto/installer/prependfileoperation/prependfileoperation.pro new file mode 100644 index 000000000..5f68385fe --- /dev/null +++ b/tests/auto/installer/prependfileoperation/prependfileoperation.pro @@ -0,0 +1,10 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +SOURCES += tst_prependfileoperation.cpp + +RESOURCES += \ + settings.qrc \ + ../shared/config.qrc diff --git a/tests/auto/installer/prependfileoperation/settings.qrc b/tests/auto/installer/prependfileoperation/settings.qrc new file mode 100644 index 000000000..deaeb257f --- /dev/null +++ b/tests/auto/installer/prependfileoperation/settings.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>data/repository/Updates.xml</file> + <file>data/repository/B/1.0.2-1content.7z</file> + <file>data/repository/B/1.0.2-1meta.7z</file> + <file>data/xmloperationrepository/Updates.xml</file> + <file>data/xmloperationrepository/C/1.0.0content.7z</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp b/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp new file mode 100644 index 000000000..12f178cb4 --- /dev/null +++ b/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp @@ -0,0 +1,180 @@ +/************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $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 "../shared/packagemanager.h" + +#include <updateoperations.h> +#include <packagemanagercore.h> + +#include <QFile> +#include <QTest> + +using namespace KDUpdater; +using namespace QInstaller; + +class tst_prependfileoperation : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + m_testFilePath = qApp->applicationDirPath() + QDir::toNativeSeparators("/test"); + } + + void testMissingArguments() + { + PrependFileOperation op; + + QVERIFY(op.testOperation()); + QVERIFY(!op.performOperation()); + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); + QCOMPARE(op.errorString(), QString("Invalid arguments in PrependFile: 0 arguments given, 2 to 4 arguments expected in the form: <filename> <text to prepend> [UNDOOPERATION, \"\"].")); + + op.setArguments(QStringList() << "" << ""); + QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified"); + QVERIFY(!op.performOperation()); + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError); + QCOMPARE(op.errorString(), QString("Cannot open file \"\" for reading: No file name specified")); + } + + void testPrependText_data() + { + QTest::addColumn<QString>("source"); + QTest::addColumn<QString>("prepend"); + QTest::addColumn<QString>("expected"); + QTest::addColumn<bool>("overrideUndo"); + QTest::newRow("newline") << "Line1\nLine2\nLine3\n" << "PrependedText" + << "PrependedTextLine1\nLine2\nLine3\n" << false; + QTest::newRow("no newline") << "dolore sit amet" << "Lorem ipsum " + << "Lorem ipsum dolore sit amet" << false; + + QTest::newRow("no undo")<< "dolore sit amet" << "Lorem ipsum " + << "Lorem ipsum dolore sit amet" << true; + } + + void testPrependText() + { + QFETCH(QString, source); + QFETCH(QString, prepend); + QFETCH(QString, expected); + QFETCH(bool, overrideUndo); + + QFile file(m_testFilePath); + QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); + + QTextStream stream(&file); + stream << source << Qt::flush; + file.close(); + + PrependFileOperation *op = new PrependFileOperation(); + op->setArguments(QStringList() << m_testFilePath << prepend); + if (overrideUndo) + op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION")); + + op->backup(); + QVERIFY(QFileInfo(op->value("backupOfFile").toString()).exists()); + + QVERIFY2(op->performOperation(), op->errorString().toLatin1()); + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); + QCOMPARE(stream.readAll(), expected); + file.close(); + + QVERIFY2(op->undoOperation(), op->errorString().toLatin1()); + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); + if (overrideUndo) + QCOMPARE(stream.readAll(), expected); + else + QCOMPARE(stream.readAll(), source); + file.close(); + + QVERIFY(file.remove()); + + QString backupFileName = op->value("backupOfFile").toString(); + delete op; + QVERIFY(!QFileInfo::exists(backupFileName)); + } + + void testPrependFromCLI_data() + { + QTest::addColumn<QString>("repository"); + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QString>("componentName"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("operationFromScript") + << (":///data/repository") + << ("B.txt") + << ("B") + << ("Prepended text: lorem ipsum"); + + QTest::newRow("operationFromXML") + << (":///data/xmloperationrepository") + << ("C.txt") + << ("C") + << ("Prepended text: lorem ipsum"); + } + + void testPrependFromCLI() + { + QFETCH(QString, repository); + QFETCH(QString, fileName); + QFETCH(QString, componentName); + QFETCH(QString, expected); + + QString installDir = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(installDir)); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit + (installDir, repository)); + core->installSelectedComponentsSilently(QStringList() << componentName); + + QFile file(installDir + QDir::separator() + fileName); + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); + QTextStream stream(&file); + QCOMPARE(stream.readAll(), expected); + file.close(); + + core->setPackageManager(); + core->commitSessionOperations(); + // We cannot check the file contents here as it will be deleted on + // undo Extract, but at least check that the uninstallation succeeds. + QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently + (QStringList()<< componentName)); + + QDir dir(installDir); + QVERIFY(dir.removeRecursively()); + } + +private: + QString m_testFilePath; +}; + +QTEST_MAIN(tst_prependfileoperation) + +#include "tst_prependfileoperation.moc" diff --git a/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml b/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml index 0826afae8..6435ae0f7 100644 --- a/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml +++ b/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml @@ -5,7 +5,7 @@ <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> - <Description>Example component A</Description> + <Description>Example component for RegisterFileTypeOperation</Description> <Version>1.0.2-1</Version> <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> diff --git a/tests/auto/installer/replaceoperation/data/repository/Updates.xml b/tests/auto/installer/replaceoperation/data/repository/Updates.xml index a0ade298c..7585b57a4 100644 --- a/tests/auto/installer/replaceoperation/data/repository/Updates.xml +++ b/tests/auto/installer/replaceoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,6 +10,7 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>edb7672270729f9d34396cb70e6afd12fec90d2b</SHA1> <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/> <DownloadableArchives>content.7z</DownloadableArchives> </PackageUpdate> diff --git a/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z b/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z Binary files differindex fa75f2979..335685bb0 100644 --- a/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z +++ b/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z diff --git a/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z b/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z Binary files differnew file mode 100644 index 000000000..6631280a7 --- /dev/null +++ b/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z diff --git a/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z b/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z Binary files differnew file mode 100644 index 000000000..16f3a6c42 --- /dev/null +++ b/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z diff --git a/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z b/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z Binary files differnew file mode 100644 index 000000000..37c8fffc4 --- /dev/null +++ b/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z diff --git a/tests/auto/installer/repository/data/repository/Updates.xml b/tests/auto/installer/repository/data/repository/Updates.xml index 6fdfec9e5..f541882c5 100644 --- a/tests/auto/installer/repository/data/repository/Updates.xml +++ b/tests/auto/installer/repository/data/repository/Updates.xml @@ -1,13 +1,33 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> <Description>Example component A</Description> <Version>1.0.2</Version> <ReleaseDate>2015-01-01</ReleaseDate> - <Default>true</Default> + <Default>false</Default> <DownloadableArchives>content.7z</DownloadableArchives> + <Script postLoad="true">script.qs</Script> + </PackageUpdate> + <PackageUpdate> + <Name>B</Name> + <DisplayName>B</DisplayName> + <Description>Example component B</Description> + <Version>1.0.0</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + <Script>script.qs</Script> + </PackageUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.0</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + <Script postLoad="false">script.qs</Script> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/repository/settings.qrc b/tests/auto/installer/repository/settings.qrc index ff628b482..92db7e3e1 100644 --- a/tests/auto/installer/repository/settings.qrc +++ b/tests/auto/installer/repository/settings.qrc @@ -2,6 +2,9 @@ <qresource prefix="/"> <file>data/repository/Updates.xml</file> <file>data/repository/A/1.0.2content.7z</file> + <file>data/repository/A/1.0.2meta.7z</file> + <file>data/repository/B/1.0.0meta.7z</file> + <file>data/repository/C/1.0.0meta.7z</file> <file>data/compressedRepository/compressedRepository.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/repository/tst_repository.cpp b/tests/auto/installer/repository/tst_repository.cpp index db538ba5d..112098130 100644 --- a/tests/auto/installer/repository/tst_repository.cpp +++ b/tests/auto/installer/repository/tst_repository.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -39,6 +39,8 @@ using namespace QInstaller; +typedef QList<QPair<QString, QString>> SettingsPairList; + class tst_Repository : public QObject { Q_OBJECT @@ -168,7 +170,7 @@ private slots: categories.insert(category); settings.setRepositoryCategories(categories); - QHash<QString, QPair<Repository, Repository>> update; + QMultiHash<QString, QPair<Repository, Repository>> update; // non-empty update update.insert(QLatin1String("replace"), qMakePair(original, replacement)); @@ -210,6 +212,102 @@ private slots: QVERIFY(dir.removeRecursively()); core->deleteLater(); } + + void testPostLoadScriptFromRepository_data() + { + QTest::addColumn<QStringList>("installComponent"); + QTest::addColumn<bool>("repositoryPostLoadSetting"); + QTest::addColumn<SettingsPairList>("expectedSettingsBeforeInstall"); + QTest::addColumn<SettingsPairList>("expectedSettingsAfterInstall"); + QTest::addColumn<QStringList>("unexpectedSettings"); + + // component A has postLoad = true in component.xml + // component B has no postLoad attribute + // component C has postLoad = false in component.xml + + SettingsPairList expectedSettingsListAfterInstall; + expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentAKey", "componentAValue")); + + SettingsPairList expectedSettingsListBeforeInstall; + expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentBKey", "componentBValue")); + expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentCKey", "componentCValue")); + + QTest::newRow("noRepoPostLoadComponentA") + << (QStringList() << "A") + << false + << expectedSettingsListBeforeInstall + << expectedSettingsListAfterInstall + << (QStringList()); + + // Component B is installed so values from component A and component C should not be set + expectedSettingsListAfterInstall.clear(); + expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentBKey", "componentBValue")); + QTest::newRow("noRepoPostLoadComponentB") + << (QStringList() << "B") + << false + << expectedSettingsListBeforeInstall + << expectedSettingsListAfterInstall + << (QStringList() << "componentAValue" << "componentCValue"); + + // PostLoad is set to whole repository. Since only A is installed, + // values from component B and component C values are not set + expectedSettingsListBeforeInstall.clear(); + expectedSettingsListAfterInstall.clear(); + expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentAKey", "componentAValue")); + QTest::newRow("repoPostLoadComponentA") << (QStringList() << "A") + << true + << expectedSettingsListBeforeInstall + << expectedSettingsListAfterInstall + << (QStringList() << "componentBValue" << "componentCValue"); + + // PostLoad is set to whole repository. Since only B is installed, + // values from component C and component A are not set. + expectedSettingsListAfterInstall.clear(); + expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentBKey", "componentBValue")); + QTest::newRow("repoPostLoadComponentB") << (QStringList() << "B") + << true + << expectedSettingsListBeforeInstall + << expectedSettingsListAfterInstall + << (QStringList() << "componentCValue" << "componentAValue"); + + // PostLoad is set to whole repository. Since component C has its postload = false, + // value is set to component C before install + expectedSettingsListBeforeInstall.clear(); + expectedSettingsListAfterInstall.clear(); + expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentCKey", "componentCValue")); + QTest::newRow("repoPostLoadComponentC") << (QStringList() << "C") + << true + << expectedSettingsListBeforeInstall + << expectedSettingsListAfterInstall + << (QStringList() << "componentAValue" << "componentBValue"); + } + + void testPostLoadScriptFromRepository() + { + QFETCH(QStringList, installComponent); + QFETCH(bool, repositoryPostLoadSetting); + QFETCH(SettingsPairList, expectedSettingsBeforeInstall); + QFETCH(SettingsPairList, expectedSettingsAfterInstall); + QFETCH(QStringList, unexpectedSettings); + + QString installDir = QInstaller::generateTemporaryFileName(); + QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit(installDir)); + QSet<Repository> repoList; + Repository repo = Repository::fromUserInput(":///data/repository"); + repo.setPostLoadComponentScript(repositoryPostLoadSetting); + repoList.insert(repo); + core->settings().setDefaultRepositories(repoList); + QVERIFY(core->fetchRemotePackagesTree()); + + for (const QPair<QString, QString> settingValue : expectedSettingsBeforeInstall) + QCOMPARE(core->value(settingValue.first), settingValue.second); + + core->installSelectedComponentsSilently(installComponent); + for (const QPair<QString, QString> settingValue : expectedSettingsAfterInstall) + QCOMPARE(core->value(settingValue.first), settingValue.second); + for (const QString unexpectedSetting : unexpectedSettings) + QVERIFY2(!core->containsValue(unexpectedSetting), "Core contains unexpected value"); + } }; QTEST_MAIN(tst_Repository) diff --git a/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro b/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro new file mode 100644 index 000000000..72e61ad80 --- /dev/null +++ b/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro @@ -0,0 +1,6 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +SOURCES = tst_rmdiroperationtest.cpp diff --git a/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp b/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp new file mode 100644 index 000000000..bfdd5921e --- /dev/null +++ b/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp @@ -0,0 +1,111 @@ +/************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $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 "init.h" +#include "updateoperations.h" + +#include <QDir> +#include <QObject> +#include <QTest> +#include <QFile> +#include <QTextStream> + +using namespace KDUpdater; +using namespace QInstaller; + +class tst_rmdiroperationtest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + QInstaller::init(); + QString path = QDir::current().path() + QDir::toNativeSeparators("/test"); + if (QDir(path).exists()) { + QFAIL("Remove test folder first!"); + } + } + + void testMissingArguments() + { + RmdirOperation op; + + QVERIFY(op.testOperation()); + QVERIFY(!op.performOperation()); + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); + QCOMPARE(op.errorString(), QLatin1String("Invalid arguments in Rmdir: 0 arguments given, 1 to 3 " + "arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"].")); + } + + void testRemoveDirectory_data() + { + QTest::addColumn<QString>("directory"); + QTest::addColumn<bool>("overrideUndo"); + QTest::newRow("/test") << "/test" << false; + QTest::newRow("/test/test") << "/test/test" << false; + QTest::newRow("/test/test/test") << "/test/test/test" << false; + QTest::newRow("no undo") << "/test/test/test/test" << true; + } + + void testRemoveDirectory() + { + QFETCH(QString, directory); + QFETCH(bool, overrideUndo); + + QString path = QDir::current().path() + QDir::toNativeSeparators(directory); + //Create first the directories utilizing MkdirOperation + MkdirOperation op; + op.setArguments(QStringList() << path); + op.setArguments(op.arguments() << QLatin1String("UNDOOPERATION")); + op.backup(); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(QDir(path).exists(), path.toLatin1()); + + RmdirOperation rmOp; + rmOp.setArguments(QStringList() << path); + if (overrideUndo) + rmOp.setArguments(op.arguments() << QLatin1String("UNDOOPERATION")); + rmOp.backup(); + rmOp.performOperation(); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); + + QVERIFY2(rmOp.undoOperation(), rmOp.errorString().toLatin1()); + if (overrideUndo) { + QVERIFY2(!QDir(path).exists(), path.toLatin1()); + } else { + QVERIFY2(QDir(path).exists(), path.toLatin1()); + QVERIFY(QDir(path).removeRecursively()); + } + } +}; + +QTEST_MAIN(tst_rmdiroperationtest) + +#include "tst_rmdiroperationtest.moc" diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp index 105bcf5d7..86017a229 100644 --- a/tests/auto/installer/scriptengine/tst_scriptengine.cpp +++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -221,13 +221,6 @@ private slots: .hasProperty(QLatin1String("getExistingDirectory")), true); QCOMPARE(global.property(QLatin1String("QFileDialog")) .hasProperty(QLatin1String("getOpenFileName")), true); - - QCOMPARE(global.hasProperty(QLatin1String("InstallerProxy")), true); - QCOMPARE(global.property(QLatin1String("InstallerProxy")) - .hasProperty(QLatin1String("componentByName")), true); - QCOMPARE(global.property(QLatin1String("InstallerProxy")) - .hasProperty(QLatin1String("components")), true); - QCOMPARE(global.hasProperty(QLatin1String("QDesktopServices")), true); QCOMPARE(global.property(QLatin1String("QDesktopServices")) .hasProperty(QLatin1String("openUrl")), true); @@ -249,6 +242,8 @@ private slots: QJSValue sinfo = global.property(QLatin1String("systemInfo")); QCOMPARE(sinfo.property(QLatin1String("currentCpuArchitecture")).toString(), QSysInfo::currentCpuArchitecture()); + QCOMPARE(sinfo.property(QLatin1String("buildCpuArchitecture")).toString(), + QSysInfo::buildCpuArchitecture()); QCOMPARE(sinfo.property(QLatin1String("kernelType")).toString(), QSysInfo::kernelType()); QCOMPARE(sinfo.property(QLatin1String("kernelVersion")).toString(), QSysInfo::kernelVersion()); @@ -388,13 +383,24 @@ private slots: QCOMPARE(result.isError(), false); } + void loadSimpleComponentScript_data() + { + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("postLoad"); + QTest::newRow("Pre component script") << ":///data/component1.qs" << false; + QTest::newRow("Post component script") << ":///data/component1.qs" << true; + } + void loadSimpleComponentScript() { - try { - // ignore retranslateUi which is called by loadComponentScript + QFETCH(QString, path); + QFETCH(bool, postLoad); + + try { + // ignore retranslateUi which is called by evaluateComponentScript setExpectedScriptOutput("Component constructor - OK"); setExpectedScriptOutput("retranslateUi - OK"); - m_component->loadComponentScript(":///data/component1.qs"); + m_component->evaluateComponentScript(path, postLoad); setExpectedScriptOutput("retranslateUi - OK"); m_component->languageChanged(); @@ -422,8 +428,19 @@ private slots: } } + void loadBrokenComponentScript_data() + { + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("postLoad"); + QTest::newRow("Pre component script") << ":///data/component2.qs" << false; + QTest::newRow("Post component script") << ":///data/component2.qs" << true; + } + void loadBrokenComponentScript() { + QFETCH(QString, path); + QFETCH(bool, postLoad); + Component *testComponent = new Component(&m_core); testComponent->setValue(scName, "broken.component"); @@ -433,21 +450,32 @@ private slots: try { // ignore Output from script setExpectedScriptOutput("script function: Component"); - testComponent->loadComponentScript(":///data/component2.qs"); + testComponent->evaluateComponentScript(path, postLoad); } catch (const Error &error) { const QString debugMessage( - QString("create Error-Exception: \"Exception while loading the component script \"%1\": " - "ReferenceError: broken is not defined\"").arg(QDir::toNativeSeparators(":///data/component2.qs"))); + QString("Exception while loading the component script \"%1\": " + "ReferenceError: broken is not defined on line number: 33").arg(QDir::toNativeSeparators(":///data/component2.qs"))); QVERIFY2(debugMessage.contains(error.message()), "(ReferenceError: broken is not defined)"); } } + void loadComponentUserInterfaces_data() + { + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("postLoad"); + QTest::newRow("Pre component script") << ":///data/userinterface.qs" << false; + QTest::newRow("Post component script") << ":///data/userinterface.qs" << true; + } + void loadComponentUserInterfaces() { - try { + QFETCH(QString, path); + QFETCH(bool, postLoad); + try { setExpectedScriptOutput("checked: false"); + TestGui testGui(&m_core); m_component->loadUserInterfaces(QDir(":///data"), QStringList() << QLatin1String("form.ui")); - m_component->loadComponentScript(":///data/userinterface.qs"); + m_component->evaluateComponentScript(path, postLoad); } catch (const Error &error) { QFAIL(qPrintable(error.message())); } @@ -591,7 +619,7 @@ private slots: try { m_core.setPackageManager(); Component *component = m_core.componentByName("component.test.addOperation"); - component->loadComponentScript(":///data/addOperation.qs"); + component->evaluateComponentScript(":///data/addOperation.qs"); setExpectedScriptOutput("Component::createOperations()"); component->createOperations(); diff --git a/tests/auto/installer/settings/data/full_config.xml b/tests/auto/installer/settings/data/full_config.xml index 304dd21f4..bccb6f7ca 100644 --- a/tests/auto/installer/settings/data/full_config.xml +++ b/tests/auto/installer/settings/data/full_config.xml @@ -37,6 +37,7 @@ File should contain all elements we allow in a config.xml <DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary> <AllowSpaceInPath>true</AllowSpaceInPath> <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters> + <AllowRepositoriesForOfflineInstaller>true</AllowRepositoriesForOfflineInstaller> <DisableAuthorizationFallback>true</DisableAuthorizationFallback> <DisableCommandLineInterface>true</DisableCommandLineInterface> <RepositorySettingsPageVisible>false</RepositorySettingsPageVisible> diff --git a/tests/auto/installer/settings/tst_settings.cpp b/tests/auto/installer/settings/tst_settings.cpp index d120f5680..15dcc98a1 100644 --- a/tests/auto/installer/settings/tst_settings.cpp +++ b/tests/auto/installer/settings/tst_settings.cpp @@ -109,6 +109,7 @@ void tst_Settings::loadTutorialConfig() QCOMPARE(settings.repositorySettingsPageVisible(), true); QCOMPARE(settings.allowSpaceInPath(), true); QCOMPARE(settings.allowNonAsciiCharacters(), false); + QCOMPARE(settings.allowRepositoriesForOfflineInstaller(), true); QCOMPARE(settings.disableAuthorizationFallback(), false); QCOMPARE(settings.disableCommandLineInterface(), false); QCOMPARE(settings.createLocalRepository(), false); diff --git a/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z b/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z Binary files differnew file mode 100644 index 000000000..211bc0e0a --- /dev/null +++ b/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z diff --git a/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z b/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z Binary files differnew file mode 100644 index 000000000..a990fdbf1 --- /dev/null +++ b/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z diff --git a/tests/auto/installer/settingsoperation/data/repository/Updates.xml b/tests/auto/installer/settingsoperation/data/repository/Updates.xml index 77b5a9956..3e88f849d 100644 --- a/tests/auto/installer/settingsoperation/data/repository/Updates.xml +++ b/tests/auto/installer/settingsoperation/data/repository/Updates.xml @@ -1,13 +1,33 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> <Description>Example component A</Description> <Version>1.0.2-1</Version> <ReleaseDate>2015-01-01</ReleaseDate> - <Default>true</Default> + <Default>false</Default> + <Script>script.qs</Script> + <SHA1>5dc8a98f591998de0c555e194e228fa740a15632</SHA1> + </PackageUpdate> + <PackageUpdate> + <Name>B</Name> + <DisplayName>B</DisplayName> + <Description>Example component B</Description> + <Version>1.0.0</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> + <Script>script.qs</Script> + </PackageUpdate> + <PackageUpdate> + <Name>C</Name> + <DisplayName>C</DisplayName> + <Description>Example component C</Description> + <Version>1.0.0</Version> + <ReleaseDate>2015-01-01</ReleaseDate> + <Default>false</Default> <Script>script.qs</Script> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/settingsoperation/settings.qrc b/tests/auto/installer/settingsoperation/settings.qrc index d030220ab..8da639ad6 100644 --- a/tests/auto/installer/settingsoperation/settings.qrc +++ b/tests/auto/installer/settingsoperation/settings.qrc @@ -2,5 +2,7 @@ <qresource prefix="/"> <file>data/repository/Updates.xml</file> <file>data/repository/A/1.0.2-1meta.7z</file> + <file>data/repository/B/1.0.0meta.7z</file> + <file>data/repository/C/1.0.0meta.7z</file> </qresource> </RCC> diff --git a/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp b/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp index 9b08d4f6f..2da0870c7 100644 --- a/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp +++ b/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp @@ -177,6 +177,7 @@ private slots: QFile testFile(testFilePath); QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Text), contentFile.errorString().toLatin1()); + m_cleanupFilePaths << testFilePath; QTextStream out(&testFile); @@ -244,6 +245,7 @@ private slots: QFile testFile(testFilePath); QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Text), contentFile.errorString() .toLatin1()); + m_cleanupFilePaths << testFilePath; QTextStream out(&testFile); @@ -293,7 +295,7 @@ private slots: QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(), QStringList() << "value1" << "value2" << "value3"); - core->installDefaultComponentsSilently(); + core->installSelectedComponentsSilently(QStringList() << "A"); QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(), QStringList() << "value1" << "value2" << "value3" << "valueFromScript"); @@ -309,6 +311,68 @@ private slots: core->deleteLater(); } + void testPerformingFromCLIWithPlaceholders() + { + QString installDir = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(installDir)); + PackageManagerCore *core = PackageManager::getPackageManagerWithInit + (installDir, ":///data/repository"); + + core->installSelectedComponentsSilently(QStringList() << "B"); + // Path is set in component constructor in install script + const QString settingsFile = core->value("SettingsPathFromVariable"); + QSettings testSettings(QDir(m_testSettingsDirPath).filePath(settingsFile), + QSettings::IniFormat); + + QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(), + QStringList() << "ValueFromPlaceholder"); + + core->commitSessionOperations(); + core->setPackageManager(); + core->uninstallComponentsSilently(QStringList() << "B"); + + // Settings file is removed as it is empty + QVERIFY(!QFile::exists(settingsFile)); + QDir dir(installDir); + QVERIFY(dir.removeRecursively()); + core->deleteLater(); + } + + void testPerformingFromCLIWithSettingsFileMoved() + { + QString installDir = QInstaller::generateTemporaryFileName(); + QVERIFY(QDir().mkpath(installDir)); + PackageManagerCore *core = PackageManager::getPackageManagerWithInit + (installDir, ":///data/repository"); + + + core->installSelectedComponentsSilently(QStringList() << "C"); + + const QString settingsFileName = qApp->applicationDirPath() + "/oldTestSettings.ini"; + QSettings testSettings(QDir(m_testSettingsDirPath).filePath(settingsFileName), + QSettings::IniFormat); + + QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(), + QStringList() << "valueFromScript"); + + QFile settingsFile(settingsFileName); + // Move the settings path to new location. Script has set values + // ComponentCSettingsPath (@InstallerDirPath@/newTestSettings.ini) and + // ComponentCSettingsPath_OLD (@InstallerDirPath@/oldTestSettings.ini) so + // UNDO operation should delete the moved newTestSettings.ini file instead. + QVERIFY2(settingsFile.rename(qApp->applicationDirPath() + "/newTestSettings.ini"), "Could not move settings file."); + core->commitSessionOperations(); + core->setPackageManager(); + core->uninstallComponentsSilently(QStringList() << "C"); + + // Settings file is removed in uninstall as it is empty + QVERIFY2(!QFile::exists(qApp->applicationDirPath() + "/newTestSettings.ini"), "Settings file not deleted correctly"); + + QDir dir(installDir); + QVERIFY(dir.removeRecursively()); + core->deleteLater(); + } + // called after all tests void cleanupTestCase() { diff --git a/tests/auto/installer/shared/packagemanager.h b/tests/auto/installer/shared/packagemanager.h index a95dd4442..9948be00a 100644 --- a/tests/auto/installer/shared/packagemanager.h +++ b/tests/auto/installer/shared/packagemanager.h @@ -61,7 +61,6 @@ struct PackageManager PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> ()); QString appFilePath = QCoreApplication::applicationFilePath(); - core->setAllowedRunningProcesses(QStringList() << appFilePath); core->disableWriteMaintenanceTool(); core->setAutoConfirmCommand(); QSet<Repository> repoList; diff --git a/tests/auto/installer/shared/verifyinstaller.h b/tests/auto/installer/shared/verifyinstaller.h index 4d70c577b..e19d3fa0a 100644 --- a/tests/auto/installer/shared/verifyinstaller.h +++ b/tests/auto/installer/shared/verifyinstaller.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -29,6 +29,8 @@ #ifndef VERIFYINSTALLER_H #define VERIFYINSTALLER_H +#include <packagemanagercore.h> + #include <QString> #include <QStringList> #include <QCryptographicHash> @@ -36,6 +38,9 @@ #include <QDir> #include <QtTest/QTest> +#include <iostream> +#include <sstream> + struct VerifyInstaller { static void verifyInstallerResources(const QString &installDir, const QString &componentName, const QString &fileName) @@ -114,5 +119,21 @@ struct VerifyInstaller } } } + + template <typename Func, typename... Args> + static void verifyListPackagesMessage(QInstaller::PackageManagerCore *core, const QString &message, + Func func, Args... args) + { + std::ostringstream stream; + std::streambuf *buf = std::cout.rdbuf(); + std::cout.rdbuf(stream.rdbuf()); + + (core->*func)(std::forward<Args>(args)...); + + std::cout.rdbuf(buf); + QVERIFY(stream && stream.tellp() == message.size()); + for (const QString &line : message.split(QLatin1String("\n"))) + QVERIFY(stream.str().find(line.toStdString()) != std::string::npos); + } }; #endif diff --git a/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml b/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml index 77b5a9956..6df6a436b 100644 --- a/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml +++ b/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml @@ -1,6 +1,7 @@ <Updates> <ApplicationName>{AnyApplication}</ApplicationName> <ApplicationVersion>1.0.0</ApplicationVersion> + <Checksum>false</Checksum> <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> @@ -9,5 +10,6 @@ <ReleaseDate>2015-01-01</ReleaseDate> <Default>true</Default> <Script>script.qs</Script> + <SHA1>8f2df84c9eada2570c02a7df573288e5cb6644e2</SHA1> </PackageUpdate> </Updates> diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp index 8b5d1fdcf..4548af3f1 100644 --- a/tests/auto/installer/solver/tst_solver.cpp +++ b/tests/auto/installer/solver/tst_solver.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2022 The Qt Company Ltd. +** Copyright (C) 2023 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -39,7 +39,7 @@ using namespace QInstaller; typedef QMap<Component *, QStringList> ComponentToStringList; -typedef QList<QPair<Component *, UninstallerCalculator::UninstallReasonType>> UninstallReasonList; +typedef QList<QPair<Component *, CalculatorBase::Resolution>> UninstallReasonList; Q_DECLARE_METATYPE(UninstallReasonList) @@ -48,7 +48,7 @@ public: Data() {} explicit Data(const QString &data) : m_data(data) {} - inline uint qHash(const Data &test); + inline hashValue qHash(const Data &test); QString data() const { return m_data; } bool operator==(const Data &rhs) const { return m_data == rhs.m_data; } const Data &operator=(const Data &rhs) { if (this != &rhs) { m_data = rhs.m_data; } return *this; } @@ -56,7 +56,7 @@ public: private: QString m_data; }; -inline uint qHash(const Data &data) +inline hashValue qHash(const Data &data) { return qHash(data.data()); } @@ -149,7 +149,7 @@ private slots: QTest::addColumn<PackageManagerCore *>("core"); QTest::addColumn<QList<Component *> >("selectedComponents"); QTest::addColumn<QList<Component *> >("expectedResult"); - QTest::addColumn<QList<int> >("installReason"); + QTest::addColumn<QList<CalculatorBase::Resolution> >("installReason"); QTest::addColumn<AutoDependencyHash >("autodependencyHash"); PackageManagerCore *core = new PackageManagerCore(); @@ -176,11 +176,11 @@ private slots: QTest::newRow("Installer resolved") << core << (QList<Component *>() << componentB) << (QList<Component *>() << componentB_NewVersion << componentAB << componentB << componentB_Auto) - << (QList<int>() - << InstallerCalculator::Dependent - << InstallerCalculator::Dependent - << InstallerCalculator::Resolved - << InstallerCalculator::Automatic) + << (QList<CalculatorBase::Resolution>() + << CalculatorBase::Resolution::Dependent + << CalculatorBase::Resolution::Dependent + << CalculatorBase::Resolution::Resolved + << CalculatorBase::Resolution::Automatic) << autodependencyHash; } @@ -189,18 +189,17 @@ private slots: QFETCH(PackageManagerCore *, core); QFETCH(QList<Component *> , selectedComponents); QFETCH(QList<Component *> , expectedResult); - QFETCH(QList<int>, installReason); + QFETCH(QList<CalculatorBase::Resolution>, installReason); QFETCH(AutoDependencyHash, autodependencyHash); - InstallerCalculator calc(core, core->components(PackageManagerCore::ComponentType::AllNoReplacements) - , autodependencyHash); - calc.appendComponentsToInstall(selectedComponents); - QList<Component *> result = calc.orderedComponentsToInstall(); + InstallerCalculator calc(core, autodependencyHash); + calc.solve(selectedComponents); + QList<Component *> result = calc.resolvedComponents(); QCOMPARE(result.count(), expectedResult.count()); for (int i = 0; i < result.count(); i++) { QCOMPARE(result.at(i), expectedResult.at(i)); - QCOMPARE((int)calc.installReasonType(result.at(i)), installReason.at(i)); + QCOMPARE(calc.resolutionType(result.at(i)), installReason.at(i)); } delete core; } @@ -236,11 +235,11 @@ private slots: QFETCH(QList<Component *> , selectedComponents); QFETCH(QList<Component *> , expectedResult); - InstallerCalculator calc(core, core->components(PackageManagerCore::ComponentType::AllNoReplacements), QHash<QString, QStringList>()); + InstallerCalculator calc(core, QHash<QString, QStringList>()); QTest::ignoreMessage(QtWarningMsg, "Cannot find missing dependency \"B->=2.0.0\" for \"A\"."); - calc.appendComponentsToInstall(selectedComponents); + calc.solve(selectedComponents); - QList<Component *> result = calc.orderedComponentsToInstall(); + QList<Component *> result = calc.resolvedComponents(); QCOMPARE(result.count(), expectedResult.count()); delete core; } @@ -249,8 +248,7 @@ private slots: { QTest::addColumn<PackageManagerCore *>("core"); QTest::addColumn<QList<Component *> >("selectedToUninstall"); - QTest::addColumn<QList<Component *> >("installedComponents"); - QTest::addColumn<QSet<Component *> >("expectedResult"); + QTest::addColumn<QList<Component *> >("expectedResult"); QTest::addColumn<UninstallReasonList >("uninstallReasons"); QTest::addColumn<LocalDependencyHash >("dependencyHash"); @@ -274,12 +272,11 @@ private slots: QHash<QString, QStringList> dependencyComponentHash; dependencyComponentHash.insert(QLatin1String("A.B"), QStringList() << QLatin1String("B")); - uninstallReasonList.append(qMakePair(componentAB, UninstallerCalculator::Selected)); - uninstallReasonList.append(qMakePair(componentB, UninstallerCalculator::Dependent)); + uninstallReasonList.append(qMakePair(componentAB, CalculatorBase::Resolution::Selected)); + uninstallReasonList.append(qMakePair(componentB, CalculatorBase::Resolution::Dependent)); QTest::newRow("Uninstaller resolved") << core << (QList<Component *>() << componentAB) - << (QList<Component *>() << componentA << componentB) - << (QSet<Component *>() << componentAB << componentB) + << (QList<Component *>() << componentB << componentAB) << uninstallReasonList << dependencyComponentHash; @@ -300,12 +297,11 @@ private slots: dependencyComponentHash.insert(QLatin1String("A"), QStringList() << QLatin1String("B")); - uninstallReasonList.append(qMakePair(compA, UninstallerCalculator::Selected)); - uninstallReasonList.append(qMakePair(compB, UninstallerCalculator::Dependent)); + uninstallReasonList.append(qMakePair(compA, CalculatorBase::Resolution::Selected)); + uninstallReasonList.append(qMakePair(compB, CalculatorBase::Resolution::Dependent)); QTest::newRow("Cascade dependencies") << core << (QList<Component *>() << compA) - << (QList<Component *>() << compB) - << (QSet<Component *>() << compA << compB) + << (QList<Component *>() << compB << compA) << (uninstallReasonList) << dependencyComponentHash; } @@ -314,16 +310,15 @@ private slots: { QFETCH(PackageManagerCore *, core); QFETCH(QList<Component *> , selectedToUninstall); - QFETCH(QList<Component *> , installedComponents); - QFETCH(QSet<Component *> , expectedResult); + QFETCH(QList<Component *> , expectedResult); QFETCH(UninstallReasonList, uninstallReasons); QFETCH(LocalDependencyHash, dependencyHash); - UninstallerCalculator calc(installedComponents, core, QHash<QString, QStringList>(), dependencyHash, QStringList()); - calc.appendComponentsToUninstall(selectedToUninstall); - QSet<Component *> result = calc.componentsToUninstall(); + UninstallerCalculator calc(core, QHash<QString, QStringList>(), dependencyHash, QStringList()); + calc.solve(selectedToUninstall); + QList<Component *> result = calc.resolvedComponents(); for (auto pair : uninstallReasons) { - UninstallerCalculator::UninstallReasonType type = calc.uninstallReasonType(pair.first); + CalculatorBase::Resolution type = calc.resolutionType(pair.first); QCOMPARE(pair.second, type); } QCOMPARE(result.count(), expectedResult.count()); diff --git a/tests/auto/installer/treename/tst_treename.cpp b/tests/auto/installer/treename/tst_treename.cpp index 3d42126eb..2c8be6ddd 100644 --- a/tests/auto/installer/treename/tst_treename.cpp +++ b/tests/auto/installer/treename/tst_treename.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -394,7 +394,7 @@ void tst_TreeName::remotePackageConflictsLocal() QHash<QString, QString> params; params.insert(scTargetDir, qApp->applicationDirPath()); PackageManagerCore core(BinaryContent::MagicPackageManagerMarker, QList<OperationBlob>(), - QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, params); + QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, params); core.settings().setAllowUnstableComponents(true); core.settings().setDefaultRepositories(QSet<Repository>() diff --git a/tests/auto/tools/repotest/test_package_versions/repository_1/Updates.xml b/tests/auto/tools/repotest/test_package_versions/repository_1/Updates.xml index dfae8c8bd..edb6515bd 100644 --- a/tests/auto/tools/repotest/test_package_versions/repository_1/Updates.xml +++ b/tests/auto/tools/repotest/test_package_versions/repository_1/Updates.xml @@ -5,7 +5,7 @@ <PackageUpdate> <Name>A</Name> <DisplayName>A</DisplayName> - <Description>Example component A</Description> + <Description>Test component A</Description> <Version>2.0.0</Version> <ReleaseDate>2020-01-01</ReleaseDate> <Default>true</Default> @@ -17,7 +17,7 @@ <PackageUpdate> <Name>B</Name> <DisplayName>B</DisplayName> - <Description>Example component B</Description> + <Description>Test component B</Description> <Version>1.0.0</Version> <ReleaseDate>2020-01-01</ReleaseDate> <Default>true</Default> diff --git a/tests/auto/tools/repotest/tst_repotest.cpp b/tests/auto/tools/repotest/tst_repotest.cpp index af48ba3fc..f1c0ae9dd 100644 --- a/tests/auto/tools/repotest/tst_repotest.cpp +++ b/tests/auto/tools/repotest/tst_repotest.cpp @@ -574,7 +574,7 @@ private slots: private: QInstallerTools::RepositoryInfo m_repoInfo; QInstallerTools::PackageInfoVector m_packages; - TempDirDeleter m_tempDirDeleter; + TempPathDeleter m_tempDirDeleter; }; QTEST_MAIN(tst_repotest) |