summaryrefslogtreecommitdiffstats
path: root/tests/auto/xml/dom/qdom/tst_qdom.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/xml/dom/qdom/tst_qdom.cpp')
-rw-r--r--tests/auto/xml/dom/qdom/tst_qdom.cpp456
1 files changed, 386 insertions, 70 deletions
diff --git a/tests/auto/xml/dom/qdom/tst_qdom.cpp b/tests/auto/xml/dom/qdom/tst_qdom.cpp
index c44626e161..b73dbc49e2 100644
--- a/tests/auto/xml/dom/qdom/tst_qdom.cpp
+++ b/tests/auto/xml/dom/qdom/tst_qdom.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QBuffer>
@@ -34,15 +9,19 @@
#include <QFile>
#include <QList>
#include <QRegularExpression>
+#include <QScopeGuard>
#include <QTextStream>
#include <QTest>
#include <QtXml>
#include <QVariant>
#include <cmath>
+#include <QtXml/private/qdom_p.h>
QT_FORWARD_DECLARE_CLASS(QDomDocument)
QT_FORWARD_DECLARE_CLASS(QDomNode)
+using namespace Qt::StringLiterals;
+
class tst_QDom : public QObject
{
Q_OBJECT
@@ -52,6 +31,11 @@ private slots:
void namespacedAttributes() const;
void setContent_data();
void setContent();
+ void setContentOverloads();
+ void parseOptions();
+ void spacingOnlyNodes_data() const;
+ void spacingOnlyNodes() const;
+ void parseResult();
void toString_01_data();
void toString_01();
void toString_02_data();
@@ -85,8 +69,10 @@ private slots:
void invalidQualifiedName();
void invalidCharData_data();
void invalidCharData();
+ void nonBMPCharacters();
void roundTripAttributes() const;
+ void roundTripCDATA() const;
void normalizeEndOfLine() const;
void normalizeAttributes() const;
void serializeWeirdEOL() const;
@@ -111,12 +97,17 @@ private slots:
void checkIntOverflow() const;
void setContentWhitespace() const;
void setContentWhitespace_data() const;
+ void setContentUnopenedQIODevice() const;
void taskQTBUG4595_dontAssertWhenDocumentSpecifiesUnknownEncoding() const;
void cloneDTD_QTBUG8398() const;
void DTDNotationDecl();
void DTDEntityDecl();
+ void DTDInternalSubset() const;
+ void DTDInternalSubset_data() const;
void QTBUG49113_dontCrashWithNegativeIndex() const;
+ void standalone();
+ void splitTextLeakMemory() const;
void cleanupTestCase() const;
@@ -190,7 +181,11 @@ void tst_QDom::setContent()
QDomDocument domDoc;
QXmlStreamReader reader(doc);
- QVERIFY(domDoc.setContent(&reader, true));
+#if QT_DEPRECATED_SINCE(6, 8)
+ QT_IGNORE_DEPRECATIONS(domDoc.setContent(&reader, true);)
+#else
+ QVERIFY(domDoc.setContent(&reader, QDomDocument::ParseOption::UseNamespaceProcessing));
+#endif // QT_DEPRECATED_SINCE(6, 8)
QString eRes;
QTextStream ts( &eRes, QIODevice::WriteOnly );
@@ -204,6 +199,190 @@ void tst_QDom::setContent()
QVERIFY( domDoc1.setContent( doc ) );
QVERIFY( domDoc2.setContent( eRes ) );
QVERIFY( compareDocuments( domDoc1, domDoc2 ) );
+
+ // Test overload taking a QAnyStringView
+ QDomDocument domFromStringView;
+ QStringView stringView(doc);
+ QVERIFY(domFromStringView.setContent(stringView));
+ QVERIFY(compareDocuments(domFromStringView, domDoc));
+
+ // Test overload taking a QByteArray
+ QDomDocument domFromByteArary;
+ QByteArray byteArray = doc.toUtf8();
+ QVERIFY(domFromByteArary.setContent(byteArray));
+ QVERIFY(compareDocuments(domFromByteArary, domDoc));
+
+ // Test overload taking a QIODevice
+ QDomDocument domFromIODevice;
+ QBuffer buffer(&byteArray);
+ QVERIFY(buffer.open(QIODevice::ReadOnly));
+ QVERIFY(domFromIODevice.setContent(&buffer));
+ QVERIFY(compareDocuments(domFromIODevice, domDoc));
+}
+
+void tst_QDom::setContentOverloads()
+{
+ QDomDocument doc;
+ QString errorMessage;
+
+ QByteArray data("<a>test</a>");
+ QString text = QString::fromLatin1(data);
+ QXmlStreamReader reader(data);
+
+ QBuffer buffer(&data);
+ QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+ QVERIFY(doc.setContent(data));
+ QVERIFY(doc.setContent(data.data()));
+ QVERIFY(doc.setContent(text));
+ QVERIFY(doc.setContent(&reader));
+ QVERIFY(doc.setContent(&buffer));
+ buffer.reset();
+
+ // With parse options
+ QVERIFY(doc.setContent(data, QDomDocument::ParseOption::Default));
+ QVERIFY(doc.setContent(data.data(), QDomDocument::ParseOption::Default));
+ QVERIFY(doc.setContent(text, QDomDocument::ParseOption::Default));
+ QVERIFY(doc.setContent(&reader, QDomDocument::ParseOption::Default));
+ QVERIFY(doc.setContent(&buffer, QDomDocument::ParseOption::Default));
+ buffer.reset();
+
+#if QT_DEPRECATED_SINCE(6, 8)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ // With output param
+ QVERIFY(doc.setContent(data, &errorMessage));
+ QVERIFY(doc.setContent(text, &errorMessage));
+ QVERIFY(doc.setContent(&buffer, &errorMessage));
+ buffer.reset();
+ // There's no setContent(QXmlStreamReader *, QString *, int *, int *) overload
+ // QVERIFY(doc.setContent(&reader, &errorMessage));
+
+ // With namespace processing param
+ QVERIFY(doc.setContent(data, false));
+ QVERIFY(doc.setContent(text, false));
+ QVERIFY(doc.setContent(&reader, false));
+ QVERIFY(doc.setContent(&buffer, false));
+ buffer.reset();
+
+ // With namespace processing and output params
+ QVERIFY(doc.setContent(data, false, &errorMessage));
+ QVERIFY(doc.setContent(text, false, &errorMessage));
+ QVERIFY(doc.setContent(&reader, false, &errorMessage));
+ QVERIFY(doc.setContent(&buffer, false, &errorMessage));
+ buffer.reset();
+QT_WARNING_POP
+#endif // QT_DEPRECATED_SINCE(6, 8)
+}
+
+void tst_QDom::parseOptions()
+{
+ QString input = u"<doc xmlns:ns='http://example.com/'>"
+ "<ns:nested/>"
+ "</doc>"_s;
+ {
+ QDomDocument document;
+ QVERIFY(document.setContent(input, QDomDocument::ParseOption::Default));
+ const QDomElement docElement = document.firstChildElement("doc");
+ QVERIFY(!docElement.isNull());
+ const QDomElement nestedElement = docElement.firstChildElement();
+ QCOMPARE(nestedElement.nodeName(), "ns:nested");
+ QVERIFY(!nestedElement.isNull());
+ QVERIFY(nestedElement.localName().isEmpty());
+ QVERIFY(nestedElement.prefix().isEmpty());
+ QVERIFY(nestedElement.namespaceURI().isEmpty());
+ }
+ {
+ QDomDocument document;
+ QVERIFY(document.setContent(input, QDomDocument::ParseOption::UseNamespaceProcessing));
+ const QDomElement docElement = document.firstChildElement("doc");
+ QVERIFY(!docElement.isNull());
+ const QDomElement nestedElement = docElement.firstChildElement("nested");
+ QVERIFY(!nestedElement.isNull());
+ QCOMPARE(nestedElement.nodeName(), "ns:nested");
+ QCOMPARE(nestedElement.localName(), "nested");
+ QCOMPARE(nestedElement.prefix(), "ns");
+ QCOMPARE(nestedElement.namespaceURI(), "http://example.com/");
+ }
+}
+
+void tst_QDom::spacingOnlyNodes_data() const
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<QDomDocument::ParseOption>("options");
+
+ QTest::newRow("spacing-only-remove")
+ << u"<a> \t \n \r</a>"_s
+ << u"<a/>"_s
+ << QDomDocument::ParseOption::Default;
+ // \r is translated to \n, see https://www.w3.org/TR/xml11/#sec-line-ends
+ QTest::newRow("spacing-only-preserve")
+ << u"<a> \t \n \r</a>"_s
+ << u"<a> \t \n \n</a>"_s
+ << QDomDocument::ParseOption::PreserveSpacingOnlyNodes;
+ QTest::newRow("mixed-text-remove")
+ << u"<a> abc \t \n \r</a>"_s
+ << u"<a> abc \t \n \n</a>"_s
+ << QDomDocument::ParseOption::Default;
+ QTest::newRow("mixed-text-preserve")
+ << u"<a> abc \t \n \r</a>"_s
+ << u"<a> abc \t \n \n</a>"_s
+ << QDomDocument::ParseOption::PreserveSpacingOnlyNodes;
+
+ // QDomDocument treats all chacarcters below as spaces (see QTBUG-105348)
+ static constexpr char16_t spaces[] = {
+ QChar::Space, QChar::Tabulation, QChar::LineFeed,
+ QChar::CarriageReturn, QChar::Nbsp,
+ 0x2002, // EN SPACE
+ 0x2003, // EM SPACE
+ 0x2009 // THIN SPACE
+ };
+
+ for (char16_t space : spaces) {
+ QTest::addRow("spacing-remove-u%04x", space)
+ << u"<a>"_s + space + u"</a>"_s
+ << u"<a/>"_s
+ << QDomDocument::ParseOption::Default;
+
+ // \r is translated to \n, see https://www.w3.org/TR/xml11/#sec-line-ends
+ char16_t expected = (space == QChar::CarriageReturn) ? char16_t(QChar::LineFeed) : space;
+ QTest::addRow("spacing-preserve-u%04x", space)
+ << u"<a>"_s + space + u"</a>"_s
+ << u"<a>"_s + expected + u"</a>"_s
+ << QDomDocument::ParseOption::PreserveSpacingOnlyNodes;
+ }
+}
+
+void tst_QDom::spacingOnlyNodes() const
+{
+ QFETCH(QString, input);
+ QFETCH(QString, expected);
+ QFETCH(QDomDocument::ParseOption, options);
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(input, options));
+ QCOMPARE(doc.toString(-1), expected);
+}
+
+void tst_QDom::parseResult()
+{
+ QString input = u"<doc xmlns:b='http://example.com/'>"
+ "<b:element/>"_s;
+
+ QDomDocument document;
+ QDomDocument::ParseResult result = document.setContent(input);
+ QVERIFY(!result);
+ QVERIFY(!result.errorMessage.isEmpty());
+ QVERIFY(result.errorLine);
+ QVERIFY(result.errorColumn);
+
+ input.append("</doc>");
+ result = document.setContent(input);
+ QVERIFY(result);
+ QVERIFY(result.errorMessage.isEmpty());
+ QVERIFY(!result.errorLine);
+ QVERIFY(!result.errorColumn);
}
void tst_QDom::toString_01_data()
@@ -242,13 +421,11 @@ void tst_QDom::toString_01()
QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Failed to open file %1, file error: %2").arg(fileName).arg(f.error())));
QDomDocument doc;
- QString errorMsg;
- int errorLine;
- int errorCol;
-
- QVERIFY(doc.setContent( &f, &errorMsg, &errorLine, &errorCol )); /*,
- QString("QDomDocument::setContent() failed: %1 in line %2, column %3")
- .arg( errorMsg ).arg( errorLine ).arg( errorCol )); */
+ QDomDocument::ParseResult result = doc.setContent(&f, QDomDocument::ParseOption::Default);
+ QVERIFY2(result,
+ qPrintable(u"QDomDocument::setContent() failed (%1:%2): %3"_s.arg(result.errorLine)
+ .arg(result.errorColumn)
+ .arg(result.errorMessage)));
// test toString()'s invariant with different indenting depths
for ( int i=0; i<5; i++ ) {
QString toStr = doc.toString( i );
@@ -508,17 +685,14 @@ void tst_QDom::saveWithSerialization() const
QVERIFY(readDevice.open(QIODevice::ReadOnly));
QDomDocument result;
+ QDomDocument::ParseResult parseResult =
+ result.setContent(&readDevice, QDomDocument::ParseOption::Default);
- QString msg;
- int line = 0;
- int column = 0;
-
- QVERIFY2(result.setContent(&readDevice, &msg, &line, &column),
+ QVERIFY2(parseResult,
qPrintable(QString::fromLatin1("Failed: line %2, column %3: %4, content: %5")
- .arg(QString::number(line),
- QString::number(column),
- msg,
- QString::fromUtf8(storage))));
+ .arg(QString::number(parseResult.errorLine),
+ QString::number(parseResult.errorColumn),
+ parseResult.errorMessage, QString::fromUtf8(storage))));
if (!compareDocuments(doc, result))
{
QCOMPARE(doc.toString(), result.toString());
@@ -1363,6 +1537,10 @@ void tst_QDom::invalidCharData_data()
QTest::newRow( "f<o&o" ) << QString("f<o&o") << true << true << true << QString("f<o&o");
QTest::newRow( "empty" ) << QString() << true << true << true << QString();
QTest::newRow("f\\x07o\\x02")<< QString("f\x07o\x02")<< true << true << false << QString("fo");
+
+ const QChar pair[2] = { QChar(0xdc00), QChar(0xe000) };
+ QString invalid(pair, 2);
+ QTest::newRow("\\xdc00\\xe000") << invalid << true << true << false << invalid.last(1);
}
void tst_QDom::invalidCharData()
@@ -1406,6 +1584,20 @@ void tst_QDom::invalidCharData()
}
}
+void tst_QDom::nonBMPCharacters()
+{
+ const auto invalidDataPolicy = QDomImplementation::invalidDataPolicy();
+ auto resetInvalidDataPolicy = qScopeGuard(
+ [invalidDataPolicy] { QDomImplementation::setInvalidDataPolicy(invalidDataPolicy); });
+ QDomImplementation::setInvalidDataPolicy(QDomImplementation::DropInvalidChars);
+
+ const QString input = u"<text>Supplementary Plane: 𝄞 😂 🀄 🀶 🃪 🃋</text>"_s;
+
+ QDomDocument doc;
+ QVERIFY(doc.setContent(input, QDomDocument::ParseOption::Default));
+ QCOMPARE(doc.toString(-1), input);
+}
+
void tst_QDom::roundTripAttributes() const
{
/* Create an attribute via the QDom API with weird whitespace content. */
@@ -1440,6 +1632,15 @@ void tst_QDom::roundTripAttributes() const
QCOMPARE(QString::fromLatin1(serialized.constData()), QString::fromLatin1(expected.constData()));
}
+void tst_QDom::roundTripCDATA() const
+{
+ const QString input = u"<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<content><![CDATA[]]></content>\n"_s;
+ QDomDocument doc;
+ QVERIFY(doc.setContent(input, QDomDocument::ParseOption::Default));
+ QCOMPARE(doc.toString(), input);
+}
+
void tst_QDom::normalizeEndOfLine() const
{
QByteArray input("<a>\r\nc\rc\ra\na</a>");
@@ -1448,7 +1649,7 @@ void tst_QDom::normalizeEndOfLine() const
QVERIFY(buffer.open(QIODevice::ReadOnly));
QDomDocument doc;
- QVERIFY(doc.setContent(&buffer, true));
+ QVERIFY(doc.setContent(&buffer, QDomDocument::ParseOption::UseNamespaceProcessing));
const QString expected(QLatin1String("<a>\nc\nc\na\na</a>"));
@@ -1465,7 +1666,7 @@ void tst_QDom::normalizeAttributes() const
QVERIFY(buffer.open(QIODevice::ReadOnly));
QDomDocument doc;
- QVERIFY(doc.setContent(&buffer, true));
+ QVERIFY(doc.setContent(&buffer, QDomDocument::ParseOption::UseNamespaceProcessing));
QCOMPARE(doc.documentElement().attribute(QLatin1String("attribute")), QString::fromLatin1("a a"));
}
@@ -1509,17 +1710,18 @@ void tst_QDom::serializeNamespaces() const
QDomDocument doc;
QByteArray ba(input);
QXmlStreamReader streamReader(input);
- QVERIFY(doc.setContent(&streamReader, true));
+ QVERIFY(doc.setContent(&streamReader, QDomDocument::ParseOption::UseNamespaceProcessing));
const QByteArray serialized(doc.toByteArray());
QDomDocument doc2;
- QVERIFY(doc2.setContent(doc.toString(), true));
+ QVERIFY(doc2.setContent(doc.toString(), QDomDocument::ParseOption::UseNamespaceProcessing));
/* Here we test that it roundtrips. */
QVERIFY(isDeepEqual(doc2, doc));
QDomDocument doc3;
- QVERIFY(doc3.setContent(QString::fromLatin1(serialized.constData()), true));
+ QVERIFY(doc3.setContent(QString::fromLatin1(serialized.constData()),
+ QDomDocument::ParseOption::UseNamespaceProcessing));
QVERIFY(isDeepEqual(doc3, doc));
}
@@ -1545,7 +1747,7 @@ void tst_QDom::flagUndeclaredNamespace() const
QDomDocument doc;
QByteArray ba(input);
QXmlStreamReader streamReader(ba);
- QVERIFY(!doc.setContent(&streamReader, true));
+ QVERIFY(!doc.setContent(&streamReader, QDomDocument::ParseOption::UseNamespaceProcessing));
}
void tst_QDom::indentComments() const
@@ -1610,7 +1812,7 @@ void tst_QDom::checkLiveness() const
void tst_QDom::reportDuplicateAttributes() const
{
QDomDocument dd;
- bool isSuccess = dd.setContent(QLatin1String("<test x=\"1\" x=\"2\"/>"));
+ bool isSuccess = bool(dd.setContent(QLatin1String("<test x=\"1\" x=\"2\"/>")));
QVERIFY2(!isSuccess, "Duplicate attributes are well-formedness errors, and should be reported as such.");
}
@@ -1627,12 +1829,12 @@ void tst_QDom::namespacedAttributes() const
"</xan:td>\n";
QDomDocument one("document");
- QString error;
- bool docParsed = one.setContent(QByteArray(xml), true, &error);
- QVERIFY2(docParsed, qPrintable(error));
+ QDomDocument::ParseResult result =
+ one.setContent(QByteArray(xml), QDomDocument::ParseOption::UseNamespaceProcessing);
+ QVERIFY2(result, qPrintable(result.errorMessage));
QDomDocument two("document2");
- docParsed = two.setContent(one.toByteArray(2), true, &error);
- QVERIFY2(docParsed, qPrintable(error));
+ result = two.setContent(one.toByteArray(2), QDomDocument::ParseOption::UseNamespaceProcessing);
+ QVERIFY2(result, qPrintable(result.errorMessage));
QVERIFY(isDeepEqual(one, two));
}
@@ -1750,7 +1952,7 @@ void tst_QDom::germanUmlautToFile() const
QString name(QLatin1String("german"));
name += QChar(0xFC);
name += QLatin1String("umlaut");
- QCOMPARE(name.length(), 13);
+ QCOMPARE(name.size(), 13);
QDomDocument d("test");
d.appendChild(d.createElement(name));
@@ -1769,7 +1971,7 @@ void tst_QDom::germanUmlautToFile() const
const QByteArray in(inFile.readAll());
/* Check that it was wwritten out correctly. */
- QCOMPARE(in.length(), 34);
+ QCOMPARE(in.size(), 34);
QCOMPARE(in, baseline.toUtf8());
inFile.close();
@@ -1794,7 +1996,8 @@ void tst_QDom::crashInSetContent() const
QDomImplementation::setInvalidDataPolicy(QDomImplementation::ReturnNullNode);
QDomDocument docImport;
- QCOMPARE(docImport.setContent(QLatin1String("<a:>text</a:>"), true), false);
+ QVERIFY(!docImport.setContent(QLatin1String("<a:>text</a:>"),
+ QDomDocument::ParseOption::UseNamespaceProcessing));
QVERIFY(docImport.setContent(QLatin1String("<?xml version=\"1.0\"?><e/>")));
}
@@ -1809,24 +2012,17 @@ void tst_QDom::doubleNamespaceDeclarations() const
QVERIFY(file.open(QIODevice::ReadOnly));
QXmlStreamReader streamReader(&file);
- QVERIFY(doc.setContent(&streamReader, true));
+ QVERIFY(doc.setContent(&streamReader, QDomDocument::ParseOption::UseNamespaceProcessing));
- // tst_QDom relies on a specific QHash ordering, see QTBUG-25071
QString docAsString = doc.toString(0);
- QVERIFY(docAsString == QString::fromLatin1("<a>\n<b p:c=\"\" xmlns:p=\"NS\" p:d=\"\"/>\n</a>\n") ||
- docAsString == QString::fromLatin1("<a>\n<b p:c=\"\" p:d=\"\" xmlns:p=\"NS\"/>\n</a>\n") ||
- docAsString == QString::fromLatin1("<a>\n<b p:d=\"\" p:c=\"\" xmlns:p=\"NS\"/>\n</a>\n") ||
- docAsString == QString::fromLatin1("<a>\n<b p:d=\"\" xmlns:p=\"NS\" p:c=\"\"/>\n</a>\n") ||
- docAsString == QString::fromLatin1("<a>\n<b xmlns:p=\"NS\" p:c=\"\" p:d=\"\"/>\n</a>\n") ||
- docAsString == QString::fromLatin1("<a>\n<b xmlns:p=\"NS\" p:d=\"\" p:c=\"\"/>\n</a>\n")
- );
+ QCOMPARE(docAsString, "<a>\n<b p:c=\"\" p:d=\"\" xmlns:p=\"NS\"/>\n</a>\n");
}
void tst_QDom::setContentQXmlReaderOverload() const
{
QDomDocument doc;
QXmlStreamReader streamReader(QByteArray("<e/>"));
- doc.setContent(&streamReader, true);
+ doc.setContent(&streamReader, QDomDocument::ParseOption::UseNamespaceProcessing);
QCOMPARE(doc.documentElement().nodeName(), QString::fromLatin1("e"));
}
@@ -1878,7 +2074,7 @@ void tst_QDom::setContentWhitespace() const
QDomDocument domDoc;
- QCOMPARE(domDoc.setContent(doc), expectedValidity);
+ QCOMPARE(bool(domDoc.setContent(doc)), expectedValidity);
if(expectedValidity)
QCOMPARE(domDoc.documentElement().nodeName(), QString::fromLatin1("e"));
@@ -1919,6 +2115,23 @@ void tst_QDom::setContentWhitespace_data() const
QTest::newRow("data25") << QString::fromLatin1("\t\t\t\t<?xml version='1.0' ?><e/>") << false;
}
+void tst_QDom::setContentUnopenedQIODevice() const
+{
+ QByteArray data("<foo>bar</foo>");
+ QBuffer buffer(&data);
+
+ QDomDocument doc;
+
+ QTest::ignoreMessage(QtWarningMsg,
+ "QDomDocument called with unopened QIODevice. "
+ "This will not be supported in future Qt versions.");
+
+ // Note: the check below is expected to fail in Qt 7.
+ // Fix the test and remove the obsolete code from setContent().
+ QVERIFY(doc.setContent(&buffer, QDomDocument::ParseOption::UseNamespaceProcessing));
+ QCOMPARE(doc.toString().trimmed(), data);
+}
+
void tst_QDom::taskQTBUG4595_dontAssertWhenDocumentSpecifiesUnknownEncoding() const
{
QString xmlWithUnknownEncoding("<?xml version='1.0' encoding='unknown-encoding'?>"
@@ -2015,5 +2228,108 @@ void tst_QDom::QTBUG49113_dontCrashWithNegativeIndex() const
QVERIFY(node.isNull());
}
+void tst_QDom::standalone()
+{
+ {
+ QDomDocument doc;
+ const QString dtd("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+ "<Test/>\n");
+ doc.setContent(dtd);
+ QVERIFY(doc.toString().contains("standalone=\'no\'"));
+ }
+ {
+ QDomDocument doc;
+ const QString dtd("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Test/>\n");
+ doc.setContent(dtd);
+ QVERIFY(!doc.toString().contains("standalone"));
+ }
+ {
+ QDomDocument doc;
+ const QString dtd("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<Test/>\n");
+ doc.setContent(dtd);
+ QVERIFY(doc.toString().contains("standalone=\'yes\'"));
+ }
+}
+
+void tst_QDom::DTDInternalSubset() const
+{
+ QFETCH( QString, doc );
+ QFETCH( QString, internalSubset );
+ QXmlStreamReader reader(doc);
+ QDomDocument document;
+ QVERIFY(document.setContent(&reader, QDomDocument::ParseOption::UseNamespaceProcessing));
+
+ QCOMPARE(document.doctype().internalSubset(), internalSubset);
+}
+
+void tst_QDom::DTDInternalSubset_data() const
+{
+ QTest::addColumn<QString>("doc");
+ QTest::addColumn<QString>("internalSubset");
+
+ QTest::newRow("data1") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note SYSTEM '/[abcd].dtd'>\n"
+ "<note/>\n"
+ << "" ;
+
+ QTest::newRow("data2") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note PUBLIC '-/freedesktop' 'https://[abcd].dtd'>\n"
+ "<note/>\n"
+ << "" ;
+
+ const QString internalSubset0(
+ "<!-- open brackets comment [ -->\n"
+ "<!-- colse brackets comment ] -->\n"
+ );
+ QTest::newRow("data3") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note ["
+ + internalSubset0 +
+ "]>\n"
+ "<note/>\n"
+ << internalSubset0;
+
+ const QString internalSubset1(
+ "<!ENTITY obra '['>\n"
+ "<!ENTITY cbra ']'>\n"
+ );
+ QTest::newRow("data4") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note ["
+ + internalSubset1 +
+ "]>\n"
+ "<note/>\n"
+ << internalSubset1;
+
+ QTest::newRow("data5") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note PUBLIC '-/freedesktop' 'https://[abcd].dtd' ["
+ + internalSubset0
+ + "]>\n"
+ "<note/>\n"
+ << internalSubset0;
+
+ QTest::newRow("data6") << "<?xml version='1.0'?>\n"
+ "<!DOCTYPE note PUBLIC '-/freedesktop' "
+ "'2001:db8:130F:0000:0000:09C0:876A:130B://[abcd].dtd' ["
+ + internalSubset0
+ + "]>\n"
+ "<note/>\n"
+ << internalSubset0;
+}
+
+void tst_QDom::splitTextLeakMemory() const
+{
+ QDomDocument doc;
+ QDomElement top = doc.createElement("top");
+ QDomText text = doc.createTextNode("abcdefgh");
+ top.appendChild(text);
+ QDomText end = text.splitText(2);
+ QCOMPARE(text.data(), "ab"_L1);
+ QCOMPARE(end.data(), "cdefgh"_L1);
+ // only the parent node and the document have a reference on the nodes
+ QCOMPARE(text.impl->ref.loadRelaxed(), 2);
+ QCOMPARE(end.impl->ref.loadRelaxed(), 2);
+}
+
QTEST_MAIN(tst_QDom)
#include "tst_qdom.moc"