1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** In addition, as a special exception, Digia gives you certain additional
27 ** rights. These rights are described in the Digia Qt LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33 
34 #include <QtTest>
35 
36 #include "json/qjsonarray.h"
37 #include "json/qjsonobject.h"
38 #include "json/qjsonvalue.h"
39 #include "json/qjsondocument.h"
40 #include <limits>
41 
42 #define INVALID_UNICODE "\xCE\xBA\xE1"
43 #define UNICODE_NON_CHARACTER "\xEF\xBF\xBF"
44 #define UNICODE_DJE "\320\202" // Character from the Serbian Cyrillic alphabet
45 
46 class tst_QtJson: public QObject
47 {
48     Q_OBJECT
49 public:
50     tst_QtJson(QObject *parent = 0);
51 
52 private Q_SLOTS:
53     void initTestCase();
54     void cleanupTestCase();
55     void init();
56     void cleanup();
57 
58     void testValueSimple();
59     void testNumbers();
60     void testNumbers_2();
61     void testNumbers_3();
62 
63     void testObjectSimple();
64     void testObjectSmallKeys();
65     void testArraySimple();
66     void testValueObject();
67     void testValueArray();
68     void testObjectNested();
69     void testArrayNested();
70     void testArrayNestedEmpty();
71     void testArrayComfortOperators();
72     void testObjectNestedEmpty();
73 
74     void testValueRef();
75     void testObjectIteration();
76     void testArrayIteration();
77 
78     void testObjectFind();
79 
80     void testDocument();
81 
82     void nullValues();
83     void nullArrays();
84     void nullObject();
85     void constNullObject();
86 
87     void keySorting();
88 
89     void undefinedValues();
90 
91     void fromVariant();
92     void fromVariantMap();
93     void toVariantMap();
94     void toVariantList();
95 
96     void toJson();
97     void toJsonSillyNumericValues();
98     void toJsonLargeNumericValues();
99     void fromJson();
100     void fromJsonErrors();
101     void fromBinary();
102     void toAndFromBinary_data();
103     void toAndFromBinary();
104     void parseNumbers();
105     void parseStrings();
106     void parseDuplicateKeys();
107     void testParser();
108 
109     void compactArray();
110     void compactObject();
111 
112     void validation();
113 
114     void assignToDocument();
115 
116     void testDuplicateKeys();
117     void testCompaction();
118     void testDebugStream();
119     void testCompactionError();
120 
121     void parseUnicodeEscapes();
122 
123     void assignObjects();
124     void assignArrays();
125 
126     void testTrailingComma();
127     void testDetachBug();
128     void testJsonValueRefDefault();
129 
130     void valueEquals();
131     void objectEquals_data();
132     void objectEquals();
133     void arrayEquals_data();
134     void arrayEquals();
135 
136     void bom();
137     void nesting();
138 
139     void longStrings();
140 
141     void arrayInitializerList();
142     void objectInitializerList();
143 
144     void unicodeKeys();
145     void garbageAtEnd();
146 };
147 
tst_QtJson(QObject * parent)148 tst_QtJson::tst_QtJson(QObject *parent) : QObject(parent)
149 {
150 }
151 
initTestCase()152 void tst_QtJson::initTestCase()
153 {
154 }
155 
cleanupTestCase()156 void tst_QtJson::cleanupTestCase()
157 {
158 }
159 
init()160 void tst_QtJson::init()
161 {
162 }
163 
cleanup()164 void tst_QtJson::cleanup()
165 {
166 }
167 
testValueSimple()168 void tst_QtJson::testValueSimple()
169 {
170     QJsonObject object;
171     object.insert("number", 999.);
172     QJsonArray array;
173     for (int i = 0; i < 10; ++i)
174         array.append((double)i);
175 
176     QJsonValue value(true);
177     QCOMPARE(value.type(), QJsonValue::Bool);
178     QCOMPARE(value.toDouble(), 0.);
179     QCOMPARE(value.toString(), QString());
180     QCOMPARE(value.toBool(), true);
181     QCOMPARE(value.toObject(), QJsonObject());
182     QCOMPARE(value.toArray(), QJsonArray());
183     QCOMPARE(value.toDouble(99.), 99.);
184     QCOMPARE(value.toString(QString("test")), QString("test"));
185     QCOMPARE(value.toObject(object), object);
186     QCOMPARE(value.toArray(array), array);
187 
188     value = 999.;
189     QCOMPARE(value.type(), QJsonValue::Double);
190     QCOMPARE(value.toDouble(), 999.);
191     QCOMPARE(value.toString(), QString());
192     QCOMPARE(value.toBool(), false);
193     QCOMPARE(value.toBool(true), true);
194     QCOMPARE(value.toObject(), QJsonObject());
195     QCOMPARE(value.toArray(), QJsonArray());
196 
197     value = QLatin1String("test");
198     QCOMPARE(value.toDouble(), 0.);
199     QCOMPARE(value.toString(), QLatin1String("test"));
200     QCOMPARE(value.toBool(), false);
201     QCOMPARE(value.toObject(), QJsonObject());
202     QCOMPARE(value.toArray(), QJsonArray());
203 }
204 
testNumbers()205 void tst_QtJson::testNumbers()
206 {
207     {
208         int numbers[] = {
209             0,
210             -1,
211             1,
212             (1<<26),
213             (1<<27),
214             (1<<28),
215             -(1<<26),
216             -(1<<27),
217             -(1<<28),
218             (1<<26) - 1,
219             (1<<27) - 1,
220             (1<<28) - 1,
221             -((1<<26) - 1),
222             -((1<<27) - 1),
223             -((1<<28) - 1)
224         };
225         int n = sizeof(numbers)/sizeof(int);
226 
227         QJsonArray array;
228         for (int i = 0; i < n; ++i)
229             array.append((double)numbers[i]);
230 
231         QByteArray serialized = QJsonDocument(array).toJson();
232         QJsonDocument json = QJsonDocument::fromJson(serialized);
233         QJsonArray array2 = json.array();
234 
235         QCOMPARE(array.size(), array2.size());
236         for (int i = 0; i < array.size(); ++i) {
237             QCOMPARE(array.at(i).type(), QJsonValue::Double);
238             QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
239             QCOMPARE(array2.at(i).type(), QJsonValue::Double);
240             QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
241         }
242     }
243 
244     {
245         qint64 numbers[] = {
246             0,
247             -1,
248             1,
249             (1ll<<54),
250             (1ll<<55),
251             (1ll<<56),
252             -(1ll<<54),
253             -(1ll<<55),
254             -(1ll<<56),
255             (1ll<<54) - 1,
256             (1ll<<55) - 1,
257             (1ll<<56) - 1,
258             -((1ll<<54) - 1),
259             -((1ll<<55) - 1),
260             -((1ll<<56) - 1)
261         };
262         int n = sizeof(numbers)/sizeof(qint64);
263 
264         QJsonArray array;
265         for (int i = 0; i < n; ++i)
266             array.append((double)numbers[i]);
267 
268         QByteArray serialized = QJsonDocument(array).toJson();
269         QJsonDocument json = QJsonDocument::fromJson(serialized);
270         QJsonArray array2 = json.array();
271 
272         QCOMPARE(array.size(), array2.size());
273         for (int i = 0; i < array.size(); ++i) {
274             QCOMPARE(array.at(i).type(), QJsonValue::Double);
275             QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
276             QCOMPARE(array2.at(i).type(), QJsonValue::Double);
277             QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
278         }
279     }
280 
281     {
282         double numbers[] = {
283             0,
284             -1,
285             1,
286             double(1ll<<54),
287             double(1ll<<55),
288             double(1ll<<56),
289             double(-(1ll<<54)),
290             double(-(1ll<<55)),
291             double(-(1ll<<56)),
292             double((1ll<<54) - 1),
293             double((1ll<<55) - 1),
294             double((1ll<<56) - 1),
295             double(-((1ll<<54) - 1)),
296             double(-((1ll<<55) - 1)),
297             double(-((1ll<<56) - 1)),
298             1.1,
299             0.1,
300             -0.1,
301             -1.1,
302             1e200,
303             -1e200
304         };
305         int n = sizeof(numbers)/sizeof(double);
306 
307         QJsonArray array;
308         for (int i = 0; i < n; ++i)
309             array.append(numbers[i]);
310 
311         QByteArray serialized = QJsonDocument(array).toJson();
312         QJsonDocument json = QJsonDocument::fromJson(serialized);
313         QJsonArray array2 = json.array();
314 
315         QCOMPARE(array.size(), array2.size());
316         for (int i = 0; i < array.size(); ++i) {
317             QCOMPARE(array.at(i).type(), QJsonValue::Double);
318             QCOMPARE(array.at(i).toDouble(), numbers[i]);
319             QCOMPARE(array2.at(i).type(), QJsonValue::Double);
320             QCOMPARE(array2.at(i).toDouble(), numbers[i]);
321         }
322     }
323 
324 }
325 
testNumbers_2()326 void tst_QtJson::testNumbers_2()
327 {
328     // test cases from TC39 test suite for ECMAScript
329     // http://hg.ecmascript.org/tests/test262/file/d067d2f0ca30/test/suite/ch08/8.5/8.5.1.js
330 
331     // Fill an array with 2 to the power of (0 ... -1075)
332     double value = 1;
333     double floatValues[1076], floatValues_1[1076];
334     QJsonObject jObject;
335     for (int power = 0; power <= 1075; power++) {
336         floatValues[power] = value;
337         jObject.insert(QString::number(power), QJsonValue(floatValues[power]));
338         // Use basic math operations for testing, which are required to support 'gradual underflow' rather
339         // than Math.pow etc..., which are defined as 'implementation dependent'.
340         value = value * 0.5;
341     }
342 
343     QJsonDocument jDocument1(jObject);
344     QByteArray ba(jDocument1.toJson());
345 
346     QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
347     for (int power = 0; power <= 1075; power++) {
348         floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble();
349 #ifdef Q_OS_QNX
350         if (power >= 970)
351             QEXPECT_FAIL("", "See QTBUG-37066", Abort);
352 #endif
353         QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1());
354     }
355 
356     // The last value is below min denorm and should round to 0, everything else should contain a value
357     QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0");
358 
359     // Validate the last actual value is min denorm
360     QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1());
361 
362     // Validate that every value is half the value before it up to 1
363     for (int index = 1074; index > 0; index--) {
364         QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1());
365 
366         QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1());
367     }
368 }
369 
testNumbers_3()370 void tst_QtJson::testNumbers_3()
371 {
372     // test case from QTBUG-31926
373     double d1 = 1.123451234512345;
374     double d2 = 1.123451234512346;
375 
376     QJsonObject jObject;
377     jObject.insert("d1", QJsonValue(d1));
378     jObject.insert("d2", QJsonValue(d2));
379     QJsonDocument jDocument1(jObject);
380     QByteArray ba(jDocument1.toJson());
381 
382     QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
383 
384     double d1_1(jDocument2.object().value("d1").toDouble());
385     double d2_1(jDocument2.object().value("d2").toDouble());
386     QVERIFY(d1_1 != d2_1);
387 }
388 
testObjectSimple()389 void tst_QtJson::testObjectSimple()
390 {
391     QJsonObject object;
392     object.insert("number", 999.);
393     QCOMPARE(object.value("number").type(), QJsonValue::Double);
394     QCOMPARE(object.value("number").toDouble(), 999.);
395     object.insert("string", QString::fromLatin1("test"));
396     QCOMPARE(object.value("string").type(), QJsonValue::String);
397     QCOMPARE(object.value("string").toString(), QString("test"));
398     object.insert("boolean", true);
399     QCOMPARE(object.value("boolean").toBool(), true);
400 
401     QStringList keys = object.keys();
402     QVERIFY2(keys.contains("number"), "key number not found");
403     QVERIFY2(keys.contains("string"), "key string not found");
404     QVERIFY2(keys.contains("boolean"), "key boolean not found");
405 
406     // if we put a JsonValue into the JsonObject and retrieve
407     // it, it should be identical.
408     QJsonValue value(QLatin1String("foo"));
409     object.insert("value", value);
410     QCOMPARE(object.value("value"), value);
411 
412     int size = object.size();
413     object.remove("boolean");
414     QCOMPARE(object.size(), size - 1);
415     QVERIFY2(!object.contains("boolean"), "key boolean should have been removed");
416 
417     QJsonValue taken = object.take("value");
418     QCOMPARE(taken, value);
419     QVERIFY2(!object.contains("value"), "key value should have been removed");
420 
421     QString before = object.value("string").toString();
422     object.insert("string", QString::fromLatin1("foo"));
423     QVERIFY2(object.value("string").toString() != before, "value should have been updated");
424 
425     size = object.size();
426     QJsonObject subobject;
427     subobject.insert("number", 42);
428     subobject.insert(QLatin1String("string"), QLatin1String("foobar"));
429     object.insert("subobject", subobject);
430     QCOMPARE(object.size(), size+1);
431     QJsonValue subvalue = object.take(QLatin1String("subobject"));
432     QCOMPARE(object.size(), size);
433     QCOMPARE(subvalue.toObject(), subobject);
434     // make object detach by modifying it many times
435     for (int i = 0; i < 64; ++i)
436         object.insert(QLatin1String("string"), QLatin1String("bar"));
437     QCOMPARE(object.size(), size);
438     QCOMPARE(subvalue.toObject(), subobject);
439 }
440 
testObjectSmallKeys()441 void tst_QtJson::testObjectSmallKeys()
442 {
443     QJsonObject data1;
444     data1.insert(QLatin1String("1"), 123);
445     QVERIFY(data1.contains(QLatin1String("1")));
446     QCOMPARE(data1.value(QLatin1String("1")).toDouble(), (double)123);
447     data1.insert(QLatin1String("12"), 133);
448     QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133);
449     QVERIFY(data1.contains(QLatin1String("12")));
450     data1.insert(QLatin1String("123"), 323);
451     QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133);
452     QVERIFY(data1.contains(QLatin1String("123")));
453     QCOMPARE(data1.value(QLatin1String("123")).type(), QJsonValue::Double);
454     QCOMPARE(data1.value(QLatin1String("123")).toDouble(), (double)323);
455 }
456 
testArraySimple()457 void tst_QtJson::testArraySimple()
458 {
459     QJsonArray array;
460     array.append(999.);
461     array.append(QString::fromLatin1("test"));
462     array.append(true);
463 
464     QJsonValue val = array.at(0);
465     QCOMPARE(array.at(0).toDouble(), 999.);
466     QCOMPARE(array.at(1).toString(), QString("test"));
467     QCOMPARE(array.at(2).toBool(), true);
468     QCOMPARE(array.size(), 3);
469 
470     // if we put a JsonValue into the JsonArray and retrieve
471     // it, it should be identical.
472     QJsonValue value(QLatin1String("foo"));
473     array.append(value);
474     QCOMPARE(array.at(3), value);
475 
476     int size = array.size();
477     array.removeAt(2);
478     --size;
479     QCOMPARE(array.size(), size);
480 
481     QJsonValue taken = array.takeAt(0);
482     --size;
483     QCOMPARE(taken.toDouble(), 999.);
484     QCOMPARE(array.size(), size);
485 
486     // check whether null values work
487     array.append(QJsonValue());
488     ++size;
489     QCOMPARE(array.size(), size);
490     QCOMPARE(array.last().type(), QJsonValue::Null);
491     QCOMPARE(array.last(), QJsonValue());
492 
493     QCOMPARE(array.first().type(), QJsonValue::String);
494     QCOMPARE(array.first(), QJsonValue(QLatin1String("test")));
495 
496     array.prepend(false);
497     QCOMPARE(array.first().type(), QJsonValue::Bool);
498     QCOMPARE(array.first(), QJsonValue(false));
499 
500     QCOMPARE(array.at(-1), QJsonValue(QJsonValue::Undefined));
501     QCOMPARE(array.at(array.size()), QJsonValue(QJsonValue::Undefined));
502 
503     array.replace(0, -555.);
504     QCOMPARE(array.first().type(), QJsonValue::Double);
505     QCOMPARE(array.first(), QJsonValue(-555.));
506     QCOMPARE(array.at(1).type(), QJsonValue::String);
507     QCOMPARE(array.at(1), QJsonValue(QLatin1String("test")));
508 }
509 
testValueObject()510 void tst_QtJson::testValueObject()
511 {
512     QJsonObject object;
513     object.insert("number", 999.);
514     object.insert("string", QLatin1String("test"));
515     object.insert("boolean", true);
516 
517     QJsonValue value(object);
518 
519     // if we don't modify the original JsonObject, toObject()
520     // on the JsonValue should return the same object (non-detached).
521     QCOMPARE(value.toObject(), object);
522 
523     // if we modify the original object, it should detach
524     object.insert("test", QJsonValue(QLatin1String("test")));
525     QVERIFY2(value.toObject() != object, "object should have detached");
526 }
527 
testValueArray()528 void tst_QtJson::testValueArray()
529 {
530     QJsonArray array;
531     array.append(999.);
532     array.append(QLatin1String("test"));
533     array.append(true);
534 
535     QJsonValue value(array);
536 
537     // if we don't modify the original JsonArray, toArray()
538     // on the JsonValue should return the same object (non-detached).
539     QCOMPARE(value.toArray(), array);
540 
541     // if we modify the original array, it should detach
542     array.append(QLatin1String("test"));
543     QVERIFY2(value.toArray() != array, "array should have detached");
544 }
545 
testObjectNested()546 void tst_QtJson::testObjectNested()
547 {
548     QJsonObject inner, outer;
549     inner.insert("number", 999.);
550     outer.insert("nested", inner);
551 
552     // if we don't modify the original JsonObject, value()
553     // should return the same object (non-detached).
554     QJsonObject value = outer.value("nested").toObject();
555     QCOMPARE(value, inner);
556     QCOMPARE(value.value("number").toDouble(), 999.);
557 
558     // if we modify the original object, it should detach and not
559     // affect the nested object
560     inner.insert("number", 555.);
561     value = outer.value("nested").toObject();
562     QVERIFY2(inner.value("number").toDouble() != value.value("number").toDouble(),
563              "object should have detached");
564 
565     // array in object
566     QJsonArray array;
567     array.append(123.);
568     array.append(456.);
569     outer.insert("array", array);
570     QCOMPARE(outer.value("array").toArray(), array);
571     QCOMPARE(outer.value("array").toArray().at(1).toDouble(), 456.);
572 
573     // two deep objects
574     QJsonObject twoDeep;
575     twoDeep.insert("boolean", true);
576     inner.insert("nested", twoDeep);
577     outer.insert("nested", inner);
578     QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep);
579     QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(),
580              true);
581 }
582 
testArrayNested()583 void tst_QtJson::testArrayNested()
584 {
585     QJsonArray inner, outer;
586     inner.append(999.);
587     outer.append(inner);
588 
589     // if we don't modify the original JsonArray, value()
590     // should return the same array (non-detached).
591     QJsonArray value = outer.at(0).toArray();
592     QCOMPARE(value, inner);
593     QCOMPARE(value.at(0).toDouble(), 999.);
594 
595     // if we modify the original array, it should detach and not
596     // affect the nested array
597     inner.append(555.);
598     value = outer.at(0).toArray();
599     QVERIFY2(inner.size() != value.size(), "array should have detached");
600 
601     // objects in arrays
602     QJsonObject object;
603     object.insert("boolean", true);
604     outer.append(object);
605     QCOMPARE(outer.last().toObject(), object);
606     QCOMPARE(outer.last().toObject().value("boolean").toBool(), true);
607 
608     // two deep arrays
609     QJsonArray twoDeep;
610     twoDeep.append(QJsonValue(QString::fromLatin1("nested")));
611     inner.append(twoDeep);
612     outer.append(inner);
613     QCOMPARE(outer.last().toArray().last().toArray(), twoDeep);
614     QCOMPARE(outer.last().toArray().last().toArray().at(0).toString(), QString("nested"));
615 }
616 
testArrayNestedEmpty()617 void tst_QtJson::testArrayNestedEmpty()
618 {
619     QJsonObject object;
620     QJsonArray inner;
621     object.insert("inner", inner);
622     QJsonValue val = object.value("inner");
623     QJsonArray value = object.value("inner").toArray();
624     QCOMPARE(value.size(), 0);
625     QCOMPARE(value, inner);
626     QCOMPARE(value.size(), 0);
627     object.insert("count", 0.);
628     QCOMPARE(object.value("inner").toArray().size(), 0);
629     QVERIFY(object.value("inner").toArray().isEmpty());
630     QJsonDocument(object).toBinaryData();
631     QCOMPARE(object.value("inner").toArray().size(), 0);
632 }
633 
testObjectNestedEmpty()634 void tst_QtJson::testObjectNestedEmpty()
635 {
636     QJsonObject object;
637     QJsonObject inner;
638     QJsonObject inner2;
639     object.insert("inner", inner);
640     object.insert("inner2", inner2);
641     QJsonObject value = object.value("inner").toObject();
642     QCOMPARE(value.size(), 0);
643     QCOMPARE(value, inner);
644     QCOMPARE(value.size(), 0);
645     object.insert("count", 0.);
646     QCOMPARE(object.value("inner").toObject().size(), 0);
647     QCOMPARE(object.value("inner").type(), QJsonValue::Object);
648     QJsonDocument(object).toBinaryData();
649     QVERIFY(object.value("inner").toObject().isEmpty());
650     QVERIFY(object.value("inner2").toObject().isEmpty());
651     QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(object).toBinaryData());
652     QVERIFY(!doc.isNull());
653     QJsonObject reconstituted(doc.object());
654     QCOMPARE(reconstituted.value("inner").toObject().size(), 0);
655     QCOMPARE(reconstituted.value("inner").type(), QJsonValue::Object);
656     QCOMPARE(reconstituted.value("inner2").type(), QJsonValue::Object);
657 }
658 
testArrayComfortOperators()659 void tst_QtJson::testArrayComfortOperators()
660 {
661     QJsonArray first;
662     first.append(123.);
663     first.append(QLatin1String("foo"));
664 
665     QJsonArray second = QJsonArray() << 123. << QLatin1String("foo");
666     QCOMPARE(first, second);
667 
668     first = first + QLatin1String("bar");
669     second += QLatin1String("bar");
670     QCOMPARE(first, second);
671 }
672 
testValueRef()673 void tst_QtJson::testValueRef()
674 {
675     QJsonArray array;
676     array.append(1.);
677     array.append(2.);
678     array.append(3.);
679     array.append(4);
680     array.append(4.1);
681     array[1] = false;
682 
683     QCOMPARE(array.size(), 5);
684     QCOMPARE(array.at(0).toDouble(), 1.);
685     QCOMPARE(array.at(2).toDouble(), 3.);
686 #if QT_VERSION >= 0x050200
687     QCOMPARE(array.at(3).toInt(), 4);
688     QCOMPARE(array.at(4).toInt(), 0);
689 #endif
690     QCOMPARE(array.at(1).type(), QJsonValue::Bool);
691     QCOMPARE(array.at(1).toBool(), false);
692 
693     QJsonObject object;
694     object[QLatin1String("key")] = true;
695     QCOMPARE(object.size(), 1);
696     object.insert(QLatin1String("null"), QJsonValue());
697     QCOMPARE(object.value(QLatin1String("null")), QJsonValue());
698     object[QLatin1String("null")] = 100.;
699     QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double);
700     QJsonValue val = object[QLatin1String("null")];
701     QCOMPARE(val.toDouble(), 100.);
702     QCOMPARE(object.size(), 2);
703 
704     array[1] = array[2] = object[QLatin1String("key")] = 42;
705     QCOMPARE(array[1], array[2]);
706     QCOMPARE(array[2], object[QLatin1String("key")]);
707     QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42));
708 }
709 
testObjectIteration()710 void tst_QtJson::testObjectIteration()
711 {
712     QJsonObject object;
713 
714     for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
715         QVERIFY(false);
716 
717     const QString property = "kkk";
718     object.insert(property, 11);
719     object.take(property);
720     for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
721         QVERIFY(false);
722 
723     for (int i = 0; i < 10; ++i)
724         object[QString::number(i)] = (double)i;
725 
726     QCOMPARE(object.size(), 10);
727 
728     QCOMPARE(object.begin()->toDouble(), object.constBegin()->toDouble());
729 
730     for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) {
731         QJsonValue value = it.value();
732         QCOMPARE((double)it.key().toInt(), value.toDouble());
733     }
734 
735     {
736         QJsonObject object2 = object;
737         QVERIFY(object == object2);
738 
739         QJsonValue val = *object2.begin();
740         object2.erase(object2.begin());
741         QCOMPARE(object.size(), 10);
742         QCOMPARE(object2.size(), 9);
743 
744         for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) {
745             QJsonValue value = it.value();
746             QVERIFY(it.value() != val);
747             QCOMPARE((double)it.key().toInt(), value.toDouble());
748         }
749     }
750 
751     {
752         QJsonObject object2 = object;
753         QVERIFY(object == object2);
754 
755         QJsonObject::iterator it = object2.find(QString::number(5));
756         object2.erase(it);
757         QCOMPARE(object.size(), 10);
758         QCOMPARE(object2.size(), 9);
759     }
760 
761     {
762         QJsonObject::Iterator it = object.begin();
763         it += 5;
764         QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
765         it -= 3;
766         QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
767         QJsonObject::Iterator it2 = it + 5;
768         QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
769         it2 = it - 1;
770         QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
771     }
772 
773     {
774         QJsonObject::ConstIterator it = object.constBegin();
775         it += 5;
776         QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
777         it -= 3;
778         QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
779         QJsonObject::ConstIterator it2 = it + 5;
780         QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
781         it2 = it - 1;
782         QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
783     }
784 
785     QJsonObject::Iterator it = object.begin();
786     while (!object.isEmpty())
787         it = object.erase(it);
788     QCOMPARE(object.size() , 0);
789     QVERIFY(it == object.end());
790 }
791 
testArrayIteration()792 void tst_QtJson::testArrayIteration()
793 {
794     QJsonArray array;
795     for (int i = 0; i < 10; ++i)
796         array.append(i);
797 
798     QCOMPARE(array.size(), 10);
799 
800     int i = 0;
801     for (QJsonArray::iterator it = array.begin(); it != array.end(); ++it, ++i) {
802         QJsonValue value = (*it);
803         QCOMPARE((double)i, value.toDouble());
804     }
805 
806     QCOMPARE(array.begin()->toDouble(), array.constBegin()->toDouble());
807 
808     {
809         QJsonArray array2 = array;
810         QVERIFY(array == array2);
811 
812         QJsonValue val = *array2.begin();
813         array2.erase(array2.begin());
814         QCOMPARE(array.size(), 10);
815         QCOMPARE(array2.size(), 9);
816 
817         i = 1;
818         for (QJsonArray::const_iterator it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) {
819             QJsonValue value = (*it);
820             QCOMPARE((double)i, value.toDouble());
821         }
822     }
823 
824     {
825         QJsonArray::Iterator it = array.begin();
826         it += 5;
827         QCOMPARE(QJsonValue((*it)).toDouble(), 5.);
828         it -= 3;
829         QCOMPARE(QJsonValue((*it)).toDouble(), 2.);
830         QJsonArray::Iterator it2 = it + 5;
831         QCOMPARE(QJsonValue(*it2).toDouble(), 7.);
832         it2 = it - 1;
833         QCOMPARE(QJsonValue(*it2).toDouble(), 1.);
834     }
835 
836     {
837         QJsonArray::ConstIterator it = array.constBegin();
838         it += 5;
839         QCOMPARE(QJsonValue((*it)).toDouble(), 5.);
840         it -= 3;
841         QCOMPARE(QJsonValue((*it)).toDouble(), 2.);
842         QJsonArray::ConstIterator it2 = it + 5;
843         QCOMPARE(QJsonValue(*it2).toDouble(), 7.);
844         it2 = it - 1;
845         QCOMPARE(QJsonValue(*it2).toDouble(), 1.);
846     }
847 
848     QJsonArray::Iterator it = array.begin();
849     while (!array.isEmpty())
850         it = array.erase(it);
851     QCOMPARE(array.size() , 0);
852     QVERIFY(it == array.end());
853 }
854 
testObjectFind()855 void tst_QtJson::testObjectFind()
856 {
857     QJsonObject object;
858     for (int i = 0; i < 10; ++i)
859         object[QString::number(i)] = i;
860 
861     QCOMPARE(object.size(), 10);
862 
863     QJsonObject::iterator it = object.find(QLatin1String("1"));
864     QCOMPARE((*it).toDouble(), 1.);
865     it = object.find(QLatin1String("11"));
866     QVERIFY((*it).type() == QJsonValue::Undefined);
867     QVERIFY(it == object.end());
868 
869     QJsonObject::const_iterator cit = object.constFind(QLatin1String("1"));
870     QCOMPARE((*cit).toDouble(), 1.);
871     cit = object.constFind(QLatin1String("11"));
872     QVERIFY((*it).type() == QJsonValue::Undefined);
873     QVERIFY(it == object.end());
874 }
875 
testDocument()876 void tst_QtJson::testDocument()
877 {
878     QJsonDocument doc;
879     QCOMPARE(doc.isEmpty(), true);
880     QCOMPARE(doc.isArray(), false);
881     QCOMPARE(doc.isObject(), false);
882 
883     QJsonObject object;
884     doc.setObject(object);
885     QCOMPARE(doc.isEmpty(), false);
886     QCOMPARE(doc.isArray(), false);
887     QCOMPARE(doc.isObject(), true);
888 
889     object.insert(QLatin1String("Key"), QLatin1String("Value"));
890     doc.setObject(object);
891     QCOMPARE(doc.isEmpty(), false);
892     QCOMPARE(doc.isArray(), false);
893     QCOMPARE(doc.isObject(), true);
894     QVERIFY(doc.object() == object);
895     QVERIFY(doc.array() == QJsonArray());
896 
897     doc = QJsonDocument();
898     QCOMPARE(doc.isEmpty(), true);
899     QCOMPARE(doc.isArray(), false);
900     QCOMPARE(doc.isObject(), false);
901 
902     QJsonArray array;
903     doc.setArray(array);
904     QCOMPARE(doc.isEmpty(), false);
905     QCOMPARE(doc.isArray(), true);
906     QCOMPARE(doc.isObject(), false);
907 
908     array.append(QLatin1String("Value"));
909     doc.setArray(array);
910     QCOMPARE(doc.isEmpty(), false);
911     QCOMPARE(doc.isArray(), true);
912     QCOMPARE(doc.isObject(), false);
913     QVERIFY(doc.array() == array);
914     QVERIFY(doc.object() == QJsonObject());
915 
916     QJsonObject outer;
917     outer.insert(QLatin1String("outerKey"), 22);
918     QJsonObject inner;
919     inner.insert(QLatin1String("innerKey"), 42);
920     outer.insert(QLatin1String("innter"), inner);
921     QJsonArray innerArray;
922     innerArray.append(23);
923     outer.insert(QLatin1String("innterArray"), innerArray);
924 
925     QJsonDocument doc2(outer.value(QLatin1String("innter")).toObject());
926     QVERIFY(doc2.object().contains(QLatin1String("innerKey")));
927     QCOMPARE(doc2.object().value(QLatin1String("innerKey")), QJsonValue(42));
928 
929     QJsonDocument doc3;
930     doc3.setObject(outer.value(QLatin1String("innter")).toObject());
931     QCOMPARE(doc3.isArray(), false);
932     QCOMPARE(doc3.isObject(), true);
933     QVERIFY(doc3.object().contains(QLatin1String("innerKey")));
934     QCOMPARE(doc3.object().value(QLatin1String("innerKey")), QJsonValue(42));
935 
936     QJsonDocument doc4(outer.value(QLatin1String("innterArray")).toArray());
937     QCOMPARE(doc4.isArray(), true);
938     QCOMPARE(doc4.isObject(), false);
939     QCOMPARE(doc4.array().size(), 1);
940     QCOMPARE(doc4.array().at(0), QJsonValue(23));
941 
942     QJsonDocument doc5;
943     doc5.setArray(outer.value(QLatin1String("innterArray")).toArray());
944     QCOMPARE(doc5.isArray(), true);
945     QCOMPARE(doc5.isObject(), false);
946     QCOMPARE(doc5.array().size(), 1);
947     QCOMPARE(doc5.array().at(0), QJsonValue(23));
948 }
949 
nullValues()950 void tst_QtJson::nullValues()
951 {
952     QJsonArray array;
953     array.append(QJsonValue());
954 
955     QCOMPARE(array.size(), 1);
956     QCOMPARE(array.at(0), QJsonValue());
957 
958     QJsonObject object;
959     object.insert(QString("key"), QJsonValue());
960     QCOMPARE(object.contains("key"), true);
961     QCOMPARE(object.size(), 1);
962     QCOMPARE(object.value("key"), QJsonValue());
963 }
964 
nullArrays()965 void tst_QtJson::nullArrays()
966 {
967     QJsonArray nullArray;
968     QJsonArray nonNull;
969     nonNull.append(QLatin1String("bar"));
970 
971     QCOMPARE(nullArray, QJsonArray());
972     QVERIFY(nullArray != nonNull);
973     QVERIFY(nonNull != nullArray);
974 
975     QCOMPARE(nullArray.size(), 0);
976     QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined));
977     QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined));
978     QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined));
979     nullArray.removeAt(0);
980     nullArray.removeAt(-1);
981 
982     nullArray.append(QString("bar"));
983     nullArray.removeAt(0);
984 
985     QCOMPARE(nullArray.size(), 0);
986     QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined));
987     QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined));
988     QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined));
989     nullArray.removeAt(0);
990     nullArray.removeAt(-1);
991 }
992 
nullObject()993 void tst_QtJson::nullObject()
994 {
995     QJsonObject nullObject;
996     QJsonObject nonNull;
997     nonNull.insert(QLatin1String("foo"), QLatin1String("bar"));
998 
999     QCOMPARE(nullObject, QJsonObject());
1000     QVERIFY(nullObject != nonNull);
1001     QVERIFY(nonNull != nullObject);
1002 
1003     QCOMPARE(nullObject.size(), 0);
1004     QCOMPARE(nullObject.keys(), QStringList());
1005     nullObject.remove("foo");
1006     QCOMPARE(nullObject, QJsonObject());
1007     QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined));
1008     QCOMPARE(nullObject.contains("foo"), false);
1009 
1010     nullObject.insert("foo", QString("bar"));
1011     nullObject.remove("foo");
1012 
1013     QCOMPARE(nullObject.size(), 0);
1014     QCOMPARE(nullObject.keys(), QStringList());
1015     nullObject.remove("foo");
1016     QCOMPARE(nullObject, QJsonObject());
1017     QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined));
1018     QCOMPARE(nullObject.contains("foo"), false);
1019 }
1020 
constNullObject()1021 void tst_QtJson::constNullObject()
1022 {
1023     const QJsonObject nullObject;
1024     QJsonObject nonNull;
1025     nonNull.insert(QLatin1String("foo"), QLatin1String("bar"));
1026 
1027     QCOMPARE(nullObject, QJsonObject());
1028     QVERIFY(nullObject != nonNull);
1029     QVERIFY(nonNull != nullObject);
1030 
1031     QCOMPARE(nullObject.size(), 0);
1032     QCOMPARE(nullObject.keys(), QStringList());
1033     QCOMPARE(nullObject, QJsonObject());
1034     QCOMPARE(nullObject.contains("foo"), false);
1035     QCOMPARE(nullObject["foo"], QJsonValue(QJsonValue::Undefined));
1036 }
1037 
keySorting()1038 void tst_QtJson::keySorting()
1039 {
1040     const char *json = "{ \"B\": true, \"A\": false }";
1041     QJsonDocument doc = QJsonDocument::fromJson(json);
1042 
1043     QCOMPARE(doc.isObject(), true);
1044 
1045     QJsonObject o = doc.object();
1046     QCOMPARE(o.size(), 2);
1047     QJsonObject::const_iterator it = o.constBegin();
1048     QCOMPARE(it.key(), QLatin1String("A"));
1049     ++it;
1050     QCOMPARE(it.key(), QLatin1String("B"));
1051 }
1052 
undefinedValues()1053 void tst_QtJson::undefinedValues()
1054 {
1055     QJsonObject object;
1056     object.insert("Key", QJsonValue(QJsonValue::Undefined));
1057     QCOMPARE(object.size(), 0);
1058 
1059     object.insert("Key", QLatin1String("Value"));
1060     QCOMPARE(object.size(), 1);
1061     QCOMPARE(object.value("Key").type(), QJsonValue::String);
1062     QCOMPARE(object.value("foo").type(), QJsonValue::Undefined);
1063     object.insert("Key", QJsonValue(QJsonValue::Undefined));
1064     QCOMPARE(object.size(), 0);
1065     QCOMPARE(object.value("Key").type(), QJsonValue::Undefined);
1066 
1067     QJsonArray array;
1068     array.append(QJsonValue(QJsonValue::Undefined));
1069     QCOMPARE(array.size(), 1);
1070     QCOMPARE(array.at(0).type(), QJsonValue::Null);
1071 
1072     QCOMPARE(array.at(1).type(), QJsonValue::Undefined);
1073     QCOMPARE(array.at(-1).type(), QJsonValue::Undefined);
1074 }
1075 
fromVariant()1076 void tst_QtJson::fromVariant()
1077 {
1078     bool boolValue = true;
1079     int intValue = -1;
1080     uint uintValue = 1;
1081     long long longlongValue = -2;
1082     unsigned long long ulonglongValue = 2;
1083     float floatValue = 3.3f;
1084     double doubleValue = 4.4;
1085     QString stringValue("str");
1086 
1087     QStringList stringList;
1088     stringList.append(stringValue);
1089     stringList.append("str2");
1090     QJsonArray jsonArray_string;
1091     jsonArray_string.append(stringValue);
1092     jsonArray_string.append("str2");
1093 
1094     QVariantList variantList;
1095     variantList.append(boolValue);
1096     variantList.append(floatValue);
1097     variantList.append(doubleValue);
1098     variantList.append(stringValue);
1099     variantList.append(stringList);
1100     variantList.append(QVariant());
1101     QJsonArray jsonArray_variant;
1102     jsonArray_variant.append(boolValue);
1103     jsonArray_variant.append(floatValue);
1104     jsonArray_variant.append(doubleValue);
1105     jsonArray_variant.append(stringValue);
1106     jsonArray_variant.append(jsonArray_string);
1107     jsonArray_variant.append(QJsonValue());
1108 
1109     QVariantMap variantMap;
1110     variantMap["bool"] = boolValue;
1111     variantMap["float"] = floatValue;
1112     variantMap["string"] = stringValue;
1113     variantMap["array"] = variantList;
1114     QJsonObject jsonObject;
1115     jsonObject["bool"] = boolValue;
1116     jsonObject["float"] = floatValue;
1117     jsonObject["string"] = stringValue;
1118     jsonObject["array"] = jsonArray_variant;
1119 
1120     QCOMPARE(QJsonValue::fromVariant(QVariant(boolValue)), QJsonValue(boolValue));
1121     QCOMPARE(QJsonValue::fromVariant(QVariant(intValue)), QJsonValue(intValue));
1122     QCOMPARE(QJsonValue::fromVariant(QVariant(uintValue)), QJsonValue(static_cast<double>(uintValue)));
1123     QCOMPARE(QJsonValue::fromVariant(QVariant(longlongValue)), QJsonValue(longlongValue));
1124     QCOMPARE(QJsonValue::fromVariant(QVariant(ulonglongValue)), QJsonValue(static_cast<double>(ulonglongValue)));
1125     QCOMPARE(QJsonValue::fromVariant(QVariant(floatValue)), QJsonValue(static_cast<double>(floatValue)));
1126     QCOMPARE(QJsonValue::fromVariant(QVariant(doubleValue)), QJsonValue(doubleValue));
1127     QCOMPARE(QJsonValue::fromVariant(QVariant(stringValue)), QJsonValue(stringValue));
1128     QCOMPARE(QJsonValue::fromVariant(QVariant(stringList)), QJsonValue(jsonArray_string));
1129     QCOMPARE(QJsonValue::fromVariant(QVariant(variantList)), QJsonValue(jsonArray_variant));
1130     QCOMPARE(QJsonValue::fromVariant(QVariant(variantMap)), QJsonValue(jsonObject));
1131 }
1132 
fromVariantMap()1133 void tst_QtJson::fromVariantMap()
1134 {
1135     QVariantMap map;
1136     map.insert(QLatin1String("key1"), QLatin1String("value1"));
1137     map.insert(QLatin1String("key2"), QLatin1String("value2"));
1138     QJsonObject object = QJsonObject::fromVariantMap(map);
1139     QCOMPARE(object.size(), 2);
1140     QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1")));
1141     QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2")));
1142 
1143     QVariantList list;
1144     list.append(true);
1145     list.append(QVariant());
1146     list.append(999.);
1147     list.append(QLatin1String("foo"));
1148     map.insert("list", list);
1149     object = QJsonObject::fromVariantMap(map);
1150     QCOMPARE(object.size(), 3);
1151     QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1")));
1152     QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2")));
1153     QCOMPARE(object.value(QLatin1String("list")).type(), QJsonValue::Array);
1154     QJsonArray array = object.value(QLatin1String("list")).toArray();
1155     QCOMPARE(array.size(), 4);
1156     QCOMPARE(array.at(0).type(), QJsonValue::Bool);
1157     QCOMPARE(array.at(0).toBool(), true);
1158     QCOMPARE(array.at(1).type(), QJsonValue::Null);
1159     QCOMPARE(array.at(2).type(), QJsonValue::Double);
1160     QCOMPARE(array.at(2).toDouble(), 999.);
1161     QCOMPARE(array.at(3).type(), QJsonValue::String);
1162     QCOMPARE(array.at(3).toString(), QLatin1String("foo"));
1163 }
1164 
toVariantMap()1165 void tst_QtJson::toVariantMap()
1166 {
1167     QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().type()), QMetaType::QVariantMap); // QTBUG-32524
1168 
1169     QJsonObject object;
1170     QVariantMap map = object.toVariantMap();
1171     QVERIFY(map.isEmpty());
1172 
1173     object.insert("Key", QString("Value"));
1174     object.insert("null", QJsonValue());
1175     QJsonArray array;
1176     array.append(true);
1177     array.append(999.);
1178     array.append(QLatin1String("string"));
1179     array.append(QJsonValue());
1180     object.insert("Array", array);
1181 
1182     map = object.toVariantMap();
1183 
1184     QCOMPARE(map.size(), 3);
1185     QCOMPARE(map.value("Key"), QVariant(QString("Value")));
1186     QCOMPARE(map.value("null"), QVariant());
1187     QCOMPARE(map.value("Array").type(), QVariant::List);
1188     QVariantList list = map.value("Array").toList();
1189     QCOMPARE(list.size(), 4);
1190     QCOMPARE(list.at(0), QVariant(true));
1191     QCOMPARE(list.at(1), QVariant(999.));
1192     QCOMPARE(list.at(2), QVariant(QLatin1String("string")));
1193     QCOMPARE(list.at(3), QVariant());
1194 }
1195 
toVariantList()1196 void tst_QtJson::toVariantList()
1197 {
1198     QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().type()), QMetaType::QVariantList); // QTBUG-32524
1199 
1200     QJsonArray array;
1201     QVariantList list = array.toVariantList();
1202     QVERIFY(list.isEmpty());
1203 
1204     array.append(QString("Value"));
1205     array.append(QJsonValue());
1206     QJsonArray inner;
1207     inner.append(true);
1208     inner.append(999.);
1209     inner.append(QLatin1String("string"));
1210     inner.append(QJsonValue());
1211     array.append(inner);
1212 
1213     list = array.toVariantList();
1214 
1215     QCOMPARE(list.size(), 3);
1216     QCOMPARE(list[0], QVariant(QString("Value")));
1217     QCOMPARE(list[1], QVariant());
1218     QCOMPARE(list[2].type(), QVariant::List);
1219     QVariantList vlist = list[2].toList();
1220     QCOMPARE(vlist.size(), 4);
1221     QCOMPARE(vlist.at(0), QVariant(true));
1222     QCOMPARE(vlist.at(1), QVariant(999.));
1223     QCOMPARE(vlist.at(2), QVariant(QLatin1String("string")));
1224     QCOMPARE(vlist.at(3), QVariant());
1225 }
1226 
toJson()1227 void tst_QtJson::toJson()
1228 {
1229     // Test QJsonDocument::Indented format
1230     {
1231         QJsonObject object;
1232         object.insert("\\Key\n", QString("Value"));
1233         object.insert("null", QJsonValue());
1234         QJsonArray array;
1235         array.append(true);
1236         array.append(999.);
1237         array.append(QLatin1String("string"));
1238         array.append(QJsonValue());
1239         array.append(QLatin1String("\\\a\n\r\b\tabcABC\""));
1240         object.insert("Array", array);
1241 
1242         QByteArray json = QJsonDocument(object).toJson();
1243 
1244         QByteArray expected =
1245                 "{\n"
1246                 "    \"Array\": [\n"
1247                 "        true,\n"
1248                 "        999,\n"
1249                 "        \"string\",\n"
1250                 "        null,\n"
1251                 "        \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n"
1252                 "    ],\n"
1253                 "    \"\\\\Key\\n\": \"Value\",\n"
1254                 "    \"null\": null\n"
1255                 "}\n";
1256         QCOMPARE(json, expected);
1257 
1258         QJsonDocument doc;
1259         doc.setObject(object);
1260         json = doc.toJson();
1261         QCOMPARE(json, expected);
1262 
1263         doc.setArray(array);
1264         json = doc.toJson();
1265         expected =
1266                 "[\n"
1267                 "    true,\n"
1268                 "    999,\n"
1269                 "    \"string\",\n"
1270                 "    null,\n"
1271                 "    \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n"
1272                 "]\n";
1273         QCOMPARE(json, expected);
1274     }
1275 
1276     // Test QJsonDocument::Compact format
1277     {
1278         QJsonObject object;
1279         object.insert("\\Key\n", QString("Value"));
1280         object.insert("null", QJsonValue());
1281         QJsonArray array;
1282         array.append(true);
1283         array.append(999.);
1284         array.append(QLatin1String("string"));
1285         array.append(QJsonValue());
1286         array.append(QLatin1String("\\\a\n\r\b\tabcABC\""));
1287         object.insert("Array", array);
1288 
1289         QByteArray json = QJsonDocument(object).toJson(QJsonDocument::Compact);
1290         QByteArray expected =
1291                 "{\"Array\":[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\":\"Value\",\"null\":null}";
1292         QCOMPARE(json, expected);
1293 
1294         QJsonDocument doc;
1295         doc.setObject(object);
1296         json = doc.toJson(QJsonDocument::Compact);
1297         QCOMPARE(json, expected);
1298 
1299         doc.setArray(array);
1300         json = doc.toJson(QJsonDocument::Compact);
1301         expected = "[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"]";
1302         QCOMPARE(json, expected);
1303     }
1304 
1305 }
1306 
toJsonSillyNumericValues()1307 void tst_QtJson::toJsonSillyNumericValues()
1308 {
1309     QJsonObject object;
1310     QJsonArray array;
1311     array.append(QJsonValue(std::numeric_limits<double>::infinity()));  // encode to: null
1312     array.append(QJsonValue(-std::numeric_limits<double>::infinity())); // encode to: null
1313     array.append(QJsonValue(std::numeric_limits<double>::quiet_NaN())); // encode to: null
1314     object.insert("Array", array);
1315 
1316     QByteArray json = QJsonDocument(object).toJson();
1317 
1318     QByteArray expected =
1319             "{\n"
1320             "    \"Array\": [\n"
1321             "        null,\n"
1322             "        null,\n"
1323             "        null\n"
1324             "    ]\n"
1325             "}\n";
1326 
1327     QCOMPARE(json, expected);
1328 
1329     QJsonDocument doc;
1330     doc.setObject(object);
1331     json = doc.toJson();
1332     QCOMPARE(json, expected);
1333 }
1334 
toJsonLargeNumericValues()1335 void tst_QtJson::toJsonLargeNumericValues()
1336 {
1337     QJsonObject object;
1338     QJsonArray array;
1339     array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0
1340     array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE
1341     array.append(QJsonValue(5e-324));                  // JS Number.MIN_VALUE
1342     array.append(QJsonValue(std::numeric_limits<double>::min()));
1343     array.append(QJsonValue(std::numeric_limits<double>::max()));
1344     array.append(QJsonValue(std::numeric_limits<double>::epsilon()));
1345     array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
1346     array.append(QJsonValue(0.0));
1347     array.append(QJsonValue(-std::numeric_limits<double>::min()));
1348     array.append(QJsonValue(-std::numeric_limits<double>::max()));
1349     array.append(QJsonValue(-std::numeric_limits<double>::epsilon()));
1350     array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
1351     array.append(QJsonValue(-0.0));
1352     array.append(QJsonValue(9007199254740992LL));  // JS Number max integer
1353     array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer
1354     object.insert("Array", array);
1355 
1356     QByteArray json = QJsonDocument(object).toJson();
1357 
1358     QByteArray expected =
1359             "{\n"
1360             "    \"Array\": [\n"
1361             "        1.234567,\n"
1362             "        1.7976931348623157e+308,\n"
1363             //     ((4.9406564584124654e-324 == 5e-324) == true)
1364             // I can only think JavaScript has a special formatter to
1365             //  emit this value for this IEEE754 bit pattern.
1366             "        4.9406564584124654e-324,\n"
1367             "        2.2250738585072014e-308,\n"
1368             "        1.7976931348623157e+308,\n"
1369             "        2.2204460492503131e-16,\n"
1370             "        4.9406564584124654e-324,\n"
1371             "        0,\n"
1372             "        -2.2250738585072014e-308,\n"
1373             "        -1.7976931348623157e+308,\n"
1374             "        -2.2204460492503131e-16,\n"
1375             "        -4.9406564584124654e-324,\n"
1376             "        0,\n"
1377             "        9007199254740992,\n"
1378             "        -9007199254740992\n"
1379             "    ]\n"
1380             "}\n";
1381 
1382 #ifdef Q_OS_QNX
1383     QEXPECT_FAIL("", "See QTBUG-37066", Continue);
1384 #endif
1385     QCOMPARE(json, expected);
1386 
1387     QJsonDocument doc;
1388     doc.setObject(object);
1389     json = doc.toJson();
1390 #ifdef Q_OS_QNX
1391     QEXPECT_FAIL("", "See QTBUG-37066", Continue);
1392 #endif
1393     QCOMPARE(json, expected);
1394 }
1395 
fromJson()1396 void tst_QtJson::fromJson()
1397 {
1398     {
1399         QByteArray json = "[\n    true\n]\n";
1400         QJsonDocument doc = QJsonDocument::fromJson(json);
1401         QVERIFY(!doc.isEmpty());
1402         QCOMPARE(doc.isArray(), true);
1403         QCOMPARE(doc.isObject(), false);
1404         QJsonArray array = doc.array();
1405         QCOMPARE(array.size(), 1);
1406         QCOMPARE(array.at(0).type(), QJsonValue::Bool);
1407         QCOMPARE(array.at(0).toBool(), true);
1408         QCOMPARE(doc.toJson(), json);
1409     }
1410     /*{
1411         //regression test: test if unicode_control_characters are correctly decoded
1412         QByteArray json = "[\n    \"" UNICODE_NON_CHARACTER "\"\n]\n";
1413         QJsonDocument doc = QJsonDocument::fromJson(json);
1414         QVERIFY(!doc.isEmpty());
1415         QCOMPARE(doc.isArray(), true);
1416         QCOMPARE(doc.isObject(), false);
1417         QJsonArray array = doc.array();
1418         QCOMPARE(array.size(), 1);
1419         QCOMPARE(array.at(0).type(), QJsonValue::String);
1420         QCOMPARE(array.at(0).toString(), QString::fromUtf8(UNICODE_NON_CHARACTER));
1421         QCOMPARE(doc.toJson(), json);
1422     }*/
1423     {
1424         QByteArray json = "[]";
1425         QJsonDocument doc = QJsonDocument::fromJson(json);
1426         QVERIFY(!doc.isEmpty());
1427         QCOMPARE(doc.isArray(), true);
1428         QCOMPARE(doc.isObject(), false);
1429         QJsonArray array = doc.array();
1430         QCOMPARE(array.size(), 0);
1431     }
1432     {
1433         QByteArray json = "{}";
1434         QJsonDocument doc = QJsonDocument::fromJson(json);
1435         QVERIFY(!doc.isEmpty());
1436         QCOMPARE(doc.isArray(), false);
1437         QCOMPARE(doc.isObject(), true);
1438         QJsonObject object = doc.object();
1439         QCOMPARE(object.size(), 0);
1440     }
1441     {
1442         QByteArray json = "{\n    \"Key\": true\n}\n";
1443         QJsonDocument doc = QJsonDocument::fromJson(json);
1444         QVERIFY(!doc.isEmpty());
1445         QCOMPARE(doc.isArray(), false);
1446         QCOMPARE(doc.isObject(), true);
1447         QJsonObject object = doc.object();
1448         QCOMPARE(object.size(), 1);
1449         QCOMPARE(object.value("Key"), QJsonValue(true));
1450         QCOMPARE(doc.toJson(), json);
1451     }
1452     {
1453         QByteArray json = "[ null, true, false, \"Foo\", 1, [], {} ]";
1454         QJsonDocument doc = QJsonDocument::fromJson(json);
1455         QVERIFY(!doc.isEmpty());
1456         QCOMPARE(doc.isArray(), true);
1457         QCOMPARE(doc.isObject(), false);
1458         QJsonArray array = doc.array();
1459         QCOMPARE(array.size(), 7);
1460         QCOMPARE(array.at(0).type(), QJsonValue::Null);
1461         QCOMPARE(array.at(1).type(), QJsonValue::Bool);
1462         QCOMPARE(array.at(1).toBool(), true);
1463         QCOMPARE(array.at(2).type(), QJsonValue::Bool);
1464         QCOMPARE(array.at(2).toBool(), false);
1465         QCOMPARE(array.at(3).type(), QJsonValue::String);
1466         QCOMPARE(array.at(3).toString(), QLatin1String("Foo"));
1467         QCOMPARE(array.at(4).type(), QJsonValue::Double);
1468         QCOMPARE(array.at(4).toDouble(), 1.);
1469         QCOMPARE(array.at(5).type(), QJsonValue::Array);
1470         QCOMPARE(array.at(5).toArray().size(), 0);
1471         QCOMPARE(array.at(6).type(), QJsonValue::Object);
1472         QCOMPARE(array.at(6).toObject().size(), 0);
1473     }
1474     {
1475         QByteArray json = "{ \"0\": null, \"1\": true, \"2\": false, \"3\": \"Foo\", \"4\": 1, \"5\": [], \"6\": {} }";
1476         QJsonDocument doc = QJsonDocument::fromJson(json);
1477         QVERIFY(!doc.isEmpty());
1478         QCOMPARE(doc.isArray(), false);
1479         QCOMPARE(doc.isObject(), true);
1480         QJsonObject object = doc.object();
1481         QCOMPARE(object.size(), 7);
1482         QCOMPARE(object.value("0").type(), QJsonValue::Null);
1483         QCOMPARE(object.value("1").type(), QJsonValue::Bool);
1484         QCOMPARE(object.value("1").toBool(), true);
1485         QCOMPARE(object.value("2").type(), QJsonValue::Bool);
1486         QCOMPARE(object.value("2").toBool(), false);
1487         QCOMPARE(object.value("3").type(), QJsonValue::String);
1488         QCOMPARE(object.value("3").toString(), QLatin1String("Foo"));
1489         QCOMPARE(object.value("4").type(), QJsonValue::Double);
1490         QCOMPARE(object.value("4").toDouble(), 1.);
1491         QCOMPARE(object.value("5").type(), QJsonValue::Array);
1492         QCOMPARE(object.value("5").toArray().size(), 0);
1493         QCOMPARE(object.value("6").type(), QJsonValue::Object);
1494         QCOMPARE(object.value("6").toObject().size(), 0);
1495     }
1496     {
1497         QByteArray compactJson = "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}";
1498         QJsonDocument doc = QJsonDocument::fromJson(compactJson);
1499         QVERIFY(!doc.isEmpty());
1500         QCOMPARE(doc.isArray(), false);
1501         QCOMPARE(doc.isObject(), true);
1502         QJsonObject object = doc.object();
1503         QCOMPARE(object.size(), 3);
1504         QCOMPARE(object.value("\\Key\n").isString(), true);
1505         QCOMPARE(object.value("\\Key\n").toString(), QString("Value"));
1506         QCOMPARE(object.value("null").isNull(), true);
1507         QCOMPARE(object.value("Array").isArray(), true);
1508         QJsonArray array = object.value("Array").toArray();
1509         QCOMPARE(array.size(), 5);
1510         QCOMPARE(array.at(0).isBool(), true);
1511         QCOMPARE(array.at(0).toBool(), true);
1512         QCOMPARE(array.at(1).isDouble(), true);
1513         QCOMPARE(array.at(1).toDouble(), 999.);
1514         QCOMPARE(array.at(2).isString(), true);
1515         QCOMPARE(array.at(2).toString(), QLatin1String("string"));
1516         QCOMPARE(array.at(3).isNull(), true);
1517         QCOMPARE(array.at(4).isString(), true);
1518         QCOMPARE(array.at(4).toString(), QLatin1String("\\\a\n\r\b\tabcABC\""));
1519     }
1520 }
1521 
fromJsonErrors()1522 void tst_QtJson::fromJsonErrors()
1523 {
1524     {
1525         QJsonParseError error;
1526         QByteArray json = "{\n    \n\n";
1527         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1528         QVERIFY(doc.isEmpty());
1529         QCOMPARE(error.error, QJsonParseError::UnterminatedObject);
1530         QCOMPARE(error.offset, 8);
1531     }
1532     {
1533         QJsonParseError error;
1534         QByteArray json = "{\n    \"key\" 10\n";
1535         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1536         QVERIFY(doc.isEmpty());
1537         QCOMPARE(error.error, QJsonParseError::MissingNameSeparator);
1538         QCOMPARE(error.offset, 13);
1539     }
1540     {
1541         QJsonParseError error;
1542         QByteArray json = "[\n    \n\n";
1543         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1544         QVERIFY(doc.isEmpty());
1545         QCOMPARE(error.error, QJsonParseError::UnterminatedArray);
1546         QCOMPARE(error.offset, 8);
1547     }
1548     {
1549         QJsonParseError error;
1550         QByteArray json = "[\n   1, true\n\n";
1551         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1552         QVERIFY(doc.isEmpty());
1553         QCOMPARE(error.error, QJsonParseError::UnterminatedArray);
1554         QCOMPARE(error.offset, 14);
1555     }
1556     {
1557         QJsonParseError error;
1558         QByteArray json = "[\n  1 true\n\n";
1559         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1560         QVERIFY(doc.isEmpty());
1561         QCOMPARE(error.error, QJsonParseError::MissingValueSeparator);
1562         QCOMPARE(error.offset, 7);
1563     }
1564     {
1565         QJsonParseError error;
1566         QByteArray json = "[\n    nul";
1567         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1568         QVERIFY(doc.isEmpty());
1569         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1570         QCOMPARE(error.offset, 7);
1571     }
1572     {
1573         QJsonParseError error;
1574         QByteArray json = "[\n    nulzz";
1575         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1576         QVERIFY(doc.isEmpty());
1577         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1578         QCOMPARE(error.offset, 10);
1579     }
1580     {
1581         QJsonParseError error;
1582         QByteArray json = "[\n    tru";
1583         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1584         QVERIFY(doc.isEmpty());
1585         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1586         QCOMPARE(error.offset, 7);
1587     }
1588     {
1589         QJsonParseError error;
1590         QByteArray json = "[\n    trud]";
1591         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1592         QVERIFY(doc.isEmpty());
1593         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1594         QCOMPARE(error.offset, 10);
1595     }
1596     {
1597         QJsonParseError error;
1598         QByteArray json = "[\n    fal";
1599         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1600         QVERIFY(doc.isEmpty());
1601         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1602         QCOMPARE(error.offset, 7);
1603     }
1604     {
1605         QJsonParseError error;
1606         QByteArray json = "[\n    falsd]";
1607         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1608         QVERIFY(doc.isEmpty());
1609         QCOMPARE(error.error, QJsonParseError::IllegalValue);
1610         QCOMPARE(error.offset, 11);
1611     }
1612     {
1613         QJsonParseError error;
1614         QByteArray json = "[\n    11111";
1615         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1616         QVERIFY(doc.isEmpty());
1617         QCOMPARE(error.error, QJsonParseError::TerminationByNumber);
1618         QCOMPARE(error.offset, 11);
1619     }
1620     {
1621         QJsonParseError error;
1622         QByteArray json = "[\n    -1E10000]";
1623         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1624         QVERIFY(doc.isEmpty());
1625         QCOMPARE(error.error, QJsonParseError::IllegalNumber);
1626         QCOMPARE(error.offset, 14);
1627     }
1628     {
1629         QJsonParseError error;
1630         QByteArray json = "[\n    -1e-10000]";
1631         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1632         QVERIFY(doc.isEmpty());
1633         QCOMPARE(error.error, QJsonParseError::IllegalNumber);
1634         QCOMPARE(error.offset, 15);
1635     }
1636     {
1637         QJsonParseError error;
1638         QByteArray json = "[\n    \"\\u12\"]";
1639         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1640         QVERIFY(doc.isEmpty());
1641         QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence);
1642         QCOMPARE(error.offset, 11);
1643     }
1644     {
1645         QJsonParseError error;
1646         QByteArray json = "[\n    \"foo" INVALID_UNICODE "bar\"]";
1647         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1648         QVERIFY(doc.isEmpty());
1649         QCOMPARE(error.error, QJsonParseError::IllegalUTF8String);
1650         QCOMPARE(error.offset, 14);
1651     }
1652     {
1653         QJsonParseError error;
1654         QByteArray json = "[\n    \"";
1655         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1656         QVERIFY(doc.isEmpty());
1657         QCOMPARE(error.error, QJsonParseError::UnterminatedString);
1658         QCOMPARE(error.offset, 8);
1659     }
1660     {
1661         QJsonParseError error;
1662         QByteArray json = "[\n    \"c" UNICODE_DJE "a\\u12\"]";
1663         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1664         QVERIFY(doc.isEmpty());
1665         QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence);
1666         QCOMPARE(error.offset, 15);
1667     }
1668     {
1669         QJsonParseError error;
1670         QByteArray json = "[\n    \"c" UNICODE_DJE "a" INVALID_UNICODE "bar\"]";
1671         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1672         QVERIFY(doc.isEmpty());
1673         QCOMPARE(error.error, QJsonParseError::IllegalUTF8String);
1674         QCOMPARE(error.offset, 15);
1675     }
1676     {
1677         QJsonParseError error;
1678         QByteArray json = "[\n    \"c" UNICODE_DJE "a ]";
1679         QJsonDocument doc = QJsonDocument::fromJson(json, &error);
1680         QVERIFY(doc.isEmpty());
1681         QCOMPARE(error.error, QJsonParseError::UnterminatedString);
1682         QCOMPARE(error.offset, 14);
1683     }
1684 }
1685 
fromBinary()1686 void tst_QtJson::fromBinary()
1687 {
1688     QFile file(":/test.json");
1689     file.open(QFile::ReadOnly);
1690     QByteArray testJson = file.readAll();
1691 
1692     QJsonDocument doc = QJsonDocument::fromJson(testJson);
1693     QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
1694     QVERIFY(!outdoc.isNull());
1695     QVERIFY(doc == outdoc);
1696 
1697     QFile bfile(":/test.bjson");
1698     bfile.open(QFile::ReadOnly);
1699     QByteArray binary = bfile.readAll();
1700 
1701     QJsonDocument bdoc = QJsonDocument::fromBinaryData(binary);
1702     QVERIFY(!bdoc.isNull());
1703     QVERIFY(doc.toVariant() == bdoc.toVariant());
1704     QVERIFY(doc == bdoc);
1705 }
1706 
toAndFromBinary_data()1707 void tst_QtJson::toAndFromBinary_data()
1708 {
1709     QTest::addColumn<QString>("filename");
1710     QTest::newRow("test.json") << (":/test.json");
1711     QTest::newRow("test2.json") << (":/test2.json");
1712 }
1713 
toAndFromBinary()1714 void tst_QtJson::toAndFromBinary()
1715 {
1716     QFETCH(QString, filename);
1717     QFile file(filename);
1718     QVERIFY(file.open(QFile::ReadOnly));
1719     QByteArray data = file.readAll();
1720 
1721     QJsonDocument doc = QJsonDocument::fromJson(data);
1722     QVERIFY(!doc.isNull());
1723     QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
1724     QVERIFY(!outdoc.isNull());
1725     QVERIFY(doc == outdoc);
1726 }
1727 
parseNumbers()1728 void tst_QtJson::parseNumbers()
1729 {
1730     {
1731         // test number parsing
1732         struct Numbers {
1733             const char *str;
1734             int n;
1735         };
1736         Numbers numbers [] = {
1737             { "0", 0 },
1738             { "1", 1 },
1739             { "10", 10 },
1740             { "-1", -1 },
1741             { "100000", 100000 },
1742             { "-999", -999 }
1743         };
1744         int size = sizeof(numbers)/sizeof(Numbers);
1745         for (int i = 0; i < size; ++i) {
1746             QByteArray json = "[ ";
1747             json += numbers[i].str;
1748             json += " ]";
1749             QJsonDocument doc = QJsonDocument::fromJson(json);
1750             QVERIFY(!doc.isEmpty());
1751             QCOMPARE(doc.isArray(), true);
1752             QCOMPARE(doc.isObject(), false);
1753             QJsonArray array = doc.array();
1754             QCOMPARE(array.size(), 1);
1755             QJsonValue val = array.at(0);
1756             QCOMPARE(val.type(), QJsonValue::Double);
1757             QCOMPARE(val.toDouble(), (double)numbers[i].n);
1758         }
1759     }
1760     {
1761         // test number parsing
1762         struct Numbers {
1763             const char *str;
1764             double n;
1765         };
1766         Numbers numbers [] = {
1767             { "0", 0 },
1768             { "1", 1 },
1769             { "10", 10 },
1770             { "-1", -1 },
1771             { "100000", 100000 },
1772             { "-999", -999 },
1773             { "1.1", 1.1 },
1774             { "1e10", 1e10 },
1775             { "-1.1", -1.1 },
1776             { "-1e10", -1e10 },
1777             { "-1E10", -1e10 },
1778             { "1.1e10", 1.1e10 },
1779             { "1.1e308", 1.1e308 },
1780             { "-1.1e308", -1.1e308 },
1781             { "1.1e-308", 1.1e-308 },
1782             { "-1.1e-308", -1.1e-308 },
1783             { "1.1e+308", 1.1e+308 },
1784             { "-1.1e+308", -1.1e+308 },
1785             { "1.e+308", 1.e+308 },
1786             { "-1.e+308", -1.e+308 }
1787         };
1788         int size = sizeof(numbers)/sizeof(Numbers);
1789         for (int i = 0; i < size; ++i) {
1790             QByteArray json = "[ ";
1791             json += numbers[i].str;
1792             json += " ]";
1793             QJsonDocument doc = QJsonDocument::fromJson(json);
1794 #ifdef Q_OS_QNX
1795             if (0 == QString::compare(numbers[i].str, "1.1e-308"))
1796                 QEXPECT_FAIL("", "See QTBUG-37066", Abort);
1797 #endif
1798             QVERIFY(!doc.isEmpty());
1799             QCOMPARE(doc.isArray(), true);
1800             QCOMPARE(doc.isObject(), false);
1801             QJsonArray array = doc.array();
1802             QCOMPARE(array.size(), 1);
1803             QJsonValue val = array.at(0);
1804             QCOMPARE(val.type(), QJsonValue::Double);
1805             QCOMPARE(val.toDouble(), numbers[i].n);
1806         }
1807     }
1808 }
1809 
parseStrings()1810 void tst_QtJson::parseStrings()
1811 {
1812     const char *strings [] =
1813     {
1814         "Foo",
1815         "abc\\\"abc",
1816         "abc\\\\abc",
1817         "abc\\babc",
1818         "abc\\fabc",
1819         "abc\\nabc",
1820         "abc\\rabc",
1821         "abc\\tabc",
1822         "abc\\u0019abc"
1823 //        "abc" UNICODE_DJE "abc",
1824 //        UNICODE_NON_CHARACTER
1825     };
1826     int size = sizeof(strings)/sizeof(const char *);
1827 
1828     for (int i = 0; i < size; ++i) {
1829         QByteArray json = "[\n    \"";
1830         json += strings[i];
1831         json += "\"\n]\n";
1832         QJsonDocument doc = QJsonDocument::fromJson(json);
1833         QVERIFY(!doc.isEmpty());
1834         QCOMPARE(doc.isArray(), true);
1835         QCOMPARE(doc.isObject(), false);
1836         QJsonArray array = doc.array();
1837         QCOMPARE(array.size(), 1);
1838         QJsonValue val = array.at(0);
1839         QCOMPARE(val.type(), QJsonValue::String);
1840 
1841         QCOMPARE(doc.toJson(), json);
1842     }
1843 
1844     struct Pairs {
1845         const char *in;
1846         const char *out;
1847     };
1848     Pairs pairs [] = {
1849         { "abc\\/abc", "abc/abc" },
1850 //        { "abc\\u0402abc", "abc" UNICODE_DJE "abc" },
1851         { "abc\\u0065abc", "abceabc" }
1852 //        { "abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc" }
1853     };
1854     size = sizeof(pairs)/sizeof(Pairs);
1855 
1856     for (int i = 0; i < size; ++i) {
1857         QByteArray json = "[\n    \"";
1858         json += pairs[i].in;
1859         json += "\"\n]\n";
1860         QByteArray out = "[\n    \"";
1861         out += pairs[i].out;
1862         out += "\"\n]\n";
1863         QJsonDocument doc = QJsonDocument::fromJson(json);
1864         QVERIFY(!doc.isEmpty());
1865         QCOMPARE(doc.isArray(), true);
1866         QCOMPARE(doc.isObject(), false);
1867         QJsonArray array = doc.array();
1868         QCOMPARE(array.size(), 1);
1869         QJsonValue val = array.at(0);
1870         QCOMPARE(val.type(), QJsonValue::String);
1871 
1872         QCOMPARE(doc.toJson(), out);
1873     }
1874 
1875 }
1876 
parseDuplicateKeys()1877 void tst_QtJson::parseDuplicateKeys()
1878 {
1879     const char *json = "{ \"B\": true, \"A\": null, \"B\": false }";
1880 
1881     QJsonDocument doc = QJsonDocument::fromJson(json);
1882     QCOMPARE(doc.isObject(), true);
1883 
1884     QJsonObject o = doc.object();
1885     QCOMPARE(o.size(), 2);
1886     QJsonObject::const_iterator it = o.constBegin();
1887     QCOMPARE(it.key(), QLatin1String("A"));
1888     QCOMPARE(it.value(), QJsonValue());
1889     ++it;
1890     QCOMPARE(it.key(), QLatin1String("B"));
1891     QCOMPARE(it.value(), QJsonValue(false));
1892 }
1893 
testParser()1894 void tst_QtJson::testParser()
1895 {
1896     QFile file(":/test.json");
1897     file.open(QFile::ReadOnly);
1898     QByteArray testJson = file.readAll();
1899 
1900     QJsonDocument doc = QJsonDocument::fromJson(testJson);
1901     QVERIFY(!doc.isEmpty());
1902 }
1903 
compactArray()1904 void tst_QtJson::compactArray()
1905 {
1906     QJsonArray array;
1907     array.append(QLatin1String("First Entry"));
1908     array.append(QLatin1String("Second Entry"));
1909     array.append(QLatin1String("Third Entry"));
1910     QJsonDocument doc(array);
1911     int s =  doc.toBinaryData().size();
1912     array.removeAt(1);
1913     doc.setArray(array);
1914     QVERIFY(s > doc.toBinaryData().size());
1915     s = doc.toBinaryData().size();
1916     QCOMPARE(doc.toJson(),
1917              QByteArray("[\n"
1918                         "    \"First Entry\",\n"
1919                         "    \"Third Entry\"\n"
1920                         "]\n"));
1921 
1922     array.removeAt(0);
1923     doc.setArray(array);
1924     QVERIFY(s > doc.toBinaryData().size());
1925     s = doc.toBinaryData().size();
1926     QCOMPARE(doc.toJson(),
1927              QByteArray("[\n"
1928                         "    \"Third Entry\"\n"
1929                         "]\n"));
1930 
1931     array.removeAt(0);
1932     doc.setArray(array);
1933     QVERIFY(s > doc.toBinaryData().size());
1934     s = doc.toBinaryData().size();
1935     QCOMPARE(doc.toJson(),
1936              QByteArray("[\n"
1937                         "]\n"));
1938 
1939 }
1940 
compactObject()1941 void tst_QtJson::compactObject()
1942 {
1943     QJsonObject object;
1944     object.insert(QLatin1String("Key1"), QLatin1String("First Entry"));
1945     object.insert(QLatin1String("Key2"), QLatin1String("Second Entry"));
1946     object.insert(QLatin1String("Key3"), QLatin1String("Third Entry"));
1947     QJsonDocument doc(object);
1948     int s =  doc.toBinaryData().size();
1949     object.remove(QLatin1String("Key2"));
1950     doc.setObject(object);
1951     QVERIFY(s > doc.toBinaryData().size());
1952     s = doc.toBinaryData().size();
1953     QCOMPARE(doc.toJson(),
1954              QByteArray("{\n"
1955                         "    \"Key1\": \"First Entry\",\n"
1956                         "    \"Key3\": \"Third Entry\"\n"
1957                         "}\n"));
1958 
1959     object.remove(QLatin1String("Key1"));
1960     doc.setObject(object);
1961     QVERIFY(s > doc.toBinaryData().size());
1962     s = doc.toBinaryData().size();
1963     QCOMPARE(doc.toJson(),
1964              QByteArray("{\n"
1965                         "    \"Key3\": \"Third Entry\"\n"
1966                         "}\n"));
1967 
1968     object.remove(QLatin1String("Key3"));
1969     doc.setObject(object);
1970     QVERIFY(s > doc.toBinaryData().size());
1971     s = doc.toBinaryData().size();
1972     QCOMPARE(doc.toJson(),
1973              QByteArray("{\n"
1974                         "}\n"));
1975 
1976 }
1977 
validation()1978 void tst_QtJson::validation()
1979 {
1980     // this basically tests that we don't crash on corrupt data
1981     QFile file(":/test.json");
1982     QVERIFY(file.open(QFile::ReadOnly));
1983     QByteArray testJson = file.readAll();
1984     QVERIFY(!testJson.isEmpty());
1985 
1986     QJsonDocument doc = QJsonDocument::fromJson(testJson);
1987     QVERIFY(!doc.isNull());
1988 
1989     QByteArray binary = doc.toBinaryData();
1990 
1991     // only test the first 1000 bytes. Testing the full file takes too long
1992     for (int i = 0; i < 1000; ++i) {
1993         QByteArray corrupted = binary;
1994         corrupted[i] = char(0xff);
1995         QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
1996         if (doc.isNull())
1997             continue;
1998         QByteArray json = doc.toJson();
1999     }
2000 
2001 
2002     QFile file2(":/test3.json");
2003     file2.open(QFile::ReadOnly);
2004     testJson = file2.readAll();
2005     QVERIFY(!testJson.isEmpty());
2006 
2007     doc = QJsonDocument::fromJson(testJson);
2008     QVERIFY(!doc.isNull());
2009 
2010     binary = doc.toBinaryData();
2011 
2012     for (int i = 0; i < binary.size(); ++i) {
2013         QByteArray corrupted = binary;
2014         corrupted[i] = char(0xff);
2015         QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
2016         if (doc.isNull())
2017             continue;
2018         QByteArray json = doc.toJson();
2019 
2020         corrupted = binary;
2021         corrupted[i] = 0x00;
2022         doc = QJsonDocument::fromBinaryData(corrupted);
2023         if (doc.isNull())
2024             continue;
2025         json = doc.toJson();
2026     }
2027 }
2028 
assignToDocument()2029 void tst_QtJson::assignToDocument()
2030 {
2031     {
2032         const char *json = "{ \"inner\": { \"key\": true } }";
2033         QJsonDocument doc = QJsonDocument::fromJson(json);
2034 
2035         QJsonObject o = doc.object();
2036         QJsonValue inner = o.value("inner");
2037 
2038         QJsonDocument innerDoc(inner.toObject());
2039 
2040         QVERIFY(innerDoc != doc);
2041         QVERIFY(innerDoc.object() == inner.toObject());
2042     }
2043     {
2044         const char *json = "[ [ true ] ]";
2045         QJsonDocument doc = QJsonDocument::fromJson(json);
2046 
2047         QJsonArray a = doc.array();
2048         QJsonValue inner = a.at(0);
2049 
2050         QJsonDocument innerDoc(inner.toArray());
2051 
2052         QVERIFY(innerDoc != doc);
2053         QVERIFY(innerDoc.array() == inner.toArray());
2054     }
2055 }
2056 
2057 
testDuplicateKeys()2058 void tst_QtJson::testDuplicateKeys()
2059 {
2060     QJsonObject obj;
2061     obj.insert(QLatin1String("foo"), QLatin1String("bar"));
2062     obj.insert(QLatin1String("foo"), QLatin1String("zap"));
2063     QCOMPARE(obj.size(), 1);
2064     QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("zap"));
2065 }
2066 
testCompaction()2067 void tst_QtJson::testCompaction()
2068 {
2069     // modify object enough times to trigger compactionCounter
2070     // and make sure the data is still valid
2071     QJsonObject obj;
2072     for (int i = 0; i < 33; ++i) {
2073         obj.remove(QLatin1String("foo"));
2074         obj.insert(QLatin1String("foo"), QLatin1String("bar"));
2075     }
2076     QCOMPARE(obj.size(), 1);
2077     QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar"));
2078 
2079     QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(obj).toBinaryData());
2080     QVERIFY(!doc.isNull());
2081     QVERIFY(!doc.isEmpty());
2082     QCOMPARE(doc.isArray(), false);
2083     QCOMPARE(doc.isObject(), true);
2084     QVERIFY(doc.object() == obj);
2085 }
2086 
testDebugStream()2087 void tst_QtJson::testDebugStream()
2088 {
2089     {
2090         // QJsonObject
2091 
2092         QJsonObject object;
2093         QTest::ignoreMessage(QtDebugMsg, "QJsonObject() ");
2094         qDebug() << object;
2095 
2096         object.insert(QLatin1String("foo"), QLatin1String("bar"));
2097         QTest::ignoreMessage(QtDebugMsg, "QJsonObject({\"foo\":\"bar\"}) ");
2098         qDebug() << object;
2099     }
2100 
2101     {
2102         // QJsonArray
2103 
2104         QJsonArray array;
2105         QTest::ignoreMessage(QtDebugMsg, "QJsonArray() ");
2106         qDebug() << array;
2107 
2108         array.append(1);
2109         array.append(QLatin1String("foo"));
2110         QTest::ignoreMessage(QtDebugMsg, "QJsonArray([1,\"foo\"]) ");
2111         qDebug() << array;
2112     }
2113 
2114     {
2115         // QJsonDocument
2116 
2117         QJsonDocument doc;
2118         QTest::ignoreMessage(QtDebugMsg, "QJsonDocument() ");
2119         qDebug() << doc;
2120 
2121         QJsonObject object;
2122         object.insert(QLatin1String("foo"), QLatin1String("bar"));
2123         doc.setObject(object);
2124         QTest::ignoreMessage(QtDebugMsg, "QJsonDocument({\"foo\":\"bar\"}) ");
2125         qDebug() << doc;
2126 
2127         QJsonArray array;
2128         array.append(1);
2129         array.append(QLatin1String("foo"));
2130         QTest::ignoreMessage(QtDebugMsg, "QJsonDocument([1,\"foo\"]) ");
2131         doc.setArray(array);
2132         qDebug() << doc;
2133     }
2134 
2135     {
2136         // QJsonValue
2137 
2138         QJsonValue value;
2139 
2140         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(null) ");
2141         qDebug() << value;
2142 
2143         value = QJsonValue(true); // bool
2144         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(bool, true) ");
2145         qDebug() << value;
2146 
2147         value = QJsonValue((double)4.2); // double
2148         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 4.2) ");
2149         qDebug() << value;
2150 
2151         value = QJsonValue((int)42); // int
2152         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 42) ");
2153         qDebug() << value;
2154 
2155         value = QJsonValue(QLatin1String("foo")); // string
2156         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(string, \"foo\") ");
2157         qDebug() << value;
2158 
2159         QJsonArray array;
2160         array.append(1);
2161         array.append(QLatin1String("foo"));
2162         value = QJsonValue(array); // array
2163         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(array, QJsonArray([1,\"foo\"]) ) ");
2164         qDebug() << value;
2165 
2166         QJsonObject object;
2167         object.insert(QLatin1String("foo"), QLatin1String("bar"));
2168         value = QJsonValue(object); // object
2169         QTest::ignoreMessage(QtDebugMsg, "QJsonValue(object, QJsonObject({\"foo\":\"bar\"}) ) ");
2170         qDebug() << value;
2171     }
2172 }
2173 
testCompactionError()2174 void tst_QtJson::testCompactionError()
2175 {
2176     QJsonObject schemaObject;
2177     schemaObject.insert("_Type", QLatin1String("_SchemaType"));
2178     schemaObject.insert("name", QLatin1String("Address"));
2179     schemaObject.insert("schema", QJsonObject());
2180     {
2181         QJsonObject content(schemaObject);
2182         QJsonDocument doc(content);
2183         QVERIFY(!doc.isNull());
2184         QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
2185         schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
2186     }
2187 
2188     QJsonObject schema;
2189     schema.insert("streetNumber", schema.value("number").toObject());
2190     schemaObject.insert("schema", schema);
2191     {
2192         QJsonObject content(schemaObject);
2193         content.remove("_Uuid");
2194         content.remove("_Version");
2195         QJsonDocument doc(content);
2196         QVERIFY(!doc.isNull());
2197         QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
2198         schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
2199     }
2200 }
2201 
parseUnicodeEscapes()2202 void tst_QtJson::parseUnicodeEscapes()
2203 {
2204     const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]";
2205 
2206     QJsonDocument doc = QJsonDocument::fromJson(json);
2207     QJsonArray array = doc.array();
2208 
2209     QString result = QLatin1String("A");
2210     result += QChar(0xe4);
2211     result += QChar(0xc4);
2212 
2213     QCOMPARE(array.first().toString(), result);
2214 }
2215 
assignObjects()2216 void tst_QtJson::assignObjects()
2217 {
2218     const char *json =
2219             "[ { \"Key\": 1 }, { \"Key\": 2 } ]";
2220 
2221     QJsonDocument doc = QJsonDocument::fromJson(json);
2222     QJsonArray array = doc.array();
2223 
2224     QJsonObject object = array.at(0).toObject();
2225     QCOMPARE(object.value("Key").toDouble(), 1.);
2226 
2227     object = array.at(1).toObject();
2228     QCOMPARE(object.value("Key").toDouble(), 2.);
2229 }
2230 
assignArrays()2231 void tst_QtJson::assignArrays()
2232 {
2233     const char *json =
2234             "[ [ 1 ], [ 2 ] ]";
2235 
2236     QJsonDocument doc = QJsonDocument::fromJson(json);
2237     QJsonArray array = doc.array();
2238 
2239     QJsonArray inner = array.at(0).toArray()  ;
2240     QCOMPARE(inner.at(0).toDouble(), 1.);
2241 
2242     inner= array.at(1).toArray();
2243     QCOMPARE(inner.at(0).toDouble(), 2.);
2244 }
2245 
testTrailingComma()2246 void tst_QtJson::testTrailingComma()
2247 {
2248     const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" };
2249 
2250     for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) {
2251         QJsonParseError error;
2252         QJsonDocument doc = QJsonDocument::fromJson(jsons[i], &error);
2253         QCOMPARE(error.error, QJsonParseError::MissingObject);
2254     }
2255 }
2256 
testDetachBug()2257 void tst_QtJson::testDetachBug()
2258 {
2259     QJsonObject dynamic;
2260     QJsonObject embedded;
2261 
2262     QJsonObject local;
2263 
2264     embedded.insert("Key1", QString("Value1"));
2265     embedded.insert("Key2", QString("Value2"));
2266     dynamic.insert(QLatin1String("Bogus"), QString("bogusValue"));
2267     dynamic.insert("embedded", embedded);
2268     local = dynamic.value("embedded").toObject();
2269 
2270     dynamic.remove("embedded");
2271 
2272     QCOMPARE(local.keys().size(),2);
2273     local.remove("Key1");
2274     local.remove("Key2");
2275     QCOMPARE(local.keys().size(), 0);
2276 
2277     local.insert("Key1", QString("anotherValue"));
2278     QCOMPARE(local.keys().size(), 1);
2279 }
2280 
valueEquals()2281 void tst_QtJson::valueEquals()
2282 {
2283     QVERIFY(QJsonValue() == QJsonValue());
2284     QVERIFY(QJsonValue() != QJsonValue(QJsonValue::Undefined));
2285     QVERIFY(QJsonValue() != QJsonValue(true));
2286     QVERIFY(QJsonValue() != QJsonValue(1.));
2287     QVERIFY(QJsonValue() != QJsonValue(QJsonArray()));
2288     QVERIFY(QJsonValue() != QJsonValue(QJsonObject()));
2289 
2290     QVERIFY(QJsonValue(true) == QJsonValue(true));
2291     QVERIFY(QJsonValue(true) != QJsonValue(false));
2292     QVERIFY(QJsonValue(true) != QJsonValue(QJsonValue::Undefined));
2293     QVERIFY(QJsonValue(true) != QJsonValue());
2294     QVERIFY(QJsonValue(true) != QJsonValue(1.));
2295     QVERIFY(QJsonValue(true) != QJsonValue(QJsonArray()));
2296     QVERIFY(QJsonValue(true) != QJsonValue(QJsonObject()));
2297 
2298     QVERIFY(QJsonValue(1) == QJsonValue(1));
2299     QVERIFY(QJsonValue(1) != QJsonValue(2));
2300     QVERIFY(QJsonValue(1) == QJsonValue(1.));
2301     QVERIFY(QJsonValue(1) != QJsonValue(1.1));
2302     QVERIFY(QJsonValue(1) != QJsonValue(QJsonValue::Undefined));
2303     QVERIFY(QJsonValue(1) != QJsonValue());
2304     QVERIFY(QJsonValue(1) != QJsonValue(true));
2305     QVERIFY(QJsonValue(1) != QJsonValue(QJsonArray()));
2306     QVERIFY(QJsonValue(1) != QJsonValue(QJsonObject()));
2307 
2308     QVERIFY(QJsonValue(1.) == QJsonValue(1.));
2309     QVERIFY(QJsonValue(1.) != QJsonValue(2.));
2310     QVERIFY(QJsonValue(1.) != QJsonValue(QJsonValue::Undefined));
2311     QVERIFY(QJsonValue(1.) != QJsonValue());
2312     QVERIFY(QJsonValue(1.) != QJsonValue(true));
2313     QVERIFY(QJsonValue(1.) != QJsonValue(QJsonArray()));
2314     QVERIFY(QJsonValue(1.) != QJsonValue(QJsonObject()));
2315 
2316     QVERIFY(QJsonValue(QJsonArray()) == QJsonValue(QJsonArray()));
2317     QJsonArray nonEmptyArray;
2318     nonEmptyArray.append(true);
2319     QVERIFY(QJsonValue(QJsonArray()) != nonEmptyArray);
2320     QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonValue::Undefined));
2321     QVERIFY(QJsonValue(QJsonArray()) != QJsonValue());
2322     QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(true));
2323     QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(1.));
2324     QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonObject()));
2325 
2326     QVERIFY(QJsonValue(QJsonObject()) == QJsonValue(QJsonObject()));
2327     QJsonObject nonEmptyObject;
2328     nonEmptyObject.insert("Key", true);
2329     QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject);
2330     QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonValue::Undefined));
2331     QVERIFY(QJsonValue(QJsonObject()) != QJsonValue());
2332     QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(true));
2333     QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(1.));
2334     QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonArray()));
2335 
2336     QVERIFY(QJsonValue("foo") == QJsonValue(QLatin1String("foo")));
2337     QVERIFY(QJsonValue("foo") == QJsonValue(QString("foo")));
2338     QVERIFY(QJsonValue("\x66\x6f\x6f") == QJsonValue(QString("foo")));
2339     QVERIFY(QJsonValue("\x62\x61\x72") == QJsonValue("bar"));
2340     /*
2341     QVERIFY(QJsonValue(UNICODE_NON_CHARACTER) == QJsonValue(QString(UNICODE_NON_CHARACTER)));
2342     QVERIFY(QJsonValue(UNICODE_DJE) == QJsonValue(QString(UNICODE_DJE)));
2343     QVERIFY(QJsonValue("\xc3\xa9") == QJsonValue(QString("\xc3\xa9")));
2344     */
2345 }
2346 
objectEquals_data()2347 void tst_QtJson::objectEquals_data()
2348 {
2349     QTest::addColumn<QJsonObject>("left");
2350     QTest::addColumn<QJsonObject>("right");
2351     QTest::addColumn<bool>("result");
2352 
2353     QTest::newRow("two defaults") << QJsonObject() << QJsonObject() << true;
2354 
2355     QJsonObject object1;
2356     object1.insert("property", 1);
2357     QJsonObject object2;
2358     object2["property"] = 1;
2359     QJsonObject object3;
2360     object3.insert("property1", 1);
2361     object3.insert("property2", 2);
2362 
2363     QTest::newRow("the same object (1 vs 2)") << object1 << object2 << true;
2364     QTest::newRow("the same object (3 vs 3)") << object3 << object3 << true;
2365     QTest::newRow("different objects (2 vs 3)") << object2 << object3 << false;
2366     QTest::newRow("object vs default") << object1 << QJsonObject() << false;
2367 
2368     QJsonObject empty;
2369     empty.insert("property", 1);
2370     empty.take("property");
2371     QTest::newRow("default vs empty") << QJsonObject() << empty << true;
2372     QTest::newRow("empty vs empty") << empty << empty << true;
2373     QTest::newRow("object vs empty") << object1 << empty << false;
2374 
2375     QJsonObject referencedEmpty;
2376     referencedEmpty["undefined"];
2377     QTest::newRow("referenced empty vs referenced empty") << referencedEmpty << referencedEmpty << true;
2378     QTest::newRow("referenced empty vs object") << referencedEmpty << object1 << false;
2379 
2380     QJsonObject referencedObject1;
2381     referencedObject1.insert("property", 1);
2382     referencedObject1["undefined"];
2383     QJsonObject referencedObject2;
2384     referencedObject2.insert("property", 1);
2385     referencedObject2["aaaaaaaaa"]; // earlier then "property"
2386     referencedObject2["zzzzzzzzz"]; // after "property"
2387     QTest::newRow("referenced object vs default") << referencedObject1 << QJsonObject() << false;
2388     QTest::newRow("referenced object vs referenced object") << referencedObject1 << referencedObject1 << true;
2389     QTest::newRow("referenced object vs object (different)") << referencedObject1 << object3 << false;
2390 }
2391 
objectEquals()2392 void tst_QtJson::objectEquals()
2393 {
2394     QFETCH(QJsonObject, left);
2395     QFETCH(QJsonObject, right);
2396     QFETCH(bool, result);
2397 
2398     QCOMPARE(left == right, result);
2399     QCOMPARE(right == left, result);
2400 
2401     // invariants checks
2402     QCOMPARE(left, left);
2403     QCOMPARE(right, right);
2404     QCOMPARE(left != right, !result);
2405     QCOMPARE(right != left, !result);
2406 
2407     // The same but from QJsonValue perspective
2408     QCOMPARE(QJsonValue(left) == QJsonValue(right), result);
2409     QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
2410     QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
2411     QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
2412 }
2413 
arrayEquals_data()2414 void tst_QtJson::arrayEquals_data()
2415 {
2416     QTest::addColumn<QJsonArray>("left");
2417     QTest::addColumn<QJsonArray>("right");
2418     QTest::addColumn<bool>("result");
2419 
2420     QTest::newRow("two defaults") << QJsonArray() << QJsonArray() << true;
2421 
2422     QJsonArray array1;
2423     array1.append(1);
2424     QJsonArray array2;
2425     array2.append(2111);
2426     array2[0] = 1;
2427     QJsonArray array3;
2428     array3.insert(0, 1);
2429     array3.insert(1, 2);
2430 
2431     QTest::newRow("the same array (1 vs 2)") << array1 << array2 << true;
2432     QTest::newRow("the same array (3 vs 3)") << array3 << array3 << true;
2433     QTest::newRow("different arrays (2 vs 3)") << array2 << array3 << false;
2434     QTest::newRow("array vs default") << array1 << QJsonArray() << false;
2435 
2436     QJsonArray empty;
2437     empty.append(1);
2438     empty.takeAt(0);
2439     QTest::newRow("default vs empty") << QJsonArray() << empty << true;
2440     QTest::newRow("empty vs default") << empty << QJsonArray() << true;
2441     QTest::newRow("empty vs empty") << empty << empty << true;
2442     QTest::newRow("array vs empty") << array1 << empty << false;
2443 }
2444 
arrayEquals()2445 void tst_QtJson::arrayEquals()
2446 {
2447     QFETCH(QJsonArray, left);
2448     QFETCH(QJsonArray, right);
2449     QFETCH(bool, result);
2450 
2451     QCOMPARE(left == right, result);
2452     QCOMPARE(right == left, result);
2453 
2454     // invariants checks
2455     QCOMPARE(left, left);
2456     QCOMPARE(right, right);
2457     QCOMPARE(left != right, !result);
2458     QCOMPARE(right != left, !result);
2459 
2460     // The same but from QJsonValue perspective
2461     QCOMPARE(QJsonValue(left) == QJsonValue(right), result);
2462     QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
2463     QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
2464     QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
2465 }
2466 
bom()2467 void tst_QtJson::bom()
2468 {
2469     QFile file(":/bom.json");
2470     file.open(QFile::ReadOnly);
2471     QByteArray json = file.readAll();
2472 
2473     // Import json document into a QJsonDocument
2474     QJsonParseError error;
2475     QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2476 
2477     QVERIFY(!doc.isNull());
2478     QVERIFY(error.error == QJsonParseError::NoError);
2479 }
2480 
nesting()2481 void tst_QtJson::nesting()
2482 {
2483     // check that we abort parsing too deeply nested json documents.
2484     // this is to make sure we don't crash because the parser exhausts the
2485     // stack.
2486 
2487     const char *array_data =
2488             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2489             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2490             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2491             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2492             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2493             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2494             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2495             "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["
2496             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2497             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2498             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2499             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2500             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2501             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2502             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
2503             "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]";
2504 
2505     QByteArray json(array_data);
2506     QJsonParseError error;
2507     QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2508 
2509     QVERIFY(!doc.isNull());
2510     QVERIFY(error.error == QJsonParseError::NoError);
2511 
2512     json.prepend("[");
2513     json.append("]");
2514     doc = QJsonDocument::fromJson(json, &error);
2515 
2516     QVERIFY(doc.isNull());
2517     QVERIFY(error.error == QJsonParseError::DeepNesting);
2518 
2519     json = QByteArray("true ");
2520 
2521     for (int i = 0; i < 1024; ++i) {
2522         json.prepend("{ \"Key\": ");
2523         json.append(" }");
2524     }
2525 
2526     doc = QJsonDocument::fromJson(json, &error);
2527 
2528     QVERIFY(!doc.isNull());
2529     QVERIFY(error.error == QJsonParseError::NoError);
2530 
2531     json.prepend("[");
2532     json.append("]");
2533     doc = QJsonDocument::fromJson(json, &error);
2534 
2535     QVERIFY(doc.isNull());
2536     QVERIFY(error.error == QJsonParseError::DeepNesting);
2537 
2538 }
2539 
longStrings()2540 void tst_QtJson::longStrings()
2541 {
2542     // test around 15 and 16 bit boundaries, as these are limits
2543     // in the data structures (for Latin1String in qjson_p.h)
2544     QString s(0x7ff0, 'a');
2545     for (int i = 0x7ff0; i < 0x8010; i++) {
2546         s.append("c");
2547 
2548         QMap <QString, QVariant> map;
2549         map["key"] = s;
2550 
2551         /* Create a QJsonDocument from the QMap ... */
2552         QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map));
2553         /* ... and a QByteArray from the QJsonDocument */
2554         QByteArray a1 = d1.toJson();
2555 
2556         /* Create a QJsonDocument from the QByteArray ... */
2557         QJsonDocument d2 = QJsonDocument::fromJson(a1);
2558         /* ... and a QByteArray from the QJsonDocument */
2559         QByteArray a2 = d2.toJson();
2560         QVERIFY(a1 == a2);
2561     }
2562 
2563     s = QString(0xfff0, 'a');
2564     for (int i = 0xfff0; i < 0x10010; i++) {
2565         s.append("c");
2566 
2567         QMap <QString, QVariant> map;
2568         map["key"] = s;
2569 
2570         /* Create a QJsonDocument from the QMap ... */
2571         QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map));
2572         /* ... and a QByteArray from the QJsonDocument */
2573         QByteArray a1 = d1.toJson();
2574 
2575         /* Create a QJsonDocument from the QByteArray ... */
2576         QJsonDocument d2 = QJsonDocument::fromJson(a1);
2577         /* ... and a QByteArray from the QJsonDocument */
2578         QByteArray a2 = d2.toJson();
2579         QVERIFY(a1 == a2);
2580     }
2581 }
2582 
testJsonValueRefDefault()2583 void tst_QtJson::testJsonValueRefDefault()
2584 {
2585     QJsonObject empty;
2586 
2587     QCOMPARE(empty["n/a"].toString(), QString());
2588     QCOMPARE(empty["n/a"].toString("default"), QLatin1String("default"));
2589 
2590     QCOMPARE(empty["n/a"].toBool(), false);
2591     QCOMPARE(empty["n/a"].toBool(true), true);
2592 
2593     QCOMPARE(empty["n/a"].toInt(), 0);
2594     QCOMPARE(empty["n/a"].toInt(42), 42);
2595 
2596     QCOMPARE(empty["n/a"].toDouble(), 0.0);
2597     QCOMPARE(empty["n/a"].toDouble(42.0), 42.0);
2598 }
2599 
arrayInitializerList()2600 void tst_QtJson::arrayInitializerList()
2601 {
2602 #ifndef Q_COMPILER_INITIALIZER_LISTS
2603     QSKIP("initializer_list is enabled only with c++11 support", SkipSingle);
2604 #else
2605     QVERIFY(QJsonArray{}.isEmpty());
2606     QCOMPARE(QJsonArray{"one"}.count(), 1);
2607     QCOMPARE(QJsonArray{1}.count(), 1);
2608 
2609     {
2610         QJsonArray a{1.3, "hello", 0};
2611         QCOMPARE(QJsonValue(a[0]), QJsonValue(1.3));
2612         QCOMPARE(QJsonValue(a[1]), QJsonValue("hello"));
2613         QCOMPARE(QJsonValue(a[2]), QJsonValue(0));
2614         QCOMPARE(a.count(), 3);
2615     }
2616     {
2617         QJsonObject o;
2618         o["property"] = 1;
2619         QJsonArray a1 {o};
2620         QCOMPARE(a1.count(), 1);
2621         QCOMPARE(a1[0].toObject(), o);
2622 
2623         QJsonArray a2 {o, 23};
2624         QCOMPARE(a2.count(), 2);
2625         QCOMPARE(a2[0].toObject(), o);
2626         QCOMPARE(QJsonValue(a2[1]), QJsonValue(23));
2627 
2628         QJsonArray a3 { a1, o, a2 };
2629         QCOMPARE(QJsonValue(a3[0]), QJsonValue(a1));
2630         QCOMPARE(QJsonValue(a3[1]), QJsonValue(o));
2631         QCOMPARE(QJsonValue(a3[2]), QJsonValue(a2));
2632 
2633         QJsonArray a4 { 1, QJsonArray{1,2,3}, QJsonArray{"hello", 2}, QJsonObject{{"one", 1}} };
2634         QCOMPARE(a4.count(), 4);
2635         QCOMPARE(QJsonValue(a4[0]), QJsonValue(1));
2636 
2637         {
2638             QJsonArray a41 = a4[1].toArray();
2639             QJsonArray a42 = a4[2].toArray();
2640             QJsonObject a43 = a4[3].toObject();
2641             QCOMPARE(a41.count(), 3);
2642             QCOMPARE(a42.count(), 2);
2643             QCOMPARE(a43.count(), 1);
2644 
2645             QCOMPARE(QJsonValue(a41[2]), QJsonValue(3));
2646             QCOMPARE(QJsonValue(a42[1]), QJsonValue(2));
2647             QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1));
2648         }
2649     }
2650 #endif
2651 }
2652 
objectInitializerList()2653 void tst_QtJson::objectInitializerList()
2654 {
2655 #ifndef Q_COMPILER_INITIALIZER_LISTS
2656     QSKIP("initializer_list is enabled only with c++11 support", SkipSingle);
2657 #else
2658     QVERIFY(QJsonObject{}.isEmpty());
2659 
2660     {   // one property
2661         QJsonObject one {{"one", 1}};
2662         QCOMPARE(one.count(), 1);
2663         QVERIFY(one.contains("one"));
2664         QCOMPARE(QJsonValue(one["one"]), QJsonValue(1));
2665     }
2666     {   // two properties
2667         QJsonObject two {
2668                            {"one", 1},
2669                            {"two", 2}
2670                         };
2671         QCOMPARE(two.count(), 2);
2672         QVERIFY(two.contains("one"));
2673         QVERIFY(two.contains("two"));
2674         QCOMPARE(QJsonValue(two["one"]), QJsonValue(1));
2675         QCOMPARE(QJsonValue(two["two"]), QJsonValue(2));
2676     }
2677     {   // nested object
2678         QJsonObject object{{"nested", QJsonObject{{"innerProperty", 2}}}};
2679         QCOMPARE(object.count(), 1);
2680         QVERIFY(object.contains("nested"));
2681         QVERIFY(object["nested"].isObject());
2682 
2683         QJsonObject nested = object["nested"].toObject();
2684         QCOMPARE(QJsonValue(nested["innerProperty"]), QJsonValue(2));
2685     }
2686     {   // nested array
2687         QJsonObject object{{"nested", QJsonArray{"innerValue", 2.1, "bum cyk cyk"}}};
2688         QCOMPARE(object.count(), 1);
2689         QVERIFY(object.contains("nested"));
2690         QVERIFY(object["nested"].isArray());
2691 
2692         QJsonArray nested = object["nested"].toArray();
2693         QCOMPARE(nested.count(), 3);
2694         QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue"));
2695         QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1));
2696     }
2697 #endif
2698 }
2699 
unicodeKeys()2700 void tst_QtJson::unicodeKeys()
2701 {
2702     QByteArray json = "{"
2703                       "\"x\\u2090_1\": \"hello_1\","
2704                       "\"y\\u2090_2\": \"hello_2\","
2705                       "\"T\\u2090_3\": \"hello_3\","
2706                       "\"xyz_4\": \"hello_4\","
2707                       "\"abc_5\": \"hello_5\""
2708                       "}";
2709 
2710     QJsonParseError error;
2711     QJsonDocument doc = QJsonDocument::fromJson(json, &error);
2712     QVERIFY(error.error == QJsonParseError::NoError);
2713     QJsonObject o = doc.object();
2714 
2715     QCOMPARE(o.keys().size(), 5);
2716     Q_FOREACH (const QString &key, o.keys()) {
2717         QString suffix = key.mid(key.indexOf(QLatin1Char('_')));
2718         QCOMPARE(o[key].toString(), QString("hello") + suffix);
2719     }
2720 }
2721 
garbageAtEnd()2722 void tst_QtJson::garbageAtEnd()
2723 {
2724     QJsonParseError error;
2725     QJsonDocument doc = QJsonDocument::fromJson("{},", &error);
2726     QVERIFY(error.error == QJsonParseError::GarbageAtEnd);
2727     QVERIFY(error.offset == 2);
2728     QVERIFY(doc.isEmpty());
2729 
2730     doc = QJsonDocument::fromJson("{}    ", &error);
2731     QVERIFY(error.error == QJsonParseError::NoError);
2732     QVERIFY(!doc.isEmpty());
2733 }
2734 
2735 QTEST_MAIN(tst_QtJson)
2736 #include "tst_qtjson.moc"
2737