| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include <QtTest/QtTest> |
| |
| #include <QAbstractMessageHandler> |
| #include <QAbstractUriResolver> |
| #include <QtNetwork/QNetworkAccessManager> |
| #include <QXmlName> |
| #include <QXmlSchema> |
| #include <QXmlSchemaValidator> |
| |
| #include "../qabstracturiresolver/TestURIResolver.h" |
| #include "../qxmlquery/MessageSilencer.h" |
| |
| /*! |
| \class tst_QXmlSchemaValidatorValidator |
| \internal |
| \brief Tests class QXmlSchemaValidator. |
| |
| This test is not intended for testing the engine, but the functionality specific |
| to the QXmlSchemaValidator class. |
| */ |
| class tst_QXmlSchemaValidator : public QObject |
| { |
| Q_OBJECT |
| |
| private Q_SLOTS: |
| void defaultConstructor() const; |
| void constructorQXmlNamePool() const; |
| void propertyInitialization() const; |
| void resetSchemaNamePool() const; |
| |
| void loadInstanceUrlSuccess() const; |
| void loadInstanceUrlFail() const; |
| void loadInstanceDeviceSuccess() const; |
| void loadInstanceDeviceFail() const; |
| void loadInstanceDataSuccess() const; |
| void loadInstanceDataFail() const; |
| |
| void networkAccessManagerSignature() const; |
| void networkAccessManagerDefaultValue() const; |
| void networkAccessManager() const; |
| |
| void messageHandlerSignature() const; |
| void messageHandlerDefaultValue() const; |
| void messageHandler() const; |
| |
| void uriResolverSignature() const; |
| void uriResolverDefaultValue() const; |
| void uriResolver() const; |
| |
| void unionCrash() const; |
| }; |
| |
| static QXmlSchema createValidSchema() |
| { |
| const QByteArray data( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |
| "<xsd:schema" |
| " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" |
| " xmlns=\"http://www.qt-project.org/xmlschematest\"" |
| " targetNamespace=\"http://www.qt-project.org/xmlschematest\"" |
| " version=\"1.0\"" |
| " elementFormDefault=\"qualified\">" |
| " <xsd:element name=\"myRoot\" type=\"xsd:string\"/>" |
| "</xsd:schema>" ); |
| |
| const QUrl documentUri("http://www.qt-project.org/xmlschematest"); |
| |
| QXmlSchema schema; |
| schema.load(data, documentUri); |
| |
| return schema; |
| } |
| |
| void tst_QXmlSchemaValidator::defaultConstructor() const |
| { |
| /* Allocate instance in different orders. */ |
| { |
| QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| } |
| |
| { |
| QXmlSchema schema1; |
| QXmlSchema schema2; |
| |
| QXmlSchemaValidator validator1(schema1); |
| QXmlSchemaValidator validator2(schema2); |
| } |
| |
| { |
| QXmlSchema schema; |
| |
| QXmlSchemaValidator validator1(schema); |
| QXmlSchemaValidator validator2(schema); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::propertyInitialization() const |
| { |
| /* Verify that properties set in the schema are used as default values for the validator */ |
| { |
| MessageSilencer handler; |
| TestURIResolver resolver; |
| QNetworkAccessManager manager; |
| |
| QXmlSchema schema; |
| schema.setMessageHandler(&handler); |
| schema.setUriResolver(&resolver); |
| schema.setNetworkAccessManager(&manager); |
| |
| QXmlSchemaValidator validator(schema); |
| QCOMPARE(validator.messageHandler(), static_cast<QAbstractMessageHandler *>(&handler)); |
| QCOMPARE(validator.uriResolver(), static_cast<const QAbstractUriResolver *>(&resolver)); |
| QCOMPARE(validator.networkAccessManager(), &manager); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::constructorQXmlNamePool() const |
| { |
| // test that the name pool from the schema is used by |
| // the schema validator as well |
| QXmlSchema schema; |
| |
| QXmlNamePool np = schema.namePool(); |
| |
| const QXmlName name(np, QLatin1String("localName"), |
| QLatin1String("http://example.com/"), |
| QLatin1String("prefix")); |
| |
| QXmlSchemaValidator validator(schema); |
| |
| QXmlNamePool np2(validator.namePool()); |
| QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/")); |
| QCOMPARE(name.localName(np2), QString::fromLatin1("localName")); |
| QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix")); |
| |
| // make sure namePool() is const |
| const QXmlSchemaValidator constValidator(schema); |
| np = constValidator.namePool(); |
| } |
| |
| void tst_QXmlSchemaValidator::resetSchemaNamePool() const |
| { |
| QXmlSchema schema1; |
| QXmlNamePool np1 = schema1.namePool(); |
| |
| const QXmlName name1(np1, QLatin1String("localName"), |
| QLatin1String("http://example.com/"), |
| QLatin1String("prefix")); |
| |
| QXmlSchemaValidator validator(schema1); |
| |
| { |
| QXmlNamePool compNamePool(validator.namePool()); |
| QCOMPARE(name1.namespaceUri(compNamePool), QString::fromLatin1("http://example.com/")); |
| QCOMPARE(name1.localName(compNamePool), QString::fromLatin1("localName")); |
| QCOMPARE(name1.prefix(compNamePool), QString::fromLatin1("prefix")); |
| } |
| |
| QXmlSchema schema2; |
| QXmlNamePool np2 = schema2.namePool(); |
| |
| const QXmlName name2(np2, QLatin1String("remoteName"), |
| QLatin1String("http://example.com/"), |
| QLatin1String("suffix")); |
| |
| // make sure that after re-setting the schema, the new namepool is used |
| validator.setSchema(schema2); |
| |
| { |
| QXmlNamePool compNamePool(validator.namePool()); |
| QCOMPARE(name2.namespaceUri(compNamePool), QString::fromLatin1("http://example.com/")); |
| QCOMPARE(name2.localName(compNamePool), QString::fromLatin1("remoteName")); |
| QCOMPARE(name2.prefix(compNamePool), QString::fromLatin1("suffix")); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceUrlSuccess() const |
| { |
| /* |
| TODO: put valid schema file on given url and enable test |
| const QXmlSchema schema(createValidSchema()); |
| const QUrl url("http://notavailable/"); |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(!validator.validate(url)); |
| */ |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceUrlFail() const |
| { |
| const QXmlSchema schema(createValidSchema()); |
| const QUrl url("http://notavailable/"); |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(!validator.validate(url)); |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceDeviceSuccess() const |
| { |
| const QXmlSchema schema(createValidSchema()); |
| |
| QByteArray data( "<myRoot xmlns=\"http://www.qt-project.org/xmlschematest\">Testme</myRoot>" ); |
| QBuffer buffer(&data); |
| buffer.open(QIODevice::ReadOnly); |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.validate(&buffer)); |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceDeviceFail() const |
| { |
| const QXmlSchema schema(createValidSchema()); |
| |
| QByteArray data( "<myRoot xmlns=\"http://www.qt-project.org/xmlschematest\">Testme</myRoot>" ); |
| QBuffer buffer(&data); |
| // a closed device can not be loaded |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(!validator.validate(&buffer)); |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceDataSuccess() const |
| { |
| const QXmlSchema schema(createValidSchema()); |
| |
| const QByteArray data( "<myRoot xmlns=\"http://www.qt-project.org/xmlschematest\">Testme</myRoot>" ); |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.validate(data)); |
| } |
| |
| void tst_QXmlSchemaValidator::loadInstanceDataFail() const |
| { |
| const QXmlSchema schema(createValidSchema()); |
| |
| // empty instance can not be loaded |
| const QByteArray data; |
| |
| QXmlSchemaValidator validator(schema); |
| QVERIFY(!validator.validate(data)); |
| } |
| |
| void tst_QXmlSchemaValidator::networkAccessManagerSignature() const |
| { |
| const QXmlSchema schema; |
| |
| /* Const object. */ |
| const QXmlSchemaValidator validator(schema); |
| |
| /* The function should be const. */ |
| validator.networkAccessManager(); |
| } |
| |
| void tst_QXmlSchemaValidator::networkAccessManagerDefaultValue() const |
| { |
| /* Test that the default value of network access manager is equal to the one from the schema. */ |
| { |
| const QXmlSchema schema; |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.networkAccessManager() == schema.networkAccessManager()); |
| } |
| |
| /* Test that the default value of network access manager is equal to the one from the schema. */ |
| { |
| QXmlSchema schema; |
| |
| QNetworkAccessManager manager; |
| schema.setNetworkAccessManager(&manager); |
| |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.networkAccessManager() == schema.networkAccessManager()); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::networkAccessManager() const |
| { |
| /* Test that we return the network access manager that was set. */ |
| { |
| QNetworkAccessManager manager; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setNetworkAccessManager(&manager); |
| QCOMPARE(validator.networkAccessManager(), &manager); |
| } |
| |
| /* Test that we return the network access manager that was set, even if the schema changed in between. */ |
| { |
| QNetworkAccessManager manager; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setNetworkAccessManager(&manager); |
| |
| const QXmlSchema schema2; |
| validator.setSchema(schema2); |
| |
| QCOMPARE(validator.networkAccessManager(), &manager); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::messageHandlerSignature() const |
| { |
| const QXmlSchema schema; |
| |
| /* Const object. */ |
| const QXmlSchemaValidator validator(schema); |
| |
| /* The function should be const. */ |
| validator.messageHandler(); |
| } |
| |
| void tst_QXmlSchemaValidator::messageHandlerDefaultValue() const |
| { |
| /* Test that the default value of message handler is equal to the one from the schema. */ |
| { |
| const QXmlSchema schema; |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.messageHandler() == schema.messageHandler()); |
| } |
| |
| /* Test that the default value of network access manager is equal to the one from the schema. */ |
| { |
| QXmlSchema schema; |
| |
| MessageSilencer handler; |
| schema.setMessageHandler(&handler); |
| |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.messageHandler() == schema.messageHandler()); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::messageHandler() const |
| { |
| /* Test that we return the message handler that was set. */ |
| { |
| MessageSilencer handler; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setMessageHandler(&handler); |
| QCOMPARE(validator.messageHandler(), static_cast<QAbstractMessageHandler *>(&handler)); |
| } |
| |
| /* Test that we return the message handler that was set, even if the schema changed in between. */ |
| { |
| MessageSilencer handler; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setMessageHandler(&handler); |
| |
| const QXmlSchema schema2; |
| validator.setSchema(schema2); |
| |
| QCOMPARE(validator.messageHandler(), static_cast<QAbstractMessageHandler *>(&handler)); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::uriResolverSignature() const |
| { |
| const QXmlSchema schema; |
| |
| /* Const object. */ |
| const QXmlSchemaValidator validator(schema); |
| |
| /* The function should be const. */ |
| validator.uriResolver(); |
| |
| /* Const object. */ |
| const TestURIResolver resolver; |
| |
| /* This should compile */ |
| QXmlSchema schema2; |
| schema2.setUriResolver(&resolver); |
| } |
| |
| void tst_QXmlSchemaValidator::uriResolverDefaultValue() const |
| { |
| /* Test that the default value of uri resolver is equal to the one from the schema. */ |
| { |
| const QXmlSchema schema; |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.uriResolver() == schema.uriResolver()); |
| } |
| |
| /* Test that the default value of uri resolver is equal to the one from the schema. */ |
| { |
| QXmlSchema schema; |
| |
| TestURIResolver resolver; |
| schema.setUriResolver(&resolver); |
| |
| const QXmlSchemaValidator validator(schema); |
| QVERIFY(validator.uriResolver() == schema.uriResolver()); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::uriResolver() const |
| { |
| /* Test that we return the uri resolver that was set. */ |
| { |
| TestURIResolver resolver; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setUriResolver(&resolver); |
| QCOMPARE(validator.uriResolver(), static_cast<const QAbstractUriResolver *>(&resolver)); |
| } |
| |
| /* Test that we return the uri resolver that was set, even if the schema changed in between. */ |
| { |
| TestURIResolver resolver; |
| |
| const QXmlSchema schema; |
| QXmlSchemaValidator validator(schema); |
| |
| validator.setUriResolver(&resolver); |
| |
| const QXmlSchema schema2; |
| validator.setSchema(schema2); |
| |
| QCOMPARE(validator.uriResolver(), static_cast<const QAbstractUriResolver *>(&resolver)); |
| } |
| } |
| |
| void tst_QXmlSchemaValidator::unionCrash() const |
| { |
| // Regression test for QTBUG-77620 (segfault on nullptr dereference). |
| const QString path = QFINDTESTDATA("testdata/"); |
| QXmlSchema schema; |
| |
| const QString filePath = path + QLatin1String("QTBUG-77620.xsd"); |
| |
| QFile file(filePath); |
| QVERIFY(file.open(QIODevice::ReadOnly)); |
| |
| schema.load(file.readAll(), QUrl(filePath)); |
| QVERIFY2(schema.isValid(), "Schema should be found valid."); |
| // Validate instance |
| QXmlSchemaValidator validator(schema); |
| QEXPECT_FAIL("", "QTBUG-77620: " // Fixed crash, but not underlying problem: |
| "the code fails to record the CUSTOM_KEY's primitive type as pattern_type", Continue); |
| QVERIFY2(validator.validate(QUrl(path + QLatin1String("QTBUG-77620.xml"))), |
| "Document should be found valid"); |
| } |
| |
| QTEST_MAIN(tst_QXmlSchemaValidator) |
| |
| #include "tst_qxmlschemavalidator.moc" |