summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/serialization/json
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/serialization/json')
-rw-r--r--tests/auto/corelib/serialization/json/CMakeLists.txt36
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/10.bjsonbin544 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/11.bjsonbin542 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/12.bjsonbin506 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/13.bjsonbin544 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/14.bjsonbin521 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/15.bjsonbin536 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/16.bjsonbin874 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/17.bjsonbin49 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/18.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/19.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/20.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/21.bjsonbin552 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/22.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/23.bjsonbin533 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/24.bjsonbin506 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/25.bjsonbin542 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/26.bjsonbin628 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/27.bjsonbin51 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/28.bjsonbin542 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/29.bjsonbin544 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/30.bjsonbin542 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/31.bjsonbin553 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/32.bjsonbin536 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/33.bjsonbin544 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/34.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/35.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/36.bjsonbin524 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/37.bjsonbin536 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/38.bjson0
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/39.bjsonbin24 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/40.bjsonbin60 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/invalidBinaryData/41.bjsonbin32 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/json.pro12
-rw-r--r--tests/auto/corelib/serialization/json/json.qrc9
-rw-r--r--tests/auto/corelib/serialization/json/simple.duplicates.json1
-rw-r--r--tests/auto/corelib/serialization/json/test.bjsonbin35392 -> 0 bytes
-rw-r--r--tests/auto/corelib/serialization/json/test.duplicates.json66
-rw-r--r--tests/auto/corelib/serialization/json/test3.duplicates.json15
-rw-r--r--tests/auto/corelib/serialization/json/tst_qtjson.cpp1768
40 files changed, 1493 insertions, 414 deletions
diff --git a/tests/auto/corelib/serialization/json/CMakeLists.txt b/tests/auto/corelib/serialization/json/CMakeLists.txt
new file mode 100644
index 0000000000..c73a99a3b8
--- /dev/null
+++ b/tests/auto/corelib/serialization/json/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tst_json Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_json LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+set(json_resource_files
+ "bom.json"
+ "test.json"
+ "test2.json"
+ "test3.json"
+ "simple.duplicates.json"
+ "test.duplicates.json"
+ "test3.duplicates.json"
+)
+
+qt_internal_add_test(tst_json
+ SOURCES
+ tst_qtjson.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::TestPrivate
+ TESTDATA ${json_resource_files}
+)
+
+qt_internal_extend_target(tst_json CONDITION NOT QT_FEATURE_doubleconversion AND NOT QT_FEATURE_system_doubleconversion
+ DEFINES
+ QT_NO_DOUBLECONVERSION
+)
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/10.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/10.bjson
deleted file mode 100644
index 12b29b7aa5..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/10.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/11.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/11.bjson
deleted file mode 100644
index cf2b612111..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/11.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/12.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/12.bjson
deleted file mode 100644
index 9c2403350e..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/12.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/13.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/13.bjson
deleted file mode 100644
index db6308b1fd..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/13.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/14.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/14.bjson
deleted file mode 100644
index 347da4572c..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/14.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/15.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/15.bjson
deleted file mode 100644
index c6c5558934..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/15.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/16.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/16.bjson
deleted file mode 100644
index ae8b57446d..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/16.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/17.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/17.bjson
deleted file mode 100644
index 32f0cc0e23..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/17.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/18.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/18.bjson
deleted file mode 100644
index 50c89169eb..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/18.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/19.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/19.bjson
deleted file mode 100644
index b922212f45..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/19.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/20.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/20.bjson
deleted file mode 100644
index c965a0d294..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/20.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/21.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/21.bjson
deleted file mode 100644
index 98165ee40c..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/21.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/22.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/22.bjson
deleted file mode 100644
index 151f773a81..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/22.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/23.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/23.bjson
deleted file mode 100644
index 6eb5269470..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/23.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/24.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/24.bjson
deleted file mode 100644
index c55a2a3e3b..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/24.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/25.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/25.bjson
deleted file mode 100644
index 6c619f2ae1..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/25.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/26.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/26.bjson
deleted file mode 100644
index 3bf303215a..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/26.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/27.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/27.bjson
deleted file mode 100644
index d2656c2287..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/27.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/28.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/28.bjson
deleted file mode 100644
index 6797cf8c40..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/28.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/29.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/29.bjson
deleted file mode 100644
index 0645dfc3b2..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/29.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/30.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/30.bjson
deleted file mode 100644
index f77fe1efd0..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/30.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/31.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/31.bjson
deleted file mode 100644
index d9840b6582..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/31.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/32.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/32.bjson
deleted file mode 100644
index 1de4cb829f..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/32.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/33.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/33.bjson
deleted file mode 100644
index 532a31dc08..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/33.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/34.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/34.bjson
deleted file mode 100644
index f498558eff..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/34.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/35.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/35.bjson
deleted file mode 100644
index 8701210755..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/35.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/36.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/36.bjson
deleted file mode 100644
index ef5864e911..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/36.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/37.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/37.bjson
deleted file mode 100644
index f4dd4ae12f..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/37.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/38.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/38.bjson
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/38.bjson
+++ /dev/null
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/39.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/39.bjson
deleted file mode 100644
index c6025aa9eb..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/39.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/40.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/40.bjson
deleted file mode 100644
index 277096f8cb..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/40.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/invalidBinaryData/41.bjson b/tests/auto/corelib/serialization/json/invalidBinaryData/41.bjson
deleted file mode 100644
index 0b5940ab95..0000000000
--- a/tests/auto/corelib/serialization/json/invalidBinaryData/41.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/json.pro b/tests/auto/corelib/serialization/json/json.pro
deleted file mode 100644
index 8fa17c5c38..0000000000
--- a/tests/auto/corelib/serialization/json/json.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-TARGET = tst_json
-QT = core-private testlib
-CONFIG += testcase
-
-!android:TESTDATA += bom.json test.json test.bjson test3.json test2.json
- else:RESOURCES += json.qrc
-
-!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) {
- DEFINES += QT_NO_DOUBLECONVERSION
-}
-
-SOURCES += tst_qtjson.cpp
diff --git a/tests/auto/corelib/serialization/json/json.qrc b/tests/auto/corelib/serialization/json/json.qrc
deleted file mode 100644
index eb122a1779..0000000000
--- a/tests/auto/corelib/serialization/json/json.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource prefix="/">
- <file>bom.json</file>
- <file>test2.json</file>
- <file>test3.json</file>
- <file>test.json</file>
- <file>test.bjson</file>
-</qresource>
-</RCC>
diff --git a/tests/auto/corelib/serialization/json/simple.duplicates.json b/tests/auto/corelib/serialization/json/simple.duplicates.json
new file mode 100644
index 0000000000..6f989e8aa9
--- /dev/null
+++ b/tests/auto/corelib/serialization/json/simple.duplicates.json
@@ -0,0 +1 @@
+{"":{"":0},"":0}
diff --git a/tests/auto/corelib/serialization/json/test.bjson b/tests/auto/corelib/serialization/json/test.bjson
deleted file mode 100644
index 137b4dfeff..0000000000
--- a/tests/auto/corelib/serialization/json/test.bjson
+++ /dev/null
Binary files differ
diff --git a/tests/auto/corelib/serialization/json/test.duplicates.json b/tests/auto/corelib/serialization/json/test.duplicates.json
new file mode 100644
index 0000000000..0d5af8ef74
--- /dev/null
+++ b/tests/auto/corelib/serialization/json/test.duplicates.json
@@ -0,0 +1,66 @@
+[
+ "JSON Test Pattern pass1",
+ {"a":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "a": 1234567890,
+ "a": -9876.543210,
+ "a": 0.123456789e-12,
+ "a": 1.234567890E+34,
+ "a": 23456789012E66,
+ "a": 0,
+ "a": 1,
+ "a": " ",
+ "a": "\"",
+ "a": "\\",
+ "a": "\b\f\n\r\t",
+ "a": "/ & \/",
+ "a": "abcdefghijklmnopqrstuvwxyz",
+ "a": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "a": "0123456789",
+ "a": "digit",
+ "a": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "a": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "a": true,
+ "a": false,
+ "a": null,
+ "a":[ ],
+ "a":{ },
+ "a": "50 St. James Street",
+ "a": "nix",
+ "a": "// /* <!-- --",
+ "a": " ",
+ "a":[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"a":[1,2,3,4,5,6,7],
+ "a": "\"a:[\"array with 1 element\"]}",
+ "a": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "a": "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,
+2e+00,
+2e-00,
+"rosebud",
+{"a": "bar"},
+{"a":{"a":1000,"a":{"a":"nix"}},"a":{"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$4,833.99","a":483399}},"a":[{"a":"PRODUCT","a":"Silicone c","a":"Elite Hori","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":310711221747712.000000,"a":{"a":{"a":"$1.56","a":156},"a":{"a":"$29.99","a":2999},"a":14},"a":1968262863,"a":8515},{"a":"PRODUCT","a":"Nonslip Ch","a":"Specificat","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":175580930637824.000000,"a":{"a":{"a":"$0.45","a":45},"a":{"a":"$194.95","a":19495},"a":34},"a":2534935499,"a":8515},{"a":"PRODUCT","a":"Plastic Ca","a":"Descriptio","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":132488642953216.000000,"a":{"a":{"a":"$0.99","a":99},"a":{"a":"$303.68","a":30368},"a":33},"a":2305624670,"a":8515},{"a":"PRODUCT","a":"Protective","a":"Made of hi","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":108614681362432.000000,"a":{"a":{"a":"$1.70","a":170},"a":{"a":"$99.99","a":9999},"a":11},"a":2120981405,"a":8515},{"a":"PRODUCT","a":"P® 4","a":"Do more th","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":96203484168192.000000,"a":{"a":{"a":"$2.49","a":249},"a":{"a":"$79.95","a":7995},"a":16},"a":2203798762,"a":8515},{"a":"PRODUCT","a":"Case Refle","a":"NCAA iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":84727583211520.000000,"a":{"a":{"a":"$0.69","a":69},"a":{"a":"$75.52","a":7552},"a":59},"a":1114627445,"a":8515},{"a":"PRODUCT","a":"Infuse Pro","a":"Protect an","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":80831066406912.000000,"a":{"a":{"a":"$0.59","a":59},"a":{"a":"$79.00","a":7900},"a":24},"a":2557462717,"a":8515},{"a":"PRODUCT","a":"Dragonfly ","a":"d","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":70900229603328.000000,"a":{"a":{"a":"$1.05","a":105},"a":{"a":"$94.49","a":9449},"a":30},"a":2442061740,"a":8515},{"a":"PRODUCT","a":"Pho","a":"Snap on Ap","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":65194915004416.000000,"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$414.99","a":41499},"a":39},"a":2004746863,"a":8515},{"a":"PRODUCT","a":"Otterbox i","a":"Your iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":61515478597632.000000,"a":{"a":{"a":"$3.28","a":328},"a":{"a":"$110.65","a":11065},"a":25},"a":2584611575,"a":8515}],"a":10,"a":2000}},
+{"a":{"a":1000,"a":{"a":"nix"}},"a":{"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$4,833.99","a":483399}},"a":[{"a":"PRODUCT","a":"Silicone c","a":"Elite Hori","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":310711221747712.000000,"a":{"a":{"a":"$1.56","a":156},"a":{"a":"$29.99","a":2999},"a":14},"a":1968262863,"a":8515},{"a":"PRODUCT","a":"Nonslip Ch","a":"Specificat","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":175580930637824.000000,"a":{"a":{"a":"$0.45","a":45},"a":{"a":"$194.95","a":19495},"a":34},"a":2534935499,"a":8515},{"a":"PRODUCT","a":"Plastic Ca","a":"Descriptio","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":132488642953216.000000,"a":{"a":{"a":"$0.99","a":99},"a":{"a":"$303.68","a":30368},"a":33},"a":2305624670,"a":8515},{"a":"PRODUCT","a":"Protective","a":"Made of hi","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":108614681362432.000000,"a":{"a":{"a":"$1.70","a":170},"a":{"a":"$99.99","a":9999},"a":11},"a":2120981405,"a":8515},{"a":"PRODUCT","a":"P® 4","a":"Do more th","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":96203484168192.000000,"a":{"a":{"a":"$2.49","a":249},"a":{"a":"$79.95","a":7995},"a":16},"a":2203798762,"a":8515},{"a":"PRODUCT","a":"Case Refle","a":"NCAA iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":84727583211520.000000,"a":{"a":{"a":"$0.69","a":69},"a":{"a":"$75.52","a":7552},"a":59},"a":1114627445,"a":8515},{"a":"PRODUCT","a":"Infuse Pro","a":"Protect an","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":80831066406912.000000,"a":{"a":{"a":"$0.59","a":59},"a":{"a":"$79.00","a":7900},"a":24},"a":2557462717,"a":8515},{"a":"PRODUCT","a":"Dragonfly ","a":"d","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":70900229603328.000000,"a":{"a":{"a":"$1.05","a":105},"a":{"a":"$94.49","a":9449},"a":30},"a":2442061740,"a":8515},{"a":"PRODUCT","a":"Pho","a":"Snap on Ap","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":65194915004416.000000,"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$414.99","a":41499},"a":39},"a":2004746863,"a":8515},{"a":"PRODUCT","a":"Otterbox i","a":"Your iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":61515478597632.000000,"a":{"a":{"a":"$3.28","a":328},"a":{"a":"$110.65","a":11065},"a":25},"a":2584611575,"a":8515}],"a":10,"a":2000}},
+{"a":{"a":1000,"a":{"a":"nix"}},"a":{"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$4,833.99","a":483399}},"a":[{"a":"PRODUCT","a":"Silicone c","a":"Elite Hori","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":310711221747712.000000,"a":{"a":{"a":"$1.56","a":156},"a":{"a":"$29.99","a":2999},"a":14},"a":1968262863,"a":8515},{"a":"PRODUCT","a":"Nonslip Ch","a":"Specificat","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":175580930637824.000000,"a":{"a":{"a":"$0.45","a":45},"a":{"a":"$194.95","a":19495},"a":34},"a":2534935499,"a":8515},{"a":"PRODUCT","a":"Plastic Ca","a":"Descriptio","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":132488642953216.000000,"a":{"a":{"a":"$0.99","a":99},"a":{"a":"$303.68","a":30368},"a":33},"a":2305624670,"a":8515},{"a":"PRODUCT","a":"Protective","a":"Made of hi","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":108614681362432.000000,"a":{"a":{"a":"$1.70","a":170},"a":{"a":"$99.99","a":9999},"a":11},"a":2120981405,"a":8515},{"a":"PRODUCT","a":"P® 4","a":"Do more th","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":96203484168192.000000,"a":{"a":{"a":"$2.49","a":249},"a":{"a":"$79.95","a":7995},"a":16},"a":2203798762,"a":8515},{"a":"PRODUCT","a":"Case Refle","a":"NCAA iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":84727583211520.000000,"a":{"a":{"a":"$0.69","a":69},"a":{"a":"$75.52","a":7552},"a":59},"a":1114627445,"a":8515},{"a":"PRODUCT","a":"Infuse Pro","a":"Protect an","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":80831066406912.000000,"a":{"a":{"a":"$0.59","a":59},"a":{"a":"$79.00","a":7900},"a":24},"a":2557462717,"a":8515},{"a":"PRODUCT","a":"Dragonfly ","a":"d","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":70900229603328.000000,"a":{"a":{"a":"$1.05","a":105},"a":{"a":"$94.49","a":9449},"a":30},"a":2442061740,"a":8515},{"a":"PRODUCT","a":"Pho","a":"Snap on Ap","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":65194915004416.000000,"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$414.99","a":41499},"a":39},"a":2004746863,"a":8515},{"a":"PRODUCT","a":"Otterbox i","a":"Your iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":61515478597632.000000,"a":{"a":{"a":"$3.28","a":328},"a":{"a":"$110.65","a":11065},"a":25},"a":2584611575,"a":8515}],"a":10,"a":2000}},
+{"a":{"a":1000,"a":{"a":"nix"}},"a":{"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$4,833.99","a":483399}},"a":[{"a":"PRODUCT","a":"Silicone c","a":"Elite Hori","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":310711221747712.000000,"a":{"a":{"a":"$1.56","a":156},"a":{"a":"$29.99","a":2999},"a":14},"a":1968262863,"a":8515},{"a":"PRODUCT","a":"Nonslip Ch","a":"Specificat","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":175580930637824.000000,"a":{"a":{"a":"$0.45","a":45},"a":{"a":"$194.95","a":19495},"a":34},"a":2534935499,"a":8515},{"a":"PRODUCT","a":"Plastic Ca","a":"Descriptio","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":132488642953216.000000,"a":{"a":{"a":"$0.99","a":99},"a":{"a":"$303.68","a":30368},"a":33},"a":2305624670,"a":8515},{"a":"PRODUCT","a":"Protective","a":"Made of hi","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":108614681362432.000000,"a":{"a":{"a":"$1.70","a":170},"a":{"a":"$99.99","a":9999},"a":11},"a":2120981405,"a":8515},{"a":"PRODUCT","a":"P® 4","a":"Do more th","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":96203484168192.000000,"a":{"a":{"a":"$2.49","a":249},"a":{"a":"$79.95","a":7995},"a":16},"a":2203798762,"a":8515},{"a":"PRODUCT","a":"Case Refle","a":"NCAA iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":84727583211520.000000,"a":{"a":{"a":"$0.69","a":69},"a":{"a":"$75.52","a":7552},"a":59},"a":1114627445,"a":8515},{"a":"PRODUCT","a":"Infuse Pro","a":"Protect an","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":80831066406912.000000,"a":{"a":{"a":"$0.59","a":59},"a":{"a":"$79.00","a":7900},"a":24},"a":2557462717,"a":8515},{"a":"PRODUCT","a":"Dragonfly ","a":"d","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":70900229603328.000000,"a":{"a":{"a":"$1.05","a":105},"a":{"a":"$94.49","a":9449},"a":30},"a":2442061740,"a":8515},{"a":"PRODUCT","a":"Pho","a":"Snap on Ap","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":65194915004416.000000,"a":{"a":{"a":"$0.01","a":1},"a":{"a":"$414.99","a":41499},"a":39},"a":2004746863,"a":8515},{"a":"PRODUCT","a":"Otterbox i","a":"Your iPhon","a":"someone","a":{"a":"nix"},"a":{"a":[{"a":"nix","a":60,"a":60},{"a":"nix","a":100,"a":100},{"a":"nix","a":160,"a":160},{"a":"nix","a":400,"a":400}]},"a":61515478597632.000000,"a":{"a":{"a":"$3.28","a":328},"a":{"a":"$110.65","a":11065},"a":25},"a":2584611575,"a":8515}],"a":10,"a":2000}}
+]
+
diff --git a/tests/auto/corelib/serialization/json/test3.duplicates.json b/tests/auto/corelib/serialization/json/test3.duplicates.json
new file mode 100644
index 0000000000..c635a2523f
--- /dev/null
+++ b/tests/auto/corelib/serialization/json/test3.duplicates.json
@@ -0,0 +1,15 @@
+{
+ "a": "John",
+ "a": "Smith",
+ "a": 25,
+ "a": {
+ "a": "21 2nd Street",
+ "a": "New York",
+ "a": "NY",
+ "a": "10021"
+ },
+ "a": [
+ { "a": "home", "a": "212 555-1234" },
+ { "a": "fax", "a": "646 555-4567" }
+ ]
+}
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 4651258ef3..54ef9be4f2 100644
--- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -1,38 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest>
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
+#include <QMap>
+#include <QVariantList>
+
+QT_WARNING_DISABLE_DEPRECATED
#include "qjsonarray.h"
#include "qjsonobject.h"
#include "qjsonvalue.h"
#include "qjsondocument.h"
#include "qregularexpression.h"
+#include "private/qnumeric_p.h"
#include <limits>
#define INVALID_UNICODE "\xCE\xBA\xE1"
@@ -46,24 +28,33 @@ class tst_QtJson: public QObject
private Q_SLOTS:
void initTestCase();
+ void compareCompiles();
void testValueSimple();
void testNumbers();
void testNumbers_2();
void testNumbers_3();
void testNumbers_4();
+ void testNumberComparisons();
+
void testObjectSimple();
+ void testObjectTakeDetach();
void testObjectSmallKeys();
+ void testObjectInsertCopies();
void testArraySimple();
+ void testArrayInsertCopies();
void testValueObject();
void testValueArray();
void testObjectNested();
void testArrayNested();
void testArrayNestedEmpty();
void testArrayComfortOperators();
+ void testArrayEquality_data();
+ void testArrayEquality();
void testObjectNestedEmpty();
void testValueRef();
+ void testValueRefComparison();
void testObjectIteration();
void testArrayIteration();
@@ -76,6 +67,7 @@ private Q_SLOTS:
void nullObject();
void constNullObject();
+ void keySorting_data();
void keySorting();
void undefinedValues();
@@ -95,30 +87,24 @@ private Q_SLOTS:
void toJson();
void toJsonSillyNumericValues();
void toJsonLargeNumericValues();
+ void toJsonDenormalValues();
void fromJson();
void fromJsonErrors();
- void fromBinary();
- void toAndFromBinary_data();
- void toAndFromBinary();
- void invalidBinaryData();
void parseNumbers();
void parseStrings();
void parseDuplicateKeys();
void testParser();
- void compactArray();
- void compactObject();
-
- void validation();
-
void assignToDocument();
void testDuplicateKeys();
void testCompaction();
void testDebugStream();
- void testCompactionError();
- void parseUnicodeEscapes();
+ void parseEscapes_data();
+ void parseEscapes();
+ void makeEscapes_data();
+ void makeEscapes();
void assignObjects();
void assignArrays();
@@ -132,6 +118,8 @@ private Q_SLOTS:
void objectEquals();
void arrayEquals_data();
void arrayEquals();
+ void documentEquals_data();
+ void documentEquals();
void bom();
void nesting();
@@ -153,6 +141,27 @@ private Q_SLOTS:
void implicitValueType();
void implicitDocumentType();
+ void streamSerializationQJsonDocument_data();
+ void streamSerializationQJsonDocument();
+ void streamSerializationQJsonArray_data();
+ void streamSerializationQJsonArray();
+ void streamSerializationQJsonObject_data();
+ void streamSerializationQJsonObject();
+ void streamSerializationQJsonValue_data();
+ void streamSerializationQJsonValue();
+ void streamSerializationQJsonValueEmpty();
+ void streamVariantSerialization();
+ void escapeSurrogateCodePoints_data();
+ void escapeSurrogateCodePoints();
+
+ void fromToVariantConversions_data();
+ void fromToVariantConversions();
+
+ void testIteratorComparison();
+
+ void noLeakOnNameClash_data();
+ void noLeakOnNameClash();
+
private:
QString testDataDir;
};
@@ -164,6 +173,31 @@ void tst_QtJson::initTestCase()
testDataDir = QCoreApplication::applicationDirPath();
}
+void tst_QtJson::compareCompiles()
+{
+ QTestPrivate::testEqualityOperatorsCompile<QJsonArray>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QJsonArray::iterator>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QJsonArray::const_iterator>();
+ QTestPrivate::testAllComparisonOperatorsCompile<QJsonArray::iterator,
+ QJsonArray::const_iterator>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonDocument>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::iterator>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::const_iterator>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValueConstRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonArray, QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValueConstRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject, QJsonValueRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValueConstRef, QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef, QJsonValue>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonValueRef, QJsonValueConstRef>();
+ QTestPrivate::testEqualityOperatorsCompile<QJsonObject::iterator,
+ QJsonObject::const_iterator>();
+}
+
void tst_QtJson::testValueSimple()
{
QJsonObject object;
@@ -206,26 +240,32 @@ void tst_QtJson::testNumbers()
{
int numbers[] = {
0,
- -1,
1,
+ 2,
+ -1,
+ -2,
+ (1<<25),
(1<<26),
(1<<27),
(1<<28),
+ -(1<<25),
-(1<<26),
-(1<<27),
-(1<<28),
(1<<26) - 1,
(1<<27) - 1,
(1<<28) - 1,
+ (1<<29) - 1,
-((1<<26) - 1),
-((1<<27) - 1),
- -((1<<28) - 1)
+ -((1<<28) - 1),
+ -((1<<29) - 1)
};
int n = sizeof(numbers)/sizeof(int);
QJsonArray array;
for (int i = 0; i < n; ++i)
- array.append((double)numbers[i]);
+ array.append(numbers[i]);
QByteArray serialized = QJsonDocument(array).toJson();
QJsonDocument json = QJsonDocument::fromJson(serialized);
@@ -234,8 +274,10 @@ void tst_QtJson::testNumbers()
QCOMPARE(array.size(), array2.size());
for (int i = 0; i < array.size(); ++i) {
QCOMPARE(array.at(i).type(), QJsonValue::Double);
+ QCOMPARE(array.at(i).toInt(), numbers[i]);
QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
QCOMPARE(array2.at(i).type(), QJsonValue::Double);
+ QCOMPARE(array2.at(i).toInt(), numbers[i]);
QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
}
}
@@ -243,8 +285,10 @@ void tst_QtJson::testNumbers()
{
qint64 numbers[] = {
0,
- -1,
1,
+ 2,
+ -1,
+ -2,
(1ll<<54),
(1ll<<55),
(1ll<<56),
@@ -254,15 +298,21 @@ void tst_QtJson::testNumbers()
(1ll<<54) - 1,
(1ll<<55) - 1,
(1ll<<56) - 1,
+ (1ll<<57) - 1,
+ (1ll<<58) - 1,
+ (1ll<<59) + 1001,
-((1ll<<54) - 1),
-((1ll<<55) - 1),
- -((1ll<<56) - 1)
+ -((1ll<<56) - 1),
+ -((1ll<<57) - 1),
+ -((1ll<<58) - 1),
+ -((1ll<<59) + 1001),
};
int n = sizeof(numbers)/sizeof(qint64);
QJsonArray array;
for (int i = 0; i < n; ++i)
- array.append((double)numbers[i]);
+ array.append(QJsonValue(numbers[i]));
QByteArray serialized = QJsonDocument(array).toJson();
QJsonDocument json = QJsonDocument::fromJson(serialized);
@@ -271,8 +321,10 @@ void tst_QtJson::testNumbers()
QCOMPARE(array.size(), array2.size());
for (int i = 0; i < array.size(); ++i) {
QCOMPARE(array.at(i).type(), QJsonValue::Double);
+ QCOMPARE(array.at(i).toInteger(), numbers[i]);
QCOMPARE(array.at(i).toDouble(), (double)numbers[i]);
QCOMPARE(array2.at(i).type(), QJsonValue::Double);
+ QCOMPARE(array2.at(i).toInteger(), numbers[i]);
QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]);
}
}
@@ -345,24 +397,24 @@ void tst_QtJson::testNumbers_2()
QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
for (int power = 0; power <= 1075; power++) {
floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble();
-#ifdef Q_OS_QNX
- if (power >= 970)
- QEXPECT_FAIL("", "See QTBUG-37066", Abort);
-#endif
QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1());
}
+ QT_TEST_EQUALITY_OPS(jDocument1, jDocument2, true);
// The last value is below min denorm and should round to 0, everything else should contain a value
QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0");
// Validate the last actual value is min denorm
QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1());
- // Validate that every value is half the value before it up to 1
- for (int index = 1074; index > 0; index--) {
- QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1());
-
- QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1());
+ if constexpr (std::numeric_limits<double>::has_denorm == std::denorm_present) {
+ // Validate that every value is half the value before it up to 1
+ for (int index = 1074; index > 0; index--) {
+ QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1());
+ QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1());
+ }
+ } else {
+ qInfo("Skipping denormal test as this system's double type lacks support");
}
}
@@ -380,6 +432,10 @@ void tst_QtJson::testNumbers_3()
QJsonDocument jDocument2(QJsonDocument::fromJson(ba));
+ QT_TEST_EQUALITY_OPS(jDocument1, jDocument2, true);
+ QT_TEST_EQUALITY_OPS(jDocument1, QJsonDocument(), false);
+ QT_TEST_EQUALITY_OPS(QJsonDocument(), QJsonDocument(), true);
+
double d1_1(jDocument2.object().value("d1").toDouble());
double d2_1(jDocument2.object().value("d2").toDouble());
QVERIFY(d1_1 != d2_1);
@@ -397,7 +453,8 @@ void tst_QtJson::testNumbers_4()
array << QJsonValue(-9223372036854775808.0);
array << QJsonValue(+18446744073709551616.0);
array << QJsonValue(-18446744073709551616.0);
- const QByteArray json(QJsonDocument(array).toJson());
+ QJsonDocument doc1 = QJsonDocument(array);
+ const QByteArray json(doc1.toJson());
const QByteArray expected =
"[\n"
" 1000000000000000,\n"
@@ -410,6 +467,49 @@ void tst_QtJson::testNumbers_4()
" -18446744073709552000\n"
"]\n";
QCOMPARE(json, expected);
+
+ QJsonArray array2;
+ array2 << QJsonValue(Q_INT64_C(+1000000000000000));
+ array2 << QJsonValue(Q_INT64_C(-1000000000000000));
+ array2 << QJsonValue(Q_INT64_C(+9007199254740992));
+ array2 << QJsonValue(Q_INT64_C(-9007199254740992));
+ array2 << QJsonValue(Q_INT64_C(+9223372036854775807));
+ array2 << QJsonValue(Q_INT64_C(-9223372036854775807));
+ QJsonDocument doc2 = QJsonDocument(array2);
+ const QByteArray json2(doc2.toJson());
+ const QByteArray expected2 =
+ "[\n"
+ " 1000000000000000,\n"
+ " -1000000000000000,\n"
+ " 9007199254740992,\n"
+ " -9007199254740992,\n"
+ " 9223372036854775807,\n"
+ " -9223372036854775807\n"
+ "]\n";
+ QCOMPARE(json2, expected2);
+
+ QT_TEST_EQUALITY_OPS(doc1, doc2, false);
+}
+
+void tst_QtJson::testNumberComparisons()
+{
+ // QJsonValues created using doubles only have double precision
+ QJsonValue llMinDbl(-9223372036854775807.0);
+ QJsonValue llMinPlus1Dbl(-9223372036854775806.0);
+ QCOMPARE(llMinDbl == llMinPlus1Dbl, -9223372036854775807.0 == -9223372036854775806.0); // true
+
+ // QJsonValues created using qint64 have full qint64 precision
+ QJsonValue llMin(Q_INT64_C(-9223372036854775807));
+ QJsonValue llMinPlus1(Q_INT64_C(-9223372036854775806));
+ QCOMPARE(llMin == llMinPlus1, Q_INT64_C(-9223372036854775807) == Q_INT64_C(-9223372036854775806)); // false
+
+ // The different storage formats should be able to compare as their C++ versions (all true)
+ QCOMPARE(llMin == llMinDbl, Q_INT64_C(-9223372036854775807) == -9223372036854775807.0);
+ QCOMPARE(llMinDbl == llMin, -9223372036854775807.0 == Q_INT64_C(-9223372036854775807));
+ QCOMPARE(llMinPlus1 == llMinPlus1Dbl, Q_INT64_C(-9223372036854775806) == -9223372036854775806.0);
+ QCOMPARE(llMinPlus1Dbl == llMinPlus1, -9223372036854775806.0 == Q_INT64_C(-9223372036854775806));
+ QCOMPARE(llMinPlus1 == llMinDbl, Q_INT64_C(-9223372036854775806) == -9223372036854775807.0);
+ QCOMPARE(llMinPlus1Dbl == llMin, -9223372036854775806.0 == Q_INT64_C(-9223372036854775807));
}
void tst_QtJson::testObjectSimple()
@@ -424,6 +524,8 @@ void tst_QtJson::testObjectSimple()
object.insert("boolean", true);
QCOMPARE(object.value("boolean").toBool(), true);
QCOMPARE(object.value(QLatin1String("boolean")).toBool(), true);
+ QJsonObject object2 = object;
+ QJsonObject object3 = object;
QStringList keys = object.keys();
QVERIFY2(keys.contains("number"), "key number not found");
@@ -435,6 +537,7 @@ void tst_QtJson::testObjectSimple()
QJsonValue value(QLatin1String("foo"));
object.insert("value", value);
QCOMPARE(object.value("value"), value);
+ QT_TEST_EQUALITY_OPS(object.value("value"), value, true);
int size = object.size();
object.remove("boolean");
@@ -443,12 +546,47 @@ void tst_QtJson::testObjectSimple()
QJsonValue taken = object.take("value");
QCOMPARE(taken, value);
+ QT_TEST_EQUALITY_OPS(taken, value, true);
QVERIFY2(!object.contains("value"), "key value should have been removed");
QString before = object.value("string").toString();
object.insert("string", QString::fromLatin1("foo"));
QVERIFY2(object.value(QLatin1String("string")).toString() != before, "value should have been updated");
+ // same tests again but with QStringView keys
+ object2.insert(QStringView(u"value"), value);
+ QCOMPARE(object2.value("value"), value);
+
+ size = object2.size();
+ object2.remove(QStringView(u"boolean"));
+ QCOMPARE(object2.size(), size - 1);
+ QVERIFY2(!object2.contains(QStringView(u"boolean")), "key boolean should have been removed");
+
+ taken = object2.take(QStringView(u"value"));
+ QCOMPARE(taken, value);
+ QVERIFY2(!object2.contains("value"), "key value should have been removed");
+
+ before = object2.value("string").toString();
+ object2.insert(QStringView(u"string"), QString::fromLatin1("foo"));
+ QVERIFY2(object2.value(QStringView(u"string")).toString() != before, "value should have been updated");
+
+ // same tests again but with QLatin1String keys
+ object3.insert(QLatin1String("value"), value);
+ QCOMPARE(object3.value("value"), value);
+
+ size = object3.size();
+ object3.remove(QLatin1String("boolean"));
+ QCOMPARE(object3.size(), size - 1);
+ QVERIFY2(!object3.contains("boolean"), "key boolean should have been removed");
+
+ taken = object3.take(QLatin1String("value"));
+ QCOMPARE(taken, value);
+ QVERIFY2(!object3.contains("value"), "key value should have been removed");
+
+ before = object3.value("string").toString();
+ object3.insert(QLatin1String("string"), QString::fromLatin1("foo"));
+ QVERIFY2(object3.value(QLatin1String("string")).toString() != before, "value should have been updated");
+
size = object.size();
QJsonObject subobject;
subobject.insert("number", 42);
@@ -465,6 +603,24 @@ void tst_QtJson::testObjectSimple()
QCOMPARE(subvalue.toObject(), subobject);
}
+void tst_QtJson::testObjectTakeDetach()
+{
+ QJsonObject object1, object2;
+ object1["key1"] = 1;
+ object1["key2"] = 2;
+ object2 = object1;
+
+ object1.take("key2");
+ object1.remove("key1");
+ QVERIFY(!object1.contains("key1"));
+ QVERIFY(object2.contains("key1"));
+ QVERIFY(object2.value("key1").isDouble());
+
+ QVERIFY(!object1.contains("key2"));
+ QVERIFY(object2.contains("key2"));
+ QVERIFY(object2.value("key2").isDouble());
+}
+
void tst_QtJson::testObjectSmallKeys()
{
QJsonObject data1;
@@ -479,6 +635,78 @@ void tst_QtJson::testObjectSmallKeys()
QVERIFY(data1.contains(QStringLiteral("123")));
QCOMPARE(data1.value(QStringLiteral("123")).type(), QJsonValue::Double);
QCOMPARE(data1.value(QStringLiteral("123")).toDouble(), (double)323);
+ QCOMPARE(data1.constEnd() - data1.constBegin(), 3);
+ QCOMPARE(data1.end() - data1.begin(), 3);
+}
+
+void tst_QtJson::testObjectInsertCopies()
+{
+ {
+ QJsonObject obj;
+ obj["prop1"] = "TEST";
+ QCOMPARE(obj.size(), 1);
+ QCOMPARE(obj.value("prop1"), "TEST");
+
+ obj["prop2"] = obj.value("prop1");
+ QCOMPARE(obj.size(), 2);
+ QCOMPARE(obj.value("prop1"), "TEST");
+ QCOMPARE(obj.value("prop2"), "TEST");
+ }
+ {
+ // see QTBUG-83366
+ QJsonObject obj;
+ obj["value"] = "TEST";
+ QCOMPARE(obj.size(), 1);
+ QCOMPARE(obj.value("value"), "TEST");
+
+ obj["prop2"] = obj.value("value");
+ QCOMPARE(obj.size(), 2);
+ QCOMPARE(obj.value("value"), "TEST");
+ QCOMPARE(obj.value("prop2"), "TEST");
+ }
+ {
+ QJsonObject obj;
+ obj["value"] = "TEST";
+ QCOMPARE(obj.size(), 1);
+ QCOMPARE(obj.value("value"), "TEST");
+
+ // same as previous, but this is a QJsonValueRef
+ QJsonValueRef rv = obj["prop2"];
+ rv = obj["value"];
+ QCOMPARE(obj.size(), 2);
+ QCOMPARE(obj.value("value"), "TEST");
+ QCOMPARE(obj.value("prop2"), "TEST");
+ QT_TEST_EQUALITY_OPS(rv, obj["value"].toObject(), true);
+ }
+ {
+ QJsonObject obj;
+ obj["value"] = "TEST";
+ QCOMPARE(obj.size(), 1);
+ QCOMPARE(obj.value("value"), "TEST");
+
+ // same as previous, but this is a QJsonValueRef
+ QJsonValueRef rv = obj["value"];
+ obj["prop2"] = rv;
+ QCOMPARE(obj.size(), 2);
+ QCOMPARE(obj.value("value"), "TEST");
+ QEXPECT_FAIL("", "QTBUG-83398: design flaw: the obj[] call invalidates the QJsonValueRef", Continue);
+ QCOMPARE(obj.value("prop2"), "TEST");
+ }
+ {
+ QJsonObject obj;
+ obj["value"] = "TEST";
+ QCOMPARE(obj.size(), 1);
+ QCOMPARE(obj.value("value"), "TEST");
+
+ QJsonValueRef v = obj["value"];
+ QJsonObject obj2 = obj;
+ obj.insert("prop2", v);
+ QCOMPARE(obj.size(), 2);
+ QCOMPARE(obj.value("value"), "TEST");
+ QCOMPARE(obj.value("prop2"), "TEST");
+ QCOMPARE(obj2.size(), 1);
+ QCOMPARE(obj2.value("value"), "TEST");
+ }
}
void tst_QtJson::testArraySimple()
@@ -534,6 +762,32 @@ void tst_QtJson::testArraySimple()
QCOMPARE(array.at(1), QJsonValue(QLatin1String("test")));
}
+void tst_QtJson::testArrayInsertCopies()
+{
+ {
+ QJsonArray array;
+ array.append("TEST");
+ QCOMPARE(array.size(), 1);
+ QCOMPARE(array.at(0), "TEST");
+
+ array.append(array.at(0));
+ QCOMPARE(array.size(), 2);
+ QCOMPARE(array.at(0), "TEST");
+ QCOMPARE(array.at(1), "TEST");
+ }
+ {
+ QJsonArray array;
+ array.append("TEST");
+ QCOMPARE(array.size(), 1);
+ QCOMPARE(array.at(0), "TEST");
+
+ array.prepend(array.at(0));
+ QCOMPARE(array.size(), 2);
+ QCOMPARE(array.at(0), "TEST");
+ QCOMPARE(array.at(1), "TEST");
+ }
+}
+
void tst_QtJson::testValueObject()
{
QJsonObject object;
@@ -555,15 +809,20 @@ void tst_QtJson::testValueObject()
void tst_QtJson::testValueArray()
{
QJsonArray array;
+ QJsonArray otherArray = {"wrong value"};
+ QJsonValue value(array);
+ QCOMPARE(value.toArray(), array);
+ QCOMPARE(value.toArray(otherArray), array);
+
array.append(999.);
array.append(QLatin1String("test"));
array.append(true);
-
- QJsonValue value(array);
+ value = array;
// if we don't modify the original JsonArray, toArray()
// on the JsonValue should return the same object (non-detached).
QCOMPARE(value.toArray(), array);
+ QCOMPARE(value.toArray(otherArray), array);
// if we modify the original array, it should detach
array.append(QLatin1String("test"));
@@ -573,14 +832,28 @@ void tst_QtJson::testValueArray()
void tst_QtJson::testObjectNested()
{
QJsonObject inner, outer;
+ QJsonObject otherObject = {{"wrong key", "wrong value"}};
+ QJsonValue v = inner;
+ QCOMPARE(v.toObject(), inner);
+ QCOMPARE(v.toObject(otherObject), inner);
+ QT_TEST_EQUALITY_OPS(v.toObject(), inner, true);
+ QT_TEST_EQUALITY_OPS(v.toObject(otherObject), inner, true);
+
inner.insert("number", 999.);
outer.insert("nested", inner);
+ QT_TEST_EQUALITY_OPS(outer, inner, false);
// if we don't modify the original JsonObject, value()
// should return the same object (non-detached).
QJsonObject value = outer.value("nested").toObject();
+ v = value;
QCOMPARE(value, inner);
QCOMPARE(value.value("number").toDouble(), 999.);
+ QCOMPARE(v.toObject(), inner);
+ QCOMPARE(v.toObject(otherObject), inner);
+ QT_TEST_EQUALITY_OPS(v.toObject(), inner, true);
+ QT_TEST_EQUALITY_OPS(v.toObject(otherObject), inner, true);
+ QCOMPARE(v["number"].toDouble(), 999.);
// if we modify the original object, it should detach and not
// affect the nested object
@@ -605,6 +878,7 @@ void tst_QtJson::testObjectNested()
QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep);
QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(),
true);
+ QT_TEST_EQUALITY_OPS(outer.value("nested").toObject().value("nested").toObject(), twoDeep, true);
}
void tst_QtJson::testArrayNested()
@@ -630,6 +904,7 @@ void tst_QtJson::testArrayNested()
object.insert("boolean", true);
outer.append(object);
QCOMPARE(outer.last().toObject(), object);
+ QT_TEST_EQUALITY_OPS(outer.last().toObject(), object, true);
QCOMPARE(outer.last().toObject().value("boolean").toBool(), true);
// two deep arrays
@@ -649,14 +924,13 @@ void tst_QtJson::testArrayNestedEmpty()
QJsonValue val = object.value("inner");
QJsonArray value = object.value("inner").toArray();
QVERIFY(QJsonDocument(value).isArray());
+ QT_TEST_EQUALITY_OPS(QJsonDocument(), QJsonDocument(value), false);
QCOMPARE(value.size(), 0);
QCOMPARE(value, inner);
QCOMPARE(value.size(), 0);
object.insert("count", 0.);
QCOMPARE(object.value("inner").toArray().size(), 0);
QVERIFY(object.value("inner").toArray().isEmpty());
- QJsonDocument(object).toBinaryData();
- QCOMPARE(object.value("inner").toArray().size(), 0);
}
void tst_QtJson::testObjectNestedEmpty()
@@ -668,21 +942,44 @@ void tst_QtJson::testObjectNestedEmpty()
object.insert("inner2", inner2);
QJsonObject value = object.value("inner").toObject();
QVERIFY(QJsonDocument(value).isObject());
+ QT_TEST_EQUALITY_OPS(QJsonDocument(), QJsonDocument(value), false);
QCOMPARE(value.size(), 0);
QCOMPARE(value, inner);
+ QT_TEST_EQUALITY_OPS(value, inner, true);
QCOMPARE(value.size(), 0);
object.insert("count", 0.);
QCOMPARE(object.value("inner").toObject().size(), 0);
QCOMPARE(object.value("inner").type(), QJsonValue::Object);
- QJsonDocument(object).toBinaryData();
- QVERIFY(object.value("inner").toObject().isEmpty());
- QVERIFY(object.value("inner2").toObject().isEmpty());
- QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(object).toBinaryData());
- QVERIFY(!doc.isNull());
- QJsonObject reconstituted(doc.object());
- QCOMPARE(reconstituted.value("inner").toObject().size(), 0);
- QCOMPARE(reconstituted.value("inner").type(), QJsonValue::Object);
- QCOMPARE(reconstituted.value("inner2").type(), QJsonValue::Object);
+}
+
+void tst_QtJson::testArrayEquality_data()
+{
+ QTest::addColumn<QJsonArray>("array1");
+ QTest::addColumn<QJsonArray>("array2");
+ QTest::addColumn<bool>("expectedResult");
+ QTest::addRow("QJsonArray(), QJsonArray{665, 666, 667}")
+ << QJsonArray() << QJsonArray{665, 666, 667} << false;
+ QTest::addRow("QJsonArray(), QJsonArray{}")
+ << QJsonArray() << QJsonArray{} <<true;
+ QTest::addRow("QJsonArray(), QJsonArray{123, QLatin1String(\"foo\")}")
+ << QJsonArray() << QJsonArray{123, QLatin1String("foo")} << false;
+ QTest::addRow(
+ "QJsonArray{123,QLatin1String(\"foo\")}, QJsonArray{123,QLatin1String(\"foo\")}")
+ << QJsonArray{123, QLatin1String("foo")}
+ << QJsonArray{123, QLatin1String("foo")}
+ << true;
+}
+
+void tst_QtJson::testArrayEquality()
+{
+ QFETCH(QJsonArray, array1);
+ QFETCH(QJsonArray, array2);
+ QFETCH(bool, expectedResult);
+
+ QJsonValue value = QJsonValue(array1);
+
+ QT_TEST_EQUALITY_OPS(array1, array2, expectedResult);
+ QT_TEST_EQUALITY_OPS(value, array2, expectedResult);
}
void tst_QtJson::testArrayComfortOperators()
@@ -724,7 +1021,7 @@ void tst_QtJson::testValueRef()
QCOMPARE(object.value(QLatin1String("null")), QJsonValue());
object[QLatin1String("null")] = 100.;
QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double);
- QJsonValue val = qAsConst(object)[QLatin1String("null")];
+ QJsonValue val = std::as_const(object)[QLatin1String("null")];
QCOMPARE(val.toDouble(), 100.);
QCOMPARE(object.size(), 2);
@@ -734,21 +1031,79 @@ void tst_QtJson::testValueRef()
QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42));
}
+void tst_QtJson::testValueRefComparison()
+{
+ QJsonValue a0 = 42.;
+ QJsonValue a1 = QStringLiteral("142");
+
+#define CHECK_IMPL(lhs, rhs, ineq) \
+ QCOMPARE(lhs, rhs); \
+ QVERIFY(!(lhs != rhs)); \
+ QVERIFY(lhs != ineq); \
+ QVERIFY(!(lhs == ineq)); \
+ QVERIFY(ineq != rhs); \
+ QVERIFY(!(ineq == rhs)); \
+ /* end */
+
+#define CHECK(lhs, rhs, ineq) \
+ do { \
+ CHECK_IMPL(lhs, rhs, ineq) \
+ CHECK_IMPL(std::as_const(lhs), rhs, ineq) \
+ CHECK_IMPL(lhs, std::as_const(rhs), ineq) \
+ CHECK_IMPL(std::as_const(lhs), std::as_const(rhs), ineq) \
+ } while (0)
+
+ // check that the (in)equality operators aren't ambiguous in C++20:
+ QJsonArray a = {a0, a1};
+
+ static_assert(std::is_same_v<decltype(a[0]), QJsonValueRef>);
+
+ auto r0 = a.begin()[0];
+ auto r1 = a.begin()[1];
+ auto c0 = std::as_const(a).begin()[0];
+ // ref <> ref
+ CHECK(r0, r0, r1);
+ // cref <> ref
+ CHECK(c0, r0, r1);
+ // ref <> cref
+ CHECK(r0, c0, r1);
+ // ref <> val
+ CHECK(r0, a0, r1);
+ // cref <> val
+ CHECK(c0, a0, r1);
+ // val <> ref
+ CHECK(a0, r0, a1);
+ // val <> cref
+ CHECK(a0, c0, a1);
+ // val <> val
+ CHECK(a0, a0, a1);
+
+ QT_TEST_EQUALITY_OPS(r0, r1, false);
+ QT_TEST_EQUALITY_OPS(r0, c0, true);
+ QT_TEST_EQUALITY_OPS(c0, r1, false);
+ QT_TEST_EQUALITY_OPS(a0, c0, true);
+ QT_TEST_EQUALITY_OPS(a0, r1, false);
+
+#undef CHECK
+#undef CHECK_IMPL
+}
+
void tst_QtJson::testObjectIteration()
{
QJsonObject object;
for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
- QVERIFY(false);
+ QFAIL("Iterator of default-initialized object should be empty");
const QString property = "kkk";
object.insert(property, 11);
object.take(property);
for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it)
- QVERIFY(false);
+ QFAIL("Iterator after property add-and-remove should be empty");
- for (int i = 0; i < 10; ++i)
- object[QString::number(i)] = (double)i;
+ // insert in weird order to confirm keys are sorted
+ for (int i : {0, 9, 5, 7, 8, 2, 1, 3, 6, 4})
+ object[QString::number(i)] = double(i);
QCOMPARE(object.size(), 10);
@@ -757,37 +1112,79 @@ void tst_QtJson::testObjectIteration()
for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) {
QJsonValue value = it.value();
QCOMPARE((double)it.key().toInt(), value.toDouble());
+ QT_TEST_EQUALITY_OPS(it, QJsonObject::iterator(), false);
}
{
QJsonObject object2 = object;
QCOMPARE(object, object2);
+ QT_TEST_EQUALITY_OPS(object, object2, true);
QJsonValue val = *object2.begin();
- object2.erase(object2.begin());
+ auto next = object2.erase(object2.begin());
QCOMPARE(object.size(), 10);
QCOMPARE(object2.size(), 9);
+ QVERIFY(next == object2.begin());
+ QT_TEST_EQUALITY_OPS(next, object2.begin(), true);
+
+ double d = 1; // we erased the first item
+ for (auto it = object2.constBegin(); it != object2.constEnd(); ++it, d += 1) {
+ QJsonValue value = it.value();
+ QVERIFY(it.value() != val);
+ QCOMPARE(it.value(), d);
+ QCOMPARE(it.value().toDouble(), d);
+ QCOMPARE(it.key().toInt(), value.toDouble());
+ }
+ }
+
+ {
+ QJsonObject object2 = object;
+ QCOMPARE(object, object2);
+ QT_TEST_EQUALITY_OPS(object, object2, true);
- for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) {
+ QJsonValue val = *(object2.end() - 1);
+ auto next = object2.erase(object2.end() - 1);
+ QCOMPARE(object.size(), 10);
+ QCOMPARE(object2.size(), 9);
+ QVERIFY(next == object2.end());
+ double d = 0;
+ for (auto it = object2.constBegin(); it != object2.constEnd(); ++it, d += 1) {
QJsonValue value = it.value();
QVERIFY(it.value() != val);
- QCOMPARE((double)it.key().toInt(), value.toDouble());
+ QCOMPARE(it.value(), d);
+ QCOMPARE(it.value().toDouble(), d);
+ QCOMPARE(it.key().toInt(), value.toDouble());
}
}
{
QJsonObject object2 = object;
QCOMPARE(object, object2);
+ QT_TEST_EQUALITY_OPS(object, object2, true);
QJsonObject::iterator it = object2.find(QString::number(5));
- object2.erase(it);
+ QJsonValue val = *it;
+ auto next = object2.erase(it);
QCOMPARE(object.size(), 10);
QCOMPARE(object2.size(), 9);
+ QCOMPARE(*next, 6);
+
+ int i = 0;
+ for (auto it = object2.constBegin(); it != object2.constEnd(); ++it, ++i) {
+ if (i == 5)
+ ++i;
+ QJsonValue value = it.value();
+ QVERIFY(it.value() != val);
+ QCOMPARE(it.value(), i);
+ QCOMPARE(it.value().toInt(), i);
+ QCOMPARE(it.key().toInt(), value.toDouble());
+ }
}
{
QJsonObject::Iterator it = object.begin();
it += 5;
+ QT_TEST_ALL_COMPARISON_OPS(it, object.begin(), Qt::strong_ordering::greater);
QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
it -= 3;
QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
@@ -802,10 +1199,14 @@ void tst_QtJson::testObjectIteration()
it += 5;
QCOMPARE(QJsonValue(it.value()).toDouble(), 5.);
it -= 3;
+ QT_TEST_ALL_COMPARISON_OPS(object.constBegin(), it, Qt::strong_ordering::less);
QCOMPARE(QJsonValue(it.value()).toDouble(), 2.);
QJsonObject::ConstIterator it2 = it + 5;
+ QT_TEST_EQUALITY_OPS(it, it2, false);
QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.);
it2 = it - 1;
+ QT_TEST_ALL_COMPARISON_OPS(it2, it, Qt::strong_ordering::less);
+ QT_TEST_ALL_COMPARISON_OPS(it2, it - 2, Qt::strong_ordering::greater);
QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.);
}
@@ -814,6 +1215,17 @@ void tst_QtJson::testObjectIteration()
it = object.erase(it);
QCOMPARE(object.size() , 0);
QCOMPARE(it, object.end());
+ QT_TEST_ALL_COMPARISON_OPS(it, object.end(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(it, object.constEnd(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(it, object.begin(),
+ Qt::strong_ordering::equal); // because object is empty
+ QT_TEST_ALL_COMPARISON_OPS(it, object.constBegin(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::Iterator(),
+ QJsonObject::Iterator(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::ConstIterator(),
+ QJsonObject::Iterator(), Qt::strong_ordering::equal);
+ QT_TEST_ALL_COMPARISON_OPS(QJsonObject::ConstIterator(),
+ QJsonObject::ConstIterator(), Qt::strong_ordering::equal);
}
void tst_QtJson::testArrayIteration()
@@ -827,7 +1239,11 @@ void tst_QtJson::testArrayIteration()
int i = 0;
for (QJsonArray::iterator it = array.begin(); it != array.end(); ++it, ++i) {
QJsonValue value = (*it);
+ QJsonArray::iterator it1 = it;
QCOMPARE((double)i, value.toDouble());
+ QT_TEST_EQUALITY_OPS(QJsonArray::iterator(), QJsonArray::iterator(), true);
+ QT_TEST_EQUALITY_OPS(QJsonArray::iterator(), it, false);
+ QT_TEST_EQUALITY_OPS(it1, it, true);
}
QCOMPARE(array.begin()->toDouble(), array.constBegin()->toDouble());
@@ -837,14 +1253,38 @@ void tst_QtJson::testArrayIteration()
QCOMPARE(array, array2);
QJsonValue val = *array2.begin();
- array2.erase(array2.begin());
+ auto next = array2.erase(array2.begin());
QCOMPARE(array.size(), 10);
QCOMPARE(array2.size(), 9);
+ QVERIFY(next == array2.begin());
i = 1;
- for (QJsonArray::const_iterator it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) {
+ for (auto it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) {
+ QJsonValue value = (*it);
+ QCOMPARE(value.toInt(), i);
+ QCOMPARE(value.toDouble(), i);
+ QCOMPARE(it->toInt(), i);
+ QCOMPARE(it->toDouble(), i);
+ }
+ }
+
+ {
+ QJsonArray array2 = array;
+ QCOMPARE(array, array2);
+
+ QJsonValue val = array2.last();
+ auto next = array2.erase(array2.end() - 1);
+ QCOMPARE(array.size(), 10);
+ QCOMPARE(array2.size(), 9);
+ QVERIFY(next == array2.end());
+
+ i = 0;
+ for (auto it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) {
QJsonValue value = (*it);
- QCOMPARE((double)i, value.toDouble());
+ QCOMPARE(value.toInt(), i);
+ QCOMPARE(value.toDouble(), i);
+ QCOMPARE(it->toInt(), i);
+ QCOMPARE(it->toDouble(), i);
}
}
@@ -858,6 +1298,13 @@ void tst_QtJson::testArrayIteration()
QCOMPARE(QJsonValue(*it2).toDouble(), 7.);
it2 = it - 1;
QCOMPARE(QJsonValue(*it2).toDouble(), 1.);
+ QT_TEST_EQUALITY_OPS(it, it2, false);
+ it = array.begin();
+ QT_TEST_EQUALITY_OPS(it, array.begin(), true);
+ it2 = it + 5;
+ QT_TEST_ALL_COMPARISON_OPS(it2, it, Qt::strong_ordering::greater);
+ it += 5;
+ QT_TEST_EQUALITY_OPS(it, it2, true);
}
{
@@ -877,6 +1324,26 @@ void tst_QtJson::testArrayIteration()
it = array.erase(it);
QCOMPARE(array.size() , 0);
QCOMPARE(it, array.end());
+ QT_TEST_EQUALITY_OPS(it, array.end(), true);
+
+ {
+ int i = 0;
+ for (QJsonArray::const_iterator it = array.constBegin();
+ it != array.constEnd(); ++it, ++i) {
+ QJsonArray::const_iterator it1 = it;
+ QT_TEST_EQUALITY_OPS(QJsonArray::const_iterator(), QJsonArray::const_iterator(), true);
+ QT_TEST_EQUALITY_OPS(QJsonArray::const_iterator(), it, false);
+ QT_TEST_EQUALITY_OPS(it1, it, true);
+ }
+ }
+
+ {
+ QJsonArray::iterator nonConstIt = array.begin();
+ QJsonArray::const_iterator it = array.constBegin();
+ QT_TEST_EQUALITY_OPS(nonConstIt, it, true);
+ it+=1;
+ QT_TEST_ALL_COMPARISON_OPS(nonConstIt, it, Qt::strong_ordering::less);
+ }
}
void tst_QtJson::testObjectFind()
@@ -890,14 +1357,12 @@ void tst_QtJson::testObjectFind()
QJsonObject::iterator it = object.find(QLatin1String("1"));
QCOMPARE((*it).toDouble(), 1.);
it = object.find(QString("11"));
- QCOMPARE((*it).type(), QJsonValue::Undefined);
QCOMPARE(it, object.end());
QJsonObject::const_iterator cit = object.constFind(QLatin1String("1"));
QCOMPARE((*cit).toDouble(), 1.);
cit = object.constFind(QString("11"));
- QCOMPARE((*it).type(), QJsonValue::Undefined);
- QCOMPARE(it, object.end());
+ QCOMPARE(cit, object.constEnd());
}
void tst_QtJson::testDocument()
@@ -972,6 +1437,8 @@ void tst_QtJson::testDocument()
QCOMPARE(doc5.isObject(), false);
QCOMPARE(doc5.array().size(), 1);
QCOMPARE(doc5.array().at(0), QJsonValue(23));
+
+ QT_TEST_EQUALITY_OPS(doc2, doc3, true);
}
void tst_QtJson::nullValues()
@@ -1062,21 +1529,55 @@ void tst_QtJson::constNullObject()
QCOMPARE(nullObject["foo"], QJsonValue(QJsonValue::Undefined));
}
-void tst_QtJson::keySorting()
+void tst_QtJson::keySorting_data()
{
+ QTest::addColumn<QString>("json");
+ QTest::addColumn<QStringList>("sortedKeys");
+
+ QStringList list = {"A", "B"};
+ QTest::newRow("sorted-ascii-2") << R"({ "A": false, "B": true })" << list;
const char *json = "{ \"B\": true, \"A\": false }";
- QJsonDocument doc = QJsonDocument::fromJson(json);
+ QTest::newRow("unsorted-ascii-2") << json << list;
+
+ list = QStringList{"A", "B", "C", "D", "E"};
+ QTest::newRow("sorted-ascii-5") << R"({"A": 1, "B": 2, "C": 3, "D": 4, "E": 5})" << list;
+ QTest::newRow("unsorted-ascii-5") << R"({"A": 1, "C": 3, "D": 4, "B": 2, "E": 5})" << list;
+ QTest::newRow("inverse-sorted-ascii-5") << R"({"E": 5, "D": 4, "C": 3, "B": 2, "A": 1})" << list;
+
+ list = QStringList{"á", "é", "í", "ó", "ú"};
+ QTest::newRow("sorted-latin1") << R"({"á": 1, "é": 2, "í": 3, "ó": 4, "ú": 5})" << list;
+ QTest::newRow("unsorted-latin1") << R"({"á": 1, "í": 3, "ó": 4, "é": 2, "ú": 5})" << list;
+ QTest::newRow("inverse-sorted-latin1") << R"({"ú": 5, "ó": 4, "í": 3, "é": 2, "á": 1})" << list;
+
+ QTest::newRow("sorted-escaped-latin1") << R"({"\u00e1": 1, "\u00e9": 2, "\u00ed": 3, "\u00f3": 4, "\u00fa": 5})" << list;
+ QTest::newRow("unsorted-escaped-latin1") << R"({"\u00e1": 1, "\u00ed": 3, "\u00f3": 4, "\u00e9": 2, "\u00fa": 5})" << list;
+ QTest::newRow("inverse-sorted-escaped-latin1") << R"({"\u00fa": 5, "\u00f3": 4, "\u00ed": 3, "\u00e9": 2, "\u00e1": 1})" << list;
+
+ list = QStringList{"A", "α", "Я", "€", "测"};
+ QTest::newRow("sorted") << R"({"A": 1, "α": 2, "Я": 3, "€": 4, "测": 5})" << list;
+ QTest::newRow("unsorted") << R"({"A": 1, "Я": 3, "€": 4, "α": 2, "测": 5})" << list;
+ QTest::newRow("inverse-sorted") << R"({"测": 5, "€": 4, "Я": 3, "α": 2, "A": 1})" << list;
+
+ QTest::newRow("sorted-escaped") << R"({"A": 1, "\u03b1": 2, "\u042f": 3, "\u20ac": 4, "\u6d4b": 5})" << list;
+ QTest::newRow("unsorted-escaped") << R"({"A": 1, "\u042f": 3, "\u20ac": 4, "\u03b1": 2, "\u6d4b": 5})" << list;
+ QTest::newRow("inverse-sorted-escaped") << R"({"\u6d4b": 5, "\u20ac": 4, "\u042f": 3, "\u03b1": 2, "A": 1})" << list;
+}
+
+void tst_QtJson::keySorting()
+{
+ QFETCH(QString, json);
+ QFETCH(QStringList, sortedKeys);
+ QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8());
QCOMPARE(doc.isObject(), true);
QJsonObject o = doc.object();
- QCOMPARE(o.size(), 2);
+ QCOMPARE(o.size(), sortedKeys.size());
+ QCOMPARE(o.keys(), sortedKeys);
QJsonObject::const_iterator it = o.constBegin();
- QCOMPARE(it.key(), QLatin1String("A"));
- ++it;
- QCOMPARE(it.key(), QLatin1String("B"));
-
- QCOMPARE(o.keys(), QStringList() << QLatin1String("A") << QLatin1String("B"));
+ QStringList::const_iterator it2 = sortedKeys.constBegin();
+ for ( ; it != o.constEnd(); ++it, ++it2)
+ QCOMPARE(it.key(), *it2);
}
void tst_QtJson::undefinedValues()
@@ -1084,6 +1585,8 @@ void tst_QtJson::undefinedValues()
QJsonObject object;
object.insert("Key", QJsonValue(QJsonValue::Undefined));
QCOMPARE(object.size(), 0);
+ object["Key"] = QJsonValue(QJsonValue::Undefined);
+ QCOMPARE(object.size(), 0);
object.insert("Key", QLatin1String("Value"));
QCOMPARE(object.size(), 1);
@@ -1110,8 +1613,8 @@ void tst_QtJson::fromVariant_data()
bool boolValue = true;
int intValue = -1;
uint uintValue = 1;
- long long longlongValue = -2;
- unsigned long long ulonglongValue = 2;
+ qlonglong longlongValue = -2;
+ qulonglong ulonglongValue = 2;
float floatValue = 3.3f;
double doubleValue = 4.4;
QString stringValue("str");
@@ -1130,6 +1633,7 @@ void tst_QtJson::fromVariant_data()
variantList.append(stringValue);
variantList.append(stringList);
variantList.append(QVariant::fromValue(nullptr));
+ variantList.append(QVariant());
QJsonArray jsonArray_variant;
jsonArray_variant.append(boolValue);
jsonArray_variant.append(floatValue);
@@ -1137,27 +1641,35 @@ void tst_QtJson::fromVariant_data()
jsonArray_variant.append(stringValue);
jsonArray_variant.append(jsonArray_string);
jsonArray_variant.append(QJsonValue(QJsonValue::Null));
+ jsonArray_variant.append(QJsonValue());
QVariantMap variantMap;
variantMap["bool"] = boolValue;
variantMap["float"] = floatValue;
variantMap["string"] = stringValue;
variantMap["array"] = variantList;
+ variantMap["null"] = QVariant::fromValue(nullptr);
+ variantMap["default"] = QVariant();
QVariantHash variantHash;
variantHash["bool"] = boolValue;
variantHash["float"] = floatValue;
variantHash["string"] = stringValue;
variantHash["array"] = variantList;
+ variantHash["null"] = QVariant::fromValue(nullptr);
+ variantHash["default"] = QVariant();
QJsonObject jsonObject;
jsonObject["bool"] = boolValue;
jsonObject["float"] = floatValue;
jsonObject["string"] = stringValue;
jsonObject["array"] = jsonArray_variant;
+ jsonObject["null"] = QJsonValue::Null;
+ jsonObject["default"] = QJsonValue();
+ QTest::newRow("default") << QVariant() << QJsonValue();
QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QJsonValue(QJsonValue::Null);
QTest::newRow("bool") << QVariant(boolValue) << QJsonValue(boolValue);
QTest::newRow("int") << QVariant(intValue) << QJsonValue(intValue);
- QTest::newRow("uint") << QVariant(uintValue) << QJsonValue(static_cast<double>(uintValue));
+ QTest::newRow("uint") << QVariant(uintValue) << QJsonValue(static_cast<qint64>(uintValue));
QTest::newRow("longlong") << QVariant(longlongValue) << QJsonValue(longlongValue);
QTest::newRow("ulonglong") << QVariant(ulonglongValue) << QJsonValue(static_cast<double>(ulonglongValue));
QTest::newRow("float") << QVariant(floatValue) << QJsonValue(floatValue);
@@ -1169,13 +1681,55 @@ void tst_QtJson::fromVariant_data()
QTest::newRow("variantHash") << QVariant(variantHash) << QJsonValue(jsonObject);
}
+// replaces QVariant() with QVariant(nullptr)
+static QVariant normalizedVariant(const QVariant &v)
+{
+ switch (v.userType()) {
+ case QMetaType::UnknownType:
+ return QVariant::fromValue(nullptr);
+ case QMetaType::QVariantList: {
+ const QVariantList in = v.toList();
+ QVariantList out;
+ out.reserve(in.size());
+ for (const QVariant &v : in)
+ out << normalizedVariant(v);
+ return out;
+ }
+ case QMetaType::QStringList: {
+ const QStringList in = v.toStringList();
+ QVariantList out;
+ out.reserve(in.size());
+ for (const QString &v : in)
+ out << v;
+ return out;
+ }
+ case QMetaType::QVariantMap: {
+ const QVariantMap in = v.toMap();
+ QVariantMap out;
+ for (auto it = in.begin(); it != in.end(); ++it)
+ out.insert(it.key(), normalizedVariant(it.value()));
+ return out;
+ }
+ case QMetaType::QVariantHash: {
+ const QVariantHash in = v.toHash();
+ QVariantMap out;
+ for (auto it = in.begin(); it != in.end(); ++it)
+ out.insert(it.key(), normalizedVariant(it.value()));
+ return out;
+ }
+
+ default:
+ return v;
+ }
+}
+
void tst_QtJson::fromVariant()
{
QFETCH( QVariant, variant );
QFETCH( QJsonValue, jsonvalue );
QCOMPARE(QJsonValue::fromVariant(variant), jsonvalue);
- QCOMPARE(variant.toJsonValue(), jsonvalue);
+ QCOMPARE(normalizedVariant(variant).toJsonValue(), jsonvalue);
}
void tst_QtJson::fromVariantSpecial_data()
@@ -1208,7 +1762,7 @@ void tst_QtJson::toVariant()
QFETCH( QVariant, variant );
QFETCH( QJsonValue, jsonvalue );
- QCOMPARE(jsonvalue.toVariant(), variant);
+ QCOMPARE(jsonvalue.toVariant(), normalizedVariant(variant));
}
void tst_QtJson::fromVariantMap()
@@ -1256,7 +1810,8 @@ void tst_QtJson::fromVariantHash()
void tst_QtJson::toVariantMap()
{
- QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().type()), QMetaType::QVariantMap); // QTBUG-32524
+ QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().typeId()),
+ QMetaType::QVariantMap); // QTBUG-32524
QJsonObject object;
QVariantMap map = object.toVariantMap();
@@ -1276,7 +1831,7 @@ void tst_QtJson::toVariantMap()
QCOMPARE(map.size(), 3);
QCOMPARE(map.value("Key"), QVariant(QString("Value")));
QCOMPARE(map.value("null"), QVariant::fromValue(nullptr));
- QCOMPARE(map.value("Array").type(), QVariant::List);
+ QCOMPARE(map.value("Array").typeId(), QMetaType::QVariantList);
QVariantList list = map.value("Array").toList();
QCOMPARE(list.size(), 4);
QCOMPARE(list.at(0), QVariant(true));
@@ -1305,7 +1860,7 @@ void tst_QtJson::toVariantHash()
QCOMPARE(hash.size(), 3);
QCOMPARE(hash.value("Key"), QVariant(QString("Value")));
QCOMPARE(hash.value("null"), QVariant::fromValue(nullptr));
- QCOMPARE(hash.value("Array").type(), QVariant::List);
+ QCOMPARE(hash.value("Array").typeId(), QMetaType::QVariantList);
QVariantList list = hash.value("Array").toList();
QCOMPARE(list.size(), 4);
QCOMPARE(list.at(0), QVariant(true));
@@ -1316,7 +1871,8 @@ void tst_QtJson::toVariantHash()
void tst_QtJson::toVariantList()
{
- QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().type()), QMetaType::QVariantList); // QTBUG-32524
+ QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().typeId()),
+ QMetaType::QVariantList); // QTBUG-32524
QJsonArray array;
QVariantList list = array.toVariantList();
@@ -1336,7 +1892,7 @@ void tst_QtJson::toVariantList()
QCOMPARE(list.size(), 3);
QCOMPARE(list[0], QVariant(QString("Value")));
QCOMPARE(list[1], QVariant::fromValue(nullptr));
- QCOMPARE(list[2].type(), QVariant::List);
+ QCOMPARE(list[2].typeId(), QMetaType::QVariantList);
QVariantList vlist = list[2].toList();
QCOMPARE(vlist.size(), 4);
QCOMPARE(vlist.at(0), QVariant(true));
@@ -1458,16 +2014,13 @@ void tst_QtJson::toJsonLargeNumericValues()
QJsonArray array;
array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0
array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE
- array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE
array.append(QJsonValue(std::numeric_limits<double>::min()));
array.append(QJsonValue(std::numeric_limits<double>::max()));
array.append(QJsonValue(std::numeric_limits<double>::epsilon()));
- array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
array.append(QJsonValue(0.0));
array.append(QJsonValue(-std::numeric_limits<double>::min()));
array.append(QJsonValue(-std::numeric_limits<double>::max()));
array.append(QJsonValue(-std::numeric_limits<double>::epsilon()));
- array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
array.append(QJsonValue(-0.0));
array.append(QJsonValue(9007199254740992LL)); // JS Number max integer
array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer
@@ -1481,27 +2034,21 @@ void tst_QtJson::toJsonLargeNumericValues()
" 1.234567,\n"
" 1.7976931348623157e+308,\n"
#ifdef QT_NO_DOUBLECONVERSION // "shortest" double conversion is not very short then
- " 4.9406564584124654e-324,\n"
" 2.2250738585072014e-308,\n"
" 1.7976931348623157e+308,\n"
" 2.2204460492503131e-16,\n"
- " 4.9406564584124654e-324,\n"
" 0,\n"
" -2.2250738585072014e-308,\n"
" -1.7976931348623157e+308,\n"
" -2.2204460492503131e-16,\n"
- " -4.9406564584124654e-324,\n"
#else
- " 5e-324,\n"
" 2.2250738585072014e-308,\n"
" 1.7976931348623157e+308,\n"
" 2.220446049250313e-16,\n"
- " 5e-324,\n"
" 0,\n"
" -2.2250738585072014e-308,\n"
" -1.7976931348623157e+308,\n"
" -2.220446049250313e-16,\n"
- " -5e-324,\n"
#endif
" 0,\n"
" 9007199254740992,\n"
@@ -1509,20 +2056,50 @@ void tst_QtJson::toJsonLargeNumericValues()
" ]\n"
"}\n";
-#ifdef Q_OS_QNX
- QEXPECT_FAIL("", "See QTBUG-37066", Continue);
-#endif
QCOMPARE(json, expected);
QJsonDocument doc;
doc.setObject(object);
json = doc.toJson();
-#ifdef Q_OS_QNX
- QEXPECT_FAIL("", "See QTBUG-37066", Continue);
-#endif
QCOMPARE(json, expected);
}
+void tst_QtJson::toJsonDenormalValues()
+{
+ if constexpr (std::numeric_limits<double>::has_denorm == std::denorm_present) {
+ QJsonObject object;
+ QJsonArray array;
+ array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE
+ array.append(QJsonValue(std::numeric_limits<double>::denorm_min()));
+ array.append(QJsonValue(-std::numeric_limits<double>::denorm_min()));
+ object.insert("Array", array);
+
+ QByteArray json = QJsonDocument(object).toJson();
+ QByteArray expected =
+ "{\n"
+ " \"Array\": [\n"
+#ifdef QT_NO_DOUBLECONVERSION // "shortest" double conversion is not very short then
+ " 4.9406564584124654e-324,\n"
+ " 4.9406564584124654e-324,\n"
+ " -4.9406564584124654e-324\n"
+#else
+ " 5e-324,\n"
+ " 5e-324,\n"
+ " -5e-324\n"
+#endif
+ " ]\n"
+ "}\n";
+
+ QCOMPARE(json, expected);
+ QJsonDocument doc;
+ doc.setObject(object);
+ json = doc.toJson();
+ QCOMPARE(json, expected);
+ } else {
+ QSKIP("Skipping 'denorm' as this type lacks denormals on this system");
+ }
+}
+
void tst_QtJson::fromJson()
{
{
@@ -1813,64 +2390,6 @@ void tst_QtJson::fromJsonErrors()
}
}
-void tst_QtJson::fromBinary()
-{
- QFile file(testDataDir + "/test.json");
- file.open(QFile::ReadOnly);
- QByteArray testJson = file.readAll();
-
- QJsonDocument doc = QJsonDocument::fromJson(testJson);
- QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
- QVERIFY(!outdoc.isNull());
- QCOMPARE(doc, outdoc);
-
- QFile bfile(testDataDir + "/test.bjson");
- bfile.open(QFile::ReadOnly);
- QByteArray binary = bfile.readAll();
-
- QJsonDocument bdoc = QJsonDocument::fromBinaryData(binary);
- QVERIFY(!bdoc.isNull());
- QCOMPARE(doc.toVariant(), bdoc.toVariant());
- QCOMPARE(doc, bdoc);
-}
-
-void tst_QtJson::toAndFromBinary_data()
-{
- QTest::addColumn<QString>("filename");
- QTest::newRow("test.json") << (testDataDir + "/test.json");
- QTest::newRow("test2.json") << (testDataDir + "/test2.json");
-}
-
-void tst_QtJson::toAndFromBinary()
-{
- QFETCH(QString, filename);
- QFile file(filename);
- QVERIFY(file.open(QFile::ReadOnly));
- QByteArray data = file.readAll();
-
- QJsonDocument doc = QJsonDocument::fromJson(data);
- QVERIFY(!doc.isNull());
- QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData());
- QVERIFY(!outdoc.isNull());
- QCOMPARE(doc, outdoc);
-}
-
-void tst_QtJson::invalidBinaryData()
-{
- QDir dir(testDataDir + "/invalidBinaryData");
- QFileInfoList files = dir.entryInfoList();
- for (int i = 0; i < files.size(); ++i) {
- if (!files.at(i).isFile())
- continue;
- QFile file(files.at(i).filePath());
- file.open(QIODevice::ReadOnly);
- QByteArray bytes = file.readAll();
- bytes.squeeze();
- QJsonDocument document = QJsonDocument::fromRawData(bytes.constData(), bytes.size());
- QVERIFY(document.isNull());
- }
-}
-
void tst_QtJson::parseNumbers()
{
{
@@ -1903,12 +2422,12 @@ void tst_QtJson::parseNumbers()
QCOMPARE(val.toDouble(), (double)numbers[i].n);
}
}
+ // test number parsing
+ struct Numbers {
+ const char *str;
+ double n;
+ };
{
- // test number parsing
- struct Numbers {
- const char *str;
- double n;
- };
Numbers numbers [] = {
{ "0", 0 },
{ "1", 1 },
@@ -1924,8 +2443,6 @@ void tst_QtJson::parseNumbers()
{ "1.1e10", 1.1e10 },
{ "1.1e308", 1.1e308 },
{ "-1.1e308", -1.1e308 },
- { "1.1e-308", 1.1e-308 },
- { "-1.1e-308", -1.1e-308 },
{ "1.1e+308", 1.1e+308 },
{ "-1.1e+308", -1.1e+308 },
{ "1.e+308", 1.e+308 },
@@ -1937,10 +2454,6 @@ void tst_QtJson::parseNumbers()
json += numbers[i].str;
json += " ]";
QJsonDocument doc = QJsonDocument::fromJson(json);
-#ifdef Q_OS_QNX
- if (0 == QString::compare(numbers[i].str, "1.1e-308"))
- QEXPECT_FAIL("", "See QTBUG-37066", Abort);
-#endif
QVERIFY(!doc.isEmpty());
QCOMPARE(doc.isArray(), true);
QCOMPARE(doc.isObject(), false);
@@ -1951,6 +2464,29 @@ void tst_QtJson::parseNumbers()
QCOMPARE(val.toDouble(), numbers[i].n);
}
}
+ if constexpr (std::numeric_limits<double>::has_denorm == std::denorm_present) {
+ Numbers numbers [] = {
+ { "1.1e-308", 1.1e-308 },
+ { "-1.1e-308", -1.1e-308 }
+ };
+ int size = sizeof(numbers)/sizeof(Numbers);
+ for (int i = 0; i < size; ++i) {
+ QByteArray json = "[ ";
+ json += numbers[i].str;
+ json += " ]";
+ QJsonDocument doc = QJsonDocument::fromJson(json);
+ QVERIFY(!doc.isEmpty());
+ QCOMPARE(doc.isArray(), true);
+ QCOMPARE(doc.isObject(), false);
+ QJsonArray array = doc.array();
+ QCOMPARE(array.size(), 1);
+ QJsonValue val = array.at(0);
+ QCOMPARE(val.type(), QJsonValue::Double);
+ QCOMPARE(val.toDouble(), numbers[i].n);
+ }
+ } else {
+ qInfo("Skipping denormal test as this system's double type lacks support");
+ }
}
void tst_QtJson::parseStrings()
@@ -2040,136 +2576,11 @@ void tst_QtJson::parseDuplicateKeys()
void tst_QtJson::testParser()
{
QFile file(testDataDir + "/test.json");
- file.open(QFile::ReadOnly);
- QByteArray testJson = file.readAll();
-
- QJsonDocument doc = QJsonDocument::fromJson(testJson);
- QVERIFY(!doc.isEmpty());
-}
-
-void tst_QtJson::compactArray()
-{
- QJsonArray array;
- array.append(QLatin1String("First Entry"));
- array.append(QLatin1String("Second Entry"));
- array.append(QLatin1String("Third Entry"));
- QJsonDocument doc(array);
- int s = doc.toBinaryData().size();
- array.removeAt(1);
- doc.setArray(array);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("[\n"
- " \"First Entry\",\n"
- " \"Third Entry\"\n"
- "]\n"));
-
- array.removeAt(0);
- doc.setArray(array);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("[\n"
- " \"Third Entry\"\n"
- "]\n"));
-
- array.removeAt(0);
- doc.setArray(array);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("[\n"
- "]\n"));
-
-}
-
-void tst_QtJson::compactObject()
-{
- QJsonObject object;
- object.insert(QLatin1String("Key1"), QLatin1String("First Entry"));
- object.insert(QLatin1String("Key2"), QLatin1String("Second Entry"));
- object.insert(QLatin1String("Key3"), QLatin1String("Third Entry"));
- QJsonDocument doc(object);
- int s = doc.toBinaryData().size();
- object.remove(QLatin1String("Key2"));
- doc.setObject(object);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("{\n"
- " \"Key1\": \"First Entry\",\n"
- " \"Key3\": \"Third Entry\"\n"
- "}\n"));
-
- object.remove(QLatin1String("Key1"));
- doc.setObject(object);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("{\n"
- " \"Key3\": \"Third Entry\"\n"
- "}\n"));
-
- object.remove(QLatin1String("Key3"));
- doc.setObject(object);
- QVERIFY(s > doc.toBinaryData().size());
- s = doc.toBinaryData().size();
- QCOMPARE(doc.toJson(),
- QByteArray("{\n"
- "}\n"));
-
-}
-
-void tst_QtJson::validation()
-{
- // this basically tests that we don't crash on corrupt data
- QFile file(testDataDir + "/test.json");
QVERIFY(file.open(QFile::ReadOnly));
QByteArray testJson = file.readAll();
- QVERIFY(!testJson.isEmpty());
QJsonDocument doc = QJsonDocument::fromJson(testJson);
- QVERIFY(!doc.isNull());
-
- QByteArray binary = doc.toBinaryData();
-
- // only test the first 1000 bytes. Testing the full file takes too long
- for (int i = 0; i < 1000; ++i) {
- QByteArray corrupted = binary;
- corrupted[i] = char(0xff);
- QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
- if (doc.isNull())
- continue;
- QByteArray json = doc.toJson();
- }
-
-
- QFile file2(testDataDir + "/test3.json");
- file2.open(QFile::ReadOnly);
- testJson = file2.readAll();
- QVERIFY(!testJson.isEmpty());
-
- doc = QJsonDocument::fromJson(testJson);
- QVERIFY(!doc.isNull());
-
- binary = doc.toBinaryData();
-
- for (int i = 0; i < binary.size(); ++i) {
- QByteArray corrupted = binary;
- corrupted[i] = char(0xff);
- QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted);
- if (doc.isNull())
- continue;
- QByteArray json = doc.toJson();
-
- corrupted = binary;
- corrupted[i] = 0x00;
- doc = QJsonDocument::fromBinaryData(corrupted);
- if (doc.isNull())
- continue;
- json = doc.toJson();
- }
+ QVERIFY(!doc.isEmpty());
}
void tst_QtJson::assignToDocument()
@@ -2222,12 +2633,12 @@ void tst_QtJson::testCompaction()
QCOMPARE(obj.size(), 1);
QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar"));
- QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(obj).toBinaryData());
- QVERIFY(!doc.isNull());
- QVERIFY(!doc.isEmpty());
- QCOMPARE(doc.isArray(), false);
- QCOMPARE(doc.isObject(), true);
- QCOMPARE(doc.object(), obj);
+ QJsonObject obj2;
+
+ QT_TEST_EQUALITY_OPS(obj, obj2, false);
+ QT_TEST_EQUALITY_OPS(QJsonObject(), obj2, true);
+ obj2 = obj;
+ QT_TEST_EQUALITY_OPS(obj, obj2, true);
}
void tst_QtJson::testDebugStream()
@@ -2317,48 +2728,128 @@ void tst_QtJson::testDebugStream()
}
}
-void tst_QtJson::testCompactionError()
+void tst_QtJson::parseEscapes_data()
{
- QJsonObject schemaObject;
- schemaObject.insert("_Type", QLatin1String("_SchemaType"));
- schemaObject.insert("name", QLatin1String("Address"));
- schemaObject.insert("schema", QJsonObject());
- {
- QJsonObject content(schemaObject);
- QJsonDocument doc(content);
- QVERIFY(!doc.isNull());
- QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
- schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
- }
+ QTest::addColumn<QByteArray>("json");
+ QTest::addColumn<QString>("result");
+
+ auto addUnicodeRow = [](char32_t u) {
+ char buf[32]; // more than enough
+ char *ptr = buf;
+ const QString result = QString::fromUcs4(&u, 1);
+ for (QChar c : result)
+ ptr += snprintf(ptr, std::end(buf) - ptr, "\\u%04x", c.unicode());
+ QTest::addRow("U+%04X", u) << "[\"" + QByteArray(buf) + "\"]" << result;
+ };
- QJsonObject schema;
- schema.insert("streetNumber", schema.value("number").toObject());
- schemaObject.insert("schema", schema);
- {
- QJsonObject content(schemaObject);
- content.remove("_Uuid");
- content.remove("_Version");
- QJsonDocument doc(content);
- QVERIFY(!doc.isNull());
- QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex();
- schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size()));
+ char singleCharJson[] = R"(["\x"])";
+ Q_ASSERT(singleCharJson[3] == 'x');
+ auto makeSingleCharEscape = [&singleCharJson](char c) {
+ singleCharJson[3] = char(c);
+ return QByteArray(singleCharJson, std::size(singleCharJson) - 1);
+ };
+
+ QTest::addRow("quote") << makeSingleCharEscape('"') << "\"";
+ QTest::addRow("backslash") << makeSingleCharEscape('\\') << "\\";
+ QTest::addRow("slash") << makeSingleCharEscape('/') << "/";
+ QTest::addRow("backspace") << makeSingleCharEscape('b') << "\b";
+ QTest::addRow("form-feed") << makeSingleCharEscape('f') << "\f";
+ QTest::addRow("newline") << makeSingleCharEscape('n') << "\n";
+ QTest::addRow("carriage-return") << makeSingleCharEscape('r') << "\r";
+ QTest::addRow("tab") << makeSingleCharEscape('t') << "\t";
+
+ // we're not going to exhaustively test all Unicode possibilities
+ for (char16_t c = 0; c < 0x21; ++c)
+ addUnicodeRow(c);
+ addUnicodeRow(u'\u007f');
+ addUnicodeRow(u'\u0080');
+ addUnicodeRow(u'\u00ff');
+ addUnicodeRow(u'\u0100');
+ addUnicodeRow(char16_t(0xd800));
+ addUnicodeRow(char16_t(0xdc00));
+ addUnicodeRow(u'\ufffe');
+ addUnicodeRow(u'\uffff');
+ addUnicodeRow(U'\U00010000');
+ addUnicodeRow(U'\U00100000');
+ addUnicodeRow(U'\U0010ffff');
+
+ QTest::addRow("mojibake-utf8") << QByteArrayLiteral(R"(["A\u00e4\u00C4"])")
+ << QStringLiteral(u"A\u00e4\u00C4");
+
+ // characters for which, preceded by backslash, it is a valid (recognized)
+ // escape sequence (should match the above list)
+ static const char validEscapes[] = "\"\\/bfnrtu";
+ for (int i = 0; i <= 0xff; ++i) {
+ if (i && strchr(validEscapes, i))
+ continue;
+ QTest::addRow("invalid-uchar-0x%02x", i) << makeSingleCharEscape(i) << QString(char16_t(i));
}
}
-void tst_QtJson::parseUnicodeEscapes()
+void tst_QtJson::parseEscapes()
{
- const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]";
+ QFETCH(QByteArray, json);
+ QFETCH(QString, result);
QJsonDocument doc = QJsonDocument::fromJson(json);
QJsonArray array = doc.array();
- QString result = QLatin1String("A");
- result += QChar(0xe4);
- result += QChar(0xc4);
-
QCOMPARE(array.first().toString(), result);
}
+void tst_QtJson::makeEscapes_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QByteArray>("result");
+
+ auto addUnicodeRow = [](char16_t c) {
+ char buf[32]; // more than enough
+ snprintf(buf, std::size(buf), "\\u%04x", c);
+ QTest::addRow("U+%04X", c) << QString(c) << QByteArray(buf);
+ };
+
+
+ QTest::addRow("quote") << "\"" << QByteArray(R"(\")");
+ QTest::addRow("backslash") << "\\" << QByteArray(R"(\\)");
+ //QTest::addRow("slash") << "/" << QByteArray(R"(\/)"); // does not get escaped
+ QTest::addRow("backspace") << "\b" << QByteArray(R"(\b)");
+ QTest::addRow("form-feed") << "\f" << QByteArray(R"(\f)");
+ QTest::addRow("newline") << "\n" << QByteArray(R"(\n)");
+ QTest::addRow("carriage-return") << "\r" << QByteArray(R"(\r)");
+ QTest::addRow("tab") << "\t" << QByteArray(R"(\t)");
+
+ // control characters other than the above
+ for (char16_t c = 0; c < 0x20; ++c) {
+ if (c && strchr("\b\f\n\r\t", c))
+ continue;
+ addUnicodeRow(c);
+ }
+ // unpaired surrogates
+ addUnicodeRow(char16_t(0xd800));
+ addUnicodeRow(char16_t(0xdc00));
+
+ QString improperlyPaired;
+ improperlyPaired.append(char16_t(0xdc00));
+ improperlyPaired.append(char16_t(0xd800));
+ QTest::addRow("inverted-surrogates") << improperlyPaired << QByteArray("\\udc00\\ud800");
+}
+
+void tst_QtJson::makeEscapes()
+{
+ QFETCH(QString, input);
+ QFETCH(QByteArray, result);
+
+ QJsonArray array = { input };
+ QByteArray json = QJsonDocument(array).toJson(QJsonDocument::Compact);
+
+ QVERIFY(json.startsWith("[\""));
+ result.prepend("[\"");
+ QVERIFY(json.endsWith("\"]"));
+ result.append("\"]");
+
+ QCOMPARE(json, result);
+}
+
void tst_QtJson::assignObjects()
{
const char *json =
@@ -2427,57 +2918,57 @@ void tst_QtJson::testDetachBug()
void tst_QtJson::valueEquals()
{
QCOMPARE(QJsonValue(), QJsonValue());
- QVERIFY(QJsonValue() != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue() != QJsonValue(true));
- QVERIFY(QJsonValue() != QJsonValue(1.));
- QVERIFY(QJsonValue() != QJsonValue(QJsonArray()));
- QVERIFY(QJsonValue() != QJsonValue(QJsonObject()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(), QJsonValue(true), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(), QJsonValue(1.), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(), QJsonValue(QJsonArray()), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(), QJsonValue(QJsonObject()), false);
QCOMPARE(QJsonValue(true), QJsonValue(true));
- QVERIFY(QJsonValue(true) != QJsonValue(false));
- QVERIFY(QJsonValue(true) != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue(true) != QJsonValue());
- QVERIFY(QJsonValue(true) != QJsonValue(1.));
- QVERIFY(QJsonValue(true) != QJsonValue(QJsonArray()));
- QVERIFY(QJsonValue(true) != QJsonValue(QJsonObject()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(false), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(1.), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(QJsonArray()), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(true), QJsonValue(QJsonObject()), false);
QCOMPARE(QJsonValue(1), QJsonValue(1));
- QVERIFY(QJsonValue(1) != QJsonValue(2));
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(2), false);
QCOMPARE(QJsonValue(1), QJsonValue(1.));
- QVERIFY(QJsonValue(1) != QJsonValue(1.1));
- QVERIFY(QJsonValue(1) != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue(1) != QJsonValue());
- QVERIFY(QJsonValue(1) != QJsonValue(true));
- QVERIFY(QJsonValue(1) != QJsonValue(QJsonArray()));
- QVERIFY(QJsonValue(1) != QJsonValue(QJsonObject()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(1.1), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(true), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(QJsonArray()), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1), QJsonValue(QJsonObject()), false);
QCOMPARE(QJsonValue(1.), QJsonValue(1.));
- QVERIFY(QJsonValue(1.) != QJsonValue(2.));
- QVERIFY(QJsonValue(1.) != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue(1.) != QJsonValue());
- QVERIFY(QJsonValue(1.) != QJsonValue(true));
- QVERIFY(QJsonValue(1.) != QJsonValue(QJsonArray()));
- QVERIFY(QJsonValue(1.) != QJsonValue(QJsonObject()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(2.), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(true), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(QJsonArray()), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(1.), QJsonValue(QJsonObject()), false);
QCOMPARE(QJsonValue(QJsonArray()), QJsonValue(QJsonArray()));
QJsonArray nonEmptyArray;
nonEmptyArray.append(true);
- QVERIFY(QJsonValue(QJsonArray()) != nonEmptyArray);
- QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue(QJsonArray()) != QJsonValue());
- QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(true));
- QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(1.));
- QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonObject()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), nonEmptyArray, false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), QJsonValue(), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), QJsonValue(true), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), QJsonValue(1.), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonArray()), QJsonValue(QJsonObject()), false);
QCOMPARE(QJsonValue(QJsonObject()), QJsonValue(QJsonObject()));
QJsonObject nonEmptyObject;
nonEmptyObject.insert("Key", true);
- QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject);
- QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonValue::Undefined));
- QVERIFY(QJsonValue(QJsonObject()) != QJsonValue());
- QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(true));
- QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(1.));
- QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonArray()));
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), nonEmptyObject, false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(QJsonValue::Undefined), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(true), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(1.), false);
+ QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(QJsonArray()), false);
QCOMPARE(QJsonValue("foo"), QJsonValue(QLatin1String("foo")));
QCOMPARE(QJsonValue("foo"), QJsonValue(QString("foo")));
@@ -2553,6 +3044,12 @@ void tst_QtJson::objectEquals()
QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
+
+ // The same, but from a QJsonDocument perspective
+ QCOMPARE(QJsonDocument(left) == QJsonDocument(right), result);
+ QCOMPARE(QJsonDocument(left) != QJsonDocument(right), !result);
+ QCOMPARE(QJsonDocument(right) == QJsonDocument(left), result);
+ QCOMPARE(QJsonDocument(right) != QJsonDocument(left), !result);
}
void tst_QtJson::arrayEquals_data()
@@ -2606,12 +3103,65 @@ void tst_QtJson::arrayEquals()
QCOMPARE(QJsonValue(left) != QJsonValue(right), !result);
QCOMPARE(QJsonValue(right) == QJsonValue(left), result);
QCOMPARE(QJsonValue(right) != QJsonValue(left), !result);
+
+ // The same but from QJsonDocument perspective
+ QCOMPARE(QJsonDocument(left) == QJsonDocument(right), result);
+ QCOMPARE(QJsonDocument(left) != QJsonDocument(right), !result);
+ QCOMPARE(QJsonDocument(right) == QJsonDocument(left), result);
+ QCOMPARE(QJsonDocument(right) != QJsonDocument(left), !result);
+}
+
+void tst_QtJson::documentEquals_data()
+{
+ QTest::addColumn<QJsonDocument>("left");
+ QTest::addColumn<QJsonDocument>("right");
+ QTest::addColumn<bool>("result");
+
+ QTest::newRow("two defaults") << QJsonDocument() << QJsonDocument() << true;
+
+ QJsonDocument emptyobj(QJsonObject{});
+ QJsonDocument emptyarr(QJsonArray{});
+ QTest::newRow("emptyarray vs default") << emptyarr << QJsonDocument() << false;
+ QTest::newRow("emptyobject vs default") << emptyobj << QJsonDocument() << false;
+ QTest::newRow("emptyarray vs emptyobject") << emptyarr << emptyobj << false;
+
+ QJsonDocument array1(QJsonArray{1});
+ QJsonDocument array2(QJsonArray{2});
+ QTest::newRow("emptyarray vs emptyarray") << emptyarr << emptyarr << true;
+ QTest::newRow("emptyarray vs array") << emptyarr << array1 << false;
+ QTest::newRow("array vs array") << array1 << array1 << true;
+ QTest::newRow("array vs otherarray") << array1 << array2 << false;
+
+ QJsonDocument object1(QJsonObject{{"hello", "world"}});
+ QJsonDocument object2(QJsonObject{{"hello", 2}});
+ QTest::newRow("emptyobject vs emptyobject") << emptyobj << emptyobj << true;
+ QTest::newRow("emptyobject vs object") << emptyobj << object1 << false;
+ QTest::newRow("object vs object") << object1 << object1 << true;
+ QTest::newRow("object vs otherobject") << object1 << object2 << false;
+
+ QTest::newRow("object vs array") << array1 << object1 << false;
+}
+
+void tst_QtJson::documentEquals()
+{
+ QFETCH(QJsonDocument, left);
+ QFETCH(QJsonDocument, right);
+ QFETCH(bool, result);
+
+ QCOMPARE(left == right, result);
+ QCOMPARE(right == left, result);
+
+ // invariants checks
+ QCOMPARE(left, left);
+ QCOMPARE(right, right);
+ QCOMPARE(left != right, !result);
+ QCOMPARE(right != left, !result);
}
void tst_QtJson::bom()
{
QFile file(testDataDir + "/bom.json");
- file.open(QFile::ReadOnly);
+ QVERIFY(file.open(QFile::ReadOnly));
QByteArray json = file.readAll();
// Import json document into a QJsonDocument
@@ -2686,6 +3236,8 @@ void tst_QtJson::longStrings()
// test around 15 and 16 bit boundaries, as these are limits
// in the data structures (for Latin1String in qjson_p.h)
QString s(0x7ff0, 'a');
+ QByteArray ba(0x7ff0, 'a');
+ ba.append(0x8010 - 0x7ff0, 'c');
for (int i = 0x7ff0; i < 0x8010; i++) {
s.append(QLatin1Char('c'));
@@ -2702,9 +3254,21 @@ void tst_QtJson::longStrings()
/* ... and a QByteArray from the QJsonDocument */
QByteArray a2 = d2.toJson();
QCOMPARE(a1, a2);
+
+ // Test long keys
+ QJsonObject o1, o2;
+ o1[s] = 42;
+ o2[QLatin1String(ba.data(), i + 1)] = 42;
+ d1.setObject(o1);
+ d2.setObject(o2);
+ a1 = d1.toJson();
+ a2 = d2.toJson();
+ QCOMPARE(a1, a2);
}
s = QString(0xfff0, 'a');
+ ba = QByteArray(0xfff0, 'a');
+ ba.append(0x10010 - 0xfff0, 'c');
for (int i = 0xfff0; i < 0x10010; i++) {
s.append(QLatin1Char('c'));
@@ -2721,6 +3285,16 @@ void tst_QtJson::longStrings()
/* ... and a QByteArray from the QJsonDocument */
QByteArray a2 = d2.toJson();
QCOMPARE(a1, a2);
+
+ // Test long keys
+ QJsonObject o1, o2;
+ o1[s] = 42;
+ o2[QLatin1String(ba.data(), i + 1)] = 42;
+ d1.setObject(o1);
+ d2.setObject(o2);
+ a1 = d1.toJson();
+ a2 = d2.toJson();
+ QCOMPARE(a1, a2);
}
}
@@ -2743,9 +3317,6 @@ void tst_QtJson::testJsonValueRefDefault()
void tst_QtJson::arrayInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonArray{}.isEmpty());
QCOMPARE(QJsonArray{"one"}.count(), 1);
QCOMPARE(QJsonArray{1}.count(), 1);
@@ -2791,14 +3362,10 @@ void tst_QtJson::arrayInitializerList()
QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1));
}
}
-#endif
}
void tst_QtJson::objectInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonObject{}.isEmpty());
{ // one property
@@ -2838,7 +3405,6 @@ void tst_QtJson::objectInitializerList()
QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue"));
QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1));
}
-#endif
}
void tst_QtJson::unicodeKeys()
@@ -2916,7 +3482,7 @@ void tst_QtJson::documentFromVariant()
// As JSON arrays they should be equal.
QCOMPARE(da1.array(), da2.array());
-
+ QT_TEST_EQUALITY_OPS(da1, da2, true);
QMap <QString, QVariant> map;
map["key"] = string;
@@ -2932,6 +3498,7 @@ void tst_QtJson::documentFromVariant()
// As JSON objects they should be equal.
QCOMPARE(do1.object(), do2.object());
+ QT_TEST_EQUALITY_OPS(do1, do2, true);
}
void tst_QtJson::parseErrorOffset_data()
@@ -3011,5 +3578,420 @@ void tst_QtJson::implicitDocumentType()
QCOMPARE(arrayDocument[-1].toInt(123), 123);
}
+void tst_QtJson::streamSerializationQJsonDocument_data()
+{
+ QTest::addColumn<QJsonDocument>("document");
+ QTest::newRow("empty") << QJsonDocument();
+ QTest::newRow("object") << QJsonDocument(QJsonObject{{"value", 42}});
+}
+
+void tst_QtJson::streamSerializationQJsonDocument()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonDocument, document);
+ QJsonDocument output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << document;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, document);
+ QT_TEST_EQUALITY_OPS(output, document, true);
+}
+
+void tst_QtJson::streamSerializationQJsonArray_data()
+{
+ QTest::addColumn<QJsonArray>("array");
+ QTest::newRow("empty") << QJsonArray();
+ QTest::newRow("values") << QJsonArray{665, 666, 667};
+}
+
+void tst_QtJson::streamSerializationQJsonArray()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonArray, array);
+ QJsonArray output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << array;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, array);
+}
+
+void tst_QtJson::streamSerializationQJsonObject_data()
+{
+ QTest::addColumn<QJsonObject>("object");
+ QTest::newRow("empty") << QJsonObject();
+ QTest::newRow("non-empty") << QJsonObject{{"foo", 665}, {"bar", 666}};
+}
+
+void tst_QtJson::streamSerializationQJsonObject()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonObject, object);
+ QJsonObject output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << object;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, object);
+}
+
+void tst_QtJson::streamSerializationQJsonValue_data()
+{
+ QTest::addColumn<QJsonValue>("value");
+ QTest::newRow("double") << QJsonValue{665};
+ QTest::newRow("bool") << QJsonValue{true};
+ QTest::newRow("string") << QJsonValue{QStringLiteral("bum")};
+ QTest::newRow("array") << QJsonValue{QJsonArray{12,1,5,6,7}};
+ QTest::newRow("object") << QJsonValue{QJsonObject{{"foo", 665}, {"bar", 666}}};
+ // test json escape sequence
+ QTest::newRow("array with 0xD800") << QJsonValue(QJsonArray{QString(QChar(0xD800))});
+ QTest::newRow("array with 0xDF06,0xD834") << QJsonValue(QJsonArray{QString(QChar(0xDF06)).append(QChar(0xD834))});
+}
+
+void tst_QtJson::streamSerializationQJsonValue()
+{
+ QByteArray buffer;
+ QFETCH(QJsonValue, value);
+ QJsonValue output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << value;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, value);
+}
+
+void tst_QtJson::streamSerializationQJsonValueEmpty()
+{
+ QByteArray buffer;
+ {
+ QJsonValue undef{QJsonValue::Undefined};
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << undef;
+ QDataStream load(buffer);
+ QJsonValue output;
+ load >> output;
+ QVERIFY(output.isUndefined());
+ }
+ {
+ QJsonValue null{QJsonValue::Null};
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << null;
+ QDataStream load(buffer);
+ QJsonValue output;
+ load >> output;
+ QVERIFY(output.isNull());
+ }
+}
+
+void tst_QtJson::streamVariantSerialization()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ {
+ QJsonDocument objectDoc(QJsonArray{665, 666, 667});
+ QVariant output;
+ QVariant variant(objectDoc);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonDocument);
+ QCOMPARE(output.toJsonDocument(), objectDoc);
+ }
+ {
+ QJsonArray array{665, 666, 667};
+ QVariant output;
+ QVariant variant(array);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonArray);
+ QCOMPARE(output.toJsonArray(), array);
+ }
+ {
+ QJsonObject obj{{"foo", 42}};
+ QVariant output;
+ QVariant variant(obj);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonObject);
+ QCOMPARE(output.toJsonObject(), obj);
+ }
+ {
+ QJsonValue value{42};
+ QVariant output;
+ QVariant variant(value);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonValue);
+ QCOMPARE(output.toJsonValue(), value);
+ }
+}
+
+void tst_QtJson::escapeSurrogateCodePoints_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::addColumn<QByteArray>("escStr");
+ QTest::newRow("0xD800") << QString(QChar(0xD800)) << QByteArray("\\ud800");
+ QTest::newRow("0xDF06,0xD834") << QString(QChar(0xDF06)).append(QChar(0xD834)) << QByteArray("\\udf06\\ud834");
+}
+
+void tst_QtJson::escapeSurrogateCodePoints()
+{
+ QFETCH(QString, str);
+ QFETCH(QByteArray, escStr);
+ QJsonArray array;
+ array.append(str);
+ QByteArray buffer;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << array;
+ // verify the buffer has escaped values
+ QVERIFY(buffer.contains(escStr));
+}
+
+void tst_QtJson::fromToVariantConversions_data()
+{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QJsonValue>("json");
+ QTest::addColumn<QVariant>("jsonToVariant");
+
+ QByteArray utf8("\xC4\x90\xC4\x81\xC5\xA3\xC3\xA2"); // Đāţâ
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ constexpr qlonglong maxInt = std::numeric_limits<qlonglong>::max();
+ constexpr qlonglong minInt = std::numeric_limits<qlonglong>::min();
+ constexpr double maxDouble = std::numeric_limits<double>::max();
+ constexpr double minDouble = std::numeric_limits<double>::min();
+
+ QTest::newRow("default") << QVariant() << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("bool") << QVariant(true) << QJsonValue(true) << QVariant(true);
+ QTest::newRow("int pos") << QVariant(123) << QJsonValue(123) << QVariant(qlonglong(123));
+ QTest::newRow("int neg") << QVariant(-123) << QJsonValue(-123) << QVariant(qlonglong(-123));
+ QTest::newRow("int big pos") << QVariant((1ll << 55) +1) << QJsonValue((1ll << 55) + 1)
+ << QVariant(qlonglong((1ll << 55) + 1));
+ QTest::newRow("int big neg") << QVariant(-(1ll << 55) + 1) << QJsonValue(-(1ll << 55) + 1)
+ << QVariant(qlonglong(-(1ll << 55) + 1));
+ QTest::newRow("int max") << QVariant(maxInt) << QJsonValue(maxInt) << QVariant(maxInt);
+ QTest::newRow("int min") << QVariant(minInt) << QJsonValue(minInt) << QVariant(minInt);
+ QTest::newRow("double pos") << QVariant(123.) << QJsonValue(123.) << QVariant(qlonglong(123.));
+ QTest::newRow("double neg") << QVariant(-123.) << QJsonValue(-123.)
+ << QVariant(qlonglong(-123.));
+ QTest::newRow("double big") << QVariant(maxDouble - 1000) << QJsonValue(maxDouble - 1000)
+ << QVariant(maxDouble - 1000);
+ QTest::newRow("double max") << QVariant(maxDouble) << QJsonValue(maxDouble)
+ << QVariant(maxDouble);
+ QTest::newRow("double min") << QVariant(minDouble) << QJsonValue(minDouble)
+ << QVariant(minDouble);
+ QTest::newRow("double big neg") << QVariant(1000 - maxDouble) << QJsonValue(1000 - maxDouble)
+ << QVariant(1000 - maxDouble);
+ QTest::newRow("double max neg") << QVariant(-maxDouble) << QJsonValue(-maxDouble)
+ << QVariant(-maxDouble);
+ QTest::newRow("double min neg") << QVariant(-minDouble) << QJsonValue(-minDouble)
+ << QVariant(-minDouble);
+
+ QTest::newRow("string null") << QVariant(QString()) << QJsonValue(QString())
+ << QVariant(QString());
+ QTest::newRow("string empty") << QVariant(QString("")) << QJsonValue(QString(""))
+ << QVariant(QString(""));
+ QTest::newRow("string ascii") << QVariant(QString("Data")) << QJsonValue(QString("Data"))
+ << QVariant(QString("Data"));
+ QTest::newRow("string utf8") << QVariant(QString(utf8)) << QJsonValue(QString(utf8))
+ << QVariant(QString(utf8));
+
+ QTest::newRow("bytearray null") << QVariant(QByteArray()) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("bytearray empty") << QVariant(QByteArray()) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("bytearray ascii") << QVariant(QByteArray("Data")) << QJsonValue(QString("Data"))
+ << QVariant(QString("Data"));
+ QTest::newRow("bytearray utf8") << QVariant(utf8) << QJsonValue(QString(utf8))
+ << QVariant(QString(utf8));
+
+ QTest::newRow("datetime") << QVariant(dt) << QJsonValue(dt.toString(Qt::ISODateWithMs))
+ << QVariant(dt.toString(Qt::ISODateWithMs));
+ QTest::newRow("url") << QVariant(QUrl("http://example.com/{q}"))
+ << QJsonValue("http://example.com/%7Bq%7D")
+ << QVariant(QString("http://example.com/%7Bq%7D"));
+ QTest::newRow("uuid") << QVariant(QUuid(uuid))
+ << QJsonValue(uuid.toString(QUuid::WithoutBraces))
+ << QVariant(uuid.toString(QUuid::WithoutBraces));
+ QTest::newRow("regexp") << QVariant(QRegularExpression(".")) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+
+ QTest::newRow("inf") << QVariant(qInf()) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("-inf") << QVariant(-qInf()) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+ QTest::newRow("NaN") << QVariant(qQNaN()) << QJsonValue(QJsonValue::Null)
+ << QVariant::fromValue(nullptr);
+
+ static_assert(std::numeric_limits<double>::digits <= 63,
+ "double is too big on this platform, this test would fail");
+ constexpr quint64 Threshold = Q_UINT64_C(1) << 63;
+ const qulonglong ulongValue = qulonglong(Threshold) + 1;
+ const double uLongToDouble = Threshold;
+ QTest::newRow("ulonglong") << QVariant(ulongValue) << QJsonValue(uLongToDouble)
+ << QVariant(uLongToDouble);
+}
+
+void tst_QtJson::fromToVariantConversions()
+{
+ QFETCH(QVariant, variant);
+ QFETCH(QJsonValue, json);
+ QFETCH(QVariant, jsonToVariant);
+
+ QVariant variantFromJson(json);
+ QVariant variantFromJsonArray(QJsonArray { json });
+ QVariant variantFromJsonObject(QVariantMap { { "foo", variant } });
+
+ QJsonObject object { QPair<QString, QJsonValue>("foo", json) };
+
+ // QJsonValue <> QVariant
+ {
+ QCOMPARE(QJsonValue::fromVariant(variant), json);
+
+ // test the same for QVariant from QJsonValue/QJsonArray/QJsonObject
+ QCOMPARE(QJsonValue::fromVariant(variantFromJson), json);
+ QCOMPARE(QJsonValue::fromVariant(variantFromJsonArray), QJsonArray { json });
+ QCOMPARE(QJsonValue::fromVariant(variantFromJsonObject), object);
+
+ // QJsonValue to variant
+ QCOMPARE(json.toVariant(), jsonToVariant);
+ QCOMPARE(json.toVariant().userType(), jsonToVariant.userType());
+
+ // variant to QJsonValue
+ QCOMPARE(QVariant(json).toJsonValue(), json);
+ }
+
+ // QJsonArray <> QVariantList
+ {
+ QCOMPARE(QJsonArray::fromVariantList(QVariantList { variant }), QJsonArray { json });
+
+ // test the same for QVariantList from QJsonValue/QJsonArray/QJsonObject
+ QCOMPARE(QJsonArray::fromVariantList(QVariantList { variantFromJson }),
+ QJsonArray { json });
+ QCOMPARE(QJsonArray::fromVariantList(QVariantList { variantFromJsonArray }),
+ QJsonArray {{ QJsonArray { json } }});
+ QCOMPARE(QJsonArray::fromVariantList(QVariantList { variantFromJsonObject }),
+ QJsonArray { object });
+
+ // QJsonArray to variant
+ QCOMPARE(QJsonArray { json }.toVariantList(), QVariantList { jsonToVariant });
+ // variant to QJsonArray
+ QCOMPARE(QVariant(QJsonArray { json }).toJsonArray(), QJsonArray { json });
+ }
+
+ // QJsonObject <> QVariantMap
+ {
+ QCOMPARE(QJsonObject::fromVariantMap(QVariantMap { { "foo", variant } }), object);
+
+ // test the same for QVariantMap from QJsonValue/QJsonArray/QJsonObject
+ QCOMPARE(QJsonObject::fromVariantMap(QVariantMap { { "foo", variantFromJson } }), object);
+
+ QJsonObject nestedArray { QPair<QString, QJsonArray>("bar", QJsonArray { json }) };
+ QJsonObject nestedObject { QPair<QString, QJsonObject>("bar", object) };
+ QCOMPARE(QJsonObject::fromVariantMap(QVariantMap { { "bar", variantFromJsonArray } }),
+ nestedArray);
+ QCOMPARE(QJsonObject::fromVariantMap(QVariantMap { { "bar", variantFromJsonObject } }),
+ nestedObject);
+
+ // QJsonObject to variant
+ QCOMPARE(object.toVariantMap(), QVariantMap({ { "foo", jsonToVariant } }));
+ // variant to QJsonObject
+ QCOMPARE(QVariant(object).toJsonObject(), object);
+ }
+}
+
+void tst_QtJson::testIteratorComparison()
+{
+ QJsonObject t = QJsonObject::fromVariantHash({
+ { QStringLiteral("a"), QVariant(12) },
+ { QStringLiteral("b"), QVariant(13) }
+ });
+
+ QVERIFY(t.begin() == t.begin());
+ QVERIFY(t.begin() <= t.begin());
+ QVERIFY(t.begin() >= t.begin());
+ QVERIFY(!(t.begin() != t.begin()));
+ QVERIFY(!(t.begin() < t.begin()));
+ QVERIFY(!(t.begin() > t.begin()));
+
+ QVERIFY(!(t.begin() == t.end()));
+ QVERIFY(t.begin() <= t.end());
+ QVERIFY(!(t.begin() >= t.end()));
+ QVERIFY(t.begin() != t.end());
+ QVERIFY(t.begin() < t.end());
+ QVERIFY(!(t.begin() > t.end()));
+
+ QVERIFY(!(t.end() == t.begin()));
+ QVERIFY(!(t.end() <= t.begin()));
+ QVERIFY(t.end() >= t.begin());
+ QVERIFY(t.end() != t.begin());
+ QVERIFY(!(t.end() < t.begin()));
+ QVERIFY(t.end() > t.begin());
+}
+
+void tst_QtJson::noLeakOnNameClash_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QByteArray>("result");
+ QTest::addRow("simple")
+ << QStringLiteral("simple.duplicates.json")
+ << QByteArray(R"({"": 0})");
+ QTest::addRow("test")
+ << QStringLiteral("test.duplicates.json")
+ << QByteArray(R"([
+ "JSON Test Pattern pass1", {"a": ["array with 1 element"]}, {}, [], -42, true,
+ false, null, {"a": "A key can be any string"}, 0.5, 98.6, 99.44, 1066, 10, 1,
+ 0.1, 1, 2, 2, "rosebud", {"a": "bar"}, {"a": {"a": 2000}}, {"a": {"a": 2000}},
+ {"a": {"a": 2000}}, {"a": {"a": 2000}}
+ ])");
+ QTest::addRow("test3")
+ << QStringLiteral("test3.duplicates.json")
+ << QByteArray(R"({"a": [{"a": "212 555-1234"}, {"a": "646 555-4567"}]})");
+}
+
+void tst_QtJson::noLeakOnNameClash()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, result);
+
+ QFile file(testDataDir + u'/' + fileName);
+ QVERIFY(file.open(QFile::ReadOnly));
+ QByteArray testJson = file.readAll();
+ QVERIFY(!testJson.isEmpty());
+
+ QJsonParseError error;
+
+ // Retains the last one of each set of duplicate keys.
+ QJsonDocument doc = QJsonDocument::fromJson(testJson, &error);
+ QVERIFY2(!doc.isNull(), qPrintable(error.errorString()));
+ QJsonDocument expected = QJsonDocument::fromJson(result, &error);
+ QVERIFY2(!expected.isNull(), qPrintable(error.errorString()));
+
+ QCOMPARE(doc, expected);
+ QT_TEST_EQUALITY_OPS(doc, expected, true);
+
+ // It should not leak.
+ // In particular it should not forget to deref the container for the inner objects.
+}
+
QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc"