1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "../../shared/util.h"
30
31#include <qtest.h>
32#include <QObject>
33#include <QQmlEngine>
34#include <QQmlComponent>
35#include <private/qqmljsdiagnosticmessage_p.h>
36#include <private/qqmldirparser_p.h>
37#include <QDebug>
38
39#include <algorithm>
40
41// Test the parsing of qmldir files
42
43class tst_qqmldirparser : public QQmlDataTest
44{
45 Q_OBJECT
46public:
47 tst_qqmldirparser();
48
49private slots:
50 void parse_data();
51 void parse();
52};
53
54tst_qqmldirparser::tst_qqmldirparser()
55{
56}
57
58namespace {
59
60 QStringList toStringList(const QList<QQmlJS::DiagnosticMessage> &errors)
61 {
62 QStringList rv;
63
64 for (const QQmlJS::DiagnosticMessage &e : errors) {
65 QString errorString = QLatin1String("qmldir");
66 if (e.loc.startLine > 0) {
67 errorString += QLatin1Char(':') + QString::number(e.loc.startLine);
68 if (e.loc.startColumn > 0)
69 errorString += QLatin1Char(':') + QString::number(e.loc.startColumn);
70 }
71
72 errorString += QLatin1String(": ") + e.message;
73 rv.append(t: errorString);
74 }
75
76 return rv;
77 }
78
79 QString toString(const QQmlDirParser::Plugin &p)
80 {
81 return p.name + QLatin1Char('|') + p.path;
82 }
83
84 QStringList toStringList(const QList<QQmlDirParser::Plugin> &plugins)
85 {
86 QStringList rv;
87
88 foreach (const QQmlDirParser::Plugin &p, plugins)
89 rv.append(t: toString(p));
90
91 return rv;
92 }
93
94 QString toString(const QQmlDirParser::Component &c)
95 {
96 return c.typeName + QLatin1Char('|') + c.fileName + QLatin1Char('|')
97 + QString::number(c.majorVersion) + QLatin1Char('|') + QString::number(c.minorVersion)
98 + QLatin1Char('|') + (c.internal ? "true" : "false");
99 }
100
101 QStringList toStringList(const QQmlDirComponents &components)
102 {
103 QStringList rv;
104
105 foreach (const QQmlDirParser::Component &c, components.values())
106 rv.append(t: toString(c));
107
108 std::sort(first: rv.begin(), last: rv.end());
109 return rv;
110 }
111
112 QString toString(const QQmlDirParser::Script &s)
113 {
114 return s.nameSpace + QLatin1Char('|') + s.fileName + QLatin1Char('|')
115 + QString::number(s.majorVersion) + '|' + QString::number(s.minorVersion);
116 }
117
118 QStringList toStringList(const QList<QQmlDirParser::Script> &scripts)
119 {
120 QStringList rv;
121
122 foreach (const QQmlDirParser::Script &s, scripts)
123 rv.append(t: toString(s));
124
125 return rv;
126 }
127}
128
129void tst_qqmldirparser::parse_data()
130{
131 QTest::addColumn<QString>(name: "file");
132 QTest::addColumn<QStringList>(name: "errors");
133 QTest::addColumn<QStringList>(name: "plugins");
134 QTest::addColumn<QStringList>(name: "components");
135 QTest::addColumn<QStringList>(name: "scripts");
136 QTest::addColumn<QStringList>(name: "dependencies");
137 QTest::addColumn<bool>(name: "designerSupported");
138
139 QTest::newRow(dataTag: "empty")
140 << "empty/qmldir"
141 << QStringList()
142 << QStringList()
143 << QStringList()
144 << QStringList()
145 << QStringList()
146 << false;
147
148 QTest::newRow(dataTag: "no-content")
149 << "no-content/qmldir"
150 << QStringList()
151 << QStringList()
152 << QStringList()
153 << QStringList()
154 << QStringList()
155 << false;
156
157 QTest::newRow(dataTag: "one-section")
158 << "one-section/qmldir"
159 << (QStringList() << "qmldir:1: a component declaration requires two or three arguments, but 1 were provided")
160 << QStringList()
161 << QStringList()
162 << QStringList()
163 << QStringList()
164 << false;
165
166 QTest::newRow(dataTag: "four-sections")
167 << "four-sections/qmldir"
168 << (QStringList() << "qmldir:1: a component declaration requires two or three arguments, but 4 were provided")
169 << QStringList()
170 << QStringList()
171 << QStringList()
172 << QStringList()
173 << false;
174
175 QTest::newRow(dataTag: "incomplete-module")
176 << "incomplete-module/qmldir"
177 << (QStringList() << "qmldir:1: module identifier directive requires one argument, but 0 were provided")
178 << QStringList()
179 << QStringList()
180 << QStringList()
181 << QStringList()
182 << false;
183
184 QTest::newRow(dataTag: "excessive-module")
185 << "excessive-module/qmldir"
186 << (QStringList() << "qmldir:1: module identifier directive requires one argument, but 2 were provided")
187 << QStringList()
188 << QStringList()
189 << QStringList()
190 << QStringList()
191 << false;
192
193 QTest::newRow(dataTag: "repeated-module")
194 << "repeated-module/qmldir"
195 << (QStringList() << "qmldir:2: only one module identifier directive may be defined in a qmldir file")
196 << QStringList()
197 << QStringList()
198 << QStringList()
199 << QStringList()
200 << false;
201
202 QTest::newRow(dataTag: "non-first-module")
203 << "non-first-module/qmldir"
204 << (QStringList() << "qmldir:2: module identifier directive must be the first directive in a qmldir file")
205 << (QStringList() << "foo|")
206 << QStringList()
207 << QStringList()
208 << QStringList()
209 << false;
210
211 QTest::newRow(dataTag: "incomplete-plugin")
212 << "incomplete-plugin/qmldir"
213 << (QStringList() << "qmldir:1: plugin directive requires one or two arguments, but 0 were provided")
214 << QStringList()
215 << QStringList()
216 << QStringList()
217 << QStringList()
218 << false;
219
220 QTest::newRow(dataTag: "excessive-plugin")
221 << "excessive-plugin/qmldir"
222 << (QStringList() << "qmldir:1: plugin directive requires one or two arguments, but 3 were provided")
223 << QStringList()
224 << QStringList()
225 << QStringList()
226 << QStringList()
227 << false;
228
229 QTest::newRow(dataTag: "name-plugin")
230 << "name-plugin/qmldir"
231 << QStringList()
232 << (QStringList() << "foo|")
233 << QStringList()
234 << QStringList()
235 << QStringList()
236 << false;
237
238 QTest::newRow(dataTag: "name-path-plugin")
239 << "name-path-plugin/qmldir"
240 << QStringList()
241 << (QStringList() << "foo|bar")
242 << QStringList()
243 << QStringList()
244 << QStringList()
245 << false;
246
247 QTest::newRow(dataTag: "unversioned-component")
248 << "unversioned-component/qmldir"
249 << QStringList()
250 << QStringList()
251 << (QStringList() << "foo|bar|-1|-1|false")
252 << QStringList()
253 << QStringList()
254 << false;
255
256 QTest::newRow(dataTag: "invalid-versioned-component")
257 << "invalid-versioned-component/qmldir"
258 << (QStringList() << "qmldir:1: invalid version 100, expected <major>.<minor>")
259 << QStringList()
260 << QStringList()
261 << QStringList()
262 << QStringList()
263 << false;
264
265 QTest::newRow(dataTag: "versioned-component")
266 << "versioned-component/qmldir"
267 << QStringList()
268 << QStringList()
269 << (QStringList() << "foo|bar|33|66|false")
270 << QStringList()
271 << QStringList()
272 << false;
273
274 QTest::newRow(dataTag: "invalid-versioned-script")
275 << "invalid-versioned-script/qmldir"
276 << (QStringList() << "qmldir:1: invalid version 100, expected <major>.<minor>")
277 << QStringList()
278 << QStringList()
279 << QStringList()
280 << QStringList()
281 << false;
282
283 QTest::newRow(dataTag: "versioned-script")
284 << "versioned-script/qmldir"
285 << QStringList()
286 << QStringList()
287 << QStringList()
288 << (QStringList() << "foo|bar.js|33|66")
289 << QStringList()
290 << false;
291
292 QTest::newRow(dataTag: "multiple")
293 << "multiple/qmldir"
294 << QStringList()
295 << (QStringList() << "PluginA|plugina.so")
296 << (QStringList() << "ComponentA|componenta-1_0.qml|1|0|false"
297 << "ComponentA|componenta-1_5.qml|1|5|false"
298 << "ComponentB|componentb-1_5.qml|1|5|false")
299 << (QStringList() << "ScriptA|scripta-1_0.js|1|0")
300 << QStringList()
301 << false;
302
303 QTest::newRow(dataTag: "designersupported-yes")
304 << "designersupported-yes/qmldir"
305 << QStringList()
306 << (QStringList() << "foo|")
307 << QStringList()
308 << QStringList()
309 << QStringList()
310 << true;
311
312 QTest::newRow(dataTag: "designersupported-no")
313 << "designersupported-no/qmldir"
314 << QStringList()
315 << (QStringList() << "foo|")
316 << QStringList()
317 << QStringList()
318 << QStringList()
319 << false;
320
321 QTest::newRow(dataTag: "invalid-versioned-dependency")
322 << "invalid-versioned-dependency/qmldir"
323 << (QStringList() << "qmldir:1: invalid version 100, expected <major>.<minor>")
324 << QStringList()
325 << QStringList()
326 << QStringList()
327 << QStringList()
328 << false;
329
330 QTest::newRow(dataTag: "dependency")
331 << "dependency/qmldir"
332 << QStringList()
333 << (QStringList() << "foo|")
334 << QStringList()
335 << QStringList()
336 << (QStringList() << "bar||1|0|true")
337 << false;
338
339 QTest::newRow(dataTag: "classname")
340 << "classname/qmldir"
341 << QStringList()
342 << (QStringList() << "qtquick2plugin|")
343 << QStringList()
344 << QStringList()
345 << QStringList()
346 << true;
347}
348
349void tst_qqmldirparser::parse()
350{
351 QFETCH(QString, file);
352 QFETCH(QStringList, errors);
353 QFETCH(QStringList, plugins);
354 QFETCH(QStringList, components);
355 QFETCH(QStringList, scripts);
356 QFETCH(QStringList, dependencies);
357 QFETCH(bool, designerSupported);
358
359 QFile f(testFile(fileName: file));
360 f.open(flags: QIODevice::ReadOnly);
361
362 QQmlDirParser p;
363 p.parse(source: f.readAll());
364
365 if (errors.isEmpty()) {
366 QCOMPARE(p.hasError(), false);
367 } else {
368 QCOMPARE(p.hasError(), true);
369 QCOMPARE(toStringList(p.errors("qmldir")), errors);
370 }
371
372 QCOMPARE(toStringList(p.plugins()), plugins);
373 QCOMPARE(toStringList(p.components()), components);
374 QCOMPARE(toStringList(p.scripts()), scripts);
375 QCOMPARE(toStringList(p.dependencies()), dependencies);
376
377 QCOMPARE(p.designerSupported(), designerSupported);
378
379 p.clear();
380 QVERIFY(p.typeNamespace().isEmpty());
381}
382
383QTEST_MAIN(tst_qqmldirparser)
384
385#include "tst_qqmldirparser.moc"
386

source code of qtdeclarative/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp