1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "tst_qmakelib.h"
30
31#include <ioutils.h>
32
33using namespace QMakeInternal;
34
35void tst_qmakelib::initTestCase()
36{
37 m_indir = QFINDTESTDATA("testdata");
38 m_outdir = m_indir + QLatin1String("_build");
39 m_env.insert(QStringLiteral("E1"), QStringLiteral("env var"));
40#ifdef Q_OS_WIN
41 m_env.insert(QStringLiteral("COMSPEC"), qgetenv("COMSPEC"));
42#endif
43 m_prop.insert(akey: ProKey("P1"), avalue: ProString("prop val"));
44 m_prop.insert(akey: ProKey("QT_HOST_DATA/get"), avalue: ProString(m_indir));
45 m_prop.insert(akey: ProKey("QT_HOST_DATA/src"), avalue: ProString(m_indir));
46
47 QVERIFY(!m_indir.isEmpty());
48 QVERIFY(QDir(m_outdir).removeRecursively());
49 QVERIFY(QDir().mkpath(m_outdir));
50}
51
52void tst_qmakelib::cleanupTestCase()
53{
54 QVERIFY(QDir(m_outdir).removeRecursively());
55}
56
57void tst_qmakelib::proString()
58{
59 QString qs1(QStringLiteral("this is a string"));
60
61 ProString s1(qs1);
62 QCOMPARE(s1.toQString(), QStringLiteral("this is a string"));
63
64 ProString s2(qs1, 5, 8);
65 QCOMPARE(s2.toQString(), QStringLiteral("is a str"));
66
67 QCOMPARE(s2.hash(), 0x80000000);
68 qHash(str: s2);
69 QCOMPARE(s2.hash(), 90404018U);
70
71 QCOMPARE(s2.mid(0, 10).toQString(), QStringLiteral("is a str"));
72 QCOMPARE(s2.mid(1, 5).toQString(), QStringLiteral("s a s"));
73 QCOMPARE(s2.mid(10, 3).toQString(), QStringLiteral(""));
74
75 QString qs2(QStringLiteral(" spacy string "));
76 QCOMPARE(ProString(qs2, 3, 13).trimmed().toQString(), QStringLiteral("spacy string"));
77 QCOMPARE(ProString(qs2, 1, 17).trimmed().toQString(), QStringLiteral("spacy string"));
78
79 QVERIFY(s2.toQStringRef().string()->isSharedWith(qs1));
80 s2.prepend(other: ProString("there "));
81 QCOMPARE(s2.toQString(), QStringLiteral("there is a str"));
82 QVERIFY(!s2.toQStringRef().string()->isSharedWith(qs1));
83
84 ProString s3("this is a longish string with bells and whistles");
85 s3 = s3.mid(off: 18, len: 17);
86 // Prepend to detached string with lots of spare space in it.
87 s3.prepend(other: ProString("another "));
88 QCOMPARE(s3.toQString(), QStringLiteral("another string with bells"));
89
90 // Note: The string still has plenty of spare space.
91 s3.append(other: QLatin1Char('.'));
92 QCOMPARE(s3.toQString(), QStringLiteral("another string with bells."));
93 s3.append(other: QLatin1String(" eh?"));
94 QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh?"));
95
96 s3.append(other: ProString(" yeah!"));
97 QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah!"));
98
99 bool pending = false; // Not in string, but joining => add space
100 s3.append(other: ProString("..."), pending: &pending);
101 QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah! ..."));
102 QVERIFY(pending);
103
104 ProStringList sl1;
105 sl1 << ProString("") << ProString("foo") << ProString("barbaz");
106 ProString s4a("hallo");
107 s4a.append(other: sl1);
108 QCOMPARE(s4a.toQString(), QStringLiteral("hallo foo barbaz"));
109 ProString s4b("hallo");
110 pending = false;
111 s4b.append(other: sl1, pending: &pending);
112 QCOMPARE(s4b.toQString(), QStringLiteral("hallo foo barbaz"));
113 ProString s4c;
114 pending = false;
115 s4c.append(other: sl1, pending: &pending);
116 QCOMPARE(s4c.toQString(), QStringLiteral(" foo barbaz"));
117 // bizarreness
118 ProString s4d("hallo");
119 pending = false;
120 s4d.append(other: sl1, pending: &pending, skipEmpty1st: true);
121 QCOMPARE(s4d.toQString(), QStringLiteral("hallo foo barbaz"));
122 ProString s4e;
123 pending = false;
124 s4e.append(other: sl1, pending: &pending, skipEmpty1st: true);
125 QCOMPARE(s4e.toQString(), QStringLiteral("foo barbaz"));
126
127 ProStringList sl2;
128 sl2 << ProString("foo");
129 ProString s5;
130 s5.append(other: sl2);
131 QCOMPARE(s5.toQString(), QStringLiteral("foo"));
132 QVERIFY(s5.toQStringRef().string()->isSharedWith(*sl2.first().toQStringRef().string()));
133
134 QCOMPARE(ProString("one") + ProString(" more"), QStringLiteral("one more"));
135}
136
137void tst_qmakelib::proStringList()
138{
139 ProStringList sl1;
140 sl1 << ProString("qt") << ProString(QLatin1String("is"))
141 << ProString(QStringLiteral("uncool")).mid(off: 2);
142
143 QCOMPARE(sl1.toQStringList(), QStringList() << "qt" << "is" << "cool");
144 QCOMPARE(sl1.join(QStringLiteral("~~")), QStringLiteral("qt~~is~~cool"));
145
146 ProStringList sl2;
147 sl2 << ProString("mostly") << ProString("...") << ProString("is") << ProString("...");
148 sl1.insertUnique(value: sl2);
149 QCOMPARE(sl1.toQStringList(), QStringList() << "qt" << "is" << "cool" << "mostly" << "...");
150
151 QVERIFY(sl1.contains("cool"));
152 QVERIFY(!sl1.contains("COOL"));
153 QVERIFY(sl1.contains("COOL", Qt::CaseInsensitive));
154}
155
156void tst_qmakelib::quoteArgUnix_data()
157{
158 QTest::addColumn<QString>(name: "in");
159 QTest::addColumn<QString>(name: "out");
160
161 static const struct {
162 const char * const in;
163 const char * const out;
164 } vals[] = {
165 { .in: "", .out: "''" },
166 { .in: "hallo", .out: "hallo" },
167 { .in: "hallo du", .out: "'hallo du'" },
168 { .in: "ha'llo", .out: "'ha'\\''llo'" },
169 };
170
171 for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
172 QTest::newRow(dataTag: vals[i].in) << QString::fromLatin1(str: vals[i].in)
173 << QString::fromLatin1(str: vals[i].out);
174}
175
176void tst_qmakelib::quoteArgUnix()
177{
178 QFETCH(QString, in);
179 QFETCH(QString, out);
180
181 QCOMPARE(IoUtils::shellQuoteUnix(in), out);
182}
183
184void tst_qmakelib::quoteArgWin_data()
185{
186 QTest::addColumn<QString>(name: "in");
187 QTest::addColumn<QString>(name: "out");
188
189 static const struct {
190 const char * const in;
191 const char * const out;
192 } vals[] = {
193 { .in: "", .out: "\"\"" },
194 { .in: "hallo", .out: "hallo" },
195 { .in: "hallo du", .out: "\"hallo du\"" },
196 { .in: "hallo\\", .out: "hallo\\" },
197 { .in: "hallo du\\", .out: "\"hallo du\\\\\"" },
198 { .in: "ha\"llo", .out: "\"ha\\\"llo^\"" },
199 { .in: "ha\\\"llo", .out: "\"ha\\\\\\\"llo^\"" },
200 };
201
202 for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
203 QTest::newRow(dataTag: vals[i].in) << QString::fromLatin1(str: vals[i].in)
204 << QString::fromLatin1(str: vals[i].out);
205}
206
207void tst_qmakelib::quoteArgWin()
208{
209 QFETCH(QString, in);
210 QFETCH(QString, out);
211
212 QCOMPARE(IoUtils::shellQuoteWin(in), out);
213}
214
215void tst_qmakelib::pathUtils()
216{
217 QString afp = QCoreApplication::applicationFilePath();
218 QVERIFY(IoUtils::exists(afp));
219 QVERIFY(!IoUtils::exists(afp + "-tehfail"));
220 QCOMPARE(IoUtils::fileType(afp), IoUtils::FileIsRegular);
221 QString adp = QCoreApplication::applicationDirPath();
222 QCOMPARE(IoUtils::fileType(adp), IoUtils::FileIsDir);
223
224 QString fn0 = "file/path";
225 QVERIFY(IoUtils::isRelativePath(fn0));
226
227 QString fn1 = "/a/unix/file/path";
228 QCOMPARE(IoUtils::pathName(fn1).toString(), QStringLiteral("/a/unix/file/"));
229 QCOMPARE(IoUtils::fileName(fn1).toString(), QStringLiteral("path"));
230}
231
232void tst_qmakelib::ioUtilRelativity_data()
233{
234 QTest::addColumn<QString>(name: "path");
235 QTest::addColumn<bool>(name: "relative");
236
237 static const struct {
238 const char *name;
239 const char *path;
240 bool relative;
241 } rows[] = {
242 { .name: "resource", .path: ":/resource",
243#ifdef QMAKE_BUILTIN_PRFS
244 false
245#else
246 .relative: true
247#endif
248 },
249#ifdef Q_OS_WIN // all the complications:
250 // (except UNC: unsupported)
251 { "drive-abs", "c:/path/to/file", false },
252 { "drive-abs-bs", "c:\\path\\to\\file", false },
253 { "drive-path", "c:path/to/file.txt", true },
254 { "drive-path-bs", "c:path\\to\\file.txt", true },
255 { "rooted", "/Users/qt/bin/true", true },
256 { "rooted-bs", "\\Users\\qt\\bin\\true", true },
257 { "drive-rel", "c:file.txt", true },
258 { "subdir-bs", "path\\to\\file", true },
259#else
260 { .name: "rooted", .path: "/usr/bin/false", .relative: false },
261#endif // Q_OS_WIN
262 { .name: "subdir", .path: "path/to/file", .relative: true },
263 { .name: "simple", .path: "file.name", .relative: true },
264 { .name: "empty", .path: "", .relative: true }
265 };
266
267 for (unsigned int i = sizeof(rows) / sizeof(rows[0]); i-- > 0; )
268 QTest::newRow(dataTag: rows[i].name) << QString::fromLatin1(str: rows[i].path)
269 << rows[i].relative;
270}
271
272void tst_qmakelib::ioUtilRelativity()
273{
274 QFETCH(QString, path);
275 QFETCH(bool, relative);
276
277 QCOMPARE(IoUtils::isRelativePath(path), relative);
278}
279
280void tst_qmakelib::ioUtilResolve_data()
281{
282 QTest::addColumn<QString>(name: "base");
283 QTest::addColumn<QString>(name: "path");
284 QTest::addColumn<QString>(name: "expect");
285
286 static const struct {
287 const char *name;
288 const char *base;
289 const char *path;
290 const char *expect;
291 } data[] = {
292#ifdef Q_OS_WIN // all the complications:
293 { "drive-drive", "a:/ms/dir", "z:/root/file", "z:/root/file" },
294 { "drive-drive-bs", "a:\\ms\\dir", "z:\\root\\file", "z:/root/file" },
295 { "drive-root", "a:/ms/dir", "/root/file", "a:/root/file" },
296 { "drive-root-bs", "a:\\ms\\dir", "\\root\\file", "a:/root/file" },
297 { "drive-sub", "a:/ms/dir", "sub/file", "a:/ms/dir/sub/file" },
298 { "drive-sub-bs", "a:\\ms\\dir", "sub\\file", "a:/ms/dir/sub/file" },
299 { "drive-rel", "a:/ms/dir", "file.txt", "a:/ms/dir/file.txt" },
300 { "drive-rel-bs", "a:\\ms\\dir", "file.txt", "a:/ms/dir/file.txt" },
301#else
302 { .name: "abs-abs", .base: "/a/unix/dir", .path: "/root/file", .expect: "/root/file" },
303 { .name: "abs-sub", .base: "/a/unix/dir", .path: "sub/file", .expect: "/a/unix/dir/sub/file" },
304 { .name: "abs-rel", .base: "/a/unix/dir", .path: "file.txt", .expect: "/a/unix/dir/file.txt" },
305#endif // Q_OS_WIN
306 };
307
308 for (unsigned i = sizeof(data) / sizeof(data[0]); i-- > 0; )
309 QTest::newRow(dataTag: data[i].name) << QString::fromLatin1(str: data[i].base)
310 << QString::fromLatin1(str: data[i].path)
311 << QString::fromLatin1(str: data[i].expect);
312}
313
314void tst_qmakelib::ioUtilResolve()
315{
316 QFETCH(QString, base);
317 QFETCH(QString, path);
318 QFETCH(QString, expect);
319
320 QCOMPARE(IoUtils::resolvePath(base, path), expect);
321}
322
323void QMakeTestHandler::print(const QString &fileName, int lineNo, int type, const QString &msg)
324{
325 QString pfx = ((type & QMakeParserHandler::CategoryMask) == QMakeParserHandler::WarningMessage)
326 ? QString::fromLatin1(str: "WARNING: ") : QString();
327 if (lineNo)
328 doPrint(QStringLiteral("%1%2:%3: %4").arg(args&: pfx, args: fileName, args: QString::number(lineNo), args: msg));
329 else
330 doPrint(QStringLiteral("%1%2").arg(args&: pfx, args: msg));
331}
332
333void QMakeTestHandler::doPrint(const QString &msg)
334{
335 if (!expected.isEmpty() && expected.first() == msg) {
336 expected.removeAt(i: 0);
337 } else {
338 qWarning(msg: "%s", qPrintable(msg));
339 printed = true;
340 }
341}
342
343QTEST_MAIN(tst_qmakelib)
344

source code of qtbase/tests/auto/tools/qmakelib/tst_qmakelib.cpp