diff options
Diffstat (limited to 'tests/auto/corelib/serialization/json/tst_qtjson.cpp')
-rw-r--r-- | tests/auto/corelib/serialization/json/tst_qtjson.cpp | 121 |
1 files changed, 119 insertions, 2 deletions
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index ecbdb0ab22..fbf0eacbd5 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -33,6 +33,7 @@ #include "qjsonvalue.h" #include "qjsondocument.h" #include "qregularexpression.h" +#include "private/qnumeric_p.h" #include <limits> #define INVALID_UNICODE "\xCE\xBA\xE1" @@ -53,6 +54,7 @@ private Q_SLOTS: void testNumbers_4(); void testObjectSimple(); + void testObjectTakeDetach(); void testObjectSmallKeys(); void testObjectInsertCopies(); void testArraySimple(); @@ -66,6 +68,7 @@ private Q_SLOTS: void testObjectNestedEmpty(); void testValueRef(); + void testValueRefComparison(); void testObjectIteration(); void testArrayIteration(); @@ -174,6 +177,8 @@ private Q_SLOTS: void fromToVariantConversions_data(); void fromToVariantConversions(); + void noLeakOnNameClash(); + private: QString testDataDir; }; @@ -522,6 +527,24 @@ void tst_QtJson::testObjectSimple() QCOMPARE(subvalue.toObject(), subobject); } +void tst_QtJson::testObjectTakeDetach() +{ + QJsonObject object1, object2; + object1["key1"] = 1; + object1["key2"] = 2; + object2 = object1; + + object1.take("key2"); + object1.remove("key1"); + QVERIFY(!object1.contains("key1")); + QVERIFY(object2.contains("key1")); + QVERIFY(object2.value("key1").isDouble()); + + QVERIFY(!object1.contains("key2")); + QVERIFY(object2.contains("key2")); + QVERIFY(object2.value("key2").isDouble()); +} + void tst_QtJson::testObjectSmallKeys() { QJsonObject data1; @@ -709,15 +732,20 @@ void tst_QtJson::testValueObject() void tst_QtJson::testValueArray() { QJsonArray array; + QJsonArray otherArray = {"wrong value"}; + QJsonValue value(array); + QCOMPARE(value.toArray(), array); + QCOMPARE(value.toArray(otherArray), array); + array.append(999.); array.append(QLatin1String("test")); array.append(true); - - QJsonValue value(array); + value = array; // if we don't modify the original JsonArray, toArray() // on the JsonValue should return the same object (non-detached). QCOMPARE(value.toArray(), array); + QCOMPARE(value.toArray(otherArray), array); // if we modify the original array, it should detach array.append(QLatin1String("test")); @@ -727,14 +755,23 @@ void tst_QtJson::testValueArray() void tst_QtJson::testObjectNested() { QJsonObject inner, outer; + QJsonObject otherObject = {{"wrong key", "wrong value"}}; + QJsonValue v = inner; + QCOMPARE(v.toObject(), inner); + QCOMPARE(v.toObject(otherObject), inner); + inner.insert("number", 999.); outer.insert("nested", inner); // if we don't modify the original JsonObject, value() // should return the same object (non-detached). QJsonObject value = outer.value("nested").toObject(); + v = value; QCOMPARE(value, inner); QCOMPARE(value.value("number").toDouble(), 999.); + QCOMPARE(v.toObject(), inner); + QCOMPARE(v.toObject(otherObject), inner); + QCOMPARE(v["number"].toDouble(), 999.); // if we modify the original object, it should detach and not // affect the nested object @@ -888,6 +925,57 @@ void tst_QtJson::testValueRef() QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42)); } +void tst_QtJson::testValueRefComparison() +{ + QJsonValue a0 = 42.; + QJsonValue a1 = QStringLiteral("142"); + +#define CHECK_IMPL(lhs, rhs, ineq) \ + QCOMPARE(lhs, rhs); \ + QVERIFY(!(lhs != rhs)); \ + QVERIFY(lhs != ineq); \ + QVERIFY(!(lhs == ineq)); \ + QVERIFY(ineq != rhs); \ + QVERIFY(!(ineq == rhs)); \ + /* end */ + +#define CHECK(lhs, rhs, ineq) \ + do { \ + CHECK_IMPL(lhs, rhs, ineq) \ + CHECK_IMPL(qAsConst(lhs), rhs, ineq) \ + CHECK_IMPL(lhs, qAsConst(rhs), ineq) \ + CHECK_IMPL(qAsConst(lhs), qAsConst(rhs), ineq) \ + } while (0) + + // check that the (in)equality operators aren't ambiguous in C++20: + QJsonArray a = {a0, a1}; + + Q_STATIC_ASSERT((std::is_same<decltype(a[0]), QJsonValueRef>::value)); + + auto r0 = a.begin()[0]; + auto r1 = a.begin()[1]; + auto c0 = qAsConst(a).begin()[0]; + // ref <> ref + CHECK(r0, r0, r1); + // cref <> ref + CHECK(c0, r0, r1); + // ref <> cref + CHECK(r0, c0, r1); + // ref <> val + CHECK(r0, a0, r1); + // cref <> val + CHECK(c0, a0, r1); + // val <> ref + CHECK(a0, r0, a1); + // val <> cref + CHECK(a0, c0, a1); + // val <> val + CHECK(a0, a0, a1); + +#undef CHECK +#undef CHECK_IMPL +} + void tst_QtJson::testObjectIteration() { QJsonObject object; @@ -3584,6 +3672,17 @@ void tst_QtJson::fromToVariantConversions_data() << QVariant::fromValue(nullptr); QTest::newRow("NaN") << QVariant(qQNaN()) << QJsonValue(QJsonValue::Null) << QVariant::fromValue(nullptr); + + const qulonglong ulongValue = (1ul << 63) + 1; + const double uLongToDouble = ulongValue; + qint64 n; + if (convertDoubleTo(uLongToDouble, &n)) { + QTest::newRow("ulonglong") << QVariant(ulongValue) << QJsonValue(uLongToDouble) + << QVariant(n); + } else { + QTest::newRow("ulonglong") << QVariant(ulongValue) << QJsonValue(uLongToDouble) + << QVariant(uLongToDouble); + } } void tst_QtJson::fromToVariantConversions() @@ -3654,5 +3753,23 @@ void tst_QtJson::fromToVariantConversions() } } +void tst_QtJson::noLeakOnNameClash() +{ + QJsonDocument doc = QJsonDocument::fromJson("{\"\":{\"\":0},\"\":0}"); + QVERIFY(!doc.isNull()); + const QJsonObject obj = doc.object(); + + // Removed the duplicate key. + QCOMPARE(obj.length(), 1); + + // Retained the last of the duplicates. + const QJsonValue val = obj.begin().value(); + QVERIFY(val.isDouble()); + QCOMPARE(val.toDouble(), 0.0); + + // It should not leak. + // In particular it should not forget to deref the container for the inner object. +} + QTEST_MAIN(tst_QtJson) #include "tst_qtjson.moc" |