diff options
author | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-06-12 17:01:37 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-06-15 09:24:08 +0000 |
commit | 3bd5fe5ebfe07e298d6b6d759090239567d78f08 (patch) | |
tree | 2352a4807fab7d5c534a7e038b4f8e8b3e704737 | |
parent | 6510c1e18c336c0a2bb0049b44b56acc8ace990d (diff) | |
download | qttools-3bd5fe5ebfe07e298d6b6d759090239567d78f08.tar.gz |
Add auto test for windeployqt.
Deploy test application and launch in clean environment
with qt.conf to verify that deployment works.
Task-number: QTBUG-46629
Change-Id: I3b73354b95e7e5c55c8f30991fbc9f7443176079
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
-rw-r--r-- | tests/auto/auto.pro | 4 | ||||
-rw-r--r-- | tests/auto/windeployqt/test/test.pro | 5 | ||||
-rw-r--r-- | tests/auto/windeployqt/testapp/main.cpp | 51 | ||||
-rw-r--r-- | tests/auto/windeployqt/testapp/testapp.pro | 2 | ||||
-rw-r--r-- | tests/auto/windeployqt/tst_windeployqt.cpp | 190 | ||||
-rw-r--r-- | tests/auto/windeployqt/windeployqt.pro | 3 |
6 files changed, 254 insertions, 1 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index a703a0609..20b5fec90 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -8,7 +8,8 @@ SUBDIRS=\ qhelpprojectdata \ cmake \ installed_cmake \ - qtdiag + qtdiag \ + windeployqt installed_cmake.depends = cmake @@ -24,3 +25,4 @@ cross_compile:SUBDIRS -= linguist qhelpprojectdata \ android|ios|qnx|wince*|winrt*:SUBDIRS -= qtdiag +!win32|wince*|winrt*:SUBDIRS -= windeployqt diff --git a/tests/auto/windeployqt/test/test.pro b/tests/auto/windeployqt/test/test.pro new file mode 100644 index 000000000..7aac19a0d --- /dev/null +++ b/tests/auto/windeployqt/test/test.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +QT = core testlib +DESTDIR = .. +TARGET = tst_windeployqt +SOURCES += ../tst_windeployqt.cpp diff --git a/tests/auto/windeployqt/testapp/main.cpp b/tests/auto/windeployqt/testapp/main.cpp new file mode 100644 index 000000000..4655408ba --- /dev/null +++ b/tests/auto/windeployqt/testapp/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QRasterWindow> +#include <QScreen> +#include <QTimer> + +// Simple test application just to verify that it comes up properly + +int main(int argc, char ** argv) +{ + QGuiApplication app(argc, argv); + QRasterWindow w; + w.setTitle("windeployqt test application"); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); + w.resize(availableGeometry.size() / 4); + w.show(); + QTimer::singleShot(200, &w, &QCoreApplication::quit); + return app.exec(); +} diff --git a/tests/auto/windeployqt/testapp/testapp.pro b/tests/auto/windeployqt/testapp/testapp.pro new file mode 100644 index 000000000..7bd2fba0e --- /dev/null +++ b/tests/auto/windeployqt/testapp/testapp.pro @@ -0,0 +1,2 @@ +SOURCES = main.cpp +DESTDIR = ./ diff --git a/tests/auto/windeployqt/tst_windeployqt.cpp b/tests/auto/windeployqt/tst_windeployqt.cpp new file mode 100644 index 000000000..4acea454f --- /dev/null +++ b/tests/auto/windeployqt/tst_windeployqt.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QLibraryInfo> +#include <QtCore/QProcess> +#include <QtCore/QProcessEnvironment> +#include <QtCore/QStandardPaths> +#include <QtCore/QTextStream> +#include <QtTest/QtTest> + +#ifndef QT_NO_PROCESS +static const QString msgProcessError(const QProcess &process, const QString &what) +{ + QString result; + QTextStream(&result) << what << ": \"" << process.program() << ' ' + << process.arguments().join(QLatin1Char(' ')) << "\": " << process.errorString(); + return result; +} + +static bool runProcess(const QString &binary, + const QStringList &arguments, + QString *errorMessage, + const QString &workingDir = QString(), + const QProcessEnvironment &env = QProcessEnvironment(), + int timeOut = 5000, + QByteArray *stdOut = Q_NULLPTR, QByteArray *stdErr = Q_NULLPTR) +{ + QProcess process; + if (!env.isEmpty()) + process.setProcessEnvironment(env); + if (!workingDir.isEmpty()) + process.setWorkingDirectory(workingDir); + qDebug().noquote().nospace() << "Running: " << QDir::toNativeSeparators(binary) + << ' ' << arguments.join(QLatin1Char(' ')); + process.start(binary, arguments, QIODevice::ReadOnly); + if (!process.waitForStarted()) { + *errorMessage = msgProcessError(process, "Failed to start"); + return false; + } + if (!process.waitForFinished(timeOut)) { + *errorMessage = msgProcessError(process, "Timed out"); + process.terminate(); + if (!process.waitForFinished(300)) + process.kill(); + return false; + } + if (stdOut) + *stdOut = process.readAllStandardOutput(); + if (stdErr) + *stdErr= process.readAllStandardError(); + if (process.exitStatus() != QProcess::NormalExit) { + *errorMessage = msgProcessError(process, "Crashed"); + return false; + } + if (process.exitCode() != QProcess::NormalExit) { + *errorMessage = msgProcessError(process, "Exit code " + QString::number(process.exitCode())); + return false; + } + return true; +} + +#endif // !QT_NO_PROCESS + +class tst_windeployqt : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void help(); + void deploy(); + +private: + QString m_windeployqtBinary; + QString m_testApp; + QString m_testAppBinary; +}; + +void tst_windeployqt::initTestCase() +{ +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess support"); +#else + m_windeployqtBinary = QStandardPaths::findExecutable("windeployqt"); + QVERIFY(!m_windeployqtBinary.isEmpty()); + m_testApp = QFINDTESTDATA("testapp"); + QVERIFY(!m_testApp.isEmpty()); + const QFileInfo testAppBinary(m_testApp + QLatin1String("/testapp.exe")); + QVERIFY2(testAppBinary.isFile(), qPrintable(testAppBinary.absoluteFilePath())); + m_testAppBinary = testAppBinary.absoluteFilePath(); +#endif // QT_NO_PROCESS +} + +void tst_windeployqt::help() +{ +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess support"); +#else + QString errorMessage; + QByteArray stdOut; + QByteArray stdErr; + QVERIFY2(runProcess(m_windeployqtBinary, QStringList("--help"), &errorMessage, + QString(), QProcessEnvironment(), 5000, &stdOut, &stdErr), + qPrintable(errorMessage)); + QVERIFY2(!stdOut.isEmpty(), stdErr); +#endif // QT_NO_PROCESS +} + +// deploy(): Deploys the test application and launches it with Qt removed from the environment +// to verify it runs stand-alone. + +void tst_windeployqt::deploy() +{ +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess support"); +#else + QString errorMessage; + // Deploy application + QStringList deployArguments; + deployArguments << QLatin1String("--no-translations") << QDir::toNativeSeparators(m_testAppBinary); + QVERIFY2(runProcess(m_windeployqtBinary, deployArguments, &errorMessage, QString(), QProcessEnvironment(), 20000), + qPrintable(errorMessage)); + + // Create environment with Qt and all "lib" paths removed. + const QString qtBinDir = QDir::toNativeSeparators(QLibraryInfo::location(QLibraryInfo::BinariesPath)); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + const QString pathKey = QLatin1String("PATH"); + const QChar pathSeparator(QLatin1Char(';')); // ### fixme: Qt 5.6: QDir::listSeparator() + const QString origPath = env.value(pathKey); + QString newPath; + foreach (const QString &pathElement, origPath.split(pathSeparator, QString::SkipEmptyParts)) { + if (pathElement.compare(qtBinDir, Qt::CaseInsensitive) + && !pathElement.contains(QLatin1String("\\lib"), Qt::CaseInsensitive)) { + if (!newPath.isEmpty()) + newPath.append(pathSeparator); + newPath.append(pathElement); + } + } + if (newPath == origPath) + qWarning() << "Unable to remove Qt from PATH"; + env.insert(pathKey, newPath); + + // Create qt.conf to enforce usage of local plugins + QFile qtConf(QFileInfo(m_testAppBinary).absolutePath() + QLatin1String("/qt.conf")); + QVERIFY2(qtConf.open(QIODevice::WriteOnly | QIODevice::Text), + qPrintable(qtConf.fileName() + QLatin1String(": ") + qtConf.errorString())); + QVERIFY(qtConf.write("[Paths]\nPrefix = .\n")); + qtConf.close(); + + // Verify that application still runs + QVERIFY2(runProcess(m_testAppBinary, QStringList(), &errorMessage, QString(), env, 10000), + qPrintable(errorMessage)); +#endif // QT_NO_PROCESS +} + +QTEST_MAIN(tst_windeployqt) +#include "tst_windeployqt.moc" diff --git a/tests/auto/windeployqt/windeployqt.pro b/tests/auto/windeployqt/windeployqt.pro new file mode 100644 index 000000000..0ae9b2bab --- /dev/null +++ b/tests/auto/windeployqt/windeployqt.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = testapp test +CONFIG += ordered |