tests/auto/xmlpatternsxqts/lib/TestCase.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QBuffer>
       
    43 #include <QUrl>
       
    44 #include <QXmlAttributes>
       
    45 #include <QXmlQuery>
       
    46 #include <QXmlResultItems>
       
    47 #include <QXmlSerializer>
       
    48 #include <qxmlquery_p.h>
       
    49 
       
    50 #include "DebugExpressionFactory.h"
       
    51 #include "ExternalSourceLoader.h"
       
    52 #include "Global.h"
       
    53 #include "TestSuite.h"
       
    54 #include "XMLWriter.h"
       
    55 
       
    56 #include "TestCase.h"
       
    57 
       
    58 using namespace QPatternistSDK;
       
    59 using namespace QPatternist;
       
    60 
       
    61 // STATIC DATA
       
    62 static const DebugExpressionFactory::Ptr s_exprFact(new DebugExpressionFactory());
       
    63 
       
    64 TestCase::TestCase() : m_result(0)
       
    65 {
       
    66 }
       
    67 
       
    68 TestCase::~TestCase()
       
    69 {
       
    70     delete m_result;
       
    71 }
       
    72 
       
    73 TestResult::List TestCase::execute(const ExecutionStage stage,
       
    74                                    TestSuite *)
       
    75 {
       
    76     if(name() == QLatin1String("Constr-cont-document-3"))
       
    77     {
       
    78             TestResult::List result;
       
    79             result.append(createTestResult(TestResult::Fail, QLatin1String("Skipped this test, because we loop infinitely on it.")));
       
    80             return result;
       
    81     }
       
    82     else if(name() == QLatin1String("Axes089"))
       
    83     {
       
    84             TestResult::List result;
       
    85             result.append(createTestResult(TestResult::Fail, QLatin1String("Skipped this test, we crash on it.")));
       
    86             return result;
       
    87     }
       
    88 
       
    89     qDebug() << "Running test case: " << name();
       
    90 
       
    91     return execute(stage);
       
    92 
       
    93     Q_ASSERT(false);
       
    94     return TestResult::List();
       
    95 }
       
    96 
       
    97 TestResult *TestCase::createTestResult(const TestResult::Status status,
       
    98                                              const QString &comment) const
       
    99 {
       
   100     TestResult *const result = new TestResult(name(),
       
   101                                               status,
       
   102                                               0 /* We don't have an AST. */,
       
   103                                               ErrorHandler::Message::List(),
       
   104                                               QPatternist::Item::List(),
       
   105                                               QString());
       
   106     result->setComment(comment);
       
   107     return result;
       
   108 }
       
   109 
       
   110 TestResult::List TestCase::execute(const ExecutionStage stage)
       
   111 {
       
   112     ErrorHandler errHandler;
       
   113     ErrorHandler::installQtMessageHandler(&errHandler);
       
   114 
       
   115     pDebug() << "TestCase::execute()";
       
   116     delete m_result;
       
   117 
       
   118     QXmlQuery query(language(), Global::namePoolAsPublic());
       
   119 
       
   120     query.d->setExpressionFactory(s_exprFact);
       
   121     query.setInitialTemplateName(initialTemplateName());
       
   122 
       
   123     QXmlQuery openDoc(query.namePool());
       
   124 
       
   125     if(contextItemSource().isValid())
       
   126     {
       
   127         openDoc.setQuery(QString::fromLatin1("doc('") + contextItemSource().toString() + QLatin1String("')"));
       
   128         Q_ASSERT(openDoc.isValid());
       
   129         QXmlResultItems result;
       
   130 
       
   131         openDoc.evaluateTo(&result);
       
   132         const QXmlItem item(result.next());
       
   133         Q_ASSERT(!item.isNull());
       
   134         query.setFocus(item);
       
   135     }
       
   136 
       
   137     TestResult::List retval;
       
   138 
       
   139     const Scenario scen(scenario());
       
   140     TestResult::Status resultStatus = TestResult::Unknown;
       
   141 
       
   142     bool ok = false;
       
   143     const QString queryString(sourceCode(ok));
       
   144 
       
   145     if(!ok)
       
   146     {
       
   147         /* Loading the query file failed, or similar. */
       
   148         resultStatus = TestResult::Fail;
       
   149 
       
   150         m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(),
       
   151                                   errHandler.messages(), QPatternist::Item::List(), QString());
       
   152         retval.append(m_result);
       
   153         ErrorHandler::installQtMessageHandler(0);
       
   154         changed(this);
       
   155         return retval;
       
   156     }
       
   157 
       
   158     query.setMessageHandler(&errHandler);
       
   159     QXmlNamePool namePool(query.namePool());
       
   160 
       
   161     /* Bind variables. */
       
   162     QPatternist::ExternalVariableLoader::Ptr loader(externalVariableLoader());
       
   163     if(loader)
       
   164     {
       
   165         Q_ASSERT(loader);
       
   166         const ExternalSourceLoader::VariableMap vMap(static_cast<const ExternalSourceLoader *>(loader.data())->variableMap());
       
   167         const QStringList variables(vMap.keys());
       
   168 
       
   169         for(int i = 0; i < variables.count(); ++i)
       
   170         {
       
   171             const QXmlName name(namePool, variables.at(i));
       
   172             const QXmlItem val(QPatternist::Item::toPublic(loader->evaluateSingleton(name, QPatternist::DynamicContext::Ptr())));
       
   173             query.bindVariable(name, val);
       
   174         }
       
   175     }
       
   176 
       
   177     /* We pass in the testCasePath(), such that the base URI is correct fort
       
   178      * XSL-T stylesheets. */
       
   179     query.setQuery(queryString, testCasePath());
       
   180 
       
   181     if(!query.isValid())
       
   182     {
       
   183         pDebug() << "Got compilation exception.";
       
   184         resultStatus = TestBaseLine::scanErrors(errHandler.messages(), baseLines());
       
   185 
       
   186         Q_ASSERT(resultStatus != TestResult::Unknown);
       
   187         m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(),
       
   188                                   errHandler.messages(), QPatternist::Item::List(), QString());
       
   189         retval.append(m_result);
       
   190         ErrorHandler::installQtMessageHandler(0);
       
   191         changed(this);
       
   192         return retval;
       
   193     }
       
   194 
       
   195     if(stage == CompileOnly)
       
   196     {
       
   197         m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(),
       
   198                                   errHandler.messages(), QPatternist::Item::List(), QString());
       
   199         retval.append(m_result);
       
   200         return retval;
       
   201     }
       
   202 
       
   203     Q_ASSERT(stage == CompileAndRun);
       
   204 
       
   205     if(scen == ParseError) /* We're supposed to have received an error
       
   206                               at this point. */
       
   207     {
       
   208         m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(),
       
   209                                   errHandler.messages(), QPatternist::Item::List(), QString());
       
   210         ErrorHandler::installQtMessageHandler(0);
       
   211         retval.append(m_result);
       
   212         changed(this);
       
   213         return retval;
       
   214     }
       
   215 
       
   216     QPatternist::Item::List itemList;
       
   217 
       
   218     QByteArray output;
       
   219     QBuffer buffer(&output);
       
   220     buffer.open(QIODevice::WriteOnly);
       
   221 
       
   222     QXmlSerializer serializer(query, &buffer);
       
   223 
       
   224     pDebug() << "-------------------------- evaluateToPushCallback() ---------------------------- ";
       
   225     const bool success = query.evaluateTo(&serializer);
       
   226     pDebug() << "------------------------------------------------------------------------------------ ";
       
   227 
       
   228     buffer.close();
       
   229 
       
   230     const QString serialized(QString::fromUtf8(output.constData(), output.size()));
       
   231 
       
   232     if(!success)
       
   233     {
       
   234         resultStatus = TestBaseLine::scanErrors(errHandler.messages(), baseLines());
       
   235 
       
   236         Q_ASSERT(resultStatus != TestResult::Unknown);
       
   237         m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(),
       
   238                                   errHandler.messages(), QPatternist::Item::List(), serialized);
       
   239         retval.append(m_result);
       
   240         ErrorHandler::installQtMessageHandler(0);
       
   241         changed(this);
       
   242         return retval;
       
   243     }
       
   244 
       
   245     /* It's a regular test. */
       
   246     Q_ASSERT(scen == Standard || scen == RuntimeError);
       
   247 
       
   248     resultStatus = TestBaseLine::scan(serialized, baseLines());
       
   249     Q_ASSERT(resultStatus != TestResult::Unknown);
       
   250 
       
   251     /* Check that errHandler()->messages() at most only contains
       
   252      * warnings, since it shouldn't have errors at this point. */
       
   253     const ErrorHandler::Message::List errors (errHandler.messages());
       
   254     const ErrorHandler::Message::List::const_iterator end(errors.constEnd());
       
   255     ErrorHandler::Message::List::const_iterator it(errors.constBegin());
       
   256 
       
   257     for(; it != end; ++it)
       
   258     {
       
   259         const QtMsgType type = (*it).type();
       
   260         if(type == QtFatalMsg)
       
   261         {
       
   262             m_result = new TestResult(name(), TestResult::Fail, s_exprFact->astTree(),
       
   263                                       errHandler.messages(), itemList, serialized);
       
   264             retval.append(m_result);
       
   265             ErrorHandler::installQtMessageHandler(0);
       
   266             changed(this);
       
   267             return retval;
       
   268         }
       
   269     }
       
   270 
       
   271     m_result = new TestResult(name(), resultStatus, s_exprFact->astTree(),
       
   272                               errHandler.messages(), itemList, serialized);
       
   273     retval.append(m_result);
       
   274     ErrorHandler::installQtMessageHandler(0);
       
   275     changed(this);
       
   276     return retval;
       
   277 }
       
   278 
       
   279 TestCase::Scenario TestCase::scenarioFromString(const QString &string)
       
   280 {
       
   281     if(string == QLatin1String("standard"))
       
   282         return Standard;
       
   283     else if(string == QLatin1String("parse-error"))
       
   284         return ParseError;
       
   285     else if(string == QLatin1String("runtime-error"))
       
   286         return RuntimeError;
       
   287     else if(string == QLatin1String("trivial"))
       
   288         return Trivial;
       
   289     else
       
   290     {
       
   291         Q_ASSERT_X(false, Q_FUNC_INFO,
       
   292                    qPrintable(QString::fromLatin1("Invalid string representation for the scenario-enum: %1").arg(string)));
       
   293         return ParseError; /* Silence GCC. */
       
   294     }
       
   295 }
       
   296 
       
   297 void TestCase::toXML(XMLWriter &receiver) const
       
   298 {
       
   299     /* <test-case> */
       
   300     QXmlAttributes test_caseAtts;
       
   301     test_caseAtts.append(QLatin1String("is-XPath2"), QString(),
       
   302                          QLatin1String("is-XPath2"), isXPath() ? QLatin1String("true")
       
   303                                                                : QLatin1String("false"));
       
   304     test_caseAtts.append(QLatin1String("name"), QString(), QLatin1String("name"), name());
       
   305     test_caseAtts.append(QLatin1String("creator"), QString(), QLatin1String("creator"), creator());
       
   306     QString scen;
       
   307     switch(scenario())
       
   308     {
       
   309         case Standard:
       
   310         {
       
   311             scen = QLatin1String("standard");
       
   312             break;
       
   313         }
       
   314         case ParseError:
       
   315         {
       
   316             scen = QLatin1String("parse-error");
       
   317             break;
       
   318         }
       
   319         case RuntimeError:
       
   320         {
       
   321             scen = QLatin1String("runtime-error");
       
   322             break;
       
   323         }
       
   324         case Trivial:
       
   325         {
       
   326             scen = QLatin1String("trivial");
       
   327             break;
       
   328         }
       
   329         default: /* includes 'AnyError' */
       
   330             Q_ASSERT(false);
       
   331     }
       
   332     test_caseAtts.append(QLatin1String("scenario"), QString(), QLatin1String("scenario"), scen);
       
   333     test_caseAtts.append(QLatin1String(QLatin1String("FilePath")), QString(),
       
   334                          QLatin1String("FilePath"), QString());
       
   335     receiver.startElement(QLatin1String("test-case"), test_caseAtts);
       
   336 
       
   337     /* <description> */
       
   338     receiver.startElement(QLatin1String("description"), test_caseAtts);
       
   339     receiver.characters(description());
       
   340 
       
   341     /* </description> */
       
   342     receiver.endElement(QLatin1String("description"));
       
   343 
       
   344     /* <query> */
       
   345     QXmlAttributes queryAtts;
       
   346     queryAtts.append(QLatin1String("date"), QString(), QLatin1String("date"), /* This date is a dummy. */
       
   347                      QDate::currentDate().toString(Qt::ISODate));
       
   348     queryAtts.append(QLatin1String("name"), QString(), QLatin1String("name"), testCasePath().toString());
       
   349     receiver.startElement(QLatin1String("query"), queryAtts);
       
   350 
       
   351     /* </query> */
       
   352     receiver.endElement(QLatin1String("query"));
       
   353 
       
   354     /* Note: this is invalid, we don't add spec-citation. */
       
   355     TestBaseLine::List bls(baseLines());
       
   356     const TestBaseLine::List::const_iterator end(bls.constEnd());
       
   357     TestBaseLine::List::const_iterator it(bls.constBegin());
       
   358 
       
   359     for(; it != end; ++it)
       
   360         (*it)->toXML(receiver);
       
   361 
       
   362     /* </test-case> */
       
   363     receiver.endElement(QLatin1String("test-case"));
       
   364 }
       
   365 
       
   366 QString TestCase::displayName(const Scenario scen)
       
   367 {
       
   368     switch(scen)
       
   369     {
       
   370         case Standard:
       
   371             return QLatin1String("Standard");
       
   372         case ParseError:
       
   373             return QLatin1String("Parse Error");
       
   374         case RuntimeError:
       
   375             return QLatin1String("Runtime Error");
       
   376         case Trivial:
       
   377             return QLatin1String("Trivial");
       
   378         case AnyError:
       
   379         {
       
   380             Q_ASSERT(false);
       
   381             return QString();
       
   382         }
       
   383     }
       
   384 
       
   385     Q_ASSERT(false);
       
   386     return QString();
       
   387 }
       
   388 
       
   389 TestItem::ResultSummary TestCase::resultSummary() const
       
   390 {
       
   391     if(m_result)
       
   392         return ResultSummary(m_result->status() == TestResult::Pass ? 1 : 0,
       
   393                              1);
       
   394 
       
   395     return ResultSummary(0, 1);
       
   396 }
       
   397 
       
   398 void TestCase::appendChild(TreeItem *)
       
   399 {
       
   400     Q_ASSERT_X(false, Q_FUNC_INFO, "Makes no sense to call appendChild() for TestCase.");
       
   401 }
       
   402 
       
   403 TreeItem *TestCase::child(const unsigned int) const
       
   404 {
       
   405     return 0; /* Silence GCC */
       
   406 }
       
   407 
       
   408 TreeItem::List TestCase::children() const
       
   409 {
       
   410     return TreeItem::List();
       
   411 }
       
   412 
       
   413 unsigned int TestCase::childCount() const
       
   414 {
       
   415     return 0;
       
   416 }
       
   417 
       
   418 TestResult *TestCase::testResult() const
       
   419 {
       
   420     return m_result;
       
   421 }
       
   422 
       
   423 bool TestCase::isFinalNode() const
       
   424 {
       
   425     return true;
       
   426 }
       
   427 
       
   428 QXmlQuery::QueryLanguage TestCase::language() const
       
   429 {
       
   430     return QXmlQuery::XQuery10;
       
   431 }
       
   432 
       
   433 QXmlName TestCase::initialTemplateName() const
       
   434 {
       
   435     return QXmlName();
       
   436 }
       
   437 
       
   438 // vim: et:ts=4:sw=4:sts=4
       
   439