Extend tst_qxmlstream::readBack() to all Unicode characters

... not just those in the BMP.

The use of char32_t makes the isValid helper function easier to
read. Its passing to write() is enabled by the recent port to
QAnyStringView, which has a char32_t ctor.

Split into per-plane executions of the test function to avoid
running into timeouts on asan builds down the road.

As a drive-by, replace use of QPair with a proper struct, and
make the intervals symmetrically inclusive the bounds.

Change-Id: I2c6858d7e6a88f448eac1b1e124d7d7b82828d4c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 6b5419f43505867949016685fe40d17d81ff2646)
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2022-12-12 10:09:07 +01:00
parent 90384f4d86
commit af15f9d8de

View File

@ -581,6 +581,7 @@ private slots:
void invalidStringCharacters_data() const; void invalidStringCharacters_data() const;
void invalidStringCharacters() const; void invalidStringCharacters() const;
void hasError() const; void hasError() const;
void readBack_data() const;
void readBack() const; void readBack() const;
void roundTrip() const; void roundTrip() const;
void roundTrip_data() const; void roundTrip_data() const;
@ -1660,35 +1661,50 @@ 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 // Conforms to https://www.w3.org/TR/REC-xml/#NT-Char
// with surrogates.
// Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
static const QPair<ushort, ushort> validRanges[] = { constexpr struct { char32_t lo, hi; } validRanges[] = {
QPair<ushort, ushort>(0x9, 0xb), {0x9, 0xA},
QPair<ushort, ushort>(0xd, 0xe), {0xD, 0xD},
QPair<ushort, ushort>(0x20, 0xd800), {0x20, 0xD7ff},
QPair<ushort, ushort>(0xe000, 0xfffe) {0xE000, 0xFFFD},
{0x1'0000, 0x10'FFFF},
}; };
for (const QPair<ushort, ushort> &range : validRanges) { for (const auto range : validRanges) {
if (c >= range.first && c < range.second) if (c >= range.lo && c <= range.hi)
return true; return true;
} }
return false; 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 void tst_QXmlStream::readBack() const
{ {
QFETCH(const int, plane);
QBuffer buffer; QBuffer buffer;
for (ushort c = 0; c < std::numeric_limits<ushort>::max(); ++c) { 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|QIODevice::Truncate)); QVERIFY(buffer.open(QIODevice::WriteOnly|QIODevice::Truncate));
QXmlStreamWriter writer(&buffer); QXmlStreamWriter writer(&buffer);
writer.writeStartDocument(); writer.writeStartDocument();
writer.writeTextElement("a", QString(QChar(c))); writer.writeTextElement("a", c);
writer.writeEndDocument(); writer.writeEndDocument();
buffer.close(); buffer.close();