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 <QtDebug>
30
31#include <private/qacceltreeresourceloader_p.h>
32#include <private/qnetworkaccessdelegator_p.h>
33
34#include "Global.h"
35#include "TestBaseLine.h"
36#include "TestGroup.h"
37
38#include "TestSuiteHandler.h"
39
40using namespace QPatternistSDK;
41
42static QNetworkAccessManager *s_networkAccessManager = 0;
43
44static void cleanupNetworkAccessManager()
45{
46 delete s_networkAccessManager;
47 s_networkAccessManager = 0;
48
49}
50static QNetworkAccessManager *networkAccessManager()
51{
52 if (!s_networkAccessManager) {
53 s_networkAccessManager = new QNetworkAccessManager;
54 qAddPostRoutine(cleanupNetworkAccessManager);
55 }
56 return s_networkAccessManager;
57}
58
59TestSuiteHandler::TestSuiteHandler(const QUrl &catalogFile,
60 const bool useEList) : m_ts(0)
61 , m_container(0)
62 , m_tc(0)
63 , m_baseLine(0)
64 , m_catalogFile(catalogFile)
65 , m_exclusionList(readExclusionList(useExclusionList: useEList))
66 , m_isExcluding(false)
67{
68 Q_ASSERT(!m_catalogFile.isRelative());
69}
70
71QStringList TestSuiteHandler::readExclusionList(const bool useExclusionList) const
72{
73 if(!useExclusionList)
74 return QStringList();
75
76 QStringList avoid;
77
78 /* These test groups are for features we don't support.
79 *
80 * Originally these were stored in a text file pulled in with Qt resources, but
81 * it was not possible to get it to link on some HP-UX and Intel-icc platforms. */
82
83 avoid << "SchemaImport"; // The schema import feature
84 avoid << "SchemaValidation"; // The validate expression(requires schema import)
85 avoid << "StaticTyping"; // Pessimistic static typing checking
86 avoid << "TrivialEmbedding"; // XQueryX inside XQuery
87 avoid << "XMark"; // We're currently too buggy for running these tests.
88
89 return avoid;
90}
91
92bool TestSuiteHandler::startElement(const QStringRef &namespaceURI, const QStringRef &localName,
93 const QStringRef & /*qName*/, const QXmlStreamAttributes &atts)
94{
95 if(namespaceURI != Global::xqtsCatalogNS)
96 return true;
97 else if(m_isExcluding)
98 {
99 if(localName == QLatin1String("test-group"))
100 {
101 m_testGroupName.push(t: atts.value(qualifiedName: QLatin1String("name")).toString());
102 return true;
103 }
104 else
105 return true;
106 }
107
108 /* The elements are handled roughly in the order of highest occurrence in the catalog file. */
109 if(localName == QLatin1String("test-case"))
110 {
111 XQTSTestCase *const c = new XQTSTestCase(
112 TestCase::scenarioFromString(string: atts.value(qualifiedName: QLatin1String("scenario")).toString()),
113 m_container);
114
115 c->setName(atts.value(qualifiedName: QLatin1String("name")).toString());
116 c->setCreator(atts.value(qualifiedName: QLatin1String("Creator")).toString());
117 c->setIsXPath(Global::readBoolean(lexicalSpace: atts.value(qualifiedName: QLatin1String("is-XPath2")).toString()));
118 c->setLastModified(QDate::fromString(s: atts.value(qualifiedName: QLatin1String("version-drop")).toString(),
119 f: Qt::ISODate));
120 Q_ASSERT(c->lastModified().isNull() || c->lastModified().isValid());
121
122 m_currentQueryPath =
123 m_queryOffset.resolved(relative: QUrl(atts.value(qualifiedName: QLatin1String("FilePath")).toString()));
124 m_currentBaselinePath =
125 m_baselineOffset.resolved(relative: QUrl(atts.value(qualifiedName: QLatin1String("FilePath")).toString()));
126
127 m_container->appendChild(item: c);
128 m_tc = c;
129 }
130 else if(localName == QLatin1String("query"))
131 {
132 m_tc->setQueryPath(m_currentQueryPath.resolved(relative: atts.value(qualifiedName: QLatin1String("name")) +
133 m_xqueryFileExtension));
134 }
135 else if(localName == QLatin1String("input-file") ||
136 localName == QLatin1String("input-URI"))
137 {
138 m_currentInputVariable = atts.value(qualifiedName: QLatin1String("variable")).toString();
139 }
140 else if(localName == QLatin1String("output-file"))
141 {
142 m_baseLine = new TestBaseLine(TestBaseLine::identifierFromString(
143 string: atts.value(qualifiedName: QLatin1String("compare")).toString()));
144 }
145 else if(localName == QLatin1String("expected-error"))
146 {
147 m_baseLine = new TestBaseLine(TestBaseLine::ExpectedError);
148 }
149 else if(localName == QLatin1String("test-group"))
150 {
151 m_testGroupName.push(t: atts.value(qualifiedName: QLatin1String("name")).toString());
152
153 if(m_exclusionList.contains(str: m_testGroupName.top()))
154 {
155 /* Ok, this group is supposed to be excluded, we don't
156 * insert it into the tree. */
157 m_isExcluding = true;
158 return true;
159 }
160 else
161 {
162 Q_ASSERT(m_container);
163 TestGroup *const newGroup = new TestGroup(m_container);
164 m_container->appendChild(item: newGroup);
165 m_container = newGroup;
166 }
167 }
168 else if(localName == QLatin1String("source"))
169 {
170 m_sourceMap.insert(
171 akey: atts.value(qualifiedName: QLatin1String("ID")).toString(),
172 avalue: m_sourceOffset.resolved(relative: QUrl(atts.value(qualifiedName: QLatin1String("FileName")).toString())));
173 }
174 else if(localName == QLatin1String("test-suite"))
175 {
176 m_ts = new TestSuite();
177 m_ts->setVersion(atts.value(qualifiedName: QLatin1String("version")).toString());
178 m_ts->setDesignDate(QDate::fromString(
179 s: atts.value(qualifiedName: QLatin1String("CatalogDesignDate")).toString(), f: Qt::ISODate));
180 Q_ASSERT(m_ts->designDate().isValid());
181 m_container = m_ts;
182
183 m_xqueryFileExtension = atts.value(qualifiedName: QLatin1String("XQueryFileExtension")).toString();
184 m_queryOffset = m_catalogFile.resolved(
185 relative: atts.value(qualifiedName: QLatin1String("XQueryQueryOffsetPath")).toString());
186 m_baselineOffset =
187 m_catalogFile.resolved(relative: atts.value(qualifiedName: QLatin1String("ResultOffsetPath")).toString());
188 m_sourceOffset =
189 m_catalogFile.resolved(relative: atts.value(qualifiedName: QLatin1String("SourceOffsetPath")).toString());
190 }
191 else if(localName == QLatin1String("input-query"))
192 {
193 m_tcSourceInputs.insert(
194 akey: atts.value(qualifiedName: QLatin1String("variable")).toString(),
195 avalue: ExternalSourceLoader::VariableValue(
196 m_currentQueryPath.resolved(relative: atts.value(qualifiedName: QLatin1String("name"))
197 + m_xqueryFileExtension),
198 ExternalSourceLoader::Query));
199 }
200
201 return true;
202}
203
204bool TestSuiteHandler::endElement(const QStringRef &namespaceURI,
205 const QStringRef &localName,
206 const QStringRef &/*qName*/)
207{
208 if(namespaceURI != Global::xqtsCatalogNS)
209 return true;
210
211 if(m_isExcluding)
212 {
213 if(localName == QLatin1String("test-group"))
214 {
215 const QString myName(m_testGroupName.pop());
216
217 if(m_exclusionList.contains(str: myName))
218 {
219 /* This test-group is being excluded and now we're exiting from it. */
220 m_isExcluding = false;
221 }
222 }
223
224 return true;
225 }
226
227 /* The elements are handled roughly in the order of highest occurrence in the catalog file. */
228 if(localName == QLatin1String("description"))
229 {
230 if(m_tc)
231 {
232 /* We're inside a <test-case>, so the <description> belongs
233 * to the test-case. */
234 m_tc->setDescription(m_ch.simplified());
235 }
236 else
237 m_container->setDescription(m_ch.simplified());
238 }
239 else if(localName == QLatin1String("test-case"))
240 {
241 Q_ASSERT(m_tc->baseLines().count() >= 1);
242 Q_ASSERT(m_resourceLoader);
243 m_tc->setExternalVariableLoader(QPatternist::ExternalVariableLoader::Ptr
244 (new ExternalSourceLoader(m_tcSourceInputs,
245 m_resourceLoader)));
246 m_tcSourceInputs.clear();
247
248 if(!m_contextItemSource.isEmpty())
249 {
250 m_tc->setContextItemSource(QUrl(m_sourceMap.value(akey: m_contextItemSource)));
251 m_contextItemSource.clear();
252 }
253
254 m_tc = 0;
255 }
256 else if(localName == QLatin1String("output-file"))
257 {
258 m_baseLine->setDetails(m_currentBaselinePath.resolved(relative: m_ch).toString());
259 m_tc->addBaseLine(lines: m_baseLine);
260 }
261 else if(localName == QLatin1String("input-file"))
262 {
263 m_tcSourceInputs.insert(akey: m_currentInputVariable, avalue: ExternalSourceLoader::VariableValue(m_sourceMap.value(akey: m_ch),
264 ExternalSourceLoader::Document));
265 }
266 else if(localName == QLatin1String("expected-error"))
267 {
268 m_baseLine->setDetails(m_ch);
269 m_tc->addBaseLine(lines: m_baseLine);
270 }
271 else if(localName == QLatin1String("title"))
272 {
273 /* A bit dangerous, the only element with name title in the vocabulary
274 * is the child of GroupInfo */
275 m_container->setTitle(m_ch.simplified());
276 }
277 else if(localName == QLatin1String("test-group"))
278 {
279 m_testGroupName.pop();
280 Q_ASSERT(m_container);
281 m_container = static_cast<TestContainer *>(m_container->parent());
282 Q_ASSERT(m_container);
283 }
284 else if(localName == QLatin1String("test-suite"))
285 {
286 Q_ASSERT(m_container);
287 m_container = static_cast<TestContainer *>(m_container->parent());
288 }
289 else if(localName == QLatin1String("sources"))
290 {
291 const QPatternist::NetworkAccessDelegator::Ptr networkDelegator(new QPatternist::NetworkAccessDelegator(networkAccessManager(), networkAccessManager()));
292
293 m_resourceLoader = QPatternist::ResourceLoader::Ptr(new QPatternist::AccelTreeResourceLoader(Global::namePool(),
294 networkDelegator));
295
296 const ExternalSourceLoader::SourceMap::const_iterator end(m_sourceMap.constEnd());
297 ExternalSourceLoader::SourceMap::const_iterator it(m_sourceMap.constBegin());
298
299 for(; it != end; ++it)
300 m_resourceLoader->announceDocument(uri: it.value(), usageHint: QPatternist::ResourceLoader::WillUse);
301 }
302 else if(localName == QLatin1String("input-URI"))
303 {
304 m_tcSourceInputs.insert(akey: m_currentInputVariable, avalue: ExternalSourceLoader::VariableValue(m_sourceMap.value(akey: m_ch),
305 ExternalSourceLoader::URI));
306 }
307 else if(localName == QLatin1String("contextItem"))
308 m_contextItemSource = m_ch;
309
310 return true;
311}
312
313bool TestSuiteHandler::characters(const QStringRef &ch)
314{
315 m_ch = ch.toString();
316 return true;
317}
318
319TestSuite *TestSuiteHandler::testSuite() const
320{
321 return m_ts;
322}
323
324// vim: et:ts=4:sw=4:sts=4
325
326

source code of qtxmlpatterns/tests/auto/xmlpatternssdk/TestSuiteHandler.cpp