1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include <QtTest/QtTest>
46 #include <QSourceLocation>
47 #include <QXmlFormatter>
48 #include <QXmlNamePool>
50 #include <QXmlResultItems>
51 #include <QXmlSerializer>
55 #include "TestNodeModel.h"
56 #include "LoadingModel.h"
57 #include "../qxmlquery/TestFundament.h"
60 \class tst_QAbstractXmlNodeModel
63 \brief Tests the QAbstractXmlNodeModel class.
65 class tst_QAbstractXmlNodeModel : public QObject
66 , private TestFundament
71 // TODO lots of tests missing
73 void constructor() const;
74 void objectSize() const;
75 void nextFromSimpleAxis();
76 void nextFromSimpleAxis_data() const;
77 void constCorrectness() const;
78 void createData() const;
79 void createPointerAdditionalData() const;
80 void createDataAdditionalData() const;
83 void typedValue() const;
84 void sourceLocation() const;
87 QAbstractXmlNodeModel::Ptr m_nodeModel;
88 QXmlNamePool m_namePool;
89 QXmlNodeModelIndex m_rootNode;
92 const char testFileName[] = "tree.xml";
94 void tst_QAbstractXmlNodeModel::initTestCase()
96 const QString testFilePath = QFINDTESTDATA(testFileName);
97 QVERIFY2(!testFilePath.isEmpty(), "tree.xml not found");
98 const QString testDirectory = QFileInfo(testFilePath).absolutePath();
99 QVERIFY2(QDir::setCurrent(testDirectory), qPrintable(QStringLiteral("Could not chdir to ") + testDirectory));
101 m_nodeModel = LoadingModel::create(m_namePool);
102 QVERIFY(m_nodeModel);
103 m_rootNode = m_nodeModel->root(QXmlNodeModelIndex());
104 QVERIFY(!m_rootNode.isNull());
107 void tst_QAbstractXmlNodeModel::constructor() const
109 /* Allocate instance. */
111 TestNodeModel instance;
115 TestNodeModel instance1;
116 TestNodeModel instance2;
120 TestNodeModel instance1;
121 TestNodeModel instance2;
122 TestNodeModel instance3;
126 void tst_QAbstractXmlNodeModel::objectSize() const
128 /* We can't currently test this in portable way,
132 const int pointerSize = sizeof(void *);
133 // adjust for pointer alignment
134 const int sharedDataSize = ((sizeof(QSharedData) + pointerSize) / pointerSize) * pointerSize;
135 const int modelSize = sizeof(QAbstractXmlNodeModel);
137 /* A d pointer plus a vtable pointer. */
138 QCOMPARE(modelSize, sharedDataSize + pointerSize * 2);
142 Tests nextFromSimpleAxis(). More exactly that all the logic in
143 QAbstractXmlNodeModel::iterate() is as we expect to. Subsequently, a lot
144 of testing code is in LoadingModel(.cpp).
148 1. In initTestCase() we loaded tree.xml into LoadingModel and
149 stored the root node in m_rootNode.
150 2. We execute a query that navigates from m_rootNode and write out
151 the result using QXmlFormatter.
152 3. We execute the exact same query, but this time use the built in node backend,
153 and write out the result in the same way. This is our baseline.
156 Hence we check QAbstractXmlNodeModel::iterate() and friends against our XQuery
157 code, which in turn is (mainly) checked by the XQTS. This means safer testing
158 since we don't create baselines manually, and it also means that we can modify
159 the input file, tree.xml, without having to update static baselines.
161 void tst_QAbstractXmlNodeModel::nextFromSimpleAxis()
163 QFETCH(QString, queryString);
167 /* Fill out, using LoadingModel. */
169 QXmlQuery query(m_namePool);
170 query.bindVariable(QLatin1String("node"), m_rootNode);
171 query.setQuery(queryString);
172 QVERIFY(query.isValid());
174 QVERIFY(out.open(QIODevice::WriteOnly));
175 QXmlFormatter formatter(query, &out);
177 QVERIFY(query.evaluateTo(&formatter));
182 /* Create the baseline. */
184 QXmlQuery openDoc(m_namePool);
185 const QString testFilePath = QDir::currentPath() + QLatin1Char('/') + QLatin1String(testFileName);
186 openDoc.bindVariable(QLatin1String("docURI"), QVariant(QUrl::fromLocalFile(testFilePath)));
187 openDoc.setQuery(QLatin1String("doc($docURI)"));
189 QVERIFY(openDoc.isValid());
190 openDoc.evaluateTo(&doc);
192 QXmlQuery produceBaseline(m_namePool);
193 produceBaseline.bindVariable(QLatin1String("node"), doc.next());
194 produceBaseline.setQuery(queryString);
195 QVERIFY(produceBaseline.isValid());
196 QVERIFY(baseline.open(QIODevice::WriteOnly));
198 QXmlFormatter baselineFormatter(produceBaseline, &baseline);
199 QVERIFY(produceBaseline.evaluateTo(&baselineFormatter));
202 if(out.data() != baseline.data())
204 QTextStream(stderr) << "ACTUAL:" << QString::fromUtf8(out.data().constData())
205 << "EXPECTED:" << QString::fromUtf8(baseline.data().constData());
208 QCOMPARE(out.data(), baseline.data());
211 void tst_QAbstractXmlNodeModel::nextFromSimpleAxis_data() const
213 QTest::addColumn<QString>("queryString");
215 QTest::newRow("The whole tree")
218 QTest::newRow("::descendant-or-self from $node, all nodes.")
219 << "$node/descendant-or-self::node()";
221 QTest::newRow("::descendant from $node, all nodes.")
222 << "$node/descendant::node()";
224 QTest::newRow("::descendant from node with no descendants.")
225 << "$node/descendant::node()";
227 QTest::newRow("following-sibling on $root.")
228 << "$node/text()[1]/following-sibling::node()";
230 QTest::newRow("following-sibling from section1.")
231 << "$node//section1/following-sibling::node()";
233 QTest::newRow("preceding-sibling-sibling from section1.")
234 << "$node//section1/preceding-sibling::node()";
236 QTest::newRow("following-sibling from oneTextChild.")
237 << "$node//oneTextChild/following-sibling::node()";
239 QTest::newRow("preceding-sibling-sibling from oneTextChild.")
240 << "$node//oneTextChild/preceding-sibling::node()";
242 QTest::newRow("preceding-sibling on $root.")
243 << "$node/preceding-sibling::node()";
245 QTest::newRow("::ancestor from node at the end")
246 << "$node//node()/ancestor::node()";
248 QTest::newRow("::ancestor-or-self from node at the end")
249 << "$node//node()/ancestor-or-self::node()";
251 QTest::newRow("Copy attributes from all nodes.")
252 << "<e>{for $i in $node//node()/@* order by $i return $i}</e>";
254 QTest::newRow("::preceding from node at the end")
255 << "($node//node())[last()]/preceding::node()";
257 QTest::newRow("::preceding from $node")
258 << "$node/preceding::node()";
260 QTest::newRow("::following from node at the end")
261 << "($node//node())[last()]/following::node()";
263 QTest::newRow("::following from $node")
264 << "$node//following::node()";
266 QTest::newRow("::following from $node")
267 << "$node/following::node()";
269 QTest::newRow("::descendant from text() nodes.")
270 << "$node/descendant-or-self::text()/descendant::node()";
272 QTest::newRow("::descendant-or-self from text() nodes.")
273 << "$node/descendant-or-self::text()/descendant-or-self::node()";
275 QTest::newRow("descendant-or-self::node() from section1.")
276 << "$node//section1/descendant-or-self::node()";
278 QTest::newRow("descendant::node() from section1.")
279 << "$node//section1/descendant::node()";
281 /* Checks for axis order. */
283 QTest::newRow("::descendant from text() nodes with last(), checking axis order.")
284 << "$node/descendant-or-self::text()/(descendant::node()[last()])";
286 QTest::newRow("::descendant-or-self from text() nodes with last(), checking axis order.")
287 << "$node/descendant-or-self::text()/(descendant-or-self::node()[last()])";
289 QTest::newRow("::descendant from text() nodes with predicate, checking axis order.")
290 << "$node/descendant-or-self::text()/(descendant::node()[2])";
292 QTest::newRow("::descendant-or-self from text() nodes with predicate, checking axis order.")
293 << "$node/descendant-or-self::text()/(descendant-or-self::node()[2])";
295 QTest::newRow("::following from node at the end with predicate, checking axis order.")
296 << "($node//node())[last()]/(following::node()[2])";
298 QTest::newRow("::following from node at the end with last(), checking axis order.")
299 << "($node//node())[last()]/(following::node()[last()])";
301 QTest::newRow("ancestor:: from node at the end with predicate, checking axis order.")
302 << "($node//node())[last()]/(ancestor::node()[2])";
304 QTest::newRow("ancestor:: from node at the end with last(), checking axis order.")
305 << "($node//node())[last()]/(ancestor::node()[last()])";
307 QTest::newRow("ancestor-or-self:: from node at the end with predicate, checking axis order.")
308 << "($node//node())[last()]/(ancestor::node()[2])";
310 QTest::newRow("ancestor-or-self:: from node at the end with last(), checking axis order.")
311 << "($node//node())[last()]/(ancestor::node()[last()])";
313 QTest::newRow("::preceding from node at the end with predicate, checking axis order.")
314 << "($node//node())[last()]/(preceding::node()[2])";
316 QTest::newRow("descendant-or-self in two levels, with last()")
317 << "$node/descendant-or-self::text()/(descendant-or-self::node()[last()])";
319 QTest::newRow("descendant-or-self with last()")
320 << "$node/descendant-or-self::node()[last()]";
322 QTest::newRow("::preceding from node at the end with last(), checking axis order.")
323 << "$node/preceding::node()[last()]";
325 QTest::newRow("::preceding combined with descendant-or-self, from node at the end with last(), checking axis order.")
326 << "$node//preceding::node()[last()]";
328 QTest::newRow("::preceding combined with descendant-or-self, from node at the end with last(), checking axis order.")
329 << "($node//node())[last()]/(preceding::node()[last()])";
332 void tst_QAbstractXmlNodeModel::constCorrectness() const
337 void tst_QAbstractXmlNodeModel::createData() const
340 // Verify that the argument is qint64
343 void tst_QAbstractXmlNodeModel::createPointerAdditionalData() const
346 // Verify that the second argument is qint64
349 void tst_QAbstractXmlNodeModel::createDataAdditionalData() const
354 void tst_QAbstractXmlNodeModel::id() const
356 // TODO verify that invalid NCNames are not sent to the model.
359 void tst_QAbstractXmlNodeModel::idref() const
361 // TODO verify that invalid NCNames are not sent to the model.
365 Verify that if QAbstractXmlNodeModel::typedValue() return a null
366 QVariant, it is treated as that the node has no typed value.
368 void tst_QAbstractXmlNodeModel::typedValue() const
370 class TypedModel : public TestNodeModel
373 virtual QVariant typedValue(const QXmlNodeModelIndex &) const
378 QXmlNodeModelIndex root() const
380 return createIndex(qint64(1));
387 query.bindVariable(QLatin1String("node"), model.root());
388 query.setQuery(QLatin1String("declare variable $node external;"
389 "string($node), data($node)"));
392 QBuffer buffer(&output);
393 QVERIFY(buffer.open(QIODevice::WriteOnly));
394 QVERIFY(query.isValid());
396 QXmlSerializer serializer(query, &buffer);
397 QVERIFY(query.evaluateTo(&serializer));
399 QVERIFY(output.isEmpty());
402 void tst_QAbstractXmlNodeModel::sourceLocation() const
404 const QAbstractXmlNodeModel* const constModel = m_nodeModel.data();
405 const QSourceLocation location = constModel->sourceLocation(m_rootNode);
408 QTEST_MAIN(tst_QAbstractXmlNodeModel)
410 #include "tst_qabstractxmlnodemodel.moc"
412 // vim: et:ts=4:sw=4:sts=4