File indexing completed on 2024-05-19 04:41:36

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"