File indexing completed on 2024-05-19 15:46:18
0001 /* 0002 SPDX-FileCopyrightText: 2010 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "test_qmakefile.h" 0008 #include "qmakefile.h" 0009 #include "variablereferenceparser.h" 0010 #include "qmakeprojectfile.h" 0011 #include "qmakemkspecs.h" 0012 #include <qmakeconfig.h> 0013 0014 #include <QTest> 0015 0016 #include <QTextStream> 0017 #include <QProcessEnvironment> 0018 #include <QDebug> 0019 #include <QTemporaryFile> 0020 #include <QFileInfo> 0021 #include <QDir> 0022 #include <QTemporaryDir> 0023 #include <QStandardPaths> 0024 0025 #include <algorithm> 0026 0027 QTEST_GUILESS_MAIN(TestQMakeFile) 0028 0029 using DefineHash = QHash<QString, QString>; 0030 0031 Q_DECLARE_METATYPE(QMakeFile::VariableMap) 0032 Q_DECLARE_METATYPE(DefineHash) 0033 0034 namespace QTest { 0035 0036 template <> 0037 char* toString(const QStringList& list) 0038 { 0039 QByteArray ba; 0040 if (list.isEmpty()) { 0041 ba = "()"; 0042 } else { 0043 ba = "(\"" + list.join(QStringLiteral("\", \"")).toLocal8Bit() + "\")"; 0044 } 0045 return qstrdup(ba.data()); 0046 } 0047 0048 template <> 0049 char* toString(const QMakeFile::VariableMap& variables) 0050 { 0051 QByteArray ba; 0052 QTextStream out(&ba); 0053 out << "VariableMap("; 0054 QMakeFile::VariableMap::const_iterator it = variables.constBegin(); 0055 while (it != variables.constEnd()) { 0056 out << "[" << it.key() << "] = " << it.value().join(", "); 0057 ++it; 0058 if (it != variables.constEnd()) { 0059 out << ", "; 0060 } 0061 } 0062 out << ")"; 0063 out.flush(); 0064 return qstrdup(ba.data()); 0065 } 0066 } 0067 0068 QHash<QString, QString> setDefaultMKSpec(QMakeProjectFile& file) 0069 { 0070 static const QHash<QString, QString> qmvars = QMakeConfig::queryQMake(QMakeConfig::qmakeExecutable(nullptr)); 0071 static const QString specFile = QMakeConfig::findBasicMkSpec(qmvars); 0072 0073 if (!QFile::exists(specFile)) { 0074 qDebug() << "mkspec file does not exist:" << specFile; 0075 return {}; 0076 } 0077 0078 static QMakeMkSpecs mkspecs(specFile, qmvars); 0079 if (!mkspecs.ast()) 0080 mkspecs.read(); 0081 0082 file.setMkSpecs(&mkspecs); 0083 0084 return qmvars; 0085 } 0086 0087 void TestQMakeFile::initTestCase() 0088 { 0089 QStandardPaths::setTestModeEnabled(true); 0090 } 0091 0092 void TestQMakeFile::varResolution() 0093 { 0094 QFETCH(QString, fileContents); 0095 QFETCH(QMakeFile::VariableMap, variables); 0096 0097 QTemporaryFile tmpfile; 0098 tmpfile.open(); 0099 QTextStream stream(&tmpfile); 0100 stream << fileContents; 0101 stream.flush(); 0102 tmpfile.close(); 0103 0104 QMakeFile file(tmpfile.fileName()); 0105 QVERIFY(file.read()); 0106 QCOMPARE(file.variableMap(), variables); 0107 } 0108 0109 void TestQMakeFile::varResolution_data() 0110 { 0111 QTest::addColumn<QString>("fileContents"); 0112 QTest::addColumn<QMakeFile::VariableMap>("variables"); 0113 0114 { 0115 QMakeFile::VariableMap variables; 0116 variables[QStringLiteral("VAR1")] = QStringList() << QStringLiteral("1"); 0117 QTest::newRow("simple") << "VAR1 = 1\n" << variables; 0118 } 0119 0120 { 0121 QMakeFile::VariableMap variables; 0122 variables[QStringLiteral("VAR1")] = QStringList() << QStringLiteral("1"); 0123 variables[QStringLiteral("VAR2")] = QStringList() << QStringLiteral("1"); 0124 QTest::newRow("var-in-var") << "VAR1 = 1\nVAR2 = $$VAR1\n" << variables; 0125 } 0126 { 0127 QMakeFile::VariableMap variables; 0128 0129 variables[QStringLiteral("VAR1")] = QStringList() << QStringLiteral("foo"); 0130 variables[QStringLiteral("VAR2")] = QStringList() << QStringLiteral("foo"); 0131 QTest::newRow("curlyvar") << "VAR1 = foo\nVAR2 = $${VAR1}\n" << variables; 0132 } 0133 { 0134 QMakeFile::VariableMap variables; 0135 0136 qputenv("BLA", "BLUB"); 0137 variables[QStringLiteral("VAR1")] = QStringList { QStringLiteral("BLUB") }; 0138 QTest::newRow("qmakeshell") << "VAR1 = $$(BLA)\n" << variables; 0139 } 0140 { 0141 QMakeFile::VariableMap variables; 0142 0143 variables[QStringLiteral("VAR1")] = QStringList() << QStringLiteral("foo"); 0144 variables[QStringLiteral("VAR2")] = QStringList() << QStringLiteral("foo/bar"); 0145 QTest::newRow("path") << "VAR1 = foo\nVAR2 = $$VAR1/bar\n" << variables; 0146 } 0147 { 0148 QMakeFile::VariableMap variables; 0149 0150 variables[QStringLiteral("VAR_1")] = QStringList() << QStringLiteral("foo"); 0151 variables[QStringLiteral("VAR_2")] = QStringList() << QStringLiteral("foo/bar"); 0152 QTest::newRow("var-underscore") << "VAR_1 = foo\nVAR_2 = $$VAR_1/bar" << variables; 0153 } 0154 } 0155 0156 void TestQMakeFile::referenceParser() 0157 { 0158 QFETCH(QString, var); 0159 0160 VariableReferenceParser parser; 0161 parser.setContent(var); 0162 QVERIFY(parser.parse()); 0163 } 0164 0165 void TestQMakeFile::referenceParser_data() 0166 { 0167 QTest::addColumn<QString>("var"); 0168 0169 QTest::newRow("dot") << "."; 0170 QTest::newRow("dotdot") << ".."; 0171 } 0172 0173 void TestQMakeFile::libTarget() 0174 { 0175 QFETCH(QString, target); 0176 QFETCH(QString, resolved); 0177 0178 QTemporaryFile tmpfile; 0179 tmpfile.open(); 0180 QTextStream stream(&tmpfile); 0181 stream << "TARGET = " << target << "\nTEMPLATE = lib\n"; 0182 stream.flush(); 0183 tmpfile.close(); 0184 0185 QMakeProjectFile file(tmpfile.fileName()); 0186 0187 const auto qmvars = setDefaultMKSpec(file); 0188 if (qmvars.isEmpty()) { 0189 QSKIP("Problem querying QMake, skipping test function"); 0190 } 0191 0192 QVERIFY(file.read()); 0193 0194 QCOMPARE(file.targets(), QStringList() << resolved); 0195 } 0196 0197 void TestQMakeFile::libTarget_data() 0198 { 0199 QTest::addColumn<QString>("target"); 0200 QTest::addColumn<QString>("resolved"); 0201 0202 QTest::newRow("simple") << "MyLib" 0203 << "MyLib"; 0204 QTest::newRow("qtLibraryTarget") << "$$qtLibraryTarget(MyLib)" 0205 << "MyLib"; 0206 QTest::newRow("qtLibraryTarget-Var") << "MyLib\nTARGET = $$qtLibraryTarget($$TARGET)" 0207 << "MyLib"; 0208 } 0209 0210 void TestQMakeFile::defines() 0211 { 0212 QFETCH(QString, fileContents); 0213 QFETCH(DefineHash, expectedDefines); 0214 QTemporaryFile tmpfile; 0215 tmpfile.open(); 0216 QTextStream stream(&tmpfile); 0217 stream << fileContents; 0218 stream.flush(); 0219 tmpfile.close(); 0220 0221 QMakeProjectFile file(tmpfile.fileName()); 0222 0223 const auto qmvars = setDefaultMKSpec(file); 0224 if (qmvars.isEmpty()) { 0225 QSKIP("Problem querying QMake, skipping test function"); 0226 } 0227 0228 QVERIFY(file.read()); 0229 0230 const QList<QMakeProjectFile::DefinePair> list = file.defines(); 0231 QCOMPARE(list.size(), expectedDefines.size()); 0232 for (const QMakeProjectFile::DefinePair& define : list) { 0233 QVERIFY(expectedDefines.find(define.first) != expectedDefines.end()); 0234 QCOMPARE(define.second, expectedDefines[define.first]); 0235 } 0236 } 0237 0238 void TestQMakeFile::defines_data() 0239 { 0240 QTest::addColumn<QString>("fileContents"); 0241 QTest::addColumn<DefineHash>("expectedDefines"); 0242 { 0243 DefineHash list; 0244 list.insert(QStringLiteral("VAR1"), QString()); 0245 QTest::newRow("Simple define") << "DEFINES += VAR1" << list; 0246 } 0247 { 0248 DefineHash list; 0249 list.insert(QStringLiteral("ANSWER"), QStringLiteral("42")); 0250 QTest::newRow("Define with value") << "DEFINES += ANSWER=42" << list; 0251 } 0252 { 0253 DefineHash list; 0254 list.insert(QStringLiteral("ANSWER"), QStringLiteral("42")); 0255 list.insert(QStringLiteral("ANOTHER_DEFINE"), QString()); 0256 QTest::newRow("Multiple defines") << "DEFINES += ANSWER=42 ANOTHER_DEFINE" << list; 0257 } 0258 } 0259 0260 void TestQMakeFile::replaceFunctions_data() 0261 { 0262 QTest::addColumn<QString>("fileContents"); 0263 QTest::addColumn<QMakeFile::VariableMap>("definedVariables"); 0264 QTest::addColumn<QStringList>("undefinedVariables"); 0265 0266 { 0267 QString contents = "defineReplace(test) {\n" 0268 " FOO = $$1\n" 0269 " return($$FOO)\n" 0270 "}\n" 0271 "BAR = $$test(asdf)\n"; 0272 QMakeFile::VariableMap vars; 0273 vars[QStringLiteral("BAR")] = QStringList() << QStringLiteral("asdf"); 0274 QStringList undefined; 0275 undefined << QStringLiteral("FOO") 0276 << QStringLiteral("1"); 0277 QTest::newRow("defineReplace-1") << contents << vars << undefined; 0278 } 0279 } 0280 0281 void TestQMakeFile::replaceFunctions() 0282 { 0283 QFETCH(QString, fileContents); 0284 QFETCH(QMakeFile::VariableMap, definedVariables); 0285 QFETCH(QStringList, undefinedVariables); 0286 0287 QTemporaryFile tmpFile; 0288 tmpFile.open(); 0289 tmpFile.write(fileContents.toUtf8()); 0290 tmpFile.close(); 0291 0292 QMakeProjectFile file(tmpFile.fileName()); 0293 0294 setDefaultMKSpec(file); 0295 0296 QVERIFY(file.read()); 0297 0298 QMakeFile::VariableMap::const_iterator it = definedVariables.constBegin(); 0299 while (it != definedVariables.constEnd()) { 0300 QCOMPARE(file.variableValues(it.key()), it.value()); 0301 ++it; 0302 } 0303 for (const auto& var : std::as_const(undefinedVariables)) { 0304 QVERIFY(!file.containsVariable(var)); 0305 } 0306 } 0307 0308 void TestQMakeFile::qtIncludeDirs_data() 0309 { 0310 QTest::addColumn<QString>("fileContents"); 0311 QTest::addColumn<QStringList>("modules"); 0312 QTest::addColumn<QStringList>("missingModules"); 0313 0314 { 0315 QStringList list; 0316 list << QStringLiteral("core") 0317 << QStringLiteral("gui"); 0318 QTest::newRow("defaults") << "" << list; 0319 } 0320 { 0321 QStringList list; 0322 list << QStringLiteral("core"); 0323 QTest::newRow("minimal") << "QT -= gui" << list; 0324 } 0325 { 0326 QStringList modules; 0327 modules << QStringLiteral("core") 0328 << QStringLiteral("gui") 0329 << QStringLiteral("network") 0330 << QStringLiteral("opengl") 0331 << QStringLiteral("phonon") 0332 << QStringLiteral("script") 0333 << QStringLiteral("scripttools") 0334 << QStringLiteral("sql") 0335 << QStringLiteral("svg") 0336 << QStringLiteral("webkit") 0337 << QStringLiteral("xml") 0338 << QStringLiteral("xmlpatterns") 0339 << QStringLiteral("qt3support") 0340 << QStringLiteral("designer") 0341 << QStringLiteral("uitools") 0342 << QStringLiteral("help") 0343 << QStringLiteral("assistant") 0344 << QStringLiteral("qtestlib") 0345 << QStringLiteral("testlib") 0346 << QStringLiteral("qaxcontainer") 0347 << QStringLiteral("qaxserver") 0348 << QStringLiteral("dbus") 0349 << QStringLiteral("declarative"); 0350 for (const auto& module : std::as_const(modules)) { 0351 QStringList expected; 0352 expected << module; 0353 if (module != QLatin1String("core")) { 0354 expected << QStringLiteral("core"); 0355 } 0356 QTest::newRow(qPrintable(module)) << QStringLiteral("QT = %1").arg(module) << expected; 0357 } 0358 } 0359 } 0360 0361 void TestQMakeFile::qtIncludeDirs() 0362 { 0363 QFETCH(QString, fileContents); 0364 QFETCH(QStringList, modules); 0365 0366 QMap<QString, QString> moduleMap; 0367 moduleMap[QStringLiteral("core")] = QStringLiteral("QtCore"); 0368 moduleMap[QStringLiteral("gui")] = QStringLiteral("QtGui"); 0369 moduleMap[QStringLiteral("network")] = QStringLiteral("QtNetwork"); 0370 moduleMap[QStringLiteral("opengl")] = QStringLiteral("QtOpenGL"); 0371 moduleMap[QStringLiteral("phonon")] = QStringLiteral("Phonon"); 0372 moduleMap[QStringLiteral("script")] = QStringLiteral("QtScript"); 0373 moduleMap[QStringLiteral("scripttools")] = QStringLiteral("QtScriptTools"); 0374 moduleMap[QStringLiteral("sql")] = QStringLiteral("QtSql"); 0375 moduleMap[QStringLiteral("svg")] = QStringLiteral("QtSvg"); 0376 moduleMap[QStringLiteral("webkit")] = QStringLiteral("QtWebKit"); 0377 moduleMap[QStringLiteral("xml")] = QStringLiteral("QtXml"); 0378 moduleMap[QStringLiteral("xmlpatterns")] = QStringLiteral("QtXmlPatterns"); 0379 moduleMap[QStringLiteral("qt3support")] = QStringLiteral("Qt3Support"); 0380 moduleMap[QStringLiteral("designer")] = QStringLiteral("QtDesigner"); 0381 moduleMap[QStringLiteral("uitools")] = QStringLiteral("QtUiTools"); 0382 moduleMap[QStringLiteral("help")] = QStringLiteral("QtHelp"); 0383 moduleMap[QStringLiteral("assistant")] = QStringLiteral("QtAssistant"); 0384 moduleMap[QStringLiteral("qtestlib")] = QStringLiteral("QtTest"); 0385 moduleMap[QStringLiteral("testlib")] = QStringLiteral("QtTest"); 0386 moduleMap[QStringLiteral("qaxcontainer")] = QStringLiteral("ActiveQt"); 0387 moduleMap[QStringLiteral("qaxserver")] = QStringLiteral("ActiveQt"); 0388 moduleMap[QStringLiteral("dbus")] = QStringLiteral("QtDBus"); 0389 moduleMap[QStringLiteral("declarative")] = QStringLiteral("QtDeclarative"); 0390 0391 QTemporaryFile tmpFile; 0392 tmpFile.open(); 0393 tmpFile.write(fileContents.toUtf8()); 0394 tmpFile.close(); 0395 0396 QMakeProjectFile file(tmpFile.fileName()); 0397 0398 const auto qmvars = setDefaultMKSpec(file); 0399 if (qmvars.isEmpty()) { 0400 QSKIP("Problem querying QMake, skipping test function"); 0401 } 0402 0403 QVERIFY(file.read()); 0404 0405 const QStringList includes = file.includeDirectories(); 0406 0407 // should always be there 0408 QVERIFY(includes.contains(qmvars["QT_INSTALL_HEADERS"])); 0409 0410 for (QMap<QString, QString>::const_iterator it = moduleMap.constBegin(); it != moduleMap.constEnd(); ++it) { 0411 QFileInfo include(qmvars[QStringLiteral("QT_INSTALL_HEADERS")] + "/" + it.value()); 0412 0413 bool shouldBeIncluded = include.exists(); 0414 if (shouldBeIncluded) { 0415 shouldBeIncluded = modules.contains(it.key()); 0416 if (!shouldBeIncluded) { 0417 for (const auto& module : std::as_const(modules)) { 0418 if (module != it.key() && moduleMap.value(module) == it.value()) { 0419 shouldBeIncluded = true; 0420 break; 0421 } 0422 } 0423 } 0424 } 0425 QCOMPARE((bool)includes.contains(include.filePath()), shouldBeIncluded); 0426 } 0427 } 0428 0429 void TestQMakeFile::testInclude() 0430 { 0431 QTemporaryDir tempDir; 0432 QVERIFY(tempDir.isValid()); 0433 QTemporaryFile includeFile(tempDir.path() + "/qmake-include"); 0434 QVERIFY(includeFile.open()); 0435 includeFile.write("DEFINES += SOME_INCLUDE_DEF\n" 0436 "SOURCES += includedFile.cpp\n" 0437 "INCLUDEPATH += $$PWD\n" 0438 "QT += webkit\n"); 0439 includeFile.close(); 0440 0441 QTemporaryFile baseFile; 0442 baseFile.open(); 0443 baseFile.write("TEMPLATE = app\n" 0444 "TARGET = includeTest\n" 0445 "QT += network\n" 0446 "DEFINES += SOME_DEF\n" 0447 "SOURCES += file.cpp\n" 0448 /* 0449 "CONFIG += console" 0450 "# Comment to enable Debug Messages" 0451 "DEFINES += QT_NO_DEBUG_OUTPUT" 0452 "DESTDIR = ../bin" 0453 "RESOURCES = phantomjs.qrc" 0454 "HEADERS += csconverter.h \\" 0455 " phantom.h \\" 0456 " webpage.h \\" 0457 " consts.h \\" 0458 " utils.h \\" 0459 " networkaccessmanager.h \\" 0460 " cookiejar.h \\" 0461 " filesystem.h \\" 0462 " terminal.h \\" 0463 " encoding.h \\" 0464 " config.h \\" 0465 " mimesniffer.cpp \\" 0466 " third_party/mongoose/mongoose.h \\" 0467 " webserver.h" 0468 "SOURCES += phantom.cpp \\" 0469 " webpage.cpp \\" 0470 " main.cpp \\" 0471 " csconverter.cpp \\" 0472 " utils.cpp \\" 0473 " networkaccessmanager.cpp \\" 0474 " cookiejar.cpp \\" 0475 " filesystem.cpp \\" 0476 " terminal.cpp \\" 0477 " encoding.cpp \\" 0478 " config.cpp \\" 0479 " mimesniffer.cpp \\" 0480 " third_party/mongoose/mongoose.c \\" 0481 " webserver.cpp" 0482 "" 0483 "OTHER_FILES += usage.txt \\" 0484 " bootstrap.js \\" 0485 " configurator.js \\" 0486 " modules/fs.js \\" 0487 " modules/webpage.js \\" 0488 " modules/webserver.js" 0489 "" 0490 */ 0491 "include(" 0492 + includeFile.fileName().toLocal8Bit() + ")\n"); 0493 baseFile.close(); 0494 0495 QMakeProjectFile file(baseFile.fileName()); 0496 0497 const auto qmvars = setDefaultMKSpec(file); 0498 if (qmvars.isEmpty()) { 0499 QSKIP("Problem querying QMake, skipping test function"); 0500 } 0501 0502 QVERIFY(file.read()); 0503 0504 QCOMPARE(file.variableValues("DEFINES"), QStringList() << "SOME_DEF" 0505 << "SOME_INCLUDE_DEF"); 0506 QCOMPARE(file.variableValues("SOURCES"), QStringList() << "file.cpp" 0507 << "includedFile.cpp"); 0508 QCOMPARE(file.variableValues("QT"), QStringList() << "core" 0509 << "gui" 0510 << "network" 0511 << "webkit"); 0512 // verify that include path was properly propagated 0513 0514 QVERIFY(file.includeDirectories().contains(tempDir.path())); 0515 } 0516 0517 void TestQMakeFile::globbing_data() 0518 { 0519 QTest::addColumn<QStringList>("files"); 0520 QTest::addColumn<QString>("pattern"); 0521 QTest::addColumn<QStringList>("matches"); 0522 0523 QTest::newRow("wildcard-simple") << (QStringList() << QStringLiteral("foo.cpp")) << "*.cpp" << (QStringList() << QStringLiteral("foo.cpp")); 0524 0525 QTest::newRow("wildcard-extended") << (QStringList() << QStringLiteral("foo.cpp") 0526 << QStringLiteral("bar.h") 0527 << QStringLiteral("asdf.cpp")) 0528 << "*.cpp" << (QStringList() << QStringLiteral("foo.cpp") 0529 << QStringLiteral("asdf.cpp")); 0530 0531 QTest::newRow("wildcard-multiple") << (QStringList() << QStringLiteral("foo.cpp") 0532 << QStringLiteral("bar.h") 0533 << QStringLiteral("asdf.cpp")) 0534 << "*.cpp *.h" << (QStringList() << QStringLiteral("foo.cpp") 0535 << QStringLiteral("bar.h") 0536 << QStringLiteral("asdf.cpp")); 0537 0538 QTest::newRow("wildcard-subdir") << (QStringList() << QStringLiteral("foo/bar.cpp") 0539 << QStringLiteral("fooasdf/bar.cpp") 0540 << QStringLiteral("asdf/asdf.cpp")) 0541 << "foo*/*.cpp" << (QStringList() << QStringLiteral("foo/bar.cpp") 0542 << QStringLiteral("fooasdf/bar.cpp")); 0543 0544 QTest::newRow("bracket") << (QStringList() << QStringLiteral("foo1.cpp") 0545 << QStringLiteral("foo2.cpp") 0546 << QStringLiteral("fooX.cpp")) 0547 << "foo[0-9].cpp" << (QStringList() << QStringLiteral("foo1.cpp") 0548 << QStringLiteral("foo2.cpp")); 0549 0550 QTest::newRow("questionmark") << (QStringList() << QStringLiteral("foo1.cpp") 0551 << QStringLiteral("fooX.cpp") 0552 << QStringLiteral("foo.cpp") 0553 << QStringLiteral("fooXY.cpp")) 0554 << "foo?.cpp" << (QStringList() << QStringLiteral("foo1.cpp") 0555 << QStringLiteral("fooX.cpp")); 0556 0557 QTest::newRow("mixed") << (QStringList() << QStringLiteral("foo/asdf/test.cpp") 0558 << QStringLiteral("fooX/asdf1/test.cpp")) 0559 << "foo?/asdf[0-9]/*.cpp" << (QStringList() << QStringLiteral("fooX/asdf1/test.cpp")); 0560 } 0561 0562 void TestQMakeFile::globbing() 0563 { 0564 QFETCH(QStringList, files); 0565 QFETCH(QString, pattern); 0566 QFETCH(QStringList, matches); 0567 0568 QTemporaryDir tempDir; 0569 QDir tempDirDir(tempDir.path()); 0570 QVERIFY(tempDir.isValid()); 0571 0572 for (const auto& file : std::as_const(files)) { 0573 QVERIFY(tempDirDir.mkpath(QFileInfo(file).path())); 0574 QFile f(tempDir.path() + '/' + file); 0575 QVERIFY(f.open(QIODevice::WriteOnly)); 0576 } 0577 0578 QTemporaryFile testFile(tempDir.path() + "/XXXXXX.pro"); 0579 QVERIFY(testFile.open()); 0580 testFile.write(("SOURCES = " + pattern + "\n").toUtf8()); 0581 testFile.close(); 0582 0583 QMakeProjectFile pro(testFile.fileName()); 0584 0585 const auto qmvars = setDefaultMKSpec(pro); 0586 if (qmvars.isEmpty()) { 0587 QSKIP("Problem querying QMake, skipping test function"); 0588 } 0589 0590 QVERIFY(pro.read()); 0591 0592 QStringList actual; 0593 const auto proFiles = pro.files(); 0594 for (auto path : proFiles) { 0595 actual << path.remove(tempDir.path() + '/'); 0596 } 0597 std::sort(actual.begin(), actual.end()); 0598 std::sort(matches.begin(), matches.end()); 0599 QCOMPARE(actual, matches); 0600 } 0601 0602 void TestQMakeFile::benchGlobbing() 0603 { 0604 QTemporaryDir tempDir; 0605 QDir dir(tempDir.path()); 0606 const int folders = 10; 0607 const int files = 100; 0608 for (int i = 0; i < folders; ++i) { 0609 QString folder = QStringLiteral("folder%1").arg(i); 0610 dir.mkdir(folder); 0611 for (int j = 0; j < files; ++j) { 0612 QFile f1(dir.filePath(folder + QStringLiteral("/file%1.cpp").arg(j))); 0613 QVERIFY(f1.open(QIODevice::WriteOnly)); 0614 QFile f2(dir.filePath(folder + QStringLiteral("/file%1.h").arg(j))); 0615 QVERIFY(f2.open(QIODevice::WriteOnly)); 0616 } 0617 } 0618 0619 QTemporaryFile testFile(tempDir.path() + "/XXXXXX.pro"); 0620 QVERIFY(testFile.open()); 0621 testFile.write("SOURCES = fo?der[0-9]/*.cpp\n"); 0622 testFile.close(); 0623 0624 QMakeProjectFile pro(testFile.fileName()); 0625 0626 const auto qmvars = setDefaultMKSpec(pro); 0627 if (qmvars.isEmpty()) { 0628 QSKIP("Problem querying QMake, skipping test function"); 0629 } 0630 0631 QVERIFY(pro.read()); 0632 0633 int found = 0; 0634 QBENCHMARK { found = pro.files().size(); } 0635 0636 QCOMPARE(found, files * folders); 0637 } 0638 0639 void TestQMakeFile::benchGlobbingNoPattern() 0640 { 0641 QTemporaryDir tempDir; 0642 QDir dir(tempDir.path()); 0643 const int folders = 10; 0644 const int files = 100; 0645 for (int i = 0; i < folders; ++i) { 0646 QString folder = QStringLiteral("folder%1").arg(i); 0647 dir.mkdir(folder); 0648 for (int j = 0; j < files; ++j) { 0649 QFile f1(dir.filePath(folder + QStringLiteral("/file%1.cpp").arg(j))); 0650 QVERIFY(f1.open(QIODevice::WriteOnly)); 0651 QFile f2(dir.filePath(folder + QStringLiteral("/file%1.h").arg(j))); 0652 QVERIFY(f2.open(QIODevice::WriteOnly)); 0653 } 0654 } 0655 0656 QTemporaryFile testFile(tempDir.path() + "/XXXXXX.pro"); 0657 QVERIFY(testFile.open()); 0658 testFile.write("SOURCES = folder0/file1.cpp\n"); 0659 testFile.close(); 0660 0661 QMakeProjectFile pro(testFile.fileName()); 0662 0663 const auto qmvars = setDefaultMKSpec(pro); 0664 if (qmvars.isEmpty()) { 0665 QSKIP("Problem querying QMake, skipping test function"); 0666 } 0667 0668 QVERIFY(pro.read()); 0669 0670 int found = 0; 0671 QBENCHMARK { found = pro.files().size(); } 0672 0673 QCOMPARE(found, 1); 0674 } 0675 0676 #include "moc_test_qmakefile.cpp"