1 /*
2     SPDX-FileCopyrightText: 2011 Martin Heide <martin.heide@gmx.net>
3     SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "test_buddies.h"
9 
10 #include <QSplitter>
11 #include <QTest>
12 #include <QLoggingCategory>
13 
14 #include <KParts/MainWindow>
15 #include <KTextEditor/View>
16 #include <KTextEditor/Document>
17 
18 #include <sublime/area.h>
19 #include <sublime/view.h>
20 #include <sublime/mainwindow.h>
21 #include <sublime/container.h>
22 #include <sublime/document.h>
23 #include <sublime/urldocument.h>
24 #include <sublime/controller.h>
25 
26 #include <tests/autotestshell.h>
27 #include <tests/testcore.h>
28 #include <tests/testfile.h>
29 
30 #include <interfaces/icore.h>
31 #include <interfaces/idocumentationcontroller.h>
32 #include <interfaces/iuicontroller.h>
33 #include <interfaces/idocumentcontroller.h>
34 #include <interfaces/ibuddydocumentfinder.h>
35 
36 #include <language/duchain/duchain.h>
37 #include <language/duchain/duchainlock.h>
38 #include <language/duchain/ducontext.h>
39 #include <language/duchain/topducontext.h>
40 #include <language/duchain/duchainutils.h>
41 #include <language/duchain/parsingenvironment.h>
42 
43 using namespace KDevelop;
44 
45 #include <KSharedConfig>
46 #include <QMimeDatabase>
47 #include <QMimeType>
48 
toSublimeWindow(KParts::MainWindow * window)49 Sublime::MainWindow* toSublimeWindow(KParts::MainWindow* window)
50 {
51     auto* ret = qobject_cast<Sublime::MainWindow*>(window);
52     Q_ASSERT(ret);
53     return ret;
54 }
55 
initTestCase()56 void TestBuddies::initTestCase()
57 {
58     QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false\ndefault.debug=true\nkdevelop.plugins.clang.debug=true\n"));
59     AutoTestShell::init({QStringLiteral("kdevclangsupport")});
60     TestCore::initialize();
61     m_documentController = ICore::self()->documentController();
62     m_uiController = ICore::self()->uiController();
63     m_sublimeController = m_uiController->controller();
64 }
65 
cleanupTestCase()66 void TestBuddies::cleanupTestCase()
67 {
68     TestCore::shutdown();
69 }
70 
init()71 void TestBuddies::init()
72 {
73     // Make sure we start with an empty document set
74     QCOMPARE(m_documentController->openDocuments().count(), 0);
75 }
76 
cleanup()77 void TestBuddies::cleanup()
78 {
79     m_documentController->closeAllDocuments();
80 }
81 
verifyFilename(Sublime::View * view,const QString & endOfFilename)82 void TestBuddies::verifyFilename(Sublime::View *view, const QString& endOfFilename)
83 {
84     QVERIFY(view);
85     if (view) {
86         auto* urlDoc = qobject_cast<Sublime::UrlDocument*>(view->document());
87         QVERIFY(urlDoc);
88         if (urlDoc) {
89             qDebug() << urlDoc->url().toLocalFile() << endOfFilename;
90             QVERIFY(urlDoc->url().toLocalFile().endsWith(endOfFilename));
91         }
92     }
93 }
94 
createFile(const QDir & dir,const QString & filename)95 void TestBuddies::createFile(const QDir& dir, const QString& filename)
96 {
97     QFile file(dir.filePath(filename));
98     QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
99     file.close();
100 }
101 
enableBuddies(bool enable)102 void TestBuddies::enableBuddies(bool enable)
103 {
104     {
105         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
106         uiGroup.writeEntry("TabBarArrangeBuddies", (enable ? 1 : 0));
107         uiGroup.sync();
108     }
109     m_sublimeController->loadSettings();
110     QCOMPARE(m_sublimeController->arrangeBuddies(), enable);
111 }
112 
enableOpenAfterCurrent(bool enable)113 void TestBuddies::enableOpenAfterCurrent(bool enable)
114 {
115     {
116         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
117         uiGroup.writeEntry("TabBarOpenAfterCurrent", (enable ? 1 : 0));
118         uiGroup.sync();
119     }
120     m_sublimeController->loadSettings();
121     QCOMPARE(m_sublimeController->openAfterCurrent(), enable);
122 }
123 
testDeclarationDefinitionOrder()124 void TestBuddies::testDeclarationDefinitionOrder()
125 {
126     enableBuddies();
127     enableOpenAfterCurrent();
128 
129     QTemporaryDir tempDirA;
130     QDir dirA(tempDirA.path());
131     createFile(dirA, QStringLiteral("a.cpp"));
132     createFile(dirA, QStringLiteral("b.cpp"));
133     createFile(dirA, QStringLiteral("c.cpp"));
134     createFile(dirA, QStringLiteral("a.h"));
135     createFile(dirA, QStringLiteral("b.h"));
136     createFile(dirA, QStringLiteral("c.h"));
137 
138     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
139     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.h"))));
140     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("c.cpp"))));
141     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
142     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
143     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("c.h"))));
144 
145     Sublime::Area *area = m_uiController->activeArea();
146     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
147     QCOMPARE(m_documentController->openDocuments().count(), 6);
148     //QCOMPARE(m_uiController->documents().count(), 6);
149     QCOMPARE(areaIndex->viewCount(), 6);
150 
151     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.h"));
152     verifyFilename(areaIndex->views().value(1), QStringLiteral("a.cpp"));
153     verifyFilename(areaIndex->views().value(2), QStringLiteral("b.h"));
154     verifyFilename(areaIndex->views().value(3), QStringLiteral("b.cpp"));
155     verifyFilename(areaIndex->views().value(4), QStringLiteral("c.h"));
156     verifyFilename(areaIndex->views().value(5), QStringLiteral("c.cpp"));
157 }
158 
testMultiDotFilenames()159 void TestBuddies::testMultiDotFilenames()
160 {
161     enableBuddies();
162     enableOpenAfterCurrent();
163 
164     QTemporaryDir tempDirA;
165     QDir dirA(tempDirA.path());
166     createFile(dirA, QStringLiteral("a.cpp"));
167     createFile(dirA, QStringLiteral("lots.of.dots.cpp"));
168     createFile(dirA, QStringLiteral("b.cpp"));
169     createFile(dirA, QStringLiteral("lots.of.dots.h"));
170 
171     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
172     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("lots.of.dots.cpp"))));
173     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
174     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("lots.of.dots.h"))));
175 
176     Sublime::Area *area = m_uiController->activeArea();
177     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
178     QCOMPARE(m_documentController->openDocuments().count(), 4);
179     //QCOMPARE(m_sublimeController->documents().count(), 4);
180     QCOMPARE(areaIndex->viewCount(), 4);
181 
182     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
183     verifyFilename(areaIndex->views().value(1), QStringLiteral("lots.of.dots.h"));
184     verifyFilename(areaIndex->views().value(2), QStringLiteral("lots.of.dots.cpp"));
185     verifyFilename(areaIndex->views().value(3), QStringLiteral("b.cpp"));
186 }
187 
188 
testActivation()189 void TestBuddies::testActivation()
190 {
191     enableBuddies();
192     enableOpenAfterCurrent();
193 
194     QTemporaryDir tempDirA;
195     QDir dirA(tempDirA.path());
196     createFile(dirA, QStringLiteral("a.h"));
197     createFile(dirA, QStringLiteral("a.cpp"));
198     createFile(dirA, QStringLiteral("b.cpp"));
199 
200     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
201     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
202     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
203 
204     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
205     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("b.cpp"));
206 }
207 
testDisableBuddies()208 void TestBuddies::testDisableBuddies()
209 {
210 /*  3. Deactivate buddy option, Activate open next to active tab
211        Open a.cpp a.h
212        Verify order (a.cpp a.h)
213        Verify that a.h is activated
214        Activate a.cpp
215        Open b.cpp
216        Verify order (a.cpp b.cpp a.h) */
217     enableBuddies(false);
218     enableOpenAfterCurrent();
219 
220     QTemporaryDir tempDirA;
221     QDir dirA(tempDirA.path());
222     createFile(dirA, QStringLiteral("a.h"));
223     createFile(dirA, QStringLiteral("a.cpp"));
224     createFile(dirA, QStringLiteral("b.cpp"));
225 
226     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
227     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.h"))));
228 
229     Sublime::Area *area = m_uiController->activeArea();
230     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
231 
232     // Buddies disabled => order of tabs should be the order of file opening
233     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
234     verifyFilename(areaIndex->views().value(1), QStringLiteral("a.h"));
235     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
236 
237     //activate a.cpp => new doc should be opened right next to it
238     toSublimeWindow(m_uiController->activeMainWindow())->activateView(areaIndex->views().value(0));
239 
240     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("b.cpp"))));
241     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
242     verifyFilename(areaIndex->views().value(1), QStringLiteral("b.cpp"));
243     verifyFilename(areaIndex->views().value(2), QStringLiteral("a.h"));
244     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("b.cpp"));
245 }
246 
testDisableOpenAfterCurrent()247 void TestBuddies::testDisableOpenAfterCurrent()
248 {
249 /*  5. Enable buddy option, Disable open next to active tab
250        Open foo.h bar.cpp foo.cpp
251        Verify order (foo.h foo.cpp bar.cpp)
252        Verify that foo.cpp is activated
253        Open x.cpp => tab must be placed at the end
254        Verify order (foo.h foo.cpp bar.cpp x.cpp)
255        Verify that x.cpp is activated*/
256     enableBuddies();
257     enableOpenAfterCurrent(false);
258 
259     QTemporaryDir tempDirA;
260     QDir dirA;
261     createFile(dirA, QStringLiteral("foo.h"));
262     createFile(dirA, QStringLiteral("bar.cpp"));
263     createFile(dirA, QStringLiteral("foo.cpp"));
264     createFile(dirA, QStringLiteral("x.cpp"));
265 
266     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.h"))));
267     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.cpp"))));
268     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.cpp"))));
269 
270     Sublime::Area *area = m_uiController->activeArea();
271     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
272 
273     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.h"));
274     verifyFilename(areaIndex->views().value(1), QStringLiteral("foo.cpp"));
275     verifyFilename(areaIndex->views().value(2), QStringLiteral("bar.cpp"));
276     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("foo.cpp"));
277 
278     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("x.cpp"))));
279     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.h"));
280     verifyFilename(areaIndex->views().value(1), QStringLiteral("foo.cpp"));
281     verifyFilename(areaIndex->views().value(2), QStringLiteral("bar.cpp"));
282     verifyFilename(areaIndex->views().value(3), QStringLiteral("x.cpp"));
283     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("x.cpp"));
284 }
285 
testDisableAll()286 void TestBuddies::testDisableAll()
287 {
288 /*  6. Disable buddy option, Disable open next to active tab
289        Open       foo.cpp bar.h foo.h
290        Activate   bar.h
291        Open       bar.cpp
292        Verify order (foo.cpp bar.h foo.h bar.cpp)
293        Verify that bar.cpp is activated*/
294     enableBuddies(false);
295     enableOpenAfterCurrent(false);
296 
297     QTemporaryDir tempDirA;
298     QDir dirA(tempDirA.path());
299     createFile(dirA, QStringLiteral("foo.h"));
300     createFile(dirA, QStringLiteral("foo.cpp"));
301     createFile(dirA, QStringLiteral("bar.h"));
302     createFile(dirA, QStringLiteral("bar.cpp"));
303 
304     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.cpp"))));
305     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.h"))));
306     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("foo.h"))));
307     Sublime::Area *area = m_uiController->activeArea();
308     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
309 
310     //activate bar.h
311     toSublimeWindow(m_uiController->activeMainWindow())->activateView(areaIndex->views().value(1));
312 
313     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("bar.cpp"))));
314 
315     verifyFilename(areaIndex->views().value(0), QStringLiteral("foo.cpp"));
316     verifyFilename(areaIndex->views().value(1), QStringLiteral("bar.h"));
317     verifyFilename(areaIndex->views().value(2), QStringLiteral("foo.h"));
318     verifyFilename(areaIndex->views().value(3), QStringLiteral("bar.cpp"));
319     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("bar.cpp"));
320 }
321 
322 
testMultipleFolders()323 void TestBuddies::testMultipleFolders()
324 {
325 /*  4. Multiple folders:
326        Activate buddy option
327        Open f/a.cpp f/xyz.cpp g/a.h
328        Verify g/a.h is activated
329        Verify order (f/a.cpp f/xyz.cpp g/a.h)*/
330     enableBuddies();
331     enableOpenAfterCurrent();
332 
333     QTemporaryDir tempDirA;
334     QDir dirA(tempDirA.path());
335     createFile(dirA, QStringLiteral("a.cpp"));
336     createFile(dirA, QStringLiteral("x.cpp"));
337     QTemporaryDir tempDirB;
338     QDir dirB(tempDirB.path());
339     createFile(dirB, QStringLiteral("a.h"));  // different folder => not dirA/a.cpp's buddy!
340 
341     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("a.cpp"))));
342     m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("x.cpp"))));
343     m_documentController->openDocument(QUrl::fromLocalFile(dirB.filePath(QStringLiteral("a.h"))));
344 
345     Sublime::Area *area = m_uiController->activeArea();
346     Sublime::AreaIndex* areaIndex = area->indexOf(toSublimeWindow(m_uiController->activeMainWindow())->activeView());
347 
348     verifyFilename(areaIndex->views().value(0), QStringLiteral("a.cpp"));
349     verifyFilename(areaIndex->views().value(1), QStringLiteral("x.cpp"));
350     verifyFilename(areaIndex->views().value(2), QStringLiteral("a.h"));
351     verifyFilename(toSublimeWindow(m_uiController->activeMainWindow())->activeView(), QStringLiteral("a.h"));
352 }
353 
testSplitViewBuddies()354 void TestBuddies::testSplitViewBuddies()
355 {
356     Sublime::MainWindow *pMainWindow = toSublimeWindow(m_uiController->activeMainWindow());
357 
358     enableBuddies();
359     enableOpenAfterCurrent();
360 
361     QTemporaryDir tempDirA;
362     QDir dirA(tempDirA.path());
363     createFile(dirA, QStringLiteral("classA.cpp"));
364     createFile(dirA, QStringLiteral("classA.h"));
365 
366     Sublime::Area *pCodeArea = m_uiController->activeArea();
367     QVERIFY(pCodeArea);
368 
369     IDocument *pClassAHeader = m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("classA.h"))));
370     QVERIFY(pClassAHeader);
371     pMainWindow->activeView()->setObjectName(QStringLiteral("classA.h"));
372 
373     // now, create a split view of the active view (pClassAHeader)
374     Sublime::View *pNewView = pMainWindow->activeView()->document()->createView();
375     pNewView->setObjectName("splitOf" + pMainWindow->activeView()->objectName());
376     pCodeArea->addView(pNewView, pMainWindow->activeView(), Qt::Vertical);
377     // and activate it
378     pMainWindow->activateView(pNewView);
379 
380     // get the current view's container from the mainwindow
381     QWidget *pCentral = pMainWindow->centralWidget();
382     QVERIFY(pCentral);
383     QVERIFY(pCentral->inherits("QWidget"));
384 
385     QWidget *pSplitter = pCentral->findChild<QSplitter*>();
386     QVERIFY(pSplitter);
387     QVERIFY(pSplitter->inherits("QSplitter"));
388 
389     auto *pContainer = pSplitter->findChild<Sublime::Container*>();
390     QVERIFY(pContainer);
391 
392     // check that it only contains pNewView
393     QVERIFY(pContainer->count() == 1 && pContainer->hasWidget(pNewView->widget()));
394 
395     // now open the corresponding definition file, classA.cpp
396     IDocument *pClassAImplem = m_documentController->openDocument(QUrl::fromLocalFile(dirA.filePath(QStringLiteral("classA.cpp"))));
397     QVERIFY(pClassAImplem);
398     pMainWindow->activeView()->setObjectName(QStringLiteral("classA.cpp"));
399 
400     // and check its presence alongside pNewView in pContainer
401     QVERIFY(pContainer->hasWidget(pNewView->widget()));
402     QVERIFY(pContainer->hasWidget(pMainWindow->activeView()->widget()));
403 }
404 
testDUChainBuddy()405 void TestBuddies::testDUChainBuddy()
406 {
407     enableBuddies();
408     enableOpenAfterCurrent();
409 
410     QTemporaryDir dirA;
411 
412     TestFile header(QStringLiteral("void myfunction();\n"), QStringLiteral("h"), nullptr, dirA.path());
413     TestFile other(QStringLiteral("void otherfunction() {}\n"), QStringLiteral("cpp"), nullptr, dirA.path());
414     TestFile source(
415         QStringLiteral("#include \"%1\"\nvoid myfunction() {}\n").arg(header.url().toUrl().fileName()),
416         QStringLiteral("cpp"), nullptr, dirA.path()
417     );
418 
419     header.parseAndWait();
420     other.parseAndWait();
421     source.parseAndWait();
422 
423     // Test IBuddyDocumentFinder::potentialBuddies()
424     QMimeDatabase db;
425     IBuddyDocumentFinder* sourceBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source.url().toUrl()).name());
426     QVector< QUrl > sourceBuddies = sourceBuddyFinder->potentialBuddies(source.url().toUrl());
427     if (!sourceBuddies.contains(header.url().toUrl())) {
428         qDebug() << "got source buddies: " << sourceBuddies;
429         qDebug() << "expected: " << header.url().toUrl();
430         QFAIL("Failed to find buddy for source file");
431     }
432     QVERIFY2(!sourceBuddies.contains(other.url().toUrl()), "source buddy list contains unrelated file");
433 
434     IBuddyDocumentFinder* headerBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(header.url().toUrl()).name());
435     QVector< QUrl > headerBuddies = headerBuddyFinder->potentialBuddies(header.url().toUrl());
436     if (!headerBuddies.contains(source.url().toUrl())) {
437         qDebug() << "got header buddies: " << headerBuddies;
438         qDebug() << "expected: " << source.url().toUrl();
439         QFAIL("Failed to find buddy for header file");
440     }
441     QVERIFY2(!headerBuddies.contains(other.url().toUrl()), "header buddy list contains unrelated file");
442 
443     // Test IBuddyDocumentFinder::areBuddies()
444     QVERIFY(sourceBuddyFinder->areBuddies(source.url().toUrl(), header.url().toUrl()));
445 }
446 
testDUChainBuddyVote()447 void TestBuddies::testDUChainBuddyVote()
448 {
449     /*
450      * Test that the DUChain buddy system finds the buddy file with the most
451      * common declarations/definitions
452      */
453 
454     enableBuddies();
455     enableOpenAfterCurrent();
456 
457     QTemporaryDir dirA;
458 
459     TestFile header(QStringLiteral("void func1();\nvoid func2();\nvoid func3();\n"), QStringLiteral("h"), nullptr, dirA.path());
460     TestFile source1(
461         QStringLiteral("#include \"%1\"\nvoid func1() {}\n").arg(header.url().toUrl().fileName()),
462         QStringLiteral("cpp"), nullptr, dirA.path()
463     );
464     TestFile source2(
465         QStringLiteral("#include \"%1\"\nvoid func2() {}\nvoid func3() {}\n").arg(header.url().toUrl().fileName()),
466         QStringLiteral("cpp"), nullptr, dirA.path()
467     );
468 
469     // -> buddy(header) should resolve to source2
470 
471     header.parseAndWait();
472     source1.parseAndWait();
473     source2.parseAndWait();
474 
475     // Test IBuddyDocumentFinder::potentialBuddies()
476     QMimeDatabase db;
477     IBuddyDocumentFinder* sourceBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source1.url().toUrl()).name());
478     QVector< QUrl > sourceBuddies = sourceBuddyFinder->potentialBuddies(source1.url().toUrl());
479     if (!sourceBuddies.contains(header.url().toUrl())) {
480         qDebug() << "got source buddies: " << sourceBuddies;
481         qDebug() << "expected: " << header.url().toUrl();
482         QFAIL("Failed to find buddy for source file");
483     }
484 
485     IBuddyDocumentFinder* source2BuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(source2.url().toUrl()).name());
486     QVector< QUrl > source2Buddies = source2BuddyFinder->potentialBuddies(source2.url().toUrl());
487     if (!source2Buddies.contains(header.url().toUrl())) {
488         qDebug() << "got source2 buddies: " << source2Buddies;
489         qDebug() << "expected: " << header.url().toUrl();
490         QFAIL("Failed to find buddy for source2 file");
491     }
492 
493     IBuddyDocumentFinder* headerBuddyFinder = IBuddyDocumentFinder::finderForMimeType(db.mimeTypeForUrl(header.url().toUrl()).name());
494     QVector< QUrl > headerBuddies = headerBuddyFinder->potentialBuddies(header.url().toUrl());
495     if (!headerBuddies.contains(source2.url().toUrl())) {
496         qDebug() << "got header buddies: " << headerBuddies;
497         qDebug() << "expected: " << source2.url().toUrl();
498         QFAIL("Failed to find buddy for header file");
499     }
500     QVERIFY2(!headerBuddies.contains(source1.url().toUrl()), "header buddy list contains weaker file");
501 }
502 
503 QTEST_MAIN(TestBuddies)
504