summaryrefslogtreecommitdiffstats
path: root/tests/auto/tools/qmake/tst_qmake.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/tools/qmake/tst_qmake.cpp')
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp214
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"