Revision control

++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++ // Helper functions for global test cases.
++
++ #ifndef QT_TESTS_SHARED_GLOBAL_H_INCLUDED
++ #define QT_TESTS_SHARED_GLOBAL_H_INCLUDED
++
++ #include <QtCore/QtCore>
++ #include <QtTest/QtTest>
++
++ QStringList qt_tests_shared_global_get_include_path(const QString &makeFile);
++ QHash<QString, QString> qt_tests_shared_global_get_modules(const QString &workDir,
++ const QString &configFile);
++ QStringList qt_tests_shared_global_get_include_paths();
++
++ QStringList qt_tests_shared_run_qmake(const QString &workDir,
++ const QByteArray &proFileConent,
++ QStringList(*makeFileParser)(const QString&));
++ QStringList qt_tests_shared_global_get_export_modules(const QString &makeFile);
++ void qt_tests_shared_filter_module_list(const QString &workDir, QHash<QString, QString> &modules);
++
++ QHash<QString, QString> qt_tests_shared_global_get_modules(const QString &workDir, const QString &configFile)
++ {
++ QHash<QString, QString> modules;
++
++ QFile file(configFile);
++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
++ qWarning("Can't open the config file for global.cfg.");
++ return modules;
++ }
++
++ QXmlStreamReader xml;
++ xml.setDevice(&file);
++
++ while (!xml.atEnd()) {
++ xml.readNext();
++ if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QLatin1String("config")) {
++ xml.readNextStartElement();
++ if (xml.name() == QLatin1String("modules")) {
++ while (!xml.atEnd()) {
++ xml.readNextStartElement();
++ QString modName;
++ QString qtModName;
++ if (xml.name() == QLatin1String("module")) {
++ modName = xml.attributes().value("name").toString().simplified();
++ qtModName = xml.attributes().value("qtname").toString().simplified();
++ if (!modName.isEmpty() && !qtModName.isEmpty())
++ modules[modName] = qtModName;
++ }
++ }
++ }
++ }
++ }
++
++ file.close();
++
++ qt_tests_shared_filter_module_list(workDir, modules);
++
++ qDebug() << "modules keys:" << modules.keys();
++ qDebug() << "modules values:" << modules.values();
++
++ return modules;
++ }
++
++ QByteArray qt_tests_shared_global_get_modules_pro_lines(const QHash<QString, QString> &modules)
++ {
++ QByteArray result;
++ for (const auto & [_, moduleName] : modules.asKeyValueRange()) {
++ QByteArray module = moduleName.toLatin1();
++ result += "qtHaveModule(" + module + ") {\n" +
++ " QT += " + module + "\n" +
++ " MODULES += " + module + "\n" +
++ "}\n";
++ }
++ result += "QMAKE_EXTRA_VARIABLES += MODULES\n";
++ return result;
++ }
++
++ QStringList qt_tests_shared_global_get_include_paths(const QString &workDir,
++ QHash<QString, QString> &modules)
++ {
++ return qt_tests_shared_run_qmake(workDir,
++ qt_tests_shared_global_get_modules_pro_lines(modules),
++ &qt_tests_shared_global_get_include_path);
++ }
++
++ void qt_tests_shared_filter_module_list(const QString &workDir, QHash<QString, QString> &modules)
++ {
++ const QStringList result = qt_tests_shared_run_qmake(workDir,
++ qt_tests_shared_global_get_modules_pro_lines(modules),
++ &qt_tests_shared_global_get_export_modules);
++ const QStringList keys = modules.keys();
++ for (int i = 0; i < keys.size(); ++i) {
++ const QString key = keys.at(i);
++ if (!result.contains(modules[key]))
++ modules.remove(key);
++ }
++ }
++
++ QStringList qt_tests_shared_run_qmake(const QString &workDir,
++ const QByteArray &proFileContent,
++ QStringList(*makeFileParser)(const QString&))
++ {
++ QString proFile = workDir + "/global.pro";
++ QString makeFile = workDir + "/Makefile";
++
++ QStringList result;
++
++ #ifndef QT_NO_PROCESS
++ QFile file(proFile);
++ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
++ qWarning("Can't open the pro file for global.");
++ return result;
++ }
++
++ file.write(proFileContent);
++ file.flush();
++ file.close();
++
++ if (!QDir::setCurrent(workDir)) {
++ qWarning("Change working dir failed.");
++ return result;
++ }
++
++ QString qmakeApp = "qmake";
++
++ QStringList qmakeArgs;
++ qmakeArgs << "-o"
++ << "Makefile";
++
++ QProcess proc;
++ proc.start(qmakeApp, qmakeArgs, QIODevice::ReadOnly);
++ if (!proc.waitForFinished(6000000)) {
++ qWarning() << qmakeApp << qmakeArgs << "in" << workDir << "didn't finish" << proc.errorString();
++ return result;
++ }
++ if (proc.exitCode() != 0) {
++ qWarning() << qmakeApp << qmakeArgs << "in" << workDir << "returned with" << proc.exitCode();
++ qDebug() << proc.readAllStandardError();
++ return result;
++ }
++
++ QFile::remove(proFile);
++
++ result = makeFileParser(makeFile);
++ #ifdef Q_OS_WIN
++ if (result.isEmpty())
++ result = makeFileParser(makeFile + QLatin1String(".Release"));
++ #endif
++
++ QFile::remove(makeFile);
++ #else
++ Q_UNUSED(proFileContent);
++ Q_UNUSED(makeFileParser);
++ #endif // QT_NO_PROCESS
++
++ return result;
++ }
++
++ QStringList qt_tests_shared_global_get_include_path(const QString &makeFile)
++ {
++ QFile file(makeFile);
++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
++ return QStringList();
++
++ QTextStream in(&file);
++ while (!in.atEnd()) {
++ QString line = in.readLine();
++ if (line.contains("=") && line.contains("INCPATH")) {
++ QString relatives = line.mid(line.indexOf("=")+1);
++ QStringList list1 = relatives.split(" ");
++ QStringList list2;
++ for (int i = 0; i < list1.size(); ++i) {
++ if (!list1.at(i).startsWith("-I"))
++ continue;
++ QString rpath = list1.at(i).mid(2);
++ QString apath = "-I" + QDir(rpath).absolutePath();
++ #ifdef Q_OS_WIN
++ apath.replace('\\', '/');
++ #endif
++ list2 << apath;
++ }
++ return list2;
++ }
++ }
++
++ return QStringList();
++ }
++
++ QStringList qt_tests_shared_global_get_export_modules(const QString &makeFile)
++ {
++ QFile file(makeFile);
++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
++ return QStringList();
++ QTextStream in(&file);
++ while (!in.atEnd()) {
++ QString line = in.readLine();
++ int index = line.indexOf('=');
++ if (index > 13 && line.startsWith(QLatin1String("EXPORT_MODULES"))) {
++ QString relatives = line.mid(index + 1);
++ #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
++ return relatives.split(QChar(' '), Qt::SkipEmptyParts);
++ #else
++ return relatives.split(QChar(' '), QString::SkipEmptyParts);
++ #endif
++ }
++ }
++ return QStringList();
++ }
++
++ #endif // QT_TESTS_SHARED_GLOBAL_H_INCLUDED