/**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #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(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 { /* */ 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); /* */ receiver.startElement(QLatin1String("description"), test_caseAtts); receiver.characters(description()); /* */ receiver.endElement(QLatin1String("description")); /* */ 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); /* */ 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); /* */ 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