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