diff options
Diffstat (limited to 'tests/auto/tools/qmake/tst_qmake.cpp')
-rw-r--r-- | tests/auto/tools/qmake/tst_qmake.cpp | 214 |
1 files changed, 168 insertions, 46 deletions
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp index cacee30c86..a32b4ab228 100644 --- a/tests/auto/tools/qmake/tst_qmake.cpp +++ b/tests/auto/tools/qmake/tst_qmake.cpp @@ -1,48 +1,18 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include "testcompiler.h" #include <QDir> #include <QDirIterator> #include <QObject> +#include <QRegularExpression> #include <QStandardPaths> #include <QTemporaryDir> - -#if defined(DEBUG_BUILD) -# define DIR_INFIX "debug/" -#elif defined(RELEASE_BUILD) -# define DIR_INFIX "release/" -#else -# define DIR_INFIX "" -#endif +#include <QLibraryInfo> +#include <QProcessEnvironment> class tst_qmake : public QObject { @@ -75,13 +45,17 @@ private slots: void findMocs(); void findDeps(); void rawString(); -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) void bundle_spaces(); +#elif defined(Q_OS_WIN) + void windowsResources(); #endif void substitutes(); void project(); void proFileCache(); + void qinstall(); void resources(); + void conflictingTargets(); private: TestCompiler test_compiler; @@ -120,8 +94,17 @@ static void copyDir(const QString &sourceDirPath, const QString &targetDirPath) void tst_qmake::initTestCase() { QVERIFY2(tempWorkDir.isValid(), qPrintable(tempWorkDir.errorString())); - QString binpath = QLibraryInfo::location(QLibraryInfo::BinariesPath); + QString binpath = QLibraryInfo::path(QLibraryInfo::BinariesPath); QString cmd = QString("%1/qmake").arg(binpath); + + // If Qt is cross-compiled with CMake, we might also cross-compile qmake for the device. + // In this case we don't want to use the cross-compiled qmake, but rather the host qmake + // shell wrapper (if it's available). + const QString hostQmake = QString("%1/host-qmake").arg(binpath); + if (QFile::exists(hostQmake)) { + cmd = hostQmake; + } + #ifdef Q_CC_MSVC const QString jom = QStandardPaths::findExecutable(QLatin1String("jom.exe")); if (jom.isEmpty()) { @@ -141,7 +124,7 @@ void tst_qmake::initTestCase() QString testDataPath = QFINDTESTDATA(subProgram); if (!testDataPath.endsWith(subProgram)) QFAIL("Cannot find test data directory."); - testDataPath.chop(subProgram.length() - testDataSubDir.length()); + testDataPath.chop(subProgram.size() - testDataSubDir.size()); QString userWorkDir = qgetenv("TST_QMAKE_BUILD_DIR"); if (userWorkDir.isEmpty()) { @@ -313,6 +296,9 @@ void tst_qmake::subdirs() void tst_qmake::subdir_via_pro_file_extra_target() { + if (QProcessEnvironment::systemEnvironment().contains(QStringLiteral("QT_TEST_RUNNING_IN_CTEST"))) + QSKIP("This test does not run properly when invoked from CTest."); + QString workDir = base_path + "/testdata/subdir_via_pro_file_extra_target"; QDir D; @@ -422,7 +408,7 @@ void tst_qmake::prompt() { #if 0 QProcess qmake; - qmake.setReadChannelMode(QProcess::MergedChannels); + qmake.setProcessChannelMode(QProcess::MergedChannels); qmake.setWorkingDirectory(QLatin1String("testdata/prompt")); qmake.start(QLatin1String("qmake CONFIG-=debug_and_release CONFIG-=debug CONFIG+=release"), QIODevice::Text | QIODevice::ReadWrite); @@ -510,7 +496,8 @@ struct TempFile } }; -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) + void tst_qmake::bundle_spaces() { QString workDir = base_path + "/testdata/bundle-spaces"; @@ -541,7 +528,34 @@ void tst_qmake::bundle_spaces() QVERIFY( !non_existing_file.exists() ); QVERIFY( test_compiler.removeMakefile(workDir) ); } -#endif // defined(Q_OS_MAC) + +#elif defined(Q_OS_WIN) // defined(Q_OS_DARWIN) + +void tst_qmake::windowsResources() +{ + QString workDir = base_path + "/testdata/windows_resources"; + QVERIFY(test_compiler.qmake(workDir, "windows_resources")); + QVERIFY(test_compiler.make(workDir)); + + // Another "make" must not rebuild the .res file + test_compiler.clearCommandOutput(); + QVERIFY(test_compiler.make(workDir)); + QVERIFY(!test_compiler.commandOutput().contains("windows_resources.rc")); + test_compiler.clearCommandOutput(); + + // Wait a second to make sure we get a new timestamp in the touch below + QTest::qWait(1000); + + // Touch the deepest include of the .rc file + QVERIFY(test_compiler.runCommand("cmd", QStringList{"/c", + "echo.>>" + QDir::toNativeSeparators(workDir + "/version.inc")})); + + // The next "make" must rebuild the .res file + QVERIFY(test_compiler.make(workDir)); + QVERIFY(test_compiler.commandOutput().contains("windows_resources.rc")); +} + +#endif // defined(Q_OS_WIN) void tst_qmake::substitutes() { @@ -588,13 +602,108 @@ void tst_qmake::proFileCache() QVERIFY( test_compiler.qmake( workDir, "pro_file_cache" )); } +void tst_qmake::qinstall() +{ + const QString testName = "qinstall"; + QDir testDataDir = base_path + "/testdata"; + if (testDataDir.exists(testName)) + testDataDir.rmdir(testName); + QVERIFY(testDataDir.mkdir(testName)); + const QString workDir = testDataDir.filePath(testName); + auto qinstall = [&](const QString &src, const QString &dst, bool executable = false) { + QStringList args = {"-install", "qinstall"}; + if (executable) + args << "-exe"; + args << src << dst; + return test_compiler.qmake(workDir, args); + }; + const QFileDevice::Permissions readFlags + = QFileDevice::ReadOwner | QFileDevice::ReadUser + | QFileDevice::ReadGroup | QFileDevice::ReadOther; + const QFileDevice::Permissions writeFlags + = QFileDevice::WriteOwner | QFileDevice::WriteUser + | QFileDevice::WriteGroup | QFileDevice::WriteOther; + const QFileDevice::Permissions exeFlags + = QFileDevice::ExeOwner | QFileDevice::ExeUser + | QFileDevice::ExeGroup | QFileDevice::ExeOther; + + // install a regular file + { + QFileInfo src(testDataDir.filePath("project/main.cpp")); + QFileInfo dst("foo.cpp"); + QVERIFY(qinstall(src.filePath(), dst.filePath())); + QVERIFY(dst.exists()); + QCOMPARE(src.size(), dst.size()); + QVERIFY(dst.permissions() & readFlags); + QVERIFY(dst.permissions() & writeFlags); + QVERIFY(!(dst.permissions() & exeFlags)); + test_compiler.clearCommandOutput(); + } + + // install an executable file + { + const QString mocFilePath = QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) + + "/moc" +#ifdef Q_OS_WIN + + ".exe" +#endif + ; + QFileInfo src(mocFilePath); + QVERIFY(src.exists()); + QVERIFY(src.permissions() & exeFlags); + QFileInfo dst("copied_" + src.fileName()); + QVERIFY(qinstall(src.filePath(), dst.filePath(), true)); + QVERIFY(dst.exists()); + QCOMPARE(src.size(), dst.size()); + QVERIFY(dst.permissions() & readFlags); + QVERIFY(dst.permissions() & writeFlags); + QVERIFY(dst.permissions() & exeFlags); + test_compiler.clearCommandOutput(); + } + + // install a read-only file + { + QFile srcfile("foo.cpp"); + QVERIFY(srcfile.setPermissions(srcfile.permissions() & ~writeFlags)); + QFileInfo src(srcfile); + QFileInfo dst("bar.cpp"); + QVERIFY(qinstall(src.filePath(), dst.filePath())); + QVERIFY(dst.exists()); + QCOMPARE(src.size(), dst.size()); + QVERIFY(dst.permissions() & readFlags); + QVERIFY(dst.permissions() & writeFlags); + QVERIFY(!(dst.permissions() & exeFlags)); + test_compiler.clearCommandOutput(); + } + + // install a directory + { + QDir src = testDataDir; + src.cd("project"); + QDir dst("narf"); + QVERIFY(qinstall(src.absolutePath(), dst.absolutePath())); + QCOMPARE(src.entryList(QDir::Files, QDir::Name), dst.entryList(QDir::Files, QDir::Name)); + test_compiler.clearCommandOutput(); + } + + // install a directory with a read-only file + { + QDir src("narf"); + QFile srcfile(src.filePath("main.cpp")); + QVERIFY(srcfile.setPermissions(srcfile.permissions() & ~writeFlags)); + QDir dst("zort"); + QVERIFY(qinstall(src.absolutePath(), dst.absolutePath())); + QCOMPARE(src.entryList(QDir::Files, QDir::Name), dst.entryList(QDir::Files, QDir::Name)); + } +} + void tst_qmake::resources() { QString workDir = base_path + "/testdata/resources"; QVERIFY(test_compiler.qmake(workDir, "resources")); { - QFile qrcFile(workDir + '/' + DIR_INFIX "qmake_pro_file.qrc"); + QFile qrcFile(workDir + '/' + "qmake_pro_file.qrc"); QVERIFY2(qrcFile.exists(), qPrintable(qrcFile.fileName())); QVERIFY(qrcFile.open(QFile::ReadOnly)); QByteArray qrcXml = qrcFile.readAll(); @@ -603,7 +712,7 @@ void tst_qmake::resources() } { - QFile qrcFile(workDir + '/' + DIR_INFIX "qmake_subdir.qrc"); + QFile qrcFile(workDir + '/' + "qmake_subdir.qrc"); QVERIFY(qrcFile.exists()); QVERIFY(qrcFile.open(QFile::ReadOnly)); QByteArray qrcXml = qrcFile.readAll(); @@ -611,7 +720,7 @@ void tst_qmake::resources() } { - QFile qrcFile(workDir + '/' + DIR_INFIX "qmake_qmake_immediate.qrc"); + QFile qrcFile(workDir + '/' + "qmake_qmake_immediate.qrc"); QVERIFY(qrcFile.exists()); QVERIFY(qrcFile.open(QFile::ReadOnly)); QByteArray qrcXml = qrcFile.readAll(); @@ -621,5 +730,18 @@ void tst_qmake::resources() QVERIFY(test_compiler.make(workDir)); } +void tst_qmake::conflictingTargets() +{ + QString workDir = base_path + "/testdata/conflicting_targets"; + QVERIFY(test_compiler.qmake(workDir, "conflicting_targets")); + const QRegularExpression rex("Targets of builds '([^']+)' and '([^']+)' conflict"); + auto match = rex.match(test_compiler.commandOutput()); + QVERIFY(match.hasMatch()); + QStringList builds = { match.captured(1), match.captured(2) }; + std::sort(builds.begin(), builds.end()); + const QStringList expectedBuilds{"Debug", "Release"}; + QCOMPARE(builds, expectedBuilds); +} + QTEST_MAIN(tst_qmake) #include "tst_qmake.moc" |