1 /*
2     SPDX-FileCopyrightText: 2013 Milian Wolff <mail@milianw.de>
3     SPDX-FileCopyrightText: 2013 Olivier de Gaalon <olivier.jg@gmail.com>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "test_files.h"
9 
10 #include <language/duchain/duchain.h>
11 #include <language/duchain/problem.h>
12 #include <language/codegen/coderepresentation.h>
13 #include <language/backgroundparser/backgroundparser.h>
14 
15 #include <tests/testcore.h>
16 #include <tests/autotestshell.h>
17 #include <tests/json/declarationvalidator.h>
18 
19 #include "testfilepaths.h"
20 
21 //Include all used json tests, otherwise "Test not found"
22 #include <tests/json/jsondeclarationtests.h>
23 #include <tests/json/jsonducontexttests.h>
24 #include <tests/json/jsontypetests.h>
25 #include <interfaces/ilanguagecontroller.h>
26 
27 #include <QTest>
28 
29 // #include "cppjsontests.h"
30 
31 using namespace KDevelop;
32 
QTEST_MAIN(TestFiles)33 QTEST_MAIN(TestFiles)
34 
35 void TestFiles::initTestCase()
36 {
37   AutoTestShell::init({"kdevqmljs"});
38   TestCore::initialize(KDevelop::Core::NoUi);
39   DUChain::self()->disablePersistentStorage();
40   Core::self()->languageController()->backgroundParser()->setDelay(0);
41   CodeRepresentation::setDiskChangesForbidden(true);
42 }
43 
cleanupTestCase()44 void TestFiles::cleanupTestCase()
45 {
46   TestCore::shutdown();
47 }
48 
testQMLCustomComponent()49 void TestFiles::testQMLCustomComponent()
50 {
51     // First parse CustomComponent, so that it is visible and can be used
52     // by CustomComponentUser. Then re-parse CustomComponent and assert that
53     // it has been used.
54     parseAndCheck(TEST_FILES_DIR "/custom_component/CustomComponent.qml", false);
55     parseAndCheck(TEST_FILES_DIR "/custom_component/CustomComponentUser.qml");
56     parseAndCheck(TEST_FILES_DIR "/custom_component/CustomComponent.qml");
57 }
58 
testQMLTypes()59 void TestFiles::testQMLTypes()
60 {
61     parseAndCheck(TEST_FILES_DIR "/qmltypes/AnItem.qml", true);
62 }
63 
testTypeMismatchFalsePositives()64 void TestFiles::testTypeMismatchFalsePositives()
65 {
66     parseAndCheck(TEST_FILES_DIR "/type_mismatch_false_positives/code.js", true);
67 }
68 
testJSUsesBetweenFiles()69 void TestFiles::testJSUsesBetweenFiles()
70 {
71     parseAndCheck(TEST_FILES_DIR "/js_cross_file_uses/js_variable_definition.js", false);
72     parseAndCheck(TEST_FILES_DIR "/js_cross_file_uses/js_variable_use.js");
73     parseAndCheck(TEST_FILES_DIR "/js_cross_file_uses/js_variable_definition.js");
74 }
75 
testNodeJS()76 void TestFiles::testNodeJS()
77 {
78     parseAndCheck(TEST_FILES_DIR "/node_modules/module.js", false); // Ensure that module.js is in the DUChain
79     parseAndCheck(TEST_FILES_DIR "/node.js/module2.js", false);
80     parseAndCheck(TEST_FILES_DIR "/node.js/main.js");
81 }
82 
testFiles_data()83 void TestFiles::testFiles_data()
84 {
85   QTest::addColumn<QString>("fileName");
86   const QString testDirPath = TEST_FILES_DIR;
87   const QStringList files = QDir(testDirPath).entryList(QStringList() << QStringLiteral("*.js") << QStringLiteral("*.qml"), QDir::Files);
88   for (const QString& file : files) {
89     QTest::newRow(file.toUtf8()) << QString(testDirPath + "/" + file);
90   }
91 }
92 
testFiles()93 void TestFiles::testFiles()
94 {
95   QFETCH(QString, fileName);
96   parseAndCheck(fileName);
97 }
98 
parseAndCheck(const QString & fileName,bool check)99 void TestFiles::parseAndCheck(const QString& fileName, bool check)
100 {
101   const IndexedString indexedFileName(fileName);
102   ReferencedTopDUContext top =
103       DUChain::self()->waitForUpdate(indexedFileName, KDevelop::TopDUContext::AllDeclarationsContextsAndUses);
104 
105   while (!ICore::self()->languageController()->backgroundParser()->isIdle()) {
106       QTest::qWait(500);
107   }
108 
109   QVERIFY(top);
110 
111   if (check) {
112     DUChainReadLocker lock;
113     DeclarationValidator validator;
114     top->visit(validator);
115     QVERIFY(validator.testsPassed());
116 
117     if (!top->problems().isEmpty()) {
118         foreach(auto p, top->problems()) {
119             qDebug() << p;
120         }
121     }
122     if (!QTest::currentDataTag() || strcmp("failparse.js", QTest::currentDataTag()) != 0) {
123         QEXPECT_FAIL("plugins.qml", "not working properly yet", Continue);
124         QEXPECT_FAIL("qrc_import.qml", "just making sure it does not crash", Continue);
125         QVERIFY(top->problems().isEmpty());
126     }
127   }
128 }
129