From e86f3c018833141776db2d15772ba53995656eac Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 28 Jul 2017 13:25:27 +0200 Subject: qmake: require a drive in a DOS path for it to be absolute For Q_OS_WIN, a path is only truly absolute if it includes a drive letter; merely starting with a slash is not enough. (We can't support UNC paths, so don't even try: qmake runs various commands in the source directory using CMD.exe, which doesn't support UNC as PWD.) This requires, when resolving a path relative to a root, transcribing the root's drive to such not-quite-absolute paths. Changed QMakeGlobals, $$absolute_path() and $$relative_path() to now use IoUtils::resolvePath() rather than delegating to QDir's absolute path method, since that doesn't correctly recognize the need for a drive letter (and qmake did run into problems with some paths, from splitPathList and a failing test, as a result). Moved existing ioUtils tests for handling of relative / absolute paths out into separate functions and expanded significantly. Fixed some existing tests to use an absolute path where one is needed; added two tests involving driveless (but rooted) paths; and fixed the test init to set a value for QT_HOST_DATA/src property (the lack of which lead to an assertion failure with this fix). Task-number: QTBUG-50839 Change-Id: I2bfc13c1bfbe1ae09997274622ea55cb3de31b43 Reviewed-by: Oswald Buddenhagen --- tests/auto/tools/qmakelib/evaltest.cpp | 46 ++++++++++---- tests/auto/tools/qmakelib/tst_qmakelib.cpp | 97 +++++++++++++++++++++++++++--- tests/auto/tools/qmakelib/tst_qmakelib.h | 5 ++ 3 files changed, 127 insertions(+), 21 deletions(-) (limited to 'tests/auto/tools/qmakelib') diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 03fd4753fd..cf69cc4026 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -34,6 +34,12 @@ #include #include +#ifdef Q_OS_WIN +# define EVAL_DRIVE "R:" +#else +# define EVAL_DRIVE +#endif + void tst_qmakelib::addAssignments() { QTest::newRow("assignment") @@ -1599,20 +1605,28 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << true; QTest::newRow("$$absolute_path(): file & path") - << "VAR = $$absolute_path(dir/file.ext, /root/sub)" - << "VAR = /root/sub/dir/file.ext" + << "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" << "" << true; +#ifdef Q_OS_WIN + QTest::newRow("$$absolute_path(): driveless file & absolute path") + << "VAR = $$absolute_path(/root/sub/dir/file.ext, " EVAL_DRIVE "/other)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" + << "" + << true; +#endif + QTest::newRow("$$absolute_path(): absolute file & path") - << "VAR = $$absolute_path(/root/sub/dir/file.ext, /other)" - << "VAR = /root/sub/dir/file.ext" + << "VAR = $$absolute_path(" EVAL_DRIVE "/root/sub/dir/file.ext, " EVAL_DRIVE "/other)" + << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" << "" << true; QTest::newRow("$$absolute_path(): empty file & path") - << "VAR = $$absolute_path('', /root/sub)" - << "VAR = /root/sub" + << "VAR = $$absolute_path('', " EVAL_DRIVE "/root/sub)" + << "VAR = " EVAL_DRIVE "/root/sub" << "" << true; @@ -1634,14 +1648,22 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << "" << true; +#ifdef Q_OS_WIN + QTest::newRow("$$relative_path(): driveless file & absolute path") + << "VAR = $$relative_path(/root/sub/dir/file.ext, " EVAL_DRIVE "/root/sub)" + << "VAR = dir/file.ext" + << "" + << true; +#endif + QTest::newRow("$$relative_path(): absolute file & path") - << "VAR = $$relative_path(/root/sub/dir/file.ext, /root/sub)" + << "VAR = $$relative_path(" EVAL_DRIVE "/root/sub/dir/file.ext, " EVAL_DRIVE "/root/sub)" << "VAR = dir/file.ext" << "" << true; QTest::newRow("$$relative_path(): empty file & path") - << "VAR = $$relative_path('', /root/sub)" + << "VAR = $$relative_path('', " EVAL_DRIVE "/root/sub)" << "VAR = ." << "" << true; @@ -2555,20 +2577,20 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) << true; QTest::newRow("touch(): missing target") - << "touch(/does/not/exist, files/other.txt): OK = 1" + << "touch(" EVAL_DRIVE "/does/not/exist, files/other.txt): OK = 1" << "OK = UNDEF" #ifdef Q_OS_WIN - << "##:1: Cannot open /does/not/exist: The system cannot find the path specified." + << "##:1: Cannot open " EVAL_DRIVE "/does/not/exist: The system cannot find the path specified." #else << "##:1: Cannot touch /does/not/exist: No such file or directory." #endif << true; QTest::newRow("touch(): missing reference") - << "touch(" + wpath + ", /does/not/exist): OK = 1" + << "touch(" + wpath + ", " EVAL_DRIVE "/does/not/exist): OK = 1" << "OK = UNDEF" #ifdef Q_OS_WIN - << "##:1: Cannot open reference file /does/not/exist: The system cannot find the path specified." + << "##:1: Cannot open reference file " EVAL_DRIVE "/does/not/exist: The system cannot find the path specified." #else << "##:1: Cannot stat() reference file /does/not/exist: No such file or directory." #endif diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp index b1250f4f1a..4a4b20fe50 100644 --- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp +++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp @@ -42,6 +42,7 @@ void tst_qmakelib::initTestCase() #endif m_prop.insert(ProKey("P1"), ProString("prop val")); m_prop.insert(ProKey("QT_HOST_DATA/get"), ProString(m_indir)); + m_prop.insert(ProKey("QT_HOST_DATA/src"), ProString(m_indir)); QVERIFY(!m_indir.isEmpty()); QVERIFY(QDir(m_outdir).removeRecursively()); @@ -224,21 +225,99 @@ void tst_qmakelib::pathUtils() QVERIFY(IoUtils::isRelativePath(fn0)); QString fn1 = "/a/unix/file/path"; - QVERIFY(IoUtils::isAbsolutePath(fn1)); QCOMPARE(IoUtils::pathName(fn1).toString(), QStringLiteral("/a/unix/file/")); QCOMPARE(IoUtils::fileName(fn1).toString(), QStringLiteral("path")); +} -#ifdef Q_OS_WIN - QString fn0a = "c:file/path"; - QVERIFY(IoUtils::isRelativePath(fn0a)); +void tst_qmakelib::ioUtilRelativity_data() +{ + QTest::addColumn("path"); + QTest::addColumn("relative"); - QString fn1a = "c:\\file\\path"; - QVERIFY(IoUtils::isAbsolutePath(fn1a)); + static const struct { + const char *name; + const char *path; + bool relative; + } rows[] = { + { "resource", ":/resource", +#ifdef QMAKE_BUILTIN_PRFS + false +#else + true #endif + }, +#ifdef Q_OS_WIN // all the complications: + // (except UNC: unsupported) + { "drive-abs", "c:/path/to/file", false }, + { "drive-abs-bs", "c:\\path\\to\\file", false }, + { "drive-path", "c:path/to/file.txt", true }, + { "drive-path-bs", "c:path\\to\\file.txt", true }, + { "rooted", "/Users/qt/bin/true", true }, + { "rooted-bs", "\\Users\\qt\\bin\\true", true }, + { "drive-rel", "c:file.txt", true }, + { "subdir-bs", "path\\to\\file", true }, +#else + { "rooted", "/usr/bin/false", false }, +#endif // Q_OS_WIN + { "subdir", "path/to/file", true }, + { "simple", "file.name", true }, + { "empty", "", true } + }; + + for (unsigned int i = sizeof(rows) / sizeof(rows[0]); i-- > 0; ) + QTest::newRow(rows[i].name) << QString::fromLatin1(rows[i].path) + << rows[i].relative; +} + +void tst_qmakelib::ioUtilRelativity() +{ + QFETCH(QString, path); + QFETCH(bool, relative); + + QCOMPARE(IoUtils::isRelativePath(path), relative); +} + +void tst_qmakelib::ioUtilResolve_data() +{ + QTest::addColumn("base"); + QTest::addColumn("path"); + QTest::addColumn("expect"); + + static const struct { + const char *name; + const char *base; + const char *path; + const char *expect; + } data[] = { +#ifdef Q_OS_WIN // all the complications: + { "drive-drive", "a:/ms/dir", "z:/root/file", "z:/root/file" }, + { "drive-drive-bs", "a:\\ms\\dir", "z:\\root\\file", "z:/root/file" }, + { "drive-root", "a:/ms/dir", "/root/file", "a:/root/file" }, + { "drive-root-bs", "a:\\ms\\dir", "\\root\\file", "a:/root/file" }, + { "drive-sub", "a:/ms/dir", "sub/file", "a:/ms/dir/sub/file" }, + { "drive-sub-bs", "a:\\ms\\dir", "sub\\file", "a:/ms/dir/sub/file" }, + { "drive-rel", "a:/ms/dir", "file.txt", "a:/ms/dir/file.txt" }, + { "drive-rel-bs", "a:\\ms\\dir", "file.txt", "a:/ms/dir/file.txt" }, +#else + { "abs-abs", "/a/unix/dir", "/root/file", "/root/file" }, + { "abs-sub", "/a/unix/dir", "sub/file", "/a/unix/dir/sub/file" }, + { "abs-rel", "/a/unix/dir", "file.txt", "/a/unix/dir/file.txt" }, +#endif // Q_OS_WIN + }; + + for (unsigned i = sizeof(data) / sizeof(data[0]); i-- > 0; ) + QTest::newRow(data[i].name) << QString::fromLatin1(data[i].base) + << QString::fromLatin1(data[i].path) + << QString::fromLatin1(data[i].expect); +} + +void tst_qmakelib::ioUtilResolve() +{ + QFETCH(QString, base); + QFETCH(QString, path); + QFETCH(QString, expect); - QString fnbase = "/another/dir"; - QCOMPARE(IoUtils::resolvePath(fnbase, fn0), QStringLiteral("/another/dir/file/path")); - QCOMPARE(IoUtils::resolvePath(fnbase, fn1), QStringLiteral("/a/unix/file/path")); + QCOMPARE(IoUtils::resolvePath(base, path), expect); } void QMakeTestHandler::print(const QString &fileName, int lineNo, int type, const QString &msg) diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.h b/tests/auto/tools/qmakelib/tst_qmakelib.h index e75dedb7ec..acfeb43ecd 100644 --- a/tests/auto/tools/qmakelib/tst_qmakelib.h +++ b/tests/auto/tools/qmakelib/tst_qmakelib.h @@ -48,7 +48,12 @@ private slots: void quoteArgUnix(); void quoteArgWin_data(); void quoteArgWin(); + void pathUtils(); + void ioUtilRelativity_data(); + void ioUtilRelativity(); + void ioUtilResolve_data(); + void ioUtilResolve(); void proString(); void proStringList(); -- cgit v1.2.3