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
30#include <QtTest/QtTest>
31
32#include <QtCore/QDir>
33#include <QtXmlPatterns/QXmlQuery>
34#include <QtXmlPatterns/QXmlSerializer>
35#include <QtXmlPatterns/QXmlResultItems>
36#include <QtXmlPatterns/QXmlFormatter>
37
38#include "../qxmlquery/MessageSilencer.h"
39#include "../qsimplexmlnodemodel/TestSimpleNodeModel.h"
40
41/*!
42 \class tst_PatternistExamples
43 \internal
44 \since 4.4
45 \brief Verifies examples for Patternist.
46 */
47class tst_PatternistExamples : public QObject
48{
49 Q_OBJECT
50
51private Q_SLOTS:
52 void initTestCase();
53 void checkQueries() const;
54 void checkQueries_data() const;
55 void checkXMLFiles() const;
56 void checkXMLFiles_data() const;
57 void buildSnippets() const;
58
59private:
60 QVector<QDir> m_dirs;
61 QStringList listFiles(const QStringList &patterns) const;
62 enum Constants
63 {
64 XMLFileCount = 12,
65 XQueryFileCount = 52
66 };
67};
68
69void tst_PatternistExamples::initTestCase()
70{
71 m_dirs.append(t: QDir(QLatin1String(SOURCETREE "src/xmlpatterns/doc/snippets/patternist/")));
72 m_dirs.append(t: QDir(QLatin1String(SOURCETREE "examples/xmlpatterns/xquery/globalVariables/")));
73 m_dirs.append(t: QDir(QLatin1String(SOURCETREE "examples/xmlpatterns/filetree/")));
74 m_dirs.append(t: QDir(QLatin1String(SOURCETREE "examples/xmlpatterns/recipes/")));
75 m_dirs.append(t: QDir(QLatin1String(SOURCETREE "examples/xmlpatterns/recipes/files/")));
76
77 for(int i = 0; i < m_dirs.size(); ++i)
78 QVERIFY(m_dirs.at(i).exists());
79}
80
81/*!
82 Returns a QStringList containing absolute filenames that were found in the predefined locations, when
83 filtered through \a pattterns.
84 */
85QStringList tst_PatternistExamples::listFiles(const QStringList &patterns) const
86{
87 QStringList result;
88
89 for(int i = 0; i < m_dirs.size(); ++i)
90 {
91 const QDir &dir = m_dirs.at(i);
92
93 const QStringList files(dir.entryList(nameFilters: patterns));
94 for(int s = 0; s < files.count(); ++s)
95 result += dir.absoluteFilePath(fileName: files.at(i: s));
96 }
97
98 return result;
99}
100
101/*!
102 Check that the queries contains no static errors such as
103 syntax errors.
104 */
105void tst_PatternistExamples::checkQueries() const
106{
107 QFETCH(QString, queryFile);
108
109 QFile file(queryFile);
110 QVERIFY(file.open(QIODevice::ReadOnly));
111
112 QXmlQuery query;
113
114 /* Two queries relies on this binding, so provide it such that we don't get a compile error. */
115 query.bindVariable(localName: QLatin1String("fileToOpen"), value: QVariant(QString::fromLatin1(str: "dummyString")));
116
117 /* This is needed for the recipes example. */
118 query.bindVariable(localName: QLatin1String("inputDocument"), value: QVariant(QString::fromLatin1(str: "dummString")));
119
120 /* This is needed for literalsAndOperators.xq. */
121 query.bindVariable(localName: QLatin1String("date"), value: QVariant(QDate::currentDate()));
122
123 /* These are needed for introExample2.xq. */
124 query.bindVariable(localName: QLatin1String("file"), value: QVariant(QLatin1String("dummy")));
125 query.bindVariable(localName: QLatin1String("publisher"), value: QVariant(QLatin1String("dummy")));
126 query.bindVariable(localName: QLatin1String("year"), value: QVariant(2000));
127
128 /* and filetree/ needs this. */
129 TestSimpleNodeModel nodeModel(query.namePool());
130 query.bindVariable(localName: QLatin1String("exampleDirectory"), value: nodeModel.root());
131
132 query.setQuery(sourceCode: &file, documentURI: queryFile);
133
134 QVERIFY2(query.isValid(), QString::fromLatin1("%1 failed to compile").arg(queryFile).toLatin1().constData());
135}
136
137void tst_PatternistExamples::checkQueries_data() const
138{
139 QTest::addColumn<QString>(name: "queryFile");
140
141 const QStringList queryExamples(listFiles(patterns: QStringList(QLatin1String("*.xq"))));
142
143 QCOMPARE(queryExamples.count(), int(XQueryFileCount));
144
145 for (const QString &q : queryExamples)
146 QTest::newRow(dataTag: q.toLocal8Bit().constData()) << q;
147}
148
149void tst_PatternistExamples::checkXMLFiles() const
150{
151 QFETCH(QString, file);
152
153 QXmlQuery query;
154 /* Wrapping in QUrl ensures it gets formatted as a URI on all platforms. */
155 query.setQuery(sourceCode: QLatin1String("doc('") + QUrl::fromLocalFile(localfile: file).toString() + QLatin1String("')"));
156 QVERIFY(query.isValid());
157
158 /* We don't care about the result, we only want to ensure the files can be parsed. */
159 QByteArray dummy;
160 QBuffer buffer(&dummy);
161 QVERIFY(buffer.open(QIODevice::WriteOnly));
162
163 QXmlSerializer serializer(query, &buffer);
164
165 /* This is the important one. */
166 QVERIFY(query.evaluateTo(&serializer));
167}
168
169void tst_PatternistExamples::checkXMLFiles_data() const
170{
171 QTest::addColumn<QString>(name: "file");
172 QStringList patterns;
173 patterns.append(t: QLatin1String("*.xml"));
174 patterns.append(t: QLatin1String("*.gccxml"));
175 patterns.append(t: QLatin1String("*.svg"));
176 patterns.append(t: QLatin1String("*.ui"));
177 patterns.append(t: QLatin1String("*.html"));
178
179 const QStringList xmlFiles(listFiles(patterns));
180
181 if(xmlFiles.count() != XMLFileCount)
182 qDebug() << "These files were encountered:" << xmlFiles;
183
184 QCOMPARE(xmlFiles.count(), int(XMLFileCount));
185
186 for (const QString &q : xmlFiles)
187 QTest::newRow(dataTag: q.toLocal8Bit().constData()) << q;
188}
189
190/*!
191 Below, we include all the examples and ensure that they build, such that we rule
192 out syntax error and that API changes has propagated into examples.
193
194 An improvement could be to run them, to ensure that they behave as they intend
195 to.
196 */
197
198static QUrl abstractURI()
199{
200 QUrl baseURI;
201 QUrl relative;
202#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qabstracturiresolver.cpp"
203}
204
205class MyValue
206{
207public:
208 MyValue parent() const
209 {
210 return MyValue();
211 }
212};
213
214static MyValue toMyValue(const QXmlNodeModelIndex &)
215{
216 return MyValue();
217}
218
219static QXmlNodeModelIndex toNodeIndex(const MyValue &)
220{
221 return QXmlNodeModelIndex();
222}
223
224class MyTreeModel : public QSimpleXmlNodeModel
225{
226public:
227 MyTreeModel(const QXmlNamePool &np, const QFile &f);
228
229 virtual QUrl documentUri(const QXmlNodeModelIndex&) const
230 {
231 return QUrl();
232 }
233
234 virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex&) const
235 {
236 return QXmlNodeModelIndex::Element;
237 }
238
239 virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex&, const QXmlNodeModelIndex&) const
240 {
241 return QXmlNodeModelIndex::Is;
242 }
243
244 virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex&) const
245 {
246 return QXmlNodeModelIndex();
247 }
248
249 virtual QXmlName name(const QXmlNodeModelIndex&) const
250 {
251 return QXmlName();
252 }
253
254 virtual QVariant typedValue(const QXmlNodeModelIndex&) const
255 {
256 return QVariant();
257 }
258
259 virtual QVector<QXmlNodeModelIndex> attributes(const QXmlNodeModelIndex&) const
260 {
261 return QVector<QXmlNodeModelIndex>();
262 }
263
264 QXmlNodeModelIndex nodeFor(const QString &) const
265 {
266 return QXmlNodeModelIndex();
267 }
268
269 virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const;
270};
271
272/*
273 Exists for linking with at least msvc-2005.
274*/
275MyTreeModel::MyTreeModel(const QXmlNamePool &np, const QFile &) : QSimpleXmlNodeModel(np)
276{
277}
278
279#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qsimplexmlnodemodel.cpp"
280
281class MyMapper
282{
283public:
284 class InputType;
285 enum OutputType
286 {
287 };
288#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qabstractxmlforwarditerator.cpp"
289};
290
291#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qxmlname.cpp"
292
293void tst_PatternistExamples::buildSnippets() const
294{
295 /* We don't run this code, see comment above. */
296 return;
297
298 /* We place a call to this function, such that GCC doesn't emit a warning. */
299 abstractURI();
300
301 {
302 }
303
304 {
305#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qxmlresultitems.cpp"
306 }
307
308 {
309 }
310
311 {
312 QIODevice *myOutputDevice = 0;
313#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qxmlformatter.cpp"
314 }
315
316 {
317 QIODevice *myOutputDevice = 0;
318#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qxmlserializer.cpp"
319 }
320
321 {
322 QXmlNodeModelIndex myInstance;
323 const char **argv = 0;
324 typedef MyTreeModel ChemistryNodeModel;
325#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp"
326 }
327
328 {
329 }
330
331 {
332 QIODevice *myOutputDevice = 0;
333#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp"
334 }
335
336 {
337 QXmlQuery query;
338 QString localName;
339 QVariant value;
340#include "../../../src/xmlpatterns/doc/snippets/code/src_xmlpatterns_api_qxmlquery.cpp"
341 }
342}
343
344QTEST_MAIN(tst_PatternistExamples)
345
346#include "tst_patternistexamples.moc"
347
348// vim: et:ts=4:sw=4:sts=4
349

source code of qtxmlpatterns/tests/auto/patternistexamples/tst_patternistexamples.cpp