diff options
Diffstat (limited to 'tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp')
-rw-r--r-- | tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp | 439 |
1 files changed, 405 insertions, 34 deletions
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 3cad03641b..b90d05b0fa 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QDirIterator> @@ -8,11 +8,12 @@ #include <QNetworkReply> #include <QNetworkRequest> #include <QTest> +#include <QtTest/private/qcomparisontesthelper_p.h> #include <QUrl> #include <QXmlStreamReader> #include <QBuffer> #include <QStack> -#include <QtGui/private/qzipreader_p.h> +#include <private/qzipreader_p.h> #include "qc14n.h" @@ -94,8 +95,8 @@ static QByteArray makeCanonical(const QString &filename, bool testIncremental = false) { QFile file(filename); - file.open(QIODevice::ReadOnly); - + if (!file.open(QIODevice::ReadOnly)) + qFatal("Could not open file %s", qPrintable(filename)); QXmlStreamReader reader; QByteArray buffer; @@ -542,6 +543,8 @@ public: private slots: void initTestCase(); void cleanupTestCase(); + void compareCompiles(); + void runTestSuite(); void reportFailures() const; void reportFailures_data(); void checkBaseline() const; @@ -569,6 +572,14 @@ private slots: void hasAttribute() const; void writeWithUtf8Codec() const; void writeWithStandalone() const; + void writeCharacters_data() const; + void writeCharacters() const; + void writeAttribute_data() const; + void writeAttribute() const; + void writeBadCharactersUtf8_data() const; + void writeBadCharactersUtf8() const; + void writeBadCharactersUtf16_data() const; + void writeBadCharactersUtf16() const; void entitiesAndWhitespace_1() const; void entitiesAndWhitespace_2() const; void testFalsePrematureError() const; @@ -581,12 +592,20 @@ private slots: void invalidStringCharacters_data() const; void invalidStringCharacters() const; void hasError() const; + void readBack_data() const; void readBack() const; void roundTrip() const; void roundTrip_data() const; + void test_fastScanName_data() const; + void test_fastScanName() const; void entityExpansionLimit() const; + void tokenErrorHandling_data() const; + void tokenErrorHandling() const; + void checkStreamNotationDeclarations() const; + void checkStreamEntityDeclarations() const; + private: static QByteArray readFile(const QString &filename); @@ -623,7 +642,22 @@ void tst_QXmlStream::initTestCase() QFile::remove(destinationPath); // copy will fail if file exists QVERIFY(QFile::copy(fileInfo.filePath(), destinationPath)); } +} + +void tst_QXmlStream::cleanupTestCase() +{ +} +void tst_QXmlStream::compareCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile<QXmlStreamAttribute>(); + QTestPrivate::testEqualityOperatorsCompile<QXmlStreamNamespaceDeclaration>(); + QTestPrivate::testEqualityOperatorsCompile<QXmlStreamNotationDeclaration>(); + QTestPrivate::testEqualityOperatorsCompile<QXmlStreamEntityDeclaration>(); +} + +void tst_QXmlStream::runTestSuite() +{ QFile file(m_tempDir.filePath(catalogFile)); QVERIFY2(file.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Failed to open the test suite catalog; %1").arg(file.fileName()))); @@ -631,10 +665,6 @@ void tst_QXmlStream::initTestCase() QVERIFY(m_handler.runTests(&file)); } -void tst_QXmlStream::cleanupTestCase() -{ -} - void tst_QXmlStream::reportFailures() const { QFETCH(bool, isError); @@ -645,7 +675,7 @@ void tst_QXmlStream::reportFailures() const void tst_QXmlStream::reportFailures_data() { - const int len = m_handler.failures.count(); + const int len = m_handler.failures.size(); QTest::addColumn<bool>("isError"); QTest::addColumn<QString>("description"); @@ -682,7 +712,7 @@ void tst_QXmlStream::checkBaseline_data() const QTest::addColumn<QString>("expected"); QTest::addColumn<QString>("output"); - const int len = m_handler.missedBaselines.count(); + const int len = m_handler.missedBaselines.size(); for(int i = 0; i < len; ++i) { @@ -711,7 +741,7 @@ void tst_QXmlStream::reportSuccess_data() const { QTest::addColumn<bool>("isError"); - const int len = m_handler.successes.count(); + const int len = m_handler.successes.size(); for (int i = 0; i < len; ++i) { const QByteArray testName = QByteArray::number(i) + ". " + m_handler.successes.at(i).toLatin1(); @@ -725,7 +755,8 @@ void tst_QXmlStream::reportSuccess_data() const QByteArray tst_QXmlStream::readFile(const QString &filename) { QFile file(filename); - file.open(QIODevice::ReadOnly); + if (!file.open(QIODevice::ReadOnly)) + qFatal("Could not open file %s", qPrintable(filename)); QXmlStreamReader reader; @@ -876,12 +907,17 @@ void tst_QXmlStream::addExtraNamespaceDeclarations() } { QXmlStreamReader xml(data); - xml.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("undeclared", "blabla")); - xml.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("undeclared_too", "foofoo")); + QXmlStreamNamespaceDeclaration undeclared("undeclared", "blabla"); + QXmlStreamNamespaceDeclaration undeclared_too("undeclared_too", "blabla"); + xml.addExtraNamespaceDeclaration(undeclared); + xml.addExtraNamespaceDeclaration(undeclared_too); while (!xml.atEnd()) { xml.readNext(); } QVERIFY2(!xml.hasError(), xml.errorString().toLatin1().constData()); + QT_TEST_EQUALITY_OPS(undeclared, undeclared_too, false); + undeclared = undeclared_too; + QT_TEST_EQUALITY_OPS(undeclared, undeclared_too, true); } } @@ -1137,6 +1173,10 @@ void tst_QXmlStream::readNextStartElement() const } QCOMPARE(amountOfB, 2); + + // well-formed document end follows + QVERIFY(!reader.readNextStartElement()); + QCOMPARE(reader.error(), QXmlStreamReader::NoError); } void tst_QXmlStream::readElementText() const @@ -1254,8 +1294,20 @@ void tst_QXmlStream::hasAttributeSignature() const void tst_QXmlStream::hasAttribute() const { - QXmlStreamReader reader(QLatin1String("<e xmlns:p='http://example.com/2' xmlns='http://example.com/' " - "attr1='value' attr2='value2' p:attr3='value3' emptyAttr=''><noAttributes/></e>")); + auto xml = QStringLiteral("<e" + " xmlns:p='http://example.com/2'" + " xmlns='http://example.com/'" + " attr1='value'" + " attr2='value2'" + " p:attr3='value3'" + " emptyAttr=''" + " atträbute='meep'" + " α='β'" + " >" + " <noAttributes/>" + "</e>"); + + QXmlStreamReader reader(xml); QCOMPARE(reader.readNext(), QXmlStreamReader::StartDocument); QCOMPARE(reader.readNext(), QXmlStreamReader::StartElement); @@ -1266,8 +1318,18 @@ void tst_QXmlStream::hasAttribute() const QVERIFY(atts.hasAttribute(QLatin1String("attr2"))); QVERIFY(atts.hasAttribute(QLatin1String("p:attr3"))); QVERIFY(atts.hasAttribute(QLatin1String("emptyAttr"))); + QVERIFY(atts.hasAttribute(QLatin1String("attr\xE4""bute"))); + // α is not representable in L1... QVERIFY(!atts.hasAttribute(QLatin1String("DOESNOTEXIST"))); + /* string literals (UTF-8/16) */ + QVERIFY(atts.hasAttribute(u8"atträbute")); + QVERIFY(atts.hasAttribute( u"atträbute")); + QVERIFY(atts.hasAttribute(u8"α")); + QVERIFY(atts.hasAttribute( u"α")); + QVERIFY(!atts.hasAttribute(u8"β")); + QVERIFY(!atts.hasAttribute( u"β")); + /* Test with an empty & null namespaces. */ QVERIFY(atts.hasAttribute(QString(), QLatin1String("attr2"))); /* A null string. */ QVERIFY(atts.hasAttribute(QLatin1String(""), QLatin1String("attr2"))); /* An empty string. */ @@ -1276,6 +1338,8 @@ void tst_QXmlStream::hasAttribute() const QVERIFY(atts.hasAttribute(QString::fromLatin1("attr1"))); QVERIFY(atts.hasAttribute(QString::fromLatin1("attr2"))); QVERIFY(atts.hasAttribute(QString::fromLatin1("p:attr3"))); + QVERIFY(atts.hasAttribute(QStringLiteral("atträbute"))); + QVERIFY(atts.hasAttribute(QStringLiteral("α"))); QVERIFY(atts.hasAttribute(QString::fromLatin1("emptyAttr"))); QVERIFY(!atts.hasAttribute(QString::fromLatin1("DOESNOTEXIST"))); @@ -1289,6 +1353,7 @@ void tst_QXmlStream::hasAttribute() const QVERIFY(!atts.hasAttribute(QLatin1String("WRONG_NAMESPACE"), QString::fromLatin1("attr3"))); /* Invoke on an QXmlStreamAttributes that has no attributes at all. */ + QCOMPARE(reader.readNext(), QXmlStreamReader::Characters); QCOMPARE(reader.readNext(), QXmlStreamReader::StartElement); const QXmlStreamAttributes &atts2 = reader.attributes(); @@ -1307,6 +1372,15 @@ void tst_QXmlStream::hasAttribute() const reader.readNext(); QVERIFY(!reader.hasError()); + + QXmlStreamAttribute attrValue1(QLatin1String("http://example.com/"), QString::fromLatin1("attr1")); + QXmlStreamAttribute attrValue2 = atts.at(0); + QT_TEST_EQUALITY_OPS(atts.at(0), QXmlStreamAttribute(), false); + QT_TEST_EQUALITY_OPS(atts.at(0), attrValue1, false); + QT_TEST_EQUALITY_OPS(atts.at(0), attrValue2, true); + QT_TEST_EQUALITY_OPS(attrValue1, attrValue2, false); + attrValue1 = attrValue2; + QT_TEST_EQUALITY_OPS(attrValue1, attrValue2, true); } void tst_QXmlStream::writeWithUtf8Codec() const @@ -1341,6 +1415,143 @@ void tst_QXmlStream::writeWithStandalone() const } } +static void writeCharacters_data_common() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("output"); + + QTest::newRow("empty") << QString() << QString(); + + // invalid content + QTest::newRow("null-character") << u"\0"_s << QString(); + QTest::newRow("vertical-tab") << "\v" << QString(); + QTest::newRow("form-feed") << "\f" << QString(); + QTest::newRow("esc") << "\x1f" << QString(); + QTest::newRow("U+FFFE") << u"\xfffe"_s << QString(); + QTest::newRow("U+FFFF") << u"\xffff"_s << QString(); + + // simple strings + QTest::newRow("us-ascii") << "Hello, world" << "Hello, world"; + QTest::newRow("latin1") << "Bokmål" << "Bokmål"; + QTest::newRow("nonlatin1") << "Ελληνικά" << "Ελληνικά"; + QTest::newRow("nonbmp") << u"\U00010000"_s << u"\U00010000"_s; + + // escaped content + QTest::newRow("less-than") << "<" << "<"; + QTest::newRow("greater-than") << ">" << ">"; + QTest::newRow("ampersand") << "&" << "&"; + QTest::newRow("quote") << "\"" << """; +} + +template <typename Execute, typename Transform> +static void writeCharacters_common(Execute &&exec, Transform &&transform) +{ + QFETCH(QString, input); + QFETCH(QString, output); + QStringView utf16 = input; + QByteArray utf8ba = input.toUtf8(); + QUtf8StringView utf8(utf8ba); + + // may be invalid if input is not Latin1 + QByteArray l1ba = input.toLatin1(); + QLatin1StringView l1(l1ba); + if (l1 != input) + l1 = {}; + + auto write = [&](auto input) -> std::optional<QString> { + QString result; + QXmlStreamWriter writer(&result); + writer.writeStartElement("a"); + exec(writer, input); + writer.writeEndElement(); + if (writer.hasError()) + return std::nullopt; + return result; + }; + + if (input.isNull() != output.isNull()) { + // error + QCOMPARE(write(utf16), std::nullopt); + QCOMPARE(write(utf8), std::nullopt); + if (!l1.isEmpty()) + QCOMPARE(write(l1), std::nullopt); + } else { + output = transform(output); + QCOMPARE(write(utf16), output); + QCOMPARE(write(utf8), output); + if (!l1.isEmpty()) + QCOMPARE(write(l1), output); + } +} + +void tst_QXmlStream::writeCharacters_data() const +{ + writeCharacters_data_common(); + QTest::newRow("tab") << "\t" << "\t"; + QTest::newRow("newline") << "\n" << "\n"; + QTest::newRow("carriage-return") << "\r" << "\r"; +} + +void tst_QXmlStream::writeCharacters() const +{ + auto exec = [](QXmlStreamWriter &writer, auto input) { + writer.writeCharacters(input); + }; + auto transform = [](auto output) { return "<a>" + output + "</a>"; }; + writeCharacters_common(exec, transform); +} + +void tst_QXmlStream::writeAttribute_data() const +{ + writeCharacters_data_common(); + QTest::newRow("tab") << "\t" << "	"; + QTest::newRow("newline") << "\n" << " "; + QTest::newRow("carriage-return") << "\r" << " "; +} + +void tst_QXmlStream::writeAttribute() const +{ + auto exec = [](QXmlStreamWriter &writer, auto input) { + writer.writeAttribute("b", input); + }; + auto transform = [](auto output) { return "<a b=\"" + output + "\"/>"; }; + writeCharacters_common(exec, transform); +} + +#include "../../io/qurlinternal/utf8data.cpp" +void tst_QXmlStream::writeBadCharactersUtf8_data() const +{ + QTest::addColumn<QByteArray>("input"); + loadInvalidUtf8Rows(); +} + +void tst_QXmlStream::writeBadCharactersUtf8() const +{ + QFETCH(QByteArray, input); + QString target; + QXmlStreamWriter writer(&target); + writer.writeTextElement("a", QUtf8StringView(input)); + QVERIFY(writer.hasError()); +} + +void tst_QXmlStream::writeBadCharactersUtf16_data() const +{ + QTest::addColumn<QString>("input"); + QTest::addRow("low-surrogate") << u"\xdc00"_s; + QTest::addRow("high-surrogate") << u"\xd800"_s; + QTest::addRow("inverted-surrogate-pair") << u"\xdc00\xd800"_s; + QTest::addRow("high-surrogate+non-surrogate") << u"\xd800z"_s; +} + +void tst_QXmlStream::writeBadCharactersUtf16() const +{ + QFETCH(QString, input); + QString target; + QXmlStreamWriter writer(&target); + writer.writeTextElement("a", input); + QVERIFY(writer.hasError()); +} + void tst_QXmlStream::entitiesAndWhitespace_1() const { QXmlStreamReader reader(QLatin1String("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"><test>&extEnt;</test>")); @@ -1660,41 +1871,64 @@ void tst_QXmlStream::invalidStringCharacters_data() const // } -static bool isValidSingleTextChar(const ushort c) +static bool isValidSingleTextChar(char32_t c) { - // Conforms to https://www.w3.org/TR/REC-xml/#NT-Char - except for the high range, which is done - // with surrogates. + // Conforms to https://www.w3.org/TR/REC-xml/#NT-Char // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] - static const QPair<ushort, ushort> validRanges[] = { - QPair<ushort, ushort>(0x9, 0xb), - QPair<ushort, ushort>(0xd, 0xe), - QPair<ushort, ushort>(0x20, 0xd800), - QPair<ushort, ushort>(0xe000, 0xfffe) + constexpr struct { char32_t lo, hi; } validRanges[] = { + {0x9, 0xA}, + {0xD, 0xD}, + {0x20, 0xD7ff}, + {0xE000, 0xFFFD}, + {0x1'0000, 0x10'FFFF}, }; - for (const QPair<ushort, ushort> &range : validRanges) { - if (c >= range.first && c < range.second) + for (const auto range : validRanges) { + if (c >= range.lo && c <= range.hi) return true; } return false; } +void tst_QXmlStream::readBack_data() const +{ + QTest::addColumn<int>("plane"); + + // Check all 17 Unicode planes. Split into separate executions lest the + // test function times out in asan builds. + + for (int i = 0; i < 17; ++i) + QTest::addRow("plane-%02d", i) << i; +} + void tst_QXmlStream::readBack() const { - for (ushort c = 0; c < std::numeric_limits<ushort>::max(); ++c) { - QBuffer buffer; + QFETCH(const int, plane); + + constexpr qsizetype MaxChunkSizeWhenEncoding = 512; // from qxmlstream.cpp + QBuffer buffer; + QString text = QString(513, 'a'); // one longer than the internal conversion buffer + + for (char16_t i = 0; i < (std::numeric_limits<char16_t>::max)(); ++i) { + + const char32_t c = (plane << 16) + i; - QVERIFY(buffer.open(QIODevice::WriteOnly)); + // end chunk in invalid character, split surrogates: + const auto pair = QChar::fromUcs4(c); + text.resize(MaxChunkSizeWhenEncoding + 1 - pair.size()); + text += pair; + + QVERIFY(buffer.open(QIODevice::WriteOnly|QIODevice::Truncate)); QXmlStreamWriter writer(&buffer); writer.writeStartDocument(); - writer.writeTextElement("a", QString(QChar(c))); + writer.writeTextElement("a", text); writer.writeEndDocument(); buffer.close(); - if (writer.hasError()) { - QVERIFY2(!isValidSingleTextChar(c), QByteArray::number(c)); + if (!isValidSingleTextChar(c)) { + QVERIFY2(writer.hasError(), QByteArray::number(c)); } else { - QVERIFY2(isValidSingleTextChar(c), QByteArray::number(c)); + QVERIFY2(!writer.hasError(), QByteArray::number(c)); QVERIFY(buffer.open(QIODevice::ReadOnly)); QXmlStreamReader reader(&buffer); do { @@ -1716,6 +1950,22 @@ void tst_QXmlStream::roundTrip_data() const "<child xmlns:unknown=\"http://mydomain\">Text</child>" "</father>" "</root>\n"; + + // When a namespace is introduced by an attribute of an element, + // that element can exercise the namespace in its tag. + // This used (QTBUG-75456) to lead to the namespace definition + // being wrongly duplicated, with a new name. + QTest::newRow("QTBUG-75456") << + "<?xml version=\"1.0\"?>" + "<abc:root xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:abc=\"ns1\">" + "<abc:parent>" + "<abc:child xmlns:unknown=\"http://mydomain\">Text</abc:child>" + "</abc:parent>" + "<def:parent xmlns:def=\"ns2\" id=\"test\">" + "<def:child id=\"Timmy\">More text</def:child>" + "<def:child id=\"Jimmy\">Even more text</def:child>" + "</def:parent>" + "</abc:root>\n"; } void tst_QXmlStream::entityExpansionLimit() const @@ -1775,5 +2025,126 @@ void tst_QXmlStream::roundTrip() const QCOMPARE(out, in); } +void tst_QXmlStream::test_fastScanName_data() const +{ + QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QXmlStreamReader::Error>("errorType"); + + // 4096 is the limit in QXmlStreamReaderPrivate::fastScanName() + + QByteArray arr = "<a:" + QByteArray("b").repeated(4096 - 1); + QTest::newRow("data1") << arr << QXmlStreamReader::PrematureEndOfDocumentError; + + arr = "<a:" + QByteArray("b").repeated(4096); + QTest::newRow("data2") << arr << QXmlStreamReader::NotWellFormedError; + + arr = "<" + QByteArray("a").repeated(4000) + ":" + QByteArray("b").repeated(96); + QTest::newRow("data3") << arr << QXmlStreamReader::PrematureEndOfDocumentError; + + arr = "<" + QByteArray("a").repeated(4000) + ":" + QByteArray("b").repeated(96 + 1); + QTest::newRow("data4") << arr << QXmlStreamReader::NotWellFormedError; + + arr = "<" + QByteArray("a").repeated(4000 + 1) + ":" + QByteArray("b").repeated(96); + QTest::newRow("data5") << arr << QXmlStreamReader::NotWellFormedError; +} + +void tst_QXmlStream::test_fastScanName() const +{ + QFETCH(QByteArray, data); + QFETCH(QXmlStreamReader::Error, errorType); + + QXmlStreamReader reader(data); + QXmlStreamReader::TokenType tokenType; + while (!reader.atEnd()) + tokenType = reader.readNext(); + + QCOMPARE(tokenType, QXmlStreamReader::Invalid); + QCOMPARE(reader.error(), errorType); +} + +void tst_QXmlStream::tokenErrorHandling_data() const +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QXmlStreamReader::Error>("expectedError"); + QTest::addColumn<QString>("errorKeyWord"); + + constexpr auto invalid = QXmlStreamReader::Error::UnexpectedElementError; + constexpr auto valid = QXmlStreamReader::Error::NoError; + QTest::newRow("DtdInBody") << "dtdInBody.xml" << invalid << "DTD"; + QTest::newRow("multipleDTD") << "multipleDtd.xml" << invalid << "second DTD"; + QTest::newRow("wellFormed") << "wellFormed.xml" << valid << ""; +} + +void tst_QXmlStream::tokenErrorHandling() const +{ + QFETCH(const QString, fileName); + QFETCH(const QXmlStreamReader::Error, expectedError); + QFETCH(const QString, errorKeyWord); + + const QDir dir(QFINDTESTDATA("tokenError")); + QFile file(dir.absoluteFilePath(fileName)); + + // Cross-compiling: Files may not be found when running test standalone + // QSKIP in that case, because the tested functionality is platform independent. + if (!file.exists()) + QSKIP(QObject::tr("Testfile %1 not found.").arg(fileName).toUtf8().constData()); + + QVERIFY(file.open(QIODevice::ReadOnly)); + QXmlStreamReader reader(&file); + while (!reader.atEnd()) + reader.readNext(); + + QCOMPARE(reader.error(), expectedError); + if (expectedError != QXmlStreamReader::Error::NoError) + QVERIFY(reader.errorString().contains(errorKeyWord)); +} + +void tst_QXmlStream::checkStreamNotationDeclarations() const +{ + QString fileName("12.xml"); + const QDir dir(QFINDTESTDATA("data")); + QFile file(dir.absoluteFilePath(fileName)); + if (!file.exists()) + QSKIP(QObject::tr("Testfile %1 not found.").arg(fileName).toUtf8().constData()); + QVERIFY(file.open(QIODevice::ReadOnly)); + QXmlStreamReader reader(&file); + while (!reader.atEnd()) + reader.readNext(); + + QVERIFY(!reader.hasError()); + QXmlStreamNotationDeclaration notation1, notation2, notation3; + QT_TEST_EQUALITY_OPS(notation1, notation2, true); + const auto notationDeclarations = reader.notationDeclarations(); + if (notationDeclarations.count() >= 2) { + notation1 = notationDeclarations.at(0); + notation2 = notationDeclarations.at(1); + notation3 = notationDeclarations.at(1); + } + QT_TEST_EQUALITY_OPS(notation1, notation2, false); + QT_TEST_EQUALITY_OPS(notation3, notation2, true); +} + +void tst_QXmlStream::checkStreamEntityDeclarations() const +{ + QString fileName("5.xml"); + const QDir dir(QFINDTESTDATA("data")); + QFile file(dir.absoluteFilePath(fileName)); + if (!file.exists()) + QSKIP(QObject::tr("Testfile %1 not found.").arg(fileName).toUtf8().constData()); + QVERIFY(file.open(QIODevice::ReadOnly)); + QXmlStreamReader reader(&file); + while (!reader.atEnd()) + reader.readNext(); + + QVERIFY(!reader.hasError()); + QXmlStreamEntityDeclaration entity; + QT_TEST_EQUALITY_OPS(entity, QXmlStreamEntityDeclaration(), true); + + const auto entityDeclarations = reader.entityDeclarations(); + if (entityDeclarations.count() >= 2) { + entity = entityDeclarations.at(1); + QT_TEST_EQUALITY_OPS(entityDeclarations.at(0), entityDeclarations.at(1), false); + QT_TEST_EQUALITY_OPS(entity, entityDeclarations.at(1), true); + } +} #include "tst_qxmlstream.moc" -// vim: et:ts=4:sw=4:sts=4 |