diff options
Diffstat (limited to 'tests/auto')
36 files changed, 2085 insertions, 142 deletions
diff --git a/tests/auto/installer/binaryformat/binaryformat.pro b/tests/auto/installer/binaryformat/binaryformat.pro new file mode 100644 index 000000000..24a7899ce --- /dev/null +++ b/tests/auto/installer/binaryformat/binaryformat.pro @@ -0,0 +1,5 @@ +include(../../qttest.pri) + +QT -= gui + +SOURCES += tst_binaryformat.cpp diff --git a/tests/auto/installer/binaryformat/tst_binaryformat.cpp b/tests/auto/installer/binaryformat/tst_binaryformat.cpp new file mode 100644 index 000000000..59f0e8e03 --- /dev/null +++ b/tests/auto/installer/binaryformat/tst_binaryformat.cpp @@ -0,0 +1,115 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include <binaryformat.h> +#include <errors.h> +#include <fileutils.h> + +#include <QTest> +#include <QTemporaryFile> + +static const qint64 scTinySize = 72704LL; +static const qint64 scSmallSize = 524288LL; +static const qint64 scLargeSize = 2097152LL; + +class tst_BinaryFormat : public QObject +{ + Q_OBJECT + +private slots: + void findMagicCookieSmallFile() + { + QTemporaryFile file; + file.open(); + + try { + QInstaller::blockingWrite(&file, QByteArray(scSmallSize, '1')); + QInstaller::appendInt64(&file, QInstaller::MagicCookie); + + QCOMPARE(QInstaller::findMagicCookie(&file, QInstaller::MagicCookie), scSmallSize); + } catch (const QInstaller::Error &error) { + QFAIL(qPrintable(error.message())); + } catch (...) { + QFAIL("Unexpected error."); + } + } + + void findMagicCookieLargeFile() + { + QTemporaryFile file; + file.open(); + + try { + QInstaller::blockingWrite(&file, QByteArray(scLargeSize, '1')); + QInstaller::appendInt64(&file, QInstaller::MagicCookie); + QInstaller::blockingWrite(&file, QByteArray(scTinySize, '2')); + + QCOMPARE(QInstaller::findMagicCookie(&file, QInstaller::MagicCookie), scLargeSize); + } catch (const QInstaller::Error &error) { + QFAIL(qPrintable(error.message())); + } catch (...) { + QFAIL("Unexpected error."); + } + } + + void testFindMagicCookieWithError() + { + QTest::ignoreMessage(QtDebugMsg, "create Error-Exception: \"No marker found, stopped after 71.00 KiB.\" "); + + QTemporaryFile file; + file.open(); + + try { + QInstaller::blockingWrite(&file, QByteArray(scTinySize, '1')); + + // throws + QInstaller::findMagicCookie(&file, QInstaller::MagicCookie); + } catch (const QInstaller::Error &error) { + QCOMPARE(qPrintable(error.message()), "No marker found, stopped after 71.00 KiB."); + } catch (...) { + QFAIL("Unexpected error."); + } + } +}; + +QTEST_MAIN(tst_BinaryFormat) + +#include "tst_binaryformat.moc" diff --git a/tests/auto/installer/componentmodel/componentmodel.pro b/tests/auto/installer/componentmodel/componentmodel.pro new file mode 100644 index 000000000..7e18ff1ba --- /dev/null +++ b/tests/auto/installer/componentmodel/componentmodel.pro @@ -0,0 +1,8 @@ +include(../../qttest.pri) + +QT -= gui +QT += network xml script + +SOURCES += tst_componentmodel.cpp + +RESOURCES += components.qrc diff --git a/tests/auto/installer/componentmodel/components.qrc b/tests/auto/installer/componentmodel/components.qrc new file mode 100644 index 000000000..a2b530f13 --- /dev/null +++ b/tests/auto/installer/componentmodel/components.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>data/updates.xml</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/componentmodel/data/updates.xml b/tests/auto/installer/componentmodel/data/updates.xml new file mode 100644 index 000000000..e1f72de10 --- /dev/null +++ b/tests/auto/installer/componentmodel/data/updates.xml @@ -0,0 +1,132 @@ +<Updates> + <ApplicationName>Your application</ApplicationName> + <ApplicationVersion>1.2.3</ApplicationVersion> + <Checksum>true</Checksum> + <PackageUpdate> + <Name>com.vendor.product</Name> + <DisplayName>The root component</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>true</Default> + <Script>installscript.qs</Script> + <SortingPriority>1</SortingPriority> + <ForcedInstallation>true</ForcedInstallation> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product</Name> + <DisplayName>The second root component</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>false</Default> + <Script>installscript.qs</Script> + <SortingPriority>1</SortingPriority> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product.subnode</Name> + <DisplayName>A sub node component for the second root</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>false</Default> + <Script>installscript.qs</Script> + <SortingPriority>1</SortingPriority> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product.subnode.sub</Name> + <DisplayName>A subcomponent for the second sub node of the second root</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>false</Default> + <Script>installscript.qs</Script> + <SortingPriority>1</SortingPriority> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product.sub</Name> + <DisplayName>A subcomponent for the second root</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Script>installscript.qs</Script> + <Default>true</Default> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product.sub1</Name> + <DisplayName>A subcomponent for the second root</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>false</Default> + <Script>installscript.qs</Script> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.second.product.virtual</Name> + <DisplayName>A virtual subcomponent for the second root</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Script>installscript.qs</Script> + <Virtual>true</Virtual> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> + <PackageUpdate> + <Name>com.vendor.third.product.virtual</Name> + <DisplayName>A virtual root component</DisplayName> + <Description>Install this example.</Description> + <Version>0.1.0-1</Version> + <ReleaseDate>2010-09-21</ReleaseDate> + <Default>true</Default> + <Script>installscript.qs</Script> + <SortingPriority>0</SortingPriority> + <Virtual>true</Virtual> + <UpdateFile UncompressedSize="61" + CompressedSize="61"/> + <Licenses> + <License name="Beer Public License Agreement" + file="license.txt"/> + </Licenses> + </PackageUpdate> +</Updates> diff --git a/tests/auto/installer/componentmodel/tst_componentmodel.cpp b/tests/auto/installer/componentmodel/tst_componentmodel.cpp new file mode 100644 index 000000000..290f0d733 --- /dev/null +++ b/tests/auto/installer/componentmodel/tst_componentmodel.cpp @@ -0,0 +1,478 @@ +#include "component.h" +#include "componentmodel.h" + +#include "kdupdaterupdatesinfo_p.h" +#include "kdupdaterupdatesourcesinfo.h" + +#include "packagemanagercore.h" + +#include <QTest> + +using namespace KDUpdater; +using namespace QInstaller; + +#define EXPECTED_COUNT_VIRTUALS_VISIBLE 8 +#define EXPECTED_COUNT_VIRTUALS_INVISIBLE 7 + +static const char vendorProduct[] = "com.vendor.product"; +static const char vendorSecondProduct[] = "com.vendor.second.product"; +static const char vendorSecondProductSub[] = "com.vendor.second.product.sub"; +static const char vendorSecondProductSub1[] = "com.vendor.second.product.sub1"; +static const char vendorSecondProductVirtual[] = "com.vendor.second.product.virtual"; +static const char vendorSecondProductSubnode[] = "com.vendor.second.product.subnode"; +static const char vendorSecondProductSubnodeSub[] = "com.vendor.second.product.subnode.sub"; +static const char vendorThirdProductVirtual[] = "com.vendor.third.product.virtual"; + +class tst_ComponentModel : public QObject +{ + Q_OBJECT + +public: + enum Option { + NoFlags = 0x00, + VirtualsVisible = 0x01, + NoForcedInstallation = 0x02 + }; + Q_DECLARE_FLAGS(Options, Option); + +private slots: + void initTestCase() + { + m_defaultChecked << vendorProduct << vendorSecondProductSub; + m_defaultPartially << vendorSecondProduct; + m_defaultUnchecked << vendorSecondProductSub1 << vendorSecondProductSubnode + << vendorSecondProductSubnodeSub; + } + + void testNameToIndexAndIndexToName() + { + setPackageManagerOptions(NoFlags); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + + // all names should be resolvable, virtual components are not indexed if they are not visible + QStringList all; + all << m_defaultChecked << m_defaultPartially << m_defaultUnchecked; + 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); + } + + foreach (Component *const component, rootComponents) + delete component; + } + + void testNameToIndexAndIndexToNameVirtualsVisible() + { + setPackageManagerOptions(VirtualsVisible); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + + // all names should be resolvable, including virtual components + QStringList all; + all << m_defaultChecked << m_defaultPartially << m_defaultUnchecked << vendorSecondProductVirtual + << vendorThirdProductVirtual; + 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); + } + + foreach (Component *const component, rootComponents) + delete component; + } + + void testDefault() + { + setPackageManagerOptions(NoFlags); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + QCOMPARE(model.core(), &m_core); + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testVirtualsVisible() + { + setPackageManagerOptions(VirtualsVisible); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + // the virtual components are not checked + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testNoForcedInstallation() + { + setPackageManagerOptions(NoForcedInstallation); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testVirtualsVisibleNoForcedInstallation() + { + setPackageManagerOptions(Options(VirtualsVisible | NoForcedInstallation)); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + // the virtual components are not checked + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testSelect() + { + setPackageManagerOptions(NoFlags); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + // select all possible components + model.setCheckedState(ComponentModel::AllChecked); + QCOMPARE(model.checkedState(), ComponentModel::AllChecked); + testModelState(&model, m_defaultChecked + m_defaultPartially + m_defaultUnchecked, QStringList() + , QStringList()); + + // deselect all possible components + // as the first root is a forced install, should result in partially checked state + model.setCheckedState(ComponentModel::AllUnchecked); + QCOMPARE(model.checkedState(), ComponentModel::PartiallyChecked); + testModelState(&model, QStringList() << vendorProduct, QStringList(), m_defaultPartially + + m_defaultUnchecked + QStringList(vendorSecondProductSub)); + + // reset all possible components + model.setCheckedState(ComponentModel::DefaultChecked); + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testSelectVirtualsVisible() + { + setPackageManagerOptions(VirtualsVisible); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + // select all possible components + model.setCheckedState(ComponentModel::AllChecked); + QCOMPARE(model.checkedState(), ComponentModel::AllChecked); + testModelState(&model, m_defaultChecked + m_defaultPartially + m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual, QStringList(), + QStringList()); + + // deselect all possible components + // as the first root is a forced install, should result in partially checked state + model.setCheckedState(ComponentModel::AllUnchecked); + QCOMPARE(model.checkedState(), ComponentModel::PartiallyChecked); + testModelState(&model, QStringList() << vendorProduct, QStringList(), m_defaultPartially + + m_defaultUnchecked + QStringList(vendorSecondProductSub) << vendorSecondProductVirtual + << vendorThirdProductVirtual); + + // reset all possible components + model.setCheckedState(ComponentModel::DefaultChecked); + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testSelectNoForcedInstallation() + { + setPackageManagerOptions(NoForcedInstallation); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + // select all possible components + model.setCheckedState(ComponentModel::AllChecked); + QCOMPARE(model.checkedState(), ComponentModel::AllChecked); + testModelState(&model, m_defaultChecked + m_defaultPartially + m_defaultUnchecked, QStringList() + , QStringList()); + + // deselect all possible components + model.setCheckedState(ComponentModel::AllUnchecked); + QCOMPARE(model.checkedState(), ComponentModel::AllUnchecked); + testModelState(&model, QStringList(), QStringList(), m_defaultPartially + m_defaultUnchecked + + QStringList(vendorSecondProductSub) << vendorProduct); + + // reset all possible components + model.setCheckedState(ComponentModel::DefaultChecked); + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked); + + foreach (Component *const component, rootComponents) + delete component; + } + + void testSelectVirtualsVisibleNoForcedInstallation() + { + setPackageManagerOptions(Options(VirtualsVisible | NoForcedInstallation)); + + QList<Component*> rootComponents = loadComponents(); + testComponentsLoaded(rootComponents); + + // setup the model with 1 column + ComponentModel model(1, &m_core); + model.setRootComponents(rootComponents); + testDefaultInheritedModelBehavior(&model, 1); + + // select all possible components + model.setCheckedState(ComponentModel::AllChecked); + QCOMPARE(model.checkedState(), ComponentModel::AllChecked); + testModelState(&model, m_defaultChecked + m_defaultPartially + m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual, QStringList(), + QStringList()); + + // deselect all possible components + model.setCheckedState(ComponentModel::AllUnchecked); + QCOMPARE(model.checkedState(), ComponentModel::AllUnchecked); + testModelState(&model, QStringList(), QStringList(), m_defaultPartially + m_defaultUnchecked + + QStringList(vendorSecondProductSub) << vendorSecondProductVirtual << vendorProduct + << vendorThirdProductVirtual); + + // reset all possible components + model.setCheckedState(ComponentModel::DefaultChecked); + QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked); + testModelState(&model, m_defaultChecked, m_defaultPartially, m_defaultUnchecked + + QStringList(vendorSecondProductVirtual) << vendorThirdProductVirtual); + + foreach (Component *const component, rootComponents) + delete component; + } + +private: + void setPackageManagerOptions(Options flags) const + { + m_core.setNoForceInstallation(flags.testFlag(NoForcedInstallation)); + m_core.setVirtualComponentsVisible(flags.testFlag(VirtualsVisible)); + } + + void testComponentsLoaded(const QList<Component *> &rootComponents) const + { + // we need to have three root components + QCOMPARE(rootComponents.count(), 3); + + QList<Component*> components = rootComponents; + foreach (Component *const component, rootComponents) + components.append(component->childItems()); + + // will differ between 6 and 7 components, (2 root nodes, 1 sub node, 3 non virtual and 1 virtual) + QCOMPARE(components.count(), m_core.virtualComponentsVisible() ? EXPECTED_COUNT_VIRTUALS_VISIBLE + : EXPECTED_COUNT_VIRTUALS_INVISIBLE); + } + + void testDefaultInheritedModelBehavior(ComponentModel *model, int columnCount) const + { + // row count with invalid model index should return: + if (m_core.virtualComponentsVisible()) + QCOMPARE(model->rowCount(), 3); // 3 (2 non virtual and 1 virtual root component) + else + QCOMPARE(model->rowCount(), 2); // 2 (the 2 non virtual root components) + QCOMPARE(model->columnCount(), columnCount); + + const QModelIndex firstParent = model->indexFromComponentName(vendorProduct); + const QModelIndex secondParent = model->indexFromComponentName(vendorSecondProduct); + const QModelIndex thirdParent = model->indexFromComponentName(vendorThirdProductVirtual); + + // return invalid indexes, as they are the root components + QCOMPARE(model->parent(firstParent), QModelIndex()); + QCOMPARE(model->parent(secondParent), QModelIndex()); + QCOMPARE(model->parent(thirdParent), QModelIndex()); + + // test valid indexes + QVERIFY(firstParent.isValid()); + QVERIFY(secondParent.isValid()); + QVERIFY(model->indexFromComponentName(vendorSecondProductSub).isValid()); + QVERIFY(model->indexFromComponentName(vendorSecondProductSub1).isValid()); + QVERIFY(model->indexFromComponentName(vendorSecondProductSubnode).isValid()); + QVERIFY(model->indexFromComponentName(vendorSecondProductSubnodeSub).isValid()); + + // they should have the same parent + QCOMPARE(model->parent(model->indexFromComponentName(vendorSecondProductSub)), secondParent); + QCOMPARE(model->parent(model->indexFromComponentName(vendorSecondProductSub1)), secondParent); + QCOMPARE(model->parent(model->indexFromComponentName(vendorSecondProductSubnode)), secondParent); + + const QModelIndex forthParent = model->indexFromComponentName(vendorSecondProductSubnode); + QCOMPARE(model->parent(model->indexFromComponentName(vendorSecondProductSubnodeSub)), forthParent); + + // row count should be 0, as they have no children + QCOMPARE(model->rowCount(firstParent), 0); + QCOMPARE(model->rowCount(model->indexFromComponentName(vendorSecondProductSub)), 0); + QCOMPARE(model->rowCount(model->indexFromComponentName(vendorSecondProductSub1)), 0); + QCOMPARE(model->rowCount(model->indexFromComponentName(vendorSecondProductSubnodeSub)), 0); + + if (m_core.virtualComponentsVisible()) { + // test valid index + QVERIFY(thirdParent.isValid()); + QCOMPARE(model->rowCount(thirdParent), 0); + + QVERIFY(model->indexFromComponentName(vendorSecondProductVirtual).isValid()); + QCOMPARE(model->rowCount(model->indexFromComponentName(vendorSecondProductVirtual)), 0); + QCOMPARE(model->parent(model->indexFromComponentName(vendorSecondProductVirtual)), secondParent); + // row count should be 4, (2 standard, 1 virtual, 1 sub node) + QCOMPARE(model->rowCount(secondParent), 4); + } else { + // test invalid index + QVERIFY(!thirdParent.isValid()); + + // row count should be 3, (2 standard, 1 sub node, omit the virtual) + QCOMPARE(model->rowCount(secondParent), 3); + } + // row count should be 1, 1 sub node + QCOMPARE(model->rowCount(model->indexFromComponentName(vendorSecondProductSubnode)), 1); + } + + 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())); + } + + QList<Component*> loadComponents() const + { + UpdatesInfo updatesInfo; + updatesInfo.setFileName(":///data/updates.xml"); + const QList<UpdateInfo> updateInfos = updatesInfo.updatesInfo(); + + QHash<QString, Component*> components; + foreach (const UpdateInfo &info, updateInfos) { + Component *component = new Component(const_cast<PackageManagerCore *>(&m_core)); + + // we need at least these to be able to test the model + component->setValue("Name", info.data.value("Name").toString()); + component->setValue("Default", info.data.value("Default").toString()); + component->setValue("Virtual", info.data.value("Virtual").toString()); + component->setValue("DisplayName", info.data.value("DisplayName").toString()); + + QString forced = info.data.value("ForcedInstallation", scFalse).toString().toLower(); + if (m_core.noForceInstallation()) + forced = scFalse; + component->setValue("ForcedInstallation", forced); + if (forced == scTrue) { + component->setEnabled(false); + component->setCheckable(false); + component->setCheckState(Qt::Checked); + } + components.insert(component->name(), component); + } + + QList <Component*> rootComponents; + foreach (QString id, components.keys()) { + QInstaller::Component *component = components.value(id); + while (!id.isEmpty() && component->parentComponent() == 0) { + id = id.section(QLatin1Char('.'), 0, -2); + if (components.contains(id)) + components[id]->appendComponent(component); + } + } + + foreach (QInstaller::Component *component, components) { + if (component->parentComponent() == 0) + rootComponents.append(component); + + if (component->isCheckable() && component->isDefault() && (!component->isTristate())) + component->setCheckState(Qt::Checked); + } + return rootComponents; + } + +private: + PackageManagerCore m_core; + + QStringList m_defaultChecked; + QStringList m_defaultPartially; + QStringList m_defaultUnchecked; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(tst_ComponentModel::Options) + +QTEST_MAIN(tst_ComponentModel) + +#include "tst_componentmodel.moc" diff --git a/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro b/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro new file mode 100644 index 000000000..0cc9e705c --- /dev/null +++ b/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro @@ -0,0 +1,8 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +SOURCES = tst_consumeoutputoperationtest.cpp + +DEFINES += "QMAKE_BINARY=$$QMAKE_BINARY" diff --git a/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp b/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp new file mode 100644 index 000000000..227820ed1 --- /dev/null +++ b/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp @@ -0,0 +1,183 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#include <init.h> +#include <packagemanagercore.h> +#include <consumeoutputoperation.h> +#include <qinstallerglobal.h> +#include <fileutils.h> +#include <qtpatchoperation.h> +#include <errors.h> + +#include <QObject> +#include <QTest> +#include <QProcess> +#include <QDir> +#include <QEventLoop> +#include <QDebug> + +#define QUOTE_(x) #x +#define QUOTE(x) QUOTE_(x) + +using namespace KDUpdater; +using namespace QInstaller; + +class tst_consumeoutputoperationtest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { +#if defined(Q_OS_WIN) + m_binSuffix = ".exe"; +#endif + // be aware that this would enable eating the qDebug output + //QInstaller::init(); + // if we don't use the init method we need to register the in QtPatchOperation used + // patch_file_lists manually +#if defined(QT_STATIC) + Q_INIT_RESOURCE(patch_file_lists); +#endif + + m_fakeQtPath = QDir::toNativeSeparators(qApp->applicationDirPath()) + QDir::separator() + + "fakeQt" + QDir::separator(); + QVERIFY(QDir().mkpath(m_fakeQtPath + "bin")); + + QFile orgQmake(QUOTE(QMAKE_BINARY)); + // use lrelease filename which will be patched by the QtPatch operation, but it hides that this + // fake Qt contains a qmake which would be used to get the patch pathes (instead of using the qmake + // output we want to use our installer value) + m_binaryInFakeQt = m_fakeQtPath + "bin" + QDir::separator() + "lrelease" + m_binSuffix; + + QVERIFY2(orgQmake.copy(m_binaryInFakeQt), qPrintable(orgQmake.errorString())); + } + + void testMissingArguments() + { + ConsumeOutputOperation operation; + + QVERIFY(operation.testOperation()); + QVERIFY(!operation.performOperation()); + // undo does nothing so this should be true + + QVERIFY(operation.undoOperation()); + + QCOMPARE(UpdateOperation::Error(operation.error()), UpdateOperation::InvalidArguments); + //qDebug() << operation.errorString(); + QString compareString("Invalid arguments in ConsumeOutput: 0 arguments given, at least 2 " + "expected(<to be saved installer key name>, <executable>, [argument1], [argument2], ...)."); + //qDebug() << compareString; + QCOMPARE(operation.errorString(), compareString); + } + + void testGetOutputFromQmake() + { + QString testOutput = getOutputFrom(QUOTE(QMAKE_BINARY), QStringList("-query")); + + ConsumeOutputOperation operation; + operation.setValue(QLatin1String("installer"), QVariant::fromValue(&m_core)); + + operation.setArguments(QStringList() << "testConsumeOutputKey" << QUOTE(QMAKE_BINARY) << "-query"); + QVERIFY2(operation.performOperation(), qPrintable(operation.errorString())); + QCOMPARE(Operation::Error(operation.error()), Operation::NoError); + + QCOMPARE(m_core.value("testConsumeOutputKey"), testOutput); + } + + void testPatchFakeQt() + { + return; +#if defined(Q_OS_WIN) + QString patchType = "windows"; +#elif defined(Q_OS_MAC) + QString patchType = "mac"; +#else + QString patchType = "linux"; +#endif + + QtPatchOperation patchOperation; + patchOperation.setValue(QLatin1String("installer"), QVariant::fromValue(&m_core)); + + // testConsumeOutputKey comes from testGetOutputFromQmake() before and it can not use qmake, + // because it does not exist in the m_fakeQtPath + patchOperation.setArguments(QStringList() << "QmakeOutputInstallerKey=testConsumeOutputKey" + << patchType << m_fakeQtPath); + QVERIFY2(patchOperation.performOperation(), qPrintable(patchOperation.errorString())); + + QString patchedBinaryOutput = getOutputFrom(m_binaryInFakeQt, QStringList("-query")); + QVERIFY(getOutputFrom(QUOTE(QMAKE_BINARY), QStringList("-query")) != patchedBinaryOutput); + QVERIFY(patchedBinaryOutput.contains(m_fakeQtPath)); + } + + void cleanupTestCase() + { + try { + removeDirectory(m_fakeQtPath); + } catch (const QInstaller::Error &error) { + QFAIL(qPrintable(error.message())); + } + } + +private: + QString getOutputFrom(const QString &binary, const QStringList &arguments = QStringList()) + { + QEventLoop loop; + QProcess process; + + QObject::connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit())); + process.start(binary, arguments, QIODevice::ReadOnly); + + if (process.state() != QProcess::NotRunning) + loop.exec(); + + return process.readAllStandardOutput(); + } + + + PackageManagerCore m_core; + QString m_fakeQtPath; + QString m_binaryInFakeQt; + QString m_binSuffix; +}; + +QTEST_MAIN(tst_consumeoutputoperationtest) + +#include "tst_consumeoutputoperationtest.moc" diff --git a/tests/auto/installer/copyoperationtest/copyoperationtest.pro b/tests/auto/installer/copyoperationtest/copyoperationtest.pro new file mode 100644 index 000000000..ce4ad42ec --- /dev/null +++ b/tests/auto/installer/copyoperationtest/copyoperationtest.pro @@ -0,0 +1,6 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +SOURCES = tst_copyoperationtest.cpp diff --git a/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp new file mode 100644 index 000000000..61d24a2ad --- /dev/null +++ b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp @@ -0,0 +1,168 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "init.h" +#include "kdupdaterupdateoperations.h" +#include "utils.h" + +#include <QDir> +#include <QObject> +#include <QTest> +#include <QFile> +#include <QDebug> + +using namespace KDUpdater; +using namespace QInstaller; + +class tst_copyoperationtest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + //QInstaller::init(); + m_testDestinationPath = qApp->applicationDirPath() + QDir::toNativeSeparators("/test"); + m_testDestinationFilePath = QDir(m_testDestinationPath).absoluteFilePath(QFileInfo( + qApp->applicationFilePath()).fileName()); + if (QDir(m_testDestinationPath).exists()) { + QFAIL("Remove test folder first!"); + } + } + + void testMissingArguments() + { + CopyOperation op; + + QVERIFY(op.testOperation()); + QVERIFY(!op.performOperation()); + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); + QCOMPARE(op.errorString(), QString("Invalid arguments: 0 arguments given, 2 expected.")); + + } + + 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(); + } + + void testCopySomething() + { + QFETCH(QString, source); + QFETCH(QString, destination); + + QVERIFY2(QFileInfo(source).exists(), QString("Source '%1' does not exist.").arg(source).toLatin1()); + CopyOperation op; + op.setArguments(QStringList() << source << destination); + op.backup(); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + + QVERIFY2(QFileInfo(m_testDestinationFilePath).exists(), 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()); + } + + void testCopyIfDestinationExist_data() + { + testCopySomething_data(); + } + + void testCopyIfDestinationExist() + { + QFETCH(QString, source); + QFETCH(QString, destination); + + QByteArray testString("This file is generated by QTest\n"); + QFile testFile(m_testDestinationFilePath); + testFile.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&testFile); + out << testString; + testFile.close(); + + QByteArray testFileHash = QInstaller::calculateHash(m_testDestinationFilePath, QCryptographicHash::Sha1); + + QVERIFY2(QFileInfo(source).exists(), QString("Source '%1' does not exist.").arg(source).toLatin1()); + CopyOperation op; + op.setArguments(QStringList() << source << destination); + op.backup(); + QVERIFY2(!op.value("backupOfExistingDestination").toString().isEmpty(), "The CopyOperation didn't saved any backup."); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + + // checking that perform did something + QByteArray currentFileHash = QInstaller::calculateHash(m_testDestinationFilePath, QCryptographicHash::Sha1); + QVERIFY(testFileHash != currentFileHash); + + QVERIFY2(QFileInfo(m_testDestinationFilePath).exists(), QString("Copying from '%1' to '%2' was " + "not working: '%3' does not exist").arg(source, destination, m_testDestinationFilePath).toLatin1()); + + // undo should replace the new one with the old backuped one + QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); + currentFileHash = QInstaller::calculateHash(m_testDestinationFilePath, QCryptographicHash::Sha1); + QVERIFY(testFileHash == currentFileHash); + } + void init() + { + QVERIFY2(!QFileInfo(m_testDestinationFilePath).exists(), QString("Destination '%1' should not exist " + "to test the copy operation.").arg(m_testDestinationFilePath).toLatin1()); + QDir().mkpath(m_testDestinationPath); + } + + void cleanup() + { + QFile(m_testDestinationFilePath).remove(); + QDir().rmpath(m_testDestinationPath); + } +private: + QString m_testDestinationPath; + QString m_testDestinationFilePath; +}; + +QTEST_MAIN(tst_copyoperationtest) + +#include "tst_copyoperationtest.moc" diff --git a/tests/auto/installer/extractarchiveoperationtest/data.qrc b/tests/auto/installer/extractarchiveoperationtest/data.qrc new file mode 100644 index 000000000..d6453a9b3 --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>data/valid.7z</file> + <file>data/invalid.7z</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/extractarchiveoperationtest/data/invalid.7z b/tests/auto/installer/extractarchiveoperationtest/data/invalid.7z Binary files differnew file mode 100644 index 000000000..bcf81250e --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/invalid.7z diff --git a/tests/auto/installer/extractarchiveoperationtest/data/valid.7z b/tests/auto/installer/extractarchiveoperationtest/data/valid.7z Binary files differnew file mode 100644 index 000000000..e583bdf99 --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/data/valid.7z diff --git a/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro b/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro new file mode 100644 index 000000000..fb53c9a8a --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro @@ -0,0 +1,7 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +RESOURCES += data.qrc +SOURCES = tst_extractarchiveoperationtest.cpp diff --git a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp new file mode 100644 index 000000000..eb3b0378e --- /dev/null +++ b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp @@ -0,0 +1,101 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "init.h" +#include "extractarchiveoperation.h" + +#include <QDir> +#include <QObject> +#include <QTest> + +using namespace KDUpdater; +using namespace QInstaller; + +class tst_extractarchiveoperationtest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + QInstaller::init(); + } + + void testMissingArguments() + { + ExtractArchiveOperation op; + + QVERIFY(op.testOperation()); + QVERIFY(!op.performOperation()); + //QVERIFY(!op.undoOperation()); Can't test for failure as we run into Q_ASSERT + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments); + QCOMPARE(op.errorString(), QString("Invalid arguments in Extract: 0 arguments given, exactly 2 expected.")); + + } + + void testExtractOperationValidFile() + { + ExtractArchiveOperation op; + op.setArguments(QStringList() << ":///data/valid.7z" << QDir::tempPath()); + + QVERIFY(op.testOperation()); + QVERIFY(op.performOperation()); + QVERIFY(op.undoOperation()); + } + + void testExtractOperationInvalidFile() + { + ExtractArchiveOperation op; + op.setArguments(QStringList() << ":///data/invalid.7z" << QDir::tempPath()); + + QVERIFY(op.testOperation()); + QVERIFY(!op.performOperation()); + QVERIFY(op.undoOperation()); + + QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError); + QCOMPARE(op.errorString(), QString("Error while extracting ':///data/invalid.7z': Could not open archive")); + } +}; + +QTEST_MAIN(tst_extractarchiveoperationtest) + +#include "tst_extractarchiveoperationtest.moc" diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro index e903b806a..414c952d7 100644 --- a/tests/auto/installer/installer.pro +++ b/tests/auto/installer/installer.pro @@ -3,5 +3,15 @@ TEMPLATE = subdirs SUBDIRS += \ settings \ repository \ + componentmodel \ fakestopprocessforupdateoperation \ - mkdiroperationtest + messageboxhandler \ + extractarchiveoperationtest \ + lib7zfacade \ + scriptengine \ + consumeoutputoperationtest \ + mkdiroperationtest \ + copyoperationtest \ + solver \ + binaryformat + diff --git a/tests/auto/installer/lib7zfacade/data.qrc b/tests/auto/installer/lib7zfacade/data.qrc new file mode 100644 index 000000000..d6453a9b3 --- /dev/null +++ b/tests/auto/installer/lib7zfacade/data.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>data/valid.7z</file> + <file>data/invalid.7z</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/lib7zfacade/data/invalid.7z b/tests/auto/installer/lib7zfacade/data/invalid.7z Binary files differnew file mode 100644 index 000000000..bcf81250e --- /dev/null +++ b/tests/auto/installer/lib7zfacade/data/invalid.7z diff --git a/tests/auto/installer/lib7zfacade/data/valid.7z b/tests/auto/installer/lib7zfacade/data/valid.7z Binary files differnew file mode 100644 index 000000000..e583bdf99 --- /dev/null +++ b/tests/auto/installer/lib7zfacade/data/valid.7z diff --git a/tests/auto/installer/lib7zfacade/lib7zfacade.pro b/tests/auto/installer/lib7zfacade/lib7zfacade.pro new file mode 100644 index 000000000..034cf1eed --- /dev/null +++ b/tests/auto/installer/lib7zfacade/lib7zfacade.pro @@ -0,0 +1,7 @@ +include(../../qttest.pri) + +QT -= gui +QT += testlib + +RESOURCES += data.qrc +SOURCES = tst_lib7zfacade.cpp diff --git a/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp b/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp new file mode 100644 index 000000000..bae42fed9 --- /dev/null +++ b/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp @@ -0,0 +1,184 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "init.h" +#include "lib7z_facade.h" + +#include <QDir> +#include <QObject> +#include <QTemporaryFile> +#include <QTest> + +class tst_lib7zfacade : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + QInstaller::init(); + + m_file.path = "valid"; + m_file.permissions = 0; + m_file.compressedSize = 836; + m_file.uncompressedSize = 5242880; + m_file.isDirectory = false; + m_file.archiveIndex = QPoint(0, 0); + m_file.mtime = QDateTime(QDate::fromJulianDay(2456413), QTime(12, 50, 42)); + } + + void testIsSupportedArchive() + { + QCOMPARE(Lib7z::isSupportedArchive(":///data/valid.7z"), true); + QCOMPARE(Lib7z::isSupportedArchive(":///data/invalid.7z"), false); + + { + QFile file(":///data/valid.7z"); + QVERIFY(file.open(QIODevice::ReadOnly)); + QCOMPARE(Lib7z::isSupportedArchive(&file), true); + } + + { + QFile file(":///data/invalid.7z"); + QVERIFY(file.open(QIODevice::ReadOnly)); + QCOMPARE(Lib7z::isSupportedArchive(&file), false); + } + } + + void testListArchive() + { + // TODO: this should work without scope, there's a bug in Lib7z::OpenArchiveInfo + // caused by the fact that we keep a pointer to the device, not the devices target + { + QFile file(":///data/valid.7z"); + QVERIFY(file.open(QIODevice::ReadOnly)); + + QVector<Lib7z::File> files = Lib7z::listArchive(&file); + QCOMPARE(files.count(), 1); +#ifdef Q_OS_UNIX + QSKIP("This test requires the tme handling to be repaired first.", SkipSingle); +#endif + QCOMPARE(files.first(), m_file); + } + + { + try { + QFile file(":///data/invalid.7z"); + QVERIFY(file.open(QIODevice::ReadOnly)); + QVector<Lib7z::File> files = Lib7z::listArchive(&file); + } catch (const Lib7z::SevenZipException& e) { + QCOMPARE(e.message(), QString("Could not open archive")); + } catch (...) { + QFAIL("Unexpected error during list archive!"); + } + } + } + + void testCreateArchive() + { + QTemporaryFile target; + QVERIFY(target.open()); + + try { + // TODO: we do not get any information about success + Lib7z::createArchive(&target, QStringList() << ":///data/invalid.7z"); + } catch (const Lib7z::SevenZipException& e) { + QFAIL(e.message().toUtf8()); + } catch (...) { + QFAIL("Unexpected error during create archive!"); + } + } + + void testExtractArchive() + { + QFile source(":///data/valid.7z"); + QVERIFY(source.open(QIODevice::ReadOnly)); + + try { + // TODO: we do not get any information about success + Lib7z::extractArchive(&source, QDir::tempPath()); + } catch (const Lib7z::SevenZipException& e) { + QFAIL(e.message().toUtf8()); + } catch (...) { + QFAIL("Unexpected error during extract archive!"); + } + } + + void testExtractFileFromArchive() + { + QFile source(":///data/valid.7z"); + QVERIFY(source.open(QIODevice::ReadOnly)); + + QTemporaryFile target; + QVERIFY(target.open()); + + try { + // TODO: we do not get any information about success + Lib7z::extractFileFromArchive(&source, m_file, &target); + } catch (const Lib7z::SevenZipException& e) { + QFAIL(e.message().toUtf8()); + } catch (...) { + QFAIL("Unexpected error during extract file from archive!"); + } + } + + void testExtractFileFromArchive2() + { + QFile source(":///data/valid.7z"); + QVERIFY(source.open(QIODevice::ReadOnly)); + + try { + // TODO: we do not get any information about success + Lib7z::extractFileFromArchive(&source, m_file, QDir::tempPath()); + } catch (const Lib7z::SevenZipException& e) { + QFAIL(e.message().toUtf8()); + } catch (...) { + QFAIL("Unexpected error during extract file from archive!"); + } + } + +private: + Lib7z::File m_file; +}; + +QTEST_MAIN(tst_lib7zfacade) + +#include "tst_lib7zfacade.moc" diff --git a/tests/auto/installer/messageboxhandler/messageboxhandler.pro b/tests/auto/installer/messageboxhandler/messageboxhandler.pro new file mode 100644 index 000000000..c0c1364d8 --- /dev/null +++ b/tests/auto/installer/messageboxhandler/messageboxhandler.pro @@ -0,0 +1,6 @@ +include(../../qttest.pri) + +QT += script +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +SOURCES += tst_messageboxhandler.cpp diff --git a/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp new file mode 100644 index 000000000..604b8e0a0 --- /dev/null +++ b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp @@ -0,0 +1,119 @@ +#include <messageboxhandler.h> +#include <qinstallerglobal.h> +#include <scriptengine.h> +#include <packagemanagercore.h> + +#include <QTest> +#include <QMetaEnum> +#include <QScriptEngine> +#include <QDebug> + +#include <stdlib.h> /* srand, rand */ +#include <time.h> /* time */ + +using namespace QInstaller; + +namespace QTest { + template<> + char *toString(const QMessageBox::StandardButton &button) + { + QString buttonAsString(QString::number(button)); + return qstrdup(buttonAsString.toLatin1().data()); + } +} + +class tst_MessageBoxHandler : public QObject +{ + Q_OBJECT +public: +private slots: + void initTestCase() + { + m_maxStandardButtons = 0; + + const QMetaObject &messageBoxMetaObject = QMessageBox::staticMetaObject; + int index = messageBoxMetaObject.indexOfEnumerator("StandardButtons"); + + QMetaEnum metaEnum = messageBoxMetaObject.enumerator(index); + for (int i = 0; i < metaEnum.keyCount(); i++) { + int enumValue = metaEnum.value(i); + if (enumValue < QMessageBox::FirstButton) + continue; + m_standardButtonValueMap.insert(static_cast<QMessageBox::StandardButton>(enumValue), + metaEnum.valueToKey(metaEnum.value(i))); + m_maxStandardButtons += enumValue; + if (enumValue == QMessageBox::LastButton) + break; + } + } + + void testScriptButtonValues() + { + PackageManagerCore core; + ScriptEngine scriptEngine(&core); + QMapIterator<QMessageBox::StandardButton, QString> i(m_standardButtonValueMap); + while (i.hasNext()) { + i.next(); + QString scriptString = QString::fromLatin1("QMessageBox.%1").arg(i.value()); + QScriptValue scriptValue(scriptEngine.evaluate(scriptString)); + + QVERIFY2(!scriptValue.isUndefined(), qPrintable( + QString::fromLatin1("It seems that %1 is undefined.").arg(scriptString))); + + qint32 evaluatedValue = scriptValue.toInt32(); + QVERIFY2(!scriptEngine.hasUncaughtException(), qPrintable( + QInstaller::uncaughtExceptionString(&scriptEngine))); + + QCOMPARE(static_cast<QMessageBox::StandardButton>(evaluatedValue), i.key()); + } + } + + void testDefaultAction() + { + int standardButtons = QMessageBox::NoButton; + QList<QMessageBox::Button> orderedButtons = MessageBoxHandler::orderedButtons(); + MessageBoxHandler *messageBoxHandler = MessageBoxHandler::instance(); + + messageBoxHandler->setDefaultAction(MessageBoxHandler::Reject); + QString testidentifier(QLatin1String("TestError")); + QString testTitle(QLatin1String("A test error")); + QString testMessage(QLatin1String("This is a test error message.")); + + const char *ignoreMessage("\"created critical message box TestError: 'A test error', This is a test error message.\" "); + /* initialize random seed: */ + srand(time(0)); + do { + standardButtons += QMessageBox::FirstButton; + + /* generate secret number between 1 and 10: */ + int iSecret = rand() % 10 + 1; + // use only every 5th run to reduce the time which it takes to run this test + if (iSecret > 2) + continue; + QTest::ignoreMessage(QtDebugMsg, ignoreMessage); + const QMessageBox::StandardButton returnButton = static_cast<QMessageBox::StandardButton>( + messageBoxHandler->critical(testidentifier, testTitle, testMessage, + static_cast<QMessageBox::StandardButton>(standardButtons))); + + QMessageBox::StandardButton wantedButton = QMessageBox::NoButton; + // find the last button which is the wanted reject button in the current + // standardButtons combination + foreach (QMessageBox::StandardButton button, orderedButtons) { + if (standardButtons & button) + wantedButton = button; + } + + QVERIFY2(wantedButton != QMessageBox::NoButton, "Could not find a wantedButton."); + QCOMPARE(returnButton, wantedButton); + + } while (standardButtons < m_maxStandardButtons); + } + +private: + QMap<QMessageBox::StandardButton, QString> m_standardButtonValueMap; + int m_maxStandardButtons; +}; + +QTEST_MAIN(tst_MessageBoxHandler) + +#include "tst_messageboxhandler.moc" diff --git a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp index fd427400d..8eef8d2b2 100644 --- a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp +++ b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp @@ -90,14 +90,14 @@ private slots: QFETCH(QString, directory); QString path = QDir::current().path() + QDir::toNativeSeparators(directory); - QVERIFY2(!QDir(path).exists(), path.toAscii()); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); MkdirOperation op; op.setArguments(QStringList() << path); op.backup(); - QVERIFY2(op.performOperation(), op.errorString().toAscii()); - QVERIFY2(QDir(path).exists(), path.toAscii()); - QVERIFY2(op.undoOperation(), op.errorString().toAscii()); - QVERIFY2(!QDir(path).exists(), path.toAscii()); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(QDir(path).exists(), path.toLatin1()); + QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); } void testCreateDirectory_customFile_data() @@ -116,23 +116,23 @@ private slots: QString path = QDir::current().path() + QDir::toNativeSeparators(directory); QString filepath = QDir::current().path() + QDir::toNativeSeparators(filename); - QVERIFY2(!QDir(path).exists(), path.toAscii()); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); MkdirOperation op; op.setArguments(QStringList() << path); op.backup(); - QVERIFY2(op.performOperation(), op.errorString().toAscii()); - QVERIFY2(QDir(path).exists(), path.toAscii()); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(QDir(path).exists(), path.toLatin1()); QFile file(filepath); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out << "This file is generated by QTest\n"; file.close(); - QVERIFY2(!op.undoOperation(), op.errorString().toAscii()); - QVERIFY2(file.exists(), filepath.toAscii()); + QVERIFY2(!op.undoOperation(), op.errorString().toLatin1()); + QVERIFY2(file.exists(), filepath.toLatin1()); QVERIFY2(QDir(filepath).remove(filepath), "Could not remove file"); - QVERIFY2(!file.exists(), filepath.toAscii()); - QVERIFY2(op.undoOperation(), op.errorString().toAscii()); - QVERIFY2(!QDir(path).exists(), path.toAscii()); + QVERIFY2(!file.exists(), filepath.toLatin1()); + QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); } void testCreateDirectory_customFile_force_data() @@ -147,20 +147,20 @@ private slots: QString path = QDir::current().path() + QDir::toNativeSeparators(directory); QString filepath = QDir::current().path() + QDir::toNativeSeparators(filename); - QVERIFY2(!QDir(path).exists(), path.toAscii()); + QVERIFY2(!QDir(path).exists(), path.toLatin1()); MkdirOperation op; op.setArguments(QStringList() << path); op.setValue("forceremoval",true); op.backup(); - QVERIFY2(op.performOperation(), op.errorString().toAscii()); - QVERIFY2(QDir(path).exists(), path.toAscii()); + QVERIFY2(op.performOperation(), op.errorString().toLatin1()); + QVERIFY2(QDir(path).exists(), path.toLatin1()); QFile file(filepath); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out << "This file is generated by QTest\n"; file.close(); - QVERIFY2(op.undoOperation(), op.errorString().toAscii()); - QVERIFY2(!file.exists(), path.toAscii()); + QVERIFY2(op.undoOperation(), op.errorString().toLatin1()); + QVERIFY2(!file.exists(), path.toLatin1()); } }; diff --git a/tests/auto/installer/scriptengine/data/auto-install.qs b/tests/auto/installer/scriptengine/data/auto-install.qs new file mode 100644 index 000000000..26937fc05 --- /dev/null +++ b/tests/auto/installer/scriptengine/data/auto-install.qs @@ -0,0 +1,16 @@ +function Controller() +{ + installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes); + installer.setValue("GuiTestValue", "hello"); +} + +Controller.prototype.ComponentSelectionPageCallback = function() +{ + var notExistingButtonId = 9999999; + gui.clickButton(notExistingButtonId); +} + +Controller.prototype.FinishedPageCallback = function() +{ + print("FinishedPageCallback - OK") +} diff --git a/tests/auto/installer/scriptengine/data/broken_connect.qs b/tests/auto/installer/scriptengine/data/broken_connect.qs new file mode 100644 index 000000000..2fe873b63 --- /dev/null +++ b/tests/auto/installer/scriptengine/data/broken_connect.qs @@ -0,0 +1,11 @@ +function BrokenConnect() +{ + emiter.emitted.connect(receive) +} + +function receive() +{ + print("function receive()"); + // this should throw an exception, "foo" does not exist + foo.bar = "test"; +} diff --git a/tests/auto/installer/scriptengine/data/component1.qs b/tests/auto/installer/scriptengine/data/component1.qs new file mode 100644 index 000000000..af81f5747 --- /dev/null +++ b/tests/auto/installer/scriptengine/data/component1.qs @@ -0,0 +1,48 @@ +function Component() +{ + print("Component constructor - OK"); +} + +Component.prototype.retranslateUi = function() +{ + // arguments.callee to get the current function name doesn't work in that case + print("retranslateUi - OK"); + // no default implementation for this method + // component.languageChanged(); +} + +Component.prototype.createOperationsForPath = function(path) +{ + print("createOperationsForPath - OK"); + component.createOperationsForPath(path); +} + +Component.prototype.createOperationsForArchive = function(archive) +{ + print("createOperationsForArchive - OK"); + component.createOperationsForArchive(archive); +} + +Component.prototype.beginInstallation = function() +{ + print("beginInstallation - OK"); + component.beginInstallation(); +} + +Component.prototype.createOperations = function() +{ + print("createOperations - OK"); + component.createOperations(); +} + +Component.prototype.isAutoDependOn = function() +{ + print("isAutoDependOn - OK"); + return false; +} + +Component.prototype.isDefault = function() +{ + print("isDefault - OK"); + return false; +} diff --git a/tests/auto/installer/scriptengine/data/component2.qs b/tests/auto/installer/scriptengine/data/component2.qs new file mode 100644 index 000000000..b27e45c83 --- /dev/null +++ b/tests/auto/installer/scriptengine/data/component2.qs @@ -0,0 +1,6 @@ +function Component() +{ + print("script function: " + arguments.callee.name); + // adding some broken javascript code here + broken + 789634 +} diff --git a/tests/auto/installer/scriptengine/scriptengine.pro b/tests/auto/installer/scriptengine/scriptengine.pro new file mode 100644 index 000000000..a7b2bd157 --- /dev/null +++ b/tests/auto/installer/scriptengine/scriptengine.pro @@ -0,0 +1,11 @@ +include(../../qttest.pri) + +QT += script +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets +} + +SOURCES += tst_scriptengine.cpp + +RESOURCES += \ + scriptengine.qrc diff --git a/tests/auto/installer/scriptengine/scriptengine.qrc b/tests/auto/installer/scriptengine/scriptengine.qrc new file mode 100644 index 000000000..0bf683852 --- /dev/null +++ b/tests/auto/installer/scriptengine/scriptengine.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>data/auto-install.qs</file> + <file>data/component1.qs</file> + <file>data/component2.qs</file> + <file>data/broken_connect.qs</file> + </qresource> +</RCC> diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp new file mode 100644 index 000000000..5c67afd0c --- /dev/null +++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp @@ -0,0 +1,253 @@ +#include <component.h> +#include <errors.h> +#include <packagemanagercore.h> +#include <packagemanagergui.h> +#include <scriptengine.h> + +#include <QTest> +#include <QSet> +#include <QFile> +#include <QString> + +using namespace QInstaller; + +class TestGui : public QInstaller::PackageManagerGui +{ + Q_OBJECT + +public: + explicit TestGui(QInstaller::PackageManagerCore *core) + : PackageManagerGui(core, 0) + { + setPage(PackageManagerCore::Introduction, new IntroductionPage(core)); + setPage(PackageManagerCore::ComponentSelection, new ComponentSelectionPage(core)); + setPage(PackageManagerCore::InstallationFinished, new FinishedPage(core)); + } + + virtual void init() {} + + void callProtectedDelayedExecuteControlScript(int id) + { + executeControlScript(id); + } +}; + +class EmitSignalObject : public QObject +{ + Q_OBJECT + +public: + EmitSignalObject() {} + ~EmitSignalObject() {} + void produceSignal() { emit emitted(); } +signals: + void emitted(); +}; + + +class tst_ScriptEngine : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + m_component = new Component(&m_core); + // append the component to the package manager which deletes it at destructor + // (it calls clearAllComponentLists which calls qDeleteAll(m_rootComponents);) + m_core.appendRootComponent(m_component); + + m_component->setValue("AutoDependOn", "Script"); + m_component->setValue("Default", "Script"); + m_component->setValue(scName, "component.test.name"); + + m_scriptEngine = m_core.componentScriptEngine(); + } + + void testBrokenJSMethodConnect() + { + EmitSignalObject emiter; + m_scriptEngine->globalObject().setProperty(QLatin1String("emiter"), + m_scriptEngine->newQObject(&emiter)); + + QScriptValue context = m_scriptEngine->loadInConext(QLatin1String("BrokenConnect"), + ":///data/broken_connect.qs"); + + QVERIFY(context.isValid()); + + if (m_scriptEngine->hasUncaughtException()) { + QFAIL(qPrintable(QString::fromLatin1("ScriptEngine hasUncaughtException:\n %1").arg( + uncaughtExceptionString(m_scriptEngine)))); + } + + const QString debugMesssage( + "create Error-Exception: \"Fatal error while evaluating a script.\n\n" + "ReferenceError: Can't find variable: foo\n\n" + "Backtrace:\n" +#if QT_VERSION < 0x050000 + "\t<anonymous>()@:///data/broken_connect.qs:10\" "); +#else + "\treceive() at :///data/broken_connect.qs:10\n" + "\t<global>() at -1\" "); +#endif + try { + // ignore Output from script + setExpectedScriptOutput("function receive()"); + setExpectedScriptOutput(qPrintable(debugMesssage)); + emiter.produceSignal(); + } catch (const Error &error) { + QVERIFY2(debugMesssage.contains(error.message()), "There was some unexpected error."); + } + } + + void testScriptPrint() + { + setExpectedScriptOutput("test"); + m_scriptEngine->evaluate("print(\"test\");"); + if (m_scriptEngine->hasUncaughtException()) { + QFAIL(qPrintable(QString::fromLatin1("ScriptEngine hasUncaughtException:\n %1").arg( + uncaughtExceptionString(m_scriptEngine)))); + } + } + + void testExistingInstallerObject() + { + setExpectedScriptOutput("object"); + m_scriptEngine->evaluate("print(typeof installer)"); + if (m_scriptEngine->hasUncaughtException()) { + QFAIL(qPrintable(QString::fromLatin1("ScriptEngine hasUncaughtException:\n %1").arg( + uncaughtExceptionString(m_scriptEngine)))); + } + } + + void testComponentByName() + { + const QString printComponentNameScript = QString::fromLatin1("var correctComponent = " + "installer.componentByName('%1');\nprint(correctComponent.name);").arg(m_component->name()); + + setExpectedScriptOutput("component.test.name"); + m_scriptEngine->evaluate(printComponentNameScript); + if (m_scriptEngine->hasUncaughtException()) { + QFAIL(qPrintable(QString::fromLatin1("ScriptEngine hasUncaughtException:\n %1").arg( + uncaughtExceptionString(m_scriptEngine)))); + } + } + + void testComponentByWrongName() + { + const QString printComponentNameScript = QString::fromLatin1( "var brokenComponent = " + "installer.componentByName('%1');\nprint(brokenComponent.name);").arg("MyNotExistingComponentName"); + + m_scriptEngine->evaluate(printComponentNameScript); + QVERIFY(m_scriptEngine->hasUncaughtException()); + } + + void loadSimpleComponentScript() + { + try { + // ignore retranslateUi which is called by loadComponentScript + setExpectedScriptOutput("Component constructor - OK"); + setExpectedScriptOutput("retranslateUi - OK"); + m_component->loadComponentScript(":///data/component1.qs"); + + setExpectedScriptOutput("retranslateUi - OK"); + m_component->languageChanged(); + + setExpectedScriptOutput("createOperationsForPath - OK"); + m_component->createOperationsForPath(":///data/"); + + setExpectedScriptOutput("createOperationsForArchive - OK"); + // ignore createOperationsForPath which is called by createOperationsForArchive + setExpectedScriptOutput("createOperationsForPath - OK"); + m_component->createOperationsForArchive("test.7z"); + + setExpectedScriptOutput("beginInstallation - OK"); + m_component->beginInstallation(); + + setExpectedScriptOutput("createOperations - OK"); + m_component->createOperations(); + + setExpectedScriptOutput("isAutoDependOn - OK"); + bool returnIsAutoDependOn = m_component->isAutoDependOn(QSet<QString>()); + QCOMPARE(returnIsAutoDependOn, false); + + setExpectedScriptOutput("isDefault - OK"); + bool returnIsDefault = m_component->isDefault(); + QCOMPARE(returnIsDefault, false); + + } catch (const Error &error) { + QFAIL(qPrintable(error.message())); + } + } + + void loadBrokenComponentScript() + { + Component *testComponent = new Component(&m_core); + testComponent->setValue(scName, "broken.component"); + + // now m_core becomes the owner of testComponent + // so it will delete it then at the destuctor + m_core.appendRootComponent(testComponent); + + const QString debugMesssage( + "create Error-Exception: \"Exception while loading the component script: ':///data/component2.qs\n\n" + "ReferenceError: Can't find variable: broken\n\n" + "Backtrace:\n" +#if QT_VERSION < 0x050000 + "\t<anonymous>()@:///data/component2.qs:5'\" "); +#else + "\tComponent() at :///data/component2.qs:5\n" + "\t<anonymous>() at :///data/component2.qs:7\n" + "\t<global>() at :///data/component2.qs:7'\" "); +#endif + try { + // ignore Output from script + setExpectedScriptOutput("script function: Component"); + setExpectedScriptOutput(qPrintable(debugMesssage)); + testComponent->loadComponentScript(":///data/component2.qs"); + } catch (const Error &error) { + QVERIFY2(debugMesssage.contains(error.message()), "There was some unexpected error."); + } + } + + void loadSimpleAutoRunScript() + { + try { + TestGui testGui(&m_core); + setExpectedScriptOutput("Loaded control script \":///data/auto-install.qs\" "); + testGui.loadControlScript(":///data/auto-install.qs"); + QCOMPARE(m_core.value("GuiTestValue"), QString("hello")); + + // show event calls automatically the first callback which does not exist + setExpectedScriptOutput("Control script callback \"IntroductionPageCallback\" does not exist. "); + testGui.show(); + + // inside the auto-install script we are clicking the next button, with a not existing button + QTest::ignoreMessage(QtWarningMsg, "Button with type: \"unknown button\" not found! "); + testGui.callProtectedDelayedExecuteControlScript(PackageManagerCore::ComponentSelection); + + setExpectedScriptOutput("FinishedPageCallback - OK"); + testGui.callProtectedDelayedExecuteControlScript(PackageManagerCore::InstallationFinished); + } catch (const Error &error) { + QFAIL(qPrintable(error.message())); + } + } + +private: + void setExpectedScriptOutput(const char *message) + { + // Using setExpectedScriptOutput(...); inside the test method + // as a simple test that the scripts are called. + QTest::ignoreMessage(QtDebugMsg, message); + } + + PackageManagerCore m_core; + Component *m_component; + ScriptEngine *m_scriptEngine; + +}; + + +QTEST_MAIN(tst_ScriptEngine) + +#include "tst_scriptengine.moc" diff --git a/tests/auto/installer/settings/data/full_config.xml b/tests/auto/installer/settings/data/full_config.xml index cde9f6310..0386f98c1 100644 --- a/tests/auto/installer/settings/data/full_config.xml +++ b/tests/auto/installer/settings/data/full_config.xml @@ -15,8 +15,11 @@ File should contain all elements we allow in a config.xml <AdminTargetDir>@rootDir@InstallationDirectory</AdminTargetDir> <Icon>icon</Icon> + <InstallerApplicationIcon>icon</InstallerApplicationIcon> + <InstallerWindowIcon>icon</InstallerWindowIcon> <Logo>logo</Logo> <Watermark>watermark</Watermark> + <Banner>banner</Banner> <Background>background</Background> <StartMenuDir>Super App</StartMenuDir> @@ -26,6 +29,7 @@ File should contain all elements we allow in a config.xml <RemoveTargetDir>true</RemoveTargetDir> <RunProgram>myapp</RunProgram> + <RunProgramArguments>foo bar</RunProgramArguments> <RunProgramDescription>Launch MyApp</RunProgramDescription> <DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary> @@ -43,125 +47,8 @@ File should contain all elements we allow in a config.xml </Repository> </RemoteRepositories> - <Pages> - <Page name="IntroductionPage"> - <Title> - <Default>Introduction Page Title</Default> - </Title> - <SubTitle> - <Default>Introduction Page Sub Title</Default> - </SubTitle> - <MessageLabel>Introduction Page Message Label</MessageLabel> - </Page> - <Page name="LicenseAgreementPage"> - <Title> - <Default>License Agreement Page Title</Default> - </Title> - <SubTitle> - <Default>License Agreement Page Sub Title</Default> - </SubTitle> - <AcceptLicenseLabel>Accept License Radio Button</AcceptLicenseLabel> - <RejectLicenseLabel>Reject License Radio Button</RejectLicenseLabel> - </Page> - <Page name="ComponentSelectionPage"> - <Title> - <Default>Component Selection Page Title</Default> - <Updater>Component Selection Page Sub Title Updater</Updater> - <Installer>Component Selection Page Sub Title Installer</Installer> - <Uninstaller>Component Selection Page Sub Title Uninstaller</Uninstaller> - <PackageManager>Component Selection Page Sub Title Package Manager</PackageManager> - </Title> - <SubTitle> - <Default>Component Selection Page Sub Title</Default> - <Updater>Component Selection Page Sub Title Updater</Updater> - <Installer>Component Selection Page Sub Title Installer</Installer> - <Uninstaller>Component Selection Page Sub Title Uninstaller</Uninstaller> - <PackageManager>Component Selection Page Sub Title Package Manager</PackageManager> - </SubTitle> - <SelectDefaultComponentsButton>Default Button</SelectDefaultComponentsButton> - <SelectAllComponentsButton>Select All Button</SelectAllComponentsButton> - <DeselectAllComponentsButton>Deselect All Button</DeselectAllComponentsButton> - <ComponentSizeLabel>Component Size Label</ComponentSizeLabel> - </Page> - <Page name="TargetDirectoryPage"> - <Title> - <Default>Target Directory Page Title</Default> - </Title> - <SubTitle> - <Default>Target Directory Page Sub Title</Default> - </SubTitle> - <MessageLabel>Target Directory Page Message Label</MessageLabel> - <BrowseDirectoryButton>Browse Directory Button</BrowseDirectoryButton> - <EmptyTargetDirectoryMessage>Empty Target Directory Message</EmptyTargetDirectoryMessage> - <ForbiddenTargetDirectoryMessage>Forbidden Target Directory Message</ForbiddenTargetDirectoryMessage> - <OverwriteTargetDirectoryMessage>Overwrite Target Directory Message</OverwriteTargetDirectoryMessage> - <SelectInstallationFolderCaption>Select Installation Folder Caption</SelectInstallationFolderCaption> - </Page> - <Page name="StartMenuDirectoryPage"> - <Title> - <Default>Start Menu Directory Page Title</Default> - </Title> - <SubTitle> - <Default>Start Menu Directory Page Sub Title</Default> - </SubTitle> - </Page> - <Page name="ReadyForInstallationPage"> - <Title> - <Default>Ready for Installation Page Title</Default> - <Updater>Ready for Installation Page Title Updater</Updater> - <Installer>Ready for Installation Page Title Installer</Installer> - <Uninstaller>Ready for Installation Page Title Uninstaller</Uninstaller> - <PackageManager>Ready for Installation Page Title Package Manager</PackageManager> - </Title> - <SubTitle> - <Default>Ready for Installation Page Sub Title</Default> - <Updater>Ready for Installation Page Sub Title Updater</Updater> - <Installer>Ready for Installation Page Sub Title Installer</Installer> - <Uninstaller>Ready for Installation Page Sub Title Uninstaller</Uninstaller> - <PackageManager>Ready for Installation Page Sub Title Package Manager</PackageManager> - </SubTitle> - <MessageLabel>Ready for Installation Page Message Label</MessageLabel> - </Page> - <Page name="PerformInstallationPage"> - <Title> - <Default>Perform Installation Page Title</Default> - <Updater>Perform Installation Page Title Updater</Updater> - <Installer>Perform Installation Page Title Installer</Installer> - <Uninstaller>Perform Installation Page Title Uninstaller</Uninstaller> - <PackageManager>Perform Installation Page Title Package Manager</PackageManager> - </Title> - <SubTitle> - <Default>Perform Installation Page Sub Title</Default> - <Updater>Perform Installation Page Sub Title Updater</Updater> - <Installer>Perform Installation Page Sub Title Installer</Installer> - <Uninstaller>Perform Installation Page Sub Title Uninstaller</Uninstaller> - <PackageManager>Perform Installation Page Sub Title Package Manager</PackageManager> - </SubTitle> - </Page> - <Page name ="FinishedPage"> - <Title> - <Default>Finished Page Title</Default> - <Updater>Finished Page Title Updater</Updater> - <Installer>Finished Page Title Installer</Installer> - <Uninstaller>Finished Page Title Uninstaller</Uninstaller> - <PackageManager>Finished Page Title Package Manager</PackageManager> - </Title> - <SubTitle> - <Default>Finished Page Sub Title</Default> - <Updater>Finished Page Sub Title Updater</Updater> - <Installer>Finished Page Sub Title Installer</Installer> - <Uninstaller>Finished Page Sub Title Uninstaller</Uninstaller> - <PackageManager>Finished Page Sub Title Package Manager</PackageManager> - </SubTitle> - <MessageLabel>Finished Page Message Label</MessageLabel> - </Page> - <Page name="RestartPage"> - <Title> - <Default>Restart Page Title</Default> - </Title> - <SubTitle> - <Default>Restart Page Sub Title</Default> - </SubTitle> - </Page> - </Pages> + <Translations> + <Translation>de_de</Translation> + <Translation>qt_de</Translation> + </Translations> </Installer> diff --git a/tests/auto/installer/settings/tst_settings.cpp b/tests/auto/installer/settings/tst_settings.cpp index be42a24ae..e6ebc6e6e 100644 --- a/tests/auto/installer/settings/tst_settings.cpp +++ b/tests/auto/installer/settings/tst_settings.cpp @@ -38,15 +38,23 @@ void tst_Settings::loadTutorialConfig() QCOMPARE(settings.logo(), QLatin1String(":///data/")); QCOMPARE(settings.url(), QString()); QCOMPARE(settings.watermark(), QLatin1String(":///data/")); + QCOMPARE(settings.banner(), QLatin1String(":///data/")); QCOMPARE(settings.background(), QLatin1String(":///data/")); #if defined(Q_OS_WIN) QCOMPARE(settings.icon(), QLatin1String(":/installer.ico")); + QCOMPARE(settings.installerApplicationIcon(), QLatin1String(":/installer.ico")); + QCOMPARE(settings.installerWindowIcon(), QLatin1String(":/installer.ico")); #elif defined(Q_OS_MAC) QCOMPARE(settings.icon(), QLatin1String(":/installer.icns")); + QCOMPARE(settings.installerApplicationIcon(), QLatin1String(":/installer.icns")); + QCOMPARE(settings.installerWindowIcon(), QLatin1String(":/installer.icns")); #else QCOMPARE(settings.icon(), QLatin1String(":/installer.png")); + QCOMPARE(settings.installerApplicationIcon(), QLatin1String(":/installer.png")); + QCOMPARE(settings.installerWindowIcon(), QLatin1String(":/installer.png")); #endif QCOMPARE(settings.runProgram(), QString()); + QCOMPARE(settings.runProgramArguments(), QString()); QCOMPARE(settings.runProgramDescription(), QString()); QCOMPARE(settings.adminTargetDir(), QString()); QCOMPARE(settings.removeTargetDir(), QLatin1String("true")); @@ -68,11 +76,13 @@ void tst_Settings::loadTutorialConfig() QCOMPARE(settings.proxyType(), Settings::NoProxy); QCOMPARE(settings.ftpProxy(), QNetworkProxy()); QCOMPARE(settings.httpProxy(), QNetworkProxy()); + + QCOMPARE(settings.translations(), QStringList()); } void tst_Settings::loadFullConfig() { - QTest::ignoreMessage(QtWarningMsg, "Deprecated element 'Pages'. "); + QTest::ignoreMessage(QtWarningMsg, "Deprecated element 'Icon'. "); Settings settings = Settings::fromFileAndPrefix(":///data/full_config.xml", ":///data"); } diff --git a/tests/auto/installer/solver/solver.pro b/tests/auto/installer/solver/solver.pro new file mode 100644 index 000000000..0094bc090 --- /dev/null +++ b/tests/auto/installer/solver/solver.pro @@ -0,0 +1,5 @@ +include(../../qttest.pri) + +QT -= gui + +SOURCES += tst_solver.cpp diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp new file mode 100644 index 000000000..f0596b31e --- /dev/null +++ b/tests/auto/installer/solver/tst_solver.cpp @@ -0,0 +1,134 @@ +/************************************************************************** +** +** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "graph.h" + +#include <QTest> + +using namespace QInstaller; + +class Data { +public: + Data() {} + explicit Data(const QString &data) + : m_data(data) {} + inline uint 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; } + +private: + QString m_data; +}; +inline uint qHash(const Data &data) +{ + return qHash(data.data()); +} + + +class tst_Solver : public QObject +{ + Q_OBJECT + +private slots: + // TODO: add failing cases + void sortGraph() + { + Graph<QString> graph; + graph.addNode("Hut"); + graph.addEdge("Jacke", "Shirt"); + graph.addEdge("Guertel", "Hose"); + graph.addEdge("Guertel", "Shirt"); + graph.addEdge("Shirt", "Socken"); + graph.addEdge("Socken", "Unterwaesche"); + graph.addEdge("Shirt", "Unterwaesche"); + graph.addEdges("Hose", QStringList() << "Unterwaesche" << "Socken"); + graph.addEdges("Krawatte", QStringList() << "Shirt" << "Hose" << "Guertel"); + graph.addEdges("Schuhe", QStringList() << "Socken" << "Unterwaesche" << "Hose"); + graph.addEdges("Jacke", QStringList() << "Hose" << "Shirt" << "Guertel" << "Schuhe" << "Krawatte"); + + QList<QString> resolved = graph.sort(); + foreach (const QString &value, resolved) + qDebug(qPrintable(value)); + } + + void sortGraphReverse() + { + Graph<QString> graph; + graph.addEdge("Krawatte", "Jacke"); + graph.addEdge("Guertel", "Jacke"); + graph.addEdge("Shirt", "Guertel"); + graph.addEdges("Shirt", QList<QString>() << "Krawatte" << "Schuhe"); + graph.addEdges("Hose", QList<QString>() << "Schuhe" << "Guertel" << "Shirt"); + graph.addEdges("Socken", QList<QString>() << "Schuhe" << "Hose"); + graph.addEdges("Unterwaesche", QList<QString>() << "Socken" << "Hose" << "Guertel" << "Shirt" + << "Krawatte" << "Schuhe"); + + QList<QString> resolved = graph.sortReverse(); + foreach (const QString &value, resolved) + qDebug(qPrintable(value)); + } + + void sortGraphCycle() + { + Data a("A"), b("B"), c("C"), d("D"), e("E"); + + Graph<Data> graph; + graph.addEdge(a, b); + graph.addEdge(b, c); + graph.addEdge(c, d); + graph.addEdge(d, e); + graph.addEdge(e, a); + + QList<Data> resolved = graph.sort(); + foreach (const Data &value, resolved) + qDebug(qPrintable(value.data())); + + QPair<Data, Data> cycle = graph.cycle(); + qDebug("Found cycle: %s", graph.hasCycle() ? "true" : "false"); + qDebug("(%s) has a indirect dependency on (%s).", qPrintable(cycle.second.data()), + qPrintable(cycle.first.data())); + } +}; + +QTEST_MAIN(tst_Solver) + +#include "tst_solver.moc" diff --git a/tests/auto/qttest.pri b/tests/auto/qttest.pri index f6be301e8..be8526933 100644 --- a/tests/auto/qttest.pri +++ b/tests/auto/qttest.pri @@ -4,7 +4,6 @@ include(../../installerfw.pri) isEmpty(TEMPLATE):TEMPLATE=app QT += testlib CONFIG += qt warn_on console depend_includepath testcase -CONFIG -= app_bundle DEFINES -= QT_NO_CAST_FROM_ASCII # prefix test binary with tst_ @@ -16,3 +15,4 @@ DEFINES -= QT_NO_CAST_FROM_ASCII # # the below gets added to later by testcase.prf # check.commands = cd . & set PATH=$$lib;%PATH%& cmd /c #} +macx:include(../../no_app_bundle.pri) |