diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-12-12 18:32:19 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2018-01-26 20:59:50 +0000 |
commit | a6b697ca13945a174cff9f3e9b1af1cf61c0bea5 (patch) | |
tree | 78d5fad97ff8e89f079df29cc5a75b4e7197bfc7 /tests/auto/corelib/json/tst_qtjson.cpp | |
parent | 657894624521b580f59ff5f58b9c0e9be159dc1c (diff) |
Create corelib/serialization and move existing file formats into it
This is in preparation to adding CBOR support. We don't need yet another
dir for CBOR and placing it in src/corelib/json is just wrong.
Change-Id: I9741f017961b410c910dfffd14ffb9d870340fa6
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib/json/tst_qtjson.cpp')
-rw-r--r-- | tests/auto/corelib/json/tst_qtjson.cpp | 2990 |
1 files changed, 0 insertions, 2990 deletions
diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp deleted file mode 100644 index 1e3604ac9e..0000000000 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ /dev/null @@ -1,2990 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <QtTest> - -#include "qjsonarray.h" -#include "qjsonobject.h" -#include "qjsonvalue.h" -#include "qjsondocument.h" -#include "qregularexpression.h" -#include <limits> - -#define INVALID_UNICODE "\xCE\xBA\xE1" -#define UNICODE_NON_CHARACTER "\xEF\xBF\xBF" -#define UNICODE_DJE "\320\202" // Character from the Serbian Cyrillic alphabet - -class tst_QtJson: public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void initTestCase(); - - void testValueSimple(); - void testNumbers(); - void testNumbers_2(); - void testNumbers_3(); - void testNumbers_4(); - - void testObjectSimple(); - void testObjectSmallKeys(); - void testArraySimple(); - void testValueObject(); - void testValueArray(); - void testObjectNested(); - void testArrayNested(); - void testArrayNestedEmpty(); - void testArrayComfortOperators(); - void testObjectNestedEmpty(); - - void testValueRef(); - void testObjectIteration(); - void testArrayIteration(); - - void testObjectFind(); - - void testDocument(); - - void nullValues(); - void nullArrays(); - void nullObject(); - void constNullObject(); - - void keySorting(); - - void undefinedValues(); - - void fromVariant_data(); - void fromVariant(); - void toVariant_data(); - void toVariant(); - void fromVariantMap(); - void fromVariantHash(); - void toVariantMap(); - void toVariantHash(); - void toVariantList(); - - void toJson(); - void toJsonSillyNumericValues(); - void toJsonLargeNumericValues(); - void fromJson(); - void fromJsonErrors(); - void fromBinary(); - void toAndFromBinary_data(); - void toAndFromBinary(); - void invalidBinaryData(); - void parseNumbers(); - void parseStrings(); - void parseDuplicateKeys(); - void testParser(); - - void compactArray(); - void compactObject(); - - void validation(); - - void assignToDocument(); - - void testDuplicateKeys(); - void testCompaction(); - void testDebugStream(); - void testCompactionError(); - - void parseUnicodeEscapes(); - - void assignObjects(); - void assignArrays(); - - void testTrailingComma(); - void testDetachBug(); - void testJsonValueRefDefault(); - - void valueEquals(); - void objectEquals_data(); - void objectEquals(); - void arrayEquals_data(); - void arrayEquals(); - - void bom(); - void nesting(); - - void longStrings(); - - void arrayInitializerList(); - void objectInitializerList(); - - void unicodeKeys(); - void garbageAtEnd(); - - void removeNonLatinKey(); - void documentFromVariant(); - - void parseErrorOffset_data(); - void parseErrorOffset(); - - void implicitValueType(); - void implicitDocumentType(); - -private: - QString testDataDir; -}; - -void tst_QtJson::initTestCase() -{ - testDataDir = QFileInfo(QFINDTESTDATA("test.json")).absolutePath(); - if (testDataDir.isEmpty()) - testDataDir = QCoreApplication::applicationDirPath(); -} - -void tst_QtJson::testValueSimple() -{ - QJsonObject object; - object.insert("number", 999.); - QJsonArray array; - for (int i = 0; i < 10; ++i) - array.append((double)i); - - QJsonValue value(true); - QCOMPARE(value.type(), QJsonValue::Bool); - QCOMPARE(value.toDouble(), 0.); - QCOMPARE(value.toString(), QString()); - QCOMPARE(value.toBool(), true); - QCOMPARE(value.toObject(), QJsonObject()); - QCOMPARE(value.toArray(), QJsonArray()); - QCOMPARE(value.toDouble(99.), 99.); - QCOMPARE(value.toString(QString("test")), QString("test")); - QCOMPARE(value.toObject(object), object); - QCOMPARE(value.toArray(array), array); - - value = 999.; - QCOMPARE(value.type(), QJsonValue::Double); - QCOMPARE(value.toDouble(), 999.); - QCOMPARE(value.toString(), QString()); - QCOMPARE(value.toBool(), false); - QCOMPARE(value.toBool(true), true); - QCOMPARE(value.toObject(), QJsonObject()); - QCOMPARE(value.toArray(), QJsonArray()); - - value = QLatin1String("test"); - QCOMPARE(value.toDouble(), 0.); - QCOMPARE(value.toString(), QLatin1String("test")); - QCOMPARE(value.toBool(), false); - QCOMPARE(value.toObject(), QJsonObject()); - QCOMPARE(value.toArray(), QJsonArray()); -} - -void tst_QtJson::testNumbers() -{ - { - int numbers[] = { - 0, - -1, - 1, - (1<<26), - (1<<27), - (1<<28), - -(1<<26), - -(1<<27), - -(1<<28), - (1<<26) - 1, - (1<<27) - 1, - (1<<28) - 1, - -((1<<26) - 1), - -((1<<27) - 1), - -((1<<28) - 1) - }; - int n = sizeof(numbers)/sizeof(int); - - QJsonArray array; - for (int i = 0; i < n; ++i) - array.append((double)numbers[i]); - - QByteArray serialized = QJsonDocument(array).toJson(); - QJsonDocument json = QJsonDocument::fromJson(serialized); - QJsonArray array2 = json.array(); - - QCOMPARE(array.size(), array2.size()); - for (int i = 0; i < array.size(); ++i) { - QCOMPARE(array.at(i).type(), QJsonValue::Double); - QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); - QCOMPARE(array2.at(i).type(), QJsonValue::Double); - QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); - } - } - - { - qint64 numbers[] = { - 0, - -1, - 1, - (1ll<<54), - (1ll<<55), - (1ll<<56), - -(1ll<<54), - -(1ll<<55), - -(1ll<<56), - (1ll<<54) - 1, - (1ll<<55) - 1, - (1ll<<56) - 1, - -((1ll<<54) - 1), - -((1ll<<55) - 1), - -((1ll<<56) - 1) - }; - int n = sizeof(numbers)/sizeof(qint64); - - QJsonArray array; - for (int i = 0; i < n; ++i) - array.append((double)numbers[i]); - - QByteArray serialized = QJsonDocument(array).toJson(); - QJsonDocument json = QJsonDocument::fromJson(serialized); - QJsonArray array2 = json.array(); - - QCOMPARE(array.size(), array2.size()); - for (int i = 0; i < array.size(); ++i) { - QCOMPARE(array.at(i).type(), QJsonValue::Double); - QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); - QCOMPARE(array2.at(i).type(), QJsonValue::Double); - QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); - } - } - - { - double numbers[] = { - 0, - -1, - 1, - double(1ll<<54), - double(1ll<<55), - double(1ll<<56), - double(-(1ll<<54)), - double(-(1ll<<55)), - double(-(1ll<<56)), - double((1ll<<54) - 1), - double((1ll<<55) - 1), - double((1ll<<56) - 1), - double(-((1ll<<54) - 1)), - double(-((1ll<<55) - 1)), - double(-((1ll<<56) - 1)), - 1.1, - 0.1, - -0.1, - -1.1, - 1e200, - -1e200 - }; - int n = sizeof(numbers)/sizeof(double); - - QJsonArray array; - for (int i = 0; i < n; ++i) - array.append(numbers[i]); - - QByteArray serialized = QJsonDocument(array).toJson(); - QJsonDocument json = QJsonDocument::fromJson(serialized); - QJsonArray array2 = json.array(); - - QCOMPARE(array.size(), array2.size()); - for (int i = 0; i < array.size(); ++i) { - QCOMPARE(array.at(i).type(), QJsonValue::Double); - QCOMPARE(array.at(i).toDouble(), numbers[i]); - QCOMPARE(array2.at(i).type(), QJsonValue::Double); - QCOMPARE(array2.at(i).toDouble(), numbers[i]); - } - } - -} - -void tst_QtJson::testNumbers_2() -{ - // test cases from TC39 test suite for ECMAScript - // http://hg.ecmascript.org/tests/test262/file/d067d2f0ca30/test/suite/ch08/8.5/8.5.1.js - - // Fill an array with 2 to the power of (0 ... -1075) - double value = 1; - double floatValues[1076], floatValues_1[1076]; - QJsonObject jObject; - for (int power = 0; power <= 1075; power++) { - floatValues[power] = value; - jObject.insert(QString::number(power), QJsonValue(floatValues[power])); - // Use basic math operations for testing, which are required to support 'gradual underflow' rather - // than Math.pow etc..., which are defined as 'implementation dependent'. - value = value * 0.5; - } - - QJsonDocument jDocument1(jObject); - QByteArray ba(jDocument1.toJson()); - - QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); - for (int power = 0; power <= 1075; power++) { - floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble(); -#ifdef Q_OS_QNX - if (power >= 970) - QEXPECT_FAIL("", "See QTBUG-37066", Abort); -#endif - QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1()); - } - - // The last value is below min denorm and should round to 0, everything else should contain a value - QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0"); - - // Validate the last actual value is min denorm - QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1()); - - // Validate that every value is half the value before it up to 1 - for (int index = 1074; index > 0; index--) { - QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1()); - - QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1()); - } -} - -void tst_QtJson::testNumbers_3() -{ - // test case from QTBUG-31926 - double d1 = 1.123451234512345; - double d2 = 1.123451234512346; - - QJsonObject jObject; - jObject.insert("d1", QJsonValue(d1)); - jObject.insert("d2", QJsonValue(d2)); - QJsonDocument jDocument1(jObject); - QByteArray ba(jDocument1.toJson()); - - QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); - - double d1_1(jDocument2.object().value("d1").toDouble()); - double d2_1(jDocument2.object().value("d2").toDouble()); - QVERIFY(d1_1 != d2_1); -} - -void tst_QtJson::testNumbers_4() -{ - // no exponent notation used to print numbers between -2^64 and 2^64 - QJsonArray array; - array << QJsonValue(+1000000000000000.0); - array << QJsonValue(-1000000000000000.0); - array << QJsonValue(+9007199254740992.0); - array << QJsonValue(-9007199254740992.0); - array << QJsonValue(+9223372036854775808.0); - array << QJsonValue(-9223372036854775808.0); - array << QJsonValue(+18446744073709551616.0); - array << QJsonValue(-18446744073709551616.0); - const QByteArray json(QJsonDocument(array).toJson()); - const QByteArray expected = - "[\n" - " 1000000000000000,\n" - " -1000000000000000,\n" - " 9007199254740992,\n" - " -9007199254740992,\n" - " 9223372036854776000,\n" - " -9223372036854776000,\n" - " 18446744073709552000,\n" - " -18446744073709552000\n" - "]\n"; - QCOMPARE(json, expected); -} - -void tst_QtJson::testObjectSimple() -{ - QJsonObject object; - object.insert("number", 999.); - QCOMPARE(object.value("number").type(), QJsonValue::Double); - QCOMPARE(object.value(QLatin1String("number")).toDouble(), 999.); - object.insert("string", QString::fromLatin1("test")); - QCOMPARE(object.value("string").type(), QJsonValue::String); - QCOMPARE(object.value(QLatin1String("string")).toString(), QString("test")); - object.insert("boolean", true); - QCOMPARE(object.value("boolean").toBool(), true); - QCOMPARE(object.value(QLatin1String("boolean")).toBool(), true); - - QStringList keys = object.keys(); - QVERIFY2(keys.contains("number"), "key number not found"); - QVERIFY2(keys.contains("string"), "key string not found"); - QVERIFY2(keys.contains("boolean"), "key boolean not found"); - - // if we put a JsonValue into the JsonObject and retrieve - // it, it should be identical. - QJsonValue value(QLatin1String("foo")); - object.insert("value", value); - QCOMPARE(object.value("value"), value); - - int size = object.size(); - object.remove("boolean"); - QCOMPARE(object.size(), size - 1); - QVERIFY2(!object.contains("boolean"), "key boolean should have been removed"); - - QJsonValue taken = object.take("value"); - QCOMPARE(taken, value); - QVERIFY2(!object.contains("value"), "key value should have been removed"); - - QString before = object.value("string").toString(); - object.insert("string", QString::fromLatin1("foo")); - QVERIFY2(object.value(QLatin1String("string")).toString() != before, "value should have been updated"); - - size = object.size(); - QJsonObject subobject; - subobject.insert("number", 42); - subobject.insert(QLatin1String("string"), QLatin1String("foobar")); - object.insert("subobject", subobject); - QCOMPARE(object.size(), size+1); - QJsonValue subvalue = object.take(QLatin1String("subobject")); - QCOMPARE(object.size(), size); - QCOMPARE(subvalue.toObject(), subobject); - // make object detach by modifying it many times - for (int i = 0; i < 64; ++i) - object.insert(QLatin1String("string"), QLatin1String("bar")); - QCOMPARE(object.size(), size); - QCOMPARE(subvalue.toObject(), subobject); -} - -void tst_QtJson::testObjectSmallKeys() -{ - QJsonObject data1; - data1.insert(QStringLiteral("1"), 123.); - QVERIFY(data1.contains(QStringLiteral("1"))); - QCOMPARE(data1.value(QStringLiteral("1")).toDouble(), (double)123); - data1.insert(QStringLiteral("12"), 133.); - QCOMPARE(data1.value(QStringLiteral("12")).toDouble(), (double)133); - QVERIFY(data1.contains(QStringLiteral("12"))); - data1.insert(QStringLiteral("123"), 323.); - QCOMPARE(data1.value(QStringLiteral("12")).toDouble(), (double)133); - QVERIFY(data1.contains(QStringLiteral("123"))); - QCOMPARE(data1.value(QStringLiteral("123")).type(), QJsonValue::Double); - QCOMPARE(data1.value(QStringLiteral("123")).toDouble(), (double)323); -} - -void tst_QtJson::testArraySimple() -{ - QJsonArray array; - array.append(999.); - array.append(QString::fromLatin1("test")); - array.append(true); - - QJsonValue val = array.at(0); - QCOMPARE(array.at(0).toDouble(), 999.); - QCOMPARE(array.at(1).toString(), QString("test")); - QCOMPARE(array.at(2).toBool(), true); - QCOMPARE(array.size(), 3); - - // if we put a JsonValue into the JsonArray and retrieve - // it, it should be identical. - QJsonValue value(QLatin1String("foo")); - array.append(value); - QCOMPARE(array.at(3), value); - - int size = array.size(); - array.removeAt(2); - --size; - QCOMPARE(array.size(), size); - - QJsonValue taken = array.takeAt(0); - --size; - QCOMPARE(taken.toDouble(), 999.); - QCOMPARE(array.size(), size); - - // check whether null values work - array.append(QJsonValue()); - ++size; - QCOMPARE(array.size(), size); - QCOMPARE(array.last().type(), QJsonValue::Null); - QCOMPARE(array.last(), QJsonValue()); - - QCOMPARE(array.first().type(), QJsonValue::String); - QCOMPARE(array.first(), QJsonValue(QLatin1String("test"))); - - array.prepend(false); - QCOMPARE(array.first().type(), QJsonValue::Bool); - QCOMPARE(array.first(), QJsonValue(false)); - - QCOMPARE(array.at(-1), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(array.at(array.size()), QJsonValue(QJsonValue::Undefined)); - - array.replace(0, -555.); - QCOMPARE(array.first().type(), QJsonValue::Double); - QCOMPARE(array.first(), QJsonValue(-555.)); - QCOMPARE(array.at(1).type(), QJsonValue::String); - QCOMPARE(array.at(1), QJsonValue(QLatin1String("test"))); -} - -void tst_QtJson::testValueObject() -{ - QJsonObject object; - object.insert("number", 999.); - object.insert("string", QLatin1String("test")); - object.insert("boolean", true); - - QJsonValue value(object); - - // if we don't modify the original JsonObject, toObject() - // on the JsonValue should return the same object (non-detached). - QCOMPARE(value.toObject(), object); - - // if we modify the original object, it should detach - object.insert("test", QJsonValue(QLatin1String("test"))); - QVERIFY2(value.toObject() != object, "object should have detached"); -} - -void tst_QtJson::testValueArray() -{ - QJsonArray array; - array.append(999.); - array.append(QLatin1String("test")); - array.append(true); - - QJsonValue 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); - - // if we modify the original array, it should detach - array.append(QLatin1String("test")); - QVERIFY2(value.toArray() != array, "array should have detached"); -} - -void tst_QtJson::testObjectNested() -{ - QJsonObject inner, outer; - 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(); - QCOMPARE(value, inner); - QCOMPARE(value.value("number").toDouble(), 999.); - - // if we modify the original object, it should detach and not - // affect the nested object - inner.insert("number", 555.); - value = outer.value("nested").toObject(); - QVERIFY2(inner.value("number").toDouble() != value.value("number").toDouble(), - "object should have detached"); - - // array in object - QJsonArray array; - array.append(123.); - array.append(456.); - outer.insert("array", array); - QCOMPARE(outer.value("array").toArray(), array); - QCOMPARE(outer.value("array").toArray().at(1).toDouble(), 456.); - - // two deep objects - QJsonObject twoDeep; - twoDeep.insert("boolean", true); - inner.insert("nested", twoDeep); - outer.insert("nested", inner); - QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep); - QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(), - true); -} - -void tst_QtJson::testArrayNested() -{ - QJsonArray inner, outer; - inner.append(999.); - outer.append(inner); - - // if we don't modify the original JsonArray, value() - // should return the same array (non-detached). - QJsonArray value = outer.at(0).toArray(); - QCOMPARE(value, inner); - QCOMPARE(value.at(0).toDouble(), 999.); - - // if we modify the original array, it should detach and not - // affect the nested array - inner.append(555.); - value = outer.at(0).toArray(); - QVERIFY2(inner.size() != value.size(), "array should have detached"); - - // objects in arrays - QJsonObject object; - object.insert("boolean", true); - outer.append(object); - QCOMPARE(outer.last().toObject(), object); - QCOMPARE(outer.last().toObject().value("boolean").toBool(), true); - - // two deep arrays - QJsonArray twoDeep; - twoDeep.append(QJsonValue(QString::fromLatin1("nested"))); - inner.append(twoDeep); - outer.append(inner); - QCOMPARE(outer.last().toArray().last().toArray(), twoDeep); - QCOMPARE(outer.last().toArray().last().toArray().at(0).toString(), QString("nested")); -} - -void tst_QtJson::testArrayNestedEmpty() -{ - QJsonObject object; - QJsonArray inner; - object.insert("inner", inner); - QJsonValue val = object.value("inner"); - QJsonArray value = object.value("inner").toArray(); - QCOMPARE(value.size(), 0); - QCOMPARE(value, inner); - QCOMPARE(value.size(), 0); - object.insert("count", 0.); - QCOMPARE(object.value("inner").toArray().size(), 0); - QVERIFY(object.value("inner").toArray().isEmpty()); - QJsonDocument(object).toBinaryData(); - QCOMPARE(object.value("inner").toArray().size(), 0); -} - -void tst_QtJson::testObjectNestedEmpty() -{ - QJsonObject object; - QJsonObject inner; - QJsonObject inner2; - object.insert("inner", inner); - object.insert("inner2", inner2); - QJsonObject value = object.value("inner").toObject(); - QCOMPARE(value.size(), 0); - QCOMPARE(value, inner); - QCOMPARE(value.size(), 0); - object.insert("count", 0.); - QCOMPARE(object.value("inner").toObject().size(), 0); - QCOMPARE(object.value("inner").type(), QJsonValue::Object); - QJsonDocument(object).toBinaryData(); - QVERIFY(object.value("inner").toObject().isEmpty()); - QVERIFY(object.value("inner2").toObject().isEmpty()); - QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(object).toBinaryData()); - QVERIFY(!doc.isNull()); - QJsonObject reconstituted(doc.object()); - QCOMPARE(reconstituted.value("inner").toObject().size(), 0); - QCOMPARE(reconstituted.value("inner").type(), QJsonValue::Object); - QCOMPARE(reconstituted.value("inner2").type(), QJsonValue::Object); -} - -void tst_QtJson::testArrayComfortOperators() -{ - QJsonArray first; - first.append(123.); - first.append(QLatin1String("foo")); - - QJsonArray second = QJsonArray() << 123. << QLatin1String("foo"); - QCOMPARE(first, second); - - first = first + QLatin1String("bar"); - second += QLatin1String("bar"); - QCOMPARE(first, second); -} - -void tst_QtJson::testValueRef() -{ - QJsonArray array; - array.append(1.); - array.append(2.); - array.append(3.); - array.append(4); - array.append(4.1); - array[1] = false; - - QCOMPARE(array.size(), 5); - QCOMPARE(array.at(0).toDouble(), 1.); - QCOMPARE(array.at(2).toDouble(), 3.); - QCOMPARE(array.at(3).toInt(), 4); - QCOMPARE(array.at(4).toInt(), 0); - QCOMPARE(array.at(1).type(), QJsonValue::Bool); - QCOMPARE(array.at(1).toBool(), false); - - QJsonObject object; - object[QLatin1String("key")] = true; - QCOMPARE(object.size(), 1); - object.insert(QLatin1String("null"), QJsonValue()); - QCOMPARE(object.value(QLatin1String("null")), QJsonValue()); - object[QLatin1String("null")] = 100.; - QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double); - QJsonValue val = qAsConst(object)[QLatin1String("null")]; - QCOMPARE(val.toDouble(), 100.); - QCOMPARE(object.size(), 2); - - array[1] = array[2] = object[QLatin1String("key")] = 42; - QCOMPARE(array[1], array[2]); - QCOMPARE(array[2], object[QLatin1String("key")]); - QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42)); -} - -void tst_QtJson::testObjectIteration() -{ - QJsonObject object; - - for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) - QVERIFY(false); - - const QString property = "kkk"; - object.insert(property, 11); - object.take(property); - for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) - QVERIFY(false); - - for (int i = 0; i < 10; ++i) - object[QString::number(i)] = (double)i; - - QCOMPARE(object.size(), 10); - - QCOMPARE(object.begin()->toDouble(), object.constBegin()->toDouble()); - - for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) { - QJsonValue value = it.value(); - QCOMPARE((double)it.key().toInt(), value.toDouble()); - } - - { - QJsonObject object2 = object; - QCOMPARE(object, object2); - - QJsonValue val = *object2.begin(); - object2.erase(object2.begin()); - QCOMPARE(object.size(), 10); - QCOMPARE(object2.size(), 9); - - for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) { - QJsonValue value = it.value(); - QVERIFY(it.value() != val); - QCOMPARE((double)it.key().toInt(), value.toDouble()); - } - } - - { - QJsonObject object2 = object; - QCOMPARE(object, object2); - - QJsonObject::iterator it = object2.find(QString::number(5)); - object2.erase(it); - QCOMPARE(object.size(), 10); - QCOMPARE(object2.size(), 9); - } - - { - QJsonObject::Iterator it = object.begin(); - it += 5; - QCOMPARE(QJsonValue(it.value()).toDouble(), 5.); - it -= 3; - QCOMPARE(QJsonValue(it.value()).toDouble(), 2.); - QJsonObject::Iterator it2 = it + 5; - QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.); - it2 = it - 1; - QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.); - } - - { - QJsonObject::ConstIterator it = object.constBegin(); - it += 5; - QCOMPARE(QJsonValue(it.value()).toDouble(), 5.); - it -= 3; - QCOMPARE(QJsonValue(it.value()).toDouble(), 2.); - QJsonObject::ConstIterator it2 = it + 5; - QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.); - it2 = it - 1; - QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.); - } - - QJsonObject::Iterator it = object.begin(); - while (!object.isEmpty()) - it = object.erase(it); - QCOMPARE(object.size() , 0); - QCOMPARE(it, object.end()); -} - -void tst_QtJson::testArrayIteration() -{ - QJsonArray array; - for (int i = 0; i < 10; ++i) - array.append(i); - - QCOMPARE(array.size(), 10); - - int i = 0; - for (QJsonArray::iterator it = array.begin(); it != array.end(); ++it, ++i) { - QJsonValue value = (*it); - QCOMPARE((double)i, value.toDouble()); - } - - QCOMPARE(array.begin()->toDouble(), array.constBegin()->toDouble()); - - { - QJsonArray array2 = array; - QCOMPARE(array, array2); - - QJsonValue val = *array2.begin(); - array2.erase(array2.begin()); - QCOMPARE(array.size(), 10); - QCOMPARE(array2.size(), 9); - - i = 1; - for (QJsonArray::const_iterator it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) { - QJsonValue value = (*it); - QCOMPARE((double)i, value.toDouble()); - } - } - - { - QJsonArray::Iterator it = array.begin(); - it += 5; - QCOMPARE(QJsonValue((*it)).toDouble(), 5.); - it -= 3; - QCOMPARE(QJsonValue((*it)).toDouble(), 2.); - QJsonArray::Iterator it2 = it + 5; - QCOMPARE(QJsonValue(*it2).toDouble(), 7.); - it2 = it - 1; - QCOMPARE(QJsonValue(*it2).toDouble(), 1.); - } - - { - QJsonArray::ConstIterator it = array.constBegin(); - it += 5; - QCOMPARE(QJsonValue((*it)).toDouble(), 5.); - it -= 3; - QCOMPARE(QJsonValue((*it)).toDouble(), 2.); - QJsonArray::ConstIterator it2 = it + 5; - QCOMPARE(QJsonValue(*it2).toDouble(), 7.); - it2 = it - 1; - QCOMPARE(QJsonValue(*it2).toDouble(), 1.); - } - - QJsonArray::Iterator it = array.begin(); - while (!array.isEmpty()) - it = array.erase(it); - QCOMPARE(array.size() , 0); - QCOMPARE(it, array.end()); -} - -void tst_QtJson::testObjectFind() -{ - QJsonObject object; - for (int i = 0; i < 10; ++i) - object[QString::number(i)] = i; - - QCOMPARE(object.size(), 10); - - QJsonObject::iterator it = object.find(QLatin1String("1")); - QCOMPARE((*it).toDouble(), 1.); - it = object.find(QString("11")); - QCOMPARE((*it).type(), QJsonValue::Undefined); - QCOMPARE(it, object.end()); - - QJsonObject::const_iterator cit = object.constFind(QLatin1String("1")); - QCOMPARE((*cit).toDouble(), 1.); - cit = object.constFind(QString("11")); - QCOMPARE((*it).type(), QJsonValue::Undefined); - QCOMPARE(it, object.end()); -} - -void tst_QtJson::testDocument() -{ - QJsonDocument doc; - QCOMPARE(doc.isEmpty(), true); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), false); - - QJsonObject object; - doc.setObject(object); - QCOMPARE(doc.isEmpty(), false); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - - object.insert(QLatin1String("Key"), QLatin1String("Value")); - doc.setObject(object); - QCOMPARE(doc.isEmpty(), false); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QCOMPARE(doc.object(), object); - QCOMPARE(doc.array(), QJsonArray()); - - doc = QJsonDocument(); - QCOMPARE(doc.isEmpty(), true); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), false); - - QJsonArray array; - doc.setArray(array); - QCOMPARE(doc.isEmpty(), false); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - - array.append(QLatin1String("Value")); - doc.setArray(array); - QCOMPARE(doc.isEmpty(), false); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QCOMPARE(doc.array(), array); - QCOMPARE(doc.object(), QJsonObject()); - - QJsonObject outer; - outer.insert(QLatin1String("outerKey"), 22); - QJsonObject inner; - inner.insert(QLatin1String("innerKey"), 42); - outer.insert(QLatin1String("innter"), inner); - QJsonArray innerArray; - innerArray.append(23); - outer.insert(QLatin1String("innterArray"), innerArray); - - QJsonDocument doc2(outer.value(QLatin1String("innter")).toObject()); - QVERIFY(doc2.object().contains(QLatin1String("innerKey"))); - QCOMPARE(doc2.object().value(QLatin1String("innerKey")), QJsonValue(42)); - - QJsonDocument doc3; - doc3.setObject(outer.value(QLatin1String("innter")).toObject()); - QCOMPARE(doc3.isArray(), false); - QCOMPARE(doc3.isObject(), true); - QVERIFY(doc3.object().contains(QString("innerKey"))); - QCOMPARE(doc3.object().value(QLatin1String("innerKey")), QJsonValue(42)); - - QJsonDocument doc4(outer.value(QLatin1String("innterArray")).toArray()); - QCOMPARE(doc4.isArray(), true); - QCOMPARE(doc4.isObject(), false); - QCOMPARE(doc4.array().size(), 1); - QCOMPARE(doc4.array().at(0), QJsonValue(23)); - - QJsonDocument doc5; - doc5.setArray(outer.value(QLatin1String("innterArray")).toArray()); - QCOMPARE(doc5.isArray(), true); - QCOMPARE(doc5.isObject(), false); - QCOMPARE(doc5.array().size(), 1); - QCOMPARE(doc5.array().at(0), QJsonValue(23)); -} - -void tst_QtJson::nullValues() -{ - QJsonArray array; - array.append(QJsonValue()); - - QCOMPARE(array.size(), 1); - QCOMPARE(array.at(0), QJsonValue()); - - QJsonObject object; - object.insert(QString("key"), QJsonValue()); - QCOMPARE(object.contains(QLatin1String("key")), true); - QCOMPARE(object.size(), 1); - QCOMPARE(object.value(QString("key")), QJsonValue()); -} - -void tst_QtJson::nullArrays() -{ - QJsonArray nullArray; - QJsonArray nonNull; - nonNull.append(QLatin1String("bar")); - - QCOMPARE(nullArray, QJsonArray()); - QVERIFY(nullArray != nonNull); - QVERIFY(nonNull != nullArray); - - QCOMPARE(nullArray.size(), 0); - QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined)); - nullArray.removeAt(0); - nullArray.removeAt(-1); - - nullArray.append(QString("bar")); - nullArray.removeAt(0); - - QCOMPARE(nullArray.size(), 0); - QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined)); - nullArray.removeAt(0); - nullArray.removeAt(-1); -} - -void tst_QtJson::nullObject() -{ - QJsonObject nullObject; - QJsonObject nonNull; - nonNull.insert(QLatin1String("foo"), QLatin1String("bar")); - - QCOMPARE(nullObject, QJsonObject()); - QVERIFY(nullObject != nonNull); - QVERIFY(nonNull != nullObject); - - QCOMPARE(nullObject.size(), 0); - QCOMPARE(nullObject.keys(), QStringList()); - nullObject.remove("foo"); - QCOMPARE(nullObject, QJsonObject()); - QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullObject.contains("foo"), false); - - nullObject.insert("foo", QString("bar")); - nullObject.remove("foo"); - - QCOMPARE(nullObject.size(), 0); - QCOMPARE(nullObject.keys(), QStringList()); - nullObject.remove("foo"); - QCOMPARE(nullObject, QJsonObject()); - QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined)); - QCOMPARE(nullObject.contains("foo"), false); -} - -void tst_QtJson::constNullObject() -{ - const QJsonObject nullObject; - QJsonObject nonNull; - nonNull.insert(QLatin1String("foo"), QLatin1String("bar")); - - QCOMPARE(nullObject, QJsonObject()); - QVERIFY(nullObject != nonNull); - QVERIFY(nonNull != nullObject); - - QCOMPARE(nullObject.size(), 0); - QCOMPARE(nullObject.keys(), QStringList()); - QCOMPARE(nullObject, QJsonObject()); - QCOMPARE(nullObject.contains("foo"), false); - QCOMPARE(nullObject["foo"], QJsonValue(QJsonValue::Undefined)); -} - -void tst_QtJson::keySorting() -{ - const char *json = "{ \"B\": true, \"A\": false }"; - QJsonDocument doc = QJsonDocument::fromJson(json); - - QCOMPARE(doc.isObject(), true); - - QJsonObject o = doc.object(); - QCOMPARE(o.size(), 2); - QJsonObject::const_iterator it = o.constBegin(); - QCOMPARE(it.key(), QLatin1String("A")); - ++it; - QCOMPARE(it.key(), QLatin1String("B")); - - QCOMPARE(o.keys(), QStringList() << QLatin1String("A") << QLatin1String("B")); -} - -void tst_QtJson::undefinedValues() -{ - QJsonObject object; - object.insert("Key", QJsonValue(QJsonValue::Undefined)); - QCOMPARE(object.size(), 0); - - object.insert("Key", QLatin1String("Value")); - QCOMPARE(object.size(), 1); - QCOMPARE(object.value("Key").type(), QJsonValue::String); - QCOMPARE(object.value("foo").type(), QJsonValue::Undefined); - object.insert("Key", QJsonValue(QJsonValue::Undefined)); - QCOMPARE(object.size(), 0); - QCOMPARE(object.value("Key").type(), QJsonValue::Undefined); - - QJsonArray array; - array.append(QJsonValue(QJsonValue::Undefined)); - QCOMPARE(array.size(), 1); - QCOMPARE(array.at(0).type(), QJsonValue::Null); - - QCOMPARE(array.at(1).type(), QJsonValue::Undefined); - QCOMPARE(array.at(-1).type(), QJsonValue::Undefined); -} - -void tst_QtJson::fromVariant_data() -{ - QTest::addColumn<QVariant>("variant"); - QTest::addColumn<QJsonValue>("jsonvalue"); - - bool boolValue = true; - int intValue = -1; - uint uintValue = 1; - long long longlongValue = -2; - unsigned long long ulonglongValue = 2; - float floatValue = 3.3f; - double doubleValue = 4.4; - QString stringValue("str"); - - QStringList stringList; - stringList.append(stringValue); - stringList.append("str2"); - QJsonArray jsonArray_string; - jsonArray_string.append(stringValue); - jsonArray_string.append("str2"); - - QVariantList variantList; - variantList.append(boolValue); - variantList.append(floatValue); - variantList.append(doubleValue); - variantList.append(stringValue); - variantList.append(stringList); - variantList.append(QVariant::fromValue(nullptr)); - QJsonArray jsonArray_variant; - jsonArray_variant.append(boolValue); - jsonArray_variant.append(floatValue); - jsonArray_variant.append(doubleValue); - jsonArray_variant.append(stringValue); - jsonArray_variant.append(jsonArray_string); - jsonArray_variant.append(QJsonValue(QJsonValue::Null)); - - QVariantMap variantMap; - variantMap["bool"] = boolValue; - variantMap["float"] = floatValue; - variantMap["string"] = stringValue; - variantMap["array"] = variantList; - QVariantHash variantHash; - variantHash["bool"] = boolValue; - variantHash["float"] = floatValue; - variantHash["string"] = stringValue; - variantHash["array"] = variantList; - QJsonObject jsonObject; - jsonObject["bool"] = boolValue; - jsonObject["float"] = floatValue; - jsonObject["string"] = stringValue; - jsonObject["array"] = jsonArray_variant; - - QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QJsonValue(QJsonValue::Null); - QTest::newRow("bool") << QVariant(boolValue) << QJsonValue(boolValue); - QTest::newRow("int") << QVariant(intValue) << QJsonValue(intValue); - QTest::newRow("uint") << QVariant(uintValue) << QJsonValue(static_cast<double>(uintValue)); - QTest::newRow("longlong") << QVariant(longlongValue) << QJsonValue(longlongValue); - QTest::newRow("ulonglong") << QVariant(ulonglongValue) << QJsonValue(static_cast<double>(ulonglongValue)); - QTest::newRow("float") << QVariant(floatValue) << QJsonValue(floatValue); - QTest::newRow("double") << QVariant(doubleValue) << QJsonValue(doubleValue); - QTest::newRow("string") << QVariant(stringValue) << QJsonValue(stringValue); - QTest::newRow("stringList") << QVariant(stringList) << QJsonValue(jsonArray_string); - QTest::newRow("variantList") << QVariant(variantList) << QJsonValue(jsonArray_variant); - QTest::newRow("variantMap") << QVariant(variantMap) << QJsonValue(jsonObject); - QTest::newRow("variantHash") << QVariant(variantHash) << QJsonValue(jsonObject); -} - -void tst_QtJson::fromVariant() -{ - QFETCH( QVariant, variant ); - QFETCH( QJsonValue, jsonvalue ); - - QCOMPARE(QJsonValue::fromVariant(variant), jsonvalue); - QCOMPARE(variant.toJsonValue(), jsonvalue); -} - -void tst_QtJson::toVariant_data() -{ - fromVariant_data(); -} - -void tst_QtJson::toVariant() -{ - QFETCH( QVariant, variant ); - QFETCH( QJsonValue, jsonvalue ); - - QCOMPARE(jsonvalue.toVariant(), variant); -} - -void tst_QtJson::fromVariantMap() -{ - QVariantMap map; - map.insert(QLatin1String("key1"), QLatin1String("value1")); - map.insert(QLatin1String("key2"), QLatin1String("value2")); - QJsonObject object = QJsonObject::fromVariantMap(map); - QCOMPARE(object.size(), 2); - QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1"))); - QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2"))); - - QVariantList list; - list.append(true); - list.append(QVariant()); - list.append(999.); - list.append(QLatin1String("foo")); - map.insert("list", list); - object = QJsonObject::fromVariantMap(map); - QCOMPARE(object.size(), 3); - QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1"))); - QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2"))); - QCOMPARE(object.value(QLatin1String("list")).type(), QJsonValue::Array); - QJsonArray array = object.value(QLatin1String("list")).toArray(); - QCOMPARE(array.size(), 4); - QCOMPARE(array.at(0).type(), QJsonValue::Bool); - QCOMPARE(array.at(0).toBool(), true); - QCOMPARE(array.at(1).type(), QJsonValue::Null); - QCOMPARE(array.at(2).type(), QJsonValue::Double); - QCOMPARE(array.at(2).toDouble(), 999.); - QCOMPARE(array.at(3).type(), QJsonValue::String); - QCOMPARE(array.at(3).toString(), QLatin1String("foo")); -} - -void tst_QtJson::fromVariantHash() -{ - QVariantHash map; - map.insert(QLatin1String("key1"), QLatin1String("value1")); - map.insert(QLatin1String("key2"), QLatin1String("value2")); - QJsonObject object = QJsonObject::fromVariantHash(map); - QCOMPARE(object.size(), 2); - QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1"))); - QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2"))); -} - -void tst_QtJson::toVariantMap() -{ - QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().type()), QMetaType::QVariantMap); // QTBUG-32524 - - QJsonObject object; - QVariantMap map = object.toVariantMap(); - QVERIFY(map.isEmpty()); - - object.insert("Key", QString("Value")); - object.insert("null", QJsonValue()); - QJsonArray array; - array.append(true); - array.append(999.); - array.append(QLatin1String("string")); - array.append(QJsonValue::Null); - object.insert("Array", array); - - map = object.toVariantMap(); - - QCOMPARE(map.size(), 3); - QCOMPARE(map.value("Key"), QVariant(QString("Value"))); - QCOMPARE(map.value("null"), QVariant::fromValue(nullptr)); - QCOMPARE(map.value("Array").type(), QVariant::List); - QVariantList list = map.value("Array").toList(); - QCOMPARE(list.size(), 4); - QCOMPARE(list.at(0), QVariant(true)); - QCOMPARE(list.at(1), QVariant(999.)); - QCOMPARE(list.at(2), QVariant(QLatin1String("string"))); - QCOMPARE(list.at(3), QVariant::fromValue(nullptr)); -} - -void tst_QtJson::toVariantHash() -{ - QJsonObject object; - QVariantHash hash = object.toVariantHash(); - QVERIFY(hash.isEmpty()); - - object.insert("Key", QString("Value")); - object.insert("null", QJsonValue::Null); - QJsonArray array; - array.append(true); - array.append(999.); - array.append(QLatin1String("string")); - array.append(QJsonValue::Null); - object.insert("Array", array); - - hash = object.toVariantHash(); - - QCOMPARE(hash.size(), 3); - QCOMPARE(hash.value("Key"), QVariant(QString("Value"))); - QCOMPARE(hash.value("null"), QVariant::fromValue(nullptr)); - QCOMPARE(hash.value("Array").type(), QVariant::List); - QVariantList list = hash.value("Array").toList(); - QCOMPARE(list.size(), 4); - QCOMPARE(list.at(0), QVariant(true)); - QCOMPARE(list.at(1), QVariant(999.)); - QCOMPARE(list.at(2), QVariant(QLatin1String("string"))); - QCOMPARE(list.at(3), QVariant::fromValue(nullptr)); -} - -void tst_QtJson::toVariantList() -{ - QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().type()), QMetaType::QVariantList); // QTBUG-32524 - - QJsonArray array; - QVariantList list = array.toVariantList(); - QVERIFY(list.isEmpty()); - - array.append(QString("Value")); - array.append(QJsonValue()); - QJsonArray inner; - inner.append(true); - inner.append(999.); - inner.append(QLatin1String("string")); - inner.append(QJsonValue()); - array.append(inner); - - list = array.toVariantList(); - - QCOMPARE(list.size(), 3); - QCOMPARE(list[0], QVariant(QString("Value"))); - QCOMPARE(list[1], QVariant::fromValue(nullptr)); - QCOMPARE(list[2].type(), QVariant::List); - QVariantList vlist = list[2].toList(); - QCOMPARE(vlist.size(), 4); - QCOMPARE(vlist.at(0), QVariant(true)); - QCOMPARE(vlist.at(1), QVariant(999.)); - QCOMPARE(vlist.at(2), QVariant(QLatin1String("string"))); - QCOMPARE(vlist.at(3), QVariant::fromValue(nullptr)); -} - -void tst_QtJson::toJson() -{ - // Test QJsonDocument::Indented format - { - QJsonObject object; - object.insert("\\Key\n", QString("Value")); - object.insert("null", QJsonValue()); - QJsonArray array; - array.append(true); - array.append(999.); - array.append(QLatin1String("string")); - array.append(QJsonValue()); - array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); - object.insert("Array", array); - - QByteArray json = QJsonDocument(object).toJson(); - - QByteArray expected = - "{\n" - " \"Array\": [\n" - " true,\n" - " 999,\n" - " \"string\",\n" - " null,\n" - " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" - " ],\n" - " \"\\\\Key\\n\": \"Value\",\n" - " \"null\": null\n" - "}\n"; - QCOMPARE(json, expected); - - QJsonDocument doc; - doc.setObject(object); - json = doc.toJson(); - QCOMPARE(json, expected); - - doc.setArray(array); - json = doc.toJson(); - expected = - "[\n" - " true,\n" - " 999,\n" - " \"string\",\n" - " null,\n" - " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" - "]\n"; - QCOMPARE(json, expected); - } - - // Test QJsonDocument::Compact format - { - QJsonObject object; - object.insert("\\Key\n", QString("Value")); - object.insert("null", QJsonValue()); - QJsonArray array; - array.append(true); - array.append(999.); - array.append(QLatin1String("string")); - array.append(QJsonValue()); - array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); - object.insert("Array", array); - - QByteArray json = QJsonDocument(object).toJson(QJsonDocument::Compact); - QByteArray expected = - "{\"Array\":[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\":\"Value\",\"null\":null}"; - QCOMPARE(json, expected); - - QJsonDocument doc; - doc.setObject(object); - json = doc.toJson(QJsonDocument::Compact); - QCOMPARE(json, expected); - - doc.setArray(array); - json = doc.toJson(QJsonDocument::Compact); - expected = "[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"]"; - QCOMPARE(json, expected); - } -} - -void tst_QtJson::toJsonSillyNumericValues() -{ - QJsonObject object; - QJsonArray array; - array.append(QJsonValue(std::numeric_limits<double>::infinity())); // encode to: null - array.append(QJsonValue(-std::numeric_limits<double>::infinity())); // encode to: null - array.append(QJsonValue(std::numeric_limits<double>::quiet_NaN())); // encode to: null - object.insert("Array", array); - - QByteArray json = QJsonDocument(object).toJson(); - - QByteArray expected = - "{\n" - " \"Array\": [\n" - " null,\n" - " null,\n" - " null\n" - " ]\n" - "}\n"; - - QCOMPARE(json, expected); - - QJsonDocument doc; - doc.setObject(object); - json = doc.toJson(); - QCOMPARE(json, expected); -} - -void tst_QtJson::toJsonLargeNumericValues() -{ - QJsonObject object; - QJsonArray array; - array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0 - array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE - array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE - array.append(QJsonValue(std::numeric_limits<double>::min())); - array.append(QJsonValue(std::numeric_limits<double>::max())); - array.append(QJsonValue(std::numeric_limits<double>::epsilon())); - array.append(QJsonValue(std::numeric_limits<double>::denorm_min())); - array.append(QJsonValue(0.0)); - array.append(QJsonValue(-std::numeric_limits<double>::min())); - array.append(QJsonValue(-std::numeric_limits<double>::max())); - array.append(QJsonValue(-std::numeric_limits<double>::epsilon())); - array.append(QJsonValue(-std::numeric_limits<double>::denorm_min())); - array.append(QJsonValue(-0.0)); - array.append(QJsonValue(9007199254740992LL)); // JS Number max integer - array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer - object.insert("Array", array); - - QByteArray json = QJsonDocument(object).toJson(); - - QByteArray expected = - "{\n" - " \"Array\": [\n" - " 1.234567,\n" - " 1.7976931348623157e+308,\n" -#ifdef QT_NO_DOUBLECONVERSION // "shortest" double conversion is not very short then - " 4.9406564584124654e-324,\n" - " 2.2250738585072014e-308,\n" - " 1.7976931348623157e+308,\n" - " 2.2204460492503131e-16,\n" - " 4.9406564584124654e-324,\n" - " 0,\n" - " -2.2250738585072014e-308,\n" - " -1.7976931348623157e+308,\n" - " -2.2204460492503131e-16,\n" - " -4.9406564584124654e-324,\n" -#else - " 5e-324,\n" - " 2.2250738585072014e-308,\n" - " 1.7976931348623157e+308,\n" - " 2.220446049250313e-16,\n" - " 5e-324,\n" - " 0,\n" - " -2.2250738585072014e-308,\n" - " -1.7976931348623157e+308,\n" - " -2.220446049250313e-16,\n" - " -5e-324,\n" -#endif - " 0,\n" - " 9007199254740992,\n" - " -9007199254740992\n" - " ]\n" - "}\n"; - -#ifdef Q_OS_QNX - QEXPECT_FAIL("", "See QTBUG-37066", Continue); -#endif - QCOMPARE(json, expected); - - QJsonDocument doc; - doc.setObject(object); - json = doc.toJson(); -#ifdef Q_OS_QNX - QEXPECT_FAIL("", "See QTBUG-37066", Continue); -#endif - QCOMPARE(json, expected); -} - -void tst_QtJson::fromJson() -{ - { - QByteArray json = "[\n true\n]\n"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QCOMPARE(array.at(0).type(), QJsonValue::Bool); - QCOMPARE(array.at(0).toBool(), true); - QCOMPARE(doc.toJson(), json); - } - { - //regression test: test if unicode_control_characters are correctly decoded - QByteArray json = "[\n \"" UNICODE_NON_CHARACTER "\"\n]\n"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QCOMPARE(array.at(0).type(), QJsonValue::String); - QCOMPARE(array.at(0).toString(), QString::fromUtf8(UNICODE_NON_CHARACTER)); - QCOMPARE(doc.toJson(), json); - } - { - QByteArray json = "[]"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 0); - } - { - QByteArray json = "{}"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QJsonObject object = doc.object(); - QCOMPARE(object.size(), 0); - } - { - QByteArray json = "{\n \"Key\": true\n}\n"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QJsonObject object = doc.object(); - QCOMPARE(object.size(), 1); - QCOMPARE(object.value("Key"), QJsonValue(true)); - QCOMPARE(doc.toJson(), json); - } - { - QByteArray json = "[ null, true, false, \"Foo\", 1, [], {} ]"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 7); - QCOMPARE(array.at(0).type(), QJsonValue::Null); - QCOMPARE(array.at(1).type(), QJsonValue::Bool); - QCOMPARE(array.at(1).toBool(), true); - QCOMPARE(array.at(2).type(), QJsonValue::Bool); - QCOMPARE(array.at(2).toBool(), false); - QCOMPARE(array.at(3).type(), QJsonValue::String); - QCOMPARE(array.at(3).toString(), QLatin1String("Foo")); - QCOMPARE(array.at(4).type(), QJsonValue::Double); - QCOMPARE(array.at(4).toDouble(), 1.); - QCOMPARE(array.at(5).type(), QJsonValue::Array); - QCOMPARE(array.at(5).toArray().size(), 0); - QCOMPARE(array.at(6).type(), QJsonValue::Object); - QCOMPARE(array.at(6).toObject().size(), 0); - } - { - QByteArray json = "{ \"0\": null, \"1\": true, \"2\": false, \"3\": \"Foo\", \"4\": 1, \"5\": [], \"6\": {} }"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QJsonObject object = doc.object(); - QCOMPARE(object.size(), 7); - QCOMPARE(object.value("0").type(), QJsonValue::Null); - QCOMPARE(object.value("1").type(), QJsonValue::Bool); - QCOMPARE(object.value("1").toBool(), true); - QCOMPARE(object.value("2").type(), QJsonValue::Bool); - QCOMPARE(object.value("2").toBool(), false); - QCOMPARE(object.value("3").type(), QJsonValue::String); - QCOMPARE(object.value("3").toString(), QLatin1String("Foo")); - QCOMPARE(object.value("4").type(), QJsonValue::Double); - QCOMPARE(object.value("4").toDouble(), 1.); - QCOMPARE(object.value("5").type(), QJsonValue::Array); - QCOMPARE(object.value("5").toArray().size(), 0); - QCOMPARE(object.value("6").type(), QJsonValue::Object); - QCOMPARE(object.value("6").toObject().size(), 0); - } - { - QByteArray compactJson = "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}"; - QJsonDocument doc = QJsonDocument::fromJson(compactJson); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QJsonObject object = doc.object(); - QCOMPARE(object.size(), 3); - QCOMPARE(object.value("\\Key\n").isString(), true); - QCOMPARE(object.value("\\Key\n").toString(), QString("Value")); - QCOMPARE(object.value("null").isNull(), true); - QCOMPARE(object.value("Array").isArray(), true); - QJsonArray array = object.value("Array").toArray(); - QCOMPARE(array.size(), 5); - QCOMPARE(array.at(0).isBool(), true); - QCOMPARE(array.at(0).toBool(), true); - QCOMPARE(array.at(1).isDouble(), true); - QCOMPARE(array.at(1).toDouble(), 999.); - QCOMPARE(array.at(2).isString(), true); - QCOMPARE(array.at(2).toString(), QLatin1String("string")); - QCOMPARE(array.at(3).isNull(), true); - QCOMPARE(array.at(4).isString(), true); - QCOMPARE(array.at(4).toString(), QLatin1String("\\\a\n\r\b\tabcABC\"")); - } -} - -void tst_QtJson::fromJsonErrors() -{ - { - QJsonParseError error; - QByteArray json = "{\n \n\n"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::UnterminatedObject); - QCOMPARE(error.offset, 8); - } - { - QJsonParseError error; - QByteArray json = "{\n \"key\" 10\n"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::MissingNameSeparator); - QCOMPARE(error.offset, 13); - } - { - QJsonParseError error; - QByteArray json = "[\n \n\n"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::UnterminatedArray); - QCOMPARE(error.offset, 8); - } - { - QJsonParseError error; - QByteArray json = "[\n 1, true\n\n"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::UnterminatedArray); - QCOMPARE(error.offset, 14); - } - { - QJsonParseError error; - QByteArray json = "[\n 1 true\n\n"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::MissingValueSeparator); - QCOMPARE(error.offset, 7); - } - { - QJsonParseError error; - QByteArray json = "[\n nul"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 7); - } - { - QJsonParseError error; - QByteArray json = "[\n nulzz"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 10); - } - { - QJsonParseError error; - QByteArray json = "[\n tru"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 7); - } - { - QJsonParseError error; - QByteArray json = "[\n trud]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 10); - } - { - QJsonParseError error; - QByteArray json = "[\n fal"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 7); - } - { - QJsonParseError error; - QByteArray json = "[\n falsd]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalValue); - QCOMPARE(error.offset, 11); - } - { - QJsonParseError error; - QByteArray json = "[\n 11111"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::TerminationByNumber); - QCOMPARE(error.offset, 11); - } - { - QJsonParseError error; - QByteArray json = "[\n -1E10000]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalNumber); - QCOMPARE(error.offset, 14); - } - { - QJsonParseError error; - QByteArray json = "[\n -1e-10000]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalNumber); - QCOMPARE(error.offset, 15); - } - { - QJsonParseError error; - QByteArray json = "[\n \"\\u12\"]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence); - QCOMPARE(error.offset, 11); - } - { - QJsonParseError error; - QByteArray json = "[\n \"foo" INVALID_UNICODE "bar\"]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalUTF8String); - QCOMPARE(error.offset, 12); - } - { - QJsonParseError error; - QByteArray json = "[\n \""; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::UnterminatedString); - QCOMPARE(error.offset, 8); - } - { - QJsonParseError error; - QByteArray json = "[\n \"c" UNICODE_DJE "a\\u12\"]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence); - QCOMPARE(error.offset, 15); - } - { - QJsonParseError error; - QByteArray json = "[\n \"c" UNICODE_DJE "a" INVALID_UNICODE "bar\"]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::IllegalUTF8String); - QCOMPARE(error.offset, 13); - } - { - QJsonParseError error; - QByteArray json = "[\n \"c" UNICODE_DJE "a ]"; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QVERIFY(doc.isEmpty()); - QCOMPARE(error.error, QJsonParseError::UnterminatedString); - QCOMPARE(error.offset, 14); - } -} - -void tst_QtJson::fromBinary() -{ - QFile file(testDataDir + "/test.json"); - file.open(QFile::ReadOnly); - QByteArray testJson = file.readAll(); - - QJsonDocument doc = QJsonDocument::fromJson(testJson); - QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData()); - QVERIFY(!outdoc.isNull()); - QCOMPARE(doc, outdoc); - - QFile bfile(testDataDir + "/test.bjson"); - bfile.open(QFile::ReadOnly); - QByteArray binary = bfile.readAll(); - - QJsonDocument bdoc = QJsonDocument::fromBinaryData(binary); - QVERIFY(!bdoc.isNull()); - QCOMPARE(doc.toVariant(), bdoc.toVariant()); - QCOMPARE(doc, bdoc); -} - -void tst_QtJson::toAndFromBinary_data() -{ - QTest::addColumn<QString>("filename"); - QTest::newRow("test.json") << (testDataDir + "/test.json"); - QTest::newRow("test2.json") << (testDataDir + "/test2.json"); -} - -void tst_QtJson::toAndFromBinary() -{ - QFETCH(QString, filename); - QFile file(filename); - QVERIFY(file.open(QFile::ReadOnly)); - QByteArray data = file.readAll(); - - QJsonDocument doc = QJsonDocument::fromJson(data); - QVERIFY(!doc.isNull()); - QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData()); - QVERIFY(!outdoc.isNull()); - QCOMPARE(doc, outdoc); -} - -void tst_QtJson::invalidBinaryData() -{ - QDir dir(testDataDir + "/invalidBinaryData"); - QFileInfoList files = dir.entryInfoList(); - for (int i = 0; i < files.size(); ++i) { - if (!files.at(i).isFile()) - continue; - QFile file(files.at(i).filePath()); - file.open(QIODevice::ReadOnly); - QByteArray bytes = file.readAll(); - QJsonDocument document = QJsonDocument::fromRawData(bytes.constData(), bytes.size()); - QVERIFY(document.isNull()); - } -} - -void tst_QtJson::parseNumbers() -{ - { - // test number parsing - struct Numbers { - const char *str; - int n; - }; - Numbers numbers [] = { - { "0", 0 }, - { "1", 1 }, - { "10", 10 }, - { "-1", -1 }, - { "100000", 100000 }, - { "-999", -999 } - }; - int size = sizeof(numbers)/sizeof(Numbers); - for (int i = 0; i < size; ++i) { - QByteArray json = "[ "; - json += numbers[i].str; - json += " ]"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QJsonValue val = array.at(0); - QCOMPARE(val.type(), QJsonValue::Double); - QCOMPARE(val.toDouble(), (double)numbers[i].n); - } - } - { - // test number parsing - struct Numbers { - const char *str; - double n; - }; - Numbers numbers [] = { - { "0", 0 }, - { "1", 1 }, - { "10", 10 }, - { "-1", -1 }, - { "100000", 100000 }, - { "-999", -999 }, - { "1.1", 1.1 }, - { "1e10", 1e10 }, - { "-1.1", -1.1 }, - { "-1e10", -1e10 }, - { "-1E10", -1e10 }, - { "1.1e10", 1.1e10 }, - { "1.1e308", 1.1e308 }, - { "-1.1e308", -1.1e308 }, - { "1.1e-308", 1.1e-308 }, - { "-1.1e-308", -1.1e-308 }, - { "1.1e+308", 1.1e+308 }, - { "-1.1e+308", -1.1e+308 }, - { "1.e+308", 1.e+308 }, - { "-1.e+308", -1.e+308 } - }; - int size = sizeof(numbers)/sizeof(Numbers); - for (int i = 0; i < size; ++i) { - QByteArray json = "[ "; - json += numbers[i].str; - json += " ]"; - QJsonDocument doc = QJsonDocument::fromJson(json); -#ifdef Q_OS_QNX - if (0 == QString::compare(numbers[i].str, "1.1e-308")) - QEXPECT_FAIL("", "See QTBUG-37066", Abort); -#endif - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QJsonValue val = array.at(0); - QCOMPARE(val.type(), QJsonValue::Double); - QCOMPARE(val.toDouble(), numbers[i].n); - } - } -} - -void tst_QtJson::parseStrings() -{ - const char *strings [] = - { - "Foo", - "abc\\\"abc", - "abc\\\\abc", - "abc\\babc", - "abc\\fabc", - "abc\\nabc", - "abc\\rabc", - "abc\\tabc", - "abc\\u0019abc", - "abc" UNICODE_DJE "abc", - UNICODE_NON_CHARACTER - }; - int size = sizeof(strings)/sizeof(const char *); - - for (int i = 0; i < size; ++i) { - QByteArray json = "[\n \""; - json += strings[i]; - json += "\"\n]\n"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QJsonValue val = array.at(0); - QCOMPARE(val.type(), QJsonValue::String); - - QCOMPARE(doc.toJson(), json); - } - - struct Pairs { - const char *in; - const char *out; - }; - Pairs pairs [] = { - { "abc\\/abc", "abc/abc" }, - { "abc\\u0402abc", "abc" UNICODE_DJE "abc" }, - { "abc\\u0065abc", "abceabc" }, - { "abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc" } - }; - size = sizeof(pairs)/sizeof(Pairs); - - for (int i = 0; i < size; ++i) { - QByteArray json = "[\n \""; - json += pairs[i].in; - json += "\"\n]\n"; - QByteArray out = "[\n \""; - out += pairs[i].out; - out += "\"\n]\n"; - QJsonDocument doc = QJsonDocument::fromJson(json); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), true); - QCOMPARE(doc.isObject(), false); - QJsonArray array = doc.array(); - QCOMPARE(array.size(), 1); - QJsonValue val = array.at(0); - QCOMPARE(val.type(), QJsonValue::String); - - QCOMPARE(doc.toJson(), out); - } - -} - -void tst_QtJson::parseDuplicateKeys() -{ - const char *json = "{ \"B\": true, \"A\": null, \"B\": false }"; - - QJsonDocument doc = QJsonDocument::fromJson(json); - QCOMPARE(doc.isObject(), true); - - QJsonObject o = doc.object(); - QCOMPARE(o.size(), 2); - QJsonObject::const_iterator it = o.constBegin(); - QCOMPARE(it.key(), QLatin1String("A")); - QCOMPARE(it.value(), QJsonValue()); - ++it; - QCOMPARE(it.key(), QLatin1String("B")); - QCOMPARE(it.value(), QJsonValue(false)); -} - -void tst_QtJson::testParser() -{ - QFile file(testDataDir + "/test.json"); - file.open(QFile::ReadOnly); - QByteArray testJson = file.readAll(); - - QJsonDocument doc = QJsonDocument::fromJson(testJson); - QVERIFY(!doc.isEmpty()); -} - -void tst_QtJson::compactArray() -{ - QJsonArray array; - array.append(QLatin1String("First Entry")); - array.append(QLatin1String("Second Entry")); - array.append(QLatin1String("Third Entry")); - QJsonDocument doc(array); - int s = doc.toBinaryData().size(); - array.removeAt(1); - doc.setArray(array); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("[\n" - " \"First Entry\",\n" - " \"Third Entry\"\n" - "]\n")); - - array.removeAt(0); - doc.setArray(array); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("[\n" - " \"Third Entry\"\n" - "]\n")); - - array.removeAt(0); - doc.setArray(array); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("[\n" - "]\n")); - -} - -void tst_QtJson::compactObject() -{ - QJsonObject object; - object.insert(QLatin1String("Key1"), QLatin1String("First Entry")); - object.insert(QLatin1String("Key2"), QLatin1String("Second Entry")); - object.insert(QLatin1String("Key3"), QLatin1String("Third Entry")); - QJsonDocument doc(object); - int s = doc.toBinaryData().size(); - object.remove(QLatin1String("Key2")); - doc.setObject(object); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("{\n" - " \"Key1\": \"First Entry\",\n" - " \"Key3\": \"Third Entry\"\n" - "}\n")); - - object.remove(QLatin1String("Key1")); - doc.setObject(object); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("{\n" - " \"Key3\": \"Third Entry\"\n" - "}\n")); - - object.remove(QLatin1String("Key3")); - doc.setObject(object); - QVERIFY(s > doc.toBinaryData().size()); - s = doc.toBinaryData().size(); - QCOMPARE(doc.toJson(), - QByteArray("{\n" - "}\n")); - -} - -void tst_QtJson::validation() -{ - // this basically tests that we don't crash on corrupt data - QFile file(testDataDir + "/test.json"); - QVERIFY(file.open(QFile::ReadOnly)); - QByteArray testJson = file.readAll(); - QVERIFY(!testJson.isEmpty()); - - QJsonDocument doc = QJsonDocument::fromJson(testJson); - QVERIFY(!doc.isNull()); - - QByteArray binary = doc.toBinaryData(); - - // only test the first 1000 bytes. Testing the full file takes too long - for (int i = 0; i < 1000; ++i) { - QByteArray corrupted = binary; - corrupted[i] = char(0xff); - QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted); - if (doc.isNull()) - continue; - QByteArray json = doc.toJson(); - } - - - QFile file2(testDataDir + "/test3.json"); - file2.open(QFile::ReadOnly); - testJson = file2.readAll(); - QVERIFY(!testJson.isEmpty()); - - doc = QJsonDocument::fromJson(testJson); - QVERIFY(!doc.isNull()); - - binary = doc.toBinaryData(); - - for (int i = 0; i < binary.size(); ++i) { - QByteArray corrupted = binary; - corrupted[i] = char(0xff); - QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted); - if (doc.isNull()) - continue; - QByteArray json = doc.toJson(); - - corrupted = binary; - corrupted[i] = 0x00; - doc = QJsonDocument::fromBinaryData(corrupted); - if (doc.isNull()) - continue; - json = doc.toJson(); - } -} - -void tst_QtJson::assignToDocument() -{ - { - const char *json = "{ \"inner\": { \"key\": true } }"; - QJsonDocument doc = QJsonDocument::fromJson(json); - - QJsonObject o = doc.object(); - QJsonValue inner = o.value("inner"); - - QJsonDocument innerDoc(inner.toObject()); - - QVERIFY(innerDoc != doc); - QCOMPARE(innerDoc.object(), inner.toObject()); - } - { - const char *json = "[ [ true ] ]"; - QJsonDocument doc = QJsonDocument::fromJson(json); - - QJsonArray a = doc.array(); - QJsonValue inner = a.at(0); - - QJsonDocument innerDoc(inner.toArray()); - - QVERIFY(innerDoc != doc); - QCOMPARE(innerDoc.array(), inner.toArray()); - } -} - - -void tst_QtJson::testDuplicateKeys() -{ - QJsonObject obj; - obj.insert(QLatin1String("foo"), QLatin1String("bar")); - obj.insert(QLatin1String("foo"), QLatin1String("zap")); - QCOMPARE(obj.size(), 1); - QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("zap")); -} - -void tst_QtJson::testCompaction() -{ - // modify object enough times to trigger compactionCounter - // and make sure the data is still valid - QJsonObject obj; - for (int i = 0; i < 33; ++i) { - obj.remove(QLatin1String("foo")); - obj.insert(QLatin1String("foo"), QLatin1String("bar")); - } - QCOMPARE(obj.size(), 1); - QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar")); - - QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(obj).toBinaryData()); - QVERIFY(!doc.isNull()); - QVERIFY(!doc.isEmpty()); - QCOMPARE(doc.isArray(), false); - QCOMPARE(doc.isObject(), true); - QCOMPARE(doc.object(), obj); -} - -void tst_QtJson::testDebugStream() -{ - { - // QJsonObject - - QJsonObject object; - QTest::ignoreMessage(QtDebugMsg, "QJsonObject()"); - qDebug() << object; - - object.insert(QLatin1String("foo"), QLatin1String("bar")); - QTest::ignoreMessage(QtDebugMsg, "QJsonObject({\"foo\":\"bar\"})"); - qDebug() << object; - } - - { - // QJsonArray - - QJsonArray array; - QTest::ignoreMessage(QtDebugMsg, "QJsonArray()"); - qDebug() << array; - - array.append(1); - array.append(QLatin1String("foo")); - QTest::ignoreMessage(QtDebugMsg, "QJsonArray([1,\"foo\"])"); - qDebug() << array; - } - - { - // QJsonDocument - - QJsonDocument doc; - QTest::ignoreMessage(QtDebugMsg, "QJsonDocument()"); - qDebug() << doc; - - QJsonObject object; - object.insert(QLatin1String("foo"), QLatin1String("bar")); - doc.setObject(object); - QTest::ignoreMessage(QtDebugMsg, "QJsonDocument({\"foo\":\"bar\"})"); - qDebug() << doc; - - QJsonArray array; - array.append(1); - array.append(QLatin1String("foo")); - QTest::ignoreMessage(QtDebugMsg, "QJsonDocument([1,\"foo\"])"); - doc.setArray(array); - qDebug() << doc; - } - - { - // QJsonValue - - QJsonValue value; - - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(null)"); - qDebug() << value; - - value = QJsonValue(true); // bool - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(bool, true)"); - qDebug() << value; - - value = QJsonValue((double)4.2); // double - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 4.2)"); - qDebug() << value; - - value = QJsonValue((int)42); // int - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 42)"); - qDebug() << value; - - value = QJsonValue(QLatin1String("foo")); // string - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(string, \"foo\")"); - qDebug() << value; - - QJsonArray array; - array.append(1); - array.append(QLatin1String("foo")); - value = QJsonValue(array); // array - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(array, QJsonArray([1,\"foo\"]))"); - qDebug() << value; - - QJsonObject object; - object.insert(QLatin1String("foo"), QLatin1String("bar")); - value = QJsonValue(object); // object - QTest::ignoreMessage(QtDebugMsg, "QJsonValue(object, QJsonObject({\"foo\":\"bar\"}))"); - qDebug() << value; - } -} - -void tst_QtJson::testCompactionError() -{ - QJsonObject schemaObject; - schemaObject.insert("_Type", QLatin1String("_SchemaType")); - schemaObject.insert("name", QLatin1String("Address")); - schemaObject.insert("schema", QJsonObject()); - { - QJsonObject content(schemaObject); - QJsonDocument doc(content); - QVERIFY(!doc.isNull()); - QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex(); - schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size())); - } - - QJsonObject schema; - schema.insert("streetNumber", schema.value("number").toObject()); - schemaObject.insert("schema", schema); - { - QJsonObject content(schemaObject); - content.remove("_Uuid"); - content.remove("_Version"); - QJsonDocument doc(content); - QVERIFY(!doc.isNull()); - QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex(); - schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size())); - } -} - -void tst_QtJson::parseUnicodeEscapes() -{ - const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]"; - - QJsonDocument doc = QJsonDocument::fromJson(json); - QJsonArray array = doc.array(); - - QString result = QLatin1String("A"); - result += QChar(0xe4); - result += QChar(0xc4); - - QCOMPARE(array.first().toString(), result); -} - -void tst_QtJson::assignObjects() -{ - const char *json = - "[ { \"Key\": 1 }, { \"Key\": 2 } ]"; - - QJsonDocument doc = QJsonDocument::fromJson(json); - QJsonArray array = doc.array(); - - QJsonObject object = array.at(0).toObject(); - QCOMPARE(object.value("Key").toDouble(), 1.); - - object = array.at(1).toObject(); - QCOMPARE(object.value("Key").toDouble(), 2.); -} - -void tst_QtJson::assignArrays() -{ - const char *json = - "[ [ 1 ], [ 2 ] ]"; - - QJsonDocument doc = QJsonDocument::fromJson(json); - QJsonArray array = doc.array(); - - QJsonArray inner = array.at(0).toArray() ; - QCOMPARE(inner.at(0).toDouble(), 1.); - - inner= array.at(1).toArray(); - QCOMPARE(inner.at(0).toDouble(), 2.); -} - -void tst_QtJson::testTrailingComma() -{ - const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" }; - - for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) { - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(jsons[i], &error); - QCOMPARE(error.error, QJsonParseError::MissingObject); - } -} - -void tst_QtJson::testDetachBug() -{ - QJsonObject dynamic; - QJsonObject embedded; - - QJsonObject local; - - embedded.insert("Key1", QString("Value1")); - embedded.insert("Key2", QString("Value2")); - dynamic.insert(QStringLiteral("Bogus"), QString("bogusValue")); - dynamic.insert("embedded", embedded); - local = dynamic.value("embedded").toObject(); - - dynamic.remove("embedded"); - - QCOMPARE(local.keys().size(),2); - local.remove("Key1"); - local.remove("Key2"); - QCOMPARE(local.keys().size(), 0); - - local.insert("Key1", QString("anotherValue")); - QCOMPARE(local.keys().size(), 1); -} - -void tst_QtJson::valueEquals() -{ - QCOMPARE(QJsonValue(), QJsonValue()); - QVERIFY(QJsonValue() != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue() != QJsonValue(true)); - QVERIFY(QJsonValue() != QJsonValue(1.)); - QVERIFY(QJsonValue() != QJsonValue(QJsonArray())); - QVERIFY(QJsonValue() != QJsonValue(QJsonObject())); - - QCOMPARE(QJsonValue(true), QJsonValue(true)); - QVERIFY(QJsonValue(true) != QJsonValue(false)); - QVERIFY(QJsonValue(true) != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue(true) != QJsonValue()); - QVERIFY(QJsonValue(true) != QJsonValue(1.)); - QVERIFY(QJsonValue(true) != QJsonValue(QJsonArray())); - QVERIFY(QJsonValue(true) != QJsonValue(QJsonObject())); - - QCOMPARE(QJsonValue(1), QJsonValue(1)); - QVERIFY(QJsonValue(1) != QJsonValue(2)); - QCOMPARE(QJsonValue(1), QJsonValue(1.)); - QVERIFY(QJsonValue(1) != QJsonValue(1.1)); - QVERIFY(QJsonValue(1) != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue(1) != QJsonValue()); - QVERIFY(QJsonValue(1) != QJsonValue(true)); - QVERIFY(QJsonValue(1) != QJsonValue(QJsonArray())); - QVERIFY(QJsonValue(1) != QJsonValue(QJsonObject())); - - QCOMPARE(QJsonValue(1.), QJsonValue(1.)); - QVERIFY(QJsonValue(1.) != QJsonValue(2.)); - QVERIFY(QJsonValue(1.) != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue(1.) != QJsonValue()); - QVERIFY(QJsonValue(1.) != QJsonValue(true)); - QVERIFY(QJsonValue(1.) != QJsonValue(QJsonArray())); - QVERIFY(QJsonValue(1.) != QJsonValue(QJsonObject())); - - QCOMPARE(QJsonValue(QJsonArray()), QJsonValue(QJsonArray())); - QJsonArray nonEmptyArray; - nonEmptyArray.append(true); - QVERIFY(QJsonValue(QJsonArray()) != nonEmptyArray); - QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue(QJsonArray()) != QJsonValue()); - QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(true)); - QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(1.)); - QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonObject())); - - QCOMPARE(QJsonValue(QJsonObject()), QJsonValue(QJsonObject())); - QJsonObject nonEmptyObject; - nonEmptyObject.insert("Key", true); - QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject); - QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonValue::Undefined)); - QVERIFY(QJsonValue(QJsonObject()) != QJsonValue()); - QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(true)); - QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(1.)); - QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonArray())); - - QCOMPARE(QJsonValue("foo"), QJsonValue(QLatin1String("foo"))); - QCOMPARE(QJsonValue("foo"), QJsonValue(QString("foo"))); - QCOMPARE(QJsonValue("\x66\x6f\x6f"), QJsonValue(QString("foo"))); - QCOMPARE(QJsonValue("\x62\x61\x72"), QJsonValue("bar")); - QCOMPARE(QJsonValue(UNICODE_NON_CHARACTER), QJsonValue(QString(UNICODE_NON_CHARACTER))); - QCOMPARE(QJsonValue(UNICODE_DJE), QJsonValue(QString(UNICODE_DJE))); - QCOMPARE(QJsonValue("\xc3\xa9"), QJsonValue(QString("\xc3\xa9"))); -} - -void tst_QtJson::objectEquals_data() -{ - QTest::addColumn<QJsonObject>("left"); - QTest::addColumn<QJsonObject>("right"); - QTest::addColumn<bool>("result"); - - QTest::newRow("two defaults") << QJsonObject() << QJsonObject() << true; - - QJsonObject object1; - object1.insert("property", 1); - QJsonObject object2; - object2["property"] = 1; - QJsonObject object3; - object3.insert("property1", 1); - object3.insert("property2", 2); - - QTest::newRow("the same object (1 vs 2)") << object1 << object2 << true; - QTest::newRow("the same object (3 vs 3)") << object3 << object3 << true; - QTest::newRow("different objects (2 vs 3)") << object2 << object3 << false; - QTest::newRow("object vs default") << object1 << QJsonObject() << false; - - QJsonObject empty; - empty.insert("property", 1); - empty.take("property"); - QTest::newRow("default vs empty") << QJsonObject() << empty << true; - QTest::newRow("empty vs empty") << empty << empty << true; - QTest::newRow("object vs empty") << object1 << empty << false; - - QJsonObject referencedEmpty; - referencedEmpty["undefined"]; - QTest::newRow("referenced empty vs referenced empty") << referencedEmpty << referencedEmpty << true; - QTest::newRow("referenced empty vs object") << referencedEmpty << object1 << false; - - QJsonObject referencedObject1; - referencedObject1.insert("property", 1); - referencedObject1["undefined"]; - QJsonObject referencedObject2; - referencedObject2.insert("property", 1); - referencedObject2["aaaaaaaaa"]; // earlier then "property" - referencedObject2["zzzzzzzzz"]; // after "property" - QTest::newRow("referenced object vs default") << referencedObject1 << QJsonObject() << false; - QTest::newRow("referenced object vs referenced object") << referencedObject1 << referencedObject1 << true; - QTest::newRow("referenced object vs object (different)") << referencedObject1 << object3 << false; -} - -void tst_QtJson::objectEquals() -{ - QFETCH(QJsonObject, left); - QFETCH(QJsonObject, right); - QFETCH(bool, result); - - QCOMPARE(left == right, result); - QCOMPARE(right == left, result); - - // invariants checks - QCOMPARE(left, left); - QCOMPARE(right, right); - QCOMPARE(left != right, !result); - QCOMPARE(right != left, !result); - - // The same but from QJsonValue perspective - QCOMPARE(QJsonValue(left) == QJsonValue(right), result); - QCOMPARE(QJsonValue(left) != QJsonValue(right), !result); - QCOMPARE(QJsonValue(right) == QJsonValue(left), result); - QCOMPARE(QJsonValue(right) != QJsonValue(left), !result); -} - -void tst_QtJson::arrayEquals_data() -{ - QTest::addColumn<QJsonArray>("left"); - QTest::addColumn<QJsonArray>("right"); - QTest::addColumn<bool>("result"); - - QTest::newRow("two defaults") << QJsonArray() << QJsonArray() << true; - - QJsonArray array1; - array1.append(1); - QJsonArray array2; - array2.append(2111); - array2[0] = 1; - QJsonArray array3; - array3.insert(0, 1); - array3.insert(1, 2); - - QTest::newRow("the same array (1 vs 2)") << array1 << array2 << true; - QTest::newRow("the same array (3 vs 3)") << array3 << array3 << true; - QTest::newRow("different arrays (2 vs 3)") << array2 << array3 << false; - QTest::newRow("array vs default") << array1 << QJsonArray() << false; - - QJsonArray empty; - empty.append(1); - empty.takeAt(0); - QTest::newRow("default vs empty") << QJsonArray() << empty << true; - QTest::newRow("empty vs default") << empty << QJsonArray() << true; - QTest::newRow("empty vs empty") << empty << empty << true; - QTest::newRow("array vs empty") << array1 << empty << false; -} - -void tst_QtJson::arrayEquals() -{ - QFETCH(QJsonArray, left); - QFETCH(QJsonArray, right); - QFETCH(bool, result); - - QCOMPARE(left == right, result); - QCOMPARE(right == left, result); - - // invariants checks - QCOMPARE(left, left); - QCOMPARE(right, right); - QCOMPARE(left != right, !result); - QCOMPARE(right != left, !result); - - // The same but from QJsonValue perspective - QCOMPARE(QJsonValue(left) == QJsonValue(right), result); - QCOMPARE(QJsonValue(left) != QJsonValue(right), !result); - QCOMPARE(QJsonValue(right) == QJsonValue(left), result); - QCOMPARE(QJsonValue(right) != QJsonValue(left), !result); -} - -void tst_QtJson::bom() -{ - QFile file(testDataDir + "/bom.json"); - file.open(QFile::ReadOnly); - QByteArray json = file.readAll(); - - // Import json document into a QJsonDocument - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - - QVERIFY(!doc.isNull()); - QCOMPARE(error.error, QJsonParseError::NoError); -} - -void tst_QtJson::nesting() -{ - // check that we abort parsing too deeply nested json documents. - // this is to make sure we don't crash because the parser exhausts the - // stack. - - const char *array_data = - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"; - - QByteArray json(array_data); - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - - QVERIFY(!doc.isNull()); - QCOMPARE(error.error, QJsonParseError::NoError); - - json.prepend('['); - json.append(']'); - doc = QJsonDocument::fromJson(json, &error); - - QVERIFY(doc.isNull()); - QCOMPARE(error.error, QJsonParseError::DeepNesting); - - json = QByteArray("true "); - - for (int i = 0; i < 1024; ++i) { - json.prepend("{ \"Key\": "); - json.append(" }"); - } - - doc = QJsonDocument::fromJson(json, &error); - - QVERIFY(!doc.isNull()); - QCOMPARE(error.error, QJsonParseError::NoError); - - json.prepend('['); - json.append(']'); - doc = QJsonDocument::fromJson(json, &error); - - QVERIFY(doc.isNull()); - QCOMPARE(error.error, QJsonParseError::DeepNesting); - -} - -void tst_QtJson::longStrings() -{ - // test around 15 and 16 bit boundaries, as these are limits - // in the data structures (for Latin1String in qjson_p.h) - QString s(0x7ff0, 'a'); - for (int i = 0x7ff0; i < 0x8010; i++) { - s.append(QLatin1Char('c')); - - QMap <QString, QVariant> map; - map["key"] = s; - - /* Create a QJsonDocument from the QMap ... */ - QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map)); - /* ... and a QByteArray from the QJsonDocument */ - QByteArray a1 = d1.toJson(); - - /* Create a QJsonDocument from the QByteArray ... */ - QJsonDocument d2 = QJsonDocument::fromJson(a1); - /* ... and a QByteArray from the QJsonDocument */ - QByteArray a2 = d2.toJson(); - QCOMPARE(a1, a2); - } - - s = QString(0xfff0, 'a'); - for (int i = 0xfff0; i < 0x10010; i++) { - s.append(QLatin1Char('c')); - - QMap <QString, QVariant> map; - map["key"] = s; - - /* Create a QJsonDocument from the QMap ... */ - QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map)); - /* ... and a QByteArray from the QJsonDocument */ - QByteArray a1 = d1.toJson(); - - /* Create a QJsonDocument from the QByteArray ... */ - QJsonDocument d2 = QJsonDocument::fromJson(a1); - /* ... and a QByteArray from the QJsonDocument */ - QByteArray a2 = d2.toJson(); - QCOMPARE(a1, a2); - } -} - -void tst_QtJson::testJsonValueRefDefault() -{ - QJsonObject empty; - - QCOMPARE(empty["n/a"].toString(), QString()); - QCOMPARE(empty["n/a"].toString("default"), QStringLiteral("default")); - - QCOMPARE(empty["n/a"].toBool(), false); - QCOMPARE(empty["n/a"].toBool(true), true); - - QCOMPARE(empty["n/a"].toInt(), 0); - QCOMPARE(empty["n/a"].toInt(42), 42); - - QCOMPARE(empty["n/a"].toDouble(), 0.0); - QCOMPARE(empty["n/a"].toDouble(42.0), 42.0); -} - -void tst_QtJson::arrayInitializerList() -{ -#ifndef Q_COMPILER_INITIALIZER_LISTS - QSKIP("initializer_list is enabled only with c++11 support"); -#else - QVERIFY(QJsonArray{}.isEmpty()); - QCOMPARE(QJsonArray{"one"}.count(), 1); - QCOMPARE(QJsonArray{1}.count(), 1); - - { - QJsonArray a{1.3, "hello", 0}; - QCOMPARE(QJsonValue(a[0]), QJsonValue(1.3)); - QCOMPARE(QJsonValue(a[1]), QJsonValue("hello")); - QCOMPARE(QJsonValue(a[2]), QJsonValue(0)); - QCOMPARE(a.count(), 3); - } - { - QJsonObject o; - o["property"] = 1; - QJsonArray a1 {o}; - QCOMPARE(a1.count(), 1); - QCOMPARE(a1[0].toObject(), o); - - QJsonArray a2 {o, 23}; - QCOMPARE(a2.count(), 2); - QCOMPARE(a2[0].toObject(), o); - QCOMPARE(QJsonValue(a2[1]), QJsonValue(23)); - - QJsonArray a3 { a1, o, a2 }; - QCOMPARE(QJsonValue(a3[0]), QJsonValue(a1)); - QCOMPARE(QJsonValue(a3[1]), QJsonValue(o)); - QCOMPARE(QJsonValue(a3[2]), QJsonValue(a2)); - - QJsonArray a4 { 1, QJsonArray{1,2,3}, QJsonArray{"hello", 2}, QJsonObject{{"one", 1}} }; - QCOMPARE(a4.count(), 4); - QCOMPARE(QJsonValue(a4[0]), QJsonValue(1)); - - { - QJsonArray a41 = a4[1].toArray(); - QJsonArray a42 = a4[2].toArray(); - QJsonObject a43 = a4[3].toObject(); - QCOMPARE(a41.count(), 3); - QCOMPARE(a42.count(), 2); - QCOMPARE(a43.count(), 1); - - QCOMPARE(QJsonValue(a41[2]), QJsonValue(3)); - QCOMPARE(QJsonValue(a42[1]), QJsonValue(2)); - QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1)); - } - } -#endif -} - -void tst_QtJson::objectInitializerList() -{ -#ifndef Q_COMPILER_INITIALIZER_LISTS - QSKIP("initializer_list is enabled only with c++11 support"); -#else - QVERIFY(QJsonObject{}.isEmpty()); - - { // one property - QJsonObject one {{"one", 1}}; - QCOMPARE(one.count(), 1); - QVERIFY(one.contains("one")); - QCOMPARE(QJsonValue(one["one"]), QJsonValue(1)); - } - { // two properties - QJsonObject two { - {"one", 1}, - {"two", 2} - }; - QCOMPARE(two.count(), 2); - QVERIFY(two.contains("one")); - QVERIFY(two.contains("two")); - QCOMPARE(QJsonValue(two["one"]), QJsonValue(1)); - QCOMPARE(QJsonValue(two["two"]), QJsonValue(2)); - } - { // nested object - QJsonObject object{{"nested", QJsonObject{{"innerProperty", 2}}}}; - QCOMPARE(object.count(), 1); - QVERIFY(object.contains("nested")); - QVERIFY(object["nested"].isObject()); - - QJsonObject nested = object["nested"].toObject(); - QCOMPARE(QJsonValue(nested["innerProperty"]), QJsonValue(2)); - } - { // nested array - QJsonObject object{{"nested", QJsonArray{"innerValue", 2.1, "bum cyk cyk"}}}; - QCOMPARE(object.count(), 1); - QVERIFY(object.contains("nested")); - QVERIFY(object["nested"].isArray()); - - QJsonArray nested = object["nested"].toArray(); - QCOMPARE(nested.count(), 3); - QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue")); - QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1)); - } -#endif -} - -void tst_QtJson::unicodeKeys() -{ - QByteArray json = "{" - "\"x\\u2090_1\": \"hello_1\"," - "\"y\\u2090_2\": \"hello_2\"," - "\"T\\u2090_3\": \"hello_3\"," - "\"xyz_4\": \"hello_4\"," - "\"abc_5\": \"hello_5\"" - "}"; - - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(json, &error); - QCOMPARE(error.error, QJsonParseError::NoError); - QJsonObject o = doc.object(); - - const auto keys = o.keys(); - QCOMPARE(keys.size(), 5); - for (const QString &key : keys) { - QString suffix = key.mid(key.indexOf(QLatin1Char('_'))); - QCOMPARE(o[key].toString(), QString("hello") + suffix); - } -} - -void tst_QtJson::garbageAtEnd() -{ - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson("{},", &error); - QCOMPARE(error.error, QJsonParseError::GarbageAtEnd); - QCOMPARE(error.offset, 2); - QVERIFY(doc.isEmpty()); - - doc = QJsonDocument::fromJson("{} ", &error); - QCOMPARE(error.error, QJsonParseError::NoError); - QVERIFY(!doc.isEmpty()); -} - -void tst_QtJson::removeNonLatinKey() -{ - const QString nonLatinKeyName = QString::fromUtf8("Атрибут100500"); - - QJsonObject sourceObject; - - sourceObject.insert("code", 1); - sourceObject.remove("code"); - - sourceObject.insert(nonLatinKeyName, 1); - - const QByteArray json = QJsonDocument(sourceObject).toJson(); - const QJsonObject restoredObject = QJsonDocument::fromJson(json).object(); - - QCOMPARE(sourceObject.keys(), restoredObject.keys()); - QVERIFY(sourceObject.contains(nonLatinKeyName)); - QVERIFY(restoredObject.contains(nonLatinKeyName)); -} - -void tst_QtJson::documentFromVariant() -{ - // Test the valid forms of QJsonDocument::fromVariant. - - QString string = QStringLiteral("value"); - - QStringList strList; - strList.append(string); - - QJsonDocument da1 = QJsonDocument::fromVariant(QVariant(strList)); - QVERIFY(da1.isArray()); - - QVariantList list; - list.append(string); - - QJsonDocument da2 = QJsonDocument::fromVariant(list); - QVERIFY(da2.isArray()); - - // As JSON arrays they should be equal. - QCOMPARE(da1.array(), da2.array()); - - - QMap <QString, QVariant> map; - map["key"] = string; - - QJsonDocument do1 = QJsonDocument::fromVariant(QVariant(map)); - QVERIFY(do1.isObject()); - - QHash <QString, QVariant> hash; - hash["key"] = string; - - QJsonDocument do2 = QJsonDocument::fromVariant(QVariant(hash)); - QVERIFY(do2.isObject()); - - // As JSON objects they should be equal. - QCOMPARE(do1.object(), do2.object()); -} - -void tst_QtJson::parseErrorOffset_data() -{ - QTest::addColumn<QByteArray>("json"); - QTest::addColumn<int>("errorOffset"); - - QTest::newRow("Trailing comma in object") << QByteArray("{ \"value\": false, }") << 19; - QTest::newRow("Trailing comma in object plus whitespace") << QByteArray("{ \"value\": false, } ") << 19; - QTest::newRow("Trailing comma in array") << QByteArray("[ false, ]") << 10; - QTest::newRow("Trailing comma in array plus whitespace") << QByteArray("[ false, ] ") << 10; - QTest::newRow("Missing value in object") << QByteArray("{ \"value\": , } ") << 12; - QTest::newRow("Missing value in array") << QByteArray("[ \"value\" , , ] ") << 13; - QTest::newRow("Leading comma in object") << QByteArray("{ , \"value\": false}") << 3; - QTest::newRow("Leading comma in array") << QByteArray("[ , false]") << 3; - QTest::newRow("Stray ,") << QByteArray(" , ") << 3; - QTest::newRow("Stray [") << QByteArray(" [ ") << 5; - QTest::newRow("Stray }") << QByteArray(" } ") << 3; -} - -void tst_QtJson::parseErrorOffset() -{ - QFETCH(QByteArray, json); - QFETCH(int, errorOffset); - - QJsonParseError error; - QJsonDocument::fromJson(json, &error); - - QVERIFY(error.error != QJsonParseError::NoError); - QCOMPARE(error.offset, errorOffset); -} - -void tst_QtJson::implicitValueType() -{ - QJsonObject rootObject{ - {"object", QJsonObject{{"value", 42}}}, - {"array", QJsonArray{665, 666, 667}} - }; - - QJsonValue objectValue = rootObject["object"]; - QCOMPARE(objectValue["value"].toInt(), 42); - QCOMPARE(objectValue["missingValue"], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(objectValue[123], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(objectValue["missingValue"].toInt(123), 123); - - QJsonValue arrayValue = rootObject["array"]; - QCOMPARE(arrayValue[1].toInt(), 666); - QCOMPARE(arrayValue[-1], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(arrayValue["asObject"], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(arrayValue[-1].toInt(123), 123); - - const QJsonObject constObject = rootObject; - QCOMPARE(constObject["object"]["value"].toInt(), 42); - QCOMPARE(constObject["array"][1].toInt(), 666); - - QJsonValue objectAsValue(rootObject); - QCOMPARE(objectAsValue["object"]["value"].toInt(), 42); - QCOMPARE(objectAsValue["array"][1].toInt(), 666); -} - -void tst_QtJson::implicitDocumentType() -{ - QJsonDocument emptyDocument; - QCOMPARE(emptyDocument["asObject"], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(emptyDocument[123], QJsonValue(QJsonValue::Undefined)); - - QJsonDocument objectDocument(QJsonObject{{"value", 42}}); - QCOMPARE(objectDocument["value"].toInt(), 42); - QCOMPARE(objectDocument["missingValue"], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(objectDocument[123], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(objectDocument["missingValue"].toInt(123), 123); - - QJsonDocument arrayDocument(QJsonArray{665, 666, 667}); - QCOMPARE(arrayDocument[1].toInt(), 666); - QCOMPARE(arrayDocument[-1], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(arrayDocument["asObject"], QJsonValue(QJsonValue::Undefined)); - QCOMPARE(arrayDocument[-1].toInt(123), 123); -} - -QTEST_MAIN(tst_QtJson) -#include "tst_qtjson.moc" |