From d2ae9c16c3427c272d41e9a471f705ad8947a97a Mon Sep 17 00:00:00 2001 From: Katja Marttila Date: Wed, 28 Feb 2018 09:54:22 +0200 Subject: Add attribute to mark parts of install tree unstable This commit adds new AllowUnstableComponents configuration. Setting AllowUnstablecomponents to true in config.xml will * allow installing other components when there are errors in scripts * allow installing other components when there are missing dependencies * will mark the 'broken' components uninstallable in treeview Task-number: QTIFW-930 Change-Id: I8d28cf9c4b0401e0bb76795e87d581f39b64f128 Reviewed-by: Iikka Eklund --- .../installer/brokeninstaller/brokeninstaller.pro | 8 + .../auto/installer/brokeninstaller/components.qrc | 6 + .../brokeninstaller/data/broken_script.qs | 31 +++ .../installer/brokeninstaller/data/updates.xml | 163 +++++++++++++++ .../brokeninstaller/tst_brokeninstaller.cpp | 228 +++++++++++++++++++++ 5 files changed, 436 insertions(+) create mode 100644 tests/auto/installer/brokeninstaller/brokeninstaller.pro create mode 100644 tests/auto/installer/brokeninstaller/components.qrc create mode 100644 tests/auto/installer/brokeninstaller/data/broken_script.qs create mode 100644 tests/auto/installer/brokeninstaller/data/updates.xml create mode 100644 tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp (limited to 'tests') diff --git a/tests/auto/installer/brokeninstaller/brokeninstaller.pro b/tests/auto/installer/brokeninstaller/brokeninstaller.pro new file mode 100644 index 000000000..e48733ac6 --- /dev/null +++ b/tests/auto/installer/brokeninstaller/brokeninstaller.pro @@ -0,0 +1,8 @@ +include(../../qttest.pri) + +QT -= gui +QT += network xml qml + +SOURCES += tst_brokeninstaller.cpp + +RESOURCES += components.qrc diff --git a/tests/auto/installer/brokeninstaller/components.qrc b/tests/auto/installer/brokeninstaller/components.qrc new file mode 100644 index 000000000..1431393a6 --- /dev/null +++ b/tests/auto/installer/brokeninstaller/components.qrc @@ -0,0 +1,6 @@ + + + data/updates.xml + data/broken_script.qs + + diff --git a/tests/auto/installer/brokeninstaller/data/broken_script.qs b/tests/auto/installer/brokeninstaller/data/broken_script.qs new file mode 100644 index 000000000..a1574f46d --- /dev/null +++ b/tests/auto/installer/brokeninstaller/data/broken_script.qs @@ -0,0 +1,31 @@ +/************************************************************************** +** +** Copyright (C) 2018 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$ +** +**************************************************************************/ +function Component() +{ + installer.invalidScriptCall() +} diff --git a/tests/auto/installer/brokeninstaller/data/updates.xml b/tests/auto/installer/brokeninstaller/data/updates.xml new file mode 100644 index 000000000..a20275120 --- /dev/null +++ b/tests/auto/installer/brokeninstaller/data/updates.xml @@ -0,0 +1,163 @@ + + Your application + 1.2.3 + true + + componentinvalidscript + Invalid script component + Install this example. + 0.1.0-1 + 2010-09-21 + true + 1 + + + + + + + componentb + The second root component + Install this example. + 0.1.0-1 + 2010-09-21 + true + + 1 + + + + + + + componentc + The third root component + Install this example. + 0.1.0-1 + 2010-09-21 + true + + 1 + + + + + + + componentc.subnode + A subcomponent for the third root, dependency to component with invalid script + Install this example. + 0.1.0-1 + 2010-09-21 + true + + 1 + componentinvalidscript + + + + + + + componentc.subnode.sub + A subcomponent for the third roots subcomponent + Install this example. + 0.1.0-1 + 2010-09-21 + + true + + + + + + + componentmissingdependency + A component that has missing sha + Install this example. + 0.1.0-1 + 2010-09-21 + true + + + + + + + + componentd + Component that depends on component which is missing dependency + Install this example. + 0.1.0-1 + 2010-09-21 + + + + + + + + componentmissingcontent + A component which is missing 7z + Install this example. + 0.1.0-1 + 2010-09-21 + true + + 0 + content.7z + + + + + + + componentmissingcontent.sub + A subcomponent of component which is missing 7z + Install this example. + 0.1.0-1 + 2010-09-21 + true + true + + + + + + + + componentE + A component which is dependent on subcomponent of missing 7z component + Install this example. + 0.1.0-1 + 2010-09-21 + + true + true + componentmissingcontent.sub + + + + + + diff --git a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp new file mode 100644 index 000000000..95f4ac77d --- /dev/null +++ b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp @@ -0,0 +1,228 @@ +/************************************************************************** +** +** Copyright (C) 2018 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 "component.h" +#include "componentmodel.h" +#include "updatesinfo_p.h" +#include "packagemanagercore.h" +#include "settings.h" + +#include +#include +#include + +using namespace KDUpdater; +using namespace QInstaller; + +#define EXPECTED_COUNTS_COMPONENTS_VISIBLE 10 +#define EXPECTED_COUNT_ROOT_COMPONENTS 7 +#define EXPECTED_COUNT_INVALID_SCRIPT 7 +#define EXPECTED_COUNT_MISSING_DEPENDENCY 8 + +static const char componentInvalidScript[] = "componentinvalidscript"; +static const char componentB[] = "componentb"; + +static const char componentC[] = "componentc"; +static const char componentCSubnodeDependsOnInvalidScriptComponent[] = "componentc.subnode"; +static const char componentCSubnodeDependsOnInvalidScriptComponentSub[] = "componentc.subnode.sub"; + +static const char componentMissingDependency[] = "componentmissingdependency"; +static const char componentDependsOnMissingDependency[] = "componentd"; + +static const char componentMissingContent[] = "componentmissingcontent"; +static const char componentMissingContentSub[] = "componentmissingcontent.sub"; +static const char componentDependsOnMissingContentSub[] = "componentE"; + +static const QMap rootComponentDisplayNames = { + {"", QLatin1String("The root component")}, + {"ru_ru", QString::fromUtf8("Корневая компонента")}, + {"de_de", QString::fromUtf8("Wurzel Komponente")} +}; + +using namespace QInstaller; + +class tst_BrokenInstaller : public QObject +{ + Q_OBJECT + +public: + enum Option { + NoFlags = 0x00, + VirtualsVisible = 0x01, + NoForcedInstallation = 0x02 + }; + Q_DECLARE_FLAGS(Options, Option); + +private slots: + void initTestCase() + { + + m_checkedComponentsWithBrokenScript << componentB << componentMissingDependency << componentDependsOnMissingDependency << componentMissingContent + << componentMissingContentSub << componentDependsOnMissingContentSub; + m_uncheckedComponentsWithBrokenScript << componentInvalidScript << componentCSubnodeDependsOnInvalidScriptComponent + << componentCSubnodeDependsOnInvalidScriptComponentSub << componentC; + + m_checkedComponentsWithMissingDependency << componentB << componentMissingContent << componentMissingContentSub << componentDependsOnMissingContentSub + << componentInvalidScript << componentCSubnodeDependsOnInvalidScriptComponent + << componentCSubnodeDependsOnInvalidScriptComponentSub << componentC; + m_uncheckedComponentsWithMissingDependency << componentMissingDependency << componentDependsOnMissingDependency; + + } + + void testNameToIndexAndIndexToName() + { + PackageManagerCore core; + QList rootComponents = loadComponents(core); + + ComponentModel *model = new ComponentModel(1, &core); + model->setRootComponents(rootComponents); + // all names should be resolvable + QStringList all; + all << m_checkedComponentsWithBrokenScript << m_uncheckedComponentsWithBrokenScript << m_partiallyCheckedComponentsWithBrokenScript; + foreach (const QString &name, all) { + QVERIFY(model->indexFromComponentName(name).isValid()); + QVERIFY(model->componentFromIndex(model->indexFromComponentName(name)) != 0); + QCOMPARE(model->componentFromIndex(model->indexFromComponentName(name))->name(), name); + } + } + + void testInvalidScript() + { + PackageManagerCore core; + QList components = loadComponents(core); + + core.settings().setAllowUnstableComponents(true); + ComponentModel *model = new ComponentModel(1, &core); + Component *invalidScriptComponent = core.componentByName("componentinvalidscript"); + + // Using regexp to ignore the warning message as the message contains + // object address which we don't know + const QString debugMessage = QString("Exception while loading the component script"); + const QRegularExpression re(debugMessage); + QTest::ignoreMessage(QtWarningMsg, re); + invalidScriptComponent->loadComponentScript(":///data/broken_script.qs"); + + model->setRootComponents(components); + testModelState(model, m_checkedComponentsWithBrokenScript, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithBrokenScript); + } + + void testMissingDependency() + { + PackageManagerCore core; + QList components = loadComponents(core); + + core.settings().setAllowUnstableComponents(true); + ComponentModel *model = new ComponentModel(1, &core); + + Component *invalidComponent = core.componentByName("componentmissingdependency"); + invalidComponent->addDependency("missingcomponent"); + + Component *componentDependingOnMissingDependency = core.componentByName("componentd"); + componentDependingOnMissingDependency->addDependency("componentmissingdependency"); + + core.componentsToInstallNeedsRecalculation(); + model->setRootComponents(components); + + testModelState(model, m_checkedComponentsWithMissingDependency, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithMissingDependency); + } + +private: + + QList loadComponents(PackageManagerCore &core) + { + UpdatesInfo updatesInfo; + updatesInfo.setFileName(":///data/updates.xml"); + const QList updateInfos = updatesInfo.updatesInfo(); + + QList components; + UpdateInfo info; + for (int i = 0; i < updateInfos.count(); i++) { + info = updateInfos.at(i); + Component *component = new Component(&core); + + // we need at least these to be able to test the model + component->setValue("Name", info.data.value("Name").toString()); + 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("Dependencies", info.data.value("Dependencies").toString()); + component->setCheckState(Qt::Checked); + QString forced = info.data.value("ForcedInstallation", scFalse).toString().toLower(); + if (core.noForceInstallation()) + forced = scFalse; + component->setValue("ForcedInstallation", forced); + if (forced == scTrue) { + component->setEnabled(false); + component->setCheckable(false); + } + //If name does not contain dot it is root component + qDebug()<<"component name "<name(); + if (!component->name().contains('.')) { + core.appendRootComponent(component); + } else { //Contains dot, is previous components child component + components.at(i-1)->appendComponent(component); + } + components.append(component); + } + return components; + } + + void testModelState(ComponentModel *model, const QStringList &checked, const QStringList &partially, + const QStringList &unchecked) const + { + QCOMPARE(model->checked().count(), checked.count()); + QCOMPARE(model->partially().count(), partially.count()); + QCOMPARE(model->unchecked().count(), unchecked.count()); + + // these components should have checked state + foreach (Component *const component, model->checked()) + QVERIFY(checked.contains(component->name())); + + // these components should not have partially checked state + foreach (Component *const component, model->partially()) + QVERIFY(partially.contains(component->name())); + + // these components should not have checked state + foreach (Component *const component, model->unchecked()) + QVERIFY(unchecked.contains(component->name())); + } + +private: + QStringList m_checkedComponentsWithBrokenScript; + QStringList m_uncheckedComponentsWithBrokenScript; + QStringList m_partiallyCheckedComponentsWithBrokenScript; + + QStringList m_checkedComponentsWithMissingDependency; + QStringList m_uncheckedComponentsWithMissingDependency; + QStringList m_partiallyCheckedComponentsWithMissingDependency; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(tst_BrokenInstaller::Options) + +QTEST_MAIN(tst_BrokenInstaller) + +#include "tst_brokeninstaller.moc" -- cgit v1.2.3