summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/serialization
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/serialization')
-rw-r--r--tests/auto/corelib/serialization/CMakeLists.txt4
-rw-r--r--tests/auto/corelib/serialization/json/tst_qtjson.cpp25
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp348
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp12
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp152
5 files changed, 459 insertions, 82 deletions
diff --git a/tests/auto/corelib/serialization/CMakeLists.txt b/tests/auto/corelib/serialization/CMakeLists.txt
index 3792336255..45965114cc 100644
--- a/tests/auto/corelib/serialization/CMakeLists.txt
+++ b/tests/auto/corelib/serialization/CMakeLists.txt
@@ -3,7 +3,9 @@
add_subdirectory(json)
add_subdirectory(qcborstreamreader)
-add_subdirectory(qcborstreamwriter)
+if(QT_FEATURE_cborstreamwriter)
+ add_subdirectory(qcborstreamwriter)
+endif()
if(NOT WASM)
add_subdirectory(qcborvalue)
endif()
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 5046478547..54ef9be4f2 100644
--- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -182,14 +182,20 @@ void tst_QtJson::compareCompiles()
QJsonArray::const_iterator>();
QTestPrivate::testEqualityOperatorsCompile<QJsonDocument>();
QTestPrivate::testEqualityOperatorsCompile<QJsonObject>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::iterator>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::const_iterator>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValue>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValueConstRef>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef>();
QTestPrivate::testEqualityOperatorsCompile<QJsonArray, QJsonValue>();
QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValueConstRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValueRef>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValueConstRef, QJsonValue>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef, QJsonValue>();
QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef, QJsonValueConstRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::iterator,
+ QJsonObject::const_iterator>();
}
void tst_QtJson::testValueSimple()
@@ -670,6 +676,7 @@ void tst_QtJson::testObjectInsertCopies()
QCOMPARE(obj.size(), 2);
QCOMPARE(obj.value("value"), "TEST");
QCOMPARE(obj.value("prop2"), "TEST");
+ QT_TEST_EQUALITY_OPS(rv, obj["value"].toObject(), true);
}
{
QJsonObject obj;
@@ -1105,6 +1112,7 @@ void tst_QtJson::testObjectIteration()
for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) {
QJsonValue value = it.value();
QCOMPARE((double)it.key().toInt(), value.toDouble());
+ QT_TEST_EQUALITY_OPS(it, QJsonObject::iterator(), false);
}
{
@@ -1117,6 +1125,7 @@ void tst_QtJson::testObjectIteration()
QCOMPARE(object.size(), 10);
QCOMPARE(object2.size(), 9);
QVERIFY(next == object2.begin());
+ QT_TEST_EQUALITY_OPS(next, object2.begin(), true);
double d = 1; // we erased the first item
for (auto it = object2.constBegin(); it != object2.constEnd(); ++it, d += 1) {
@@ -1175,6 +1184,7 @@ void tst_QtJson::testObjectIteration()
{
QJsonObject::Iterator it = object.begin();
it += 5;
+ QT_TEST_ALL_COMPARISON_OPS(it, object.begin(), Qt::strong_ordering::greater);
QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
it -= 3;
QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
@@ -1189,10 +1199,14 @@ void tst_QtJson::testObjectIteration()
it += 5;
QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
it -= 3;
+ QT_TEST_ALL_COMPARISON_OPS(object.constBegin(), it, Qt::strong_ordering::less);
QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
QJsonObject::ConstIterator it2 = it + 5;
+ QT_TEST_EQUALITY_OPS(it, it2, false);
QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
it2 = it - 1;
+ QT_TEST_ALL_COMPARISON_OPS(it2, it, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(it2, it - 2, Qt::strong_ordering::greater);
QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
}
@@ -1201,6 +1215,17 @@ void tst_QtJson::testObjectIteration()
it = object.erase(it);
QCOMPARE(object.size() , 0);
QCOMPARE(it, object.end());
+ QT_TEST_ALL_COMPARISON_OPS(it, object.end(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(it, object.constEnd(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(it, object.begin(),
+ Qt::strong_ordering::equal); // because object is empty
+ QT_TEST_ALL_COMPARISON_OPS(it, object.constBegin(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::Iterator(),
+ QJsonObject::Iterator(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::ConstIterator(),
+ QJsonObject::Iterator(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::ConstIterator(),
+ QJsonObject::ConstIterator(), Qt::strong_ordering::equal);
}
void tst_QtJson::testArrayIteration()
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
index 37f1569bbc..e480b033e1 100644
--- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -7,7 +7,9 @@
#include <QBuffer>
#include <QCborStreamReader>
+#if QT_CONFIG(cborstreamwriter)
#include <QCborStreamWriter>
+#endif
#include <QDateTime>
#include <QtEndian>
#include <QTimeZone>
@@ -16,6 +18,8 @@ Q_DECLARE_METATYPE(QCborKnownTags)
Q_DECLARE_METATYPE(QCborValue)
Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
+using namespace Qt::StringLiterals;
+
class tst_QCborValue : public QObject
{
Q_OBJECT
@@ -78,16 +82,17 @@ private slots:
void mapComplexKeys();
void mapNested();
+ void sorting_data();
void sorting();
- void comparison_data();
- void comparison();
void comparisonMap_data();
void comparisonMap();
void toCbor_data();
+#if QT_CONFIG(cborstreamwriter)
void toCbor();
void toCborStreamWriter_data() { toCbor_data(); }
void toCborStreamWriter();
+#endif
void fromCbor_data();
void fromCbor();
void fromCborStreamReaderByteArray_data() { fromCbor_data(); }
@@ -457,7 +462,11 @@ void tst_QCborValue::compareCompiles()
QTestPrivate::testAllComparisonOperatorsCompile<QCborValueRef>();
QTestPrivate::testAllComparisonOperatorsCompile<QCborValueConstRef>();
QTestPrivate::testAllComparisonOperatorsCompile<QCborArray>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QCborArray::Iterator>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QCborArray::ConstIterator>();
QTestPrivate::testAllComparisonOperatorsCompile<QCborMap>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QCborMap::Iterator>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QCborMap::ConstIterator>();
// QCborValue, Ref and ConstRef
QTestPrivate::testAllComparisonOperatorsCompile<QCborValueRef, QCborValueConstRef>();
@@ -471,6 +480,8 @@ void tst_QCborValue::compareCompiles()
QTestPrivate::testAllComparisonOperatorsCompile<QCborMap, QCborValue>();
QTestPrivate::testAllComparisonOperatorsCompile<QCborMap, QCborValueRef>();
QTestPrivate::testAllComparisonOperatorsCompile<QCborMap, QCborValueConstRef>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QCborArray::Iterator,
+ QCborArray::ConstIterator>();
}
void tst_QCborValue::extendedTypes()
@@ -739,6 +750,13 @@ void tst_QCborValue::mapNonEmptyDetach()
{ QCborMap copy(m); auto it = m.find(QLatin1String("3")); QVERIFY(it == m.end()); }
{ QCborMap copy(m); auto it = m.find(QString("3")); QVERIFY(it == m.end()); }
{ QCborMap copy(m); auto it = m.find(QCborValue(3)); QVERIFY(it == m.end()); }
+
+ QT_TEST_EQUALITY_OPS(m.constBegin(), m.constEnd(), false);
+ QT_TEST_EQUALITY_OPS(m.begin(), m.end(), false);
+ QT_TEST_EQUALITY_OPS(m.constFind(3), m.constEnd(), true);
+ QT_TEST_EQUALITY_OPS(m.find(3), m.end(), true);
+ QT_TEST_EQUALITY_OPS(m.find(3), m.constEnd(), true);
+ QT_TEST_EQUALITY_OPS(m.constFind(3), m.end(), true);
}
void tst_QCborValue::arrayInitializerList()
@@ -785,12 +803,17 @@ void tst_QCborValue::arrayInitializerList()
// iterators
auto it = a.constBegin();
auto end = a.constEnd();
+ QT_TEST_ALL_COMPARISON_OPS(it, end, Qt::strong_ordering::less);
QCOMPARE(end - it, 7);
QCOMPARE(it + 7, end);
+ QT_TEST_EQUALITY_OPS(it + 7, end, true);
QVERIFY(it->isInteger());
QCOMPARE(*it, QCborValue(0));
QCOMPARE(it[1], QCborValue(-1));
QCOMPARE(*(it + 2), QCborValue(false));
+ QT_TEST_EQUALITY_OPS(*it, QCborValue(0), true);
+ QT_TEST_EQUALITY_OPS(it[1], QCborValue(-1), true);
+ QT_TEST_EQUALITY_OPS(*(it + 2), QCborValue(false), true);
it += 3;
QCOMPARE(*it, QCborValue(true));
++it;
@@ -801,6 +824,24 @@ void tst_QCborValue::arrayInitializerList()
QCOMPARE(*end, QCborValue(1.0));
end--;
QCOMPARE(it, end);
+ QT_TEST_EQUALITY_OPS(it, end, true);
+ QT_TEST_EQUALITY_OPS(it, QCborArray::ConstIterator(), false);
+ QT_TEST_EQUALITY_OPS(QCborArray::ConstIterator(), end, false);
+ QT_TEST_EQUALITY_OPS(QCborArray::ConstIterator(), QCborArray::ConstIterator(), true);
+ QT_TEST_EQUALITY_OPS(QCborArray::ConstIterator(), QCborArray::Iterator(), true);
+
+ {
+ auto it = a.begin();
+ auto it1 = a.constBegin();
+ auto end = a.end();
+ QT_TEST_ALL_COMPARISON_OPS(it, end, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(it1, end, Qt::strong_ordering::less);
+ QT_TEST_EQUALITY_OPS(it + 7, end, true);
+ QT_TEST_EQUALITY_OPS(it1 + 7, end, true);
+ QT_TEST_EQUALITY_OPS(it, QCborArray::Iterator(), false);
+ QT_TEST_EQUALITY_OPS(QCborArray::Iterator(), end, false);
+ QT_TEST_EQUALITY_OPS(QCborArray::Iterator(), QCborArray::ConstIterator(), true);
+ }
// range for
int i = 0;
@@ -1151,8 +1192,18 @@ void tst_QCborValue::mapMutation()
m2 = m;
auto it = m.begin(); // detaches again
auto end = m.end();
+ auto it1 = m.constBegin(); // detaches again
+ auto end2 = m.constEnd();
QCOMPARE(end - it, 2);
+ QT_TEST_ALL_COMPARISON_OPS(it, it + 1, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(it, it1 + 1, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(it, it - 1, Qt::strong_ordering::greater);
+ QT_TEST_ALL_COMPARISON_OPS(it, it1 - 1, Qt::strong_ordering::greater);
+ QT_TEST_EQUALITY_OPS(it, it1, true);
QCOMPARE(it + 2, end);
+ QT_TEST_EQUALITY_OPS(it + 2, end, true);
+ QT_TEST_EQUALITY_OPS(it + 2, end2, true);
+ QT_TEST_EQUALITY_OPS(it1 + 2, end2, true);
QT_TEST_EQUALITY_OPS(it.key(), QCborValue(42), true);
QT_TEST_EQUALITY_OPS(it.value(), QCborValue(2.5), true);
QT_TEST_EQUALITY_OPS((++it).value(), QCborValue(nullptr), true);
@@ -1287,6 +1338,8 @@ void tst_QCborValue::arrayValueRef()
QVERIFY(v == a.first());
QVERIFY(v == a.last());
QVERIFY(v == a[0]);
+ QT_TEST_EQUALITY_OPS(a.first(), v, true);
+ QT_TEST_EQUALITY_OPS(a.last(), v, true);
auto iteratorCheck = [&v](auto it) {
QT_TEST_EQUALITY_OPS(*it, v, true);
@@ -1819,8 +1872,24 @@ void tst_QCborValue::mapNested()
}
}
-void tst_QCborValue::sorting()
+void tst_QCborValue::sorting_data()
{
+ // CBOR data comparisons are done as if we were comparing their canonically
+ // (deterministic) encoded forms in the byte stream, including the Major
+ // Type. That has a few surprises noted below:
+ // 1) because the length of a string precedes it, effectively strings are
+ // sorted by their UTF-8 length before their contents
+ // 2) because negative integers are stored in negated form, they sort in
+ // descending order (i.e. by absolute value)
+ // 3) negative integers (Major Type 1) sort after all positive integers
+ // (Major Type 0)
+ // Effectively, this means integers are sorted as sign+magnitude.
+ // 4) floating point types (Major Type 7) sort after all integers
+
+ QTest::addColumn<QCborValue>("lhs");
+ QTest::addColumn<QCborValue>("rhs");
+ QTest::addColumn<Qt::strong_ordering>("expectedOrdering");
+
QCborValue vundef, vnull(nullptr);
QCborValue vtrue(true), vfalse(false);
QCborValue vint1(1), vint2(2);
@@ -1839,97 +1908,213 @@ void tst_QCborValue::sorting()
QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/"));
QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid());
QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255));
- QCborValue vdouble1(1.5), vdouble2(qInf());
+ QCborValue vdouble1(1.5), vdouble2(qInf()), vdouble3(qQNaN());
QCborValue vndouble1(-1.5), vndouble2(-qInf());
+ auto addRow = [](QCborValue lhs, QCborValue rhs, Qt::strong_ordering order) {
+ QTest::addRow("%s-cmp-%s", qPrintable(lhs.toDiagnosticNotation()),
+ qPrintable(rhs.toDiagnosticNotation()))
+ << lhs << rhs << order;
+ };
+ auto addSelfCmp = [](QCborValue v) {
+ QTest::addRow("self-%s", qPrintable(v.toDiagnosticNotation()))
+ << v << v << Qt::strong_ordering::equal;
+ };
+
+ // self compares
+ addSelfCmp(vundef);
+ addSelfCmp(vnull);
+ addSelfCmp(vfalse);
+ addSelfCmp(vtrue);
+ addSelfCmp(vint1);
+ addSelfCmp(vint2);
+ addSelfCmp(vneg1);
+ addSelfCmp(vneg2);
+ addSelfCmp(vba1);
+ addSelfCmp(vba2);
+ addSelfCmp(vba3);
+ addSelfCmp(vs1);
+ addSelfCmp(vs2);
+ addSelfCmp(vs3);
+ addSelfCmp(va1);
+ addSelfCmp(va2);
+ addSelfCmp(va3);
+ addSelfCmp(vm1);
+ addSelfCmp(vm2);
+ addSelfCmp(vm3);
+ addSelfCmp(vdt1);
+ addSelfCmp(vdt2);
+ addSelfCmp(vtagged1);
+ addSelfCmp(vtagged2);
+ addSelfCmp(vtagged3);
+ addSelfCmp(vtagged4);
+ addSelfCmp(vtagged5);
+ addSelfCmp(vurl1);
+ addSelfCmp(vurl2);
+ addSelfCmp(vuuid1);
+ addSelfCmp(vuuid2);
+ addSelfCmp(vsimple1);
+ addSelfCmp(vsimple32);
+ addSelfCmp(vsimple255);
+ addSelfCmp(vdouble1);
+ addSelfCmp(vdouble2);
+ addSelfCmp(vdouble3); // surprise: NaNs do compare
+ addSelfCmp(vndouble1);
+ addSelfCmp(vndouble2);
+
// intra-type comparisons
- QT_TEST_ALL_COMPARISON_OPS(vfalse, vtrue, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vsimple1, vsimple32, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vsimple32, vsimple255, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vint1, vint2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vdouble1, vdouble2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vndouble1, vndouble2, Qt::strong_ordering::less);
- // note: shorter length sorts first
- QT_TEST_ALL_COMPARISON_OPS(vba1, vba2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vba2, vba3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vs1, vs2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vs2, vs3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(va1, va2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(va2, va3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vm1, vm2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vm2, vm3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vdt1, vdt2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged1, vtagged2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged2, vtagged3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged3, vtagged4, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged4, vtagged5, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vurl1, vurl2, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vuuid1, vuuid2, Qt::strong_ordering::less);
-
- // surprise 1: CBOR sorts integrals by absolute value
- QT_TEST_ALL_COMPARISON_OPS(vneg1, vneg2, Qt::strong_ordering::less);
-
- // surprise 2: CBOR sorts negatives after positives (sign+magnitude)
- QT_TEST_ALL_COMPARISON_OPS(vint2, vneg1, Qt::strong_ordering::less);
- QVERIFY(vint2.toInteger() > vneg1.toInteger());
- QT_TEST_ALL_COMPARISON_OPS(vdouble2, vndouble1, Qt::strong_ordering::less);
- QVERIFY(vdouble2.toDouble() > vndouble1.toDouble());
+ addRow(vfalse, vtrue, Qt::strong_ordering::less);
+ addRow(vsimple1, vsimple32, Qt::strong_ordering::less);
+ addRow(vsimple32, vsimple255, Qt::strong_ordering::less);
+ addRow(vint1, vint2, Qt::strong_ordering::less);
+ addRow(vdouble1, vdouble2, Qt::strong_ordering::less);
+ addRow(vdouble2, vdouble3, Qt::strong_ordering::less); // surprise: NaNs do compare
+ addRow(vndouble1, vndouble2, Qt::strong_ordering::less); // surprise: -1.5 < -inf
+ addRow(va1, va2, Qt::strong_ordering::less);
+ addRow(va2, va3, Qt::strong_ordering::less);
+ addRow(vm1, vm2, Qt::strong_ordering::less);
+ addRow(vm2, vm3, Qt::strong_ordering::less);
+ addRow(vdt1, vdt2, Qt::strong_ordering::less);
+ addRow(vtagged1, vtagged2, Qt::strong_ordering::less);
+ addRow(vtagged2, vtagged3, Qt::strong_ordering::less);
+ addRow(vtagged3, vtagged4, Qt::strong_ordering::less);
+ addRow(vtagged4, vtagged5, Qt::strong_ordering::less);
+ addRow(vurl1, vurl2, Qt::strong_ordering::less);
+ addRow(vuuid1, vuuid2, Qt::strong_ordering::less);
+
+ // surprise 1: CBOR sorts strings by length first
+ addRow(vba1, vba2, Qt::strong_ordering::less);
+ addRow(vba2, vba3, Qt::strong_ordering::less);
+ addRow(vs1, vs2, Qt::strong_ordering::less);
+ addRow(vs2, vs3, Qt::strong_ordering::less);
+
+ // surprise 2: CBOR sorts integrals by absolute value
+ addRow(vneg1, vneg2, Qt::strong_ordering::less);
+
+ // surprise 3: CBOR sorts negatives after positives (sign+magnitude)
+ addRow(vint2, vneg1, Qt::strong_ordering::less);
+ addRow(vdouble2, vndouble1, Qt::strong_ordering::less);
// inter-type comparisons
- QT_TEST_ALL_COMPARISON_OPS(vneg2, vba1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vba3, vs1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vs3, va1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(va2, vm1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vm2, vdt1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vdt2, vtagged1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged2, vurl1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vurl1, vuuid1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vuuid2, vtagged3, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtagged4, vsimple1, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vsimple1, vfalse, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vtrue, vnull, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vnull, vundef, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vundef, vsimple32, Qt::strong_ordering::less);
- QT_TEST_ALL_COMPARISON_OPS(vsimple255, vdouble1, Qt::strong_ordering::less);
+ addRow(vneg2, vba1, Qt::strong_ordering::less);
+ addRow(vba3, vs1, Qt::strong_ordering::less);
+ addRow(vs3, va1, Qt::strong_ordering::less);
+ addRow(va2, vm1, Qt::strong_ordering::less);
+ addRow(vm2, vdt1, Qt::strong_ordering::less);
+ addRow(vdt2, vtagged1, Qt::strong_ordering::less);
+ addRow(vtagged2, vurl1, Qt::strong_ordering::less);
+ addRow(vurl1, vuuid1, Qt::strong_ordering::less);
+ addRow(vuuid2, vtagged3, Qt::strong_ordering::less);
+ addRow(vtagged4, vsimple1, Qt::strong_ordering::less);
+ addRow(vsimple1, vfalse, Qt::strong_ordering::less);
+ addRow(vtrue, vnull, Qt::strong_ordering::less);
+ addRow(vnull, vundef, Qt::strong_ordering::less);
+ addRow(vundef, vsimple32, Qt::strong_ordering::less);
+ addRow(vsimple255, vdouble1, Qt::strong_ordering::less);
// which shows all doubles sorted after integrals
- QT_TEST_ALL_COMPARISON_OPS(vint2, vdouble1, Qt::strong_ordering::less);
- QVERIFY(vint2.toInteger() > vdouble1.toDouble());
-}
+ addRow(vint2, vdouble1, Qt::strong_ordering::less);
-void tst_QCborValue::comparison_data()
-{
- QTest::addColumn<QCborValue>("lhs");
- QTest::addColumn<QCborValue>("rhs");
- QTest::addColumn<Qt::strong_ordering>("expectedOrdering");
+ // Add some non-US-ASCII strings. In the current implementation, QCborValue
+ // can store a string as either US-ASCII, UTF-8, or UTF-16, so let's exercise
+ // those comparisons.
- auto addRow = [](QCborValue lhs, QCborValue rhs, Qt::strong_ordering order) {
- QTest::addRow("%s-cmp-%s", qPrintable(lhs.toDiagnosticNotation()),
- qPrintable(rhs.toDiagnosticNotation()))
- << lhs << rhs << order;
+ // we don't have a QUtf8StringView constructor, so work around it
+ auto utf8string = [](QByteArray str) {
+ Q_ASSERT(str.size() < 24);
+ str.prepend(char(QCborValue::String) + str.size());
+ return QCborValue::fromCbor(str);
};
- // typical, sorts as expected
- addRow(0, 0, Qt::strong_ordering::equivalent);
- addRow(1, 0, Qt::strong_ordering::greater);
- addRow(0, 1, Qt::strong_ordering::less);
- addRow(10.0, 10.0, Qt::strong_ordering::equivalent);
- addRow(10.5, 10.8, Qt::strong_ordering::less);
- addRow(-10.5, -10.8, Qt::strong_ordering::less);
- addRow("Qt","Qt", Qt::strong_ordering::equivalent);
- addRow("qt","Qt", Qt::strong_ordering::greater);
- // atypical gotchas
- addRow(0, -1, Qt::strong_ordering::less);
- addRow(10, 10.0, Qt::strong_ordering::less);
- addRow(0, "Qt", Qt::strong_ordering::less);
+ auto addStringCmp = [&](const char *prefix, const char *tag, QUtf8StringView lhs,
+ QUtf8StringView rhs) {
+ // CBOR orders strings by UTF-8 length
+ auto order = Qt::compareThreeWay(lhs.size(), rhs.size());
+ if (is_eq(order))
+ order = compareThreeWay(lhs, rhs);
+ Q_ASSERT(is_eq(order) || is_lt(order)); // please keep lhs <= rhs!
+
+ QCborValue lhs_utf8 = utf8string(QByteArrayView(lhs).toByteArray());
+ QCborValue rhs_utf8 = utf8string(QByteArrayView(rhs).toByteArray());
+ QCborValue lhs_utf16 = QString::fromUtf8(lhs);
+ QCborValue rhs_utf16 = QString::fromUtf8(rhs);
+
+ QTest::addRow("string-%s%s:utf8-utf8", prefix, tag) << lhs_utf8 << rhs_utf8 << order;
+ QTest::addRow("string-%s%s:utf8-utf16", prefix, tag) << lhs_utf8 << rhs_utf16 << order;
+ QTest::addRow("string-%s%s:utf16-utf8", prefix, tag) << lhs_utf16 << rhs_utf8 << order;
+ QTest::addRow("string-%s%s:utf16-utf16", prefix, tag) << lhs_utf16 << rhs_utf16 << order;
+ };
+ auto addStringCmpSameLength = [&](const char *tag, QUtf8StringView lhs, QUtf8StringView rhs) {
+ Q_ASSERT(lhs.size() == rhs.size());
+ addStringCmp("samelength-", tag, lhs, rhs);
+ };
+ auto addStringCmpShorter = [&](const char *tag, QUtf8StringView lhs, QUtf8StringView rhs) {
+ Q_ASSERT(lhs.size() < rhs.size());
+ addStringCmp("shorter-", tag, lhs, rhs);
+ };
+
+ // ascii-only is already tested
+ addStringCmp("equal-", "1continuation", "ab\u00A0c", "ab\u00A0c");
+ addStringCmp("equal-", "2continuation", "ab\u0800", "ab\u0800");
+ addStringCmp("equal-", "3continuation", "a\U00010000", "a\U00010000");
+
+ // these strings all have the same UTF-8 length (5 bytes)
+ addStringCmpSameLength("less-ascii", "abcde", "ab\u00A0c");
+ addStringCmpSameLength("less-1continuation", "ab\u00A0c", "ab\u07FFc");
+ addStringCmpSameLength("less-2continuation", "ab\u0800", "ab\uFFFC");
+ addStringCmpSameLength("less-3continuation", "a\U00010000", "a\U0010FFFC");
+ addStringCmpSameLength("less-0-vs-1continuation", "abcde", "ab\u00A0c");
+ addStringCmpSameLength("less-0-vs-2continuation", "abcde", "ab\u0800");
+ addStringCmpSameLength("less-0-vs-3continuation", "abcde", "a\U00010000");
+ addStringCmpSameLength("less-1-vs-2continuation", "ab\u00A0c", "ab\uFFFC");
+ addStringCmpSameLength("less-1-vs-3continuation", "ab\u00A0c", "a\U00010000");
+ addStringCmpSameLength("less-2-vs-3continuation", "ab\u0800", "a\U00010000");
+ addStringCmpSameLength("less-2-vs-3continuation_surrogate", "a\uFFFCz", "a\U00010000"); // even though U+D800 < U+FFFC
+
+ // these strings have different lengths in UTF-8
+ // (0continuation already tested)
+ addStringCmpShorter("1continuation", "ab\u00A0", "ab\u00A0c");
+ addStringCmpShorter("2continuation", "ab\u0800", "ab\u0800c");
+ addStringCmpShorter("3continuation", "ab\U00010000", "ab\U00010000c");
+ // most of these have the same length in UTF-16!
+ addStringCmpShorter("0-vs-1continuation", "abc", "ab\u00A0");
+ addStringCmpShorter("0-vs-2continuation", "abcd", "ab\u0800");
+ addStringCmpShorter("0-vs-3continuation", "abcde", "ab\U00010000");
+ addStringCmpShorter("1-vs-2continuation", "ab\u00A0", "ab\u0800");
+ addStringCmpShorter("1-vs-3continuation", "abc\u00A0", "ab\U00010000");
+ addStringCmpShorter("2-vs-3continuation", "ab\u0800", "ab\U00010000");
+
+ // lhs is 4xUTF-16 and 8xUTF-8; rhs is 3xUTF-16 but 9xUTF-8
+ addStringCmpShorter("3x2-vs-2x3continuation", "\U00010000\U00010000", "\u0800\u0800\u0800");
+
+ // slight surprising because normally rhs would sort first ("aa" vs "ab" prefix)
+ // (0continuation_surprise already tested)
+ addStringCmpShorter("1continuation_surprise", "ab\u00A0", "aa\u00A0c");
+ addStringCmpShorter("2continuation_surprise", "ab\u0800", "aa\u0800c");
+ addStringCmpShorter("3continuation_surprise", "ab\U00010000", "aa\U00010000c");
+ addStringCmpShorter("0-vs-1continuation_surprise", "abc", "aa\u00A0");
+ addStringCmpShorter("0-vs-2continuation_surprise", "abcd", "aa\u0800");
+ addStringCmpShorter("0-vs-3continuation_surprise", "abcde", "aa\U00010000");
+ addStringCmpShorter("1-vs-2continuation_surprise", "ab\u00A0", "aa\u0800");
+ addStringCmpShorter("1-vs-3continuation_surprise", "abc\u00A0", "aa\U00010000");
+ addStringCmpShorter("2-vs-3continuation_surprise", "ab\u0800", "aa\U00010000");
}
-void tst_QCborValue::comparison()
+void tst_QCborValue::sorting()
{
QFETCH(QCborValue, lhs);
QFETCH(QCborValue, rhs);
QFETCH(Qt::strong_ordering, expectedOrdering);
+ // do a QCOMPARE first so we get a proper QTest error in case QCborValue is
+ // broken
+ if (expectedOrdering == Qt::strong_ordering::equal)
+ QCOMPARE_EQ(lhs, rhs);
+ else if (expectedOrdering == Qt::strong_ordering::less)
+ QCOMPARE_LT(lhs, rhs);
+ else if (expectedOrdering == Qt::strong_ordering::greater)
+ QCOMPARE_GT(lhs, rhs);
+
QCborArray array{lhs, rhs};
QCborValueConstRef lhsCRef = array.constBegin()[0];
@@ -1937,7 +2122,7 @@ void tst_QCborValue::comparison()
QCborValueRef lhsRef = array[0];
QCborValueRef rhsRef = array[1];
- // QCborValue vs QCborValue
+ // QCborValue vs QCborValue
QT_TEST_ALL_COMPARISON_OPS(lhs, rhs, expectedOrdering);
// QCborValueConstRef vs QCborValueConstRef
QT_TEST_ALL_COMPARISON_OPS(lhsCRef, rhsCRef, expectedOrdering);
@@ -1951,7 +2136,6 @@ void tst_QCborValue::comparison()
QT_TEST_ALL_COMPARISON_OPS(lhsCRef, rhsRef, expectedOrdering);
}
-
void tst_QCborValue::comparisonMap_data()
{
QTest::addColumn<QCborMap>("left");
@@ -2131,6 +2315,7 @@ void tst_QCborValue::toCbor_data()
QTest::newRow("UseInteger:-2^65") << QCborValue(-2 * 18446744073709551616.0) << raw("\xfb\xc4\0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
}
+#if QT_CONFIG(cborstreamwriter)
void tst_QCborValue::toCbor()
{
QFETCH(QCborValue, v);
@@ -2170,6 +2355,7 @@ void tst_QCborValue::toCborStreamWriter()
QCOMPARE(buffer.pos(), result.size());
QCOMPARE(output, result);
}
+#endif
void tst_QCborValue::fromCbor_data()
{
@@ -2487,12 +2673,14 @@ void tst_QCborValue::extendedTypeValidation()
QCOMPARE(error.offset, data.size());
QT_TEST_EQUALITY_OPS(decoded, expected, true);
+#if QT_CONFIG(cborstreamwriter)
QByteArray encoded = decoded.toCbor();
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
// behavior change, see qdatetime.cpp:fromIsoTimeString
QEXPECT_FAIL("DateTime:Null-at-19", "QDateTime parsing fixed, but only in 6.0", Abort);
#endif
QCOMPARE(encoded, data);
+#endif
}
void tst_QCborValue::hugeDeviceValidation_data()
@@ -2820,7 +3008,9 @@ template <typename ValueRef> static void cborValueRef_template()
else
QCOMPARE(ref.toVariant(), v.toVariant());
QCOMPARE(ref.toJsonValue(), v.toJsonValue());
+#if QT_CONFIG(cborstreamwriter)
QCOMPARE(ref.toCbor(), v.toCbor());
+#endif
QCOMPARE(ref.toDiagnosticNotation(), v.toDiagnosticNotation());
}
@@ -2980,6 +3170,7 @@ void tst_QCborValue::datastreamSerialization_data()
void tst_QCborValue::datastreamSerialization()
{
+#if QT_CONFIG(cborstreamwriter)
QFETCH(QCborValue, v);
QByteArray buffer;
{
@@ -3007,6 +3198,7 @@ void tst_QCborValue::datastreamSerialization()
load >> output;
QCOMPARE(output, map);
}
+#endif
}
void tst_QCborValue::streamVariantSerialization()
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 77ca884897..9a227c782d 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -143,9 +143,11 @@ private slots:
void stream_QJsonObject();
void stream_QJsonValue();
+#if QT_CONFIG(cborstreamwriter)
void stream_QCborArray();
void stream_QCborMap();
void stream_QCborValue();
+#endif
void setVersion_data();
void setVersion();
@@ -2326,6 +2328,7 @@ void tst_QDataStream::stream_QJsonValue()
}
}
+#if QT_CONFIG(cborstreamwriter)
void tst_QDataStream::stream_QCborArray()
{
QByteArray buffer;
@@ -2361,6 +2364,7 @@ void tst_QDataStream::stream_QCborValue()
load >> valueLoad;
QCOMPARE(valueLoad, valueSave);
}
+#endif
void tst_QDataStream::setVersion_data()
{
@@ -3254,11 +3258,13 @@ void tst_QDataStream::streamRealDataTypes()
// Generate QPicture from pixmap.
QPixmap pm(open_xpm);
QVERIFY(!pm.isNull());
+#ifndef QT_NO_PICTURE
QPicture picture;
picture.setBoundingRect(QRect(QPoint(0, 0), pm.size()));
QPainter painter(&picture);
painter.drawPixmap(0, 0, pm);
painter.end();
+#endif
// Generate path
QPainterPath path;
@@ -3296,7 +3302,9 @@ void tst_QDataStream::streamRealDataTypes()
stream << QPointF(3, 5) << QRectF(-1, -2, 3, 4) << (QPolygonF() << QPointF(0, 0) << QPointF(1, 2));
stream << QTransform().rotate(90).scale(2, 2).asAffineMatrix();
stream << path;
+#ifndef QT_NO_PICTURE
stream << picture;
+#endif
stream << QTextLength(QTextLength::VariableLength, 1.5);
stream << color;
stream << radialBrush << conicalBrush;
@@ -3310,7 +3318,9 @@ void tst_QDataStream::streamRealDataTypes()
QPolygonF polygon {{3, 4}, {5, 6}};
QTransform transform;
QPainterPath p = otherPath;
+#ifndef QT_NO_PICTURE
QPicture pict;
+#endif
QTextLength textLength(QTextLength::FixedLength, 2.5);
QColor col(128, 128, 127);
QBrush rGrad(Qt::CrossPattern);
@@ -3363,6 +3373,7 @@ void tst_QDataStream::streamRealDataTypes()
QCOMPARE(transform, QTransform().rotate(90).scale(2, 2));
stream >> p;
QCOMPARE(p, path);
+#ifndef QT_NO_PICTURE
if (i == 1) {
stream >> pict;
@@ -3376,6 +3387,7 @@ void tst_QDataStream::streamRealDataTypes()
QCOMPARE(pictA, pictB);
}
+#endif
stream >> textLength;
QCOMPARE(textLength, QTextLength(QTextLength::VariableLength, 1.5));
stream >> col;
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index 0b7d9ab0ed..b90d05b0fa 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -95,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;
@@ -572,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;
@@ -747,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;
@@ -1406,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") << "<" << "&lt;";
+ QTest::newRow("greater-than") << ">" << "&gt;";
+ QTest::newRow("ampersand") << "&" << "&amp;";
+ QTest::newRow("quote") << "\"" << "&quot;";
+}
+
+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" << "&#9;";
+ QTest::newRow("newline") << "\n" << "&#10;";
+ QTest::newRow("carriage-return") << "\r" << "&#13;";
+}
+
+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>"));