summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-11-11 15:24:30 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-02-15 17:00:03 -0800
commit9b8f064cd36e014ecb3e6b60e2190b74f69aee5a (patch)
treebce6128e99adef3c51307b9f655d670d3e7b7a8a /tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
parent3c7b507d1c0f9d1fd645ff5244391f9e4aab51eb (diff)
QCborValueRef: fix using operator[] to convert an empty array to map
The flag IsContainer was not set, causing the QCborContainerPrivate to become confused. This commit also expands and subsumes the existing test for QCborValue (non-Ref). Change-Id: I5e52dc5b093c43a3b678fffd16b6a17c6f4a0676 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp')
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp215
1 files changed, 207 insertions, 8 deletions
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
index cb93a701b7..4fd4255b7d 100644
--- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -88,6 +88,12 @@ private slots:
void mapEmptyDetach();
void mapNonEmptyDetach();
void mapSimpleInitializerList();
+ void mapFromArrayLargeIntKey_data() { basics_data(); }
+ void mapFromArrayLargeIntKey();
+ void mapFromArrayNegativeIntKey_data() { basics_data(); }
+ void mapFromArrayNegativeIntKey();
+ void mapFromArrayStringKey_data() { basics_data(); }
+ void mapFromArrayStringKey();
void mapMutation();
void mapMutateWithCopies();
void mapStringValues();
@@ -129,6 +135,14 @@ private slots:
void cborValueRef_data();
void cborValueRef();
+ void cborValueRefMutatingArray_data() { cborValueRef_data(); }
+ void cborValueRefMutatingArray();
+ void cborValueRefMutatingMapIntKey_data() { cborValueRef_data(); }
+ void cborValueRefMutatingMapIntKey();
+ void cborValueRefMutatingMapLatin1StringKey_data() { cborValueRef_data(); }
+ void cborValueRefMutatingMapLatin1StringKey();
+ void cborValueRefMutatingMapStringKey_data() { cborValueRef_data(); }
+ void cborValueRefMutatingMapStringKey();
void datastreamSerialization_data();
void datastreamSerialization();
@@ -912,6 +926,60 @@ void tst_QCborValue::mapSimpleInitializerList()
QCOMPARE(i, m.size());
}
+template <typename T> static void mapFromArray_template(T key)
+{
+ QFETCH(QCborValue::Type, type);
+ QFETCH(QCborValue, v);
+ if (v.isMap())
+ return; // already a map, nothing will happen
+
+ auto ignoreMessage = [type]() {
+ if (type == QCborValue::Array)
+ QTest::ignoreMessage(QtWarningMsg, "Using CBOR array as map forced conversion");
+ };
+
+ // verify forced conversions work
+ // (our only Array row is an empty array, so it doesn't produce the warning)
+ QCborValue v2 = v;
+ QVERIFY(v2[key].isUndefined());
+ QCOMPARE(v2.type(), QCborValue::Map);
+ QCOMPARE(v.type(), type);
+ QCborMap m = v2.toMap();
+ QCOMPARE(m.size(), 1);
+ QCOMPARE(m.begin().key(), QCborValue(key));
+
+ // non-empty array conversions
+ QCborValue va = QCborArray{v};
+ v2 = va;
+ ignoreMessage();
+ QVERIFY(v2[key].isUndefined());
+ QCOMPARE(v2.type(), QCborValue::Map);
+ QCOMPARE(va.type(), QCborValue::Array);
+ m = v2.toMap();
+ QCOMPARE(m.size(), 2);
+ auto it = m.constBegin();
+ QCOMPARE(it.key(), QCborValue(0));
+ QCOMPARE(it.value(), v);
+ ++it;
+ QCOMPARE(it.key(), QCborValue(key));
+ QCOMPARE(it.value(), QCborValue());
+}
+
+void tst_QCborValue::mapFromArrayLargeIntKey()
+{
+ mapFromArray_template(Q_INT64_C(1) << 20);
+}
+
+void tst_QCborValue::mapFromArrayNegativeIntKey()
+{
+ mapFromArray_template(-1);
+}
+
+void tst_QCborValue::mapFromArrayStringKey()
+{
+ mapFromArray_template(QLatin1String("Hello"));
+}
+
void tst_QCborValue::arrayMutation()
{
QCborArray a{42};
@@ -983,14 +1051,6 @@ void tst_QCborValue::arrayMutation()
QVERIFY(val.isArray());
QCOMPARE(val.toArray().size(), 4);
QCOMPARE(val[3], 42);
-
- // Coerce to map on string key:
- const QLatin1String any("any");
- val[any] = any;
- QVERIFY(val.isMap());
- QCOMPARE(val.toMap().size(), 5);
- QVERIFY(val[2].isArray());
- QCOMPARE(val[2].toArray().size(), 5);
}
void tst_QCborValue::arrayMutateWithCopies()
@@ -2657,6 +2717,145 @@ void tst_QCborValue::cborValueRef()
QCOMPARE(ref.toDiagnosticNotation(), v.toDiagnosticNotation());
}
+void tst_QCborValue::cborValueRefMutatingArray()
+{
+ // complements arrayMutation()
+ QFETCH(QCborValue, v);
+
+ {
+ QCborArray origArray = { 123 };
+ QCborArray a = { QCborValue(origArray) };
+ QCborValueRef ref = a[0];
+ QVERIFY(ref.isArray());
+ QVERIFY(!ref.toArray().isEmpty());
+
+ // this will force the array to grow
+ ref[1] = v;
+
+ QCborValue va = a.at(0);
+ QVERIFY(va.isArray());
+ QCOMPARE(va.toArray().size(), 2);
+ QCOMPARE(va.toArray().first(), 123);
+ QCOMPARE(va.toArray().last(), v);
+
+ // ensure the array didn't get modified
+ QCOMPARE(origArray, QCborArray{123});
+ }
+ {
+ QCborArray emptyArray;
+ QCborArray a = { QCborValue(emptyArray) };
+ QCborValueRef ref = a[0];
+ QVERIFY(ref.isArray());
+ QVERIFY(ref.toArray().isEmpty());
+
+ // this will force the array to become non-empty
+ ref[1] = v;
+
+ QCborValue va = a.at(0);
+ QVERIFY(va.isArray());
+ QCOMPARE(va.toArray().size(), 2);
+ QCOMPARE(va.toArray().first(), QCborValue());
+ QCOMPARE(va.toArray().last(), v);
+
+ // ensure the array didn't get modified
+ QCOMPARE(emptyArray, QCborArray());
+ }
+ {
+ QCborArray emptyArray = { 123, 456 };
+ emptyArray.takeFirst();
+ emptyArray.takeFirst();
+ QCborArray a = { QCborValue(emptyArray) };
+ QCborValueRef ref = a[0];
+ QVERIFY(ref.isArray());
+ QVERIFY(ref.toArray().isEmpty());
+
+ // this will force the array to become non-empty
+ ref[1] = v;
+
+ QCborValue va = a.at(0);
+ QVERIFY(va.isArray());
+ QCOMPARE(va.toArray().size(), 2);
+ QCOMPARE(va.toArray().first(), QCborValue());
+ QCOMPARE(va.toArray().last(), v);
+
+ // ensure the array didn't get modified
+ QCOMPARE(emptyArray, QCborArray());
+ }
+}
+
+void tst_QCborValue::cborValueRefMutatingMapIntKey()
+{
+ // complements mapMutation()
+ QFETCH(QCborValue, v);
+ QCborValue::Type type = v.type();
+
+ auto executeTest = [=](qint64 index) {
+ QCborArray a = { v };
+ QCborValueRef ref = a[0];
+
+ if (type == QCborValue::Array && !v.toArray().isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "Using CBOR array as map forced conversion");
+ ref[index] = v;
+
+ QCborValue vm = a.at(0);
+ QVERIFY(vm.isMap());
+ QCOMPARE(vm.toMap()[index].type(), type);
+ QCOMPARE(vm.toMap()[index], v);
+
+ if (type == QCborValue::Array && !v.toArray().isEmpty())
+ QCOMPARE(vm.toMap()[0], v.toArray()[0]);
+ else if (type == QCborValue::Map && !v.toMap().isEmpty())
+ QCOMPARE(vm.toMap()[0], v.toMap()[0]);
+ };
+ // accessing a negative index causes it to become a map
+ executeTest(-1);
+ if (QTest::currentTestFailed())
+ return;
+
+ // if the index is bigger than 0x10000, the array becomes a map
+ executeTest(0x10000);
+ if (QTest::currentTestFailed())
+ return;
+
+ if (type != QCborValue::Array)
+ executeTest(5);
+}
+
+template <typename String> static void cborValueRefMutatingMapStringKey_template(const String &key)
+{
+ // complements mapMutation() too
+ QFETCH(QCborValue, v);
+ QCborValue::Type type = v.type();
+ QCborArray a = { v };
+ QCborValueRef ref = a[0];
+
+ if (type == QCborValue::Array && !v.toArray().isEmpty())
+ QTest::ignoreMessage(QtWarningMsg, "Using CBOR array as map forced conversion");
+
+ // force conversion to map
+ ref[key] = v;
+
+ QCborValue vm = a.at(0);
+ QVERIFY(vm.isMap());
+ QCOMPARE(vm.toMap()[key].type(), type);
+ QCOMPARE(vm.toMap()[key], v);
+
+ if (type == QCborValue::Array && !v.toArray().isEmpty())
+ QCOMPARE(vm.toMap()[0], v.toArray()[0]);
+ else if (type == QCborValue::Map && !v.toMap().isEmpty())
+ QCOMPARE(vm.toMap()[0], v.toMap()[0]);
+}
+
+void tst_QCborValue::cborValueRefMutatingMapLatin1StringKey()
+{
+ cborValueRefMutatingMapStringKey_template(QLatin1String("other"));
+}
+
+void tst_QCborValue::cborValueRefMutatingMapStringKey()
+{
+ cborValueRefMutatingMapStringKey_template(QString("other"));
+}
+
void tst_QCborValue::datastreamSerialization_data()
{
addCommonCborData();