File indexing completed on 2024-05-12 04:39:15

0001 /*
0002     SPDX-FileCopyrightText: 2011 Martin Heide <martin.heide@gmx.net>
0003     SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "test_buddies.h"
0009 
0010 #include <QSplitter>
0011 #include <QTest>
0012 #include <QLoggingCategory>
0013 
0014 #include <KParts/MainWindow>
0015 #include <KTextEditor/View>
0016 #include <KTextEditor/Document>
0017 
0018 #include <sublime/area.h>
0019 #include <sublime/view.h>
0020 #include <sublime/mainwindow.h>
0021 #include <sublime/container.h>
0022 #include <sublime/document.h>
0023 #include <sublime/urldocument.h>
0024 #include <sublime/controller.h>
0025 
0026 #include <tests/autotestshell.h>
0027 #include <tests/testcore.h>
0028 #include <tests/testfile.h>
0029 
0030 #include <interfaces/icore.h>
0031 #include <interfaces/idocumentationcontroller.h>
0032 #include <interfaces/iuicontroller.h>
0033 #include <interfaces/idocumentcontroller.h>
0034 #include <interfaces/ibuddydocumentfinder.h>
0035 
0036 #include <language/duchain/duchain.h>
0037 #include <language/duchain/duchainlock.h>
0038 #include <language/duchain/ducontext.h>
0039 #include <language/duchain/topducontext.h>
0040 #include <language/duchain/duchainutils.h>
0041 #include <language/duchain/parsingenvironment.h>
0042 
0043 using namespace KDevelop;
0044 
0045 #include <KSharedConfig>
0046 #include <QMimeDatabase>
0047 #include <QMimeType>
0048 
0049 Sublime::MainWindow* toSublimeWindow(KParts::MainWindow* window)
0050 {
0051     auto* ret = qobject_cast<Sublime::MainWindow*>(window);
0052     Q_ASSERT(ret);
0053     return ret;
0054 }
0055 
0056 void TestBuddies::initTestCase()
0057 {
0058     QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false\ndefault.debug=true\nkdevelop.plugins.clang.debug=true\n"));
0059     AutoTestShell::init({QStringLiteral("kdevclangsupport")});
0060     TestCore::initialize();
0061     m_documentController = ICore::self()->documentController();
0062     m_uiController = ICore::self()->uiController();
0063     m_sublimeController = m_uiController->controller();
0064 }
0065 
0066 void TestBuddies::cleanupTestCase()
0067 {
0068     TestCore::shutdown();
0069 }
0070 
0071 void TestBuddies::init()
0072 {
0073     // Make sure we start with an empty document set
0074     QCOMPARE(m_documentController->openDocuments().count(), 0);
0075 }
0076 
0077 void TestBuddies::cleanup()
0078 {
0079     m_documentController->closeAllDocuments();
0080 }
0081 
0082 void TestBuddies::verifyFilename(Sublime::View *view, const QString& endOfFilename)
0083 {
0084     QVERIFY(view);
0085     if (view) {
0086         auto* urlDoc = qobject_cast<Sublime::UrlDocument*>(view->document());
0087         QVERIFY(urlDoc);
0088         if (urlDoc) {
0089             qDebug() << urlDoc->url().toLocalFile() << endOfFilename;
0090             QVERIFY(urlDoc->url().toLocalFile().endsWith(endOfFilename));
0091         }
0092     }
0093 }
0094 
0095 void TestBuddies::createFile(const QDir& dir, const QString& filename)
0096 {
0097     QFile file(dir.filePath(filename));
0098     QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
0099     file.close();
0100 }
0101 
0102 void TestBuddies::enableBuddies(bool enable)
0103 {
0104     {
0105         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
0106         uiGroup.writeEntry("TabBarArrangeBuddies", (enable ? 1 : 0));
0107         uiGroup.sync();
0108     }
0109     m_sublimeController->loadSettings();
0110     QCOMPARE(m_sublimeController->arrangeBuddies(), enable);
0111 }
0112 
0113 void TestBuddies::enableOpenAfterCurrent(bool enable)
0114 {
0115     {
0116         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
0117         uiGroup.writeEntry("TabBarOpenAfterCurrent", (enable ? 1 : 0));
0118         uiGroup.sync();
0119     }
0120     m_sublimeController->loadSettings();
0121     QCOMPARE(m_sublimeController->openAfterCurrent(), enable);
0122 }
0123 
0124 void TestBuddies::testDeclarationDefinitionOrder()
0125 {
0126     enableBuddies();
0127     enableOpenAfterCurrent();
0128 
0129     QTemporaryDir tempDirA;
0130     QDir dirA(tempDirA.path());
0131     createFile(dirA, QStringLiteral("a.cpp"));
0132     createFile(dirA, QStringLiteral("b.cpp"));
0133     createFile(dirA, QStringLiteral("c.cpp"));
0134     createFile(dirA, QStringLiteral("a.h"));
0135     createFile(dirA, QStringLiteral("b.h"));
0136     createFile(dirA, QStringLiteral("c.h"));
0137 
0138     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
0139     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.h"))));
0140     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("c.cpp"))));
0141     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
0142     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
0143     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("c.h"))));
0144 
0145     Sublime::Area *area = m_uiController->activeArea();
0146     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0147     QCOMPARE(m_documentController->openDocuments().count(), 6);
0148     //QCOMPARE(m_uiController->documents().count(), 6);
0149     QCOMPARE(areaIndex->viewCount(), 6);
0150 
0151     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.h"));
0152     verifyFilename(areaIndex->views().value(1), QStringLiteral("a.cpp"));
0153     verifyFilename(areaIndex->views().value(2), QStringLiteral("b.h"));
0154     verifyFilename(areaIndex->views().value(3), QStringLiteral("b.cpp"));
0155     verifyFilename(areaIndex->views().value(4), QStringLiteral("c.h"));
0156     verifyFilename(areaIndex->views().value(5), QStringLiteral("c.cpp"));
0157 }
0158 
0159 void TestBuddies::testMultiDotFilenames()
0160 {
0161     enableBuddies();
0162     enableOpenAfterCurrent();
0163 
0164     QTemporaryDir tempDirA;
0165     QDir dirA(tempDirA.path());
0166     createFile(dirA, QStringLiteral("a.cpp"));
0167     createFile(dirA, QStringLiteral("lots.of.dots.cpp"));
0168     createFile(dirA, QStringLiteral("b.cpp"));
0169     createFile(dirA, QStringLiteral("lots.of.dots.h"));
0170 
0171     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
0172     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("lots.of.dots.cpp"))));
0173     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
0174     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("lots.of.dots.h"))));
0175 
0176     Sublime::Area *area = m_uiController->activeArea();
0177     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0178     QCOMPARE(m_documentController->openDocuments().count(), 4);
0179     //QCOMPARE(m_sublimeController->documents().count(), 4);
0180     QCOMPARE(areaIndex->viewCount(), 4);
0181 
0182     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
0183     verifyFilename(areaIndex->views().value(1), QStringLiteral("lots.of.dots.h"));
0184     verifyFilename(areaIndex->views().value(2), QStringLiteral("lots.of.dots.cpp"));
0185     verifyFilename(areaIndex->views().value(3), QStringLiteral("b.cpp"));
0186 }
0187 
0188 
0189 void TestBuddies::testActivation()
0190 {
0191     enableBuddies();
0192     enableOpenAfterCurrent();
0193 
0194     QTemporaryDir tempDirA;
0195     QDir dirA(tempDirA.path());
0196     createFile(dirA, QStringLiteral("a.h"));
0197     createFile(dirA, QStringLiteral("a.cpp"));
0198     createFile(dirA, QStringLiteral("b.cpp"));
0199 
0200     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
0201     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
0202     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
0203 
0204     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
0205     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("b.cpp"));
0206 }
0207 
0208 void TestBuddies::testDisableBuddies()
0209 {
0210 /*  3. Deactivate buddy option, Activate open next to active tab
0211        Open a.cpp a.h
0212        Verify order (a.cpp a.h)
0213        Verify that a.h is activated
0214        Activate a.cpp
0215        Open b.cpp
0216        Verify order (a.cpp b.cpp a.h) */
0217     enableBuddies(false);
0218     enableOpenAfterCurrent();
0219 
0220     QTemporaryDir tempDirA;
0221     QDir dirA(tempDirA.path());
0222     createFile(dirA, QStringLiteral("a.h"));
0223     createFile(dirA, QStringLiteral("a.cpp"));
0224     createFile(dirA, QStringLiteral("b.cpp"));
0225 
0226     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
0227     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
0228 
0229     Sublime::Area *area = m_uiController->activeArea();
0230     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0231 
0232     // Buddies disabled => order of tabs should be the order of file opening
0233     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
0234     verifyFilename(areaIndex->views().value(1), QStringLiteral("a.h"));
0235     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
0236 
0237     //activate a.cpp => new doc should be opened right next to it
0238     toSublimeWindow(m_uiController->activeMainWindow())->activateView(areaIndex->views().value(0));
0239 
0240     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
0241     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
0242     verifyFilename(areaIndex->views().value(1), QStringLiteral("b.cpp"));
0243     verifyFilename(areaIndex->views().value(2), QStringLiteral("a.h"));
0244     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("b.cpp"));
0245 }
0246 
0247 void TestBuddies::testDisableOpenAfterCurrent()
0248 {
0249 /*  5. Enable buddy option, Disable open next to active tab
0250        Open foo.h bar.cpp foo.cpp
0251        Verify order (foo.h foo.cpp bar.cpp)
0252        Verify that foo.cpp is activated
0253        Open x.cpp => tab must be placed at the end
0254        Verify order (foo.h foo.cpp bar.cpp x.cpp)
0255        Verify that x.cpp is activated*/
0256     enableBuddies();
0257     enableOpenAfterCurrent(false);
0258 
0259     QTemporaryDir tempDirA;
0260     QDir dirA;
0261     createFile(dirA, QStringLiteral("foo.h"));
0262     createFile(dirA, QStringLiteral("bar.cpp"));
0263     createFile(dirA, QStringLiteral("foo.cpp"));
0264     createFile(dirA, QStringLiteral("x.cpp"));
0265 
0266     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.h"))));
0267     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.cpp"))));
0268     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.cpp"))));
0269 
0270     Sublime::Area *area = m_uiController->activeArea();
0271     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0272 
0273     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.h"));
0274     verifyFilename(areaIndex->views().value(1), QStringLiteral("foo.cpp"));
0275     verifyFilename(areaIndex->views().value(2), QStringLiteral("bar.cpp"));
0276     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("foo.cpp"));
0277 
0278     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("x.cpp"))));
0279     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.h"));
0280     verifyFilename(areaIndex->views().value(1), QStringLiteral("foo.cpp"));
0281     verifyFilename(areaIndex->views().value(2), QStringLiteral("bar.cpp"));
0282     verifyFilename(areaIndex->views().value(3), QStringLiteral("x.cpp"));
0283     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("x.cpp"));
0284 }
0285 
0286 void TestBuddies::testDisableAll()
0287 {
0288 /*  6. Disable buddy option, Disable open next to active tab
0289        Open       foo.cpp bar.h foo.h
0290        Activate   bar.h
0291        Open       bar.cpp
0292        Verify order (foo.cpp bar.h foo.h bar.cpp)
0293        Verify that bar.cpp is activated*/
0294     enableBuddies(false);
0295     enableOpenAfterCurrent(false);
0296 
0297     QTemporaryDir tempDirA;
0298     QDir dirA(tempDirA.path());
0299     createFile(dirA, QStringLiteral("foo.h"));
0300     createFile(dirA, QStringLiteral("foo.cpp"));
0301     createFile(dirA, QStringLiteral("bar.h"));
0302     createFile(dirA, QStringLiteral("bar.cpp"));
0303 
0304     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.cpp"))));
0305     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.h"))));
0306     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.h"))));
0307     Sublime::Area *area = m_uiController->activeArea();
0308     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0309 
0310     //activate bar.h
0311     toSublimeWindow(m_uiController->activeMainWindow())->activateView(areaIndex->views().value(1));
0312 
0313     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.cpp"))));
0314 
0315     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.cpp"));
0316     verifyFilename(areaIndex->views().value(1), QStringLiteral("bar.h"));
0317     verifyFilename(areaIndex->views().value(2), QStringLiteral("foo.h"));
0318     verifyFilename(areaIndex->views().value(3), QStringLiteral("bar.cpp"));
0319     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("bar.cpp"));
0320 }
0321 
0322 
0323 void TestBuddies::testMultipleFolders()
0324 {
0325 /*  4. Multiple folders:
0326        Activate buddy option
0327        Open f/a.cpp f/xyz.cpp g/a.h
0328        Verify g/a.h is activated
0329        Verify order (f/a.cpp f/xyz.cpp g/a.h)*/
0330     enableBuddies();
0331     enableOpenAfterCurrent();
0332 
0333     QTemporaryDir tempDirA;
0334     QDir dirA(tempDirA.path());
0335     createFile(dirA, QStringLiteral("a.cpp"));
0336     createFile(dirA, QStringLiteral("x.cpp"));
0337     QTemporaryDir tempDirB;
0338     QDir dirB(tempDirB.path());
0339     createFile(dirB, QStringLiteral("a.h"));  // different folder => not dirA/a.cpp's buddy!
0340 
0341     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
0342     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("x.cpp"))));
0343     m_documentController->openDocument(QUrl::fromLocalFile(dirB.filePath(QStringLiteral("a.h"))));
0344 
0345     Sublime::Area *area = m_uiController->activeArea();
0346     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
0347 
0348     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
0349     verifyFilename(areaIndex->views().value(1), QStringLiteral("x.cpp"));
0350     verifyFilename(areaIndex->views().value(2), QStringLiteral("a.h"));
0351     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
0352 }
0353 
0354 void TestBuddies::testSplitViewBuddies()
0355 {
0356     Sublime::MainWindow *pMainWindow = toSublimeWindow(m_uiController->activeMainWindow());
0357 
0358     enableBuddies();
0359     enableOpenAfterCurrent();
0360 
0361     QTemporaryDir tempDirA;
0362     QDir dirA(tempDirA.path());
0363     createFile(dirA, QStringLiteral("classA.cpp"));
0364     createFile(dirA, QStringLiteral("classA.h"));
0365 
0366     Sublime::Area *pCodeArea = m_uiController->activeArea();
0367     QVERIFY(pCodeArea);
0368 
0369     IDocument *pClassAHeader = m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("classA.h"))));
0370     QVERIFY(pClassAHeader);
0371     pMainWindow->activeView()->setObjectName(QStringLiteral("classA.h"));
0372 
0373     // now, create a split view of the active view (pClassAHeader)
0374     Sublime::View *pNewView = pMainWindow->activeView()->document()->createView();
0375     pNewView->setObjectName("splitOf" + pMainWindow->activeView()->objectName());
0376     pCodeArea->addView(pNewView, pMainWindow->activeView(), Qt::Vertical);
0377     // and activate it
0378     pMainWindow->activateView(pNewView);
0379 
0380     // get the current view's container from the mainwindow
0381     QWidget *pCentral = pMainWindow->centralWidget();
0382     QVERIFY(pCentral);
0383     QVERIFY(pCentral->inherits("QWidget"));
0384 
0385     QWidget *pSplitter = pCentral->findChild<QSplitter*>();
0386     QVERIFY(pSplitter);
0387     QVERIFY(pSplitter->inherits("QSplitter"));
0388 
0389     auto *pContainer = pSplitter->findChild<Sublime::Container*>();
0390     QVERIFY(pContainer);
0391 
0392     // check that it only contains pNewView
0393     QVERIFY(pContainer->count() == 1 && pContainer->hasWidget(pNewView->widget()));
0394 
0395     // now open the corresponding definition file, classA.cpp
0396     IDocument *pClassAImplem = m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("classA.cpp"))));
0397     QVERIFY(pClassAImplem);
0398     pMainWindow->activeView()->setObjectName(QStringLiteral("classA.cpp"));
0399 
0400     // and check its presence alongside pNewView in pContainer
0401     QVERIFY(pContainer->hasWidget(pNewView->widget()));
0402     QVERIFY(pContainer->hasWidget(pMainWindow->activeView()->widget()));
0403 }
0404 
0405 void TestBuddies::testDUChainBuddy()
0406 {
0407     enableBuddies();
0408     enableOpenAfterCurrent();
0409 
0410     QTemporaryDir dirA;
0411 
0412     TestFile header(QStringLiteral("void myfunction();\n"), QStringLiteral("h"), nullptr, dirA.path());
0413     TestFile other(QStringLiteral("void otherfunction() {}\n"), QStringLiteral("cpp"), nullptr, dirA.path());
0414     TestFile source(
0415         QStringLiteral("#include \"%1\"\nvoid myfunction() {}\n").arg(header.url().toUrl().fileName()),
0416         QStringLiteral("cpp"), nullptr, dirA.path()
0417     );
0418 
0419     header.parseAndWait();
0420     other.parseAndWait();
0421     source.parseAndWait();
0422 
0423     // Test IBuddyDocumentFinder::potentialBuddies()
0424     QMimeDatabase db;
0425     IBuddyDocumentFinder* sourceBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source.url().toUrl()).name());
0426     QVector< QUrl > sourceBuddies = sourceBuddyFinder->potentialBuddies(source.url().toUrl());
0427     if (!sourceBuddies.contains(header.url().toUrl())) {
0428         qDebug() << "got source buddies: " << sourceBuddies;
0429         qDebug() << "expected: " << header.url().toUrl();
0430         QFAIL("Failed to find buddy for source file");
0431     }
0432     QVERIFY2(!sourceBuddies.contains(other.url().toUrl()), "source buddy list contains unrelated file");
0433 
0434     IBuddyDocumentFinder* headerBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(header.url().toUrl()).name());
0435     QVector< QUrl > headerBuddies = headerBuddyFinder->potentialBuddies(header.url().toUrl());
0436     if (!headerBuddies.contains(source.url().toUrl())) {
0437         qDebug() << "got header buddies: " << headerBuddies;
0438         qDebug() << "expected: " << source.url().toUrl();
0439         QFAIL("Failed to find buddy for header file");
0440     }
0441     QVERIFY2(!headerBuddies.contains(other.url().toUrl()), "header buddy list contains unrelated file");
0442 
0443     // Test IBuddyDocumentFinder::areBuddies()
0444     QVERIFY(sourceBuddyFinder->areBuddies(source.url().toUrl(), header.url().toUrl()));
0445 }
0446 
0447 void TestBuddies::testDUChainBuddyVote()
0448 {
0449     /*
0450      * Test that the DUChain buddy system finds the buddy file with the most
0451      * common declarations/definitions
0452      */
0453 
0454     enableBuddies();
0455     enableOpenAfterCurrent();
0456 
0457     QTemporaryDir dirA;
0458 
0459     TestFile header(QStringLiteral("void func1();\nvoid func2();\nvoid func3();\n"), QStringLiteral("h"), nullptr, dirA.path());
0460     TestFile source1(
0461         QStringLiteral("#include \"%1\"\nvoid func1() {}\n").arg(header.url().toUrl().fileName()),
0462         QStringLiteral("cpp"), nullptr, dirA.path()
0463     );
0464     TestFile source2(
0465         QStringLiteral("#include \"%1\"\nvoid func2() {}\nvoid func3() {}\n").arg(header.url().toUrl().fileName()),
0466         QStringLiteral("cpp"), nullptr, dirA.path()
0467     );
0468 
0469     // -> buddy(header) should resolve to source2
0470 
0471     header.parseAndWait();
0472     source1.parseAndWait();
0473     source2.parseAndWait();
0474 
0475     // Test IBuddyDocumentFinder::potentialBuddies()
0476     QMimeDatabase db;
0477     IBuddyDocumentFinder* sourceBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source1.url().toUrl()).name());
0478     QVector< QUrl > sourceBuddies = sourceBuddyFinder->potentialBuddies(source1.url().toUrl());
0479     if (!sourceBuddies.contains(header.url().toUrl())) {
0480         qDebug() << "got source buddies: " << sourceBuddies;
0481         qDebug() << "expected: " << header.url().toUrl();
0482         QFAIL("Failed to find buddy for source file");
0483     }
0484 
0485     IBuddyDocumentFinder* source2BuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source2.url().toUrl()).name());
0486     QVector< QUrl > source2Buddies = source2BuddyFinder->potentialBuddies(source2.url().toUrl());
0487     if (!source2Buddies.contains(header.url().toUrl())) {
0488         qDebug() << "got source2 buddies: " << source2Buddies;
0489         qDebug() << "expected: " << header.url().toUrl();
0490         QFAIL("Failed to find buddy for source2 file");
0491     }
0492 
0493     IBuddyDocumentFinder* headerBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(header.url().toUrl()).name());
0494     QVector< QUrl > headerBuddies = headerBuddyFinder->potentialBuddies(header.url().toUrl());
0495     if (!headerBuddies.contains(source2.url().toUrl())) {
0496         qDebug() << "got header buddies: " << headerBuddies;
0497         qDebug() << "expected: " << source2.url().toUrl();
0498         QFAIL("Failed to find buddy for header file");
0499     }
0500     QVERIFY2(!headerBuddies.contains(source1.url().toUrl()), "header buddy list contains weaker file");
0501 }
0502 
0503 QTEST_MAIN(TestBuddies)
0504 
0505 #include "moc_test_buddies.cpp"