summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp')
-rw-r--r--tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
new file mode 100644
index 0000000000..56245a7173
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcborvalue.h>
+#include <QtTest>
+
+Q_DECLARE_METATYPE(QCborValue)
+
+class tst_QCborValue_Json : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void toVariant_data();
+ void toVariant();
+ void toJson_data() { toVariant_data(); }
+ void toJson();
+ void taggedByteArrayToJson_data();
+ void taggedByteArrayToJson();
+
+ void fromVariant_data() { toVariant_data(); }
+ void fromVariant();
+ void fromJson_data();
+ void fromJson();
+
+ void nonStringKeysInMaps_data();
+ void nonStringKeysInMaps();
+};
+
+void tst_QCborValue_Json::toVariant_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QJsonValue>("json");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](const QCborValue &v, const QVariant &exp, const QJsonValue &json) {
+ auto addRow = [=]() -> QTestData & {
+ const char *typeString = me.valueToKey(v.type());
+ if (v.type() == QCborValue::Integer)
+ return QTest::addRow("Integer:%lld", exp.toLongLong());
+ if (v.type() == QCborValue::Double)
+ return QTest::addRow("Double:%g", exp.toDouble());
+ if (v.type() == QCborValue::ByteArray || v.type() == QCborValue::String)
+ return QTest::addRow("%s:%d", typeString, exp.toString().size());
+ if (v.type() >= 0x10000)
+ return QTest::newRow(exp.typeName());
+ return QTest::newRow(typeString);
+ };
+ addRow() << v << exp << json;
+ };
+
+ // good JSON matching:
+ add(QCborValue(), QVariant(), QJsonValue::Undefined);
+ add(nullptr, QVariant::fromValue(nullptr), QJsonValue::Null);
+ add(false, false, false);
+ add(true, true, true);
+ add(0, 0, 0);
+ add(1, 1, 1);
+ add(-1, -1, -1);
+ add(0., 0., 0.);
+ add(1.25, 1.25, 1.25);
+ add(-1.25, -1.25, -1.25);
+ add("Hello", "Hello", "Hello");
+
+ // converts to string in JSON:
+ add(QByteArray("Hello"), QByteArray("Hello"), "SGVsbG8");
+ add(QCborValue(dt), dt, dt.toString(Qt::ISODateWithMs));
+ add(QCborValue(QUrl("http://example.com/{q}")), QUrl("http://example.com/{q}"),
+ "http://example.com/%7Bq%7D"); // note the encoded form in JSON
+ add(QCborValue(QRegularExpression(".")), QRegularExpression("."), ".");
+ add(QCborValue(uuid), uuid, uuid.toString(QUuid::WithoutBraces));
+
+ // not valid in JSON
+ QTest::newRow("simpletype") << QCborValue(QCborSimpleType(255))
+ << QVariant::fromValue(QCborSimpleType(255))
+ << QJsonValue("simple(255)");
+ QTest::newRow("Double:inf") << QCborValue(qInf())
+ << QVariant(qInf())
+ << QJsonValue();
+ QTest::newRow("Double:-inf") << QCborValue(-qInf())
+ << QVariant(-qInf())
+ << QJsonValue();
+ QTest::newRow("Double:nan") << QCborValue(qQNaN())
+ << QVariant(qQNaN())
+ << QJsonValue();
+
+ // large integral values lose precision in JSON
+ QTest::newRow("Integer:max") << QCborValue(std::numeric_limits<qint64>::max())
+ << QVariant(std::numeric_limits<qint64>::max())
+ << QJsonValue(std::numeric_limits<qint64>::max());
+ QTest::newRow("Integer:min") << QCborValue(std::numeric_limits<qint64>::min())
+ << QVariant(std::numeric_limits<qint64>::min())
+ << QJsonValue(std::numeric_limits<qint64>::min());
+
+ // empty arrays and maps
+ add(QCborArray(), QVariantList(), QJsonArray());
+ add(QCborMap(), QVariantMap(), QJsonObject());
+}
+
+void tst_QCborValue_Json::toVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ if (qIsNaN(variant.toDouble())) {
+ // because NaN != NaN, QVariant(NaN) != QVariant(NaN), so we
+ // only need to compare the classification
+ QVERIFY(qIsNaN(v.toVariant().toDouble()));
+
+ // the rest of this function depends on the variant comparison
+ return;
+ }
+
+ QCOMPARE(v.toVariant(), variant);
+ if (variant.isValid()) {
+ QVariant variant2 = QVariant::fromValue(v);
+ QVERIFY(variant2.canConvert(variant.userType()));
+ QVERIFY(variant2.convert(variant.userType()));
+ QCOMPARE(variant2, variant);
+ }
+
+ // tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toVariant(), variant);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toVariantList(), QVariantList({variant}));
+ QCOMPARE(QCborArray({v, v}).toVariantList(), QVariantList({variant, variant}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantMap(), QVariantMap({{"foo", variant}}));
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantHash(), QVariantHash({{"foo", variant}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toVariantList(),
+ QVariantList{QVariantMap({{"foo", variant}})});
+}
+
+void tst_QCborValue_Json::toJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QVariant::fromValue(v).toJsonValue(), json);
+
+ // most tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toJsonValue(), json);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+ QCOMPARE(QCborArray({v, v}).toJsonArray(), QJsonArray({json, json}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toJsonObject(), QJsonObject({{"foo", json}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toJsonArray(),
+ QJsonArray{QJsonObject({{"foo", json}})});
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << QJsonValue("_wE");
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << QJsonValue("/wE=");
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << QJsonValue("ff01");
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+}
+
+void tst_QCborValue_Json::fromVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ QCOMPARE(QCborValue::fromVariant(variant), v);
+ QCOMPARE(variant.value<QCborValue>(), v);
+
+ // try arrays
+ QCOMPARE(QCborArray::fromVariantList({variant}), QCborArray{v});
+ QCOMPARE(QCborArray::fromVariantList({variant, variant}), QCborArray({v, v}));
+
+ if (variant.type() == QVariant::String) {
+ QString s = variant.toString();
+ QCOMPARE(QCborArray::fromStringList({s}), QCborArray{v});
+ QCOMPARE(QCborArray::fromStringList({s, s}), QCborArray({v, v}));
+ }
+
+ // maps...
+ QVariantMap map{{"foo", variant}};
+ QCOMPARE(QCborMap::fromVariantMap(map), QCborMap({{"foo", v}}));
+ QCOMPARE(QCborMap::fromVariantHash({{"foo", variant}}), QCborMap({{"foo", v}}));
+
+ // nested
+ QVariantMap outer{{"bar", QVariantList{0, map, true}}};
+ QCOMPARE(QCborMap::fromVariantMap(outer),
+ QCborMap({{"bar", QCborArray{0, QCborMap{{"foo", v}}, true}}}));
+}
+
+void tst_QCborValue_Json::fromJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QTest::newRow("null") << QCborValue(QCborValue::Null) << QJsonValue(QJsonValue::Null);
+ QTest::newRow("false") << QCborValue(false) << QJsonValue(false);
+ QTest::newRow("true") << QCborValue(true) << QJsonValue(true);
+ QTest::newRow("0") << QCborValue(0) << QJsonValue(0.);
+ QTest::newRow("1") << QCborValue(1) << QJsonValue(1);
+ QTest::newRow("1.5") << QCborValue(1.5) << QJsonValue(1.5);
+ QTest::newRow("string") << QCborValue("Hello") << QJsonValue("Hello");
+ QTest::newRow("array") << QCborValue(QCborValue::Array) << QJsonValue(QJsonValue::Array);
+ QTest::newRow("map") << QCborValue(QCborValue::Map) << QJsonValue(QJsonValue::Object);
+}
+
+void tst_QCborValue_Json::fromJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(QCborValue::fromJsonValue(json), v);
+ QCOMPARE(QVariant(json).value<QCborValue>(), v);
+ QCOMPARE(QCborArray::fromJsonArray({json}), QCborArray({v}));
+ QCOMPARE(QCborArray::fromJsonArray({json, json}), QCborArray({v, v}));
+ QCOMPARE(QCborMap::fromJsonObject({{"foo", json}}), QCborMap({{"foo", v}}));
+
+ // confirm we can roundtrip back to JSON
+ QCOMPARE(QCborValue::fromJsonValue(json).toJsonValue(), json);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps_data()
+{
+ QTest::addColumn<QCborValue>("key");
+ QTest::addColumn<QString>("converted");
+
+ auto add = [](const char *str, const QCborValue &v) {
+ QTest::newRow(str) << v << str;
+ };
+ add("0", 0);
+ add("-1", -1);
+ add("false", false);
+ add("true", true);
+ add("null", nullptr);
+ add("undefined", {}); // should this be ""?
+ add("simple(255)", QCborSimpleType(255));
+ add("2.5", 2.5);
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("bytearray") << QCborValue(data) << "_wE";
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << "_wE";
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << "/wE=";
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << "ff01";
+
+ QTest::newRow("emptyarray") << QCborValue(QCborValue::Array) << "[]";
+ QTest::newRow("emptymap") << QCborValue(QCborValue::Map) << "{}";
+ QTest::newRow("array") << QCborValue(QCborArray{1, true, 2.5, "Hello"})
+ << "[1, true, 2.5, \"Hello\"]";
+ QTest::newRow("map") << QCborValue(QCborMap{{"Hello", 0}, {0, "Hello"}})
+ << "{\"Hello\": 0, 0: \"Hello\"}";
+
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUrl url("https://example.com");
+ QUuid uuid = QUuid::createUuid();
+ QTest::newRow("QDateTime") << QCborValue(dt) << dt.toString(Qt::ISODateWithMs);
+ QTest::newRow("QUrl") << QCborValue(url) << url.toString(QUrl::FullyEncoded);
+ QTest::newRow("QRegularExpression") << QCborValue(QRegularExpression(".*")) << ".*";
+ QTest::newRow("QUuid") << QCborValue(uuid) << uuid.toString(QUuid::WithoutBraces);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps()
+{
+ QFETCH(QCborValue, key);
+ QFETCH(QString, converted);
+
+ QCborMap m;
+ m.insert(key, 0);
+
+ {
+ QVariantMap vm = m.toVariantMap();
+ auto it = vm.begin();
+ QVERIFY(it != vm.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, vm.end());
+ }
+
+ {
+ QJsonObject o = m.toJsonObject();
+ auto it = o.begin();
+ QVERIFY(it != o.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, o.end());
+ }
+}
+
+QTEST_MAIN(tst_QCborValue_Json)
+
+#include "tst_qcborvalue_json.moc"