1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #ifdef QTEST_XMLPATTERNS
46
47 #include <QtCore/QDir>
48 #include <QtXmlPatterns/QXmlQuery>
49 #include <QtXmlPatterns/QXmlSerializer>
50 #include <QtXmlPatterns/QXmlResultItems>
51 #include <QtXmlPatterns/QXmlFormatter>
52
53 #include "../qxmlquery/MessageSilencer.h"
54 #include "../qsimplexmlnodemodel/TestSimpleNodeModel.h"
55
56 /*!
57 \class tst_PatternistExamples
58 \internal
59 \since 4.4
60 \brief Verifies examples for Patternist.
61 */
62 class tst_PatternistExamples : public QObject
63 {
64 Q_OBJECT
65
66 private Q_SLOTS:
67 void initTestCase();
68 void checkQueries() const;
69 void checkQueries_data() const;
70 void checkXMLFiles() const;
71 void checkXMLFiles_data() const;
72 void buildSnippets() const;
73
74 private:
75 QVector<QDir> m_dirs;
76 QStringList listFiles(const QStringList &patterns) const;
77 enum Constants
78 {
79 XMLFileCount = 12,
80 XQueryFileCount = 52
81 };
82 };
83
initTestCase()84 void tst_PatternistExamples::initTestCase()
85 {
86 #ifndef Q_OS_WINCE
87 m_dirs.append(QDir(QLatin1String("../../../doc/src/snippets/patternist/")));
88 m_dirs.append(QDir(QLatin1String("../../../examples/xmlpatterns/xquery/globalVariables/")));
89 m_dirs.append(QDir(QLatin1String("../../../examples/xmlpatterns/filetree/")));
90 m_dirs.append(QDir(QLatin1String("../../../examples/xmlpatterns/recipes/")));
91 m_dirs.append(QDir(QLatin1String("../../../examples/xmlpatterns/recipes/files/")));
92 #else
93 m_dirs.append(QDir(QLatin1String("patternist/")));
94 m_dirs.append(QDir(QLatin1String("globalVariables/")));
95 m_dirs.append(QDir(QLatin1String("filetree/")));
96 m_dirs.append(QDir(QLatin1String("recipes/")));
97 m_dirs.append(QDir(QLatin1String("recipes/files/")));
98 #endif
99 for(int i = 0; i < m_dirs.size(); ++i)
100 QVERIFY(m_dirs.at(i).exists());
101 }
102
103 /*!
104 Returns a QStringList containing absolute filenames that were found in the predefined locations, when
105 filtered through \a pattterns.
106 */
listFiles(const QStringList & patterns) const107 QStringList tst_PatternistExamples::listFiles(const QStringList &patterns) const
108 {
109 QStringList result;
110
111 for(int i = 0; i < m_dirs.size(); ++i)
112 {
113 const QDir &dir = m_dirs.at(i);
114
115 const QStringList files(dir.entryList(patterns));
116 for(int s = 0; s < files.count(); ++s)
117 result += dir.absoluteFilePath(files.at(s));
118 }
119
120 return result;
121 }
122
123 /*!
124 Check that the queries contains no static errors such as
125 syntax errors.
126 */
checkQueries() const127 void tst_PatternistExamples::checkQueries() const
128 {
129 QFETCH(QString, queryFile);
130
131 QFile file(queryFile);
132 QVERIFY(file.open(QIODevice::ReadOnly));
133
134 QXmlQuery query;
135
136 /* Two queries relies on this binding, so provide it such that we don't get a compile error. */
137 query.bindVariable(QLatin1String("fileToOpen"), QVariant(QString::fromLatin1("dummyString")));
138
139 /* This is needed for the recipes example. */
140 query.bindVariable(QLatin1String("inputDocument"), QVariant(QString::fromLatin1("dummString")));
141
142 /* This is needed for literalsAndOperators.xq. */
143 query.bindVariable(QLatin1String("date"), QVariant(QDate::currentDate()));
144
145 /* These are needed for introExample2.xq. */
146 query.bindVariable(QLatin1String("file"), QVariant(QLatin1String("dummy")));
147 query.bindVariable(QLatin1String("publisher"), QVariant(QLatin1String("dummy")));
148 query.bindVariable(QLatin1String("year"), QVariant(2000));
149
150 /* and filetree/ needs this. */
151 TestSimpleNodeModel nodeModel(query.namePool());
152 query.bindVariable(QLatin1String("exampleDirectory"), nodeModel.root());
153
154 query.setQuery(&file, queryFile);
155
156 QVERIFY2(query.isValid(), QString::fromLatin1("%1 failed to compile").arg(queryFile).toLatin1().constData());
157 }
158
checkQueries_data() const159 void tst_PatternistExamples::checkQueries_data() const
160 {
161 QTest::addColumn<QString>("queryFile");
162
163 const QStringList queryExamples(listFiles(QStringList(QLatin1String("*.xq"))));
164
165 QCOMPARE(queryExamples.count(), int(XQueryFileCount));
166
167 foreach(QString q, queryExamples)
168 QTest::newRow(q.toLocal8Bit().constData()) << q;
169 }
170
checkXMLFiles() const171 void tst_PatternistExamples::checkXMLFiles() const
172 {
173 QFETCH(QString, file);
174
175 QXmlQuery query;
176 /* Wrapping in QUrl ensures it gets formatted as a URI on all platforms. */
177 query.setQuery(QLatin1String("doc('") + QUrl::fromLocalFile(file).toString() + QLatin1String("')"));
178 QVERIFY(query.isValid());
179
180 /* We don't care about the result, we only want to ensure the files can be parsed. */
181 QByteArray dummy;
182 QBuffer buffer(&dummy);
183 QVERIFY(buffer.open(QIODevice::WriteOnly));
184
185 QXmlSerializer serializer(query, &buffer);
186
187 /* This is the important one. */
188 QVERIFY(query.evaluateTo(&serializer));
189 }
190
checkXMLFiles_data() const191 void tst_PatternistExamples::checkXMLFiles_data() const
192 {
193 QTest::addColumn<QString>("file");
194 QStringList patterns;
195 patterns.append(QLatin1String("*.xml"));
196 patterns.append(QLatin1String("*.gccxml"));
197 patterns.append(QLatin1String("*.svg"));
198 patterns.append(QLatin1String("*.ui"));
199 patterns.append(QLatin1String("*.html"));
200
201 const QStringList xmlFiles(listFiles(patterns));
202
203 if(xmlFiles.count() != XMLFileCount)
204 qDebug() << "These files were encountered:" << xmlFiles;
205
206 QCOMPARE(xmlFiles.count(), int(XMLFileCount));
207
208 foreach(QString q, xmlFiles)
209 QTest::newRow(q.toLocal8Bit().constData()) << q;
210 }
211
212 /*!
213 Below, we include all the examples and ensure that they build, such that we rule
214 out syntax error and that API changes has propagated into examples.
215
216 An improvement could be to run them, to ensure that they behave as they intend
217 to.
218 */
219
abstractURI()220 static QUrl abstractURI()
221 {
222 QUrl baseURI;
223 QUrl relative;
224 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qabstracturiresolver.cpp"
225 }
226
227 class MyValue
228 {
229 public:
parent() const230 MyValue parent() const
231 {
232 return MyValue();
233 }
234 };
235
toMyValue(const QXmlNodeModelIndex &)236 static MyValue toMyValue(const QXmlNodeModelIndex &)
237 {
238 return MyValue();
239 }
240
toNodeIndex(const MyValue &)241 static QXmlNodeModelIndex toNodeIndex(const MyValue &)
242 {
243 return QXmlNodeModelIndex();
244 }
245
246 class MyTreeModel : public QSimpleXmlNodeModel
247 {
248 public:
249 MyTreeModel(const QXmlNamePool &np, const QFile &f);
250
documentUri(const QXmlNodeModelIndex &) const251 virtual QUrl documentUri(const QXmlNodeModelIndex&) const
252 {
253 return QUrl();
254 }
255
kind(const QXmlNodeModelIndex &) const256 virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex&) const
257 {
258 return QXmlNodeModelIndex::Element;
259 }
260
compareOrder(const QXmlNodeModelIndex &,const QXmlNodeModelIndex &) const261 virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex&, const QXmlNodeModelIndex&) const
262 {
263 return QXmlNodeModelIndex::Is;
264 }
265
root(const QXmlNodeModelIndex &) const266 virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex&) const
267 {
268 return QXmlNodeModelIndex();
269 }
270
name(const QXmlNodeModelIndex &) const271 virtual QXmlName name(const QXmlNodeModelIndex&) const
272 {
273 return QXmlName();
274 }
275
typedValue(const QXmlNodeModelIndex &) const276 virtual QVariant typedValue(const QXmlNodeModelIndex&) const
277 {
278 return QVariant();
279 }
280
attributes(const QXmlNodeModelIndex &) const281 virtual QVector<QXmlNodeModelIndex> attributes(const QXmlNodeModelIndex&) const
282 {
283 return QVector<QXmlNodeModelIndex>();
284 }
285
nodeFor(const QString &) const286 QXmlNodeModelIndex nodeFor(const QString &) const
287 {
288 return QXmlNodeModelIndex();
289 }
290
291 virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const;
292 };
293
294 /*
295 Exists for linking with at least msvc-2005.
296 */
MyTreeModel(const QXmlNamePool & np,const QFile &)297 MyTreeModel::MyTreeModel(const QXmlNamePool &np, const QFile &) : QSimpleXmlNodeModel(np)
298 {
299 }
300
301 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qsimplexmlnodemodel.cpp"
302
303 class MyMapper
304 {
305 public:
306 class InputType;
307 enum OutputType
308 {
309 };
310 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlforwarditerator.cpp"
311 };
312
313 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qxmlname.cpp"
314
buildSnippets() const315 void tst_PatternistExamples::buildSnippets() const
316 {
317 /* We don't run this code, see comment above. */
318 return;
319
320 /* We place a call to this function, such that GCC doesn't emit a warning. */
321 abstractURI();
322
323 {
324 }
325
326 {
327 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qxmlresultitems.cpp"
328 }
329
330 {
331 }
332
333 {
334 QIODevice *myOutputDevice = 0;
335 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qxmlformatter.cpp"
336 }
337
338 {
339 QIODevice *myOutputDevice = 0;
340 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qxmlserializer.cpp"
341 }
342
343 {
344 QXmlNodeModelIndex myInstance;
345 const char **argv = 0;
346 typedef MyTreeModel ChemistryNodeModel;
347 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp"
348 }
349
350 {
351 }
352
353 {
354 QIODevice *myOutputDevice = 0;
355 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp"
356 }
357
358 {
359 QXmlQuery query;
360 QString localName;
361 QVariant value;
362 #include "../../doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp"
363 }
364 }
365
366 QTEST_MAIN(tst_PatternistExamples)
367
368 #include "tst_patternistexamples.moc"
369 #else
370 QTEST_NOOP_MAIN
371 #endif
372
373 // vim: et:ts=4:sw=4:sts=4
374