diff options
author | Qt by Nokia <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
---|---|---|
committer | axis <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
commit | e1b2c9deb5943faae2b29be6a5c006f75bb73f06 (patch) | |
tree | fc79e45367c0a8fc71185e9afc33f7503a58653c /tests/auto/xmlpatternssdk | |
download | qtxmlpatterns-e1b2c9deb5943faae2b29be6a5c006f75bb73f06.tar.gz |
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:
http://qt.gitorious.org/qt/pages/GitIntroductionWithQt
If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.
Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tests/auto/xmlpatternssdk')
61 files changed, 11293 insertions, 0 deletions
diff --git a/tests/auto/xmlpatternssdk/ASTItem.cpp b/tests/auto/xmlpatternssdk/ASTItem.cpp new file mode 100644 index 0000000..c866d07 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ASTItem.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QList> +#include <QPointer> +#include <QVariant> + +#include "ASTItem.h" + +using namespace QPatternistSDK; + +/** + * This is what the AST rendering is indented with. + */ +static const QLatin1String astIndent(" "); +// STATIC DATA + +ASTItem::ASTItem(ASTItem *p, + const QString &name, + const QString &details, + const QString &staticType, + const QString &reqType) : m_name(name), + m_details(details), + m_reqType(reqType), + m_staticType(staticType), + m_parent(p) +{ +} + +ASTItem::~ASTItem() +{ + qDeleteAll(m_children); +} + +QString ASTItem::toString() const +{ + /* The first ASTItem* is a virtual root node, so skip "this". */ + Q_ASSERT(m_children.count() == 1); + TreeItem *treeChild = m_children.first(); + Q_ASSERT(treeChild); + + ASTItem *astChild = static_cast<ASTItem *>(treeChild); + + return astChild->toString(QString()); +} + +QString ASTItem::toString(const QString &indent) const +{ + QString retval; + + retval += indent; + retval += m_name; + retval += QLatin1Char('('); + retval += m_details; + retval += QLatin1String(")\n"); + + const TreeItem::List::const_iterator end(m_children.constEnd()); + + for(TreeItem::List::const_iterator it(m_children.constBegin()); it != end; ++it) + { + TreeItem *treeChild = *it; /* Cast away the QPointer with its casting operator. */ + ASTItem *astChild = static_cast<ASTItem *>(treeChild); + + retval += astChild->toString(indent + astIndent); + } + + return retval; +} + +QVariant ASTItem::data(const Qt::ItemDataRole role, int column) const +{ + if(role != Qt::DisplayRole) + return QVariant(); + + switch(column) + { + case 0: + return m_name; + case 1: + return m_details; + case 2: + return m_staticType; + case 3: + return m_reqType; + default: + { + Q_ASSERT(false); + return QVariant(); + } + } +} + +int ASTItem::columnCount() const +{ + return 4; +} + +TreeItem::List ASTItem::children() const +{ + return m_children; +} + +void ASTItem::appendChild(TreeItem *item) +{ + m_children.append(item); +} + +TreeItem *ASTItem::child(const unsigned int rowP) const +{ + return m_children.value(rowP); +} + +unsigned int ASTItem::childCount() const +{ + return m_children.count(); +} + +TreeItem *ASTItem::parent() const +{ + return m_parent; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ASTItem.h b/tests/auto/xmlpatternssdk/ASTItem.h new file mode 100644 index 0000000..7c43212 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ASTItem.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ASTItem_H +#define PatternistSDK_ASTItem_H + +#include <QList> +#include <QString> + +#include "TreeItem.h" +#include "Global.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Is a node in a ASTItem tree; each ASTItem contains + * debug information about an QPatternist::Expression. + * + * ASTItem, by implementing TreeItem, leverages debug data about QPatternist::Expression + * instances into Qt's model/view framework. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ASTItem : public TreeItem + { + public: + virtual ~ASTItem(); + ASTItem(ASTItem *parent, + const QString &name, + const QString &details = QString(), + const QString &staticType = QString(), + const QString &reqType = QString()); + + virtual void appendChild(TreeItem *item); + virtual TreeItem *child(const unsigned int row) const; + virtual unsigned int childCount() const; + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + virtual TreeItem::List children() const; + virtual TreeItem *parent() const; + int columnCount() const; + + /** + * Returns a string representation of this AST node, recursively including + * children. For example, the query <tt>1 eq number()</tt> would result in the string: + * +@verbatim +ValueComparison(eq) + xs:integer(0) + FunctionCall(fn:number) + ContextItem +@endverbatim + */ + QString toString() const; + + private: + QString toString(const QString &indent) const; + + const QString m_name; + const QString m_details; + const QString m_reqType; + const QString m_staticType; + TreeItem::List m_children; + TreeItem *m_parent; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/DebugExpressionFactory.cpp b/tests/auto/xmlpatternssdk/DebugExpressionFactory.cpp new file mode 100644 index 0000000..9b307cf --- /dev/null +++ b/tests/auto/xmlpatternssdk/DebugExpressionFactory.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QStringList> +#include <QVariant> +#include <QtDebug> +#include <QXmlNamePool> + +#include "qfunctionfactorycollection_p.h" + +#include "ASTItem.h" +#include "ExpressionInfo.h" +#include "ExpressionNamer.h" +#include "Global.h" + +#include "DebugExpressionFactory.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +static const QPatternist::ExpressionVisitor::Ptr namer(new ExpressionNamer()); + +QStringList DebugExpressionFactory::availableFunctionSignatures() +{ + const QPatternist::FunctionFactory::Ptr factory(QPatternist::FunctionFactoryCollection::xpath20Factory(Global::namePool())); + const QPatternist::FunctionSignature::Hash signs(factory->functionSignatures()); + const QPatternist::FunctionSignature::Hash::const_iterator end(signs.constEnd()); + QPatternist::FunctionSignature::Hash::const_iterator it(signs.constBegin()); + QStringList retval; + + while(it != end) + { + retval << it.value()->displayName(Global::namePool()); + ++it; + } + + return retval; +} + +ASTItem *DebugExpressionFactory::buildASTTree(const QPatternist::Expression::Ptr &expr, + ASTItem *parent, + const QPatternist::SequenceType::Ptr &reqType) +{ + Q_ASSERT(expr); + const QPatternist::ExpressionVisitorResult::Ptr exprInfo(expr->accept(namer)); + Q_ASSERT(exprInfo); + const ExpressionInfo *const constExprInfo = static_cast<const ExpressionInfo *>(exprInfo.data()); + const QString name(constExprInfo->first); + const QString details(constExprInfo->second); + const QString rType(reqType ? reqType->displayName(Global::namePool()) : QLatin1String("Not specified")); + + /* ---------- Handle its staticType() -------- */ + const QPatternist::SequenceType::Ptr type(expr->staticType()); + QString seqType; + + if(type) + seqType = type->displayName(Global::namePool()); + else + seqType = QLatin1String("no type, null pointer returned"); + /* ------------------------------------------- */ + + ASTItem *const node = new ASTItem(parent, name, details, seqType, rType); + + /* ------------ Handle child nodes ----------- */ + const QPatternist::Expression::List children(expr->operands()); + QPatternist::Expression::List::const_iterator it(children.constBegin()); + const QPatternist::Expression::List::const_iterator end(children.constEnd()); + + const QPatternist::SequenceType::List reqTypes(expr->expectedOperandTypes()); + const QPatternist::SequenceType::List::const_iterator typeEnd(reqTypes.constEnd()); + QPatternist::SequenceType::List::const_iterator typeIt(reqTypes.constBegin()); + QPatternist::SequenceType::Ptr t; + + for(; it != end; ++it) + { + if(typeIt != typeEnd) + { + t = *typeIt; + ++typeIt; + } + + node->appendChild(buildASTTree(*it, node, t)); + } + /* ------------------------------------------- */ + + return node; +} + +QPatternist::Expression::Ptr +DebugExpressionFactory::createExpression(QIODevice *const expr, + const QPatternist::StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const QPatternist::SequenceType::Ptr &requiredType, + const QUrl &baseURI, + const QXmlName &initialTemplateName) +{ + /* Create the root node. */ + m_ast = new ASTItem(0, QString()); + + return ExpressionFactory::createExpression(expr, context, lang, requiredType, baseURI, initialTemplateName); +} + +void DebugExpressionFactory::processTreePass(const QPatternist::Expression::Ptr &expr, + const CompilationStage stage) +{ + ASTItem *newChild = 0; + + switch(stage) + { + case QueryBodyInitial: + { + newChild = new ASTItem(m_ast, QLatin1String("Initial Build")); + break; + } + case QueryBodyTypeCheck: + { + newChild = new ASTItem(m_ast, QLatin1String("Type Check")); + break; + } + case QueryBodyCompression: + { + newChild = new ASTItem(m_ast, QLatin1String("Compression")); + break; + } + case UserFunctionTypeCheck: + { + newChild = new ASTItem(m_ast, QLatin1String("User Function Type Check")); + break; + } + case UserFunctionCompression: + { + newChild = new ASTItem(m_ast, QLatin1String("User Function Compression")); + break; + } + case GlobalVariableTypeCheck: + { + newChild = new ASTItem(m_ast, QLatin1String("Global Variable Type Check")); + break; + } + } + + Q_ASSERT(newChild); + m_ast->appendChild(newChild); + newChild->appendChild(buildASTTree(expr, newChild, QPatternist::SequenceType::Ptr())); +} + +void DebugExpressionFactory::processTemplateRule(const Expression::Ptr &body, + const TemplatePattern::Ptr &pattern, + const QXmlName &mode, + const TemplateCompilationStage stage) +{ + const char * title; + + switch(stage) + { + case TemplateInitial: + { + title = "Initial Build"; + break; + } + case TemplateTypeCheck: + { + title = "Type Check"; + break; + } + case TemplateCompress: + { + title = "Compression"; + break; + } + } + + const QString modeName(Global::namePool()->displayName(mode)); + Q_ASSERT(title); + ASTItem *const newChild = new ASTItem(m_ast, QLatin1String("T-Rule ") + + QLatin1String(title) + + QLatin1String(" mode: ") + + modeName + + QLatin1String(" priority: ") + + QString::number(pattern->priority())); + m_ast->appendChild(newChild); + + newChild->appendChild(buildASTTree(pattern->matchPattern(), newChild, QPatternist::SequenceType::Ptr())); + newChild->appendChild(buildASTTree(body, newChild, QPatternist::SequenceType::Ptr())); +} + +void DebugExpressionFactory::processNamedTemplate(const QXmlName &name, + const Expression::Ptr &body, + const TemplateCompilationStage stage) +{ + const char * title; + + switch(stage) + { + case TemplateInitial: + { + title = "Named Template Initial Build"; + break; + } + case TemplateTypeCheck: + { + title = "Named Template Type Check"; + break; + } + case TemplateCompress: + { + title = "Named Template Compression"; + break; + } + } + + Q_ASSERT(title); + ASTItem *const newChild = new ASTItem(m_ast, QLatin1String(title) + + QLatin1String(": ") + + Global::namePool()->displayName(name)); + + m_ast->appendChild(newChild); + newChild->appendChild(buildASTTree(body, newChild, QPatternist::SequenceType::Ptr())); +} + +ASTItem *DebugExpressionFactory::astTree() const +{ + return m_ast; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/DebugExpressionFactory.h b/tests/auto/xmlpatternssdk/DebugExpressionFactory.h new file mode 100644 index 0000000..558f096 --- /dev/null +++ b/tests/auto/xmlpatternssdk/DebugExpressionFactory.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_DebugExpressionFactory_H +#define PatternistSDK_DebugExpressionFactory_H + +#include "Global.h" +#include "qexpressionfactory_p.h" +#include "qfunctionfactory_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class ASTItem; + + /** + * @short Is a QPatternist::ExpressionFactory, with the + * difference that it provides the hooks for building from a tree of + * debug data from the compiled expression. + * + * This tree can be retrieved via astTree(). The astTree() function + * returns the AST built the last time createExpression() was called. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT DebugExpressionFactory : public QPatternist::ExpressionFactory + { + public: + DebugExpressionFactory() : m_ast(0) + { + } + + typedef QExplicitlySharedDataPointer<DebugExpressionFactory> Ptr; + /** + * Identical to ExpressionFactory::createExpression() with the difference + * that it builds an ASTItem tree which can be accessed via astTree(). + */ + virtual QPatternist::Expression::Ptr createExpression(QIODevice *const expr, + const QPatternist::StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const QPatternist::SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName); + + /** + * @returns an ASTItem tree built for the last created expression, + * via createExpression(). + */ + virtual ASTItem *astTree() const; + + /** + * @returns a list containing string representations of all available + * functions in Patternist. Each QString in the returned QStringList + * is a function synopsis for human consumption. + */ + static QStringList availableFunctionSignatures(); + + protected: + /** + * Performs the ASTItem tree building. + */ + virtual void processTreePass(const QPatternist::Expression::Ptr &tree, + const CompilationStage stage); + + void processTemplateRule(const QPatternist::Expression::Ptr &body, + const QPatternist::TemplatePattern::Ptr &pattern, + const QXmlName &mode, + const TemplateCompilationStage stage); + + void processNamedTemplate(const QXmlName &name, + const QPatternist::Expression::Ptr &body, + const TemplateCompilationStage stage); + private: + static ASTItem *buildASTTree(const QPatternist::Expression::Ptr &expr, + ASTItem *const parent, + const QPatternist::SequenceType::Ptr &reqType); + ASTItem *m_ast; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ErrorHandler.cpp b/tests/auto/xmlpatternssdk/ErrorHandler.cpp new file mode 100644 index 0000000..e7b08dd --- /dev/null +++ b/tests/auto/xmlpatternssdk/ErrorHandler.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <cstdio> + +#include <QBuffer> +#include <QStringList> +#include <QtDebug> +#include <QtTest> +#include <QtGlobal> +#include <QXmlQuery> +#include <QXmlResultItems> + +#include "ErrorHandler.h" + +using namespace QPatternistSDK; + +ErrorHandler *ErrorHandler::handler = 0; + +void qMessageHandler(QtMsgType type, const char *description) +{ + if(type == QtDebugMsg) + { + std::fprintf(stderr, "%s\n", description); + return; + } + + QtMsgType t; + + switch(type) + { + case QtWarningMsg: + { + t = QtWarningMsg; + break; + } + case QtCriticalMsg: + { + t = QtFatalMsg; + break; + } + case QtFatalMsg: + { + /* We can't swallow Q_ASSERTs, we need to fail the hard way here. + * But maybe not: when run from "patternistrunsingle" it could be an idea + * to actually try to record it(but nevertheless fail somehow) such + * that it gets reported. */ + std::fprintf(stderr, "Fatal error: %s\n", description); + t = QtFatalMsg; /* Dummy, to silence a bogus compiler warning. */ + return; + } + case QtDebugMsg: /* This enum is handled above in the if-clause. */ + /* Fallthrough. */ + default: + { + Q_ASSERT(false); + return; + } + } + + Q_ASSERT(ErrorHandler::handler); + /* This message is hacky. Ideally, we should do it the same way + * ReportContext::error() constructs messages, but this is just testing + * code. */ + ErrorHandler::handler->message(t, QLatin1String("<p>") + QPatternist::escape(QLatin1String(description)) + QLatin1String("</p>")); +} + +void ErrorHandler::installQtMessageHandler(ErrorHandler *const h) +{ + handler = h; + + if(h) + qInstallMsgHandler(qMessageHandler); + else + qInstallMsgHandler(0); +} + +void ErrorHandler::handleMessage(QtMsgType type, + const QString &description, + const QUrl &identifier, + const QSourceLocation &) +{ + /* Don't use pDebug() in this function, it results in infinite + * recursion. Talking from experience.. */ + + Message msg; + msg.setType(type); + msg.setIdentifier(identifier); + + /* Let's remove all the XHTML markup. */ + QBuffer buffer; + buffer.setData(description.toLatin1()); + buffer.open(QIODevice::ReadOnly); + + QXmlQuery query; + query.bindVariable(QLatin1String("desc"), &buffer); + query.setQuery(QLatin1String("string(doc($desc))")); + + QStringList result; + const bool success = query.evaluateTo(&result); + + if(!description.startsWith(QLatin1String("\"Test-suite harness error:"))) + { + const QString msg(QString::fromLatin1("Invalid description: %1").arg(description)); + QVERIFY2(success, qPrintable(msg)); + + if(!success) + QTextStream(stderr) << msg; + } + + + if(!result.isEmpty()) + msg.setDescription(result.first()); + + m_messages.append(msg); +} + +ErrorHandler::Message::List ErrorHandler::messages() const +{ + return m_messages; +} + +void ErrorHandler::reset() +{ + m_messages.clear(); +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ErrorHandler.h b/tests/auto/xmlpatternssdk/ErrorHandler.h new file mode 100644 index 0000000..27395aa --- /dev/null +++ b/tests/auto/xmlpatternssdk/ErrorHandler.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ErrorHandler_H +#define PatternistSDK_ErrorHandler_H + +#include "Global.h" +#include "qabstractmessagehandler.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template<typename T> class QList; + +namespace QPatternistSDK +{ + /** + * @short A MessageHandler which + * accumulates all its received ErrorHandler::Message instances + * in a list, retrievable via messages(). + * + * Thus, ErrorHandler does not report errors, but collects them + * and allows easy access to them. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ErrorHandler : public QAbstractMessageHandler + { + public: + class Message + { + public: + typedef QList<Message> List; + + QString description() const + { + return m_description; + } + + void setDescription(const QString &desc) + { + m_description = desc; + } + + void setIdentifier(const QUrl &newId) + { + m_identifier = newId; + } + + QUrl identifier() const + { + return m_identifier; + } + + QtMsgType type() const + { + return m_type; + } + + void setType(const QtMsgType t) + { + m_type = t; + } + + private: + QUrl m_identifier; + QtMsgType m_type; + QString m_description; + }; + + /** + * Clears all accumulated errors. + */ + void reset(); + + Message::List messages() const; + + /** + * Calling this function causes all Qt's internal debug messages to be + * sent to @p handler. If @p handler is @c null, Qt's default message + * handler is re-installed. In other words, via an internal proxy function, + * it installs @p handler as Qt's message handler. + * + * If @p handler is heap allocated, it will be leaked. + * + * @see qInstallMsgHandler() + */ + static void installQtMessageHandler(ErrorHandler *const handler); + + static ErrorHandler *handler; + + protected: + virtual void handleMessage(QtMsgType type, + const QString &description, + const QUrl &identifier = QUrl(), + const QSourceLocation &sourceLocation = QSourceLocation()); + + private: + ErrorHandler::Message::List m_messages; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ErrorItem.cpp b/tests/auto/xmlpatternssdk/ErrorItem.cpp new file mode 100644 index 0000000..df5d266 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ErrorItem.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QList> +#include <QPointer> +#include <QVariant> + +#include "qreportcontext_p.h" +#include "qcommonnamespaces_p.h" + +#include "ErrorItem.h" + +using namespace QPatternistSDK; + +QString ErrorItem::toString(const QtMsgType type) +{ + switch(type) + { + case QtWarningMsg: + return QLatin1String("Warning"); + case QtFatalMsg: + return QLatin1String("Error"); + default: + { + Q_ASSERT(false); + return QString(); + } + } +} + +ErrorItem::ErrorItem(const ErrorHandler::Message &error, + ErrorItem *p) : m_message(error), + m_parent(p) +{ +} + +ErrorItem::~ErrorItem() +{ + qDeleteAll(m_children); +} + +int ErrorItem::columnCount() const +{ + return 3; +} + +QVariant ErrorItem::data(const Qt::ItemDataRole role, int column) const +{ + if(role != Qt::DisplayRole) + return QVariant(); + + switch(column) + { + case 0: + return toString(m_message.type()); + case 1: + { + if(!m_message.type()) /* It's a warning, likely. */ + return QString(); + + QString ns; + const QString code(QPatternist::ReportContext::codeFromURI(m_message.identifier().toString(), ns)); + + if(ns == QPatternist::CommonNamespaces::XPERR) + return code; + else /* Do the full version. */ + return m_message.type(); + } + case 2: + return m_message.description(); + default: + { + Q_ASSERT(false); + return QVariant(); + } + } +} + +TreeItem::List ErrorItem::children() const +{ + return m_children; +} + +void ErrorItem::appendChild(TreeItem *item) +{ + m_children.append(item); +} + +TreeItem *ErrorItem::child(const unsigned int rowP) const +{ + return m_children.value(rowP); +} + +unsigned int ErrorItem::childCount() const +{ + return m_children.count(); +} + +TreeItem *ErrorItem::parent() const +{ + return m_parent; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ErrorItem.h b/tests/auto/xmlpatternssdk/ErrorItem.h new file mode 100644 index 0000000..b8ae05c --- /dev/null +++ b/tests/auto/xmlpatternssdk/ErrorItem.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ErrorItem_H +#define PatternistSDK_ErrorItem_H + +#include <QList> + +#include "ErrorHandler.h" +#include "Global.h" +#include "TreeItem.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Delegates a ErrorHandler::Message through the interface + * exposed by TreeItem, such that errors from DOM related code + * can be displayed/used in Qt's model/view framework. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ErrorItem : public TreeItem + { + public: + ErrorItem(const ErrorHandler::Message &error, ErrorItem *parent); + virtual ~ErrorItem(); + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + virtual void appendChild(TreeItem *item); + virtual TreeItem *child(const unsigned int row) const; + virtual unsigned int childCount() const; + virtual TreeItem::List children() const; + virtual TreeItem *parent() const; + int columnCount() const; + + private: + static QString toString(const QtMsgType sev); + + const ErrorHandler::Message m_message; + ErrorItem * m_parent; + TreeItem::List m_children; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ExitCode.h b/tests/auto/xmlpatternssdk/ExitCode.h new file mode 100644 index 0000000..c284ac7 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExitCode.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ExitCode_H +#define PatternistSDK_ExitCode_H + +#include "Global.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Houses program exit codes for PatternistSDK utilities. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ExitCode + { + public: + /** + * Exit codes for programs part of PatternistSDK. The values for the enums are specified + * to make it easily understandable what number a symbol corresponds to. + */ + enum Code + { + Success = 0, + InvalidArgCount = 1, + InvalidArgs = 2, + + /** + * Used in @c patternistrunsuite + */ + InvalidCatalogFile = 3, + FileNotExists = 4, + OpenError = 5, + WriteError = 6, + + /** + * Used in the test program used for comparing files on the byte level. + */ + NotEqual = 7, + UnevenTestCount = 8, + InternalError = 9, + Regression = 10 + }; + + private: + /** + * This constructor is private and has no implementation, because this + * class is not supposed to be instantiated. + */ + inline ExitCode(); + + Q_DISABLE_COPY(ExitCode) + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ExpressionInfo.cpp b/tests/auto/xmlpatternssdk/ExpressionInfo.cpp new file mode 100644 index 0000000..92fc8e0 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExpressionInfo.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "ExpressionInfo.h" + +using namespace QPatternistSDK; + +ExpressionInfo::ExpressionInfo(const QString &name, + const QString &details) : QPair<QString, QString>(name, details) +{ +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/ExpressionInfo.h b/tests/auto/xmlpatternssdk/ExpressionInfo.h new file mode 100644 index 0000000..eb56d17 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExpressionInfo.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ExpressionInfo_H +#define PatternistSDK_ExpressionInfo_H + +#include "Global.h" +#include "qexpressiondispatch_p.h" + +#include <QPair> +#include <QString> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Houses debug information about an QPatternist::Expression instance. + * + * An Expression's name, typically its class name, can be retrieved + * via the member variable first, and additional data, for example its string + * value or operator, can be retrieved via the member variable second. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ExpressionInfo : public QPatternist::ExpressionVisitorResult + , public QPair<QString, QString> + { + public: + ExpressionInfo(const QString &name, const QString &details); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ExpressionNamer.cpp b/tests/auto/xmlpatternssdk/ExpressionNamer.cpp new file mode 100644 index 0000000..045b77c --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExpressionNamer.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "qabstractfloat_p.h" +#include "qandexpression_p.h" +#include "qanyuri_p.h" +#include "qapplytemplate_p.h" +#include "qargumentreference_p.h" +#include "qarithmeticexpression_p.h" +#include "qatomicstring_p.h" +#include "qatomizer_p.h" +#include "qattributeconstructor_p.h" +#include "qattributenamevalidator_p.h" +#include "qaxisstep_p.h" +#include "qbase64binary_p.h" +#include "qboolean_p.h" +#include "qcardinalityverifier_p.h" +#include "qcastableas_p.h" +#include "qcastas_p.h" +#include "qcombinenodes_p.h" +#include "qcontextitem_p.h" +#include "qdate_p.h" +#include "qdecimal_p.h" +#include "qdynamiccontextstore_p.h" +#include "qelementconstructor_p.h" +#include "qemptysequence_p.h" +#include "qevaluationcache_p.h" +#include "qexpressionsequence_p.h" +#include "qexpressionvariablereference_p.h" +#include "qfirstitempredicate_p.h" +#include "qforclause_p.h" +#include "qfunctioncall_p.h" +#include "qgday_p.h" +#include "qgeneralcomparison_p.h" +#include "qgenericpredicate_p.h" +#include "qgmonthday_p.h" +#include "qgmonth_p.h" +#include "qgyearmonth_p.h" +#include "qgyear_p.h" +#include "qhexbinary_p.h" +#include "qifthenclause_p.h" +#include "qinstanceof_p.h" +#include "qinteger_p.h" +#include "qitem_p.h" +#include "qitemverifier_p.h" +#include "qliteral_p.h" +#include "qnamespaceconstructor_p.h" +#include "qncnameconstructor_p.h" +#include "qnodecomparison_p.h" +#include "qorexpression_p.h" +#include "qpath_p.h" +#include "qpositionalvariablereference_p.h" +#include "qqnameconstructor_p.h" +#include "qqnamevalue_p.h" +#include "qquantifiedexpression_p.h" +#include "qrangeexpression_p.h" +#include "qrangevariablereference_p.h" +#include "qschemadatetime_p.h" +#include "qschematime_p.h" +#include "qsimplecontentconstructor_p.h" +#include "qtreatas_p.h" +#include "qtruthpredicate_p.h" +#include "quntypedatomicconverter_p.h" +#include "quntypedatomic_p.h" +#include "quserfunctioncallsite_p.h" +#include "qvalidationerror_p.h" +#include "qvaluecomparison_p.h" + +#include "ExpressionInfo.h" +#include "Global.h" + +#include "ExpressionNamer.h" + +using namespace QPatternistSDK; + +/* Simple ones, they have no additional data. */ +#define implClass(cls) \ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::cls *) const \ +{ \ + return QPatternist::ExpressionVisitorResult::Ptr \ + (new ExpressionInfo(QLatin1String(#cls), QString())); \ +} + +implClass(AndExpression) +implClass(ArgumentConverter) +implClass(Atomizer) +implClass(AttributeConstructor) +implClass(AttributeNameValidator) +implClass(CallTemplate) +implClass(CardinalityVerifier) +implClass(CollationChecker) +implClass(CommentConstructor) +implClass(ComputedNamespaceConstructor) +implClass(ContextItem) +implClass(CopyOf) +implClass(CurrentItemStore) +implClass(DocumentConstructor) +implClass(DynamicContextStore) +implClass(EBVExtractor) +implClass(ElementConstructor) +implClass(EmptySequence) +implClass(ExpressionSequence) +implClass(ExternalVariableReference) +implClass(FirstItemPredicate) +implClass(ForClause) +implClass(GenericPredicate) +implClass(IfThenClause) +implClass(ItemVerifier) +implClass(LetClause) +implClass(LiteralSequence) +implClass(NCNameConstructor) +implClass(NodeSortExpression) +implClass(OrderBy) +implClass(OrExpression) +implClass(ParentNodeAxis) +implClass(ProcessingInstructionConstructor) +implClass(QNameConstructor) +implClass(RangeExpression) +implClass(ReturnOrderBy) +implClass(SimpleContentConstructor) +implClass(StaticBaseURIStore) +implClass(StaticCompatibilityStore) +implClass(TemplateParameterReference) +implClass(TextNodeConstructor) +implClass(TreatAs) +implClass(TruthPredicate) +implClass(UnresolvedVariableReference) +implClass(UntypedAtomicConverter) +implClass(UserFunctionCallsite) +implClass(ValidationError) +#undef implClass + +/** Variable references. */ +#define implVarRef(name) \ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::name *i) const \ +{ \ + return QPatternist::ExpressionVisitorResult::Ptr \ + (new ExpressionInfo(QLatin1String(#name), \ + QString(QLatin1String("Slot: %1")).arg(i->slot()))); \ +} +implVarRef(RangeVariableReference) +implVarRef(ArgumentReference) +implVarRef(ExpressionVariableReference) +implVarRef(PositionalVariableReference) +#undef implVarRef + +/* Type related classes which have a targetType() function. */ +#define implTypeClass(cls) \ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::cls *i) const \ +{ \ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String(#cls), \ + i->targetType()->displayName(Global::namePool()))); \ +} + +implTypeClass(InstanceOf) +implTypeClass(CastableAs) +#undef implTypeClass + +/* Type related classes which have a targetType() function. */ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::CastAs *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("CastAs"), + i->targetSequenceType()->displayName(Global::namePool()))); +} + +/* Classes which represent operators. */ +#define implOPClass(cls, compClass) \ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::cls *i) const \ +{ \ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String(#cls), \ + QPatternist::compClass::displayName(i->operatorID()))); \ +} + +implOPClass(ArithmeticExpression, AtomicMathematician) +implOPClass(NodeComparison, NodeComparison) +implOPClass(QuantifiedExpression, QuantifiedExpression) +implOPClass(CombineNodes, CombineNodes) +#undef implOPClass + +/* Classes which represent operators. */ +#define implCompClass(cls, type) \ +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::cls *i) const \ +{ \ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String(#cls), \ + QPatternist::AtomicComparator::displayName(i->operatorID(), \ + QPatternist::AtomicComparator::type))); \ +} + +implCompClass(GeneralComparison, AsGeneralComparison) +implCompClass(ValueComparison, AsValueComparison) +#undef implCompClass + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::FunctionCall *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr + (new ExpressionInfo(QLatin1String("FunctionCall"), + Global::namePool()->displayName(i->signature()->name()))); +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::Literal *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo( + i->item().type()->displayName(Global::namePool()), + i->item().stringValue())); +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::AxisStep *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("AxisStep"), + QPatternist::AxisStep::axisName(i->axis()) + + QLatin1String("::") + + i->nodeTest()->displayName(Global::namePool()))); + +} + + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::EvaluationCache<true> *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("EvaluationCache<IsForGlobal=true>"), + QLatin1String("Slot: ") + QString::number(i->slot()))); + +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::EvaluationCache<false> *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("EvaluationCache<IsForGlobal=false>"), + QLatin1String("Slot: ") + QString::number(i->slot()))); + +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::NamespaceConstructor *i) const +{ + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("NamespaceConstructor"), + Global::namePool()->stringForPrefix(i->namespaceBinding().prefix()) + + QLatin1Char('=') + + Global::namePool()->stringForNamespace(i->namespaceBinding().namespaceURI()))); + +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::Path *path) const +{ + + QPatternist::Path::Kind k = path->kind(); + QString type; + + switch(k) + { + case QPatternist::Path::XSLTForEach: + { + type = QLatin1String("XSLTForEach"); + break; + } + case QPatternist::Path::RegularPath: + { + type = QLatin1String("RegularPath"); + break; + } + case QPatternist::Path::ForApplyTemplate: + { + type = QLatin1String("ForApplyTemplate"); + break; + } + } + + return QPatternist::ExpressionVisitorResult::Ptr(new ExpressionInfo(QLatin1String("Path"), type)); +} + +QPatternist::ExpressionVisitorResult::Ptr ExpressionNamer::visit(const QPatternist::ApplyTemplate *path) const +{ + const QPatternist::TemplateMode::Ptr mode(path->mode()); + return QPatternist::ExpressionVisitorResult::Ptr + (new ExpressionInfo(QLatin1String("ApplyTemplate"), mode ? Global::namePool()->displayName(mode->name()) : QString::fromLatin1("#current"))); +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/ExpressionNamer.h b/tests/auto/xmlpatternssdk/ExpressionNamer.h new file mode 100644 index 0000000..6cdbed5 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExpressionNamer.h @@ -0,0 +1,281 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ExpressionNamer_H +#define PatternistSDK_ExpressionNamer_H + +#include "Global.h" +#include "qexpressiondispatch_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Extracts debug information from a QPatternist::Expression tree. + * + * This data is the name of the AST node(typically the class name), + * and additional data such as the value, type of operator, and so forth. The result + * is returned(from visit()), is an ExpressionInfo instance. + * + * @see ExpressionInfo + * @see ASTItem + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ExpressionNamer : public QPatternist::ExpressionVisitor + { + public: + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::AndExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ApplyTemplate *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ArgumentReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ArithmeticExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::Atomizer *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::AttributeConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::AttributeNameValidator *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CallTemplate *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CardinalityVerifier *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CastAs *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CastableAs *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CollationChecker *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CombineNodes *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ComputedNamespaceConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CommentConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ContextItem *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CopyOf *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::CurrentItemStore *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::DocumentConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::DynamicContextStore *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::EBVExtractor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ElementConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::EmptySequence *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ExpressionSequence *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ExpressionVariableReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ExternalVariableReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::EvaluationCache<true> *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::EvaluationCache<false> *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::FirstItemPredicate *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ForClause *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::FunctionCall *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::GeneralComparison *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::GenericPredicate *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::IfThenClause *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::InstanceOf *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ItemVerifier *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::LetClause *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::Literal *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::LiteralSequence *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::NCNameConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::NodeComparison *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::NodeSortExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::OrderBy *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::OrExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ParentNodeAxis *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::Path *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::PositionalVariableReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ProcessingInstructionConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::QNameConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::QuantifiedExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::RangeExpression *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::RangeVariableReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ReturnOrderBy *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::SimpleContentConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::StaticBaseURIStore *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::StaticCompatibilityStore *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::AxisStep *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::TemplateParameterReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::TextNodeConstructor *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::TreatAs *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::TruthPredicate *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::UntypedAtomicConverter *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::UnresolvedVariableReference *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ArgumentConverter *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::UserFunctionCallsite *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ValidationError *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::ValueComparison *) const; + + virtual QPatternist::ExpressionVisitorResult::Ptr + visit(const QPatternist::NamespaceConstructor *) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ExternalSourceLoader.cpp b/tests/auto/xmlpatternssdk/ExternalSourceLoader.cpp new file mode 100644 index 0000000..929ad4e --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExternalSourceLoader.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <QFile> +#include <QtDebug> +#include <QXmlResultItems> +#include <QXmlNamePool> + +#include "Global.h" + +#include "qcommonsequencetypes_p.h" +#include "qdebug_p.h" +#include "qatomicstring_p.h" + +#include "ExternalSourceLoader.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +ExternalSourceLoader::ExternalSourceLoader(const VariableMap &varMap, + const QPatternist::ResourceLoader::Ptr &r) : m_variableMap(varMap) + , m_resourceLoader(r) + , m_query(Global::namePoolAsPublic()) +{ + Q_ASSERT(m_resourceLoader); +} + +QPatternist::SequenceType::Ptr +ExternalSourceLoader::announceExternalVariable(const QXmlName name, + const QPatternist::SequenceType::Ptr &declaredType) +{ + pDebug() << "ExternalSourceLoader::announceExternalVariable()"; + Q_ASSERT(!name.isNull()); + Q_ASSERT(declaredType); + Q_UNUSED(declaredType); /* Needed when bulding in release mode. */ + + if(name.namespaceURI() == QPatternist::StandardNamespaces::empty) + { + const VariableValue variable(m_variableMap.value(Global::namePool()->stringForLocalName(name.localName()))); + + if(variable.first.isEmpty()) + return QPatternist::SequenceType::Ptr(); + else + { + /* If announceDocument() can't load a document for uriForVar, it will return + * null, which we will too, which is fine, since we can't supply a value for + * this variable then. */ + if(variable.second == Document) + return m_resourceLoader->announceDocument(variable.first, QPatternist::ResourceLoader::WillUse); + else if(variable.second == URI) + { + return QPatternist::CommonSequenceTypes::ExactlyOneString; + } + else + { + /* The type is Query, and we don't pre-load + * them. No particular reason, just not worth it. */ + return QPatternist::CommonSequenceTypes::ZeroOrMoreItems; + } + } + } + else + return QPatternist::SequenceType::Ptr(); +} + +QPatternist::Item +ExternalSourceLoader::evaluateSingleton(const QXmlName name, + const QPatternist::DynamicContext::Ptr &context) +{ + Q_ASSERT(!name.isNull()); + const VariableValue variable(m_variableMap.value(Global::namePool()->stringForLocalName(name.localName()))); + + if(variable.second == Document) + { + Q_ASSERT_X(QFile::exists(variable.first.toLocalFile()), Q_FUNC_INFO, + qPrintable(QString::fromLatin1("The file %1 doesn't exist").arg(variable.first.toLocalFile()))); + Q_ASSERT_X(m_resourceLoader->openDocument(variable.first, context), Q_FUNC_INFO, + "We're supposed to have the value. If not, an error should have been issued at query compile time."); + + return m_resourceLoader->openDocument(variable.first, context); + } + else if(variable.second == Query) + { + /* Well, here we open the file and execute it. */ + m_query.setQuery(QUrl::fromLocalFile(variable.first.toLocalFile())); + Q_ASSERT(m_query.isValid()); + + QXmlResultItems result; + m_query.evaluateTo(&result); + + return QPatternist::Item::fromPublic(result.next()); + } + else + { + Q_ASSERT(variable.second == URI); + return QPatternist::AtomicString::fromValue(variable.first.toString()); + } +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/ExternalSourceLoader.h b/tests/auto/xmlpatternssdk/ExternalSourceLoader.h new file mode 100644 index 0000000..09da363 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ExternalSourceLoader.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ExternalSourceLoader_H +#define PatternistSDK_ExternalSourceLoader_H + +#include <QHash> +#include <QUrl> +#include <QXmlQuery> + +#include "qdynamiccontext_p.h" +#include "qresourceloader_p.h" +#include "qexternalvariableloader_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Handles external variables in XQTS queries, such as <tt>$input-context</tt>, + * by loading appropriate XML source files. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT ExternalSourceLoader : public QPatternist::ExternalVariableLoader + { + public: + enum TargetOfURI + { + /** + * Identifies @c input-file. + */ + Document, + + /** + * Identifies @c input-URI. + */ + URI, + + /** + * Identifies @c input-query. + */ + Query + }; + + /** + * The first is the complete, absolute, final URI to the file to be loaded, + * and the second is the type of source found at that URI. + */ + typedef QPair<QUrl, TargetOfURI> VariableValue; + + /** + * In the XQTSCatalog.xml each source file in each test is referred to + * by a key, which can be fully looked up in the @c sources element. This QHash + * maps the keys to absolute URIs pointing to the source file. + */ + typedef QHash<QString, QUrl> SourceMap; + + /** + * The first value is the variable name, and the second is the URI identifying + * the XML source file that's supposed to be loaded as a document. + * + * This is one for every test case, except for @c rdb-queries-results-q5, + * @c rdb-queries-results-q17 and @c rdb-queries-results-q18(at least in XQTS 1.0). + */ + typedef QHash<QString, VariableValue> VariableMap; + + ExternalSourceLoader(const VariableMap &varMap, + const QPatternist::ResourceLoader::Ptr &resourceLoader); + + virtual QPatternist::SequenceType::Ptr + announceExternalVariable(const QXmlName name, + const QPatternist::SequenceType::Ptr &declaredType); + + virtual QPatternist::Item + evaluateSingleton(const QXmlName name, + const QPatternist::DynamicContext::Ptr &context); + + VariableMap variableMap() const + { + return m_variableMap; + } + + private: + const VariableMap m_variableMap; + const QPatternist::ResourceLoader::Ptr m_resourceLoader; + QXmlQuery m_query; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/Global.cpp b/tests/auto/xmlpatternssdk/Global.cpp new file mode 100644 index 0000000..a1c31ed --- /dev/null +++ b/tests/auto/xmlpatternssdk/Global.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QXmlNamePool> + +#include "Global.h" + +using namespace QPatternistSDK; + +const QString Global::xqtsCatalogNS (QLatin1String("http://www.w3.org/2005/02/query-test-XQTSCatalog")); +const QString Global::xqtsResultNS (QLatin1String("http://www.w3.org/2005/02/query-test-XQTSResult")); +const QString Global::xsltsCatalogNS (QLatin1String("http://www.w3.org/2005/05/xslt20-test-catalog")); +const QString Global::organizationName (QLatin1String("Patternist Team")); +const qint16 Global::versionNumber (0x01); + +static QXmlNamePool s_namePool; + +QPatternist::NamePool::Ptr Global::namePool() +{ + return s_namePool.d; +} + +QXmlNamePool Global::namePoolAsPublic() +{ + return s_namePool; +} + +bool Global::readBoolean(const QString &value) +{ + const QString normd(value.simplified()); + + if(normd == QLatin1String("true") || + normd == QLatin1String("1")) + return true; + else if(normd.isEmpty() || + normd == QLatin1String("false") || + normd == QLatin1String("0")) + return false; + + Q_ASSERT_X(false, Q_FUNC_INFO, + "The lexical representation of xs:boolean was invalid"); + return false; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/Global.h b/tests/auto/xmlpatternssdk/Global.h new file mode 100644 index 0000000..30c0edf --- /dev/null +++ b/tests/auto/xmlpatternssdk/Global.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_Global_H +#define PatternistSDK_Global_H + +#include <QString> + +#include "private/qitem_p.h" +#include "private/qnamepool_p.h" + +#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +# ifdef Q_PATTERNISTSDK_BUILDING + #define Q_PATTERNISTSDK_EXPORT __declspec(dllexport) + #else + #define Q_PATTERNISTSDK_EXPORT __declspec(dllimport) + #endif +#else + #define Q_PATTERNISTSDK_EXPORT +#endif + +/** + * @short Contains testing utilities for Patternist, interfacing W3C's XQuery Test Suite. + * + * @see <a href="http://www.w3.org/XML/Query/test-suite/">XML Query Test Suite</a> + * @author Frans Englich <frans.englich@nokia.com> + */ +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Contains global constants. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT Global + { + public: + + /** + * The namespace which the XQTS test case catalog(specified by Catalog.xsd) + * is in. The namespace is: <tt>http://www.w3.org/2005/02/query-test-XQTSCatalog</tt> + */ + static const QString xqtsCatalogNS; + + /** + * The namespace which the XQTS test results collection(specified by XQTSResult.xsd) + * is in. The namespace is: <tt>http://www.w3.org/2005/02/query-test-XQTSResult</tt> + */ + static const QString xqtsResultNS; + + /** + * The organization which created PatternistSDK. It say something + * in the direction of "Patternist Team", and is used for QSettings and the like. + */ + static const QString organizationName; + + /** + * The namespace which W3C's XSL-T test suite resides in. + */ + static const QString xsltsCatalogNS; + + /** + * The version of PatternistSDK. The value has currently no other + * meaning than that larger means older. This version information is supplied to + * QMainWindow::restoreState() and QMainWindow::saveState(). + */ + static const qint16 versionNumber; + + /** + * Parses the lexical space of @c xs:boolean, + * with the exception that the empty string is considered @c false. + */ + static bool readBoolean(const QString &lexicalSpace); + + static QPatternist::NamePool::Ptr namePool(); + static QXmlNamePool namePoolAsPublic(); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ResultThreader.cpp b/tests/auto/xmlpatternssdk/ResultThreader.cpp new file mode 100644 index 0000000..2758906 --- /dev/null +++ b/tests/auto/xmlpatternssdk/ResultThreader.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QEventLoop> + +#include "ResultThreader.h" + +using namespace QPatternistSDK; + +ResultThreader::ResultThreader(QEventLoop &ev, + QFile *file, + const Type t, + QObject *p) : QThread(p) + , m_file(file) + , m_type(t) + , m_eventLoop(ev) +{ + Q_ASSERT_X(p, Q_FUNC_INFO, "Should have a parent"); + Q_ASSERT_X(file, Q_FUNC_INFO, "Should have a valid file"); + Q_ASSERT(m_type == Baseline || m_type == Result); +} + +void ResultThreader::run() +{ + QXmlSimpleReader reader; + reader.setContentHandler(this); + + QXmlInputSource source(m_file); + reader.parse(source); + m_file->close(); +} + +ResultThreader::Type ResultThreader::type() const +{ + return m_type; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/ResultThreader.h b/tests/auto/xmlpatternssdk/ResultThreader.h new file mode 100644 index 0000000..53ec70c --- /dev/null +++ b/tests/auto/xmlpatternssdk/ResultThreader.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_ResultThreader_H +#define PatternistSDK_ResultThreader_H + +#include <QFile> +#include <QFileInfo> +#include <QThread> + +#include "TestResultHandler.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QEventLoop; + +namespace QPatternistSDK +{ + /** + * @short Reads XML in the @c XQTSResult.xsd format, as a thread, allowing + * multiple parses to be done simultaneously. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup PatternistSDK + */ + class Q_PATTERNISTSDK_EXPORT ResultThreader : public QThread + , public TestResultHandler + { + public: + enum Type + { + Baseline = 1, + Result + }; + + /** + * Creates a ResultThreader that will read @p file when run() is called. + */ + ResultThreader(QEventLoop &ev, + QFile *file, + const Type type, + QObject *parent); + + /** + * Parses the file passed in this class's constructor with this ResultHandlerTH::Item::LisT + * as the QXmlContentHandler, and returns. + */ + virtual void run(); + + /** + * @note Do not reimplement this function. + * @returns whether this ResultThreader handles the baseline or the result. + */ + Type type() const; + + private: + Q_DISABLE_COPY(ResultThreader) + + QFile *const m_file; + const Type m_type; + QEventLoop & m_eventLoop; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestBaseLine.cpp b/tests/auto/xmlpatternssdk/TestBaseLine.cpp new file mode 100644 index 0000000..c54fad3 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestBaseLine.cpp @@ -0,0 +1,511 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDomDocument> +#include <QFile> +#include <QFileInfo> +#include <QRegExp> +#include <QtDebug> +#include <QUrl> +#include <QXmlAttributes> +#include <QXmlSimpleReader> + +#include "qdebug_p.h" +#include "XMLWriter.h" + +#include "TestBaseLine.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +Q_GLOBAL_STATIC_WITH_ARGS(QRegExp, errorRegExp, (QLatin1String("[A-Z]{4}[0-9]{4}"))) + +TestBaseLine::TestBaseLine(const Type t) : m_type(t) +{ + Q_ASSERT(errorRegExp()->isValid()); +} + +TestResult::Status TestBaseLine::scan(const QString &serialized, + const TestBaseLine::List &lines) +{ + Q_ASSERT_X(lines.count() >= 1, Q_FUNC_INFO, + "At least one base line must be passed, otherwise there's nothing " + "to compare to."); + + const TestBaseLine::List::const_iterator end(lines.constEnd()); + TestBaseLine::List::const_iterator it(lines.constBegin()); + for(; it != end; ++it) + { + const TestResult::Status retval((*it)->verify(serialized)); + + if(retval == TestResult::Pass || retval == TestResult::NotTested) + return retval; + } + + return TestResult::Fail; +} + +TestResult::Status TestBaseLine::scanErrors(const ErrorHandler::Message::List &errors, + const TestBaseLine::List &lines) +{ + pDebug() << "TestBaseLine::scanErrors()"; + + /* 1. Find the first error in @p errors that's a Patternist + * error(not warning and not from Qt) and extract the error code. */ + QString errorCode; + + const ErrorHandler::Message::List::const_iterator end(errors.constEnd()); + ErrorHandler::Message::List::const_iterator it(errors.constBegin()); + for(; it != end; ++it) + { + if((*it).type() != QtFatalMsg) + continue; + + errorCode = QUrl((*it).identifier()).fragment(); + + pDebug() << "ERR:" << (*it).description(); + /* This is hackish. We have no way of determining whether a Message + * is actually issued from Patternist, so we try to narrow it down like this. */ + if(errorRegExp()->exactMatch(errorCode)) + break; /* It's an error code. */ + else + errorCode.clear(); + } + + pDebug() << "Got error code: " << errorCode; + /* 2. Loop through @p lines, and for the first base line + * which is of type ExpectedError and which matches @p errorCode + * return Pass, otherwise Fail. */ + const TestBaseLine::List::const_iterator blend(lines.constEnd()); + TestBaseLine::List::const_iterator blit(lines.constBegin()); + for(; blit != blend; ++blit) + { + const Type t = (*blit)->type(); + + if(t == TestBaseLine::ExpectedError) + { + const QString d((*blit)->details()); + if(d == errorCode || d == QChar::fromLatin1('*')) + return TestResult::Pass; + } + } + + return TestResult::Fail; +} + +void TestBaseLine::toXML(XMLWriter &receiver) const +{ + switch(m_type) + { + case XML: /* Fallthrough. */ + case Fragment: /* Fallthrough. */ + case SchemaIsValid: /* Fallthrough. */ + case Text: + { + QXmlAttributes inspectAtts; + inspectAtts.append(QLatin1String("role"), QString(), + QLatin1String("role"), QLatin1String("principal")); + inspectAtts.append(QLatin1String("compare"), QString(), + QLatin1String("compare"), displayName(m_type)); + receiver.startElement(QLatin1String("output-file"), inspectAtts); + receiver.characters(m_details); + receiver.endElement(QLatin1String("output-file")); + return; + } + case Ignore: + { + Q_ASSERT_X(false, Q_FUNC_INFO, "Serializing 'Ignore' is not implemented."); + return; + } + case Inspect: + { + QXmlAttributes inspectAtts; + inspectAtts.append(QLatin1String("role"), QString(), + QLatin1String("role"), QLatin1String("principal")); + inspectAtts.append(QLatin1String("compare"), QString(), + QLatin1String("compare"), QLatin1String("Inspect")); + receiver.startElement(QLatin1String("output-file"), inspectAtts); + receiver.characters(m_details); + receiver.endElement(QLatin1String("output-file")); + return; + } + case ExpectedError: + { + receiver.startElement(QLatin1String("expected-error")); + receiver.characters(m_details); + receiver.endElement(QLatin1String("expected-error")); + return; + } + } +} + +bool TestBaseLine::isChildrenDeepEqual(const QDomNodeList &cl1, const QDomNodeList &cl2) +{ + const unsigned int len = cl1.length(); + + if(len == cl2.length()) + { + for(unsigned int i = 0; i < len; ++i) + { + if(!isDeepEqual(cl1.at(i), cl2.at(i))) + return false; + } + + return true; + } + else + return false; +} + +bool TestBaseLine::isAttributesEqual(const QDomNamedNodeMap &cl1, const QDomNamedNodeMap &cl2) +{ + const unsigned int len = cl1.length(); + pDebug() << "LEN:" << len; + + if(len == cl2.length()) + { + for(unsigned int i1 = 0; i1 < len; ++i1) + { + const QDomNode attr1(cl1.item(i1)); + Q_ASSERT(!attr1.isNull()); + + /* This is set if attr1 cannot be found at all in cl2. */ + bool earlyExit = false; + + for(unsigned int i2 = 0; i2 < len; ++i2) + { + const QDomNode attr2(cl2.item(i2)); + Q_ASSERT(!attr2.isNull()); + pDebug() << "ATTR1:" << attr1.localName() << attr1.namespaceURI() << attr1.prefix() << attr1.nodeName(); + pDebug() << "ATTR2:" << attr2.localName() << attr2.namespaceURI() << attr2.prefix() << attr2.nodeName(); + + if(attr1.localName() == attr2.localName() && + attr1.namespaceURI() == attr2.namespaceURI() && + attr1.prefix() == attr2.prefix() && + attr1.nodeName() == attr2.nodeName() && /* Yes, needed in addition to all the other. */ + attr1.nodeValue() == attr2.nodeValue()) + { + earlyExit = true; + break; + } + } + + if(!earlyExit) + { + /* An attribute was found that doesn't exist in the other list so exit. */ + return false; + } + } + + return true; + } + else + return false; +} + +bool TestBaseLine::isDeepEqual(const QDomNode &n1, const QDomNode &n2) +{ + if(n1.nodeType() != n2.nodeType()) + return false; + + switch(n1.nodeType()) + { + case QDomNode::CommentNode: + /* Fallthrough. */ + case QDomNode::TextNode: + { + return static_cast<const QDomCharacterData &>(n1).data() == + static_cast<const QDomCharacterData &>(n2).data(); + } + case QDomNode::ProcessingInstructionNode: + { + return n1.nodeName() == n2.nodeName() && + n1.nodeValue() == n2.nodeValue(); + } + case QDomNode::DocumentNode: + return isChildrenDeepEqual(n1.childNodes(), n2.childNodes()); + case QDomNode::ElementNode: + { + return n1.localName() == n2.localName() && + n1.namespaceURI() == n2.namespaceURI() && + n1.nodeName() == n2.nodeName() && /* Yes, this one is needed in addition to localName(). */ + isAttributesEqual(n1.attributes(), n2.attributes()) && + isChildrenDeepEqual(n1.childNodes(), n2.childNodes()); + } + /* Fallthrough all these. */ + case QDomNode::EntityReferenceNode: + case QDomNode::CDATASectionNode: + case QDomNode::EntityNode: + case QDomNode::DocumentTypeNode: + case QDomNode::DocumentFragmentNode: + case QDomNode::NotationNode: + case QDomNode::BaseNode: + case QDomNode::CharacterDataNode: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "An unsupported node type was encountered."); + return false; + } + case QDomNode::AttributeNode: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "This should never happen. QDom doesn't allow us to compare DOM attributes " + "properly."); + return false; + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled QDom::NodeType value."); + return false; + } + } +} + +TestResult::Status TestBaseLine::verify(const QString &serializedInput) const +{ + switch(m_type) + { + case SchemaIsValid: + /* Fall through. */ + case Text: + { + if(serializedInput == details()) + return TestResult::Pass; + else + return TestResult::Fail; + } + case Fragment: + /* Fall through. */ + case XML: + { + /* Read the baseline and the serialized input into two QDomDocuments, and compare + * them deeply. We wrap fragments in a root node such that it is well-formed XML. + */ + + QDomDocument output; + { + /* The reason we put things into a QByteArray and then parse it through QXmlSimpleReader, is that + * QDomDocument does whitespace stripping when calling setContent(QString). In other words, + * this workarounds a bug. */ + + QXmlInputSource source; + source.setData((m_type == XML ? serializedInput : QLatin1String("<r>") + + serializedInput + + QLatin1String("</r>")).toUtf8()); + + QString outputReadingError; + + QXmlSimpleReader reader; + reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), true); + + const bool success = output.setContent(&source, + &reader, + &outputReadingError); + + if(!success) + return TestResult::Fail; + + Q_ASSERT(success); + } + + QDomDocument baseline; + { + QXmlInputSource source; + source.setData((m_type == XML ? details() : QLatin1String("<r>") + + details() + + QLatin1String("</r>")).toUtf8()); + QString baselineReadingError; + + QXmlSimpleReader reader; + reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), true); + + const bool success = baseline.setContent(&source, + &reader, + &baselineReadingError); + + if(!success) + return TestResult::Fail; + + /* This piece of code workaround a bug in QDom, which treats XML prologs as processing + * instructions and make them available in the tree as so. */ + if(m_type == XML) + { + /* $doc/r/node() */ + const QDomNodeList children(baseline.childNodes()); + const int len = children.length(); + + for(int i = 0; i < len; ++i) + { + const QDomNode &child = children.at(i); + if(child.isProcessingInstruction() && child.nodeName() == QLatin1String("xml")) + { + baseline.removeChild(child); + break; + } + } + } + + Q_ASSERT_X(baselineReadingError.isNull(), Q_FUNC_INFO, + qPrintable((QLatin1String("Reading the baseline failed: ") + baselineReadingError))); + } + + if(isDeepEqual(output, baseline)) + return TestResult::Pass; + else + { + pDebug() << "FAILURE:" << output.toString() << "is NOT IDENTICAL to(baseline):" << baseline.toString(); + return TestResult::Fail; + } + } + case Ignore: + return TestResult::Pass; + case Inspect: + return TestResult::NotTested; + case ExpectedError: + { + /* This function is only called for Text/XML/Fragment tests. */ + return TestResult::Fail; + } + } + Q_ASSERT(false); + return TestResult::Fail; +} + +TestBaseLine::Type TestBaseLine::identifierFromString(const QString &string) +{ + /* "html-output: Using an ad hoc tool, it must assert that the document obeys the HTML + * Output Method as defined in the Serialization specification and section + * 20 of the XSLT 2.0 specification." We treat it as XML for now, same with + * xhtml-output. */ + if(string.compare(QLatin1String("XML"), Qt::CaseInsensitive) == 0 || + string == QLatin1String("html-output") || + string == QLatin1String("xml-output") || + string == QLatin1String("xhtml-output")) + return XML; + else if(string == QLatin1String("Fragment") || string == QLatin1String("xml-frag")) + return Fragment; + else if(string.compare(QLatin1String("Text"), Qt::CaseInsensitive) == 0) + return Text; + else if(string == QLatin1String("Ignore")) + return Ignore; + else if(string.compare(QLatin1String("Inspect"), Qt::CaseInsensitive) == 0) + return Inspect; + else + { + Q_ASSERT_X(false, Q_FUNC_INFO, + qPrintable(QString::fromLatin1("Invalid string representation for a comparation type: %1").arg(string))); + + return Ignore; /* Silence GCC. */ + } +} + +QString TestBaseLine::displayName(const Type id) +{ + switch(id) + { + case XML: + return QLatin1String("XML"); + case Fragment: + return QLatin1String("Fragment"); + case Text: + return QLatin1String("Text"); + case Ignore: + return QLatin1String("Ignore"); + case Inspect: + return QLatin1String("Inspect"); + case ExpectedError: + return QLatin1String("ExpectedError"); + case SchemaIsValid: + return QLatin1String("SchemaIsValid"); + } + + Q_ASSERT(false); + return QString(); +} + +QString TestBaseLine::details() const +{ + if(m_type == Ignore) /* We're an error code. */ + return QString(); + if(m_type == ExpectedError) /* We're an error code. */ + return m_details; + if(m_type == SchemaIsValid) /* We're a schema validation information . */ + return m_details; + + if(m_details.isEmpty()) + return m_details; + + /* m_details is a file name, we open it and return the result. */ + QFile file(QUrl(m_details).toLocalFile()); + + QString retval; + if(!file.exists()) + retval = QString::fromLatin1("%1 does not exist.").arg(file.fileName()); + else if(!QFileInfo(file.fileName()).isFile()) + retval = QString::fromLatin1("%1 is not a file, cannot display it.").arg(file.fileName()); + else if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) + retval = QString::fromLatin1("Could not open %1. Likely a permission error.").arg(file.fileName()); + + if(retval.isNull()) + { + /* Scary, we assume the query/baseline is in UTF-8. */ + return QString::fromUtf8(file.readAll()); + } + else + { + /* We had a file error. */ + retval.prepend(QLatin1String("Test-suite harness error: ")); + qCritical() << retval; + return retval; + } +} + +TestBaseLine::Type TestBaseLine::type() const +{ + return m_type; +} + +void TestBaseLine::setDetails(const QString &detailsP) +{ + m_details = detailsP; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestBaseLine.h b/tests/auto/xmlpatternssdk/TestBaseLine.h new file mode 100644 index 0000000..b48ab49 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestBaseLine.h @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestBaseLine_H +#define PatternistSDK_TestBaseLine_H + +#include <QString> + +#include "Global.h" +#include "TestResult.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDomNamedNodeMap; +class QDomNode; +class QDomNodeList; +template<typename T> class QList; + +namespace QPatternistSDK +{ + /** + * @short Represents an expected test result for a test case. + * + * TestBaseLine represents a valid outcome for a test case, + * the "base line". A XQTS test case can have many different valid + * base lines, and one TestBaseLine instance represents on of them. + * + * Of highest interest, TestBaseLine have the function scan() and + * scanErrors(), which allows serialized output to be + * compared to the base line. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestBaseLine + { + public: + typedef QList<TestBaseLine *> List; + + /** + * Identifies what kind of comparator to use. The documentation + * for each enumerator is copied from + * <a href="http://www.w3.org/XML/Query/test-suite/Guidelines + * for Running the XML Query Test Suite.html">Guidelines + * for Running the XML Query Test Suite</a> + */ + enum Type + { + /** + * The test harness must canonicalize both, the actual result + * and the expected result according to the "Canonical XML" recommendation [2], + * which refers to a number of open-source implementations. Byte-comparison can + * then be applied to the resulting XML documents. If the test harness does + * this process in a different manner, it must be documented. + */ + XML, + + /** + * For XML fragments, the same root node must be created for both, + * implementation result and test suite result. The resulting XML + * can be compared using XML comparison. + */ + Fragment, + + /** + * Text (that has been produced by XML serialization) is compared + * using byte-comparison. + */ + Text, + + /** + * No comparison needs to be applied; the result is always @c true if + * the implementation successfully executes the test case. + */ + Ignore, + + /** + * A human is required to make the call about correctness of the result + * according to the description in the test case. + */ + Inspect, + + /** + * The expected result of the test case is an error, identified as an + * eight-character error code (e.g., XPST0003). The result of a test is + * @c true, if the implementation raises an error. However, raising an error + * because an implementation does not support the feature is not + * considered a correct result. + */ + ExpectedError, + + /** + * A special comparison for the schema validation tests. The details + * can only be 'true' or 'false' depending on whether it is a valid + * schema or not. + */ + SchemaIsValid + }; + + /** + * Takes a string identifying a comparator either in the XSL-T or the + * XQuery test suite, and returns an enum value for it. + * + * If the value is unknown, the code asserts. + */ + static Type identifierFromString(const QString &string); + + /** + * @returns a display name for @p id. For example, if Inspect was passed, "Inspect" + * would be returned. + */ + static QString displayName(const Type id); + + /** + * Compares @p items(typically the result of an evaluation) against + * the base lines @p lines. + * + * @returns the status of the first base line which passes, + * otherwise TestResult::Fail. + */ + static TestResult::Status scan(const QString &serialized, + const TestBaseLine::List &lines); + + static TestResult::Status scanErrors(const ErrorHandler::Message::List &errors, + const TestBaseLine::List &lines); + + /** + * Constructs a TestBaseLine of type @p type. + */ + TestBaseLine(const Type type); + + /** + * What @p details contains depends on the type(). If the type() is ExpectedError, + * @p details contains the relevant error code. If the type() is one which compares + * result against a base line, it is a filename locating the baseline. + */ + void setDetails(const QString &details); + + Type type() const; + + QString details() const; + + void toXML(XMLWriter &receiver) const; + + protected: + TestResult::Status verify(const QString &serializedInput) const; + + private: + static bool isDeepEqual(const QDomNode &n1, const QDomNode &n2); + + /** + * @returns @c true if the nodes in @p cl1 are equal to @p cl2, by calling isDeepEqual() + * for each pair. + */ + static bool isChildrenDeepEqual(const QDomNodeList &cl1, const QDomNodeList &cl2); + + /** + * Considers @p cl1 and @p cl2 to be lists containing attributes. The list are equal + * if they contain attributes by same value and name, but regardless of order. + */ + static bool isAttributesEqual(const QDomNamedNodeMap &cl1, const QDomNamedNodeMap &cl2); + const Type m_type; + QString m_details; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestCase.cpp b/tests/auto/xmlpatternssdk/TestCase.cpp new file mode 100644 index 0000000..49656ac --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestCase.cpp @@ -0,0 +1,439 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QBuffer> +#include <QUrl> +#include <QXmlAttributes> +#include <QXmlQuery> +#include <QXmlResultItems> +#include <QXmlSerializer> +#include <qxmlquery_p.h> + +#include "DebugExpressionFactory.h" +#include "ExternalSourceLoader.h" +#include "Global.h" +#include "TestSuite.h" +#include "XMLWriter.h" + +#include "TestCase.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +// STATIC DATA +static const DebugExpressionFactory::Ptr s_exprFact(new DebugExpressionFactory()); + +TestCase::TestCase() : m_result(0) +{ +} + +TestCase::~TestCase() +{ + delete m_result; +} + +TestResult::List TestCase::execute(const ExecutionStage stage, + TestSuite *) +{ + if(name() == QLatin1String("Constr-cont-document-3")) + { + TestResult::List result; + result.append(createTestResult(TestResult::Fail, QLatin1String("Skipped this test, because we loop infinitely on it."))); + return result; + } + else if(name() == QLatin1String("Axes089")) + { + TestResult::List result; + result.append(createTestResult(TestResult::Fail, QLatin1String("Skipped this test, we crash on it."))); + return result; + } + + qDebug() << "Running test case: " << name(); + + return execute(stage); + + Q_ASSERT(false); + return TestResult::List(); +} + +TestResult *TestCase::createTestResult(const TestResult::Status status, + const QString &comment) const +{ + TestResult *const result = new TestResult(name(), + status, + 0 /* We don't have an AST. */, + ErrorHandler::Message::List(), + QPatternist::Item::List(), + QString()); + result->setComment(comment); + return result; +} + +TestResult::List TestCase::execute(const ExecutionStage stage) +{ + ErrorHandler errHandler; + ErrorHandler::installQtMessageHandler(&errHandler); + + pDebug() << "TestCase::execute()"; + delete m_result; + + QXmlQuery query(language(), Global::namePoolAsPublic()); + + query.d->setExpressionFactory(s_exprFact); + query.setInitialTemplateName(initialTemplateName()); + + QXmlQuery openDoc(query.namePool()); + + if(contextItemSource().isValid()) + { + openDoc.setQuery(QString::fromLatin1("doc('") + contextItemSource().toString() + QLatin1String("')")); + Q_ASSERT(openDoc.isValid()); + QXmlResultItems result; + + openDoc.evaluateTo(&result); + const QXmlItem item(result.next()); + Q_ASSERT(!item.isNull()); + query.setFocus(item); + } + + TestResult::List retval; + + const Scenario scen(scenario()); + TestResult::Status resultStatus = TestResult::Unknown; + + bool ok = false; + const QString queryString(sourceCode(ok)); + + if(!ok) + { + /* Loading the query file failed, or similar. */ + resultStatus = TestResult::Fail; + + m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(), + errHandler.messages(), QPatternist::Item::List(), QString()); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; + } + + query.setMessageHandler(&errHandler); + QXmlNamePool namePool(query.namePool()); + + /* Bind variables. */ + QPatternist::ExternalVariableLoader::Ptr loader(externalVariableLoader()); + if(loader) + { + Q_ASSERT(loader); + const ExternalSourceLoader::VariableMap vMap(static_cast<const ExternalSourceLoader *>(loader.data())->variableMap()); + const QStringList variables(vMap.keys()); + + for(int i = 0; i < variables.count(); ++i) + { + const QXmlName name(namePool, variables.at(i)); + const QXmlItem val(QPatternist::Item::toPublic(loader->evaluateSingleton(name, QPatternist::DynamicContext::Ptr()))); + query.bindVariable(name, val); + } + } + + /* We pass in the testCasePath(), such that the base URI is correct fort + * XSL-T stylesheets. */ + query.setQuery(queryString, testCasePath()); + + if(!query.isValid()) + { + pDebug() << "Got compilation exception."; + resultStatus = TestBaseLine::scanErrors(errHandler.messages(), baseLines()); + + Q_ASSERT(resultStatus != TestResult::Unknown); + m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(), + errHandler.messages(), QPatternist::Item::List(), QString()); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; + } + + if(stage == CompileOnly) + { + m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(), + errHandler.messages(), QPatternist::Item::List(), QString()); + retval.append(m_result); + return retval; + } + + Q_ASSERT(stage == CompileAndRun); + + if(scen == ParseError) /* We're supposed to have received an error + at this point. */ + { + m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(), + errHandler.messages(), QPatternist::Item::List(), QString()); + ErrorHandler::installQtMessageHandler(0); + retval.append(m_result); + changed(this); + return retval; + } + + QPatternist::Item::List itemList; + + QByteArray output; + QBuffer buffer(&output); + buffer.open(QIODevice::WriteOnly); + + QXmlSerializer serializer(query, &buffer); + + pDebug() << "-------------------------- evaluateToPushCallback() ---------------------------- "; + const bool success = query.evaluateTo(&serializer); + pDebug() << "------------------------------------------------------------------------------------ "; + + buffer.close(); + + const QString serialized(QString::fromUtf8(output.constData(), output.size())); + + if(!success) + { + resultStatus = TestBaseLine::scanErrors(errHandler.messages(), baseLines()); + + Q_ASSERT(resultStatus != TestResult::Unknown); + m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(), + errHandler.messages(), QPatternist::Item::List(), serialized); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; + } + + /* It's a regular test. */ + Q_ASSERT(scen == Standard || scen == RuntimeError); + + resultStatus = TestBaseLine::scan(serialized, baseLines()); + Q_ASSERT(resultStatus != TestResult::Unknown); + + /* Check that errHandler()->messages() at most only contains + * warnings, since it shouldn't have errors at this point. */ + const ErrorHandler::Message::List errors (errHandler.messages()); + const ErrorHandler::Message::List::const_iterator end(errors.constEnd()); + ErrorHandler::Message::List::const_iterator it(errors.constBegin()); + + for(; it != end; ++it) + { + const QtMsgType type = (*it).type(); + if(type == QtFatalMsg) + { + m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(), + errHandler.messages(), itemList, serialized); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; + } + } + + m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(), + errHandler.messages(), itemList, serialized); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; +} + +TestCase::Scenario TestCase::scenarioFromString(const QString &string) +{ + if(string == QLatin1String("standard")) + return Standard; + else if(string == QLatin1String("parse-error")) + return ParseError; + else if(string == QLatin1String("runtime-error")) + return RuntimeError; + else if(string == QLatin1String("trivial")) + return Trivial; + else + { + Q_ASSERT_X(false, Q_FUNC_INFO, + qPrintable(QString::fromLatin1("Invalid string representation for the scenario-enum: %1").arg(string))); + return ParseError; /* Silence GCC. */ + } +} + +void TestCase::toXML(XMLWriter &receiver) const +{ + /* <test-case> */ + QXmlAttributes test_caseAtts; + test_caseAtts.append(QLatin1String("is-XPath2"), QString(), + QLatin1String("is-XPath2"), isXPath() ? QLatin1String("true") + : QLatin1String("false")); + test_caseAtts.append(QLatin1String("name"), QString(), QLatin1String("name"), name()); + test_caseAtts.append(QLatin1String("creator"), QString(), QLatin1String("creator"), creator()); + QString scen; + switch(scenario()) + { + case Standard: + { + scen = QLatin1String("standard"); + break; + } + case ParseError: + { + scen = QLatin1String("parse-error"); + break; + } + case RuntimeError: + { + scen = QLatin1String("runtime-error"); + break; + } + case Trivial: + { + scen = QLatin1String("trivial"); + break; + } + default: /* includes 'AnyError' */ + Q_ASSERT(false); + } + test_caseAtts.append(QLatin1String("scenario"), QString(), QLatin1String("scenario"), scen); + test_caseAtts.append(QLatin1String(QLatin1String("FilePath")), QString(), + QLatin1String("FilePath"), QString()); + receiver.startElement(QLatin1String("test-case"), test_caseAtts); + + /* <description> */ + receiver.startElement(QLatin1String("description"), test_caseAtts); + receiver.characters(description()); + + /* </description> */ + receiver.endElement(QLatin1String("description")); + + /* <query> */ + QXmlAttributes queryAtts; + queryAtts.append(QLatin1String("date"), QString(), QLatin1String("date"), /* This date is a dummy. */ + QDate::currentDate().toString(Qt::ISODate)); + queryAtts.append(QLatin1String("name"), QString(), QLatin1String("name"), testCasePath().toString()); + receiver.startElement(QLatin1String("query"), queryAtts); + + /* </query> */ + receiver.endElement(QLatin1String("query")); + + /* Note: this is invalid, we don't add spec-citation. */ + TestBaseLine::List bls(baseLines()); + const TestBaseLine::List::const_iterator end(bls.constEnd()); + TestBaseLine::List::const_iterator it(bls.constBegin()); + + for(; it != end; ++it) + (*it)->toXML(receiver); + + /* </test-case> */ + receiver.endElement(QLatin1String("test-case")); +} + +QString TestCase::displayName(const Scenario scen) +{ + switch(scen) + { + case Standard: + return QLatin1String("Standard"); + case ParseError: + return QLatin1String("Parse Error"); + case RuntimeError: + return QLatin1String("Runtime Error"); + case Trivial: + return QLatin1String("Trivial"); + case AnyError: + { + Q_ASSERT(false); + return QString(); + } + } + + Q_ASSERT(false); + return QString(); +} + +TestItem::ResultSummary TestCase::resultSummary() const +{ + if(m_result) + return ResultSummary(m_result->status() == TestResult::Pass ? 1 : 0, + 1); + + return ResultSummary(0, 1); +} + +void TestCase::appendChild(TreeItem *) +{ + Q_ASSERT_X(false, Q_FUNC_INFO, "Makes no sense to call appendChild() for TestCase."); +} + +TreeItem *TestCase::child(const unsigned int) const +{ + return 0; /* Silence GCC */ +} + +TreeItem::List TestCase::children() const +{ + return TreeItem::List(); +} + +unsigned int TestCase::childCount() const +{ + return 0; +} + +TestResult *TestCase::testResult() const +{ + return m_result; +} + +bool TestCase::isFinalNode() const +{ + return true; +} + +QXmlQuery::QueryLanguage TestCase::language() const +{ + return QXmlQuery::XQuery10; +} + +QXmlName TestCase::initialTemplateName() const +{ + return QXmlName(); +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/TestCase.h b/tests/auto/xmlpatternssdk/TestCase.h new file mode 100644 index 0000000..c7aee25 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestCase.h @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestCase_H +#define PatternistSDK_TestCase_H + +#include <QtXmlPatterns/QXmlQuery> + +#include "qexternalvariableloader_p.h" + +#include "ErrorHandler.h" +#include "TestBaseLine.h" +#include "Global.h" + +#include "TestItem.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDate; +class QString; +class QUrl; + +namespace QPatternistSDK +{ + class XMLWriter; + + /** + * @short A generic abstract base class for test cases. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestCase : public TestItem + { + public: + /** + * Corresponds to the simpleType test:scenarios-enum + */ + enum Scenario + { + /** + * The test case should evaluate normally and that the output + * should match the supplied base line. + */ + Standard = 1, + + /** + * The test case should result in a static error, a parser error. + */ + ParseError = 2, + + /** + * The test case should result in a dynamic error, a runtime error. + */ + RuntimeError = 4, + + Trivial = 8, + + /** + * ParseError and RuntimeError OR'd. + */ + AnyError = RuntimeError | ParseError + + }; + + TestCase(); + virtual ~TestCase(); + + /** + * Executes the test, and returns the result. The returned list + * will always contain exactly one TestResult. + * + * @p stage is ignored when running out-of-process. + */ + virtual TestResult::List execute(const ExecutionStage stage, + TestSuite *ts); + + /** + * Determines the corresponding Scenario enumerator from the string + * representation @p string. + * + * The following mappings are in effect: + * @arg @c Standard "standard" + * @arg @c ParseError "parse-error" + * @arg @c RuntimeError "runtime-error" + */ + static Scenario scenarioFromString(const QString &string); + + /** + * @return always @c true + */ + virtual bool isFinalNode() const; + + /** + * Calling this function makes no sense, so it always + * performs an Q_ASSERT check. + */ + virtual void appendChild(TreeItem *); + + /** + * Calling this function makes no sense, so it always + * performs an Q_ASSERT check. + */ + virtual TreeItem *child(const unsigned int) const; + + /** + * @return always zero + */ + virtual unsigned int childCount() const; + + /** + * @return always an empty list. + */ + virtual TreeItem::List children() const; + + /** + * A description of the test case for human consumption. + */ + virtual QString description() const = 0; + + /** + * The title of the test. This can be the identifier of the test, for example. + */ + virtual QString title() const = 0; + + /** + * Whether this test case only make use of XPath features. + * + * @returns @c false if the test case exercises any XQuery feature + * which is not available in XPath 2.0. + */ + virtual bool isXPath() const = 0; + + /** + * The full name of the creator of the test case. For example, "Frans Englich". + */ + virtual QString creator() const = 0; + + /** + * The date of when the test case was created or last modified. + */ + virtual QDate lastModified() const = 0; + + /** + * The test's source code. That is, the XPath/XQuery code for the test. + * + * @param ok the function sets this value to @c false if loading the query + * failed, and returns a description of the error for human consumption. If + * everything went ok, @p ok is set to @c true, and the query is returned. + */ + virtual QString sourceCode(bool &ok) const = 0; + + /** + * The path to the file containing the code of the test case. + */ + virtual QUrl testCasePath() const = 0; + + /** + * The test case's identifier. For example, "Literals001". + */ + virtual QString name() const = 0; + + /** + * What kind of test this is. For example, whether the test case + * should result in a parser error or should evaluate without errors. + * + * The vast common case is that one Scenario is returned; the bit signifiance + * is for the TestCase sub-class UserTestCase. + */ + virtual Scenario scenario() const = 0; + + static QString displayName(const Scenario scen); + + /** + * @returns the valid test baselines for this test case. If only + * one outcome is valid, the returned list only contains + * that baseline. + */ + virtual TestBaseLine::List baseLines() const = 0; + + virtual TestResult *testResult() const; + + virtual ResultSummary resultSummary() const; + + void toXML(XMLWriter &receiver) const; + + virtual QPatternist::ExternalVariableLoader::Ptr externalVariableLoader() const = 0; + + /** + * @short The XML document that should be used as focus. If none should + * be used, and hence the focus be undefined, a default constructed + * QUrl is returned. + */ + virtual QUrl contextItemSource() const = 0; + + /** + * Returns by default QXmlQuery::XQuery10. + */ + virtual QXmlQuery::QueryLanguage language() const; + + virtual QXmlName initialTemplateName() const; + private: + TestResult::List execute(const ExecutionStage stage); + TestResult *createTestResult(const TestResult::Status status, + const QString &comment) const; + + QPointer<TestResult> m_result; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestContainer.cpp b/tests/auto/xmlpatternssdk/TestContainer.cpp new file mode 100644 index 0000000..3141f9d --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestContainer.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QPair> +#include <QtDebug> + +#include "TestContainer.h" + +using namespace QPatternistSDK; + +TestContainer::TestContainer() : m_deleteChildren(true) +{ +} + +TestContainer::~TestContainer() +{ + if(m_deleteChildren) + qDeleteAll(m_children); +} + +TestResult::List TestContainer::execute(const ExecutionStage stage, + TestSuite *ts) +{ + Q_ASSERT(ts); + const unsigned int c = m_children.count(); + TestResult::List result; + + for(unsigned int i = 0; i != c; ++i) + result += static_cast<TestItem *>(child(i))->execute(stage, ts); + + return result; +} + +TestItem::ResultSummary TestContainer::resultSummary() const +{ + const int c = childCount(); + int total = 0; + int pass = 0; + + for(int i = 0; i != c; ++i) + { + TestItem *t = static_cast<TestItem *>(child(i)); + const ResultSummary sum(t->resultSummary()); + pass += sum.first; + total += sum.second; + } + + return ResultSummary(pass, total); +} + +TreeItem::List TestContainer::children() const +{ + return m_children; +} + +void TestContainer::appendChild(TreeItem *item) +{ + /* When one of our children changes, we changes. */ + connect(item, SIGNAL(changed(TreeItem *)), SIGNAL(changed(TreeItem *))); + m_children.append(item); +} + +TreeItem *TestContainer::child(const unsigned int rowP) const +{ + return m_children.value(rowP); +} + +unsigned int TestContainer::childCount() const +{ + return m_children.count(); +} + +void TestContainer::setTitle(const QString &titleP) +{ + m_title = titleP; +} + +QString TestContainer::title() const +{ + return m_title; +} + +bool TestContainer::isFinalNode() const +{ + return false; +} + +int TestContainer::columnCount() const +{ + return 4; +} + +QString TestContainer::description() const +{ + return m_description; +} + +void TestContainer::setDescription(const QString &desc) +{ + m_description = desc; +} + +void TestContainer::setDeleteChildren(const bool val) +{ + m_deleteChildren = val; +} + +void TestContainer::removeLast() +{ + m_children.removeLast(); +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestContainer.h b/tests/auto/xmlpatternssdk/TestContainer.h new file mode 100644 index 0000000..981c2e9 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestContainer.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestContainer_H +#define PatternistSDK_TestContainer_H + +#include "Global.h" +#include "TestItem.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short an abstract base class, containing + * an appropriate implementation of TestItem for sub-classes + * which can contain other TestItem instances. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestContainer : public TestItem + { + public: + virtual ~TestContainer(); + virtual void appendChild(TreeItem *item); + virtual TreeItem *child(const unsigned int row) const; + virtual unsigned int childCount() const; + + /** + * @returns the TestResults of this TestContainer's children. + */ + virtual TestResult::List execute(const ExecutionStage stage, + TestSuite *ts); + + QString title() const; + void setTitle(const QString &title); + + virtual TreeItem::List children() const; + + /** + * @return always 2 + */ + virtual int columnCount() const; + + virtual bool isFinalNode() const; + + virtual ResultSummary resultSummary() const; + virtual QString description() const; + virtual void setDescription(const QString &desc); + + /** + * Determines whether TestContainer will delete its children upon + * destruction. By default, it will. + */ + void setDeleteChildren(const bool val); + + /** + * Removes the last appended child. + */ + void removeLast(); + + protected: + /** + * Constructor, protected. TestContainer is an abstract class, + * and is not ment to be instantiated, but sub classed. + */ + TestContainer(); + + private: + TreeItem::List m_children; + QString m_title; + QString m_description; + bool m_deleteChildren; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestGroup.cpp b/tests/auto/xmlpatternssdk/TestGroup.cpp new file mode 100644 index 0000000..e34292b --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestGroup.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QColor> +#include <QPair> +#include <QVariant> + +#include "TestGroup.h" + +using namespace QPatternistSDK; + +TestGroup::TestGroup(TreeItem *p) : m_parent(p) +{ +} + +QVariant TestGroup::data(const Qt::ItemDataRole role, int column) const +{ + if(role != Qt::DisplayRole && role != Qt::BackgroundRole && role != Qt::ToolTipRole) + return QVariant(); + + /* In ResultSummary, the first is the amount of passes and the second is the total. */ + const ResultSummary sum(resultSummary()); + const int failures = sum.second - sum.first; + + switch(role) + { + case Qt::DisplayRole: + { + + switch(column) + { + case 0: + return title(); + case 1: + /* Passes. */ + return QString::number(sum.first); + case 2: + /* Failures. */ + return QString::number(failures); + case 3: + /* Total. */ + return QString::number(sum.second); + default: + { + Q_ASSERT(false); + return QString(); + } + } + } + case Qt::BackgroundRole: + { + switch(column) + { + case 1: + { + if(sum.first) + { + /* Pass. */ + return Qt::green; + } + else + return QVariant(); + } + case 2: + { + if(failures) + { + /* Failure. */ + return Qt::red; + } + else + return QVariant(); + } + default: + return QVariant(); + } + } + case Qt::ToolTipRole: + { + return description(); + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, "This shouldn't be reached"); + return QVariant(); + } + } +} + +void TestGroup::setNote(const QString &n) +{ + m_note = n; +} + +QString TestGroup::note() const +{ + return m_note; +} + +TreeItem *TestGroup::parent() const +{ + return m_parent; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestGroup.h b/tests/auto/xmlpatternssdk/TestGroup.h new file mode 100644 index 0000000..00a3daf --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestGroup.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestGroup_H +#define PatternistSDK_TestGroup_H + +#include <QString> + +#include "TestContainer.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Groups test groups and test cases into a group. + * + * TestGroup corresponds to the @c test-group element in XQTSCatalog.xsd. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestGroup : public TestContainer + { + public: + TestGroup(TreeItem *parent); + + /** + * @returns the parent of this group. Is either another group, or + * the TestSuite instance governing this tree. + */ + virtual TreeItem *parent() const; + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + QString note() const; + + void setName(const QString &name); + void setNote(const QString ¬e); + + private: + QString m_name; + QString m_note; + TreeItem *m_parent; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestItem.h b/tests/auto/xmlpatternssdk/TestItem.h new file mode 100644 index 0000000..2d559a7 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestItem.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestItem_H +#define PatternistSDK_TestItem_H + +#include "TestResult.h" +#include "TreeItem.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template<typename A, typename B> struct QPair; + +namespace QPatternistSDK +{ + class XMLWriter; + class TestSuite; + + /** + * @short base class for all classes which + * represent an element in an XQuery Test Suite catalog. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestItem : public TreeItem + { + public: + + /** + * Determines how far an test case execution should go. + */ + enum ExecutionStage + { + /** + * The query will not be run. It will only go through the (whole) compilation stage. + */ + CompileOnly = 1, + + /** + * The query will be compiled and run, as ordinary. + */ + CompileAndRun + }; + + /** + * Represents a summary of test results for a collection + * of tests. QPair::first contains the amount of + * passed tests; QPair::second contains the count of + * all tests. For example TestCase::summary() returns + * ResultSummary(0, 1) or ResultSummary(1, 1) depending + * on whether the TestCase have succeeded or not. + */ + typedef QPair<int, int> ResultSummary; + + /** + * Executes the test case(s) this TestItem represents, + * and return the TestResult. For example, the TestGroup + * returns the result of its children concatenated, while + * TestCase always returns a list containing one + * TestResult(what it evaluated to). + */ + virtual TestResult::List execute(const ExecutionStage stage, + TestSuite *ts) = 0; + + /** + * @todo Rename this function. Perhaps create a type() hierarchy + * instead. + */ + virtual bool isFinalNode() const = 0; + + /** + * @returns a ResultSummary for this TestItem. + */ + virtual ResultSummary resultSummary() const = 0; + + /** + * Serializes into the corresponding elements attributes + * specified in XQTSCatalog.xsd. + * + * @note Sub-classes must assume the XQTSCatalog namespace + * is the default namespace, and not add any namespace declarations. + */ + //virtual void toXML(XMLWriter &receiver) const = 0; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestResult.cpp b/tests/auto/xmlpatternssdk/TestResult.cpp new file mode 100644 index 0000000..37603e7 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestResult.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QXmlAttributes> +#include <QtDebug> + +#include "qdebug_p.h" +#include "Global.h" +#include "XMLWriter.h" + +#include "TestResult.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +QString TestResult::displayName(const TestResult::Status stat) +{ + switch(stat) + { + case Pass: + return QLatin1String("pass"); + case Fail: + return QLatin1String("fail"); + case NotTested: + return QLatin1String("not tested"); + case Unknown: + Q_ASSERT(false); + } + + Q_ASSERT(false); + return QString(); +} + +TestResult::Status TestResult::statusFromString(const QString &string) +{ + if(string == QLatin1String("pass")) + return Pass; + else if(string == QLatin1String("fail")) + return Fail; + else if(string == QLatin1String("not tested")) + return NotTested; + else + { + Q_ASSERT(false); + return Fail; + } +} + +TestResult::TestResult(const QString &n, + const Status s, + ASTItem *tree, + const ErrorHandler::Message::List &ers, + const QPatternist::Item::List &itemsP, + const QString &serialized) : m_status(s), + m_messages(ers), + m_astTree(tree), + m_testName(n), + m_items(itemsP), + m_asSerialized(serialized) +{ + Q_ASSERT(!n.isEmpty()); + Q_ASSERT(s != 0); +} + +TestResult::~TestResult() +{ + delete m_astTree; +} + +void TestResult::toXML(XMLWriter &receiver) const +{ + QXmlAttributes atts; + atts.append(QLatin1String("name"), QString(), QLatin1String("name"), m_testName); + atts.append(QLatin1String("result"), QString(), QLatin1String("result"), displayName(m_status)); + + if(!m_comment.isEmpty()) + atts.append(QLatin1String("comment"), QString(), QLatin1String("comment"), m_comment); + + receiver.startElement(QLatin1String("test-case"), atts); + receiver.endElement(QLatin1String("test-case")); +} + +void TestResult::setComment(const QString &comm) +{ + m_comment = comm; +} + +TestResult::Status TestResult::status() const +{ + return m_status; +} + +QString TestResult::comment() const +{ + return m_comment; +} + +ASTItem *TestResult::astTree() const +{ + return m_astTree; +} + +ErrorHandler::Message::List TestResult::messages() const +{ + return m_messages; +} + +QPatternist::Item::List TestResult::items() const +{ + return m_items; +} + +QString TestResult::asSerialized() const +{ + pDebug() << "asSerialized: " << m_asSerialized; + return m_asSerialized; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/TestResult.h b/tests/auto/xmlpatternssdk/TestResult.h new file mode 100644 index 0000000..96b4610 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestResult.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestResult_H +#define PatternistSDK_TestResult_H + +#include <QList> +#include <QObject> +#include <QPointer> +#include <QString> + +#include <QtXmlPatterns/private/qitem_p.h> +#include "ErrorHandler.h" + +#include "ASTItem.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class ASTItem; + class XMLWriter; + + /** + * @short represents the result produced by running a test case. + * + * This information TestResult houses is: + * + * - The result status() of the run. Whether the test case succeeded or not, for example. + * - The astTree() which reflects the compiled test case + * - The messages issued when compiling and running the test case, retrievable via messages() + * - The data -- XPath Data Model items() -- the test case evaluated to, if any. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestResult : public QObject + { + Q_OBJECT + + public: + enum Status + { + /** + * Used when the status is unknown. + */ + Unknown = 0, + + /** + * The test case passed. + */ + Pass, + + /** + * The test case failed. + */ + Fail, + + /** + * The test was not run. Similar to "SKIP". + */ + NotTested + }; + + /** + * A list of TestResult instances. + */ + typedef QList<QPointer<TestResult> > List; + + /** + * Constructs a TestResult. + * + * @param testName the name of the test. For example, @c Literal-001. + * @param astTree may be @c null, signalling no AST being available, or point to one. + * @param status the result status of running the test-case. Whether the test-case + * passed or failed, and so forth. + * @param errors the errors and warnings that were reported while running the test-case + * @param items the XDM items that were outputted, if any + * @param serialized the output when serialized + */ + TestResult(const QString &testName, + const Status status, + ASTItem *astTree, + const ErrorHandler::Message::List &errors, + const QPatternist::Item::List &items, + const QString &serialized); + + virtual ~TestResult(); + + Status status() const; + + QString comment() const; + void setComment(const QString &comment); + + QPatternist::Item::List items() const; + + ErrorHandler::Message::List messages() const; + + /** + * Serializes itself to @p receiver, into a test-case element, + * as per @c XQTSResult.xsd. + */ + void toXML(XMLWriter &receiver) const; + + ASTItem *astTree() const; + + /** + * @returns a string representation for @p status, as per the anonymous + * type inside the type test-case, in @c XQTSResult.xsd. For example, if @p status + * is NotTested, is "not tested" returned. + */ + static QString displayName(const TestResult::Status status); + + static Status statusFromString(const QString &string); + + /** + * @returns the output of this test result(if any) as when + * being serialized. + */ + QString asSerialized() const; + + private: + const Status m_status; + QString m_comment; + const ErrorHandler::Message::List m_messages; + QPointer<ASTItem> m_astTree; + QString m_testName; + const QPatternist::Item::List m_items; + const QString m_asSerialized; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestResultHandler.cpp b/tests/auto/xmlpatternssdk/TestResultHandler.cpp new file mode 100644 index 0000000..95aaf1e --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestResultHandler.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "Global.h" + +#include "TestResultHandler.h" + +using namespace QPatternistSDK; + +TestResultHandler::TestResultHandler() +{ + /* Fifteen thousand. When finished, we squeeze them. */ + m_result.reserve(15000); + m_comments.reserve(1000); /* Comments are only used for stuff that crash, more or less. */ +} + +bool TestResultHandler::startElement(const QString &namespaceURI, + const QString &localName, + const QString &, + const QXmlAttributes &atts) +{ + /* We only care about 'test-case', ignore everything else. */ + if(localName != QLatin1String("test-case") || + namespaceURI != Global::xqtsResultNS) + return true; + + /* The 'comments' attribute is optional. */ + Q_ASSERT_X(atts.count() == 2 || atts.count() == 3, Q_FUNC_INFO, + "The input appears to not conform to XQTSResult.xsd"); + + Q_ASSERT_X(!m_result.contains(atts.value(QLatin1String("name"))), + Q_FUNC_INFO, + qPrintable(QString::fromLatin1("A test result for test case %1 has " + "already been read(duplicate entry it seems).").arg(atts.value(QLatin1String("name"))))); + + m_result.insert(atts.value(0), TestResult::statusFromString(atts.value(QLatin1String("result")))); + + return true; +} + +bool TestResultHandler::endDocument() +{ + m_result.squeeze(); + m_comments.squeeze(); + return true; +} + +TestResultHandler::Hash TestResultHandler::result() const +{ + return m_result; +} + +TestResultHandler::CommentHash TestResultHandler::comments() const +{ + return m_comments; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestResultHandler.h b/tests/auto/xmlpatternssdk/TestResultHandler.h new file mode 100644 index 0000000..87f7b61 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestResultHandler.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestResultHandler_H +#define PatternistSDK_TestResultHandler_H + +#include <QHash> +#include <QString> +#include <QtXml/QXmlDefaultHandler> + +#include "TestResult.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Reads XML in the @c XQTSResult.xsd format, and provides access to + * the reported results. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup PatternistSDK + */ + class Q_PATTERNISTSDK_EXPORT TestResultHandler : public QXmlDefaultHandler + { + public: + /** + * A hash where the key is the class's name, that is <tt>test-case/@@name</tt>, + * and the value the test's result status. + */ + typedef QHash<QString, TestResult::Status> Hash; + + /** + * A hash mapping test-case names to their' comments. + */ + typedef QHash<QString, QString> CommentHash; + + /** + * Creates a TestResultHandler that will read @p file when run() is called. + */ + TestResultHandler(); + + /** + * Performs finalization. + */ + virtual bool endDocument(); + + /** + * Reads the <tt>test-case</tt> element and its attributes, everything else is ignored. + */ + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + /** + * @note Do not reimplement this function. + * @returns the result obtained from reading the XML file. + */ + Hash result() const; + + CommentHash comments() const; + + private: + Q_DISABLE_COPY(TestResultHandler) + Hash m_result; + CommentHash m_comments; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestSuite.cpp b/tests/auto/xmlpatternssdk/TestSuite.cpp new file mode 100644 index 0000000..8b8856a --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuite.cpp @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QFileInfo> +#include <QVariant> +#include <QXmlInputSource> +#include <QXmlSimpleReader> +#include <QtDebug> + +#include "Global.h" +#include "TestSuiteHandler.h" +#include "TestSuiteResult.h" +#include "XMLWriter.h" +#include "XSLTTestSuiteHandler.h" +#include "XSDTestSuiteHandler.h" +#include "qdebug_p.h" + +#include "TestSuite.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +TestSuite::TestSuite() +{ +} + +QVariant TestSuite::data(const Qt::ItemDataRole role, int column) const +{ + if(role != Qt::DisplayRole) + return QVariant(); + + switch(column) + { + case 0: + return title(); + case 1: + return QString(); + default: + { + Q_ASSERT(false); + return QString(); + } + } +} + +TestSuiteResult *TestSuite::runSuite() +{ + const QDate date(QDate::currentDate()); + TestResult::List result(execute(CompileAndRun, this)); + + return new TestSuiteResult(version(), date, result); +} + +TestSuite *TestSuite::openCatalog(const QUrl &catalogURI, + QString &errorMsg, + const bool useExclusionList, + SuiteType suiteType) +{ + pDebug() << "Opening catalog:" << catalogURI.toString(); + QFile ts(catalogURI.toLocalFile()); + Q_ASSERT(catalogURI.isValid()); + + if(!ts.exists()) + { + errorMsg = QString::fromLatin1("The test suite catalog \"%1\" could not be found.\n") + .arg(ts.fileName()); + return 0; + } + + const QFileInfo info(ts); + + if(!info.isReadable()) + { + errorMsg = QString::fromLatin1("Cannot read the test suite catalog.\n"); + return 0; + } + else if(!info.isFile()) + { + errorMsg = QString::fromLatin1("The specified test suite catalog \"%1\" is not a file. " + "The test suite catalog must be a file, it cannot be " + "a directory, for example.\n") + .arg(ts.fileName()); + return 0; + } + else if(!ts.open(QIODevice::ReadOnly | QIODevice::Text)) + { + errorMsg = QString::fromLatin1("Failed to open the test suite catalog, \"%1\".\n") + .arg(ts.fileName()); + return 0; + } + + return openCatalog(&ts, errorMsg, catalogURI, useExclusionList, suiteType); +} + +TestSuite *TestSuite::openCatalog(QIODevice *input, + QString &errorMsg, + const QUrl &fileName, + const bool useExclusionList, + SuiteType suiteType) +{ + Q_ASSERT(input); + + QXmlSimpleReader reader; + typedef QPatternist::AutoPtr<QXmlDefaultHandler> HandlerPtr; + + HandlerPtr loader; + + switch (suiteType) { + case XQuerySuite: loader = HandlerPtr(new TestSuiteHandler(fileName, useExclusionList)); break; + case XsltSuite: loader = HandlerPtr(new XSLTTestSuiteHandler(fileName)); break; + case XsdSuite: loader = HandlerPtr(new XSDTestSuiteHandler(fileName)); break; + default: Q_ASSERT(false); break; + } + + reader.setContentHandler(loader.data()); + + QXmlInputSource source(input); + + if(!reader.parse(source)) + { + errorMsg = QString::fromLatin1("Couldn't parse %1").arg(fileName.toString()); + return 0; + } + + TestSuite *suite = 0; + switch (suiteType) { + case XQuerySuite: suite = static_cast<TestSuiteHandler *>(loader.data())->testSuite(); break; + case XsltSuite: suite = static_cast<XSLTTestSuiteHandler *>(loader.data())->testSuite(); break; + case XsdSuite: suite = static_cast<XSDTestSuiteHandler *>(loader.data())->testSuite(); break; + default: Q_ASSERT(false); break; + } + + if(suite) + return suite; + + errorMsg = QString::fromLatin1("Failed to load \"%1\". " + "It appears to have no test-suite element.\n").arg(fileName.toString()); + return 0; +} + +void TestSuite::toXML(XMLWriter &receiver, TestCase *const tc) const +{ + // TODO startElement() endElement() calls can be simplified. + + Q_ASSERT(tc); + + receiver.startDocument(); + /* <test-suite> */ + QXmlAttributes test_suiteAtts; + test_suiteAtts.append(QLatin1String("CatalogDesignDate"), QString(), + QLatin1String("CatalogDesignDate"), m_designDate.toString(Qt::ISODate)); + test_suiteAtts.append(QLatin1String("version"), QString(), + QLatin1String("version"), m_version); + test_suiteAtts.append(QLatin1String("SourceOffsetPath"), QString(), + QLatin1String("SourceOffsetPath"), QString()); + test_suiteAtts.append(QLatin1String("ResultOffsetPath"), QString(), + QLatin1String("ResultOffsetPath"), QString()); + test_suiteAtts.append(QLatin1String("XQueryQueryOffsetPath"), QString(), + QLatin1String("XQueryQueryOffsetPath"), QString()); + test_suiteAtts.append(QLatin1String("QueryXQueryOffsetPath"), QString(), + QLatin1String("QueryXQueryOffsetPath"), QString()); + test_suiteAtts.append(QLatin1String("XQueryFileExtension"), QString(), + QLatin1String("XQueryFileExtension"), QString()); + test_suiteAtts.append(QLatin1String("XQueryXFileExtension"), QString(), + QLatin1String("XQueryXFileExtension"), QString()); + + receiver.startPrefixMapping(QString(), Global::xqtsCatalogNS); + receiver.startElement(QLatin1String("test-suite"), test_suiteAtts); + receiver.endPrefixMapping(QString()); + + /* <test-group> */ + QXmlAttributes test_groupAtts; + test_groupAtts.append(QLatin1String("GeneratedGroupByPatternistSDKRunSuite"), QString(), + QLatin1String("GeneratedGroupByPatternistSDKRunSuite"), QString()); + receiver.startElement(QLatin1String("test-group"), test_groupAtts); + + /* <GroupInfo> */ + receiver.startElement(QLatin1String("GroupInfo"), test_groupAtts); + + /* <title> */ + receiver.startElement(QLatin1String("title"), test_groupAtts); + receiver.characters(QLatin1String("Contains the test case generated by PatternistSDKRunSuite.")); + + /* </title> */ + receiver.endElement(QLatin1String("title")); + + /* <description> */ + receiver.startElement(QLatin1String("description"), test_groupAtts); + /* </description> */ + receiver.endElement(QLatin1String("description")); + + /* </GroupInfo> */ + receiver.endElement(QLatin1String("GroupInfo")); + + /* <test-case> */ + tc->toXML(receiver); + /* </test-case> */ + + /* </test-group> */ + receiver.endElement(QLatin1String("test-group")); + + /* </test-suite> */ + receiver.endElement(QLatin1String("test-suite")); +} + +QString TestSuite::version() const +{ + return m_version; +} + +QDate TestSuite::designDate() const +{ + return m_designDate; +} + +void TestSuite::setVersion(const QString &ver) +{ + m_version = ver; +} + +void TestSuite::setDesignDate(const QDate &date) +{ + m_designDate = date; +} + +TestContainer *TestSuite::parent() const +{ + return 0; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestSuite.h b/tests/auto/xmlpatternssdk/TestSuite.h new file mode 100644 index 0000000..746f26b --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuite.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestSuite_H +#define PatternistSDK_TestSuite_H + +#include <QDate> +#include <QString> + +#include "TestContainer.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QIODevice; +class QUrl; +class QVariant; + +namespace QPatternistSDK +{ + class TestCase; + class TestSuiteResult; + + /** + * @short Represents a test suite in the W3C XML Query Test Suite format. + * + * TestSuite contains the test suite's test cases and meta data. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestSuite : public TestContainer + { + public: + /** + * Describes the type of test suite. + */ + enum SuiteType + { + XQuerySuite, ///< The test suite for XQuery + XsltSuite, ///< The test suite for XSLT + XsdSuite ///< The test suite for XML Schema + }; + + TestSuite(); + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + /** + * The version of the catalog test suite. For example, "0.8.0". + */ + QString version() const; + + /** + * When the catalog was designed, last modified. + */ + QDate designDate() const; + + void setVersion(const QString &version); + void setDesignDate(const QDate &version); + + /** + * @return always @c null + */ + virtual TestContainer *parent() const; + + /** + * Creates and returns a pointer to a TestSuite instance, which + * was instantiated from the XQuery Test Suite catalog file @p catalogFile. + * + * If loading went wrong, @c null is returned and @p errorMsg is set with a + * human readable message string. However, @p catalogFile is not validated; + * if the XML file is not valid against the XQTS task force's W3C XML Schema, the + * behavior and result for this function is undefined. + * + * This function blocks. Currently is only local files supported. + */ + static TestSuite *openCatalog(const QUrl &catalogFile, + QString &errorMsg, + const bool useExclusionList, + SuiteType type); + + void toXML(XMLWriter &receiver, TestCase *const tc) const; + + /** + * Evaluates all the test cases in this TestSuite, and returns + * it all in a TestSuiteResult. + */ + TestSuiteResult *runSuite(); + + private: + /** + * Essentially similar to open(const QUrl &, QString &errorMsg), + * with the difference that it takes directly a QIODevice as input, + * as opposed to a file name locating the catalog file to read. + * + * @param input the test suite catalog + * @param fileName this URI is used for resolving relative paths inside + * the catalog file into absolute. + * @param errorMsg if an error occurs, this QString is set to contain the message. + * Whether an error occurred can therefore be determined by checking if this variable + * still is @c null after the call + * @param useExclusionList whether the excludeTestGroups.txt file should be used + * to exclude test groups for this catalog + */ + static TestSuite *openCatalog(QIODevice *input, + QString &errorMsg, + const QUrl &fileName, + const bool useExclusionList, + SuiteType type); + QString m_version; + QDate m_designDate; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestSuiteHandler.cpp b/tests/auto/xmlpatternssdk/TestSuiteHandler.cpp new file mode 100644 index 0000000..65cb99b --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuiteHandler.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "qacceltreeresourceloader_p.h" +#include "qnetworkaccessdelegator_p.h" + +#include "Global.h" +#include "TestBaseLine.h" +#include "TestGroup.h" + +#include "TestSuiteHandler.h" + +using namespace QPatternistSDK; + +QNetworkAccessManager s_networkManager; + +TestSuiteHandler::TestSuiteHandler(const QUrl &catalogFile, + const bool useEList) : m_ts(0) + , m_container(0) + , m_tc(0) + , m_baseLine(0) + , m_catalogFile(catalogFile) + , m_exclusionList(readExclusionList(useEList)) + , m_isExcluding(false) +{ + Q_ASSERT(!m_catalogFile.isRelative()); +} + +QStringList TestSuiteHandler::readExclusionList(const bool useExclusionList) const +{ + if(!useExclusionList) + return QStringList(); + + QStringList avoid; + + /* These test groups are for features we don't support. + * + * Originally these were stored in a text file pulled in with Qt resources, but + * it was not possible to get it to link on some HP-UX and Intel-icc platforms. */ + + avoid << "SchemaImport"; // The schema import feature + avoid << "SchemaValidation"; // The validate expression(requires schema import) + avoid << "StaticTyping"; // Pessimistic static typing checking + avoid << "TrivialEmbedding"; // XQueryX inside XQuery + avoid << "XMark"; // We're currently too buggy for running these tests. + + return avoid; +} + +bool TestSuiteHandler::startElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/, + const QXmlAttributes &atts) +{ + if(namespaceURI != Global::xqtsCatalogNS) + return true; + else if(m_isExcluding) + { + if(localName == QLatin1String("test-group")) + { + m_testGroupName.push(atts.value(QLatin1String("name"))); + return true; + } + else + return true; + } + + /* The elements are handled roughly in the order of highest occurrence in the catalog file. */ + if(localName == QLatin1String("test-case")) + { + XQTSTestCase *const c = new XQTSTestCase( + TestCase::scenarioFromString(atts.value(QLatin1String("scenario"))), m_container); + + c->setName(atts.value(QLatin1String("name"))); + c->setCreator(atts.value(QLatin1String("Creator"))); + c->setIsXPath(Global::readBoolean(atts.value(QLatin1String("is-XPath2")))); + c->setLastModified(QDate::fromString(atts.value(QLatin1String("version-drop")), Qt::ISODate)); + Q_ASSERT(c->lastModified().isNull() || c->lastModified().isValid()); + + m_currentQueryPath = m_queryOffset.resolved(QUrl(atts.value(QLatin1String("FilePath")))); + m_currentBaselinePath = m_baselineOffset.resolved(QUrl(atts.value(QLatin1String("FilePath")))); + + m_container->appendChild(c); + m_tc = c; + } + else if(localName == QLatin1String("query")) + { + m_tc->setQueryPath(m_currentQueryPath.resolved(atts.value(QLatin1String("name")) + + m_xqueryFileExtension)); + } + else if(localName == QLatin1String("input-file") || + localName == QLatin1String("input-URI")) + { + m_currentInputVariable = atts.value(QLatin1String("variable")); + } + else if(localName == QLatin1String("output-file")) + { + m_baseLine = new TestBaseLine(TestBaseLine::identifierFromString(atts.value(QLatin1String("compare")))); + } + else if(localName == QLatin1String("expected-error")) + { + m_baseLine = new TestBaseLine(TestBaseLine::ExpectedError); + } + else if(localName == QLatin1String("test-group")) + { + m_testGroupName.push(atts.value(QLatin1String("name"))); + + if(m_exclusionList.contains(m_testGroupName.top())) + { + /* Ok, this group is supposed to be excluded, we don't + * insert it into the tree. */ + m_isExcluding = true; + return true; + } + else + { + Q_ASSERT(m_container); + TestGroup *const newGroup = new TestGroup(m_container); + m_container->appendChild(newGroup); + m_container = newGroup; + } + } + else if(localName == QLatin1String("source")) + { + m_sourceMap.insert(atts.value(QLatin1String("ID")), + m_sourceOffset.resolved(QUrl(atts.value(QLatin1String("FileName"))))); + } + else if(localName == QLatin1String("test-suite")) + { + m_ts = new TestSuite(); + m_ts->setVersion(atts.value(QLatin1String("version"))); + m_ts->setDesignDate(QDate::fromString(atts.value(QLatin1String("CatalogDesignDate")), Qt::ISODate)); + Q_ASSERT(m_ts->designDate().isValid()); + m_container = m_ts; + + m_xqueryFileExtension = atts.value(QLatin1String("XQueryFileExtension")); + m_queryOffset = m_catalogFile.resolved(atts.value(QLatin1String("XQueryQueryOffsetPath"))); + m_baselineOffset = m_catalogFile.resolved(atts.value(QLatin1String("ResultOffsetPath"))); + m_sourceOffset = m_catalogFile.resolved(atts.value(QLatin1String("SourceOffsetPath"))); + } + else if(localName == QLatin1String("input-query")) + { + m_tcSourceInputs.insert(atts.value(QLatin1String("variable")), + ExternalSourceLoader::VariableValue(m_currentQueryPath.resolved(atts.value(QLatin1String("name")) + m_xqueryFileExtension), + ExternalSourceLoader::Query)); + } + + return true; +} + +bool TestSuiteHandler::endElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/) +{ + if(namespaceURI != Global::xqtsCatalogNS) + return true; + + if(m_isExcluding) + { + if(localName == QLatin1String("test-group")) + { + const QString myName(m_testGroupName.pop()); + + if(m_exclusionList.contains(myName)) + { + /* This test-group is being excluded and now we're exiting from it. */ + m_isExcluding = false; + } + } + + return true; + } + + /* The elements are handled roughly in the order of highest occurrence in the catalog file. */ + if(localName == QLatin1String("description")) + { + if(m_tc) + { + /* We're inside a <test-case>, so the <description> belongs + * to the test-case. */ + m_tc->setDescription(m_ch.simplified()); + } + else + m_container->setDescription(m_ch.simplified()); + } + else if(localName == QLatin1String("test-case")) + { + Q_ASSERT(m_tc->baseLines().count() >= 1); + Q_ASSERT(m_resourceLoader); + m_tc->setExternalVariableLoader(QPatternist::ExternalVariableLoader::Ptr + (new ExternalSourceLoader(m_tcSourceInputs, + m_resourceLoader))); + m_tcSourceInputs.clear(); + + if(!m_contextItemSource.isEmpty()) + { + m_tc->setContextItemSource(QUrl(m_sourceMap.value(m_contextItemSource))); + m_contextItemSource.clear(); + } + + m_tc = 0; + } + else if(localName == QLatin1String("output-file")) + { + m_baseLine->setDetails(m_currentBaselinePath.resolved(m_ch).toString()); + m_tc->addBaseLine(m_baseLine); + } + else if(localName == QLatin1String("input-file")) + { + m_tcSourceInputs.insert(m_currentInputVariable, ExternalSourceLoader::VariableValue(m_sourceMap.value(m_ch), + ExternalSourceLoader::Document)); + } + else if(localName == QLatin1String("expected-error")) + { + m_baseLine->setDetails(m_ch); + m_tc->addBaseLine(m_baseLine); + } + else if(localName == QLatin1String("title")) + { + /* A bit dangerous, the only element with name title in the vocabulary + * is the the child of GroupInfo */ + m_container->setTitle(m_ch.simplified()); + } + else if(localName == QLatin1String("test-group")) + { + m_testGroupName.pop(); + Q_ASSERT(m_container); + m_container = static_cast<TestContainer *>(m_container->parent()); + Q_ASSERT(m_container); + } + else if(localName == QLatin1String("test-suite")) + { + Q_ASSERT(m_container); + m_container = static_cast<TestContainer *>(m_container->parent()); + } + else if(localName == QLatin1String("sources")) + { + const QPatternist::NetworkAccessDelegator::Ptr networkDelegator(new QPatternist::NetworkAccessDelegator(&s_networkManager, &s_networkManager)); + + m_resourceLoader = QPatternist::ResourceLoader::Ptr(new QPatternist::AccelTreeResourceLoader(Global::namePool(), + networkDelegator)); + + const ExternalSourceLoader::SourceMap::const_iterator end(m_sourceMap.constEnd()); + ExternalSourceLoader::SourceMap::const_iterator it(m_sourceMap.constBegin()); + + for(; it != end; ++it) + m_resourceLoader->announceDocument(it.value(), QPatternist::ResourceLoader::WillUse); + } + else if(localName == QLatin1String("input-URI")) + { + m_tcSourceInputs.insert(m_currentInputVariable, ExternalSourceLoader::VariableValue(m_sourceMap.value(m_ch), + ExternalSourceLoader::URI)); + } + else if(localName == QLatin1String("contextItem")) + m_contextItemSource = m_ch; + + return true; +} + +bool TestSuiteHandler::characters(const QString &ch) +{ + m_ch = ch; + return true; +} + +TestSuite *TestSuiteHandler::testSuite() const +{ + return m_ts; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/TestSuiteHandler.h b/tests/auto/xmlpatternssdk/TestSuiteHandler.h new file mode 100644 index 0000000..a189cf9 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuiteHandler.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestSuiteHandler_H +#define PatternistSDK_TestSuiteHandler_H + +#include <QStack> +#include <QUrl> +#include <QXmlDefaultHandler> + +#include "ExternalSourceLoader.h" +#include "TestSuite.h" +#include "XQTSTestCase.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class TestBaseLine; + + /** + * @short Creates a TestSuite from the XQuery Test Suite catalog, + * represented as a SAX stream. + * + * The created TestSuite can be retrieved via testSuite(). + * + * @note TestSuiteHandler assumes the XML is valid by having been validated + * against the W3C XML Schema. It have no safety checks for that the XML format + * is correct but is hard coded for it. Thus, the behavior is undefined if + * the XML is invalid. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestSuiteHandler : public QXmlDefaultHandler + { + public: + /** + * @param catalogFile the URI for the catalog file being parsed. This + * URI is used for creating absolute URIs for files mentioned in + * the catalog with relative URIs. + * @param useExclusionList whether excludeTestGroups.txt should be used to ignore + * test groups when loading + */ + TestSuiteHandler(const QUrl &catalogFile, + const bool useExclusionList); + virtual bool characters(const QString &ch); + + virtual bool endElement(const QString &namespaceURI, + const QString &localName, + const QString &qName); + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + + virtual TestSuite *testSuite() const; + + private: + QStringList readExclusionList(const bool useExclusionList) const; + + TestSuite * m_ts; + TestContainer * m_container; + XQTSTestCase * m_tc; + TestBaseLine * m_baseLine; + QString m_ch; + const QUrl m_catalogFile; + + /** + * The extension of XQuery files. For example, ".xq" + */ + QString m_xqueryFileExtension; + + /** + * The base URI for where the XQuery query files are found. + * It is absolute, resolved against catalogFile. + */ + QUrl m_queryOffset; + + QUrl m_baselineOffset; + QUrl m_sourceOffset; + QUrl m_currentQueryPath; + QUrl m_currentBaselinePath; + + /** + * In the XQTSCatalog.xml, each source file in each test is referred to + * by a key, which can be fully looked up in the @c sources element. This QHash + * maps the keys to absolute URIs pointing to the source files. + */ + ExternalSourceLoader::SourceMap m_sourceMap; + + ExternalSourceLoader::VariableMap m_tcSourceInputs; + + QPatternist::ResourceLoader::Ptr m_resourceLoader; + + /** + * The current value of <tt>input-file/\@variable/</tt>. + */ + QString m_currentInputVariable; + + /** + * The names of the test groups we're excluding. + */ + const QStringList m_exclusionList; + + /** + * This is set when we're inside a test-group that we're excluding. + */ + bool m_isExcluding; + + /** + * The names of the test groups. + */ + QStack<QString> m_testGroupName; + + /** + * Holds the content of the current <tt>input-URI</tt> element. + */ + QString m_inputURI; + QString m_contextItemSource; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TestSuiteResult.cpp b/tests/auto/xmlpatternssdk/TestSuiteResult.cpp new file mode 100644 index 0000000..b4df16d --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuiteResult.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QXmlContentHandler> + +#include "Global.h" +#include "XMLWriter.h" + +#include "TestSuiteResult.h" + +using namespace QPatternistSDK; + +TestSuiteResult::TestSuiteResult(const QString &testSuiteVersion, + const QDate &runDate, + const TestResult::List &results) : m_testSuiteVersion(testSuiteVersion), + m_runDate(runDate), + m_results(results) +{ +} + +TestSuiteResult::~TestSuiteResult() +{ + qDeleteAll(m_results); +} + +void TestSuiteResult::toXML(XMLWriter &receiver) const +{ + /* If this data needs to be configurable in someway(say, another + * XML format is supported), then break out the info into getters(alternatively, combined + * with setters, or that the class is subclassed), and access the getters instead. + */ + const QString organizationName (QLatin1String("K Desktop Environment(KDE)")); + const QString organizationWebsite (QLatin1String("http://www.kde.org/")); + const QString submittorName (QLatin1String("Frans Englich")); + const QString submittorEmail (QLatin1String("frans.englich@nokia.com")); + const QString implementationVersion (QLatin1String("0.1")); + const QString implementationName (QLatin1String("Patternist")); + const QString implementationDescription (QLatin1String( + "Patternist is an implementation written in C++ " + "and with the Qt/KDE libraries. " + "It is licensed under GNU LGPL and part of KDE, " + "the K Desktop Environment.")); + + /* Not currently serialized: + * - <implementation-defined-items> + * - <features> + * - <context-properties> + */ + + receiver.startDocument(); + /* <test-suite-result> */ + receiver.startPrefixMapping(QString(), Global::xqtsResultNS); + receiver.startElement(QLatin1String("test-suite-result")); + receiver.endPrefixMapping(QString()); + + /* <implementation> */ + QXmlAttributes implementationAtts; + implementationAtts.append(QLatin1String("name"), QString(), + QLatin1String("name"), implementationName); + implementationAtts.append(QLatin1String("version"), QString(), + QLatin1String("version"), implementationVersion); + receiver.startElement(QLatin1String("implementation"), implementationAtts); + + /* <organization> */ + QXmlAttributes organizationAtts; + organizationAtts.append(QLatin1String("name"), QString(), + QLatin1String("name"), organizationName); + organizationAtts.append(QLatin1String("website"), QString(), + QLatin1String("website"), organizationWebsite); + receiver.startElement(QLatin1String("organization"), organizationAtts); + + /* </organization> */ + receiver.endElement(QLatin1String("organization")); + + /* <submittor> */ + QXmlAttributes submittorAtts; + submittorAtts.append(QLatin1String("name"), QString(), QLatin1String("name"), submittorName); + submittorAtts.append(QLatin1String("email"), QString(), QLatin1String("email"), submittorEmail); + receiver.startElement(QLatin1String("submittor"), submittorAtts); + + /* </submittor> */ + receiver.endElement(QLatin1String("submittor")); + + /* <description> */ + receiver.startElement(QLatin1String("description")); + + /* <p> */ + receiver.startElement(QLatin1String("p")); + receiver.characters(implementationDescription); + + /* </p> */ + receiver.endElement(QLatin1String("p")); + /* </description> */ + receiver.endElement(QLatin1String("description")); + + /* </implementation> */ + receiver.endElement(QLatin1String("implementation")); + + /* <syntax> */ + receiver.startElement(QLatin1String("syntax")); + receiver.characters(QLatin1String(QLatin1String("XQuery"))); + + /* </syntax> */ + receiver.endElement(QLatin1String("syntax")); + + /* <test-run> */ + QXmlAttributes test_runAtts; + test_runAtts.append(QLatin1String("dateRun"), QString(), QLatin1String("dateRun"), m_runDate.toString(QLatin1String("yyyy-MM-dd"))); + receiver.startElement(QLatin1String("test-run"), test_runAtts); + + /* <test-suite> */ + QXmlAttributes test_suiteAtts; + test_suiteAtts.append(QLatin1String("version"), QString(), QLatin1String("version"), m_testSuiteVersion); + receiver.startElement(QLatin1String("test-suite"), test_suiteAtts); + + /* </test-suite> */ + receiver.endElement(QLatin1String("test-suite")); + + /* </test-run> */ + receiver.endElement(QLatin1String("test-run")); + + /* Serialize the TestResults: tons of test-case elements. */ + const TestResult::List::const_iterator end(m_results.constEnd()); + TestResult::List::const_iterator it(m_results.constBegin()); + + for(; it != end; ++it) + (*it)->toXML(receiver); + + /* </test-suite-result> */ + receiver.endElement(QLatin1String("test-suite-result")); + receiver.endDocument(); +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/TestSuiteResult.h b/tests/auto/xmlpatternssdk/TestSuiteResult.h new file mode 100644 index 0000000..474190e --- /dev/null +++ b/tests/auto/xmlpatternssdk/TestSuiteResult.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TestSuiteResult_H +#define PatternistSDK_TestSuiteResult_H + +#include <QDate> +#include <QString> + +#include "TestResult.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short A collection of TestResult instances. + * + * A TestSuiteResult gathers all TestResult instances, and provides + * the toXML() function which serializes it all into a XQuery Test Suite + * result file, conforming to XQTSResult.xsd. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TestSuiteResult + { + public: + ~TestSuiteResult(); + + TestSuiteResult(const QString &testSuiteVersion, + const QDate &runDate, + const TestResult::List &results); + + /** + * Serializes the test results this TestSuiteResult represents, + * into XQTS test-suite-result document, conformant to XQTSCatalog.xsd. + */ + void toXML(XMLWriter &receiver) const; + + private: + const QString m_testSuiteVersion; + const QDate m_runDate; + const TestResult::List m_results; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TreeItem.cpp b/tests/auto/xmlpatternssdk/TreeItem.cpp new file mode 100644 index 0000000..016aefc --- /dev/null +++ b/tests/auto/xmlpatternssdk/TreeItem.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "TestContainer.h" + +#include "TreeItem.h" + +using namespace QPatternistSDK; + +int TreeItem::row() const +{ + const TreeItem *const p = parent(); + + if(p) + { + /* The const_cast makes it possible for QPointer's constructor + * to implicitly kick in. */ + return p->children().indexOf(const_cast<TreeItem *>(this)); + } + else + return -1; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TreeItem.h b/tests/auto/xmlpatternssdk/TreeItem.h new file mode 100644 index 0000000..f4e67f8 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TreeItem.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TreeItem_H +#define PatternistSDK_TreeItem_H + +#include <QObject> + +#include "Global.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QVariant; +template<typename T> class QList; +template<typename T> class QPointer; + +namespace QPatternistSDK +{ + /** + * @short TreeItem is a node in a hierachial structure and is used together + * with TreeModel. + * + * TreeItem is abstract base class. Instances of sub-classes of TreeItem + * can be used with TreeModel in order to use hierarchial data in Qt's + * model/view framework. + * + * TreeItem is a QObject in order to be able to be used with QPointer. + * + * @author Frans Englich <frans.englich@nokia.com> + * @see TreeModel + * @ingroup PatternistSDK + */ + class Q_PATTERNISTSDK_EXPORT TreeItem : public QObject + { + Q_OBJECT + public: + typedef QList<QPointer<TreeItem> > List; + + virtual ~TreeItem() {} + virtual void appendChild(TreeItem *item) = 0; + virtual TreeItem *child(const unsigned int row) const = 0; + virtual unsigned int childCount() const = 0; + virtual TreeItem *parent() const = 0; + + virtual TreeItem::List children() const = 0; + virtual int columnCount() const = 0; + + /** + * Determines the position among the children of + * this TreeItem's parent. This is done by introspecting the result + * of children(). + */ + int row() const; + + virtual QVariant data(const Qt::ItemDataRole role, int column) const = 0; + + Q_SIGNALS: + /** + * Emitted whenever this item changed. This is used for keeping + * views in synchronization with the item model which houses + * this item. + * + * @param item the item which changed. That is, this TreeItem. + */ + void changed(TreeItem *item); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TreeModel.cpp b/tests/auto/xmlpatternssdk/TreeModel.cpp new file mode 100644 index 0000000..b54f0a8 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TreeModel.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "TestContainer.h" + +#include "TreeModel.h" + +using namespace QPatternistSDK; + +TreeModel::TreeModel(const QStringList columnData, + QObject *p) : QAbstractItemModel(p), + m_root(0), + m_columnData(columnData) +{ +} + +TreeModel::~TreeModel() +{ +} + +QVariant TreeModel::data(const QModelIndex &idx, int role) const +{ + if(!idx.isValid()) + return QVariant(); + + TreeItem *item = static_cast<TreeItem *>(idx.internalPointer()); + Q_ASSERT(item); + + return item->data(static_cast<Qt::ItemDataRole>(role), idx.column()); +} + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal && role == Qt::DisplayRole) + return m_columnData.value(section); + + return QVariant(); +} + +void TreeModel::childChanged(TreeItem *item) +{ + if (item) { + const QModelIndex index = createIndex(item->row(), 0, item); + dataChanged(index, index); + } else { + layoutChanged(); + } +} + +QModelIndex TreeModel::index(int row, int column, const QModelIndex &p) const +{ + const int c = columnCount(p); + + if(row < 0 || column < 0 || column >= c) + return QModelIndex(); + + TreeItem *parentItem; + + if(p.isValid()) + parentItem = static_cast<TreeItem *>(p.internalPointer()); + else + parentItem = m_root; + + if(!parentItem) + return QModelIndex(); + + TreeItem *childItem = parentItem->child(row); + + if(childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + +QModelIndex TreeModel::parent(const QModelIndex &idx) const +{ + if(!idx.isValid()) + return QModelIndex(); + + TreeItem *childItem = static_cast<TreeItem *>(idx.internalPointer()); + Q_ASSERT(childItem); + TreeItem *parentItem = childItem->parent(); + + if(!parentItem || parentItem == m_root) + return QModelIndex(); + + Q_ASSERT(parentItem); + return createIndex(parentItem->row(), 0, parentItem); +} + +Qt::ItemFlags TreeModel::flags(const QModelIndex &idx) const +{ + /* Not sure about this code. */ + if(!idx.isValid()) + return Qt::ItemFlags(); + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +int TreeModel::rowCount(const QModelIndex &p) const +{ + if(p.column() > 0) + return 0; + + const TreeItem *parentItem; + + if(p.isValid()) + parentItem = static_cast<TreeItem *>(p.internalPointer()); + else + { + if(m_root) + parentItem = m_root; + else + return 0; + } + + return parentItem->childCount(); +} + +int TreeModel::columnCount(const QModelIndex &p) const +{ + if(p.isValid()) + return static_cast<TreeItem *>(p.internalPointer())->columnCount(); + else + return m_columnData.count(); +} + +TreeItem *TreeModel::root() const +{ + return m_root; +} + +void TreeModel::setRoot(TreeItem *r) +{ + TreeItem *const oldRoot = m_root; + m_root = r; + + if(m_root) + connect(r, SIGNAL(changed(TreeItem *)), SLOT(childChanged(TreeItem *))); + reset(); /* Notify views that we have radically changed. */ + delete oldRoot; +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/TreeModel.h b/tests/auto/xmlpatternssdk/TreeModel.h new file mode 100644 index 0000000..b1220e4 --- /dev/null +++ b/tests/auto/xmlpatternssdk/TreeModel.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_TreeModel_H +#define PatternistSDK_TreeModel_H + +#include <QAbstractItemModel> +#include <QObject> +#include <QPointer> +#include <QStringList> + +#include "Global.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class TreeItem; + + /** + * @short TreeItem is a generic QAbstractItemModel tailored for + * representing hierarchial data. + * + * TreeModel is an item model in Qt's model/view framework. Its + * data consists of TreeItem instances. + * + * @see TreeItem + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT TreeModel : public QAbstractItemModel + { + Q_OBJECT + public: + TreeModel(const QStringList columnData, QObject *parent); + virtual ~TreeModel(); + + virtual QVariant data(const QModelIndex &index, int role) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + virtual QModelIndex index(int row, + int column, + const QModelIndex &parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex &index) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + TreeItem *root() const; + /** + * Sets @p root to the new root, and deletes the old. + */ + void setRoot(TreeItem *root); + + protected Q_SLOTS: + void childChanged(TreeItem *child); + + private: + QPointer<TreeItem> m_root; + const QStringList m_columnData; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/Worker.cpp b/tests/auto/xmlpatternssdk/Worker.cpp new file mode 100644 index 0000000..02c21f8 --- /dev/null +++ b/tests/auto/xmlpatternssdk/Worker.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDir> +#include <QEventLoop> +#include <QPair> +#include <QtDebug> + +#include "ExitCode.h" + +#include "Worker.h" + +using namespace QPatternistSDK; + +const char *const Worker::m_indent = " "; + +Worker::Worker(QEventLoop &ev, + const QFileInfo &baseline, + const QFileInfo &result) : m_finishedCount(0) + , m_baselineFile(baseline) + , m_resultFile(result) + , m_eventLoop(ev) +{ +} + +void Worker::list(QTextStream &out, const QString &msg, QStringList &list) +{ + Q_ASSERT(!msg.isEmpty()); + + if(list.isEmpty()) + return; + + list.sort(); /* Make it pretty, and easy to read. */ + + out << msg << ":\n"; + + const QStringList::const_iterator end(list.constEnd()); + QStringList::const_iterator it(list.constBegin()); + + for(; it != end; ++it) + out << m_indent << qPrintable(*it) << '\n'; +} + +static inline int count(const ResultThreader::Hash &list, const TestResult::Status stat) +{ + const ResultThreader::Hash::const_iterator end(list.constEnd()); + ResultThreader::Hash::const_iterator it(list.constBegin()); + int result = 0; + + for(; it != end; ++it) + { + if(it.value() == stat) + ++result; + } + + return result; +} + +void Worker::threadFinished() +{ + ++m_finishedCount; + Q_ASSERT(m_finishedCount == 1 || m_finishedCount == 2); + + const ResultThreader *const handler = static_cast<ResultThreader *>(sender()); + Q_ASSERT(handler); + + switch(handler->type()) + { + case ResultThreader::Baseline: + { + m_baseline = handler->result(); + break; + } + case ResultThreader::Result: + m_result = handler->result(); + } + + if(m_finishedCount == 1) /* One thread's missing. */ + return; + + /* Ok, both threads have now finished, and we got their results in m_result and m_baseline. */ + + /* No matter how this function exits, we want to delete this Worker. */ + deleteLater(); + + ResultThreader::Hash::const_iterator itA(m_result.constBegin()); + ResultThreader::Hash::const_iterator itB(m_baseline.constBegin()); + const ResultThreader::Hash::const_iterator endA(m_result.constEnd()); + const ResultThreader::Hash::const_iterator endB(m_baseline.constEnd()); + const int baselineCount = m_baseline.count(); + const int resultCount = m_result.count(); + + /* If you want useful output, change the QTextStream to use stderr. */ + //QTextStream err(stderr); + QByteArray out; + QTextStream err(&out); + + if(resultCount < baselineCount) + { + err << qPrintable(QString(QLatin1String("WARNING: Test result contains %1 reports, " + "but the baseline contains %2, a DECREASE " + "of %3 tests.\n")) + .arg(resultCount) + .arg(baselineCount) + .arg(resultCount - baselineCount)); + } + else if(resultCount > baselineCount) + { + err << qPrintable(QString(QLatin1String("NOTE: The number of tests run is more than what " + "the baseline specifies. Run was %1 test cases, the " + "baseline specifies %2; an increase of %3 tests.\n")) + .arg(resultCount) + .arg(baselineCount) + .arg(resultCount - baselineCount)); + } + + for(; itA != endA; ++itA) + { + const TestResult::Status result = itA.value(); + const TestResult::Status baseline = m_baseline.value(itA.key()); + + if(result == baseline) /* We have no change. */ + { + if(result == TestResult::NotTested) + m_notTested.append(itA.key()); + else + continue; + } + else if(baseline == TestResult::Pass && result == TestResult::Fail) + m_unexpectedFailures.append(itA.key()); + else if(baseline == TestResult::Fail && result == TestResult::Pass) + m_unexpectedPasses.append(itA.key()); + } + + list(err, QLatin1String("Not tested"), m_notTested); + list(err, QLatin1String("Unexpected failures"), m_unexpectedFailures); + list(err, QLatin1String("Unexpected passes"), m_unexpectedPasses); + + err << "SUMMARY:\n"; + typedef QPair<QString, int> Info; + typedef QList<Info> InfoList; + InfoList info; + + const int totFail = count(m_result, TestResult::Fail); + const int totPass = count(m_result, TestResult::Pass); + const int total = resultCount; + const int notTested = m_notTested.count(); + const int percentage = int((static_cast<double>(totPass) / total) * 100); + + Q_ASSERT_X(percentage >= 0 && percentage <= 100, Q_FUNC_INFO, + qPrintable(QString(QLatin1String("Percentage was: %1")).arg(percentage))); + + info.append(Info(QLatin1String("Total"), total)); + info.append(Info(QLatin1String("Failures"), totFail)); + info.append(Info(QLatin1String("Passes"), totPass)); + info.append(Info(QLatin1String("Not tested"), notTested)); + info.append(Info(QLatin1String("Pass percentage(%)"), percentage)); + info.append(Info(QLatin1String("Unexpected failures"), m_unexpectedFailures.count())); + info.append(Info(QLatin1String("Unexpected passes"), m_unexpectedPasses.count())); + + const InfoList::const_iterator end(info.constEnd()); + InfoList::const_iterator it(info.constBegin()); + + /* List the statistics nicely in a row with padded columns. */ + for(; it != end; ++it) + { + const QString result((((*it).first) + QLatin1Char(':')).leftJustified(22, QLatin1Char(' '))); + err << m_indent << qPrintable(result) << (*it).second << '\n'; + } + + if(!m_unexpectedFailures.isEmpty()) + { + err << "FAILURE: Regressions discovered, baseline was not updated.\n"; + err.flush(); + QTextStream(stderr) << out; + m_eventLoop.exit(ExitCode::Regression); + return; + } + else if(m_unexpectedPasses.isEmpty() && baselineCount == resultCount) + { + err << "Result was identical to the baseline, baseline was not updated.\n"; + m_eventLoop.exit(ExitCode::Success); + return; + } + + /* Ok, we got unexpected successes and no regressions: let's update the baseline. */ + + QFile resultFile(m_resultFile.absoluteFilePath()); + + /* Remove the old file, otherwise QFile::copy() will fail. */ + QDir baselineDir(m_baselineFile.absolutePath()); + baselineDir.remove(m_baselineFile.fileName()); + + if(resultFile.copy(m_baselineFile.absoluteFilePath())) + { + /* Give a detailed message of what's going on. */ + if(resultCount > baselineCount) + err << "More tests was run than specified in the baseline, updating the baseline.\n"; + else + err << "Improvement, the baseline was updated.\n"; + + /* We actually flag this as an error, because the new baseline must be submitted. */ + err.flush(); + QTextStream(stderr) << out; + m_eventLoop.exit(ExitCode::Regression); + return; + } + else + { + err << qPrintable(QString(QLatin1String("Encountered error when updating " + "the baseline: %1\n")) + .arg(resultFile.errorString())); + err.flush(); + QTextStream(stderr) << out; + m_eventLoop.exit(ExitCode::WriteError); + return; + } +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/Worker.h b/tests/auto/xmlpatternssdk/Worker.h new file mode 100644 index 0000000..31c5c1b --- /dev/null +++ b/tests/auto/xmlpatternssdk/Worker.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_Worker_H +#define PatternistSDK_Worker_H + +#include <QFileInfo> +#include <QList> +#include <QObject> +#include <QStringList> + +#include "ResultThreader.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QEventLoop; + +namespace QPatternistSDK +{ + /** + * @short Gets notified when the ResultThreader threads are + * finished, and output summaries and adjusts a baseline. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup PatternistSDK + */ + class Q_PATTERNISTSDK_EXPORT Worker : public QObject + { + Q_OBJECT + public: + Worker(QEventLoop &e, + const QFileInfo &baseline, + const QFileInfo &result); + + public Q_SLOTS: + void threadFinished(); + + private: + static inline void list(QTextStream &out, const QString &msg, QStringList &list); + + qint8 m_finishedCount; + const QFileInfo m_baselineFile; + const QFileInfo m_resultFile; + ResultThreader::Hash m_result; + ResultThreader::Hash m_baseline; + ResultThreader::Hash m_summary; + QStringList m_unexpectedPasses; + QStringList m_unexpectedFailures; + QStringList m_notTested; + QEventLoop & m_eventLoop; + static const char *const m_indent; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/XMLWriter.cpp b/tests/auto/xmlpatternssdk/XMLWriter.cpp new file mode 100644 index 0000000..b13db10 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XMLWriter.cpp @@ -0,0 +1,669 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <QDateTime> +#include <QIODevice> +#include <QList> +#include <QPair> +#include <QStack> +#include <QtDebug> + +#include "XMLWriter.h" + +/* Issues: + * - Switch to Qt's d-pointer semantics, if in Qt. + * - Remove namespace(PatternistSDK), and change name, if in Qt. + * - Is it really necessary to pass the tag name to endElement()? + * - Could it be of interest to let the user control the encoding? Are those cases common + * enough to justify support in Qt? Using anything but UTF-8 or UTF-16 + * means asking for trouble, from an interoperability perspective. + */ + +/* Design rationalis, comments: + * + * - The class is called XMLWriter to harvest familarity by being consistent with + * Java's XMLWriter class. If XMLWriter is moved to Qt, the name QXmlWriter is perhaps suitable. + * - The class does not handle indentation because the "do one thing well"-principle is + * in use. XMLWriter should be fast and not assume a certain idea of indentation. Indentation + * should be implemented in a standalone QXmlContentHandler that performs the indentation and + * "has a" QXmlContentHandler which it in addition calls, and by that proxying/piping another + * QXmlContentHandler(which most likely is an XMLWriter). Thus, achieving a modularized, + * flexibly approach to indentation. A reason is also that indentation is very subjective. + * The indenter class should probably be called XMLIndenter/QXmlIndenter. + * - It could be of interest to implement QXmlDTDHandler such that it would be possible to serialize + * DTDs. Must be done before BC becomes significant. + * - I think the most valuable of this class is its Q_ASSERT tests. Many programmers have severe problems + * producing XML, and the tests helps them catching their mistakes. They therefore promote + * interoperability. Do not remove them. If any are wrong, fix them instead. + */ + +using namespace QPatternistSDK; + +/** + * A namespace binding, prefix/namespace URI. + */ +typedef QPair<QString, QString> NSBinding; +typedef QList<NSBinding> NSBindingList; + +#ifdef QT_NO_DEBUG +# define DEBUG_CODE(code) +#else +# define DEBUG_CODE(code) code +#endif + +class XMLWriter::Private +{ +public: + inline Private(QIODevice *devP) : insideCDATA(false), + addModificationNote(false), + dev(devP) + { + hasContentStack.push(true); + } + +#ifdef QT_NO_DEBUG + inline void validateQName(const QString &) const + { + } + + inline void verifyNS(const QString &) const + { + } +#else + /** + * Simple test of that @p name is an acceptable QName. + */ + inline void validateQName(const QString &name) + { + Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, + "An XML name cannot be empty."); + Q_ASSERT_X(!name.endsWith(QLatin1Char(':')), Q_FUNC_INFO, + "An XML name cannot end with a colon(QLatin1Char(':'))."); + Q_ASSERT_X(!name.contains(QRegExp(QLatin1String("[ \t\n]"))), Q_FUNC_INFO, + "An XML name cannot contain whitespace."); + } + + /** + * Ensures that the prefix of @p qName is declared. + */ + inline void verifyNS(const QString &qName) const + { + const QString prefix(qName.left(qName.indexOf(QLatin1Char(':')))); + + if(qName.contains(QLatin1Char(':')) && prefix != QLatin1String("xml")) + { + bool foundPrefix = false; + const QStack<NSBindingList>::const_iterator end(namespaceTracker.constEnd()); + QStack<NSBindingList>::const_iterator it(namespaceTracker.constBegin()); + + for(; it != end; ++it) + { + const NSBindingList::const_iterator lend((*it).constEnd()); + NSBindingList::const_iterator lit((*it).constBegin()); + + for(; lit != lend; ++it) + { + if((*lit).first == prefix) + { + foundPrefix = true; + break; + } + } + if(foundPrefix) + break; + } + + Q_ASSERT_X(foundPrefix, "XMLWriter::startElement()", + qPrintable(QString::fromLatin1("The prefix %1 is not declared. All prefixes " + "except 'xml' must be declared.").arg(prefix))); + } + } +#endif + + inline QString escapeElementContent(const QString &ch) + { + const int l = ch.length(); + QString retval; + + for(int i = 0; i != l; ++i) + { + const QChar c(ch.at(i)); + + if(c == QLatin1Char(QLatin1Char('&'))) + retval += QLatin1String("&"); + else if(c == QLatin1Char(QLatin1Char('<'))) + retval += QLatin1String("<"); + else + retval += c; + } + + return retval; + } + + inline QString escapeAttributeContent(const QString &ch) + { + const int l = ch.length(); + QString retval; + + for(int i = 0; i != l; ++i) + { + const QChar c(ch.at(i)); + + /* We don't have to escape '\'' because we use '\"' as attribute delimiter. */ + if(c == QLatin1Char('&')) + retval += QLatin1String("&"); + else if(c == QLatin1Char('<')) + retval += QLatin1String("<"); + else if(c == QLatin1Char('"')) + retval += QLatin1String("""); + else + retval += c; + } + + return retval; + } + + inline QString escapeCDATAContent(const QString &ch) + { + const int l = ch.length(); + QString retval; + qint8 atEnd = 0; + + for(int i = 0; i != l; ++i) + { + const QChar c(ch.at(i)); + + /* Escape '>' if in "]]>" */ + if(c == QLatin1Char(']')) + { + if(atEnd == 0 || atEnd == 1) + ++atEnd; + else + atEnd = 0; + + retval += QLatin1Char(']'); + } + else if(c == QLatin1Char('>')) + { + if(atEnd == 2) + retval += QLatin1String(">"); + else + { + atEnd = 0; + retval += QLatin1Char('>'); + } + } + else + retval += c; + } + + return retval; + } + + /** + * We wrap dev in this function such that we can deploy the Q_ASSERT_X + * macro in each place it's used. + */ + inline QIODevice *device() const + { + Q_ASSERT_X(dev, Q_FUNC_INFO, + "No device specified for XMLWriter; one must be specified with " + "setDevice() or via the constructor before XMLWriter can be used."); + return dev; + } + + /** + * @returns true on success, otherwise false + */ + inline bool serialize(const QString &data) + { + const QByteArray utf8(data.toUtf8()); + + return device()->write(utf8) == utf8.size(); + } + + /** + * @returns true on success, otherwise false + */ + inline bool serialize(const char data) + { + return device()->putChar(data); + } + + /** + * @returns true on success, otherwise false + */ + inline bool serialize(const char *data) + { + return device()->write(data) == qstrlen(data); + } + + inline bool hasElementContent() const + { + return hasContentStack.top(); + } + + inline void handleElement() + { + if(!hasElementContent()) + serialize('>'); + + /* This element is content for the parent. */ + hasContentStack.top() = true; + } + + NSBindingList namespaces; + bool insideCDATA; + bool addModificationNote; + QString msg; + QIODevice *dev; + QStack<bool> hasContentStack; + QString errorString; + DEBUG_CODE(QStack<QString> tags;) + DEBUG_CODE(QStack<NSBindingList> namespaceTracker;) +}; + +/** + * Reduces complexity. The empty else clause is for avoiding mess when macro + * is used in the 'then' branch of an if clause, which is followed by an else clause. + */ +#define serialize(string) if(!d->serialize(string)) \ + { \ + d->errorString = d->device()->errorString(); \ + return false; \ + } \ + else do {} while (false) + +XMLWriter::XMLWriter(QIODevice *outStream) : d(new Private(outStream)) +{ +} + +XMLWriter::~XMLWriter() +{ + delete d; +} + +bool XMLWriter::startDocument() +{ + if(!device()->isOpen() && !device()->open(QIODevice::WriteOnly)) + return false; + + if(d->addModificationNote) + { + if(d->msg.isNull()) + { + d->msg = QString::fromLatin1("NOTE: This file was automatically generated " + "by %1 at %2. All changes to this file will be lost.") + .arg(QCoreApplication::instance()->applicationName(), + QDateTime::currentDateTime().toString()); + } + if(!comment(d->msg)) + return false; + + serialize('\n'); + } + + serialize(QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")); + + return true; +} + +bool XMLWriter::startElement(const QString &/*namespaceURI*/, + const QString &/*localName*/, + const QString &qName, + const QXmlAttributes &atts) +{ + return startElement(qName, atts); +} + +bool XMLWriter::startElement(const QString &qName, + const QXmlAttributes &atts) +{ + Q_ASSERT_X(!d->insideCDATA, Q_FUNC_INFO, + "Only characters() can be received when inside CDATA."); + Q_ASSERT_X(!qName.startsWith(QLatin1String("xmlns")), Q_FUNC_INFO, + "startElement should not be used for declaring prefixes, " + "use startPrefixMapping() for that."); + + d->validateQName(qName); + d->verifyNS(qName); + + d->handleElement(); + + serialize('<'); + serialize(qName); + + DEBUG_CODE(d->tags.push(qName)); + DEBUG_CODE(d->namespaceTracker.push(d->namespaces)); + + /* Add namespace declarations. */ + const NSBindingList::const_iterator end(d->namespaces.constEnd()); + NSBindingList::const_iterator it(d->namespaces.constBegin()); + + for(; it != end; ++it) + { + if((*it).first.isEmpty()) + serialize(" xmlns="); + else + { + serialize(" xmlns:"); + serialize((*it).first); + serialize('='); + } + + serialize('"'); + serialize(d->escapeElementContent((*it).second)); + serialize('"'); + } + d->namespaces.clear(); + + const int c = atts.count(); + + /* Serialize attributes. */ + for(int i = 0; i != c; ++i) + { + d->validateQName(atts.qName(i)); + d->verifyNS(atts.qName(i)); + + serialize(' '); + serialize(atts.qName(i)); + serialize("=\""); + serialize(d->escapeAttributeContent(atts.value(i))); + serialize('"'); + } + + d->hasContentStack.push(false); + return true; +} + +bool XMLWriter::endElement(const QString &/*namespaceURI*/, + const QString &/*localName*/, + const QString &qName) +{ + return endElement(qName); +} + +bool XMLWriter::endElement(const QString &qName) +{ + Q_ASSERT_X(!d->insideCDATA, Q_FUNC_INFO, + "Only characters() can be received when inside CDATA."); + Q_ASSERT_X(d->tags.pop() == qName, Q_FUNC_INFO, + "The element tags are not balanced, the produced XML is invalid."); + + DEBUG_CODE(d->namespaceTracker.pop()); + + /* "this" element is content for our parent, so ensure hasElementContent is true. */ + + if(d->hasElementContent()) + { + serialize(QLatin1String("</")); + serialize(qName); + serialize('>'); + } + else + serialize(QLatin1String("/>")); + + d->hasContentStack.pop(); + + return true; +} + +bool XMLWriter::startPrefixMapping(const QString &prefix, const QString &uri) +{ + Q_ASSERT_X(!d->insideCDATA, Q_FUNC_INFO, + "Only characters() can be received when inside CDATA."); + Q_ASSERT_X(prefix.toLower() != QLatin1String("xml") || + (prefix.toLower() == QLatin1String("xml") && + (uri == QLatin1String("http://www.w3.org/TR/REC-xml-names/") || + uri.isEmpty())), + Q_FUNC_INFO, + "The prefix 'xml' can only be bound to the namespace " + "\"http://www.w3.org/TR/REC-xml-names/\"."); + Q_ASSERT_X(prefix.toLower() != QLatin1String("xml") && + uri != QLatin1String("http://www.w3.org/TR/REC-xml-names/"), + Q_FUNC_INFO, + "The namespace \"http://www.w3.org/TR/REC-xml-names/\" can only be bound to the " + "\"xml\" prefix."); + + d->namespaces.append(qMakePair(prefix, uri)); + return true; +} + +bool XMLWriter::processingInstruction(const QString &target, + const QString &data) +{ + Q_ASSERT_X(target.toLower() != QLatin1String("xml"), Q_FUNC_INFO, + "A processing instruction cannot have the name xml in any " + "capitalization, because it is reserved."); + Q_ASSERT_X(!data.contains(QLatin1String("?>")), Q_FUNC_INFO, + "The content of a processing instruction cannot contain the string \"?>\"."); + Q_ASSERT_X(!d->insideCDATA, "XMLWriter::processingInstruction()", + "Only characters() can be received when inside CDATA."); + + d->handleElement(); + + serialize(QLatin1String("<?")); + serialize(target); + serialize(' '); + serialize(data); + serialize(QLatin1String("?>")); + return true; +} + +bool XMLWriter::characters(const QString &ch) +{ + Q_ASSERT_X(d->tags.count() >= 1, Q_FUNC_INFO, + "Text nodes can only appear inside elements(no elements sent)."); + d->handleElement(); + + if(d->insideCDATA) + serialize(d->escapeCDATAContent(ch)); + else + serialize(d->escapeElementContent(ch)); + + return true; +} + +bool XMLWriter::comment(const QString &ch) +{ + Q_ASSERT_X(!d->insideCDATA, Q_FUNC_INFO, + "Only characters() can be received when inside CDATA."); + Q_ASSERT_X(!ch.contains(QLatin1String("--")), Q_FUNC_INFO, + "XML comments may not contain double-hyphens(\"--\")."); + Q_ASSERT_X(!ch.endsWith(QLatin1Char('-')), Q_FUNC_INFO, + "XML comments cannot end with a hyphen, \"-\"(add a space, for example)."); + /* A comment starting with "<!---" is ok. */ + + d->handleElement(); + + serialize(QLatin1String("<!--")); + serialize(ch); + serialize(QLatin1String("-->")); + + return true; +} + +bool XMLWriter::startCDATA() +{ + Q_ASSERT_X(d->insideCDATA, Q_FUNC_INFO, + "startCDATA() has already been called."); + Q_ASSERT_X(d->tags.count() >= 1, Q_FUNC_INFO, + "CDATA sections can only appear inside elements(no elements sent)."); + d->insideCDATA = true; + serialize(QLatin1String("<![CDATA[")); + return true; +} + +bool XMLWriter::endCDATA() +{ + d->insideCDATA = false; + serialize("]]>"); + return true; +} + +bool XMLWriter::startDTD(const QString &name, + const QString &publicId, + const QString &systemId) +{ + Q_ASSERT_X(!d->insideCDATA, Q_FUNC_INFO, + "Only characters() can be received when inside CDATA."); + Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, + "The DOCTYPE name cannot be empty."); + Q_ASSERT_X(d->tags.isEmpty() && d->namespaces.isEmpty(), Q_FUNC_INFO, + "No content such as namespace declarations or elements can be serialized " + "before the DOCTYPE declaration, the XML is invalid."); + Q_ASSERT_X(!publicId.contains(QLatin1Char('"')), Q_FUNC_INFO, + "The PUBLIC ID cannot contain quotes('\"')."); + Q_ASSERT_X(!systemId.contains(QLatin1Char('"')), Q_FUNC_INFO, + "The SYSTEM ID cannot contain quotes('\"')."); + + serialize(QLatin1String("<!DOCTYPE ")); + serialize(name); + + if(!publicId.isEmpty()) + { + Q_ASSERT_X(!systemId.isEmpty(), Q_FUNC_INFO, + "When a public identifier is specified, a system identifier " + "must also be specified in order to produce valid XML."); + serialize(" PUBLIC \""); + serialize(publicId); + serialize('"'); + } + + if(!systemId.isEmpty()) + { + if(publicId.isEmpty()) + serialize(" SYSTEM"); + + serialize(" \""); + serialize(systemId); + serialize('"'); + } + + return true; +} + +bool XMLWriter::endDTD() +{ + Q_ASSERT_X(d->tags.isEmpty() && d->namespaces.isEmpty(), Q_FUNC_INFO, + "Content such as namespace declarations or elements cannot occur inside " + "the DOCTYPE declaration, the XML is invalid."); + serialize(QLatin1String(">\n")); + return true; +} + +bool XMLWriter::startEntity(const QString &) +{ + return true; +} + +bool XMLWriter::endEntity(const QString &) +{ + return true; +} + +void XMLWriter::setMessage(const QString &msg) +{ + d->msg = msg; +} + +QString XMLWriter::modificationMessage() const +{ + return d->msg; +} + +bool XMLWriter::endDocument() +{ + Q_ASSERT_X(d->tags.isEmpty(), Q_FUNC_INFO, + "endDocument() called before all elements were closed with endElement()."); + d->device()->close(); + return true; +} + +QString XMLWriter::errorString() const +{ + return d->errorString; +} + +bool XMLWriter::ignorableWhitespace(const QString &ch) +{ + return characters(ch); +} + +bool XMLWriter::endPrefixMapping(const QString &) +{ + /* Again, should we do something with this? */ + return true; +} + +bool XMLWriter::skippedEntity(const QString &) +{ + return true; +} + +void XMLWriter::setDocumentLocator(QXmlLocator *) +{ +} + +QIODevice *XMLWriter::device() const +{ + return d->dev; +} + +void XMLWriter::setDevice(QIODevice *dev) +{ + d->dev = dev; +} + +void XMLWriter::setAddMessage(const bool toggle) +{ + d->addModificationNote = toggle; +} + +bool XMLWriter::addModificationMessage() const +{ + return d->addModificationNote; +} + +#undef serialize +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/XMLWriter.h b/tests/auto/xmlpatternssdk/XMLWriter.h new file mode 100644 index 0000000..dd7b548 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XMLWriter.h @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XMLWriter_H +#define PatternistSDK_XMLWriter_H + +#include "Global.h" + +#include <QtXml/QXmlContentHandler> +#include <QtXml/QXmlLexicalHandler> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QIODevice; + +namespace QPatternistSDK +{ + /** + * @short Serializes a stream of SAX events into XML, sent to a QIODevice. + * + * XMLWriter is a fast and simple XML serializer which takes care of + * all the low level details of well-formedness and character escaping, allowing + * the user to focus on higher level issues and increasing the chances of producing + * valid, interoperable XML. + * + * The content XMLWriter produces is sent to a QIODevice, which is either + * specified in XMLWriter's constructor or via setDevice(). If writing to + * the device fails, the content functions such as startElement() returns @c false. + * + * XMLWriter sub-classes QXmlContentHandler meaning it can serialize content + * from any code that produces SAX events. The class can also be used manually, + * by calling startElement(), endCDATA(), and so forth. + * + * XMLWriter cannot be used to serialize multiple documents. One instance per + * document must be used. + * + * XMLWriter takes care of escaping content into character references as necessary. Thus, + * it should not be done manually. In fact, it would most likely + * result in invalid XML or an unintended result. XMLWriter always serializes into UTF-8. + * + * When compiled in debug mode, XMLWriter contains several tests that helps + * ensuring that XMLWriter produces valid XML. Some of these tests ensures that: + * + * - The @c xmlns and @c xml prefixes are used properly + * - Content of comments and processing instructions is valid + * - Element, attribute and DOCTYPE names are sensible + * - Elements are properly nested and balanced + * - To some extent that things occur in the proper order. For example, that + * the document type definition isn't added inside an element + * - That namespaces prefixes are declared + * + * Not triggering XMLWriter's tests does not guarantee valid XML is produced, + * but they do help catching common mistakes and some of the corner cases in the + * specifications. When XMLWriter is compiled in release mode, these tests are not enabled + * and the error handling in effect is concerning writing to the QIODevice. + * + * Often it is of interest to add a note at the beginning of the file communicating + * it is auto-generated. setMessage() and setAddMessage() provides + * a convenient way of doing that. + * + * Namespace declarations are added with startPrefixMapping(), not by sending attributes + * with name <tt>xmlns:*</tt> to startElement(). + * + * @see <a href="http://hsivonen.iki.fi/producing-xml/">HOWTO Avoid Being + * Called a Bozo When Producing XML</a> + * @see <a href="http://www.w3.org/TR/REC-xml/">Extensible Markup + * Language (XML) 1.0 (Third Edition)</a> + * @see <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a> + * @todo Replace this class with QXmlStreamWriter + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup PatternistSDK + */ + class Q_PATTERNISTSDK_EXPORT XMLWriter : public QXmlContentHandler + , public QXmlLexicalHandler + { + public: + /** + * Creates a XMLWriter which serializes its received events + * to @p outStream. + * + * @note XMLWriter does not claim ownership of @p outStream. Thus, + * @p outStream may not be destroyed as long as + * this XMLWriter instance uses it. + */ + XMLWriter(QIODevice *outStream = 0); + + virtual ~XMLWriter(); + + /** + * @returns @c true if opening the output device succeeds, otherwise @c false + */ + virtual bool startDocument(); + + /** + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool characters(const QString &ch); + + /** + * Starts an element with name @p qName and attributes @p atts. The prefix + * in @p qName must first be declared with startPrefixMapping(), if it has one. + * + * A call to startElement() must always at some point be balanced with a call + * to endElement(). + * + * To declare namespaces, don't put attributes with name <tt>xmlns:*</tt> in @p atts, + * but use startPrefixMapping(). + */ + virtual bool startElement(const QString &qName, const QXmlAttributes &atts = QXmlAttributes()); + + /** + * + * Behaves essentially as startElement(const QString &qName, const QXmlAttributes &atts). This + * function is used in conjunction with other SAX classes. + * + * The call: + * + * @code + * startElement(QString(), QString(), qName, atts); + * @endcode + * + * is equivalent to: + * + * @code + * startElement(qName, atts); + * @endcode + * + * @p namespaceURI and @p localName are not used. This function is + * used in conjunction with other SAX classes. + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + + /** + * Signals the end of an element with name @p qName. @p qName must + * be supplied. + * + * Calls to startElement() and endElement() must always be balanced. + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool endElement(const QString &qName); + + /** + * Behaves essentially as endElement(const QString &qName). This function + * is used when XMLWriter is used in SAX code. + * + * @p namespaceURI and @p localName are not used. + * + * The call: + * + * @code + * endElement(QString(), QString(), qName); + * @endcode + * + * is equivalent to: + * + * @code + * endElement(qName); + * @endcode + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool endElement(const QString &namespaceURI, + const QString &localName, + const QString &qName); + + /** + * A description of an error if it occurred. This is typically + * QIODevice::errorString(). If no error has occurred, an empty + * string is returned. + */ + virtual QString errorString() const; + + /** + * Starts a CDATA section. Content sent with characters() will not be escaped + * except for ">" if occurring in "]]>". + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool startCDATA(); + + /** + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool endCDATA(); + + /** + * Creates a document type definition. + * + * For example, the code snippet: + * + * @code + * writer.startDTD("html", "-//W3C//DTD XHTML 1.0 Strict//EN", + * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); + * writer.endDTD(); + * @endcode + * + * would create: + * @verbatim + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +@endverbatim + * + * @note A system identifier must always be specified, but a public identifier may + * be left out. + * + * A call to startDTD() must be followed by a call to endDTD(). + */ + virtual bool startDTD(const QString &name, + const QString &publicId, + const QString &systemId); + + /** + * Apart from closing the DTD, an new line is also added at end. + */ + virtual bool endDTD(); + + /** + * Creates a processing instruction by name @p target, and content + * @p data. + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool processingInstruction(const QString &target, + const QString &data); + + /** + * Declares a namespace which maps @p prefix to @p namespaceURI. For example, the call: + * + * @code + * startPrefixMapping("xhtml", "http://www.w3.org/1999/xhtml"); + * @endcode + * + * would result in: + * + * @code + * xmlns="http://www.w3.org/1999/xhtml" + * @endcode + */ + virtual bool startPrefixMapping(const QString &prefix, + const QString &namespaceURI); + + /** + * Creates a comment with content @p ch. @p ch is escaped, there's + * no need to do it manually. For example, calling comment() with @p ch + * set to "my comment", results in "<!--my comment-->" in the output. + * + * @note if @p ch contains double hyphen("--"), the produced XML will + * not be well formed. + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool comment(const QString &ch); + + virtual bool startEntity(const QString &name); + virtual bool endEntity(const QString &name); + + /** + * Sets the message which is added as a comment if addModificationMessage() + * is set to @c true. If no message is specified and addModificationMessage() + * is set to @c true, a default message is used. + * + * @see modificationMessage(), setAddMessage() + */ + virtual void setMessage(const QString &msg); + + /** + * The message that is added at the beginning of the XML events + * in a comment node. If no modificationMessage is set via modificationMessage(), + * and addModificationMessage is set to @c true, this message will be used: + * "NOTE: This file was automatically generated by [the application name] at + * [the current date time]. All changes to this file will be lost." + * + * @see setMessage() + */ + virtual QString modificationMessage() const; + + /** + * Closes the QIODevice XMLWriter writes to. + */ + virtual bool endDocument(); + + /** + * Serializes @p ch as if it was sent to characters(). + * + * @returns @c false if failure occurs in writing to the QIODevice, otherwise + * @c true + */ + virtual bool ignorableWhitespace(const QString &ch); + + /** + * This function is not used by XMLWriter, but is implemented + * in order to satisfy QXmlContentHandler's interface. + */ + virtual bool endPrefixMapping(const QString &prefix); + + /** + * This function is not used by XMLWriter, but is implemented + * in order to satisfy QXmlContentHandler's interface. + */ + virtual bool skippedEntity(const QString &name); + + /** + * This function is not used by XMLWriter, but is implemented + * in order to satisfy QXmlContentHandler's interface. + */ + virtual void setDocumentLocator(QXmlLocator *); + + /** + * @returns the device XMLWriter writes its output to. + * XMLWriter does not own the device. + */ + virtual QIODevice *device() const; + + /** + * Sets the QIODevice XMLWriter writes to, to @p device. A device must be specified + * either via this function or in the constructor before XMLWriter is used. + * + * XMLWriter does not claim ownership of @p device. + */ + virtual void setDevice(QIODevice *device); + + /** + * Determines whether the modification message should be inserted as a comment + * before the document element. The message returned by modificationMessage() is used. + * + * If @p toggle is @c true, the message will be added, otherwise not. + */ + virtual void setAddMessage(const bool toggle); + + /** + * Tells whether a modification message will be added. + * + * @see setAddMessage(), modificationMessage() + */ + virtual bool addModificationMessage() const; + + private: + Q_DISABLE_COPY(XMLWriter) + + class Private; + Private *d; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/XQTSTestCase.cpp b/tests/auto/xmlpatternssdk/XQTSTestCase.cpp new file mode 100644 index 0000000..c793d71 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XQTSTestCase.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QColor> +#include <QFile> +#include <QFileInfo> +#include <QVariant> +#include <QtDebug> + +#include "XQTSTestCase.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +XQTSTestCase::XQTSTestCase(const Scenario scen, + TreeItem *p, + const QXmlQuery::QueryLanguage lang) : m_isXPath(false) + , m_scenario(scen) + , m_parent(p) + , m_lang(lang) +{ +} + +XQTSTestCase::~XQTSTestCase() +{ + qDeleteAll(m_baseLines); +} + +QVariant XQTSTestCase::data(const Qt::ItemDataRole role, int column) const +{ + if(role == Qt::DisplayRole) + { + if(column == 0) + return title(); + + const TestResult *const tr = testResult(); + if(!tr) + { + if(column == 1) + return TestResult::displayName(TestResult::NotTested); + else + return QString(); + } + const TestResult::Status status = tr->status(); + + switch(column) + { + case 1: + return status == TestResult::Pass ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + case 2: + return status == TestResult::Fail ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + default: + return QString(); + } + } + + if(role != Qt::BackgroundRole) + return QVariant(); + + const TestResult *const tr = testResult(); + + if(!tr) + { + if(column == 0) + return Qt::yellow; + else + return QVariant(); + } + + const TestResult::Status status = tr->status(); + + if(status == TestResult::NotTested || status == TestResult::Unknown) + return Qt::yellow; + + switch(column) + { + case 1: + return status == TestResult::Pass ? Qt::green : QVariant(); + case 2: + return status == TestResult::Fail ? Qt::red : QVariant(); + default: + return QVariant(); + } +} + +QString XQTSTestCase::sourceCode(bool &ok) const +{ + QFile file(m_queryPath.toLocalFile()); + + QString err; + + if(!file.exists()) + err = QString::fromLatin1("Error: %1 does not exist.").arg(file.fileName()); + else if(!QFileInfo(file.fileName()).isFile()) + err = QString::fromLatin1("Error: %1 is not a file, cannot display it.").arg(file.fileName()); + else if(!file.open(QIODevice::ReadOnly)) + err = QString::fromLatin1("Error: Could not open %1. Likely a permission error.") + .arg(file.fileName()); + + if(err.isNull()) /* No errors. */ + { + ok = true; + /* Scary, we assume the query is stored in UTF-8. */ + return QString::fromUtf8(file.readAll()); + } + else + { + ok = false; + return err; + } +} + +int XQTSTestCase::columnCount() const +{ + return 2; +} + +void XQTSTestCase::addBaseLine(TestBaseLine *line) +{ + m_baseLines.append(line); +} + +QString XQTSTestCase::name() const +{ + return m_name; +} + +QString XQTSTestCase::creator() const +{ + return m_creator; +} + +QString XQTSTestCase::description() const +{ + return m_description; +} + +QDate XQTSTestCase::lastModified() const +{ + return m_lastModified; +} + +bool XQTSTestCase::isXPath() const +{ + return m_isXPath; +} + +TestCase::Scenario XQTSTestCase::scenario() const +{ + return m_scenario; +} + +void XQTSTestCase::setName(const QString &n) +{ + m_name = n; +} + +void XQTSTestCase::setCreator(const QString &ctor) +{ + m_creator = ctor; +} + +void XQTSTestCase::setDescription(const QString &descriptionP) +{ + m_description = descriptionP; +} + +void XQTSTestCase::setLastModified(const QDate &date) +{ + m_lastModified = date; +} + +void XQTSTestCase::setIsXPath(const bool isXPathP) +{ + m_isXPath = isXPathP; +} + +void XQTSTestCase::setQueryPath(const QUrl &uri) +{ + m_queryPath = uri; +} + +TreeItem *XQTSTestCase::parent() const +{ + return m_parent; +} + +QString XQTSTestCase::title() const +{ + return m_name; +} + +TestBaseLine::List XQTSTestCase::baseLines() const +{ + Q_ASSERT_X(!m_baseLines.isEmpty(), Q_FUNC_INFO, + qPrintable(QString::fromLatin1("The test %1 has no base lines, it should have at least one.").arg(name()))); + return m_baseLines; +} + +QUrl XQTSTestCase::testCasePath() const +{ + return m_queryPath; +} + +void XQTSTestCase::setExternalVariableLoader(const QPatternist::ExternalVariableLoader::Ptr &loader) +{ + m_externalVariableLoader = loader; +} + +QPatternist::ExternalVariableLoader::Ptr XQTSTestCase::externalVariableLoader() const +{ + return m_externalVariableLoader; +} + +void XQTSTestCase::setContextItemSource(const QUrl &uri) +{ + m_contextItemSource = uri; +} + +QUrl XQTSTestCase::contextItemSource() const +{ + return m_contextItemSource; +} + +QXmlQuery::QueryLanguage XQTSTestCase::language() const +{ + return m_lang; +} + +void XQTSTestCase::setParent(TreeItem *const p) +{ + m_parent = p; +} + +void XQTSTestCase::setInitialTemplateName(const QXmlName &name) +{ + m_initialTemplateName = name; +} + +QXmlName XQTSTestCase::initialTemplateName() const +{ + return m_initialTemplateName; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/XQTSTestCase.h b/tests/auto/xmlpatternssdk/XQTSTestCase.h new file mode 100644 index 0000000..edb4d63 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XQTSTestCase.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XQTSTestCase_H +#define PatternistSDK_XQTSTestCase_H + +#include <QDate> +#include <QString> +#include <QUrl> + +#include "qexternalvariableloader_p.h" + +#include "TestBaseLine.h" +#include "TestCase.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Represents a test case in a test suite in the XML Query Test Suite. + * + * TestCase is a memory representation of a test case, and maps + * to the @c test-case element in the XQuery Test Suite test + * case catalog. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT XQTSTestCase : public TestCase + { + public: + XQTSTestCase(const Scenario scen, TreeItem *parent, + const QXmlQuery::QueryLanguage lang = QXmlQuery::XQuery10); + virtual ~XQTSTestCase(); + + /** + * The identifier, the name of the test. For example, "Literals034". + * The name of a test case must be unique. + */ + virtual QString name() const; + virtual QString creator() const; + virtual QString description() const; + /** + * @returns the query inside the file, specified by testCasePath(). Loading + * of the file is not cached in order to avoid complications. + * @param ok is set to @c false if loading the query file fails + */ + virtual QString sourceCode(bool &ok) const; + virtual QUrl testCasePath() const; + virtual QDate lastModified() const; + + bool isXPath() const; + + /** + * What kind of test case this is, what kind of scenario it takes part + * of. For example, whether the test case should evaluate normally or fail. + */ + Scenario scenario() const; + + void setCreator(const QString &creator); + void setLastModified(const QDate &date); + void setDescription(const QString &description); + void setIsXPath(const bool isXPath); + void setName(const QString &name); + void setQueryPath(const QUrl &uri); + void setContextItemSource(const QUrl &uri); + void addBaseLine(TestBaseLine *lines); + void setInitialTemplateName(const QXmlName &name); + + virtual TreeItem *parent() const; + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + virtual QString title() const; + virtual TestBaseLine::List baseLines() const; + + virtual int columnCount() const; + + void setExternalVariableLoader(const QPatternist::ExternalVariableLoader::Ptr &loader); + virtual QPatternist::ExternalVariableLoader::Ptr externalVariableLoader() const; + virtual QUrl contextItemSource() const; + virtual QXmlQuery::QueryLanguage language() const; + void setParent(TreeItem *const parent); + virtual QXmlName initialTemplateName() const; + + private: + QString m_name; + QString m_creator; + QString m_description; + QUrl m_queryPath; + bool m_isXPath; + QDate m_lastModified; + const Scenario m_scenario; + TreeItem * m_parent; + TestBaseLine::List m_baseLines; + QPatternist::ExternalVariableLoader::Ptr m_externalVariableLoader; + QUrl m_contextItemSource; + QXmlQuery::QueryLanguage m_lang; + QXmlName m_initialTemplateName; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/XSDTSTestCase.cpp b/tests/auto/xmlpatternssdk/XSDTSTestCase.cpp new file mode 100644 index 0000000..c51ad7a --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSDTSTestCase.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the autotests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QColor> +#include <QFile> +#include <QFileInfo> +#include <QVariant> +#include <QtDebug> + +#include "XSDTSTestCase.h" + +#include "qxmlschema.h" +#include "qxmlschemavalidator.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +XSDTSTestCase::XSDTSTestCase(const Scenario scen, TreeItem *p, TestType testType) + : m_scenario(scen) + , m_parent(p) + , m_testType(testType) +{ +} + +XSDTSTestCase::~XSDTSTestCase() +{ + qDeleteAll(m_baseLines); +} + +TestResult::List XSDTSTestCase::execute(const ExecutionStage, TestSuite*) +{ + ErrorHandler errHandler; + ErrorHandler::installQtMessageHandler(&errHandler); + + TestResult::List retval; + TestResult::Status resultStatus = TestResult::Unknown; + QString serialized; + + if (m_testType == SchemaTest) { + executeSchemaTest(resultStatus, serialized, &errHandler); + } else { + executeInstanceTest(resultStatus, serialized, &errHandler); + } + + resultStatus = TestBaseLine::scan(serialized, baseLines()); + Q_ASSERT(resultStatus != TestResult::Unknown); + + m_result = new TestResult(name(), resultStatus, 0, errHandler.messages(), + QPatternist::Item::List(), serialized); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; +} + +void XSDTSTestCase::executeSchemaTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler) +{ + QFile file(m_schemaUri.path()); + if (!file.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + QXmlSchema schema; + schema.setMessageHandler(handler); + schema.load(&file, m_schemaUri); + + if (schema.isValid()) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("true"); + } else { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + } +} + +void XSDTSTestCase::executeInstanceTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler) +{ + QFile instanceFile(m_instanceUri.path()); + if (!instanceFile.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + QXmlSchema schema; + if (m_schemaUri.isValid()) { + QFile file(m_schemaUri.path()); + if (!file.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + schema.setMessageHandler(handler); + schema.load(&file, m_schemaUri); + + if (!schema.isValid()) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + return; + } + } + + QXmlSchemaValidator validator(schema); + validator.setMessageHandler(handler); + + qDebug("check %s", qPrintable(m_instanceUri.path())); + if (validator.validate(&instanceFile, m_instanceUri)) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("true"); + } else { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + } +} + +QVariant XSDTSTestCase::data(const Qt::ItemDataRole role, int column) const +{ + if(role == Qt::DisplayRole) + { + if(column == 0) + return title(); + + const TestResult *const tr = testResult(); + if(!tr) + { + if(column == 1) + return TestResult::displayName(TestResult::NotTested); + else + return QString(); + } + const TestResult::Status status = tr->status(); + + switch(column) + { + case 1: + return status == TestResult::Pass ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + case 2: + return status == TestResult::Fail ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + default: + return QString(); + } + } + + if(role != Qt::BackgroundRole) + return QVariant(); + + const TestResult *const tr = testResult(); + + if(!tr) + { + if(column == 0) + return Qt::yellow; + else + return QVariant(); + } + + const TestResult::Status status = tr->status(); + + if(status == TestResult::NotTested || status == TestResult::Unknown) + return Qt::yellow; + + switch(column) + { + case 1: + return status == TestResult::Pass ? Qt::green : QVariant(); + case 2: + return status == TestResult::Fail ? Qt::red : QVariant(); + default: + return QVariant(); + } +} + +QString XSDTSTestCase::sourceCode(bool &ok) const +{ + QFile file((m_testType == SchemaTest ? m_schemaUri : m_instanceUri).toLocalFile()); + + QString err; + + if(!file.exists()) + err = QString::fromLatin1("Error: %1 does not exist.").arg(file.fileName()); + else if(!QFileInfo(file.fileName()).isFile()) + err = QString::fromLatin1("Error: %1 is not a file, cannot display it.").arg(file.fileName()); + else if(!file.open(QIODevice::ReadOnly)) + err = QString::fromLatin1("Error: Could not open %1. Likely a permission error.") + .arg(file.fileName()); + + if(err.isNull()) /* No errors. */ + { + ok = true; + /* Scary, we assume the query is stored in UTF-8. */ + return QString::fromUtf8(file.readAll()); + } + else + { + ok = false; + return err; + } +} + +int XSDTSTestCase::columnCount() const +{ + return 2; +} + +void XSDTSTestCase::addBaseLine(TestBaseLine *line) +{ + m_baseLines.append(line); +} + +QString XSDTSTestCase::name() const +{ + return m_name; +} + +QString XSDTSTestCase::creator() const +{ + return m_creator; +} + +QString XSDTSTestCase::description() const +{ + return m_description; +} + +QDate XSDTSTestCase::lastModified() const +{ + return m_lastModified; +} + +bool XSDTSTestCase::isXPath() const +{ + return false; +} + +TestCase::Scenario XSDTSTestCase::scenario() const +{ + return m_scenario; +} + +void XSDTSTestCase::setName(const QString &n) +{ + m_name = n; +} + +void XSDTSTestCase::setCreator(const QString &ctor) +{ + m_creator = ctor; +} + +void XSDTSTestCase::setDescription(const QString &descriptionP) +{ + m_description = descriptionP; +} + +void XSDTSTestCase::setLastModified(const QDate &date) +{ + m_lastModified = date; +} + +void XSDTSTestCase::setSchemaUri(const QUrl &uri) +{ + m_schemaUri = uri; +} + +void XSDTSTestCase::setInstanceUri(const QUrl &uri) +{ + m_instanceUri = uri; +} + +TreeItem *XSDTSTestCase::parent() const +{ + return m_parent; +} + +QString XSDTSTestCase::title() const +{ + return m_name; +} + +TestBaseLine::List XSDTSTestCase::baseLines() const +{ + Q_ASSERT_X(!m_baseLines.isEmpty(), Q_FUNC_INFO, + qPrintable(QString::fromLatin1("The test %1 has no base lines, it should have at least one.").arg(name()))); + return m_baseLines; +} + +QUrl XSDTSTestCase::schemaUri() const +{ + return m_schemaUri; +} + +QUrl XSDTSTestCase::instanceUri() const +{ + return m_instanceUri; +} + +void XSDTSTestCase::setContextItemSource(const QUrl &uri) +{ + m_contextItemSource = uri; +} + +QUrl XSDTSTestCase::contextItemSource() const +{ + return m_contextItemSource; +} + +void XSDTSTestCase::setParent(TreeItem *const p) +{ + m_parent = p; +} + +QPatternist::ExternalVariableLoader::Ptr XSDTSTestCase::externalVariableLoader() const +{ + return QPatternist::ExternalVariableLoader::Ptr(); +} + +TestResult *XSDTSTestCase::testResult() const +{ + return m_result; +} + +TestItem::ResultSummary XSDTSTestCase::resultSummary() const +{ + if(m_result) + return ResultSummary(m_result->status() == TestResult::Pass ? 1 : 0, + 1); + + return ResultSummary(0, 1); +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/XSDTSTestCase.h b/tests/auto/xmlpatternssdk/XSDTSTestCase.h new file mode 100644 index 0000000..cf37577 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSDTSTestCase.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the autotests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XSDTSTestCase_H +#define PatternistSDK_XSDTSTestCase_H + +#include <QDate> +#include <QString> +#include <QUrl> + +#include "TestBaseLine.h" +#include "TestCase.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + /** + * @short Represents a test case in a test suite in the XML Query Test Suite. + * + * TestCase is a memory representation of a test case, and maps + * to the @c test-case element in the XQuery Test Suite test + * case catalog. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT XSDTSTestCase : public TestCase + { + public: + enum TestType + { + SchemaTest, + InstanceTest + }; + + XSDTSTestCase(const Scenario scen, TreeItem *parent, TestType testType); + virtual ~XSDTSTestCase(); + + /** + * Executes the test, and returns the result. The returned list + * will always contain exactly one TestResult. + * + * @p stage is ignored when running out-of-process. + */ + virtual TestResult::List execute(const ExecutionStage stage, + TestSuite *ts); + /** + * The identifier, the name of the test. For example, "Literals034". + * The name of a test case must be unique. + */ + virtual QString name() const; + virtual QString creator() const; + virtual QString description() const; + /** + * @returns the query inside the file, specified by testCasePath(). Loading + * of the file is not cached in order to avoid complications. + * @param ok is set to @c false if loading the query file fails + */ + virtual QString sourceCode(bool &ok) const; + virtual QUrl schemaUri() const; + virtual QUrl instanceUri() const; + virtual QUrl testCasePath() const {return QUrl();} + virtual QDate lastModified() const; + + bool isXPath() const; + + /** + * What kind of test case this is, what kind of scenario it takes part + * of. For example, whether the test case should evaluate normally or fail. + */ + Scenario scenario() const; + + void setCreator(const QString &creator); + void setLastModified(const QDate &date); + void setDescription(const QString &description); + void setName(const QString &name); + void setSchemaUri(const QUrl &uri); + void setInstanceUri(const QUrl &uri); + void setTestCasePath(const QUrl & /* uri */) {} + void setContextItemSource(const QUrl &uri); + void addBaseLine(TestBaseLine *lines); + + virtual TreeItem *parent() const; + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + virtual QString title() const; + virtual TestBaseLine::List baseLines() const; + + virtual int columnCount() const; + + virtual QUrl contextItemSource() const; + void setParent(TreeItem *const parent); + virtual QPatternist::ExternalVariableLoader::Ptr externalVariableLoader() const; + virtual TestResult *testResult() const; + virtual ResultSummary resultSummary() const; + + private: + void executeSchemaTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler); + void executeInstanceTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler); + + QString m_name; + QString m_creator; + QString m_description; + QUrl m_schemaUri; + QUrl m_instanceUri; + QDate m_lastModified; + const Scenario m_scenario; + TreeItem * m_parent; + TestBaseLine::List m_baseLines; + QUrl m_contextItemSource; + TestType m_testType; + QPointer<TestResult> m_result; + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.cpp b/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.cpp new file mode 100644 index 0000000..028d88c --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.cpp @@ -0,0 +1,910 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the autotests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "qacceltreeresourceloader_p.h" +#include "qnetworkaccessdelegator_p.h" + +#include "Global.h" +#include "TestBaseLine.h" +#include "TestGroup.h" + +#include "XSDTestSuiteHandler.h" +#include "XSDTSTestCase.h" + +using namespace QPatternistSDK; + +extern QNetworkAccessManager s_networkManager; + +XSDTestSuiteHandler::XSDTestSuiteHandler(const QUrl &catalogFile) : m_ts(0) + , m_catalogFile(catalogFile) + , m_inSchemaTest(false) + , m_inInstanceTest(false) + , m_inTestGroup(false) + , m_inDescription(false) + , m_schemaBlacklisted(false) + , m_counter(0) +{ + Q_ASSERT(!m_catalogFile.isRelative()); + m_ts = new TestSuite(); + m_topLevelGroup = new TestGroup(m_ts); + m_topLevelGroup->setTitle("XML Schema Test Suite"); + m_ts->appendChild(m_topLevelGroup); + + // exclude these test cases, as they break our current state machine + m_blackList << QLatin1String("addB099") + << QLatin1String("addB118") + << QLatin1String("elemJ003") + << QLatin1String("elemJ011") + << QLatin1String("elemZ004") + << QLatin1String("elemZ020") + << QLatin1String("groupH021v") + << QLatin1String("groupJ009v") + << QLatin1String("name00101m2") + << QLatin1String("schL5") + << QLatin1String("ste110") + << QLatin1String("stZ007") + << QLatin1String("stZ047") + << QLatin1String("stZ055") + << QLatin1String("addB049") + << QLatin1String("addB068") + << QLatin1String("addB078") + << QLatin1String("addB078A") + << QLatin1String("addB078B") + << QLatin1String("addB167") + << QLatin1String("addB191") + << QLatin1String("isDefault060_2") + << QLatin1String("isDefault069") + << QLatin1String("annotB025") + << QLatin1String("base64Binary_enumeration003_1321") + << QLatin1String("anyURI_a001_1336") + << QLatin1String("anyURI_a001_1336") + << QLatin1String("anyURI_a003_1338") + << QLatin1String("anyURI_a004_1339") + << QLatin1String("anyURI_b004_1354") + << QLatin1String("anyURI_b004_1354") + << QLatin1String("anyURI_b006_1356") + << QLatin1String("QName_length001_1357") + << QLatin1String("QName_length003_1359") + << QLatin1String("QName_minLength003_1362") + << QLatin1String("QName_maxLength001_1364") + << QLatin1String("NOTATION_length001_1372") + << QLatin1String("NOTATION_length003_1374") + << QLatin1String("NOTATION_minLength003_1377") + << QLatin1String("NOTATION_maxLength001_1379") + << QLatin1String("hexBinary003_2069") + << QLatin1String("QName009_2092") + << QLatin1String("dtZ107447_a_2245") + << QLatin1String("elemE001") + << QLatin1String("elemE002") + << QLatin1String("elemE003") + << QLatin1String("elemE004") + << QLatin1String("elemE005") + << QLatin1String("elemT026") + << QLatin1String("elemT027") + << QLatin1String("elemT028") + << QLatin1String("elemT029") + << QLatin1String("elemT054") + << QLatin1String("elemT055") + << QLatin1String("elemT056") + << QLatin1String("elemT057") + << QLatin1String("elemZ006") + << QLatin1String("elemZ007") + << QLatin1String("elemZ026") + << QLatin1String("elemZ027_c") + << QLatin1String("elemZ028c") + << QLatin1String("elemZ028d") + << QLatin1String("elemZ028f1") + << QLatin1String("elemZ028f1") + << QLatin1String("elemZ028f2") + << QLatin1String("elemZ028f2") + << QLatin1String("elemZ028f3") + << QLatin1String("elemZ028f3") + << QLatin1String("elemZ031") + << QLatin1String("errF001") + << QLatin1String("idC019") + << QLatin1String("idL100") + << QLatin1String("idZ011") + << QLatin1String("idZ015") + << QLatin1String("mgO013") + << QLatin1String("particlesA012") + << QLatin1String("particlesA013") + << QLatin1String("particlesA014") + << QLatin1String("particlesA015") + << QLatin1String("particlesHa161") + << QLatin1String("particlesHb008") + << QLatin1String("particlesHb011") + << QLatin1String("particlesIe003") + << QLatin1String("particlesIg003") + << QLatin1String("particlesIg004") + << QLatin1String("particlesJb003") + << QLatin1String("particlesJd003") + << QLatin1String("particlesJf003") + << QLatin1String("particlesJk003") + << QLatin1String("particlesOb001") + << QLatin1String("particlesOb002") + << QLatin1String("particlesOb004") + << QLatin1String("particlesOb008") + << QLatin1String("particlesOb009") + << QLatin1String("particlesOb013") + << QLatin1String("particlesOb018") + << QLatin1String("particlesQ005") + << QLatin1String("particlesS002") + << QLatin1String("particlesT002") + << QLatin1String("particlesT009") + << QLatin1String("particlesT014") + << QLatin1String("particlesV001") + << QLatin1String("particlesV002") + << QLatin1String("particlesV020") + << QLatin1String("particlesZ001") + << QLatin1String("particlesZ005") + << QLatin1String("particlesZ007") + << QLatin1String("particlesZ023") + << QLatin1String("particlesZ024") + << QLatin1String("particlesZ026") + << QLatin1String("particlesZ028") + << QLatin1String("particlesZ033_c") + << QLatin1String("particlesZ033_d") + << QLatin1String("particlesZ033_e") + << QLatin1String("particlesZ033_f") + << QLatin1String("particlesZ033_g") + << QLatin1String("particlesZ034_a1") + << QLatin1String("particlesZ034_a2") + << QLatin1String("particlesZ034_a3") + << QLatin1String("particlesZ034_b") + << QLatin1String("particlesZ035_a") + << QLatin1String("particlesZ035_b") + << QLatin1String("particlesZ036_a") + << QLatin1String("particlesZ036_b1") + << QLatin1String("particlesZ036_b2") + << QLatin1String("particlesZ036_c") +/* + << QLatin1String("reC65") + << QLatin1String("reC66") + << QLatin1String("reC67") + << QLatin1String("reC68") + << QLatin1String("reF58") + << QLatin1String("reG50") + << QLatin1String("reJ11") + << QLatin1String("reJ13") + << QLatin1String("reJ19") + << QLatin1String("reJ21") + << QLatin1String("reJ23") + << QLatin1String("reJ25") + << QLatin1String("reJ29") + << QLatin1String("reJ31") + << QLatin1String("reJ33") + << QLatin1String("reJ35") + << QLatin1String("reJ61") + << QLatin1String("reJ69") + << QLatin1String("reJ75") + << QLatin1String("reJ77") + << QLatin1String("reL98") + << QLatin1String("reL99") + << QLatin1String("reM98") + << QLatin1String("reN99") + << QLatin1String("reS21") + << QLatin1String("reS42") + << QLatin1String("reT63") + << QLatin1String("reT84") + << QLatin1String("reDG2") + << QLatin1String("RegexTest_9") + << QLatin1String("RegexTest_11") + << QLatin1String("RegexTest_14") + << QLatin1String("RegexTest_15") + << QLatin1String("RegexTest_16") + << QLatin1String("RegexTest_17") + << QLatin1String("RegexTest_23") + << QLatin1String("RegexTest_24") + << QLatin1String("RegexTest_25") + << QLatin1String("RegexTest_26") + << QLatin1String("RegexTest_27") + << QLatin1String("RegexTest_28") + << QLatin1String("RegexTest_30") + << QLatin1String("RegexTest_30") + << QLatin1String("RegexTest_33") + << QLatin1String("RegexTest_34") + << QLatin1String("RegexTest_34") + << QLatin1String("RegexTest_43") + << QLatin1String("RegexTest_44") + << QLatin1String("RegexTest_45") + << QLatin1String("RegexTest_46") + << QLatin1String("RegexTest_47") + << QLatin1String("RegexTest_48") + << QLatin1String("RegexTest_49") + << QLatin1String("RegexTest_50") + << QLatin1String("RegexTest_51") + << QLatin1String("RegexTest_52") + << QLatin1String("RegexTest_53") + << QLatin1String("RegexTest_54") + << QLatin1String("RegexTest_55") + << QLatin1String("RegexTest_56") + << QLatin1String("RegexTest_57") + << QLatin1String("RegexTest_57") + << QLatin1String("RegexTest_58") + << QLatin1String("RegexTest_58") + << QLatin1String("RegexTest_65") + << QLatin1String("RegexTest_113") + << QLatin1String("RegexTest_116") + << QLatin1String("RegexTest_119") + << QLatin1String("RegexTest_120") + << QLatin1String("RegexTest_121") + << QLatin1String("RegexTest_141") + << QLatin1String("RegexTest_142") + << QLatin1String("RegexTest_143") + << QLatin1String("RegexTest_145") + << QLatin1String("RegexTest_146") + << QLatin1String("RegexTest_147") + << QLatin1String("RegexTest_148") + << QLatin1String("RegexTest_149") + << QLatin1String("RegexTest_150") + << QLatin1String("RegexTest_151") + << QLatin1String("RegexTest_152") + << QLatin1String("RegexTest_154") + << QLatin1String("RegexTest_155") + << QLatin1String("RegexTest_156") + << QLatin1String("RegexTest_157") + << QLatin1String("RegexTest_158") + << QLatin1String("RegexTest_163") + << QLatin1String("RegexTest_164") + << QLatin1String("RegexTest_165") + << QLatin1String("RegexTest_166") + << QLatin1String("RegexTest_167") + << QLatin1String("RegexTest_168") + << QLatin1String("RegexTest_169") + << QLatin1String("RegexTest_170") + << QLatin1String("RegexTest_171") + << QLatin1String("RegexTest_172") + << QLatin1String("RegexTest_173") + << QLatin1String("RegexTest_174") + << QLatin1String("RegexTest_178") + << QLatin1String("RegexTest_194") + << QLatin1String("RegexTest_194") + << QLatin1String("RegexTest_195") + << QLatin1String("RegexTest_195") + << QLatin1String("RegexTest_196") + << QLatin1String("RegexTest_196") + << QLatin1String("RegexTest_197") + << QLatin1String("RegexTest_198") + << QLatin1String("RegexTest_199") + << QLatin1String("RegexTest_200") + << QLatin1String("RegexTest_200") + << QLatin1String("RegexTest_201") + << QLatin1String("RegexTest_201") + << QLatin1String("RegexTest_202") + << QLatin1String("RegexTest_202") + << QLatin1String("RegexTest_203") + << QLatin1String("RegexTest_204") + << QLatin1String("RegexTest_205") + << QLatin1String("RegexTest_206") + << QLatin1String("RegexTest_207") + << QLatin1String("RegexTest_208") + << QLatin1String("RegexTest_209") + << QLatin1String("RegexTest_209") + << QLatin1String("RegexTest_210") + << QLatin1String("RegexTest_210") + << QLatin1String("RegexTest_211") + << QLatin1String("RegexTest_211") + << QLatin1String("RegexTest_212") + << QLatin1String("RegexTest_213") + << QLatin1String("RegexTest_214") + << QLatin1String("RegexTest_215") + << QLatin1String("RegexTest_216") + << QLatin1String("RegexTest_217") + << QLatin1String("RegexTest_218") + << QLatin1String("RegexTest_220") + << QLatin1String("RegexTest_221") + << QLatin1String("RegexTest_222") + << QLatin1String("RegexTest_226") + << QLatin1String("RegexTest_230") + << QLatin1String("RegexTest_232") + << QLatin1String("RegexTest_233") + << QLatin1String("RegexTest_294") + << QLatin1String("RegexTest_294") + << QLatin1String("RegexTest_295") + << QLatin1String("RegexTest_295") + << QLatin1String("RegexTest_299") + << QLatin1String("RegexTest_300") + << QLatin1String("RegexTest_301") + << QLatin1String("RegexTest_302") + << QLatin1String("RegexTest_303") + << QLatin1String("RegexTest_304") + << QLatin1String("RegexTest_305") + << QLatin1String("RegexTest_306") + << QLatin1String("RegexTest_307") + << QLatin1String("RegexTest_308") + << QLatin1String("RegexTest_309") + << QLatin1String("RegexTest_310") + << QLatin1String("RegexTest_311") + << QLatin1String("RegexTest_312") + << QLatin1String("RegexTest_313") + << QLatin1String("RegexTest_314") + << QLatin1String("RegexTest_315") + << QLatin1String("RegexTest_315") + << QLatin1String("RegexTest_316") + << QLatin1String("RegexTest_316") + << QLatin1String("RegexTest_317") + << QLatin1String("RegexTest_317") + << QLatin1String("RegexTest_440") + << QLatin1String("RegexTest_441") + << QLatin1String("RegexTest_442") + << QLatin1String("RegexTest_443") + << QLatin1String("RegexTest_448") + << QLatin1String("RegexTest_449") + << QLatin1String("RegexTest_450") + << QLatin1String("RegexTest_451") + << QLatin1String("RegexTest_458") + << QLatin1String("RegexTest_464") + << QLatin1String("RegexTest_464") + << QLatin1String("RegexTest_465") + << QLatin1String("RegexTest_469") + << QLatin1String("RegexTest_470") + << QLatin1String("RegexTest_471") + << QLatin1String("RegexTest_472") + << QLatin1String("RegexTest_473") + << QLatin1String("RegexTest_477") + << QLatin1String("RegexTest_478") + << QLatin1String("RegexTest_478") + << QLatin1String("RegexTest_479") + << QLatin1String("RegexTest_480") + << QLatin1String("RegexTest_481") + << QLatin1String("RegexTest_482") + << QLatin1String("RegexTest_482") + << QLatin1String("RegexTest_483") + << QLatin1String("RegexTest_483") + << QLatin1String("RegexTest_484") + << QLatin1String("RegexTest_487") + << QLatin1String("RegexTest_516") + << QLatin1String("RegexTest_516") + << QLatin1String("RegexTest_517") + << QLatin1String("RegexTest_517") + << QLatin1String("RegexTest_518") + << QLatin1String("RegexTest_518") + << QLatin1String("RegexTest_519") + << QLatin1String("RegexTest_519") + << QLatin1String("RegexTest_521") + << QLatin1String("RegexTest_523") + << QLatin1String("RegexTest_524") + << QLatin1String("RegexTest_524") + << QLatin1String("RegexTest_586") + << QLatin1String("RegexTest_587") + << QLatin1String("RegexTest_592") + << QLatin1String("RegexTest_593") + << QLatin1String("RegexTest_594") + << QLatin1String("RegexTest_595") + << QLatin1String("RegexTest_596") + << QLatin1String("RegexTest_597") + << QLatin1String("RegexTest_598") + << QLatin1String("RegexTest_599") + << QLatin1String("RegexTest_600") + << QLatin1String("RegexTest_601") + << QLatin1String("RegexTest_602") + << QLatin1String("RegexTest_603") + << QLatin1String("RegexTest_604") + << QLatin1String("RegexTest_605") + << QLatin1String("RegexTest_648") + << QLatin1String("RegexTest_655") + << QLatin1String("RegexTest_688") + << QLatin1String("RegexTest_696") + << QLatin1String("RegexTest_697") + << QLatin1String("RegexTest_698") + << QLatin1String("RegexTest_700") + << QLatin1String("RegexTest_701") + << QLatin1String("RegexTest_702") + << QLatin1String("RegexTest_703") + << QLatin1String("RegexTest_704") + << QLatin1String("RegexTest_705") + << QLatin1String("RegexTest_706") + << QLatin1String("RegexTest_707") + << QLatin1String("RegexTest_717") + << QLatin1String("RegexTest_718") + << QLatin1String("RegexTest_719") + << QLatin1String("RegexTest_724") + << QLatin1String("RegexTest_725") + << QLatin1String("RegexTest_726") + << QLatin1String("RegexTest_727") + << QLatin1String("RegexTest_728") + << QLatin1String("RegexTest_729") + << QLatin1String("RegexTest_730") + << QLatin1String("RegexTest_731") + << QLatin1String("RegexTest_732") + << QLatin1String("RegexTest_733") + << QLatin1String("RegexTest_743") + << QLatin1String("RegexTest_755") + << QLatin1String("RegexTest_756") + << QLatin1String("RegexTest_761") + << QLatin1String("RegexTest_762") + << QLatin1String("RegexTest_781") + << QLatin1String("RegexTest_782") + << QLatin1String("RegexTest_783") + << QLatin1String("RegexTest_790") + << QLatin1String("RegexTest_791") + << QLatin1String("RegexTest_824") + << QLatin1String("RegexTest_826") + << QLatin1String("RegexTest_827") + << QLatin1String("RegexTest_836") + << QLatin1String("RegexTest_837") + << QLatin1String("RegexTest_841") + << QLatin1String("RegexTest_842") + << QLatin1String("RegexTest_843") + << QLatin1String("RegexTest_844") + << QLatin1String("RegexTest_845") + << QLatin1String("RegexTest_846") + << QLatin1String("RegexTest_847") + << QLatin1String("RegexTest_848") + << QLatin1String("RegexTest_851") + << QLatin1String("RegexTest_852") + << QLatin1String("RegexTest_853") + << QLatin1String("RegexTest_854") + << QLatin1String("RegexTest_855") + << QLatin1String("RegexTest_856") + << QLatin1String("RegexTest_857") + << QLatin1String("RegexTest_861") + << QLatin1String("RegexTest_862") + << QLatin1String("RegexTest_863") + << QLatin1String("RegexTest_864") + << QLatin1String("RegexTest_865") + << QLatin1String("RegexTest_866") + << QLatin1String("RegexTest_870") + << QLatin1String("RegexTest_879") + << QLatin1String("RegexTest_880") + << QLatin1String("RegexTest_888") + << QLatin1String("RegexTest_889") + << QLatin1String("RegexTest_890") + << QLatin1String("RegexTest_891") + << QLatin1String("RegexTest_892") + << QLatin1String("RegexTest_893") + << QLatin1String("RegexTest_894") + << QLatin1String("RegexTest_895") + << QLatin1String("RegexTest_896") + << QLatin1String("RegexTest_897") + << QLatin1String("RegexTest_898") + << QLatin1String("RegexTest_899") + << QLatin1String("RegexTest_900") + << QLatin1String("RegexTest_901") + << QLatin1String("RegexTest_902") + << QLatin1String("RegexTest_903") + << QLatin1String("RegexTest_904") + << QLatin1String("RegexTest_905") + << QLatin1String("RegexTest_906") + << QLatin1String("RegexTest_907") + << QLatin1String("RegexTest_908") + << QLatin1String("RegexTest_909") + << QLatin1String("RegexTest_910") + << QLatin1String("RegexTest_911") + << QLatin1String("RegexTest_912") + << QLatin1String("RegexTest_913") + << QLatin1String("RegexTest_914") + << QLatin1String("RegexTest_915") + << QLatin1String("RegexTest_916") + << QLatin1String("RegexTest_917") + << QLatin1String("RegexTest_918") + << QLatin1String("RegexTest_919") + << QLatin1String("RegexTest_920") + << QLatin1String("RegexTest_921") + << QLatin1String("RegexTest_922") + << QLatin1String("RegexTest_923") + << QLatin1String("RegexTest_924") + << QLatin1String("RegexTest_925") + << QLatin1String("RegexTest_926") + << QLatin1String("RegexTest_928") + << QLatin1String("RegexTest_929") + << QLatin1String("RegexTest_930") + << QLatin1String("RegexTest_936") + << QLatin1String("RegexTest_937") + << QLatin1String("RegexTest_938") + << QLatin1String("RegexTest_939") + << QLatin1String("RegexTest_940") + << QLatin1String("RegexTest_941") + << QLatin1String("RegexTest_942") + << QLatin1String("RegexTest_943") + << QLatin1String("RegexTest_944") + << QLatin1String("RegexTest_945") + << QLatin1String("RegexTest_946") + << QLatin1String("RegexTest_949") + << QLatin1String("RegexTest_950") + << QLatin1String("RegexTest_951") + << QLatin1String("RegexTest_952") + << QLatin1String("RegexTest_953") + << QLatin1String("RegexTest_954") + << QLatin1String("RegexTest_955") + << QLatin1String("RegexTest_956") + << QLatin1String("RegexTest_957") + << QLatin1String("RegexTest_958") + << QLatin1String("RegexTest_959") + << QLatin1String("RegexTest_960") + << QLatin1String("RegexTest_961") + << QLatin1String("RegexTest_962") + << QLatin1String("RegexTest_963") + << QLatin1String("RegexTest_964") + << QLatin1String("RegexTest_976") + << QLatin1String("RegexTest_977") + << QLatin1String("RegexTest_988") + << QLatin1String("RegexTest_989") + << QLatin1String("RegexTest_990") + << QLatin1String("RegexTest_991") + << QLatin1String("RegexTest_994") + << QLatin1String("RegexTest_995") + << QLatin1String("RegexTest_996") + << QLatin1String("RegexTest_997") + << QLatin1String("RegexTest_1000") + << QLatin1String("RegexTest_1001") + << QLatin1String("RegexTest_1002") + << QLatin1String("RegexTest_1003") + << QLatin1String("RegexTest_1004") + << QLatin1String("RegexTest_1007") + << QLatin1String("RegexTest_1008") + << QLatin1String("RegexTest_1009") + << QLatin1String("RegexTest_1010") + << QLatin1String("RegexTest_1011") + << QLatin1String("RegexTest_1012") + << QLatin1String("RegexTest_1013") + << QLatin1String("RegexTest_1014") + << QLatin1String("RegexTest_1015") + << QLatin1String("RegexTest_1016") + << QLatin1String("RegexTest_1017") + << QLatin1String("RegexTest_1018") + << QLatin1String("RegexTest_1019") + << QLatin1String("RegexTest_1070") + << QLatin1String("RegexTest_1071") + << QLatin1String("RegexTest_1076") + << QLatin1String("RegexTest_1077") + << QLatin1String("RegexTest_1078") + << QLatin1String("RegexTest_1079") + << QLatin1String("RegexTest_1080") + << QLatin1String("RegexTest_1081") + << QLatin1String("RegexTest_1082") + << QLatin1String("RegexTest_1083") + << QLatin1String("RegexTest_1084") + << QLatin1String("RegexTest_1085") + << QLatin1String("RegexTest_1086") + << QLatin1String("RegexTest_1087") + << QLatin1String("RegexTest_1088") + << QLatin1String("RegexTest_1089") + << QLatin1String("RegexTest_1132") + << QLatin1String("RegexTest_1139") + << QLatin1String("RegexTest_1172") + << QLatin1String("RegexTest_1180") + << QLatin1String("RegexTest_1181") + << QLatin1String("RegexTest_1182") + << QLatin1String("RegexTest_1184") + << QLatin1String("RegexTest_1185") + << QLatin1String("RegexTest_1186") + << QLatin1String("RegexTest_1187") + << QLatin1String("RegexTest_1188") + << QLatin1String("RegexTest_1189") + << QLatin1String("RegexTest_1190") + << QLatin1String("RegexTest_1191") + << QLatin1String("RegexTest_1201") + << QLatin1String("RegexTest_1202") + << QLatin1String("RegexTest_1203") + << QLatin1String("RegexTest_1208") + << QLatin1String("RegexTest_1209") + << QLatin1String("RegexTest_1210") + << QLatin1String("RegexTest_1211") + << QLatin1String("RegexTest_1212") + << QLatin1String("RegexTest_1213") + << QLatin1String("RegexTest_1214") + << QLatin1String("RegexTest_1215") + << QLatin1String("RegexTest_1216") + << QLatin1String("RegexTest_1217") + << QLatin1String("RegexTest_1227") + << QLatin1String("RegexTest_1239") + << QLatin1String("RegexTest_1240") + << QLatin1String("RegexTest_1245") + << QLatin1String("RegexTest_1246") + << QLatin1String("RegexTest_1265") + << QLatin1String("RegexTest_1266") + << QLatin1String("RegexTest_1267") + << QLatin1String("RegexTest_1274") + << QLatin1String("RegexTest_1275") + << QLatin1String("RegexTest_1308") + << QLatin1String("RegexTest_1310") + << QLatin1String("RegexTest_1311") + << QLatin1String("RegexTest_1320") + << QLatin1String("RegexTest_1321") + << QLatin1String("RegexTest_1322") + << QLatin1String("RegexTest_1323") + << QLatin1String("RegexTest_1324") + << QLatin1String("RegexTest_1325") + << QLatin1String("RegexTest_1326") + << QLatin1String("RegexTest_1327") + << QLatin1String("RegexTest_1328") + << QLatin1String("RegexTest_1329") + << QLatin1String("RegexTest_1330") + << QLatin1String("RegexTest_1331") + << QLatin1String("RegexTest_1332") + << QLatin1String("RegexTest_1335") + << QLatin1String("RegexTest_1336") + << QLatin1String("RegexTest_1337") + << QLatin1String("RegexTest_1338") + << QLatin1String("RegexTest_1339") + << QLatin1String("RegexTest_1340") + << QLatin1String("RegexTest_1341") + << QLatin1String("RegexTest_1345") + << QLatin1String("RegexTest_1346") + << QLatin1String("RegexTest_1347") + << QLatin1String("RegexTest_1348") + << QLatin1String("RegexTest_1349") + << QLatin1String("RegexTest_1350") + << QLatin1String("RegexTest_1354") + << QLatin1String("RegexTest_1363") + << QLatin1String("RegexTest_1364") + << QLatin1String("RegexTest_1365") + << QLatin1String("RegexTest_1372") + << QLatin1String("RegexTest_1373") + << QLatin1String("RegexTest_1374") + << QLatin1String("RegexTest_1375") + << QLatin1String("RegexTest_1376") + << QLatin1String("RegexTest_1377") + << QLatin1String("RegexTest_1378") + << QLatin1String("RegexTest_1379") + << QLatin1String("RegexTest_1380") + << QLatin1String("RegexTest_1381") + << QLatin1String("RegexTest_1382") + << QLatin1String("RegexTest_1383") + << QLatin1String("RegexTest_1384") + << QLatin1String("RegexTest_1385") + << QLatin1String("RegexTest_1386") + << QLatin1String("RegexTest_1387") + << QLatin1String("RegexTest_1388") + << QLatin1String("RegexTest_1389") + << QLatin1String("RegexTest_1390") + << QLatin1String("RegexTest_1391") + << QLatin1String("RegexTest_1392") + << QLatin1String("RegexTest_1393") + << QLatin1String("RegexTest_1394") + << QLatin1String("RegexTest_1395") + << QLatin1String("RegexTest_1396") + << QLatin1String("RegexTest_1397") + << QLatin1String("RegexTest_1398") + << QLatin1String("RegexTest_1399") + << QLatin1String("RegexTest_1400") + << QLatin1String("RegexTest_1401") + << QLatin1String("RegexTest_1402") + << QLatin1String("RegexTest_1403") + << QLatin1String("RegexTest_1404") + << QLatin1String("RegexTest_1405") + << QLatin1String("RegexTest_1406") + << QLatin1String("RegexTest_1407") + << QLatin1String("RegexTest_1408") + << QLatin1String("RegexTest_1409") + << QLatin1String("RegexTest_1410") + << QLatin1String("RegexTest_1412") + << QLatin1String("RegexTest_1413") + << QLatin1String("RegexTest_1414") + << QLatin1String("RegexTest_1420") + << QLatin1String("RegexTest_1421") + << QLatin1String("RegexTest_1422") + << QLatin1String("RegexTest_1423") + << QLatin1String("RegexTest_1424") + << QLatin1String("RegexTest_1425") + << QLatin1String("RegexTest_1426") + << QLatin1String("RegexTest_1427") + << QLatin1String("RegexTest_1428") + << QLatin1String("RegexTest_1429") + << QLatin1String("RegexTest_1430") + << QLatin1String("RegexTest_1433") + << QLatin1String("RegexTest_1434") + << QLatin1String("RegexTest_1435") + << QLatin1String("RegexTest_1436") + << QLatin1String("RegexTest_1437") + << QLatin1String("RegexTest_1438") + << QLatin1String("RegexTest_1439") + << QLatin1String("RegexTest_1440") + << QLatin1String("RegexTest_1441") + << QLatin1String("RegexTest_1442") + << QLatin1String("RegexTest_1443") + << QLatin1String("RegexTest_1444") + << QLatin1String("RegexTest_1445") + << QLatin1String("RegexTest_1446") + << QLatin1String("RegexTest_1447") + << QLatin1String("RegexTest_1448") + << QLatin1String("RegexTest_1451") + << QLatin1String("RegexTest_1452") + << QLatin1String("RegexTest_1453") + << QLatin1String("RegexTest_1454") + << QLatin1String("RegexTest_1455") + << QLatin1String("RegexTest_1456") + << QLatin1String("RegexTest_1472") + << QLatin1String("RegexTest_1473") + << QLatin1String("RegexTest_1474") + << QLatin1String("RegexTest_1475") + << QLatin1String("RegexTest_1478") + << QLatin1String("RegexTest_1479") + << QLatin1String("RegexTest_1480") + << QLatin1String("RegexTest_1481") + << QLatin1String("RegexTest_1484") + << QLatin1String("RegexTest_1485") + << QLatin1String("RegexTest_1486") + << QLatin1String("RegexTest_1487") + << QLatin1String("RegexTest_1488") + << QLatin1String("RegexTest_1491") + << QLatin1String("RegexTest_1492") + << QLatin1String("RegexTest_1493") + << QLatin1String("RegexTest_1494") + << QLatin1String("RegexTest_1495") + << QLatin1String("RegexTest_1496") + << QLatin1String("RegexTest_1497") + << QLatin1String("RegexTest_1498") + << QLatin1String("RegexTest_1499") + << QLatin1String("RegexTest_1500") + << QLatin1String("RegexTest_1501") + << QLatin1String("RegexTest_1502") + << QLatin1String("RegexTest_1503") + << QLatin1String("RegexTest_1543") + << QLatin1String("RegexTest_1544") + << QLatin1String("reZ001") +*/ + << QLatin1String("schA2") + << QLatin1String("schA5") + << QLatin1String("schA7") + << QLatin1String("schD8") + << QLatin1String("schG3") + << QLatin1String("schG6") + << QLatin1String("schG9") + << QLatin1String("schG11") + << QLatin1String("schG12") + << QLatin1String("schU1") + << QLatin1String("schU3") + << QLatin1String("schU4") + << QLatin1String("schU5") + << QLatin1String("schZ004") + << QLatin1String("schZ005") + << QLatin1String("schZ012_a") + << QLatin1String("stZ041") + << QLatin1String("wildZ010"); +} + +bool XSDTestSuiteHandler::startElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/, + const QXmlAttributes &atts) +{ + if(namespaceURI != QString::fromLatin1("http://www.w3.org/XML/2004/xml-schema-test-suite/")) + return true; + + if (localName == QLatin1String("testSet")) { + m_currentTestSet = new TestGroup(m_topLevelGroup); + Q_ASSERT(m_currentTestSet); + m_currentTestSet->setTitle(atts.value("name")); + m_topLevelGroup->appendChild(m_currentTestSet); + } else if (localName == QLatin1String("testGroup")) { + m_currentTestGroup = new TestGroup(m_currentTestSet); + Q_ASSERT(m_currentTestGroup); + m_currentTestGroup->setTitle(atts.value("name")); + m_currentTestSet->appendChild(m_currentTestGroup); + m_inTestGroup = true; + } else if (localName == QLatin1String("schemaTest")) { + if (m_blackList.contains(atts.value("name"))) { + m_currentTestCase = 0; + m_schemaBlacklisted = true; + return true; + } + m_schemaBlacklisted = false; + + m_currentTestCase = new XSDTSTestCase(TestCase::Standard, m_currentTestGroup, XSDTSTestCase::SchemaTest); + Q_ASSERT(m_currentTestCase); + m_counter++; + m_currentTestCase->setName(QString::number(m_counter) + atts.value("name")); + m_currentTestGroup->appendChild(m_currentTestCase); + m_currentTestCase->setParent(m_currentTestGroup); + + m_inSchemaTest = true; + } else if (localName == QLatin1String("instanceTest")) { + if (m_schemaBlacklisted) { + m_currentTestCase = 0; + return true; + } + + m_currentTestCase = new XSDTSTestCase(TestCase::Standard, m_currentTestGroup, XSDTSTestCase::InstanceTest); + Q_ASSERT(m_currentTestCase); + m_counter++; + m_currentTestCase->setName(QString::number(m_counter) + atts.value("name")); + m_currentTestGroup->appendChild(m_currentTestCase); + + m_inInstanceTest = true; + } else if (localName == QLatin1String("schemaDocument") || localName == QLatin1String("instanceDocument")) { + if (m_inSchemaTest) { + m_currentTestCase->setSchemaUri(QUrl(atts.value("xlink:href"))); + if (m_currentSchemaLink.isEmpty()) // we only use the first schema document for validation + m_currentSchemaLink = atts.value("xlink:href"); + } + if (m_inInstanceTest) { + m_currentTestCase->setInstanceUri(QUrl(atts.value("xlink:href"))); + m_currentTestCase->setSchemaUri(QUrl(m_currentSchemaLink)); + } + } else if (localName == QLatin1String("expected") && (m_inSchemaTest || m_inInstanceTest)) { + TestBaseLine *baseLine = new TestBaseLine(TestBaseLine::SchemaIsValid); + if (atts.value("validity") == QLatin1String("valid")) { + baseLine->setDetails(QLatin1String("true")); + m_currentTestCase->setName(m_currentTestCase->name() + QLatin1String(" tokoe:valid")); + } else { + baseLine->setDetails(QLatin1String("false")); + m_currentTestCase->setName(m_currentTestCase->name() + QLatin1String(" tokoe:invalid")); + } + + m_currentTestCase->addBaseLine(baseLine); + } else if (localName == QLatin1String("documentation") && m_inTestGroup) { + m_inDescription = true; + } + + return true; +} + +bool XSDTestSuiteHandler::endElement(const QString &/*namespaceURI*/, + const QString &localName, + const QString &/*qName*/) +{ + if (localName == QLatin1String("testGroup")) { + m_inTestGroup = false; + m_currentTestGroup->setDescription(m_documentation); + m_documentation.clear(); + m_currentSchemaLink.clear(); + + if (m_currentTestGroup->childCount() == 0) + m_currentTestSet->removeLast(); + } else if (localName == QLatin1String("schemaTest")) + m_inSchemaTest = false; + else if (localName == QLatin1String("instanceTest")) + m_inInstanceTest = false; + else if (localName == QLatin1String("documentation")) + m_inDescription = false; + + return true; +} + +bool XSDTestSuiteHandler::characters(const QString &ch) +{ + if (m_inDescription) + m_documentation += ch; + + return true; +} + +TestSuite *XSDTestSuiteHandler::testSuite() const +{ + return m_ts; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.h b/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.h new file mode 100644 index 0000000..21a54eb --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSDTestSuiteHandler.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the autotests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XSDTestSuiteHandler_H +#define PatternistSDK_XSDTestSuiteHandler_H + +#include <QUrl> +#include <QXmlDefaultHandler> + +#include "ExternalSourceLoader.h" +#include "TestSuite.h" +#include "XQTSTestCase.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class TestBaseLine; + class TestGroup; + class XSDTSTestCase; + + /** + * @short Creates a TestSuite from the XSD Test Suite. + * + * The created TestSuite can be retrieved via testSuite(). + * + * @note XSDTestSuiteHandler assumes the XML is valid by having been validated + * against the W3C XML Schema. It has no safety checks for that the XML format + * is correct but is hard coded for it. Thus, the behavior is undefined if + * the XML is invalid. + * + * @ingroup PatternistSDK + * @author Tobias Koenig <tobias.koenig@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT XSDTestSuiteHandler : public QXmlDefaultHandler + { + public: + /** + * @param catalogFile the URI for the catalog file being parsed. This + * URI is used for creating absolute URIs for files mentioned in + * the catalog with relative URIs. + * @param useExclusionList whether excludeTestGroups.txt should be used to ignore + * test groups when loading + */ + XSDTestSuiteHandler(const QUrl &catalogFile); + virtual bool characters(const QString &ch); + + virtual bool endElement(const QString &namespaceURI, + const QString &localName, + const QString &qName); + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + + virtual TestSuite *testSuite() const; + + private: + TestSuite* m_ts; + const QUrl m_catalogFile; + + TestGroup* m_topLevelGroup; + TestGroup* m_currentTestSet; + TestGroup* m_currentTestGroup; + XSDTSTestCase* m_currentTestCase; + bool m_inSchemaTest; + bool m_inInstanceTest; + bool m_inTestGroup; + bool m_inDescription; + bool m_schemaBlacklisted; + QString m_documentation; + QString m_currentSchemaLink; + int m_counter; + QSet<QString> m_blackList; + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.cpp b/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.cpp new file mode 100644 index 0000000..b6b38d0 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "qacceltreeresourceloader_p.h" +#include "qnetworkaccessdelegator_p.h" + +#include "Global.h" +#include "TestBaseLine.h" +#include "TestGroup.h" + +#include "XSLTTestSuiteHandler.h" + +using namespace QPatternistSDK; + +extern QNetworkAccessManager s_networkManager; + +XSLTTestSuiteHandler::XSLTTestSuiteHandler(const QUrl &catalogFile) : m_ts(0) + , m_tc(0) + , m_baseLine(0) + , m_catalogFile(catalogFile) + , m_removeTestcase(false) +{ + const QPatternist::NetworkAccessDelegator::Ptr networkDelegator(new QPatternist::NetworkAccessDelegator(&s_networkManager, &s_networkManager)); + + m_resourceLoader = QPatternist::ResourceLoader::Ptr(new QPatternist::AccelTreeResourceLoader(Global::namePool(), + networkDelegator)); + Q_ASSERT(!m_catalogFile.isRelative()); +} + +bool XSLTTestSuiteHandler::startElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/, + const QXmlAttributes &atts) + { + if(namespaceURI != Global::xsltsCatalogNS) + return true; + + /* The elements are handled roughly in the order of highest occurrence in the catalog file. */ + if(localName == QLatin1String("testcase")) + { + /* We pass m_ts temporarily, and change it later. */ + m_tc = new XQTSTestCase(TestCase::Standard, 0, QXmlQuery::XSLT20); + + m_currentQueryPath = m_queryOffset.resolved(QUrl(atts.value(QLatin1String("FilePath")))); + m_currentBaselinePath = m_baselineOffset.resolved(QUrl(atts.value(QLatin1String("FilePath")))); + } + else if(localName == QLatin1String("stylesheet")) + m_tc->setQueryPath(m_currentQueryPath.resolved(atts.value(QLatin1String("file")))); + else if(localName == QLatin1String("error")) + { + m_baseLine = new TestBaseLine(TestBaseLine::ExpectedError); + m_baseLine->setDetails(atts.value(QLatin1String("error-id"))); + m_tc->addBaseLine(m_baseLine); + } + else if(localName == QLatin1String("testcases")) + { + m_ts = new TestSuite(); + m_ts->setVersion(atts.value(QLatin1String("testSuiteVersion"))); + + m_queryOffset = m_catalogFile.resolved(atts.value(QLatin1String("InputOffsetPath"))); + m_baselineOffset = m_catalogFile.resolved(atts.value(QLatin1String("ResultOffsetPath"))); + m_sourceOffset = m_catalogFile.resolved(atts.value(QLatin1String("InputOffsetPath"))); + } + else if(localName == QLatin1String("source-document")) + { + if(atts.value(QLatin1String("role")) == QLatin1String("principal")) + m_tc->setContextItemSource(m_sourceOffset.resolved(QUrl(atts.value(QLatin1String("file"))))); + } + else if(localName == QLatin1String("result-document")) + { + m_baseLine = new TestBaseLine(TestBaseLine::identifierFromString(atts.value(QLatin1String("type")))); + m_baseLine->setDetails(m_currentBaselinePath.resolved(atts.value(QLatin1String("file"))).toString()); + m_tc->addBaseLine(m_baseLine); + } + else if(localName == QLatin1String("discretionary-feature")) + { + const QString feature(atts.value(QLatin1String("name"))); + + m_removeTestcase = feature == QLatin1String("schema_aware") || + feature == QLatin1String("namespace_axis") || + feature == QLatin1String("disabling_output_escaping") || + feature == QLatin1String("XML_1.1"); + } + else if(localName == QLatin1String("discretionary-choice")) + { + m_baseLine = new TestBaseLine(TestBaseLine::ExpectedError); + m_baseLine->setDetails(atts.value(QLatin1String("name"))); + m_tc->addBaseLine(m_baseLine); + const QString feature(atts.value(QLatin1String("name"))); + + m_removeTestcase = feature == QLatin1String("schema_aware") || + feature == QLatin1String("namespace_axis") || + feature == QLatin1String("disabling_output_escaping") || + feature == QLatin1String("XML_1.1"); + } + else if(localName == QLatin1String("entry-named-template")) + { + const QString name(atts.value(QLatin1String("qname"))); + + if(!name.contains(QLatin1Char(':'))) + { + // TODO do namespace processing + const QXmlName complete(Global::namePool()->allocateQName(QString(), name)); + + m_tc->setInitialTemplateName(complete); + } + } + + return true; +} + +TestGroup *XSLTTestSuiteHandler::containerFor(const QString &name) +{ + TestGroup *& c = m_containers[name]; + + if(!c) + { + c = new TestGroup(m_ts); + c->setTitle(name); + Q_ASSERT(c); + m_ts->appendChild(c); + } + + return c; +} + +bool XSLTTestSuiteHandler::endElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/) +{ + if(namespaceURI != Global::xsltsCatalogNS) + return true; + + /* The elements are handled roughly in the order of highest occurrence in the catalog file. */ + if(localName == QLatin1String("description")) + { + if(m_tc) + { + /* We're inside a <testcase>, so the <description> belongs + * to the testcase. */ + m_tc->setDescription(m_ch.simplified()); + } + } + else if(localName == QLatin1String("testcase")) + { + Q_ASSERT(m_tc->baseLines().count() >= 1); + Q_ASSERT(m_resourceLoader); + // TODO can this be removed? + m_tc->setExternalVariableLoader(QPatternist::ExternalVariableLoader::Ptr + (new ExternalSourceLoader(m_tcSourceInputs, + m_resourceLoader))); + m_tcSourceInputs.clear(); + + if(!m_removeTestcase) + { + /* + TestContainer *const container = containerFor(m_currentCategory); + delete m_tc; + container->removeLast(); + */ + TestContainer *const container = containerFor(m_currentCategory); + m_tc->setParent(container); + Q_ASSERT(m_tc); + container->appendChild(m_tc); + } + + m_tc = 0; + m_removeTestcase = false; + } + else if(localName == QLatin1String("name")) + m_tc->setName(m_ch); + else if(localName == QLatin1String("creator")) + m_tc->setCreator(m_ch); + else if(localName == QLatin1String("contextItem")) + m_contextItemSource = m_ch; + else if(localName == QLatin1String("category")) + m_currentCategory = m_ch; + + return true; +} + +bool XSLTTestSuiteHandler::characters(const QString &ch) +{ + m_ch = ch; + return true; +} + +TestSuite *XSLTTestSuiteHandler::testSuite() const +{ + return m_ts; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.h b/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.h new file mode 100644 index 0000000..d5d82a2 --- /dev/null +++ b/tests/auto/xmlpatternssdk/XSLTTestSuiteHandler.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XSLTTestSuiteHandler_H +#define PatternistSDK_XSLTTestSuiteHandler_H + +#include <QStack> +#include <QUrl> +#include <QXmlDefaultHandler> + +#include "ExternalSourceLoader.h" +#include "TestSuite.h" +#include "XQTSTestCase.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternistSDK +{ + class TestBaseLine; + class TestGroup; + + /** + * @short Creates a TestSuite from the XQuery Test Suite catalog. + * + * The created TestSuite can be retrieved via testSuite(). + * + * @note XSLTTestSuiteHandler assumes the XML is valid by having been validated + * against the W3C XML Schema. It has no safety checks for that the XML format + * is correct but is hard coded for it. Thus, the behavior is undefined if + * the XML is invalid. + * + * @see http://www.w3.org/XML/Group/xslt20-test/TestSuiteStagingArea/catalog.html + * @see http://www.w3.org/XML/Group/xslt20-test/Documentation/XSLT2Test.htm + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_PATTERNISTSDK_EXPORT XSLTTestSuiteHandler : public QXmlDefaultHandler + { + public: + /** + * @param catalogFile the URI for the catalog file being parsed. This + * URI is used for creating absolute URIs for files mentioned in + * the catalog with relative URIs. + * @param useExclusionList whether excludeTestGroups.txt should be used to ignore + * test groups when loading + */ + XSLTTestSuiteHandler(const QUrl &catalogFile); + virtual bool characters(const QString &ch); + + virtual bool endElement(const QString &namespaceURI, + const QString &localName, + const QString &qName); + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + + virtual TestSuite *testSuite() const; + + private: + TestGroup *containerFor(const QString &name); + + QHash<QString, TestGroup *> m_containers; + + TestSuite * m_ts; + XQTSTestCase * m_tc; + TestBaseLine * m_baseLine; + QString m_ch; + const QUrl m_catalogFile; + + /** + * The base URI for where the XQuery query files are found. + * It is absolute, resolved against catalogFile. + */ + QUrl m_queryOffset; + + QUrl m_baselineOffset; + QUrl m_sourceOffset; + QUrl m_currentQueryPath; + QUrl m_currentBaselinePath; + + /** + * In the XQTSCatalog.xml, each source file in each test is referred to + * by a key, which can be fully looked up in the @c sources element. This QHash + * maps the keys to absolute URIs pointing to the source files. + */ + ExternalSourceLoader::SourceMap m_sourceMap; + + ExternalSourceLoader::VariableMap m_tcSourceInputs; + + QPatternist::ResourceLoader::Ptr m_resourceLoader; + + /** + * The current value of <tt>input-file/\@variable</tt>. + */ + QString m_currentInputVariable; + + /** + * The names of the test groups. + */ + QStack<QString> m_testGroupName; + + /** + * Holds the content of the current <tt>input-URI</tt> element. + */ + QString m_inputURI; + QString m_contextItemSource; + QString m_currentCategory; + bool m_removeTestcase; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/docs/XMLIndenterExample.cpp b/tests/auto/xmlpatternssdk/docs/XMLIndenterExample.cpp new file mode 100644 index 0000000..9df47c3 --- /dev/null +++ b/tests/auto/xmlpatternssdk/docs/XMLIndenterExample.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +QByteArray result; +QBuffer returnBuffer(&result); +XMLWriter writer(&returnBuffer); + +writer.startDocument(); + +writer.startDTD(QLatin1String("html"), QLatin1String("-//W3C//DTD XHTML 1.0 Strict//EN"), + QLatin1String("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")); +writer.endDTD(); + +writer.startPrefixMapping(QString(), QLatin1String("http://www.w3.org/1999/xhtml")); + +writer.startElement(QLatin1String("html"), QXmlAttributes()); +writer.startElement(QLatin1String("body"), QXmlAttributes()); +writer.startElement(QLatin1String("p"), QXmlAttributes()); + +writer.characters(QLatin1String("Hello World!")); + +writer.endElement(QLatin1String("p")); +writer.endElement(QLatin1String("body")); +writer.endElement(QLatin1String("html")); + +writer.endDocument(); diff --git a/tests/auto/xmlpatternssdk/docs/XMLIndenterExampleResult.xml b/tests/auto/xmlpatternssdk/docs/XMLIndenterExampleResult.xml new file mode 100644 index 0000000..c5e7312 --- /dev/null +++ b/tests/auto/xmlpatternssdk/docs/XMLIndenterExampleResult.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"><body><p>Hello World!</p></body></html> diff --git a/tests/auto/xmlpatternssdk/docs/XMLWriterExample.cpp b/tests/auto/xmlpatternssdk/docs/XMLWriterExample.cpp new file mode 100644 index 0000000..9df47c3 --- /dev/null +++ b/tests/auto/xmlpatternssdk/docs/XMLWriterExample.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +QByteArray result; +QBuffer returnBuffer(&result); +XMLWriter writer(&returnBuffer); + +writer.startDocument(); + +writer.startDTD(QLatin1String("html"), QLatin1String("-//W3C//DTD XHTML 1.0 Strict//EN"), + QLatin1String("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")); +writer.endDTD(); + +writer.startPrefixMapping(QString(), QLatin1String("http://www.w3.org/1999/xhtml")); + +writer.startElement(QLatin1String("html"), QXmlAttributes()); +writer.startElement(QLatin1String("body"), QXmlAttributes()); +writer.startElement(QLatin1String("p"), QXmlAttributes()); + +writer.characters(QLatin1String("Hello World!")); + +writer.endElement(QLatin1String("p")); +writer.endElement(QLatin1String("body")); +writer.endElement(QLatin1String("html")); + +writer.endDocument(); diff --git a/tests/auto/xmlpatternssdk/docs/XMLWriterExampleResult.xml b/tests/auto/xmlpatternssdk/docs/XMLWriterExampleResult.xml new file mode 100644 index 0000000..c5e7312 --- /dev/null +++ b/tests/auto/xmlpatternssdk/docs/XMLWriterExampleResult.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"><body><p>Hello World!</p></body></html> diff --git a/tests/auto/xmlpatternssdk/tests/XMLWriterTest.cpp b/tests/auto/xmlpatternssdk/tests/XMLWriterTest.cpp new file mode 100644 index 0000000..37a4814 --- /dev/null +++ b/tests/auto/xmlpatternssdk/tests/XMLWriterTest.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include "XMLWriter.h" + +#include "XMLWriterTest.h" +#include "XMLWriterTest.moc" + +using namespace QPatternistSDK; + +QTEST_MAIN(XMLWriterTest) + +void XMLWriterTest::serialize() +{ + QFETCH(QString, input); + QFETCH(QString, expectedResult); + + QByteArray result; + QBuffer returnBuffer(&result); + + XMLWriter writer(&returnBuffer); + + QXmlInputSource inputSource; + inputSource.setData(input); + + QXmlSimpleReader reader; + reader.setContentHandler(&writer); + + const bool parseSuccess = reader.parse(inputSource); + Q_ASSERT_X(parseSuccess, Q_FUNC_INFO, + "XMLWriter reported an error while serializing the input."); + + QCOMPARE(QString::fromLatin1(result), expectedResult); +} + +void XMLWriterTest::serialize_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("expectedResult"); + + /* ------------------- Elements ------------------- */ + QTest::newRow("Only an document element") + << "<doc></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc/>"; + + QTest::newRow("Document element containing a short closed element") + << "<doc><f/></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><f/></doc>"; + QTest::newRow("Complex nested elements") + << "<doc><a/><b/><c><d/><e><f><x/></f></e></c></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><a/><b/><c><d/><e><f><x/></f></e></c></doc>"; + /* ------------------------------------------------- */ + + /* ---------------- Element Content ---------------- */ + QTest::newRow("Element content with simple content") + << "<doc>content</doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc>content</doc>"; + + QTest::newRow("Element content with tricky to escape content") + << "<doc>>>&'\"''/></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc>>>&'\"''/></doc>"; + /* ------------------------------------------------- */ + + /* ----------- Processing Instructions ------------- */ + QTest::newRow("Simple processing instruction.") + << "<doc><?php content?></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><?php content?></doc>"; + /* ------------------------------------------------- */ + + /* --------------- 'xml' attributes ---------------- */ + QTest::newRow("Simple xml:space attribute.") + << "<doc xml:space='preserve'>content</doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc xml:space=\"preserve\">content</doc>"; + + QTest::newRow("Many 'xml' attributes.") + << "<doc xml:space='preserve' xml:foo='3' xml:s2='3'>content</doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<doc xml:space=\"preserve\" xml:foo=\"3\" xml:s2=\"3\">content</doc>"; + /* ------------------------------------------------- */ + + /* ------------ namespace declarations ------------- */ + QTest::newRow("One simple namespace declaration.") + << "<doc xmlns:f='example.org/'/>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<doc xmlns:f=\"example.org/\"/>"; + + QTest::newRow("Two simple namespace declarations.") + << "<doc xmlns:f='example.org/' xmlns:e='example.org/'/>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<doc xmlns:f=\"example.org/\" xmlns:e=\"example.org/\"/>"; + + QTest::newRow("A simple default namespace.") + << "<doc xmlns='example.org/'/>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<doc xmlns=\"example.org/\"/>"; + /* ------------------------------------------------- */ + + /* -------- namespace declarations in use ---------- */ + QTest::newRow("Simple use of a namespace declaration.") + << "<doc xmlns:f='example.org/' f:attr='chars'><n/><f:name f:attr='chars'/></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<doc xmlns:f=\"example.org/\" f:attr=\"chars\"><n/><f:name f:attr=\"chars\"/></doc>"; + /* ------------------------------------------------- */ +} + +void XMLWriterTest::cdata() +{ + /* + QTest::newRow("Simple CDATA") + << "<doc><![CDATA[content]]></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><![CDATA[content]]></doc>"; + + QTest::newRow("Complex CDATA") + << "<doc><![CDATA[<<>>&'\";&987;]]></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><![CDATA[<<>>&'\";&123;]]></doc>"; + */ +} + +void XMLWriterTest::comments() +{ + /* + QTest::newRow("Simple comment") + << "<doc><!-- comment --></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><!-- comment --></doc>"; + QTest::newRow("Comment") + << "<doc><!--- comment --></doc>" + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doc><!--- comment --></doc>"; + */ +} + +void XMLWriterTest::doxygenExample() +{ +#include "../docs/XMLWriterExample.cpp" + + /* When changing, remember to update the Doxygen in XMLWriter.h */ + const QByteArray expectedResult( + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body><p>Hello World!</p></body></html>" + ); + + QCOMPARE(QString::fromLatin1(result), QString::fromLatin1(expectedResult)); +} + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/tests/XMLWriterTest.h b/tests/auto/xmlpatternssdk/tests/XMLWriterTest.h new file mode 100644 index 0000000..7479a77 --- /dev/null +++ b/tests/auto/xmlpatternssdk/tests/XMLWriterTest.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PatternistSDK_XMLWriterTest_H +#define PatternistSDK_XMLWriterTest_H + +#include <QObject> + +QT_BEGIN_HEADER + +namespace QPatternistSDK +{ + /** + * @short QTestLib test for XMLWriter. + * + * @ingroup PatternistSDK + * @author Frans Englich <frans.englich@nokia.com> + */ + class XMLWriterTest : public QObject + { + Q_OBJECT + private Q_SLOTS: + void serialize(); + void serialize_data(); + void comments(); + void cdata(); + + /** + * Ensure the example compiles, and that it does + * what it claims to. + */ + void doxygenExample(); + }; +} + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternssdk/xmlpatternssdk.pro b/tests/auto/xmlpatternssdk/xmlpatternssdk.pro new file mode 100644 index 0000000..6204f01 --- /dev/null +++ b/tests/auto/xmlpatternssdk/xmlpatternssdk.pro @@ -0,0 +1,88 @@ +include (../xmlpatterns.pri) + +TARGET = $$XMLPATTERNS_SDK +TEMPLATE = lib +DEFINES += Q_PATTERNISTSDK_BUILDING + +# lib_bundle ensures we get a framework on OS X, a library bundle. +CONFIG += resources + +mac { + CONFIG += absolute_library_soname + target.path=$$[QT_INSTALL_LIBS] + INSTALLS += target +} + +symbian { + TARGET.EPOCALLOWDLLDATA=1 + TARGET.CAPABILITY = All -Tcb + MMP_RULES += EXPORTUNFROZEN +} + +# We add gui, because xmlpatterns.pri pull it out. +QT += xmlpatterns xml network testlib gui + +DESTDIR = $$QT_BUILD_TREE/lib +!wince*:DLLDESTDIR = $$QT_BUILD_TREE/bin + +# syncqt doesn't copy headers in tools/ so let's manually ensure +# it works with shadow builds and source builds. +INCLUDEPATH += $$QT_BUILD_TREE/include/QtXmlPatterns/private \ + $$QT_SOURCE_TREE/include/QtXmlPatterns/private \ + $$QT_SOURCE_TREE/tools/xmlpatterns + +HEADERS = ASTItem.h \ + DebugExpressionFactory.h \ + ErrorHandler.h \ + ErrorItem.h \ + ExitCode.h \ + ExpressionInfo.h \ + ExpressionNamer.h \ + ExternalSourceLoader.h \ + Global.h \ + ResultThreader.h \ + TestBaseLine.h \ + TestCase.h \ + TestContainer.h \ + TestGroup.h \ + TestItem.h \ + TestResult.h \ + TestResultHandler.h \ + TestSuite.h \ + TestSuiteHandler.h \ + TestSuiteResult.h \ + TreeItem.h \ + TreeModel.h \ + Worker.h \ + XMLWriter.h \ + XQTSTestCase.h \ + XSDTestSuiteHandler.h \ + XSDTSTestCase.h \ + XSLTTestSuiteHandler.h + +SOURCES = ASTItem.cpp \ + DebugExpressionFactory.cpp \ + ErrorHandler.cpp \ + ErrorItem.cpp \ + ExpressionInfo.cpp \ + ExpressionNamer.cpp \ + ExternalSourceLoader.cpp \ + Global.cpp \ + ResultThreader.cpp \ + TestBaseLine.cpp \ + TestCase.cpp \ + TestContainer.cpp \ + TestGroup.cpp \ + TestResult.cpp \ + TestResultHandler.cpp \ + TestSuite.cpp \ + TestSuiteHandler.cpp \ + TestSuiteResult.cpp \ + TreeItem.cpp \ + TreeModel.cpp \ + Worker.cpp \ + XMLWriter.cpp \ + XQTSTestCase.cpp \ + XSDTestSuiteHandler.cpp \ + XSDTSTestCase.cpp \ + XSLTTestSuiteHandler.cpp |