tests/auto/qxmlquery/tst_qxmlquery.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/qxmlquery/tst_qxmlquery.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,3463 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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>
+
+#ifdef QTEST_XMLPATTERNS
+
+#include <QAbstractMessageHandler>
+#include <QFileInfo>
+#include <QNetworkReply>
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+#include <QXmlFormatter>
+#include <QXmlItem>
+#include <QXmlName>
+#include <QXmlQuery>
+#include <QXmlResultItems>
+#include <QXmlSerializer>
+
+#include "MessageSilencer.h"
+#include "MessageValidator.h"
+#include "NetworkOverrider.h"
+#include "PushBaseliner.h"
+#include "../qabstracturiresolver/TestURIResolver.h"
+#include "../qsimplexmlnodemodel/TestSimpleNodeModel.h"
+#include "TestFundament.h"
+#include "../network-settings.h"
+
+#if defined(Q_OS_SYMBIAN)
+#define SRCDIR ""
+#endif
+
+/*!
+ \class tst_QXmlQuery
+ \internal
+ \since 4.4
+ \brief Tests class QXmlQuery.
+
+ This test is not intended for testing the engine, but the functionality specific
+ to the QXmlQuery class.
+
+ In other words, if you have an engine bug; don't add it here because it won't be
+ tested properly. Instead add it to the test suite.
+
+ */
+class tst_QXmlQuery : public QObject
+                    , private TestFundament
+{
+    Q_OBJECT
+
+public:
+    inline tst_QXmlQuery() : m_generatedBaselines(0)
+                           , m_pushTestsCount(0)
+                           , m_testNetwork(true)
+    {
+        Q_SET_DEFAULT_IAP
+    }
+
+private Q_SLOTS:
+    void defaultConstructor() const;
+    void copyConstructor() const;
+    void constructorQXmlNamePool() const;
+    void constructorQXmlNamePoolQueryLanguage() const;
+    void constructorQXmlNamePoolWithinQSimpleXmlNodeModel() const;
+    void assignmentOperator() const;
+    void isValid() const;
+    void sequentialExecution() const;
+    void bindVariableQString() const;
+    void bindVariableQStringNoExternalDeclaration() const;
+    void bindVariableQXmlName() const;
+    void bindVariableQXmlNameTriggerWarnings() const;
+    void bindVariableQStringQIODevice() const;
+    void bindVariableQStringQIODeviceWithByteArray() const;
+    void bindVariableQStringQIODeviceWithString() const;
+    void bindVariableQStringQIODeviceWithQFile() const;
+    void bindVariableQXmlNameQIODevice() const;
+    void bindVariableQXmlNameQIODeviceTriggerWarnings() const;
+    void bindVariableXSLTSuccess() const;
+    void bindVariableTemporaryNode() const;
+    void setMessageHandler() const;
+    void messageHandler() const;
+    void evaluateToQAbstractXmlReceiverTriggerWarnings() const;
+    void evaluateToQXmlResultItems() const;
+    void evaluateToQXmlResultItemsTriggerWarnings() const;
+    void evaluateToQXmlResultItemsErrorAtEnd() const;
+    void evaluateToReceiver();
+    void evaluateToReceiver_data() const;
+    void evaluateToReceiverOnInvalidQuery() const;
+    void evaluateToQStringTriggerError() const;
+    void evaluateToQString() const;
+    void evaluateToQString_data() const;
+    void evaluateToQStringSignature() const;
+    void checkGeneratedBaselines() const;
+    void basicXQueryToQtTypeCheck() const;
+    void basicQtToXQueryTypeCheck() const;
+    void bindNode() const;
+    void relativeBaseURI() const;
+    void emptyBaseURI() const;
+    void roundTripDateWithinQXmlItem() const;
+    void bindingMissing() const;
+    void bindDefaultConstructedItem() const;
+    void bindDefaultConstructedItem_data() const;
+    void bindEmptyNullString() const;
+    void bindEmptyString() const;
+    void rebindVariableSameType() const;
+    void rebindVariableDifferentType() const;
+    void rebindVariableWithNullItem() const;
+    void eraseQXmlItemBinding() const;
+    void eraseDeviceBinding() const;
+    void constCorrectness() const;
+    void objectSize() const;
+    void setUriResolver() const;
+    void uriResolver() const;
+    void messageXML() const;
+    void resultItemsDeallocatedQuery() const;
+    void copyCheckMessageHandler() const;
+    void shadowedVariables() const;
+    void setFocusQXmlItem() const;
+    void setFocusQUrl() const;
+    void setFocusQIODevice() const;
+    void setFocusQIODeviceAvoidVariableClash() const;
+    void setFocusQIODeviceFailure() const;
+    void setFocusQIODeviceTriggerWarnings() const;
+    void setFocusQString() const;
+    void setFocusQStringFailure() const;
+    void setFocusQStringSignature() const;
+    void recompilationWithEvaluateToResultFailing() const;
+    void secondEvaluationWithEvaluateToResultFailing() const;
+    void recompilationWithEvaluateToReceiver() const;
+    void fnDocOnQIODeviceTimeout() const;
+    void evaluateToQStringListOnInvalidQuery() const;
+    void evaluateToQStringList() const;
+    void evaluateToQStringListTriggerWarnings() const;
+    void evaluateToQStringList_data() const;
+    void evaluateToQStringListNoConversion() const;
+    void evaluateToQIODevice() const;
+    void evaluateToQIODeviceTriggerWarnings() const;
+    void evaluateToQIODeviceSignature() const;
+    void evaluateToQIODeviceOnInvalidQuery() const;
+    void setQueryQIODeviceQUrl() const;
+    void setQueryQIODeviceQUrlTriggerWarnings() const;
+    void setQueryQString() const;
+    void setQueryQUrlSuccess() const;
+    void setQueryQUrlSuccess_data() const;
+    void setQueryQUrlFailSucceed() const;
+    void setQueryQUrlFailure() const;
+    void setQueryQUrlFailure_data() const;
+    void setQueryQUrlBaseURI() const;
+    void setQueryQUrlBaseURI_data() const;
+    void setQueryWithNonExistentQUrlOnValidQuery() const;
+    void setQueryWithInvalidQueryFromQUrlOnValidQuery() const;
+    void retrieveNameFromQuery() const;
+    void retrieveNameFromQuery_data() const;
+    void cleanupTestCase() const;
+    void declareUnavailableExternal() const;
+    void msvcCacheIssue() const;
+    void unavailableExternalVariable() const;
+    void useUriResolver() const;
+    void queryWithFocusAndVariable() const;
+    void undefinedFocus() const;
+    void basicFocusUsage() const;
+
+    void queryLanguage() const;
+    void queryLanguageSignature() const;
+    void enumQueryLanguage() const;
+
+    void setNetworkAccessManager() const;
+    void networkAccessManagerSignature() const;
+    void networkAccessManagerDefaultValue() const;
+    void networkAccessManager() const;
+
+    void setInitialTemplateNameQXmlName() const;
+    void setInitialTemplateNameQXmlNameSignature() const;
+    void setInitialTemplateNameQString() const;
+    void setInitialTemplateNameQStringSignature() const;
+    void initialTemplateName() const;
+    void initialTemplateNameSignature() const;
+
+    void fnDocNetworkAccessSuccess() const;
+    void fnDocNetworkAccessSuccess_data() const;
+    void fnDocNetworkAccessFailure() const;
+    void fnDocNetworkAccessFailure_data() const;
+    void multipleDocsAndFocus() const;
+    void multipleEvaluationsWithDifferentFocus() const;
+    void bindVariableQXmlQuery() const;
+    void bindVariableQXmlQuery_data() const;
+    void bindVariableQStringQXmlQuerySignature() const;
+    void bindVariableQXmlNameQXmlQuerySignature() const;
+    void bindVariableQXmlNameQXmlQuery() const;
+    void bindVariableQXmlQueryInvalidate() const;
+    void unknownSourceLocation() const;
+
+    void identityConstraintSuccess() const;
+    void identityConstraintFailure() const;
+    void identityConstraintFailure_data() const;
+
+    // TODO call all URI resolving functions where 1) the URI resolver return a null QUrl(); 2) resolves into valid, existing URI, 3) invalid, non-existing URI.
+    // TODO bind stringlists, variant lists, both ways.
+    // TODO trigger serialization error, or any error in evaluateToushCallback().
+    // TODO let items travle between two queries, as seen in the SDK
+    // TODO what happens if the query declares local variable and external ones are provided?
+
+private:
+    enum
+    {
+        /**
+         * One excluded, since we skip static-base-uri.xq.
+         */
+        ExpectedQueryCount = 29
+    };
+
+    static void checkBaseURI(const QUrl &baseURI, const QString &candidate);
+    static QStringList queries();
+    static const char *const queriesDirectory;
+
+    int m_generatedBaselines;
+    int m_pushTestsCount;
+    const bool m_testNetwork;
+};
+
+void tst_QXmlQuery::checkBaseURI(const QUrl &baseURI, const QString &candidate)
+{
+    /* The use of QFileInfo::canonicalFilePath() takes into account that drive letters
+     * on Windows may have different cases. */
+    QVERIFY(QDir(baseURI.toLocalFile()).relativeFilePath(QFileInfo(candidate).canonicalFilePath()).startsWith("../"));
+}
+
+const char *const tst_QXmlQuery::queriesDirectory = SRCDIR "../xmlpatterns/queries/";
+
+QStringList tst_QXmlQuery::queries()
+{
+    QDir dir;
+    dir.cd(inputFile(QLatin1String(queriesDirectory)));
+
+    return dir.entryList(QStringList(QLatin1String("*.xq")));
+}
+
+void tst_QXmlQuery::defaultConstructor() const
+{
+    /* Allocate instance in different orders. */
+    {
+        QXmlQuery query;
+    }
+
+    {
+        QXmlQuery query1;
+        QXmlQuery query2;
+    }
+
+    {
+        QXmlQuery query1;
+        QXmlQuery query2;
+        QXmlQuery query3;
+    }
+}
+
+void tst_QXmlQuery::copyConstructor() const
+{
+    /* Verify that we can take a const reference, and simply do a copy of a default constructed object. */
+    {
+        const QXmlQuery query1;
+        QXmlQuery query2(query1);
+    }
+
+    /* Copy twice. */
+    {
+        const QXmlQuery query1;
+        QXmlQuery query2(query1);
+        QXmlQuery query3(query2);
+    }
+
+    /* Verify that copying default values works. */
+    {
+        const QXmlQuery query1;
+        const QXmlQuery query2(query1);
+        QCOMPARE(query2.messageHandler(), query1.messageHandler());
+        QCOMPARE(query2.uriResolver(), query1.uriResolver());
+        QCOMPARE(query2.queryLanguage(), query1.queryLanguage());
+        QCOMPARE(query2.initialTemplateName(), query1.initialTemplateName());
+        QCOMPARE(query2.networkAccessManager(), query1.networkAccessManager());
+    }
+
+    /* Check that the
+     *
+     * - name pool
+     * - URI resolver
+     * - message handler
+     * - query language
+     * - initial template name
+     *
+     *   sticks with the copy. */
+    {
+        MessageSilencer silencer;
+        TestURIResolver resolver;
+        QNetworkAccessManager networkManager;
+        QXmlQuery query1(QXmlQuery::XSLT20);
+        QXmlNamePool np1(query1.namePool());
+
+        query1.setMessageHandler(&silencer);
+        query1.setUriResolver(&resolver);
+        query1.setNetworkAccessManager(&networkManager);
+
+        const QXmlName name(np1, QLatin1String("localName"),
+                                 QLatin1String("http://example.com/"),
+                                 QLatin1String("prefix"));
+        query1.setInitialTemplateName(name);
+
+        const QXmlQuery query2(query1);
+        QCOMPARE(query2.messageHandler(), &silencer);
+        QCOMPARE(query2.uriResolver(), &resolver);
+        QCOMPARE(query2.queryLanguage(), QXmlQuery::XSLT20);
+        QCOMPARE(query2.initialTemplateName(), name);
+        QCOMPARE(query2.networkAccessManager(), &networkManager);
+
+        QXmlNamePool np2(query2.namePool());
+
+        QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/"));
+        QCOMPARE(name.localName(np2), QString::fromLatin1("localName"));
+        QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix"));
+    }
+
+    {
+        QXmlQuery original;
+
+        original.setFocus(QXmlItem(4));
+        original.setQuery(QLatin1String("."));
+        QVERIFY(original.isValid());
+
+        const QXmlQuery copy(original);
+
+        QXmlResultItems result;
+        copy.evaluateTo(&result);
+        QCOMPARE(result.next().toAtomicValue(), QVariant(4));
+        QVERIFY(result.next().isNull());
+        QVERIFY(!result.hasError());
+    }
+
+    /* Copy, set, compare. Check that copies are independent. */
+    {
+        // TODO all members except queryLanguage().
+    }
+}
+
+void tst_QXmlQuery::constructorQXmlNamePool() const
+{
+    /* Check that the namepool we are passed, is actually used. */
+    QXmlNamePool np;
+
+    QXmlQuery query(np);
+    const QXmlName name(np, QLatin1String("localName"),
+                            QLatin1String("http://example.com/"),
+                            QLatin1String("prefix"));
+
+    QXmlNamePool np2(query.namePool());
+    QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/"));
+    QCOMPARE(name.localName(np2), QString::fromLatin1("localName"));
+    QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix"));
+}
+
+/*!
+  Ensure that the internal variable loading mechanisms uses the user-supplied
+  name pool.
+
+  If that is not the case, different name pools are used and the code crashes.
+
+  \since 4.5
+ */
+void tst_QXmlQuery::constructorQXmlNamePoolQueryLanguage() const
+{
+    QXmlNamePool np;
+    QXmlName name(np, QLatin1String("arbitraryName"));
+
+    QXmlQuery query(QXmlQuery::XQuery10, np);
+
+    QBuffer input;
+    input.setData("<yall/>");
+
+    QVERIFY(input.open(QIODevice::ReadOnly));
+    query.bindVariable(name, &input);
+    query.setQuery("string(doc($arbitraryName))");
+
+    QStringList result;
+    query.evaluateTo(&result);
+}
+
+void tst_QXmlQuery::constructorQXmlNamePoolWithinQSimpleXmlNodeModel() const
+{
+    class TestCTOR : public TestSimpleNodeModel
+    {
+    public:
+        TestCTOR(const QXmlNamePool &np) : TestSimpleNodeModel(np)
+        {
+        }
+
+        void checkCTOR() const
+        {
+            /* If this fails to compile, the constructor has trouble with taking
+             * a mutable reference.
+             *
+             * The reason we use the this pointer explicitly, is to avoid a compiler
+             * warnings with MSVC 2005. */
+            QXmlQuery(this->namePool());
+        }
+    };
+
+    QXmlNamePool np;
+    TestCTOR ctor(np);
+    ctor.checkCTOR();
+}
+
+void tst_QXmlQuery::assignmentOperator() const
+{
+    class ReturnURI : public QAbstractUriResolver
+    {
+    public:
+        virtual QUrl resolve(const QUrl &relative,
+                             const QUrl &baseURI) const
+        {
+            return baseURI.resolved(relative);
+        }
+    };
+
+    /* Assign this to this. */
+    {
+        QXmlQuery query;
+        query = query;
+        query = query;
+        query = query;
+
+        /* Just call a couple of functions to give valgrind
+         * something to check. */
+        QVERIFY(!query.isValid());
+        query.messageHandler();
+    }
+
+    /* Assign null instances a couple of times. */
+    {
+        QXmlQuery query1;
+        QXmlQuery query2;
+        query1 = query2;
+        query1 = query2;
+        query1 = query2;
+
+        /* Just call a couple of functions to give valgrind
+         * something to check. */
+        QVERIFY(!query1.isValid());
+        query1.messageHandler();
+
+        /* Just call a couple of functions to give valgrind
+         * something to check. */
+        QVERIFY(!query2.isValid());
+        query2.messageHandler();
+    }
+
+    /* Create a query, set all the things it stores, and ensure it
+     * travels over to the new instance. */
+    {
+        MessageSilencer silencer;
+        const ReturnURI returnURI;
+        QXmlNamePool namePool;
+
+        QBuffer documentDevice;
+        documentDevice.setData(QByteArray("<e>a</e>"));
+        QVERIFY(documentDevice.open(QIODevice::ReadOnly));
+
+        QXmlQuery original(namePool);
+        QXmlName testName(namePool, QLatin1String("somethingToCheck"));
+
+        original.setMessageHandler(&silencer);
+        original.bindVariable(QLatin1String("var"), QXmlItem(1));
+        original.bindVariable(QLatin1String("device"), &documentDevice);
+        original.setUriResolver(&returnURI);
+        original.setFocus(QXmlItem(3));
+        original.setQuery(QLatin1String("$var, 1 + 1, ., string(doc($device))"));
+
+        /* Do a copy, and check that everything followed on into the copy. No modification
+         * of the copy. */
+        {
+            QXmlQuery copy;
+
+            /* We use assignment operator, not copy constructor. */
+            copy = original;
+
+            QVERIFY(copy.isValid());
+            QCOMPARE(copy.uriResolver(), static_cast<const QAbstractUriResolver *>(&returnURI));
+            QCOMPARE(copy.messageHandler(), &silencer);
+            QCOMPARE(testName.localName(copy.namePool()), QString::fromLatin1("somethingToCheck"));
+
+            QXmlResultItems result;
+            copy.evaluateTo(&result);
+            QCOMPARE(result.next().toAtomicValue(), QVariant(1));
+            QCOMPARE(result.next().toAtomicValue(), QVariant(2));
+            QCOMPARE(result.next().toAtomicValue(), QVariant(3));
+            QCOMPARE(result.next().toAtomicValue(), QVariant(QString::fromLatin1("a")));
+            QVERIFY(result.next().isNull());
+            QVERIFY(!result.hasError());
+        }
+
+        /* Copy, and change values. Things should detach. */
+        {
+            /* Evaluate the copy. */
+            {
+                MessageSilencer secondSilencer;
+                const ReturnURI secondUriResolver;
+                QBuffer documentDeviceCopy;
+                documentDeviceCopy.setData(QByteArray("<e>b</e>"));
+                QVERIFY(documentDeviceCopy.open(QIODevice::ReadOnly));
+
+                QXmlQuery copy;
+                copy = original;
+
+                copy.setMessageHandler(&secondSilencer);
+                /* Here we rebind variable values. */
+                copy.bindVariable(QLatin1String("var"), QXmlItem(4));
+                copy.bindVariable(QLatin1String("device"), &documentDeviceCopy);
+                copy.setUriResolver(&secondUriResolver);
+                copy.setFocus(QXmlItem(6));
+                copy.setQuery(QLatin1String("$var, 1 + 1, ., string(doc($device))"));
+
+                /* Check that the copy picked up the new things. */
+                QVERIFY(copy.isValid());
+                QCOMPARE(copy.uriResolver(), static_cast<const QAbstractUriResolver *>(&secondUriResolver));
+                QCOMPARE(copy.messageHandler(), &secondSilencer);
+
+                QXmlResultItems resultCopy;
+                copy.evaluateTo(&resultCopy);
+                QCOMPARE(resultCopy.next().toAtomicValue(), QVariant(4));
+                QCOMPARE(resultCopy.next().toAtomicValue(), QVariant(2));
+                QCOMPARE(resultCopy.next().toAtomicValue(), QVariant(6));
+                const QString stringedDevice(resultCopy.next().toAtomicValue().toString());
+                QCOMPARE(stringedDevice, QString::fromLatin1("b"));
+                QVERIFY(resultCopy.next().isNull());
+                QVERIFY(!resultCopy.hasError());
+            }
+
+            /* Evaluate the original. */
+            {
+                /* Check that the original is unchanged. */
+                QVERIFY(original.isValid());
+                QCOMPARE(original.uriResolver(), static_cast<const QAbstractUriResolver *>(&returnURI));
+                QCOMPARE(original.messageHandler(), &silencer);
+
+                QXmlResultItems resultOriginal;
+                original.evaluateTo(&resultOriginal);
+                QCOMPARE(resultOriginal.next().toAtomicValue(), QVariant(1));
+                QCOMPARE(resultOriginal.next().toAtomicValue(), QVariant(2));
+                QCOMPARE(resultOriginal.next().toAtomicValue(), QVariant(3));
+                QCOMPARE(resultOriginal.next().toAtomicValue(), QVariant(QString::fromLatin1("a")));
+                QVERIFY(resultOriginal.next().isNull());
+                QVERIFY(!resultOriginal.hasError());
+            }
+        }
+    }
+}
+
+/*!
+  Since QXmlQuery doesn't seek devices to position 0, this code triggers a bug
+  where document caching doesn't work. Since the document caching doesn't work,
+  the device will be read twice, and the second time the device is at the end,
+  hence premature end of document.
+ */
+void tst_QXmlQuery::sequentialExecution() const
+{
+    QBuffer inBuffer;
+    inBuffer.setData(QByteArray("<input/>"));
+    QVERIFY(inBuffer.open(QIODevice::ReadOnly));
+
+    QXmlQuery query;
+    query.bindVariable("inputDocument", &inBuffer);
+
+    QByteArray outArray;
+    QBuffer outBuffer(&outArray);
+    outBuffer.open(QIODevice::WriteOnly);
+
+    const QString queryString(QLatin1String("doc($inputDocument)"));
+    query.setQuery(queryString);
+
+    QXmlFormatter formatter(query, &outBuffer);
+
+    QVERIFY(query.evaluateTo(&formatter));
+
+    /* If this line is removed, the bug isn't triggered. */
+    query.setQuery(queryString);
+
+    QVERIFY(query.evaluateTo(&formatter));
+}
+
+void tst_QXmlQuery::isValid() const
+{
+    /* Check default value. */
+    QXmlQuery query;
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::bindVariableQString() const
+{
+    {
+        QXmlQuery query;
+        /* Bind with a null QXmlItem. */
+        query.bindVariable(QLatin1String("name"), QXmlItem());
+    }
+
+    {
+        QXmlQuery query;
+        /* Bind with a null QVariant. */
+        query.bindVariable(QLatin1String("name"), QXmlItem(QVariant()));
+    }
+
+    {
+        QXmlQuery query;
+        /* Bind with a null QXmlNodeModelIndex. */
+        query.bindVariable(QLatin1String("name"), QXmlItem(QXmlNodeModelIndex()));
+    }
+}
+
+void tst_QXmlQuery::bindVariableQStringNoExternalDeclaration() const
+{
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("foo"), QXmlItem(QLatin1String("Variable Value")));
+    query.setQuery(QLatin1String("$foo"));
+
+    QVERIFY(query.isValid());
+
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+
+    QCOMPARE(result, QStringList() << QLatin1String("Variable Value"));
+}
+
+void tst_QXmlQuery::bindVariableQXmlName() const
+{
+    // TODO
+}
+
+void tst_QXmlQuery::bindVariableQXmlNameTriggerWarnings() const
+{
+    QXmlQuery query;
+
+    QTest::ignoreMessage(QtWarningMsg, "The variable name cannot be null.");
+    query.bindVariable(QXmlName(), QVariant());
+}
+
+void tst_QXmlQuery::bindVariableQStringQIODeviceWithByteArray() const
+{
+    QXmlQuery query;
+
+    QByteArray in("<e/>");
+    QBuffer device(&in);
+    QVERIFY(device.open(QIODevice::ReadOnly));
+
+    query.bindVariable("doc", &device);
+
+    query.setQuery(QLatin1String("declare variable $doc external; $doc"));
+
+    QVERIFY(query.isValid());
+
+    /* Check the URI corresponding to the variable. */
+    {
+        QXmlResultItems items;
+        query.evaluateTo(&items);
+
+        QCOMPARE(items.next().toAtomicValue().toString(), QString::fromLatin1("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:doc"));
+    }
+
+    /* Now, actually load the document. We use the same QXmlQuery just to stress recompilation a bit. */
+    {
+        query.setQuery(QLatin1String("declare variable $doc external; doc($doc)"));
+
+        QByteArray out;
+        QBuffer outBuffer(&out);
+        QVERIFY(outBuffer.open(QIODevice::WriteOnly));
+
+        QXmlSerializer serializer(query, &outBuffer);
+
+        QVERIFY(query.evaluateTo(&serializer));
+        QCOMPARE(out, in);
+    }
+}
+
+void tst_QXmlQuery::bindVariableQStringQIODeviceWithString() const
+{
+    QXmlQuery query;
+
+    QString in("<qstring/>");
+    QByteArray inUtf8(in.toUtf8());
+    QBuffer inDevice(&inUtf8);
+
+    QVERIFY(inDevice.open(QIODevice::ReadOnly));
+
+    query.bindVariable("doc", &inDevice);
+
+    query.setQuery(QLatin1String("declare variable $doc external; doc($doc)"));
+
+    QByteArray out;
+    QBuffer outBuffer(&out);
+    QVERIFY(outBuffer.open(QIODevice::WriteOnly));
+
+    QXmlSerializer serializer(query, &outBuffer);
+    QVERIFY(query.evaluateTo(&serializer));
+
+    QCOMPARE(out, inUtf8);
+}
+
+void tst_QXmlQuery::bindVariableQStringQIODeviceWithQFile() const
+{
+    QXmlQuery query;
+    QFile inDevice(QLatin1String(SRCDIR "input.xml"));
+
+    QVERIFY(inDevice.open(QIODevice::ReadOnly));
+
+    query.bindVariable("doc", &inDevice);
+
+    query.setQuery(QLatin1String("declare variable $doc external; doc($doc)"));
+
+    QByteArray out;
+    QBuffer outBuffer(&out);
+    QVERIFY(outBuffer.open(QIODevice::WriteOnly));
+
+    QXmlSerializer serializer(query, &outBuffer);
+    QVERIFY(query.evaluateTo(&serializer));
+    outBuffer.close();
+
+    QCOMPARE(out, QByteArray("<!-- This is just a file for testing. --><input/>"));
+}
+
+void tst_QXmlQuery::bindVariableQStringQIODevice() const
+{
+    QXmlQuery query;
+
+    /* Rebind the variable. */
+    {
+        /* First evaluation. */
+        {
+            QByteArray in1("<e1/>");
+            QBuffer inDevice1(&in1);
+            QVERIFY(inDevice1.open(QIODevice::ReadOnly));
+
+            query.bindVariable("in", &inDevice1);
+            query.setQuery(QLatin1String("doc($in)"));
+
+            QByteArray out1;
+            QBuffer outDevice1(&out1);
+            QVERIFY(outDevice1.open(QIODevice::WriteOnly));
+
+            QXmlSerializer serializer(query, &outDevice1);
+            query.evaluateTo(&serializer);
+            QCOMPARE(out1, in1);
+        }
+
+        /* Second evaluation, rebind variable. */
+        {
+            QByteArray in2("<e2/>");
+            QBuffer inDevice2(&in2);
+            QVERIFY(inDevice2.open(QIODevice::ReadOnly));
+
+            query.bindVariable(QLatin1String("in"), &inDevice2);
+
+            QByteArray out2;
+            QBuffer outDevice2(&out2);
+            QVERIFY(outDevice2.open(QIODevice::WriteOnly));
+
+            QXmlSerializer serializer(query, &outDevice2);
+            QVERIFY(query.evaluateTo(&serializer));
+            QCOMPARE(out2, in2);
+        }
+    }
+
+    // TODO trigger recompilation when setting qiodevices., and qiodevice overwritten by other type, etc.
+}
+
+void tst_QXmlQuery::bindVariableQXmlNameQIODevice() const
+{
+    // TODO
+}
+
+void tst_QXmlQuery::bindVariableQXmlNameQIODeviceTriggerWarnings() const
+{
+    QXmlNamePool np;
+    QXmlQuery query(np);
+
+    QBuffer buffer;
+    QTest::ignoreMessage(QtWarningMsg, "A null, or readable QIODevice must be passed.");
+    query.bindVariable(QXmlName(np, QLatin1String("foo")), &buffer);
+
+    QTest::ignoreMessage(QtWarningMsg, "The variable name cannot be null.");
+    query.bindVariable(QXmlName(), 0);
+}
+
+void tst_QXmlQuery::bindVariableXSLTSuccess() const
+{
+    QXmlQuery stylesheet(QXmlQuery::XSLT20);
+    stylesheet.setInitialTemplateName(QLatin1String("main"));
+
+    stylesheet.bindVariable(QLatin1String("variableNoSelectNoBodyBoundWithBindVariable"),
+                                          QVariant(QLatin1String("MUST NOT SHOW 1")));
+
+    stylesheet.bindVariable(QLatin1String("variableSelectBoundWithBindVariable"),
+                                          QVariant(QLatin1String("MUST NOT SHOW 2")));
+
+    stylesheet.bindVariable(QLatin1String("variableSelectWithTypeIntBoundWithBindVariable"),
+                                          QVariant(QLatin1String("MUST NOT SHOW 3")));
+
+    stylesheet.bindVariable(QLatin1String("paramNoSelectNoBodyBoundWithBindVariable"),
+                                          QVariant(QLatin1String("param1")));
+
+    stylesheet.bindVariable(QLatin1String("paramNoSelectNoBodyBoundWithBindVariableRequired"),
+                                          QVariant(QLatin1String("param1")));
+
+    stylesheet.bindVariable(QLatin1String("paramSelectBoundWithBindVariable"),
+                                          QVariant(QLatin1String("param2")));
+
+    stylesheet.bindVariable(QLatin1String("paramSelectBoundWithBindVariableRequired"),
+                                          QVariant(QLatin1String("param3")));
+
+    stylesheet.bindVariable(QLatin1String("paramSelectWithTypeIntBoundWithBindVariable"),
+                                          QVariant(4));
+
+    stylesheet.bindVariable(QLatin1String("paramSelectWithTypeIntBoundWithBindVariableRequired"),
+                                          QVariant(QLatin1String("param5")));
+
+    stylesheet.setQuery(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/parameters.xsl"))));
+
+    QVERIFY(stylesheet.isValid());
+
+    QBuffer deviceOut;
+    QVERIFY(deviceOut.open(QIODevice::ReadWrite));
+
+    QVERIFY(stylesheet.evaluateTo(&deviceOut));
+
+    const QString result(QString::fromUtf8(deviceOut.data().constData()));
+
+    QCOMPARE(result,
+             QString::fromLatin1("Variables:   variableSelectsDefaultValue variableSelectsDefaultValue2 3 4 "
+                                 "Parameters: param1 param1 param2 param3 4 param5"));
+}
+
+void tst_QXmlQuery::bindVariableTemporaryNode() const
+{
+    /* First we do it with QXmlResultItems staying in scope. */;
+    {
+        QXmlQuery query1;
+        query1.setQuery("<anElement/>");
+
+        QXmlResultItems result1;
+        query1.evaluateTo(&result1);
+
+        QXmlQuery query2(query1);
+        query2.bindVariable("fromQuery1", result1.next());
+        query2.setQuery("$fromQuery1");
+
+        QString output;
+        QVERIFY(query2.evaluateTo(&output));
+
+        QCOMPARE(output, QString::fromLatin1("<anElement/>\n"));
+    }
+
+    /* And now with it deallocating, so its internal DynamicContext pointer is
+     * released. This doesn't work in Qt 4.5 and is ok. */
+    {
+        QXmlQuery query1;
+        query1.setQuery("<anElement/>");
+
+        QXmlQuery query2;
+
+        {
+            QXmlResultItems result1;
+            query1.evaluateTo(&result1);
+
+            query2.bindVariable("fromQuery1", result1.next());
+            query2.setQuery("$fromQuery1");
+        }
+
+        QString output;
+        return; // See comment above.
+        QVERIFY(query2.evaluateTo(&output));
+
+        QCOMPARE(output, QString::fromLatin1("<anElement/>\n"));
+    }
+}
+
+void tst_QXmlQuery::messageHandler() const
+{
+    {
+        /* Check default value. */
+        QXmlQuery query;
+        QCOMPARE(query.messageHandler(), static_cast<QAbstractMessageHandler *>(0));
+    }
+}
+
+void tst_QXmlQuery::setMessageHandler() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+    QCOMPARE(&silencer, query.messageHandler());
+}
+
+void tst_QXmlQuery::evaluateToReceiver()
+{
+    QFETCH(QString, inputQuery);
+
+    /* This query prints a URI specific to the local system. */
+    if(inputQuery == QLatin1String("static-base-uri.xq"))
+        return;
+
+    ++m_pushTestsCount;
+    const QString queryURI(inputFile(QLatin1String(queriesDirectory) + inputQuery));
+    QFile queryFile(queryURI);
+
+    QVERIFY(queryFile.exists());
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+
+    QXmlQuery query;
+
+    MessageSilencer receiver;
+    query.setMessageHandler(&receiver);
+    query.setQuery(&queryFile, QUrl::fromLocalFile(queryURI));
+
+    /* We read all the queries, and some of them are invalid. However, we
+     * only want those that compile. */
+    if(!query.isValid())
+        return;
+
+    QString produced;
+    QTextStream stream(&produced, QIODevice::WriteOnly);
+    PushBaseliner push(stream, query.namePool());
+    query.evaluateTo(&push);
+
+    const QString baselineName(inputFile(QLatin1String(SRCDIR "pushBaselines/") + inputQuery.left(inputQuery.length() - 2) + QString::fromLatin1("ref")));
+    QFile baseline(baselineName);
+
+    if(baseline.exists())
+    {
+        QVERIFY(baseline.open(QIODevice::ReadOnly | QIODevice::Text));
+        const QString stringedBaseline(QString::fromUtf8(baseline.readAll()));
+        QCOMPARE(produced, stringedBaseline);
+    }
+    else
+    {
+        QVERIFY(baseline.open(QIODevice::WriteOnly));
+        /* This is intentionally a warning, don't remove it. Update the baselines instead. */
+        qWarning() << "Generated baseline for:" << baselineName;
+        ++m_generatedBaselines;
+
+        baseline.write(produced.toUtf8());
+    }
+}
+
+void tst_QXmlQuery::evaluateToReceiver_data() const
+{
+    QTest::addColumn<QString>("inputQuery");
+
+    const QStringList qs(queries());
+
+    for(int i = 0; i < qs.size(); ++i)
+    {
+        /* This outputs a URI specific to the environment, so we can't use it for this
+         * particular test. */
+        if(qs.at(i) != QLatin1String("staticBaseURI.xq"))
+            QTest::newRow(qs.at(i).toUtf8().constData()) << qs.at(i);
+    }
+}
+
+void tst_QXmlQuery::evaluateToReceiverOnInvalidQuery() const
+{
+    /* Invoke on a default constructed object. */
+    {
+        QByteArray out;
+        QBuffer buffer(&out);
+        buffer.open(QIODevice::WriteOnly);
+
+        QXmlQuery query;
+        QXmlSerializer serializer(query, &buffer);
+        QVERIFY(!query.evaluateTo(&serializer));
+    }
+
+    /* Invoke on an invalid query; compile time error. */
+    {
+        QByteArray out;
+        QBuffer buffer(&out);
+        buffer.open(QIODevice::WriteOnly);
+        MessageSilencer silencer;
+
+        QXmlQuery query;
+        query.setMessageHandler(&silencer);
+        query.setQuery(QLatin1String("1 + "));
+        QXmlSerializer serializer(query, &buffer);
+        QVERIFY(!query.evaluateTo(&serializer));
+    }
+
+    /* Invoke on an invalid query; runtime error. */
+    {
+        QByteArray out;
+        QBuffer buffer(&out);
+        buffer.open(QIODevice::WriteOnly);
+        MessageSilencer silencer;
+
+        QXmlQuery query;
+        query.setMessageHandler(&silencer);
+        query.setQuery(QLatin1String("error()"));
+        QXmlSerializer serializer(query, &buffer);
+        QVERIFY(!query.evaluateTo(&serializer));
+    }
+}
+
+void tst_QXmlQuery::evaluateToQStringTriggerError() const
+{
+    /* Invoke on a default constructed object. */
+    {
+        QXmlQuery query;
+        QString out;
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on an invalid query; compile time error. */
+    {
+        QXmlQuery query;
+        MessageSilencer silencer;
+        query.setMessageHandler(&silencer);
+
+        query.setQuery(QLatin1String("1 + "));
+
+        QString out;
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on an invalid query; runtime error. */
+    {
+        QXmlQuery query;
+        MessageSilencer silencer;
+        query.setMessageHandler(&silencer);
+
+        query.setQuery(QLatin1String("error()"));
+
+        QString out;
+        QVERIFY(!query.evaluateTo(&out));
+    }
+}
+
+void tst_QXmlQuery::evaluateToQString() const
+{
+    QFETCH(QString, query);
+    QFETCH(QString, expectedOutput);
+
+    QXmlQuery queryInstance;
+    queryInstance.setQuery(query);
+    QVERIFY(queryInstance.isValid());
+
+    QString result;
+    QVERIFY(queryInstance.evaluateTo(&result));
+
+    QCOMPARE(result, expectedOutput);
+}
+
+void tst_QXmlQuery::evaluateToQString_data() const
+{
+    QTest::addColumn<QString>("query");
+    QTest::addColumn<QString>("expectedOutput");
+
+    QTest::newRow("Two atomics")
+        << QString::fromLatin1("1, 'two'")
+        << QString::fromLatin1("1 two\n");
+
+    QTest::newRow("An element")
+        << QString::fromLatin1("<e>{1}</e>")
+        << QString::fromLatin1("<e>1</e>\n");
+}
+
+void tst_QXmlQuery::evaluateToQStringSignature() const
+{
+    const QXmlQuery query;
+
+    QString output;
+
+    /* evaluateTo(QString *) should be a const function. */
+    query.evaluateTo(&output);
+}
+
+void tst_QXmlQuery::evaluateToQAbstractXmlReceiverTriggerWarnings() const
+{
+    QXmlQuery query;
+
+    /* We check the return value as well as warning message here. */
+    QTest::ignoreMessage(QtWarningMsg, "A non-null callback must be passed.");
+    QCOMPARE(query.evaluateTo(static_cast<QAbstractXmlReceiver *>(0)),
+             false);
+}
+
+void tst_QXmlQuery::evaluateToQXmlResultItems() const
+{
+    /* Invoke on a default constructed object. */
+    {
+        QXmlQuery query;
+        QXmlResultItems result;
+        query.evaluateTo(&result);
+        QVERIFY(result.next().isNull());
+    }
+}
+
+void tst_QXmlQuery::evaluateToQXmlResultItemsTriggerWarnings() const
+{
+    QTest::ignoreMessage(QtWarningMsg, "A null pointer cannot be passed.");
+    QXmlQuery query;
+    query.evaluateTo(static_cast<QXmlResultItems *>(0));
+}
+
+void tst_QXmlQuery::evaluateToQXmlResultItemsErrorAtEnd() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+    query.setQuery(QLatin1String("1 to 100, fn:error()"));
+    QVERIFY(query.isValid());
+
+    QXmlResultItems it;
+    query.evaluateTo(&it);
+
+    while(!it.next().isNull())
+    {
+    }
+}
+
+/*!
+  If baselines were generated, we flag it as a failure such that it gets
+  attention, and that they are adjusted accordingly.
+ */
+void tst_QXmlQuery::checkGeneratedBaselines() const
+{
+    QCOMPARE(m_generatedBaselines, 0);
+
+    /* If this check fails, the auto test setup is misconfigured, or files have
+     * been added/removed without this number being updated. */
+    QCOMPARE(m_pushTestsCount, int(ExpectedQueryCount));
+}
+
+void tst_QXmlQuery::basicXQueryToQtTypeCheck() const
+{
+    QFile queryFile(QLatin1String(queriesDirectory) + QString::fromLatin1("allAtomics.xq"));
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+
+    QXmlQuery query;
+    query.setQuery(&queryFile);
+    QVERIFY(query.isValid());
+
+    QXmlResultItems it;
+    query.evaluateTo(&it);
+
+    QVariantList expectedValues;
+    expectedValues.append(QString::fromLatin1("xs:untypedAtomic"));
+    expectedValues.append(QDateTime(QDate(2002, 10, 10), QTime(23, 2, 11), Qt::UTC));
+    expectedValues.append(QDate(2002, 10, 10));
+    expectedValues.append(QVariant()); /* We currently doesn't support xs:time through the API. */
+
+    expectedValues.append(QVariant()); /* xs:duration */
+    expectedValues.append(QVariant()); /* xs:dayTimeDuration */
+    expectedValues.append(QVariant()); /* xs:yearMonthDuration */
+
+    expectedValues.append(QVariant(double(3e3)));     /* xs:float */
+    expectedValues.append(QVariant(double(4e4)));     /* xs:double */
+    expectedValues.append(QVariant(double(2)));       /* xs:decimal */
+
+    /* xs:integer and its sub-types. */
+    expectedValues.append(QVariant(qlonglong(16)));
+    expectedValues.append(QVariant(qlonglong(-6)));
+    expectedValues.append(QVariant(qlonglong(-4)));
+    expectedValues.append(QVariant(qlonglong(5)));
+    expectedValues.append(QVariant(qlonglong(6)));
+    expectedValues.append(QVariant(qlonglong(7)));
+    expectedValues.append(QVariant(qlonglong(8)));
+    expectedValues.append(QVariant(qlonglong(9)));
+    expectedValues.append(QVariant(qulonglong(10)));
+    expectedValues.append(QVariant(qlonglong(11)));
+    expectedValues.append(QVariant(qlonglong(12)));
+    expectedValues.append(QVariant(qlonglong(13)));
+    expectedValues.append(QVariant(qlonglong(14)));
+
+    expectedValues.append(QVariant());                                                          /* xs:gYearMonth("1976-02"), */
+    expectedValues.append(QVariant());                                                          /* xs:gYear("2005-12:00"), */
+    expectedValues.append(QVariant());                                                          /* xs:gMonthDay("--12-25-14:00"), */
+    expectedValues.append(QVariant());                                                          /* xs:gDay("---25-14:00"), */
+    expectedValues.append(QVariant());                                                          /* xs:gMonth("--12-14:00"), */
+    expectedValues.append(true);                                                                /* xs:boolean("true"), */
+    expectedValues.append(QVariant(QByteArray::fromBase64(QByteArray("aaaa"))));                /* xs:base64Binary("aaaa"), */
+    expectedValues.append(QVariant(QByteArray::fromHex(QByteArray("FFFF"))));                   /* xs:hexBinary("FFFF"), */
+    expectedValues.append(QVariant(QString::fromLatin1("http://example.com/")));                /* xs:anyURI("http://example.com/"), */
+    QXmlNamePool np(query.namePool());
+    expectedValues.append(QVariant(qVariantFromValue(QXmlName(np, QLatin1String("localName"),
+                                                              QLatin1String("http://example.com/2"),
+                                                              QLatin1String("prefix")))));
+
+    expectedValues.append(QVariant(QString::fromLatin1("An xs:string")));
+    expectedValues.append(QVariant(QString::fromLatin1("normalizedString")));
+    expectedValues.append(QVariant(QString::fromLatin1("token")));
+    expectedValues.append(QVariant(QString::fromLatin1("language")));
+    expectedValues.append(QVariant(QString::fromLatin1("NMTOKEN")));
+    expectedValues.append(QVariant(QString::fromLatin1("Name")));
+    expectedValues.append(QVariant(QString::fromLatin1("NCName")));
+    expectedValues.append(QVariant(QString::fromLatin1("ID")));
+    expectedValues.append(QVariant(QString::fromLatin1("IDREF")));
+    expectedValues.append(QVariant(QString::fromLatin1("ENTITY")));
+
+    int i = 0;
+    QXmlItem item(it.next());
+
+    while(!item.isNull())
+    {
+        QVERIFY(item.isAtomicValue());
+        const QVariant produced(item.toAtomicValue());
+
+        const QVariant &expected = expectedValues.at(i);
+
+        /* For the cases where we can't represent a value in the XDM with Qt,
+         * we return an invalid QVariant. */
+        QCOMPARE(expected.isValid(), produced.isValid());
+
+        QCOMPARE(produced.type(), expected.type());
+
+        if(expected.isValid())
+        {
+            /* This is only needed for xs:decimal though, for some reason. Probably
+             * just artifacts created somewhere. */
+            if(produced.type() == QVariant::Double)
+                QVERIFY(qFuzzyCompare(produced.toDouble(), expected.toDouble()));
+            else if(qVariantCanConvert<QXmlName>(produced))
+            {
+                /* QVariant::operator==() does identity comparison, it doesn't delegate to operator==() of
+                 * the contained type, unless it's hardcoded into QVariant. */
+                const QXmlName n1 = qVariantValue<QXmlName>(produced);
+                const QXmlName n2 = qVariantValue<QXmlName>(expected);
+                QCOMPARE(n1, n2);
+            }
+            else
+                QCOMPARE(produced, expected);
+        }
+
+        ++i;
+        item = it.next();
+    }
+
+    QCOMPARE(i, expectedValues.count());
+}
+
+/*!
+  Send values from Qt into XQuery.
+ */
+void tst_QXmlQuery::basicQtToXQueryTypeCheck() const
+{
+    QFile queryFile(QLatin1String(queriesDirectory) + QLatin1String("allAtomicsExternally.xq"));
+    QVERIFY(queryFile.exists());
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+
+    QCOMPARE(QVariant(QDate(1999, 9, 10)).type(), QVariant::Date);
+
+    QXmlQuery query;
+
+    QXmlNamePool np(query.namePool());
+
+    const QXmlName name(np, QLatin1String("localname"),
+                            QLatin1String("http://example.com"),
+                            QLatin1String("prefix"));
+
+    query.bindVariable(QLatin1String("fromQUrl"), QXmlItem(QUrl(QString::fromLatin1("http://example.com/"))));
+    query.bindVariable(QLatin1String("fromQByteArray"), QXmlItem(QByteArray("AAAA")));
+    query.bindVariable(QLatin1String("fromBool"), QXmlItem(bool(true)));
+    query.bindVariable(QLatin1String("fromQDate"), QXmlItem(QDate(2000, 10, 11)));
+    // TODO Do with different QDateTime time specs
+    query.bindVariable(QLatin1String("fromQDateTime"), QXmlItem(QDateTime(QDate(2001, 9, 10), QTime(1, 2, 3))));
+    query.bindVariable(QLatin1String("fromDouble"), QXmlItem(double(3)));
+    query.bindVariable(QLatin1String("fromFloat"), QXmlItem(float(4)));
+    query.bindVariable(QLatin1String("integer"), QXmlItem(5));
+    query.bindVariable(QLatin1String("fromQString"), QXmlItem(QString::fromLatin1("A QString")));
+    query.bindVariable(QLatin1String("fromQChar"), QXmlItem(QChar::fromLatin1('C')));
+
+    query.bindVariable(QLatin1String("fromIntLiteral"), QXmlItem(QVariant(654)));
+
+    {
+        QVariant ui(uint(5));
+        QCOMPARE(ui.type(), QVariant::UInt);
+        query.bindVariable(QLatin1String("fromUInt"), ui);
+    }
+
+    {
+        QVariant ulnglng(qulonglong(6));
+        QCOMPARE(ulnglng.type(), QVariant::ULongLong);
+        query.bindVariable(QLatin1String("fromULongLong"), ulnglng);
+    }
+
+    {
+        QVariant qlnglng(qlonglong(7));
+        QCOMPARE(qlnglng.type(), QVariant::LongLong);
+        query.bindVariable(QLatin1String("fromLongLong"), qlnglng);
+    }
+
+    query.setQuery(&queryFile);
+
+    // TODO do queries which declares external variables with types. Tons of combos here.
+    // TODO ensure that binding with QXmlItem() doesn't make a binding available.
+    // TODO test rebinding a variable.
+
+    QVERIFY(query.isValid());
+
+    QXmlResultItems it;
+    query.evaluateTo(&it);
+    QXmlItem item(it.next());
+    QVERIFY(!item.isNull());
+    QVERIFY(item.isAtomicValue());
+
+    QCOMPARE(item.toAtomicValue().toString(),
+             QLatin1String("4 true 3 654 7 41414141 C 2000-10-11Z 2001-09-10T01:02:03 "
+                           "A QString http://example.com/ 5 6 true true true true true true true true true true "
+                           "true true true"));
+}
+
+void tst_QXmlQuery::bindNode() const
+{
+    QXmlQuery query;
+    TestSimpleNodeModel nodeModel(query.namePool());
+
+    query.bindVariable(QLatin1String("node"), nodeModel.root());
+    QByteArray out;
+    QBuffer buff(&out);
+    QVERIFY(buff.open(QIODevice::WriteOnly));
+
+    query.setQuery(QLatin1String("declare variable $node external; $node"));
+    QXmlSerializer serializer(query, &buff);
+
+    QVERIFY(query.evaluateTo(&serializer));
+    QCOMPARE(out, QByteArray("<nodeName/>"));
+}
+
+/*!
+  Pass in a relative URI, and make sure it is resolved against the current application directory.
+ */
+void tst_QXmlQuery::relativeBaseURI() const
+{
+    QXmlQuery query;
+    query.setQuery(QLatin1String("fn:static-base-uri()"), QUrl(QLatin1String("a/relative/uri.weirdExtension")));
+    QVERIFY(query.isValid());
+
+    QByteArray result;
+    QBuffer buffer(&result);
+    QVERIFY(buffer.open(QIODevice::ReadWrite));
+
+    QXmlSerializer serializer(query, &buffer);
+    QVERIFY(query.evaluateTo(&serializer));
+
+    const QUrl loaded(QUrl::fromEncoded(result));
+    QUrl appPath(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()));
+
+    QVERIFY(loaded.isValid());
+    QVERIFY(appPath.isValid());
+    QVERIFY(!loaded.isRelative());
+    QVERIFY(!appPath.isRelative());
+
+    QFileInfo dir(appPath.toLocalFile());
+    dir.setFile(QString());
+
+    /* We can't use QUrl::isParentOf() because it doesn't do what we want it to */
+    if(!loaded.toLocalFile().startsWith(dir.absoluteFilePath()))
+        QTextStream(stderr) << "dir.absoluteFilePath():" << dir.absoluteFilePath() << "loaded.toLocalFile():" << loaded.toLocalFile();
+
+    checkBaseURI(loaded, dir.absoluteFilePath());
+}
+
+void tst_QXmlQuery::emptyBaseURI() const
+{
+    QXmlQuery query;
+    query.setQuery(QLatin1String("fn:static-base-uri()"), QUrl());
+    QVERIFY(query.isValid());
+
+    QByteArray result;
+    QBuffer buffer(&result);
+    QVERIFY(buffer.open(QIODevice::ReadWrite));
+
+    QXmlSerializer serializer(query, &buffer);
+    QVERIFY(query.evaluateTo(&serializer));
+
+    const QUrl loaded(QUrl::fromEncoded(result));
+    QUrl appPath(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()));
+
+    QVERIFY(loaded.isValid());
+    QVERIFY(appPath.isValid());
+    QVERIFY(!loaded.isRelative());
+    QVERIFY(!appPath.isRelative());
+
+    QFileInfo dir(appPath.toLocalFile());
+    dir.setFile(QString());
+
+    QCOMPARE(loaded, appPath);
+}
+
+/*!
+  Ensure that QDate comes out as QDateTime.
+ */
+void tst_QXmlQuery::roundTripDateWithinQXmlItem() const
+{
+    const QDate date(1999, 9, 10);
+    QVERIFY(date.isValid());
+
+    const QVariant variant(date);
+    QVERIFY(variant.isValid());
+    QCOMPARE(variant.type(), QVariant::Date);
+
+    const QXmlItem item(variant);
+    QVERIFY(!item.isNull());
+    QVERIFY(item.isAtomicValue());
+
+    const QVariant out(item.toAtomicValue());
+    QVERIFY(out.isValid());
+    QCOMPARE(out.type(), QVariant::Date);
+    QCOMPARE(out.toDate(), date);
+}
+
+/*!
+ Check whether a query is valid, which uses an unbound variable.
+ */
+void tst_QXmlQuery::bindingMissing() const
+{
+    QXmlQuery query;
+    MessageSilencer messageHandler;
+    query.setMessageHandler(&messageHandler);
+
+    QFile queryFile(QLatin1String(queriesDirectory) + QString::fromLatin1("externalVariable.xq"));
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+    query.setQuery(&queryFile);
+
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::bindDefaultConstructedItem() const
+{
+    QFETCH(QXmlItem, item);
+
+    QXmlQuery query;
+    MessageSilencer messageHandler;
+    query.setMessageHandler(&messageHandler);
+
+    QFile queryFile(QLatin1String(queriesDirectory) + QString::fromLatin1("externalVariable.xq"));
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+    query.setQuery(&queryFile);
+    query.bindVariable(QLatin1String("externalVariable"), item);
+
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::bindDefaultConstructedItem_data() const
+{
+    QTest::addColumn<QXmlItem>("item");
+
+    QTest::newRow("QXmlItem()") << QXmlItem();
+    QTest::newRow("QXmlItem(QVariant())") << QXmlItem(QVariant());
+    QTest::newRow("QXmlItem(QXmlNodeModelIndex())") << QXmlItem(QXmlNodeModelIndex());
+}
+
+/*!
+  Remove a binding by binding QXmlItem() with the same name.
+ */
+void tst_QXmlQuery::eraseQXmlItemBinding() const
+{
+    QXmlQuery query;
+    MessageSilencer messageHandler;
+    query.setMessageHandler(&messageHandler);
+
+    QFile queryFile(QLatin1String(queriesDirectory) + QString::fromLatin1("externalVariable.xq"));
+    QVERIFY(queryFile.open(QIODevice::ReadOnly));
+    query.bindVariable(QLatin1String("externalVariable"), QXmlItem(3));
+    query.setQuery(&queryFile);
+    QVERIFY(query.isValid());
+
+    QByteArray result;
+    QBuffer buffer(&result);
+    QVERIFY(buffer.open(QIODevice::ReadWrite));
+
+    QXmlSerializer serializer(query, &buffer);
+    QVERIFY(query.evaluateTo(&serializer));
+
+    QCOMPARE(result, QByteArray("3 6<e>3</e>false"));
+
+    query.bindVariable(QLatin1String("externalVariable"), QXmlItem());
+    QVERIFY(!query.isValid());
+}
+
+/*!
+ Erase a variable binding
+ */
+void tst_QXmlQuery::eraseDeviceBinding() const
+{
+    /* Erase an existing QIODevice binding with another QIODevice binding. */
+    {
+        QXmlQuery query;
+
+        QByteArray doc("<e/>");
+        QBuffer buffer(&doc);
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+        query.bindVariable(QLatin1String("in"), &buffer);
+        query.setQuery(QLatin1String("$in"));
+        QVERIFY(query.isValid());
+
+        query.bindVariable(QLatin1String("in"), 0);
+        QVERIFY(!query.isValid());
+    }
+
+    /* Erase an existing QXmlItem binding with another QIODevice binding. */
+    {
+        QXmlQuery query;
+
+        query.bindVariable(QLatin1String("in"), QXmlItem(5));
+        query.setQuery(QLatin1String("$in"));
+        QVERIFY(query.isValid());
+
+        query.bindVariable(QLatin1String("in"), 0);
+        QVERIFY(!query.isValid());
+    }
+}
+
+/*!
+ Bind a variable, evaluate, bind with a different value but same type, and evaluate again.
+ */
+void tst_QXmlQuery::rebindVariableSameType() const
+{
+    QXmlQuery query;
+    MessageSilencer messageHandler;
+    query.setMessageHandler(&messageHandler);
+
+    query.bindVariable(QLatin1String("externalVariable"), QXmlItem(3));
+
+    {
+        QFile queryFile(QLatin1String(queriesDirectory) + QString::fromLatin1("externalVariable.xq"));
+        QVERIFY(queryFile.open(QIODevice::ReadOnly));
+        query.setQuery(&queryFile);
+    }
+
+    QVERIFY(query.isValid());
+
+    {
+        QByteArray result;
+        QBuffer buffer(&result);
+        QVERIFY(buffer.open(QIODevice::ReadWrite));
+
+        QXmlSerializer serializer(query, &buffer);
+        QVERIFY(query.evaluateTo(&serializer));
+
+        QCOMPARE(result, QByteArray("3 6<e>3</e>false"));
+    }
+
+    {
+        query.bindVariable(QLatin1String("externalVariable"), QXmlItem(5));
+        QByteArray result;
+        QBuffer buffer(&result);
+        QVERIFY(buffer.open(QIODevice::ReadWrite));
+
+        QXmlSerializer serializer(query, &buffer);
+        QVERIFY(query.evaluateTo(&serializer));
+
+        QCOMPARE(result, QByteArray("5 8<e>5</e>false"));
+    }
+
+}
+
+void tst_QXmlQuery::rebindVariableDifferentType() const
+{
+    /* Rebind QXmlItem variable with QXmlItem variable. */
+    {
+        QXmlQuery query;
+        query.bindVariable(QLatin1String("in"), QXmlItem(3));
+        query.setQuery(QLatin1String("$in"));
+        QVERIFY(query.isValid());
+
+        query.bindVariable(QLatin1String("in"), QXmlItem("A string"));
+        QVERIFY(!query.isValid());
+    }
+
+    /* Rebind QIODevice variable with QXmlItem variable. */
+    {
+        QXmlQuery query;
+        QBuffer buffer;
+        buffer.setData(QByteArray("<e/>"));
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+        query.bindVariable(QLatin1String("in"), &buffer);
+        query.setQuery(QLatin1String("$in"));
+        QVERIFY(query.isValid());
+
+        query.bindVariable(QLatin1String("in"), QXmlItem("A string"));
+        QVERIFY(!query.isValid());
+    }
+
+    /* Rebind QXmlItem variable with QIODevice variable. The type of the
+     * variable changes, so a recompile is necessary. */
+    {
+        QXmlQuery query;
+
+        query.bindVariable(QLatin1String("in"), QXmlItem(QLatin1String("A string")));
+        query.setQuery(QLatin1String("$in"));
+        QVERIFY(query.isValid());
+
+        QBuffer buffer;
+        buffer.setData(QByteArray("<e/>"));
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+        query.bindVariable(QLatin1String("in"), &buffer);
+        QVERIFY(!query.isValid());
+    }
+}
+
+void tst_QXmlQuery::rebindVariableWithNullItem() const
+{
+    QXmlQuery query;
+
+    query.bindVariable(QLatin1String("name"), QXmlItem(5));
+    query.bindVariable(QLatin1String("name"), QXmlItem());
+}
+
+void tst_QXmlQuery::constCorrectness() const
+{
+    QXmlResultItems result;
+    QXmlQuery tmp;
+    tmp.setQuery(QLatin1String("1")); /* Just so we have a valid query. */
+    const QXmlQuery query(tmp);
+
+    /* These functions should be const. */
+    query.isValid();
+    query.evaluateTo(&result);
+    query.namePool();
+    query.uriResolver();
+    query.messageHandler();
+
+    {
+        QString dummyString;
+        QTextStream dummyStream(&dummyString);
+        PushBaseliner dummy(dummyStream, query.namePool());
+        query.evaluateTo(&dummy);
+    }
+}
+
+void tst_QXmlQuery::objectSize() const
+{
+    /* We have a d pointer. */
+    QCOMPARE(sizeof(QXmlQuery), sizeof(void *));
+}
+
+void tst_QXmlQuery::setUriResolver() const
+{
+    /* Set a null resolver, and make sure it can take a const pointer. */
+    {
+        QXmlQuery query;
+        query.setUriResolver(static_cast<const QAbstractUriResolver *>(0));
+        QCOMPARE(query.uriResolver(), static_cast<const QAbstractUriResolver *>(0));
+    }
+
+    {
+        TestURIResolver resolver;
+        QXmlQuery query;
+        query.setUriResolver(&resolver);
+        QCOMPARE(query.uriResolver(), &resolver);
+    }
+}
+
+void tst_QXmlQuery::uriResolver() const
+{
+    /* Check default value. */
+    {
+        QXmlQuery query;
+        QCOMPARE(query.uriResolver(), static_cast<const QAbstractUriResolver *>(0));
+    }
+}
+
+void tst_QXmlQuery::messageXML() const
+{
+    QXmlQuery query;
+
+    MessageValidator messageValidator;
+    query.setMessageHandler(&messageValidator);
+
+    query.setQuery(QLatin1String("1basicSyntaxError"));
+
+    const QRegExp removeFilename(QLatin1String("Location: file:.*\\#"));
+    QVERIFY(removeFilename.isValid());
+
+    QVERIFY(messageValidator.success());
+    QCOMPARE(messageValidator.received().remove(removeFilename),
+             QString::fromLatin1("Type:3\n"
+                                 "Description: <html xmlns='http://www.w3.org/1999/xhtml/'><body><p>syntax error, unexpected unknown keyword</p></body></html>\n"
+                                 "Identifier: http://www.w3.org/2005/xqt-errors#XPST0003\n"
+                                 "1,1"));
+}
+
+/*!
+  1. Allocate QXmlResultItems
+  2. Allocate QXmlQuery
+  3. evaluate to the QXmlResultItems instance
+  4. Dellocate the QXmlQuery instance
+  5. Ensure QXmlResultItems works
+ */
+void tst_QXmlQuery::resultItemsDeallocatedQuery() const
+{
+    QXmlResultItems result;
+
+    {
+        QXmlQuery query;
+        query.setQuery(QLatin1String("1, 2, xs:integer(<e>3</e>)"));
+        query.evaluateTo(&result);
+    }
+
+    QCOMPARE(result.next().toAtomicValue(), QVariant(1));
+    QCOMPARE(result.next().toAtomicValue(), QVariant(2));
+    QCOMPARE(result.next().toAtomicValue(), QVariant(3));
+    QVERIFY(result.next().isNull());
+    QVERIFY(!result.hasError());
+}
+
+/*!
+  1. Bind variable with bindVariable()
+  2. setQuery that has 'declare variable' with same name.
+  3. Ensure the value inside the query is used. We don't guarantee this behavior
+     but that's what we lock.
+ */
+void tst_QXmlQuery::shadowedVariables() const
+{
+    QXmlQuery query;
+    query.bindVariable("varName", QXmlItem(3));
+    query.setQuery(QLatin1String("declare variable $varName := 5; $varName"));
+
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+
+    QCOMPARE(result.next().toAtomicValue(), QVariant(5));
+}
+
+void tst_QXmlQuery::setFocusQXmlItem() const
+{
+    /* Make sure we can take a const reference. */
+    {
+        QXmlQuery query;
+        const QXmlItem item;
+        query.setFocus(item);
+    }
+
+    // TODO evaluate with atomic value, check type
+    // TODO evaluate with node, check type
+    // TODO ensure that setFocus() triggers query recompilation, as appropriate.
+    // TODO let the focus be undefined, call isvalid, call evaluate anyway
+    // TODO let the focus be undefined, call evaluate directly
+}
+
+void tst_QXmlQuery::setFocusQUrl() const
+{
+    /* Load a focus which isn't well-formed. */
+    {
+        QXmlQuery query;
+        MessageSilencer silencer;
+
+        query.setMessageHandler(&silencer);
+
+        QVERIFY(!query.setFocus(QUrl(QLatin1String("data/notWellformed.xml"))));
+    }
+
+    /* Ensure the same URI resolver is used. */
+    {
+        QXmlQuery query(QXmlQuery::XSLT20);
+
+        const TestURIResolver resolver(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/documentElement.xml"))));
+        query.setUriResolver(&resolver);
+
+        QVERIFY(query.setFocus(QUrl(QLatin1String("arbitraryURI"))));
+        query.setQuery(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/copyWholeDocument.xsl"))));
+        QVERIFY(query.isValid());
+
+        QBuffer result;
+        QVERIFY(result.open(QIODevice::ReadWrite));
+        QXmlSerializer serializer(query, &result);
+        query.evaluateTo(&serializer);
+
+        QCOMPARE(result.data(), QByteArray("<doc/>"));
+    }
+
+    // TODO ensure that the focus type doesn't change from XSLT20 on the main instance.
+}
+
+/*!
+  This code poses a challenge wrt. to internal caching.
+ */
+void tst_QXmlQuery::setFocusQIODevice() const
+{
+    QXmlQuery query;
+
+    {
+        QBuffer focus;
+        focus.setData(QByteArray("<e>abc</e>"));
+        QVERIFY(focus.open(QIODevice::ReadOnly));
+        query.setFocus(&focus);
+        query.setQuery(QLatin1String("string()"));
+        QVERIFY(query.isValid());
+
+        QString output;
+        query.evaluateTo(&output);
+
+        QCOMPARE(output, QString::fromLatin1("abc\n"));
+    }
+
+    /* Set a new focus, make sure it changes & works. */
+    {
+        QBuffer focus2;
+        focus2.setData(QByteArray("<e>abc2</e>"));
+        QVERIFY(focus2.open(QIODevice::ReadOnly));
+        query.setFocus(&focus2);
+        QVERIFY(query.isValid());
+
+        QString output;
+        query.evaluateTo(&output);
+
+        QCOMPARE(output, QString::fromLatin1("abc2\n"));
+    }
+}
+
+/*!
+ Since we internally use variable bindings for implementing the focus, we need
+ to make sure we don't clash in this area.
+*/
+void tst_QXmlQuery::setFocusQIODeviceAvoidVariableClash() const
+{
+    QBuffer buffer;
+    buffer.setData("<e>focus</e>");
+    QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+    /* First we bind the variable name, then the focus. */
+    {
+        QXmlQuery query;
+        query.bindVariable(QString(QLatin1Char('u')), QVariant(1));
+        query.setFocus(&buffer);
+        query.setQuery(QLatin1String("string()"));
+
+        QString out;
+        query.evaluateTo(&out);
+
+        QCOMPARE(out, QString::fromLatin1("focus\n"));
+    }
+
+    /* First we bind the focus, then the variable name. */
+    {
+        QXmlQuery query;
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+        query.setFocus(&buffer);
+        query.bindVariable(QString(QLatin1Char('u')), QVariant(1));
+        query.setQuery(QLatin1String("string()"));
+
+        QString out;
+        query.evaluateTo(&out);
+
+        QCOMPARE(out, QString::fromLatin1("focus\n"));
+    }
+}
+
+void tst_QXmlQuery::setFocusQIODeviceFailure() const
+{
+    /* A not well-formed input document. */
+    {
+        QXmlQuery query;
+
+        MessageSilencer silencer;
+        query.setMessageHandler(&silencer);
+
+        QBuffer input;
+        input.setData("<e");
+        QVERIFY(input.open(QIODevice::ReadOnly));
+
+        QCOMPARE(query.setFocus(&input), false);
+    }
+}
+
+void tst_QXmlQuery::setFocusQString() const
+{
+    QXmlQuery query;
+
+    /* Basic use of focus. */
+    {
+        QVERIFY(query.setFocus(QLatin1String("<e>textNode</e>")));
+        query.setQuery(QLatin1String("string()"));
+        QVERIFY(query.isValid());
+        QString out;
+        query.evaluateTo(&out);
+        QCOMPARE(out, QString::fromLatin1("textNode\n"));
+    }
+
+    /* Set to a new focus, make sure it changes and works. */
+    {
+        QVERIFY(query.setFocus(QLatin1String("<e>newFocus</e>")));
+        QString out;
+        query.evaluateTo(&out);
+        QCOMPARE(out, QString::fromLatin1("newFocus\n"));
+    }
+}
+
+void tst_QXmlQuery::setFocusQStringFailure() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+
+    query.setMessageHandler(&silencer);
+    QVERIFY(!query.setFocus(QLatin1String("<notWellformed")));
+
+    /* Let's try the slight special case of a null string. */
+    QVERIFY(!query.setFocus(QString()));
+}
+
+void tst_QXmlQuery::setFocusQStringSignature() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    const QString argument;
+    /* We should take a const ref. */
+    query.setFocus(argument);
+
+    /* We should return a bool. */
+    static_cast<bool>(query.setFocus(QString()));
+}
+
+void tst_QXmlQuery::setFocusQIODeviceTriggerWarnings() const
+{
+    /* A null pointer. */
+    {
+        QXmlQuery query;
+
+        QTest::ignoreMessage(QtWarningMsg, "A null QIODevice pointer cannot be passed.");
+        QCOMPARE(query.setFocus(static_cast<QIODevice *>(0)), false);
+    }
+
+    /* A non opened-device. */
+    {
+        QXmlQuery query;
+
+        QBuffer notReadable;
+        QVERIFY(!notReadable.isReadable());
+
+        QTest::ignoreMessage(QtWarningMsg, "The device must be readable.");
+        QCOMPARE(query.setFocus(&notReadable), false);
+    }
+}
+
+void tst_QXmlQuery::fnDocNetworkAccessSuccess() const
+{
+#if defined(Q_OS_WINCE) && !defined(_X86_)
+    QStringList testsToSkip;
+    testsToSkip << "http scheme" << "ftp scheme";
+    if (testsToSkip.contains(QTest::currentDataTag()))
+        QSKIP("Network tests are currently unsupported on Windows CE.", SkipSingle);
+#endif
+
+    QFETCH(QUrl, uriToOpen);
+    QFETCH(QByteArray, expectedOutput);
+
+    if(!uriToOpen.isValid())
+        qDebug() << "uriToOpen:" << uriToOpen;
+
+    QVERIFY(uriToOpen.isValid());
+
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("uri"), QVariant(uriToOpen));
+    query.setQuery(QLatin1String("declare variable $uri external;\ndoc($uri)"));
+    QVERIFY(query.isValid());
+
+    QByteArray result;
+    QBuffer buffer(&result);
+    QVERIFY(buffer.open(QIODevice::WriteOnly));
+
+    QXmlSerializer serializer(query, &buffer);
+    QVERIFY(query.evaluateTo(&serializer));
+
+    QCOMPARE(result, expectedOutput);
+}
+
+void tst_QXmlQuery::fnDocNetworkAccessSuccess_data() const
+{
+    QTest::addColumn<QUrl>("uriToOpen");
+    QTest::addColumn<QByteArray>("expectedOutput");
+
+    QTest::newRow("file scheme")
+        << inputFileAsURI(QLatin1String(SRCDIR "input.xml"))
+        << QByteArray("<!-- This is just a file for testing. --><input/>");
+
+    QTest::newRow("data scheme with ASCII")
+        /* QUrl::toPercentEncoding(QLatin1String("<e/>")) yields "%3Ce%2F%3E". */
+        << QUrl::fromEncoded("data:application/xml,%3Ce%2F%3E")
+        << QByteArray("<e/>");
+
+    QTest::newRow("data scheme with ASCII no MIME type")
+        << QUrl::fromEncoded("data:,%3Ce%2F%3E")
+        << QByteArray("<e/>");
+
+    QTest::newRow("data scheme with base 64")
+        << QUrl::fromEncoded("data:application/xml;base64,PGUvPg==")
+        << QByteArray("<e/>");
+
+    QTest::newRow("qrc scheme")
+        << QUrl::fromEncoded("qrc:/QXmlQueryTestData/data/oneElement.xml")
+        << QByteArray("<oneElement/>");
+
+    if(!m_testNetwork)
+        return;
+
+    QTest::newRow("http scheme")
+        << QUrl(QString("http://" + QtNetworkSettings::serverName() + "/qxmlquery/wellFormed.xml"))
+        << QByteArray("<!-- a comment --><e from=\"http\">Some Text</e>");
+
+    QTest::newRow("ftp scheme")
+        << QUrl(QString("ftp://" + QtNetworkSettings::serverName() + "/pub/qxmlquery/wellFormed.xml"))
+        << QByteArray("<!-- a comment --><e from=\"ftp\">Some Text</e>");
+
+}
+
+void tst_QXmlQuery::fnDocNetworkAccessFailure() const
+{
+    QFETCH(QUrl, uriToOpen);
+
+    QVERIFY(uriToOpen.isValid());
+
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+    query.bindVariable(QLatin1String("uri"), QVariant(uriToOpen));
+    query.setQuery(QLatin1String("declare variable $uri external;\ndoc($uri)"));
+    QVERIFY(query.isValid());
+
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+
+    while(!result.next().isNull())
+    {
+        /* Just loop until the end. */
+    }
+
+    // TODO do something that triggers a /timeout/.
+    QVERIFY(result.hasError());
+}
+
+void tst_QXmlQuery::fnDocNetworkAccessFailure_data() const
+{
+    QTest::addColumn<QUrl>("uriToOpen");
+
+    QTest::newRow("data scheme, not-well-formed")
+        << QUrl(QLatin1String("data:application/xml;base64,PGUvg==="));
+
+    QTest::newRow("file scheme, non-existant file")
+        << QUrl(QLatin1String("file:///example.com/does/notExist.xml"));
+
+    QTest::newRow("http scheme, file not found")
+        << QUrl(QLatin1String("http://www.example.com/does/not/exist.xml"));
+
+    QTest::newRow("http scheme, nonexistent host")
+        << QUrl(QLatin1String("http://this.host.does.not.exist.I.SWear"));
+
+    QTest::newRow("qrc scheme, not well-formed")
+        << QUrl(QLatin1String("qrc:/QXmlQueryTestData/notWellformed.xml"));
+
+    QTest::newRow("'qrc:/', non-existing file")
+        << QUrl(QLatin1String(":/QXmlQueryTestData/data/thisFileDoesNotExist.xml"));
+
+    QTest::newRow("':/', this scheme is not supported")
+        << QUrl(QLatin1String(":/QXmlQueryTestData/data/notWellformed.xml"));
+
+    if(!m_testNetwork)
+        return;
+
+    QTest::newRow("http scheme, not well-formed")
+        << QUrl(QString("http://" + QtNetworkSettings::serverName() + "/qxmlquery/notWellformed.xml"));
+
+    QTest::newRow("https scheme, not well-formed")
+        << QUrl(QString("https://" + QtNetworkSettings::serverName() + "/qxmlquery/notWellformedViaHttps.xml"));
+
+    QTest::newRow("https scheme, nonexistent host")
+        << QUrl(QLatin1String("https://this.host.does.not.exist.I.SWear"));
+
+    QTest::newRow("ftp scheme, nonexistent host")
+        << QUrl(QLatin1String("ftp://this.host.does.not.exist.I.SWear"));
+
+    QTest::newRow("ftp scheme, not well-formed")
+        << QUrl(QString("ftp://" + QtNetworkSettings::serverName() + "/pub/qxmlquery/notWellFormed.xml"));
+}
+
+/*!
+  Create a network timeout from a QIODevice binding such
+  that we ensure we don't hang infinitely.
+ */
+void tst_QXmlQuery::fnDocOnQIODeviceTimeout() const
+{
+    if(!m_testNetwork)
+        return;
+
+    QTcpServer server;
+    server.listen(QHostAddress::LocalHost, 1088);
+
+    QTcpSocket client;
+    client.connectToHost("localhost", 1088);
+    QVERIFY(client.isReadable());
+
+    QXmlQuery query;
+
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.bindVariable(QLatin1String("inDevice"), &client);
+    query.setQuery(QLatin1String("declare variable $inDevice external;\ndoc($inDevice)"));
+    QVERIFY(query.isValid());
+
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+    QXmlItem next(result.next());
+
+    while(!next.isNull())
+    {
+        next = result.next();
+    }
+
+    QVERIFY(result.hasError());
+}
+
+/*!
+ When changing query, the static context must change too, such that
+ the source locations are updated.
+ */
+void tst_QXmlQuery::recompilationWithEvaluateToResultFailing() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("1 + 1")); /* An arbitrary valid query. */
+    QVERIFY(query.isValid()); /* Trigger query compilation. */
+
+    query.setQuery(QLatin1String("fn:doc('doesNotExist.example.com.xml')")); /* An arbitrary invalid query that make use of a source location. */
+    QVERIFY(query.isValid()); /* Trigger second compilation. */
+
+    QXmlResultItems items;
+    query.evaluateTo(&items);
+    items.next();
+    QVERIFY(items.hasError());
+}
+
+void tst_QXmlQuery::secondEvaluationWithEvaluateToResultFailing() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("1 + 1")); /* An arbitrary valid query. */
+    QVERIFY(query.isValid()); /* Trigger query compilation. */
+
+    query.setQuery(QLatin1String("fn:doc('doesNotExist.example.com.xml')")); /* An arbitrary invalid query that make use of a source location. */
+    /* We don't call isValid(). */
+QXmlResultItems items;
+    query.evaluateTo(&items);
+    items.next();
+    QVERIFY(items.hasError());
+}
+
+/*!
+ Compilation is triggered in the evaluation function due to no call to QXmlQuery::isValid().
+ */
+void tst_QXmlQuery::recompilationWithEvaluateToReceiver() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("1 + 1")); /* An arbitrary valid query. */
+    QVERIFY(query.isValid()); /* Trigger query compilation. */
+
+    query.setQuery(QLatin1String("fn:doc('doesNotExist.example.com.xml')")); /* An arbitrary invalid query that make use of a source location. */
+    /* We don't call isValid(). */
+
+    QByteArray dummy;
+    QBuffer buffer(&dummy);
+    buffer.open(QIODevice::WriteOnly);
+
+    QXmlSerializer serializer(query, &buffer);
+
+    QVERIFY(!query.evaluateTo(&serializer));
+}
+
+void tst_QXmlQuery::evaluateToQStringListOnInvalidQuery() const
+{
+    MessageSilencer silencer;
+
+    /* Invoke on a default constructed object. */
+    {
+        QXmlQuery query;
+        QStringList out;
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on a syntactically invalid query. */
+    {
+        QXmlQuery query;
+        QStringList out;
+        MessageSilencer silencer;
+
+        query.setMessageHandler(&silencer);
+        query.setQuery(QLatin1String("1 + "));
+
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on a query with the wrong type, one atomic. */
+    {
+        QXmlQuery query;
+        QStringList out;
+
+        query.setQuery(QLatin1String("1"));
+        query.setMessageHandler(&silencer);
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on a query with the wrong type, one element. */
+    {
+        QXmlQuery query;
+        QStringList out;
+
+        query.setQuery(QLatin1String("<e/>"));
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Invoke on a query with the wrong type, mixed nodes & atomics. */
+    {
+        QXmlQuery query;
+        QStringList out;
+
+        query.setQuery(QLatin1String("<e/>, 1, 'a string'"));
+        query.setMessageHandler(&silencer);
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* Evaluate the empty sequence. */
+    {
+        QXmlQuery query;
+        QStringList out;
+
+        query.setQuery(QLatin1String("()"));
+        QVERIFY(!query.evaluateTo(&out));
+        QVERIFY(out.isEmpty());
+    }
+}
+
+void tst_QXmlQuery::evaluateToQStringList() const
+{
+    QFETCH(QString, queryString);
+    QFETCH(QStringList, expectedOutput);
+
+    QXmlQuery query;
+    query.setQuery(queryString);
+    QStringList out;
+    QVERIFY(query.isValid());
+
+    QVERIFY(query.evaluateTo(&out));
+
+    QCOMPARE(out, expectedOutput);
+}
+
+void tst_QXmlQuery::evaluateToQStringListTriggerWarnings() const
+{
+    QXmlQuery query;
+
+    QTest::ignoreMessage(QtWarningMsg, "A non-null callback must be passed.");
+    QCOMPARE(query.evaluateTo(static_cast<QStringList *>(0)),
+             false);
+}
+
+void tst_QXmlQuery::evaluateToQStringList_data() const
+{
+    QTest::addColumn<QString>("queryString");
+    QTest::addColumn<QStringList>("expectedOutput");
+
+    QTest::newRow("One atomic")
+        << QString::fromLatin1("(1 + 1) cast as xs:string")
+        << QStringList(QString::fromLatin1("2"));
+
+    {
+        QStringList expected;
+        expected << QLatin1String("2");
+        expected << QLatin1String("a string");
+
+        QTest::newRow("Two atomics")
+            << QString::fromLatin1("(1 + 1) cast as xs:string, 'a string'")
+            << expected;
+    }
+
+    QTest::newRow("A query which evaluates to sub-types of xs:string.")
+        << QString::fromLatin1("xs:NCName('NCName'), xs:normalizedString('  a b c   ')")
+        << (QStringList() << QString::fromLatin1("NCName")
+                          << QString::fromLatin1("  a b c   "));
+
+    QTest::newRow("A query which evaluates to two elements.")
+        << QString::fromLatin1("string(<e>theString1</e>), string(<e>theString2</e>)")
+        << (QStringList() << QString::fromLatin1("theString1")
+                          << QString::fromLatin1("theString2"));
+}
+
+/*!
+  Ensure that we don't automatically convert non-xs:string values.
+ */
+void tst_QXmlQuery::evaluateToQStringListNoConversion() const
+{
+    QXmlQuery query;
+    query.setQuery(QString::fromLatin1("<e/>"));
+    QVERIFY(query.isValid());
+    QStringList result;
+    QVERIFY(!query.evaluateTo(&result));
+}
+
+void tst_QXmlQuery::evaluateToQIODevice() const
+{
+    /* an XQuery, check that no indentation is performed. */
+    {
+        QBuffer out;
+        QVERIFY(out.open(QIODevice::ReadWrite));
+
+        QXmlQuery query;
+        query.setQuery(QLatin1String("<a><b/></a>"));
+        QVERIFY(query.isValid());
+        QVERIFY(query.evaluateTo(&out));
+        QCOMPARE(out.data(), QByteArray("<a><b/></a>"));
+    }
+}
+
+void tst_QXmlQuery::evaluateToQIODeviceTriggerWarnings() const
+{
+    QXmlQuery query;
+
+    QTest::ignoreMessage(QtWarningMsg, "The pointer to the device cannot be null.");
+    QCOMPARE(query.evaluateTo(static_cast<QIODevice *>(0)),
+             false);
+
+    QBuffer buffer;
+
+    QTest::ignoreMessage(QtWarningMsg, "The device must be writable.");
+    QCOMPARE(query.evaluateTo(&buffer),
+             false);
+}
+
+void tst_QXmlQuery::evaluateToQIODeviceSignature() const
+{
+    /* The function should be const. */
+    {
+        QBuffer out;
+        QVERIFY(out.open(QIODevice::ReadWrite));
+
+        const QXmlQuery query;
+
+        query.evaluateTo(&out);
+    }
+}
+
+void tst_QXmlQuery::evaluateToQIODeviceOnInvalidQuery() const
+{
+    QBuffer out;
+    QVERIFY(out.open(QIODevice::WriteOnly));
+
+    /* On syntactically invalid query. */
+    {
+        QXmlQuery query;
+        MessageSilencer silencer;
+        query.setMessageHandler(&silencer);
+        query.setQuery(QLatin1String("1 +"));
+        QVERIFY(!query.isValid());
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+    /* On null QXmlQuery instance. */
+    {
+        QXmlQuery query;
+        QVERIFY(!query.evaluateTo(&out));
+    }
+
+}
+
+void tst_QXmlQuery::setQueryQIODeviceQUrl() const
+{
+    /* Basic test. */
+    {
+        QBuffer buffer;
+        buffer.setData("1, 2, 2 + 1");
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+        QXmlQuery query;
+        query.setQuery(&buffer);
+        QVERIFY(query.isValid());
+
+        QXmlResultItems result;
+        query.evaluateTo(&result);
+        QCOMPARE(result.next().toAtomicValue(), QVariant(1));
+        QCOMPARE(result.next().toAtomicValue(), QVariant(2));
+        QCOMPARE(result.next().toAtomicValue(), QVariant(3));
+        QVERIFY(result.next().isNull());
+        QVERIFY(!result.hasError());
+    }
+
+    /* Set query that is invalid. */
+    {
+        QBuffer buffer;
+        buffer.setData("1, ");
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+        QXmlQuery query;
+        MessageSilencer silencer;
+        query.setMessageHandler(&silencer);
+        query.setQuery(&buffer);
+        QVERIFY(!query.isValid());
+    }
+
+    /* Check that the base URI passes through. */
+    {
+        QBuffer buffer;
+        buffer.setData("string(static-base-uri())");
+        QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+        QXmlQuery query;
+        query.setQuery(&buffer, QUrl::fromEncoded("http://www.example.com/QIODeviceQUrl"));
+        QVERIFY(query.isValid());
+
+        QStringList result;
+        query.evaluateTo(&result);
+        QCOMPARE(result, QStringList(QLatin1String("http://www.example.com/QIODeviceQUrl")));
+    }
+}
+
+void tst_QXmlQuery::setQueryQIODeviceQUrlTriggerWarnings() const
+{
+    QXmlQuery query;
+    QTest::ignoreMessage(QtWarningMsg, "A null QIODevice pointer cannot be passed.");
+    query.setQuery(0);
+
+    QBuffer buffer;
+    QTest::ignoreMessage(QtWarningMsg, "The device must be readable.");
+    query.setQuery(&buffer);
+}
+
+void tst_QXmlQuery::setQueryQString() const
+{
+    /* Basic test. */
+    {
+        QXmlQuery query;
+        query.setQuery(QLatin1String("1, 2, 2 + 1"));
+        QVERIFY(query.isValid());
+
+        QXmlResultItems result;
+        query.evaluateTo(&result);
+        QCOMPARE(result.next().toAtomicValue(), QVariant(1));
+        QCOMPARE(result.next().toAtomicValue(), QVariant(2));
+        QCOMPARE(result.next().toAtomicValue(), QVariant(3));
+        QVERIFY(result.next().isNull());
+        QVERIFY(!result.hasError());
+    }
+
+    /* Set query that is invalid. */
+    {
+        MessageSilencer silencer;
+        QXmlQuery query;
+        query.setMessageHandler(&silencer);
+        query.setQuery(QLatin1String("1, "));
+        QVERIFY(!query.isValid());
+    }
+
+    /* Check that the base URI passes through. */
+    {
+        QXmlQuery query;
+        query.setQuery(QLatin1String("string(static-base-uri())"), QUrl::fromEncoded("http://www.example.com/QIODeviceQUrl"));
+        QVERIFY(query.isValid());
+
+        QStringList result;
+        query.evaluateTo(&result);
+        QCOMPARE(result, QStringList(QLatin1String("http://www.example.com/QIODeviceQUrl")));
+    }
+}
+
+void tst_QXmlQuery::setQueryQUrlSuccess() const
+{
+#if defined(Q_OS_WINCE) && !defined(_X86_)
+    QStringList testsToSkip;
+    testsToSkip << "A valid query via the ftp scheme" << "A valid query via the http scheme";
+    if (testsToSkip.contains(QTest::currentDataTag()))
+        QSKIP("Network tests are currently unsupported on Windows CE.", SkipSingle);
+#endif
+
+    QFETCH(QUrl, queryURI);
+    QFETCH(QByteArray, expectedOutput);
+
+    QVERIFY(queryURI.isValid());
+
+    QXmlQuery query;
+
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(queryURI);
+    QVERIFY(query.isValid());
+
+    QByteArray out;
+    QBuffer buffer(&out);
+    QVERIFY(buffer.open(QIODevice::WriteOnly));
+    QXmlSerializer serializer(query, &buffer);
+
+    query.evaluateTo(&serializer);
+    QCOMPARE(out, expectedOutput);
+}
+
+void tst_QXmlQuery::setQueryQUrlSuccess_data() const
+{
+    QTest::addColumn<QUrl>("queryURI");
+    QTest::addColumn<QByteArray>("expectedOutput");
+
+    QTest::newRow("A valid query via the data scheme")
+        << QUrl::fromEncoded("data:application/xml,1%20%2B%201") /* "1 + 1" */
+        << QByteArray("2");
+
+    QTest::newRow("A valid query via the file scheme")
+        << QUrl::fromLocalFile(inputFile(QLatin1String(queriesDirectory) + QLatin1String("onePlusOne.xq")))
+        << QByteArray("2");
+
+    if(!m_testNetwork)
+        return;
+
+    QTest::newRow("A valid query via the ftp scheme")
+        << QUrl::fromEncoded(QString("ftp://" + QtNetworkSettings::serverName() + "/pub/qxmlquery/viaFtp.xq").toLatin1())
+        << QByteArray("This was received via FTP");
+
+    QTest::newRow("A valid query via the http scheme")
+        << QUrl::fromEncoded(QString("http://" + QtNetworkSettings::serverName() + "/qxmlquery/viaHttp.xq").toLatin1())
+        << QByteArray("This was received via HTTP.");
+}
+
+void tst_QXmlQuery::setQueryQUrlFailSucceed() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("1 + 1"));
+    QVERIFY(query.isValid());
+
+    query.setQuery(QUrl::fromEncoded("file://example.com/does/not/exist"));
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::setQueryQUrlFailure() const
+{
+    QFETCH(QUrl, queryURI);
+
+    MessageSilencer silencer;
+
+    QXmlQuery query;
+    query.setMessageHandler(&silencer);
+    query.setQuery(queryURI);
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::setQueryQUrlFailure_data() const
+{
+    QTest::addColumn<QUrl>("queryURI");
+
+    QTest::newRow("Query via file:// that does not exist.")
+        << QUrl::fromEncoded("file://example.com/does/not/exist");
+
+    QTest::newRow("A query via file:// that is completely empty, but readable.")
+        << QUrl::fromLocalFile(QCoreApplication::applicationFilePath()).resolved(QUrl("../xmlpatterns/queries/completelyEmptyQuery.xq"));
+
+    {
+        const QString name(QLatin1String("nonReadableFile.xq"));
+        QFile outFile(name);
+        QVERIFY(outFile.open(QIODevice::WriteOnly));
+        outFile.write(QByteArray("1"));
+        outFile.close();
+        /* On some windows versions, this fails, so we don't check that this works with QVERIFY. */
+        outFile.setPermissions(QFile::Permissions(QFile::Permissions()));
+
+        QTest::newRow("Query via file:/ that does not have read permissions.")
+            << QUrl::fromLocalFile(QCoreApplication::applicationFilePath()).resolved(QUrl("nonReadableFile.xq"));
+    }
+
+    if(!m_testNetwork)
+        return;
+
+    QTest::newRow("Query via HTTP that does not exist.")
+        << QUrl::fromEncoded("http://example.com/NoQuery/ISWear");
+
+    /*
+    QTest::newRow("Query via FTP that does not exist.")
+        << QUrl::fromEncoded("ftp://example.com/NoQuery/ISWear");
+        */
+
+    QTest::newRow("A query via http:// that is completely empty, but readable.")
+        << QUrl::fromEncoded(QString(
+                "http://" + QtNetworkSettings::serverName() + "/qxmlquery/completelyEmptyQuery.xq").toLatin1());
+
+    QTest::newRow("A query via ftp:// that is completely empty, but readable.")
+        << QUrl::fromEncoded(QString(
+                "ftp://" + QtNetworkSettings::serverName() + "qxmlquery/completelyEmptyQuery.xq").toLatin1());
+
+}
+
+void tst_QXmlQuery::setQueryQUrlBaseURI() const
+{
+    QFETCH(QUrl, inputBaseURI);
+    QFETCH(QUrl, expectedBaseURI);
+
+    QXmlQuery query;
+
+    query.setQuery(QUrl(QLatin1String("qrc:/QXmlQueryTestData/queries/staticBaseURI.xq")), inputBaseURI);
+    QVERIFY(query.isValid());
+
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+    QCOMPARE(result.count(), 1);
+
+    if(qstrcmp(QTest::currentDataTag(), "Relative base URI") == 0)
+        checkBaseURI(QUrl(result.first()), QCoreApplication::applicationFilePath());
+    else
+        QCOMPARE(result.first(), expectedBaseURI.toString());
+}
+
+void tst_QXmlQuery::setQueryQUrlBaseURI_data() const
+{
+    QTest::addColumn<QUrl>("inputBaseURI");
+    QTest::addColumn<QUrl>("expectedBaseURI");
+
+    QTest::newRow("absolute HTTP")
+        << QUrl(QLatin1String("http://www.example.com/"))
+        << QUrl(QLatin1String("http://www.example.com/"));
+
+    QTest::newRow("None, so the query URI is used")
+        << QUrl()
+        << QUrl(QLatin1String("qrc:/QXmlQueryTestData/queries/staticBaseURI.xq"));
+
+    QTest::newRow("Relative base URI")
+        << QUrl(QLatin1String("../data/relative.uri"))
+        << QUrl();
+}
+
+/*!
+  1. Create a valid query.
+  2. Call setQuery(QUrl), with a query file that doesn't exist.
+  3. Verify that the query has changed state into invalid.
+ */
+void tst_QXmlQuery::setQueryWithNonExistentQUrlOnValidQuery() const
+{
+    QXmlQuery query;
+
+    MessageSilencer messageSilencer;
+    query.setMessageHandler(&messageSilencer);
+
+    query.setQuery(QLatin1String("1 + 1"));
+    QVERIFY(query.isValid());
+
+    query.setQuery(QUrl::fromEncoded("qrc:/QXmlQueryTestData/DOESNOTEXIST.xq"));
+    QVERIFY(!query.isValid());
+}
+
+/*!
+  1. Create a valid query.
+  2. Call setQuery(QUrl), with a query file that is invalid.
+  3. Verify that the query has changed state into invalid.
+ */
+void tst_QXmlQuery::setQueryWithInvalidQueryFromQUrlOnValidQuery() const
+{
+    QXmlQuery query;
+
+    MessageSilencer messageSilencer;
+    query.setMessageHandler(&messageSilencer);
+
+    query.setQuery(QLatin1String("1 + 1"));
+    QVERIFY(query.isValid());
+
+    query.setQuery(QUrl::fromEncoded("qrc:/QXmlQueryTestData/queries/syntaxError.xq"));
+    QVERIFY(!query.isValid());
+}
+
+/*!
+  This triggered two bugs:
+
+  - First, the DynamicContext wasn't assigned to QXmlResultItems, meaning it went out of
+    scope and therefore deallocated the document pool, and calls
+    to QXmlResultItems::next() would use dangling pointers.
+
+  - Conversion between QPatternist::Item and QXmlItem was incorrectly done, leading to nodes
+    being treated as atomic values, and subsequent crashes.
+
+ */
+void tst_QXmlQuery::retrieveNameFromQuery() const
+{
+    QFETCH(QString, queryString);
+    QFETCH(QString, expectedName);
+
+    QXmlQuery query;
+    query.setQuery(queryString);
+    QVERIFY(query.isValid());
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+
+    QVERIFY(!result.hasError());
+
+    const QXmlItem item(result.next());
+    QVERIFY(!result.hasError());
+    QVERIFY(!item.isNull());
+    QVERIFY(item.isNode());
+
+    const QXmlNodeModelIndex node(item.toNodeModelIndex());
+    QVERIFY(!node.isNull());
+
+    QCOMPARE(node.model()->name(node).localName(query.namePool()), expectedName);
+}
+
+void tst_QXmlQuery::retrieveNameFromQuery_data() const
+{
+    QTest::addColumn<QString>("queryString");
+    QTest::addColumn<QString>("expectedName");
+
+    QTest::newRow("Document-node")
+        << QString::fromLatin1("document{<elementName/>}")
+        << QString();
+
+    QTest::newRow("Element")
+        << QString::fromLatin1("document{<elementName/>}/*")
+        << QString::fromLatin1("elementName");
+}
+
+/*!
+ Binding a null QString leads to no variable binding, but an
+ empty non-null QString is possible.
+ */
+void tst_QXmlQuery::bindEmptyNullString() const
+{
+    MessageSilencer messageHandler;
+    QXmlQuery query;
+    query.setMessageHandler(&messageHandler);
+    query.setQuery(QLatin1String("declare variable $v external; $v"));
+    /* Here, we effectively pass an invalid QVariant. */
+    query.bindVariable(QLatin1String("v"), QVariant(QString()));
+    QVERIFY(!query.isValid());
+
+    QStringList result;
+    QVERIFY(!query.evaluateTo(&result));
+}
+
+void tst_QXmlQuery::bindEmptyString() const
+{
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("v"), QVariant(QString(QLatin1String(""))));
+    query.setQuery(QLatin1String("declare variable $v external; $v"));
+    QVERIFY(query.isValid());
+
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+    QStringList expected((QString()));
+    QCOMPARE(result, expected);
+}
+
+void tst_QXmlQuery::cleanupTestCase() const
+{
+    /* Remove a weird file we created. */
+    const QString name(QLatin1String("nonReadableFile.xq"));
+
+    if(QFile::exists(name))
+    {
+        QFile file(name);
+        QVERIFY(file.setPermissions(QFile::WriteOwner));
+        QVERIFY(file.remove());
+    }
+}
+
+void tst_QXmlQuery::declareUnavailableExternal() const
+{
+    QXmlQuery query;
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+    query.setQuery(QLatin1String("declare variable $var external;"
+                                 "1 + 1"));
+    /* We do not bind $var with QXmlQuery::bindVariable(). */
+    QVERIFY(!query.isValid());
+}
+
+/*!
+ This test triggers an assert in one of the cache iterator
+ with MSVC 2005 when compiled in debug mode.
+ */
+void tst_QXmlQuery::msvcCacheIssue() const
+{
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("externalVariable"), QXmlItem("Variable Value"));
+    query.setQuery(QUrl::fromLocalFile(QLatin1String(queriesDirectory) + QString::fromLatin1("externalVariableUsedTwice.xq")));
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+
+    QCOMPARE(result,
+             QStringList() << QString::fromLatin1("Variable Value") << QString::fromLatin1("Variable Value"));
+}
+
+void tst_QXmlQuery::unavailableExternalVariable() const
+{
+    QXmlQuery query;
+
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("declare variable $foo external; 1"));
+
+    QVERIFY(!query.isValid());
+}
+
+/*!
+ Ensure that setUriResolver() affects \c fn:doc() and \c fn:doc-available().
+ */
+void tst_QXmlQuery::useUriResolver() const
+{
+    class TestUriResolver : public QAbstractUriResolver
+                          , private TestFundament
+    {
+    public:
+        virtual QUrl resolve(const QUrl &relative,
+                             const QUrl &baseURI) const
+        {
+            Q_UNUSED(relative);
+            return baseURI.resolved(inputFile(QLatin1String(queriesDirectory) + QLatin1String("simpleDocument.xml")));
+        }
+    };
+
+    const TestUriResolver uriResolver;
+    QXmlQuery query;
+
+    query.setUriResolver(&uriResolver);
+    query.setQuery(QLatin1String("let $i := 'http://www.example.com/DoesNotExist'"
+                                 "return (string(doc($i)), doc-available($i))"));
+
+
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+
+    QVERIFY(!result.hasError());
+    QCOMPARE(result.next().toAtomicValue().toString(), QString::fromLatin1("text text node"));
+    QCOMPARE(result.next().toAtomicValue().toBool(), true);
+    QVERIFY(result.next().isNull());
+    QVERIFY(!result.hasError());
+}
+
+void tst_QXmlQuery::queryWithFocusAndVariable() const
+{
+    QXmlQuery query;
+    query.setFocus(QXmlItem(5));
+    query.bindVariable(QLatin1String("var"), QXmlItem(2));
+
+    query.setQuery(QLatin1String("string(. * $var)"));
+
+    QStringList result;
+
+    QVERIFY(query.evaluateTo(&result));
+
+    QCOMPARE(result, QStringList(QLatin1String("10")));
+}
+
+void tst_QXmlQuery::undefinedFocus() const
+{
+    QXmlQuery query;
+
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("."));
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::basicFocusUsage() const
+{
+    QXmlQuery query;
+
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setFocus(QXmlItem(5));
+    query.setQuery(QLatin1String("string(. * .)"));
+    QVERIFY(query.isValid());
+
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+
+    QCOMPARE(result, QStringList(QLatin1String("25")));
+}
+
+/*!
+  Triggers an ownership related crash.
+ */
+void tst_QXmlQuery::copyCheckMessageHandler() const
+{
+    QXmlQuery query;
+    QCOMPARE(query.messageHandler(), static_cast<QAbstractMessageHandler *>(0));
+
+    query.setQuery(QLatin1String("doc('qrc:/QXmlQueryTestData/data/oneElement.xml')"));
+    /* By now, we should have set the builtin message handler. */
+    const QAbstractMessageHandler *const messageHandler = query.messageHandler();
+    QVERIFY(messageHandler);
+
+    {
+        /* This copies QXmlQueryPrivate::m_ownerObject, and its destructor
+         * will delete it, and hence the builtin message handler attached to it. */
+        QXmlQuery copy(query);
+    }
+
+    QXmlResultItems result;
+    query.evaluateTo(&result);
+
+    while(!result.next().isNull())
+    {
+    }
+    QVERIFY(!result.hasError());
+}
+
+void tst_QXmlQuery::queryLanguage() const
+{
+    /* Check default value. */
+    {
+        const QXmlQuery query;
+        QCOMPARE(query.queryLanguage(), QXmlQuery::XQuery10);
+    }
+
+    /* Check default value of copies default instance. */
+    {
+        const QXmlQuery query1;
+        const QXmlQuery query2(query1);
+
+        QCOMPARE(query1.queryLanguage(), QXmlQuery::XQuery10);
+        QCOMPARE(query2.queryLanguage(), QXmlQuery::XQuery10);
+    }
+}
+
+void tst_QXmlQuery::queryLanguageSignature() const
+{
+    /* This getter should be const. */
+    QXmlQuery query;
+    query.queryLanguage();
+}
+
+void tst_QXmlQuery::enumQueryLanguage() const
+{
+    /* These enum values should be possible to OR for future plans. */
+    QCOMPARE(int(QXmlQuery::XQuery10), 1);
+    QCOMPARE(int(QXmlQuery::XSLT20), 2);
+    QCOMPARE(int(QXmlQuery::XmlSchema11IdentityConstraintSelector), 1024);
+    QCOMPARE(int(QXmlQuery::XmlSchema11IdentityConstraintField), 2048);
+    QCOMPARE(int(QXmlQuery::XPath20), 4096);
+}
+
+void tst_QXmlQuery::setInitialTemplateNameQXmlName() const
+{
+    QXmlQuery query(QXmlQuery::XSLT20);
+    QXmlNamePool np(query.namePool());
+    const QXmlName name(np, QLatin1String("main"));
+
+    query.setInitialTemplateName(name);
+
+    QCOMPARE(query.initialTemplateName(), name);
+
+    query.setQuery(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/namedTemplate.xsl"))));
+    QVERIFY(query.isValid());
+
+    QBuffer result;
+    QVERIFY(result.open(QIODevice::ReadWrite));
+    QXmlSerializer serializer(query, &result);
+    query.evaluateTo(&serializer);
+
+    QCOMPARE(result.data(), QByteArray("1 2 3 4 5"));
+
+    // TODO invoke a template which has required params.
+}
+
+void tst_QXmlQuery::setInitialTemplateNameQXmlNameSignature() const
+{
+    QXmlQuery query;
+    QXmlNamePool np(query.namePool());
+    const QXmlName name(np, QLatin1String("foo"));
+
+    /* The signature should take a const reference. */
+    query.setInitialTemplateName(name);
+}
+
+void tst_QXmlQuery::setInitialTemplateNameQString() const
+{
+    QXmlQuery query;
+    QXmlNamePool np(query.namePool());
+    query.setInitialTemplateName(QLatin1String("foo"));
+
+    QCOMPARE(query.initialTemplateName(), QXmlName(np, QLatin1String("foo")));
+}
+
+void tst_QXmlQuery::setInitialTemplateNameQStringSignature() const
+{
+    const QString name(QLatin1String("name"));
+    QXmlQuery query;
+
+    /* We should take a const reference. */
+    query.setInitialTemplateName(name);
+}
+
+void tst_QXmlQuery::initialTemplateName() const
+{
+    /* Check our default value. */
+    QXmlQuery query;
+    QCOMPARE(query.initialTemplateName(), QXmlName());
+    QVERIFY(query.initialTemplateName().isNull());
+}
+
+void tst_QXmlQuery::initialTemplateNameSignature() const
+{
+    const QXmlQuery query;
+    /* This should be a const member. */
+    query.initialTemplateName();
+}
+
+void tst_QXmlQuery::setNetworkAccessManager() const
+{
+
+    /* Ensure fn:doc() picks up the right QNetworkAccessManager. */
+    {
+        NetworkOverrider networkOverrider(QUrl(QLatin1String("tag:example.com:DOESNOTEXIST")),
+                                          QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/queries/simpleDocument.xml"))));
+
+        QXmlQuery query;
+        query.setNetworkAccessManager(&networkOverrider);
+        query.setQuery(QLatin1String("string(doc('tag:example.com:DOESNOTEXIST'))"));
+        QVERIFY(query.isValid());
+
+        QStringList result;
+        QVERIFY(query.evaluateTo(&result));
+
+        QCOMPARE(result, QStringList(QLatin1String("text text node")));
+    }
+
+    /* Ensure setQuery() is using the right network manager. */
+    {
+        NetworkOverrider networkOverrider(QUrl(QLatin1String("tag:example.com:DOESNOTEXIST")),
+                                          QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/queries/concat.xq"))));
+
+        QXmlQuery query;
+        query.setNetworkAccessManager(&networkOverrider);
+        query.setQuery(QUrl("tag:example.com:DOESNOTEXIST"));
+        QVERIFY(query.isValid());
+
+        QStringList result;
+        QVERIFY(query.evaluateTo(&result));
+
+        QCOMPARE(result, QStringList(QLatin1String("abcdef")));
+    }
+}
+void tst_QXmlQuery::networkAccessManagerSignature() const
+{
+    /* Const object. */
+    const QXmlQuery query;
+
+    /* The function should be const. */
+    query.networkAccessManager();
+}
+
+void tst_QXmlQuery::networkAccessManagerDefaultValue() const
+{
+    const QXmlQuery query;
+
+    QCOMPARE(query.networkAccessManager(), static_cast<QNetworkAccessManager *>(0));
+}
+
+void tst_QXmlQuery::networkAccessManager() const
+{
+    /* Test that we return the network manager that was set. */
+    {
+        QNetworkAccessManager manager;
+        QXmlQuery query;
+        query.setNetworkAccessManager(&manager);
+        QCOMPARE(query.networkAccessManager(), &manager);
+    }
+}
+
+/*!
+ \internal
+ \since 4.5
+
+  1. Load a document into QXmlQuery's document cache, by executing a query which does it.
+  2. Set a focus
+  3. Change query, to one which uses the focus
+  4. Evaluate
+
+ Used to crash.
+ */
+void tst_QXmlQuery::multipleDocsAndFocus() const
+{
+    QXmlQuery query;
+
+    /* We use string concatenation, since variable bindings might disturb what
+     * we're testing. */
+    query.setQuery(QLatin1String("string(doc('") +
+                   inputFile(QLatin1String(SRCDIR "../xmlpatterns/queries/simpleDocument.xml")) +
+                   QLatin1String("'))"));
+    query.setFocus(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/documentElement.xml"))));
+    query.setQuery(QLatin1String("string(.)"));
+
+    QStringList result;
+    QVERIFY(query.evaluateTo(&result));
+}
+
+/*!
+ \internal
+ \since 4.5
+
+ 1. Set a focus
+ 2. Set a query
+ 3. Evaluate
+ 4. Change focus
+ 5. Evaluate
+
+ Used to crash.
+ */
+void tst_QXmlQuery::multipleEvaluationsWithDifferentFocus() const
+{
+    QXmlQuery query;
+    QStringList result;
+
+    query.setFocus(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/documentElement.xml"))));
+    query.setQuery(QLatin1String("string(.)"));
+    QVERIFY(query.evaluateTo(&result));
+
+    query.setFocus(QUrl(inputFile(QLatin1String(SRCDIR "../xmlpatterns/stylesheets/documentElement.xml"))));
+    QVERIFY(query.evaluateTo(&result));
+}
+
+void tst_QXmlQuery::bindVariableQXmlQuery() const
+{
+    QFETCH(QString, query1);
+    QFETCH(QString, query2);
+    QFETCH(QString, expectedOutput);
+    QFETCH(bool, expectedSuccess);
+
+    MessageSilencer silencer;
+    QXmlQuery xmlQuery1;
+    xmlQuery1.setMessageHandler(&silencer);
+    xmlQuery1.setQuery(query1);
+
+    QXmlQuery xmlQuery2(xmlQuery1);
+    xmlQuery2.bindVariable("query1", xmlQuery1);
+    xmlQuery2.setQuery(query2);
+
+    QString output;
+    const bool querySuccess = xmlQuery2.evaluateTo(&output);
+
+    QCOMPARE(querySuccess, expectedSuccess);
+
+    if(querySuccess)
+        QCOMPARE(output, expectedOutput);
+}
+
+void tst_QXmlQuery::bindVariableQXmlQuery_data() const
+{
+    QTest::addColumn<QString>("query1");
+    QTest::addColumn<QString>("query2");
+    QTest::addColumn<QString>("expectedOutput");
+    QTest::addColumn<bool>("expectedSuccess");
+
+    QTest::newRow("First query has one atomic value.")
+            << "2"
+            << "1, $query1, 3"
+            << "1 2 3\n"
+            << true;
+
+    QTest::newRow("First query has two atomic values.")
+            << "2, 3"
+            << "1, $query1, 4"
+            << "1 2 3 4\n"
+            << true;
+
+    QTest::newRow("First query is a node.")
+            << "<e/>"
+            << "1, $query1, 3"
+            << "1<e/>3\n"
+            << true;
+
+    /* This is a good test, because it triggers the exception in the
+     * bindVariable() call, as supposed to when the actual evaluation is done.
+     */
+    QTest::newRow("First query has a dynamic error.")
+            << "error()"
+            << "1, $query1"
+            << QString() /* We don't care. */
+            << false;
+}
+
+void tst_QXmlQuery::bindVariableQStringQXmlQuerySignature() const
+{
+    QXmlQuery query1;
+    query1.setQuery("'dummy'");
+
+    QXmlQuery query2;
+    const QString name(QLatin1String("name"));
+
+    /* We should be able to take a const QXmlQuery reference. Evaluation never mutate
+     * QXmlQuery, and evaluation is what we do here. */
+    query2.bindVariable(name, const_cast<const QXmlQuery &>(query1));
+}
+
+void tst_QXmlQuery::bindVariableQXmlNameQXmlQuerySignature() const
+{
+    QXmlNamePool np;
+    QXmlQuery query1(np);
+    query1.setQuery("'dummy'");
+
+    QXmlQuery query2;
+    const QXmlName name(np, QLatin1String("name"));
+
+    /* We should be able to take a const QXmlQuery reference. Evaluation never mutate
+     * QXmlQuery, and evaluation is what we do here. */
+    query2.bindVariable(name, const_cast<const QXmlQuery &>(query1));
+}
+
+/*!
+  Check that the QXmlName is handled correctly.
+ */
+void tst_QXmlQuery::bindVariableQXmlNameQXmlQuery() const
+{
+    QXmlNamePool np;
+    QXmlQuery query1;
+    query1.setQuery(QLatin1String("1"));
+
+    QXmlQuery query2(np);
+    query2.bindVariable(QXmlName(np, QLatin1String("theName")), query1);
+    query2.setQuery("$theName");
+
+    QString result;
+    query2.evaluateTo(&result);
+
+    QCOMPARE(result, QString::fromLatin1("1\n"));
+}
+
+void tst_QXmlQuery::bindVariableQXmlQueryInvalidate() const
+{
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("name"), QVariant(1));
+    query.setQuery("$name");
+    QVERIFY(query.isValid());
+
+    QXmlQuery query2;
+    query2.setQuery("'query2'");
+
+    query.bindVariable(QLatin1String("name"), query);
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::unknownSourceLocation() const
+{
+    QBuffer b;
+    b.setData("<a><b/><b/></a>");
+    b.open(QIODevice::ReadOnly);
+
+    MessageSilencer silencer;
+    QXmlQuery query;
+    query.bindVariable(QLatin1String("inputDocument"), &b);
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(QLatin1String("doc($inputDocument)/a/(let $v := b/string() return if ($v) then $v else ())"));
+
+    QString output;
+    query.evaluateTo(&output);
+}
+
+void tst_QXmlQuery::identityConstraintSuccess() const
+{
+    QXmlQuery::QueryLanguage queryLanguage = QXmlQuery::XmlSchema11IdentityConstraintSelector;
+
+    /* We run this code for Selector and Field. */
+    for(int i = 0; i < 3; ++i)
+    {
+        QXmlNamePool namePool;
+        QXmlResultItems result;
+        QXmlItem node;
+
+        {
+            QXmlQuery nodeSource(namePool);
+            nodeSource.setQuery(QLatin1String("<e/>"));
+
+            nodeSource.evaluateTo(&result);
+            node = result.next();
+        }
+
+        /* Basic use:
+         * 1. The focus is undefined, but it's still valid.
+         * 2. We never evaluate. */
+        {
+            QXmlQuery query(queryLanguage);
+            query.setQuery(QLatin1String("a"));
+            QVERIFY(query.isValid());
+        }
+
+        /* Basic use:
+         * 1. The focus is undefined, but it's still valid.
+         * 2. We afterwards set the focus. */
+        {
+            QXmlQuery query(queryLanguage, namePool);
+            query.setQuery(QLatin1String("a"));
+            query.setFocus(node);
+            QVERIFY(query.isValid());
+        }
+
+        /* Basic use:
+         * 1. The focus is undefined, but it's still valid.
+         * 2. We afterwards set the focus.
+         * 3. We evaluate. */
+        {
+            QXmlQuery query(queryLanguage, namePool);
+            query.setQuery(QString(QLatin1Char('.')));
+            query.setFocus(node);
+            QVERIFY(query.isValid());
+
+            QString result;
+            QVERIFY(query.evaluateTo(&result));
+            QCOMPARE(result, QString::fromLatin1("<e/>\n"));
+        }
+
+        /* A slightly more complex Field. */
+        {
+            QXmlQuery query(queryLanguage);
+            query.setQuery(QLatin1String("* | .//xml:*/."));
+            QVERIFY(query.isValid());
+        }
+
+        /* @ is only allowed in Field. */
+        if(queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField)
+        {
+            QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintField);
+            query.setQuery(QLatin1String("@abc"));
+            QVERIFY(query.isValid());
+        }
+
+        /* Field allows attribute:: and child:: .*/
+        if(queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField)
+        {
+            QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintField);
+            query.setQuery(QLatin1String("attribute::name | child::name"));
+            QVERIFY(query.isValid());
+        }
+
+        /* Selector allows only child:: .*/
+        {
+            QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintSelector);
+            query.setQuery(QLatin1String("child::name"));
+            QVERIFY(query.isValid());
+        }
+
+        if(i == 0)
+            queryLanguage = QXmlQuery::XmlSchema11IdentityConstraintField;
+        else if(i == 1)
+            queryLanguage = QXmlQuery::XPath20;
+    }
+}
+
+Q_DECLARE_METATYPE(QXmlQuery::QueryLanguage);
+
+/*!
+ We just do some basic tests for boot strapping and sanity checking. The actual regression
+ testing is in the Schema suite.
+ */
+void tst_QXmlQuery::identityConstraintFailure() const
+{
+    QFETCH(QXmlQuery::QueryLanguage, queryLanguage);
+    QFETCH(QString, inputQuery);
+
+    QXmlQuery query(queryLanguage);
+    MessageSilencer silencer;
+    query.setMessageHandler(&silencer);
+
+    query.setQuery(inputQuery);
+    QVERIFY(!query.isValid());
+}
+
+void tst_QXmlQuery::identityConstraintFailure_data() const
+{
+    QTest::addColumn<QXmlQuery::QueryLanguage>("queryLanguage");
+    QTest::addColumn<QString>("inputQuery");
+
+    QTest::newRow("We don't have element constructors in identity constraint pattern, "
+                  "it's an XQuery feature(Selector).")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("<e/>");
+
+    QTest::newRow("We don't have functions in identity constraint pattern, "
+                  "it's an XPath feature(Selector).")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("current-time()");
+
+    QTest::newRow("We don't have element constructors in identity constraint pattern, "
+                  "it's an XQuery feature(Field).")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("<e/>");
+
+    QTest::newRow("We don't have functions in identity constraint pattern, "
+                  "it's an XPath feature(Field).")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("current-time()");
+
+    QTest::newRow("@attributeName is disallowed for the selector.")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("@abc");
+
+    QTest::newRow("attribute:: is disallowed for the selector.")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("attribute::name");
+
+    QTest::newRow("ancestor::name is disallowed for the selector.")
+        << QXmlQuery::XmlSchema11IdentityConstraintSelector
+        << QString::fromLatin1("ancestor::name");
+
+    QTest::newRow("ancestor::name is disallowed for the field.")
+        << QXmlQuery::XmlSchema11IdentityConstraintField
+        << QString::fromLatin1("ancestor::name");
+}
+
+QTEST_MAIN(tst_QXmlQuery)
+
+#include "tst_qxmlquery.moc"
+#else //QTEST_XMLPATTERNS
+QTEST_NOOP_MAIN
+#endif