diff options
-rw-r--r-- | src/libs/installer/settings.cpp | 47 | ||||
-rw-r--r-- | tests/auto/installer/settings/data/empty_config.xml | 3 | ||||
-rw-r--r-- | tests/auto/installer/settings/data/full_config.xml | 171 | ||||
-rw-r--r-- | tests/auto/installer/settings/data/minimal_config.xml | 5 | ||||
-rw-r--r-- | tests/auto/installer/settings/data/unknown_element_config.xml | 6 | ||||
-rw-r--r-- | tests/auto/installer/settings/settings.qrc | 6 | ||||
-rw-r--r-- | tests/auto/installer/settings/tst_settings.cpp | 43 |
7 files changed, 269 insertions, 12 deletions
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp index d52ff2f52..3bf979bee 100644 --- a/src/libs/installer/settings.cpp +++ b/src/libs/installer/settings.cpp @@ -97,12 +97,22 @@ static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefaul else if (reader.name() == QLatin1String("Enabled")) repo.setEnabled(bool(reader.readElementText().toInt())); else - reader.skipCurrentElement(); + reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg( + reader.name().toString())); + + if (!reader.attributes().isEmpty()) + reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg( + reader.name().toString())); } set.insert(repo); } else { - reader.skipCurrentElement(); + reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg( + reader.name().toString())); } + + if (!reader.attributes().isEmpty()) + reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg( + reader.name().toString())); } return set; } @@ -121,7 +131,10 @@ static QHash<QString, QVariantHash> readPages(QXmlStreamReader &reader) while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("Page")) { QVariantHash pageElements; - QString pageName = reader.attributes().value(QLatin1String("name")).toString(); + const QString pageName = reader.attributes().value(QLatin1String("name")).toString(); + if (pageName.isEmpty()) + reader.raiseError(QLatin1String("Expected non-empty attribute 'name' for element 'Page'.")); + while (reader.readNextStartElement()) { const QString name = reader.name().toString(); if (name == QLatin1String("Title") || name == QLatin1String("SubTitle")) { @@ -131,6 +144,8 @@ static QHash<QString, QVariantHash> readPages(QXmlStreamReader &reader) } } hash.insert(pageName, pageElements); + } else { + reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString())); } } return hash; @@ -196,8 +211,19 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) QXmlStreamReader reader(&file); if (reader.readNextStartElement()) { if (reader.name() != QLatin1String("Installer")) - throw Error(tr("%1 is not valid: Installer root node expected.").arg(path)); + reader.raiseError(QString::fromLatin1("Unexpected element '%1' as root element.").arg( + reader.name().toString())); } + QStringList elementList; + elementList << scName << scVersion << scTitle << scPublisher << scProductUrl + << scTargetDir << scAdminTargetDir + << scIcon << scLogo << scLogoSmall << scWatermark << scBackground + << scStartMenuDir << scUninstallerName << scUninstallerIniFile << scRemoveTargetDir + << scRunProgram << scRunProgramDescription + << scSigningCertificate << scDependsOnLocalInstallerBinary + << scAllowSpaceInPath << scAllowNonAsciiCharacters + << scRepositorySettingsPageVisible << scTargetConfigurationFile + << scRemoteRepositories << scPages; QStringList blackList; blackList << scRemoteRepositories << scSigningCertificate << scPages; @@ -206,6 +232,13 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) s.d->m_data.insert(scPrefix, prefix); while (reader.readNextStartElement()) { const QString name = reader.name().toString(); + + if (!elementList.contains(name)) + reader.raiseError(QString::fromLatin1("Unexpected element '%1'.").arg(name)); + + if (!reader.attributes().isEmpty()) + reader.raiseError(QString::fromLatin1("Unexpected attribute for element '%1'.").arg(name)); + if (blackList.contains(name)) { if (name == scSigningCertificate) s.d->m_data.insertMulti(name, s.d->makeAbsolutePath(reader.readElementText())); @@ -221,14 +254,14 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix) } } else { if (s.d->m_data.contains(name)) - throw Error(tr("Multiple %1 elements found, but only one allowed.").arg(name)); + reader.raiseError(QString::fromLatin1("Element '%1' has been defined before.").arg(name)); s.d->m_data.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements)); } } if (reader.error() != QXmlStreamReader::NoError) { - throw Error(QString::fromLatin1("Xml parse error in %1: %2 Line: %3, Column: %4").arg(path) - .arg(reader.errorString()).arg(reader.lineNumber()).arg(reader.columnNumber())); + throw Error(QString::fromLatin1("Error in %1, line %2, column %3: %4") + .arg(path).arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); } if (s.d->m_data.value(scName).isNull()) diff --git a/tests/auto/installer/settings/data/empty_config.xml b/tests/auto/installer/settings/data/empty_config.xml new file mode 100644 index 000000000..66c9879a5 --- /dev/null +++ b/tests/auto/installer/settings/data/empty_config.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Installer> +</Installer> diff --git a/tests/auto/installer/settings/data/full_config.xml b/tests/auto/installer/settings/data/full_config.xml new file mode 100644 index 000000000..2b11c0166 --- /dev/null +++ b/tests/auto/installer/settings/data/full_config.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +File should contain all elements we allow in a config.xml +--> + +<Installer> + <Name>Your application</Name> + <Version>1.2.3</Version> + <Title>Your application Installer</Title> + <Publisher>Your vendor</Publisher> + <ProductUrl>Your vendor</ProductUrl> + + <TargetDir>@homeDir@InstallationDirectory</TargetDir> + <AdminTargetDir>@rootDir@InstallationDirectory</AdminTargetDir> + + <Icon>icon</Icon> + <Logo>logo</Logo> + <LogoSmall>logo_small</LogoSmall> + <Watermark>watermark</Watermark> + <Background>background</Background> + + <StartMenuDir>Super App</StartMenuDir> + + <UninstallerName>uninstaller</UninstallerName> + <UninstallerIniFile>uninstaller.ini</UninstallerIniFile> + <RemoveTargetDir>true</RemoveTargetDir> + + <RunProgram>myapp</RunProgram> + <RunProgramDescription>Launch MyApp</RunProgramDescription> + + <SigningCertificate>certificate1</SigningCertificate> + <SigningCertificate>certificate2</SigningCertificate> + + <DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary> + <AllowSpaceInPath>true</AllowSpaceInPath> + <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters> + <RepositorySettingsPageVisible>false</RepositorySettingsPageVisible> + <TargetConfigurationFile>components.xml</TargetConfigurationFile> + + <RemoteRepositories> + <Repository> + <Url>http://www.yourcompany.com/packages</Url> + <Enabled>1</Enabled> + <Username>user</Username> + <Password>password</Password> + </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> +</Installer> diff --git a/tests/auto/installer/settings/data/minimal_config.xml b/tests/auto/installer/settings/data/minimal_config.xml new file mode 100644 index 000000000..1b4e1d25d --- /dev/null +++ b/tests/auto/installer/settings/data/minimal_config.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Installer> + <Name>Your application</Name> + <Version>1.2.3</Version> +</Installer> diff --git a/tests/auto/installer/settings/data/unknown_element_config.xml b/tests/auto/installer/settings/data/unknown_element_config.xml new file mode 100644 index 000000000..0d97564e6 --- /dev/null +++ b/tests/auto/installer/settings/data/unknown_element_config.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Installer> + <Name>Your application</Name> + <Version>1.2.3</Version> + <unknown></unknown> +</Installer> diff --git a/tests/auto/installer/settings/settings.qrc b/tests/auto/installer/settings/settings.qrc index eaa92b93e..de130ea10 100644 --- a/tests/auto/installer/settings/settings.qrc +++ b/tests/auto/installer/settings/settings.qrc @@ -1,6 +1,10 @@ <RCC> <qresource prefix="/"> - <file>data/tutorial_config.xml</file> + <file>data/empty_config.xml</file> + <file>data/full_config.xml</file> <file>data/malformed_config.xml</file> + <file>data/minimal_config.xml</file> + <file>data/tutorial_config.xml</file> + <file>data/unknown_element_config.xml</file> </qresource> </RCC> diff --git a/tests/auto/installer/settings/tst_settings.cpp b/tests/auto/installer/settings/tst_settings.cpp index 2fcd6bf3f..9fbbd8292 100644 --- a/tests/auto/installer/settings/tst_settings.cpp +++ b/tests/auto/installer/settings/tst_settings.cpp @@ -12,12 +12,15 @@ class tst_Settings : public QObject Q_OBJECT private slots: - void loadConfig(); + void loadTutorialConfig(); + void loadFullConfig(); + void loadEmptyConfig(); void loadNotExistingConfig(); void loadMalformedConfig(); + void loadUnknownElementConfig(); }; -void tst_Settings::loadConfig() +void tst_Settings::loadTutorialConfig() { Settings settings = Settings::fromFileAndPrefix(":///data/tutorial_config.xml", ":///data"); @@ -62,12 +65,31 @@ void tst_Settings::loadConfig() QCOMPARE(settings.httpProxy(), QNetworkProxy()); } +void tst_Settings::loadFullConfig() +{ + Settings settings = + Settings::fromFileAndPrefix(":///data/full_config.xml", ":///data"); +} + +void tst_Settings::loadEmptyConfig() +{ + try { + Settings::fromFileAndPrefix(":/data/empty_config.xml", ":/data"); + } catch (const Error &error) { + QCOMPARE(error.message(), QLatin1String("Missing or empty <Name> tag in :/data/empty_config.xml.")); + return; + } + QFAIL("No exception thrown"); +} + void tst_Settings::loadNotExistingConfig() { try { Settings::fromFileAndPrefix(":/data/inexisting_config.xml", ":/data"); } catch (const Error &error) { - QVERIFY(error.message() == ("Could not open settings file :/data/inexisting_config.xml for reading: Unknown error")); + QCOMPARE(error.message(), QLatin1String("Could not open settings file " + ":/data/inexisting_config.xml for reading: " + "Unknown error")); return; } QFAIL("No exception thrown"); @@ -78,7 +100,20 @@ void tst_Settings::loadMalformedConfig() try { Settings::fromFileAndPrefix(":/data/malformed_config.xml", ":/data"); } catch (const Error &error) { - QVERIFY(error.message().startsWith("Xml parse error")); + QCOMPARE(error.message(), QLatin1String("Error in :/data/malformed_config.xml, line 9, column 0: " + "Premature end of document.")); + return; + } + QFAIL("No exception thrown"); +} + +void tst_Settings::loadUnknownElementConfig() +{ + try { + Settings::fromFileAndPrefix(":/data/unknown_element_config.xml", ":/data"); + } catch (const Error &error) { + QCOMPARE(error.message(), QLatin1String("Error in :/data/unknown_element_config.xml, line 5, " + "column 13: Unexpected element 'unknown'.")); return; } QFAIL("No exception thrown"); |