File indexing completed on 2024-06-23 04:36:24

0001 /*
0002     SPDX-FileCopyrightText: 2014 Sergey Kalinichev <kalinichev.so.0@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "test_compilerprovider.h"
0008 
0009 #include <QTest>
0010 #include <QTemporaryFile>
0011 #include <QSignalBlocker>
0012 
0013 #include <tests/autotestshell.h>
0014 #include <tests/testcore.h>
0015 #include <tests/projectsgenerator.h>
0016 
0017 #include <interfaces/iproject.h>
0018 #include <interfaces/iprojectcontroller.h>
0019 #include <project/projectmodel.h>
0020 
0021 #include <serialization/indexedstring.h>
0022 
0023 #include <algorithm>
0024 
0025 #include "../compilerprovider.h"
0026 #include "../settingsmanager.h"
0027 
0028 using namespace KDevelop;
0029 
0030 namespace
0031 {
0032 void testCompilerEntry(SettingsManager* settings, KConfig* config){
0033     auto entries = settings->readPaths(config);
0034     auto entry = entries.first();
0035     auto compilers = settings->provider()->compilers();
0036     Q_ASSERT(!compilers.isEmpty());
0037     bool gccCompilerInstalled = std::any_of(compilers.begin(), compilers.end(), [](const CompilerPointer& compiler){return compiler->name().contains(QLatin1String("gcc"), Qt::CaseInsensitive);});
0038     if (gccCompilerInstalled) {
0039         QCOMPARE(entry.compiler->name(), QStringLiteral("GCC"));
0040     }
0041 }
0042 
0043 void testAddingEntry(SettingsManager* settings, KConfig* config){
0044     auto entries = settings->readPaths(config);
0045     auto entry = entries.first();
0046     auto compilers = settings->provider()->compilers();
0047     ConfigEntry otherEntry;
0048     otherEntry.defines[QStringLiteral("TEST")] = QStringLiteral("lalal");
0049     otherEntry.includes = QStringList() << QStringLiteral("/foo");
0050     otherEntry.path = QStringLiteral("test");
0051     otherEntry.compiler = compilers.first();
0052     entries << otherEntry;
0053     settings->writePaths(config, entries);
0054 
0055     auto readWriteEntries = settings->readPaths(config);
0056     QCOMPARE(readWriteEntries.size(), 2);
0057     QCOMPARE(readWriteEntries.at(0).path, entry.path);
0058     QCOMPARE(readWriteEntries.at(0).defines, entry.defines);
0059     QCOMPARE(readWriteEntries.at(0).includes, entry.includes);
0060     QCOMPARE(readWriteEntries.at(0).compiler->name(), entry.compiler->name());
0061 
0062     QCOMPARE(readWriteEntries.at(1).path, otherEntry.path);
0063     QCOMPARE(readWriteEntries.at(1).defines, otherEntry.defines);
0064     QCOMPARE(readWriteEntries.at(1).includes, otherEntry.includes);
0065     QCOMPARE(readWriteEntries.at(1).compiler->name(), otherEntry.compiler->name());
0066 }
0067 }
0068 
0069 void TestCompilerProvider::initTestCase()
0070 {
0071     AutoTestShell::init({QStringLiteral("kdevdefinesandincludesmanager"), QStringLiteral("KDevCustomBuildSystem"), QStringLiteral("KDevStandardOutputView")});
0072     TestCore::initialize();
0073 }
0074 
0075 void TestCompilerProvider::cleanupTestCase()
0076 {
0077     TestCore::shutdown();
0078 }
0079 
0080 void TestCompilerProvider::testRegisterCompiler()
0081 {
0082     auto settings = SettingsManager::globalInstance();
0083     auto provider = settings->provider();
0084     auto cf = provider->compilerFactories();
0085     for (int i = 0 ; i < cf.size(); ++i) {
0086         auto compiler = cf[i]->createCompiler(QString::number(i), QString::number(i));
0087         QVERIFY(provider->registerCompiler(compiler));
0088         QVERIFY(!provider->registerCompiler(compiler));
0089         QVERIFY(provider->compilers().contains(compiler));
0090     }
0091     QVERIFY(!provider->registerCompiler({}));
0092 }
0093 
0094 void TestCompilerProvider::testCompilerIncludesAndDefines()
0095 {
0096     auto settings = SettingsManager::globalInstance();
0097     auto provider = settings->provider();
0098     const auto& compilers = provider->compilers();
0099     for (auto& c : compilers) {
0100         if (!c->editable() && !c->path().isEmpty()) {
0101             QVERIFY(!c->defines(Utils::Cpp, {}).isEmpty());
0102             QVERIFY(!c->includes(Utils::Cpp, {}).isEmpty());
0103         }
0104     }
0105 
0106     QVERIFY(!provider->defines(nullptr).isEmpty());
0107     QVERIFY(!provider->includes(nullptr).isEmpty());
0108 
0109     auto compiler = provider->compilerForItem(nullptr);
0110     QVERIFY(compiler);
0111     QVERIFY(!compiler->defines(Utils::Cpp, QStringLiteral("-std=c++11")).isEmpty());
0112     QVERIFY(!compiler->includes(Utils::Cpp, QStringLiteral("-std=c++11")).isEmpty());
0113 }
0114 
0115 void TestCompilerProvider::testStorageBackwardsCompatible()
0116 {
0117     auto settings = SettingsManager::globalInstance();
0118     QTemporaryFile file;
0119     QVERIFY(file.open());
0120     QTextStream stream(&file);
0121     stream << "[Buildset]\n" <<
0122       "BuildItems=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x1a\\x00S\\x00i\\x00m\\x00p\\x00l\\x00e\\x00P\\x00r\\x00o\\x00j\\x00e\\x00c\\x00t)\n" <<
0123       "[CustomBuildSystem]\n" << "CurrentConfiguration=BuildConfig0\n" <<
0124       "[CustomDefinesAndIncludes][ProjectPath0]\n" <<
0125       "Defines=\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x0c\\x00_\\x00D\\x00E\\x00B\\x00U\\x00G\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00V\\x00A\\x00R\\x00I\\x00A\\x00B\\x00L\\x00E\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\n\\x00V\\x00A\\x00L\\x00U\\x00E\n" <<
0126       "Includes=\\x00\\x00\\x00\\x01\\x00\\x00\\x00$\\x00/\\x00u\\x00s\\x00r\\x00/\\x00i\\x00n\\x00c\\x00l\\x00u\\x00d\\x00e\\x00/\\x00m\\x00y\\x00d\\x00i\\x00r\n" <<
0127       "Path=/\n" <<
0128       "[CustomDefinesAndIncludes][ProjectPath0][Compiler]\nName=GCC\nPath=gcc\nType=GCC\n";
0129     file.close();
0130     KConfig config(file.fileName());
0131     auto entries = settings->readPaths(&config);
0132     QCOMPARE(entries.size(), 1);
0133     auto entry = entries.first();
0134     Defines defines;
0135     defines[QStringLiteral("VARIABLE")] = QStringLiteral("VALUE");
0136     defines[QStringLiteral("_DEBUG")] = QString();
0137     QCOMPARE(entry.defines, defines);
0138     QStringList includes = QStringList() << QStringLiteral("/usr/include/mydir");
0139     QCOMPARE(entry.includes, includes);
0140     QCOMPARE(entry.path, QString("/"));
0141     QVERIFY(entry.compiler);
0142 
0143     testCompilerEntry(settings, &config);
0144     testAddingEntry(settings, &config);
0145 }
0146 
0147 void TestCompilerProvider::testStorageNewSystem()
0148 {
0149     auto settings = SettingsManager::globalInstance();
0150     QTemporaryFile file;
0151     QVERIFY(file.open());
0152     QTextStream stream(&file);
0153     stream << "[Buildset]\n" <<
0154       "BuildItems=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x1a\\x00S\\x00i\\x00m\\x00p\\x00l\\x00e\\x00P\\x00r\\x00o\\x00j\\x00e\\x00c\\x00t)\n\n" <<
0155       "[CustomBuildSystem]\n" << "CurrentConfiguration=BuildConfig0\n\n" <<
0156       "[CustomDefinesAndIncludes][ProjectPath0]\n" << "Path=/\n\n" <<
0157       "[CustomDefinesAndIncludes][ProjectPath0][Defines]\n" <<
0158       "_DEBUG=\n" <<
0159       "VARIABLE=VALUE\n" <<
0160       "[CustomDefinesAndIncludes][ProjectPath0][Includes]\n" <<
0161       "1=/usr/include/mydir\n" <<
0162       "2=/usr/local/include/mydir\n" <<
0163       "[CustomDefinesAndIncludes][ProjectPath0][Compiler]\nName=GCC\nPath=gcc\nType=GCC\n";
0164     file.close();
0165     KConfig config(file.fileName());
0166     auto entries = settings->readPaths(&config);
0167     QCOMPARE(entries.size(), 1);
0168     auto entry = entries.first();
0169     QCOMPARE(entry.path, QString("/"));
0170     Defines defines;
0171     defines[QStringLiteral("VARIABLE")] = QStringLiteral("VALUE");
0172     defines[QStringLiteral("_DEBUG")] = QString();
0173     QCOMPARE(entry.defines, defines);
0174     QMap<QString, QString> includeMap;
0175     includeMap[QStringLiteral("1")] = QStringLiteral("/usr/include/mydir");
0176     includeMap[QStringLiteral("2")] = QStringLiteral("/usr/local/include/mydir");
0177 
0178     int i = 0;
0179     for (auto& include : qAsConst(includeMap)) {
0180         QCOMPARE(entry.includes.at(i++), include);
0181     }
0182 
0183     testCompilerEntry(settings, &config);
0184     testAddingEntry(settings, &config);
0185 }
0186 
0187 void TestCompilerProvider::testCompilerIncludesAndDefinesForProject()
0188 {
0189     auto project = ProjectsGenerator::GenerateMultiPathProject();
0190     Q_ASSERT(project);
0191 
0192     auto settings = SettingsManager::globalInstance();
0193     auto provider = settings->provider();
0194 
0195     Q_ASSERT(!provider->compilerFactories().isEmpty());
0196     auto compiler = provider->compilerFactories().first()->createCompiler(QStringLiteral("name"), QStringLiteral("path"));
0197 
0198     QVERIFY(provider->registerCompiler(compiler));
0199     QVERIFY(provider->compilers().contains(compiler));
0200 
0201     auto projectCompiler = provider->compilerForItem(project->projectItem());
0202 
0203     QVERIFY(projectCompiler);
0204     QVERIFY(projectCompiler != compiler);
0205 
0206     ProjectBaseItem* mainfile = nullptr;
0207     const auto& fileSet = project->fileSet();
0208     for (const auto& file: fileSet) {
0209         const auto& files = project->filesForPath(file);
0210         for (auto i: files) {
0211             if( i->text() == QLatin1String("main.cpp") ) {
0212                 mainfile = i;
0213                 break;
0214             }
0215         }
0216     }
0217     QVERIFY(mainfile);
0218     auto mainCompiler = provider->compilerForItem(mainfile);
0219     QVERIFY(mainCompiler);
0220     QVERIFY(mainCompiler->name() == projectCompiler->name());
0221 
0222     ConfigEntry entry;
0223     entry.path = QStringLiteral("src/main.cpp");
0224     entry.compiler = compiler;
0225 
0226     auto entries = settings->readPaths(project->projectConfiguration().data());
0227 
0228     entries.append(entry);
0229     settings->writePaths(project->projectConfiguration().data(), entries);
0230 
0231     QVERIFY(provider->compilers().contains(compiler));
0232 
0233     mainCompiler = provider->compilerForItem(mainfile);
0234     QVERIFY(mainCompiler);
0235     QVERIFY(mainCompiler->name() == compiler->name());
0236 
0237     ICore::self()->projectController()->closeProject(project);
0238 }
0239 
0240 QTEST_MAIN(TestCompilerProvider)
0241 
0242 #include "moc_test_compilerprovider.cpp"