Improved coverage of JsonObject

This commit is contained in:
Benoit Blanchon
2020-02-22 14:17:10 +01:00
parent af0edecddb
commit a471aed6db
5 changed files with 60 additions and 36 deletions

View File

@ -15,8 +15,9 @@ TEST_CASE("JsonObject::set()") {
SECTION("doesn't copy static string in key or value") { SECTION("doesn't copy static string in key or value") {
obj1["hello"] = "world"; obj1["hello"] = "world";
obj2.set(obj1); bool success = obj2.set(obj1);
REQUIRE(success == true);
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
@ -24,8 +25,9 @@ TEST_CASE("JsonObject::set()") {
SECTION("copy local string value") { SECTION("copy local string value") {
obj1["hello"] = std::string("world"); obj1["hello"] = std::string("world");
obj2.set(obj1); bool success = obj2.set(obj1);
REQUIRE(success == true);
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
@ -33,8 +35,9 @@ TEST_CASE("JsonObject::set()") {
SECTION("copy local key") { SECTION("copy local key") {
obj1[std::string("hello")] = "world"; obj1[std::string("hello")] = "world";
obj2.set(obj1); bool success = obj2.set(obj1);
REQUIRE(success == true);
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
@ -42,8 +45,9 @@ TEST_CASE("JsonObject::set()") {
SECTION("copy string from deserializeJson()") { SECTION("copy string from deserializeJson()") {
deserializeJson(doc1, "{'hello':'world'}"); deserializeJson(doc1, "{'hello':'world'}");
obj2.set(obj1); bool success = obj2.set(obj1);
REQUIRE(success == true);
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
@ -51,8 +55,9 @@ TEST_CASE("JsonObject::set()") {
SECTION("copy string from deserializeMsgPack()") { SECTION("copy string from deserializeMsgPack()") {
deserializeMsgPack(doc1, "\x81\xA5hello\xA5world"); deserializeMsgPack(doc1, "\x81\xA5hello\xA5world");
obj2.set(obj1); bool success = obj2.set(obj1);
REQUIRE(success == true);
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
@ -65,4 +70,28 @@ TEST_CASE("JsonObject::set()") {
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
REQUIRE(obj2["hello"] == std::string("world")); REQUIRE(obj2["hello"] == std::string("world"));
} }
SECTION("destination too small to store the key") {
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc3;
JsonObject obj3 = doc3.to<JsonObject>();
obj1[std::string("hello")] = "world";
bool success = obj3.set(obj1);
REQUIRE(success == false);
REQUIRE(doc3.as<std::string>() == "{}");
}
SECTION("destination too small to store the value") {
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc3;
JsonObject obj3 = doc3.to<JsonObject>();
obj1["hello"] = std::string("world");
bool success = obj3.set(obj1);
REQUIRE(success == false);
REQUIRE(doc3.as<std::string>() == "{\"hello\":null}");
}
} }

View File

@ -34,8 +34,10 @@ template <typename TAdaptedString>
inline VariantData* CollectionData::addMember(TAdaptedString key, inline VariantData* CollectionData::addMember(TAdaptedString key,
MemoryPool* pool) { MemoryPool* pool) {
VariantSlot* slot = addSlot(pool); VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) if (!slotSetKey(slot, key, pool)) {
removeSlot(slot);
return 0; return 0;
}
return slot->data(); return slot->data();
} }
@ -132,8 +134,16 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const {
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
MemoryPool* pool) { MemoryPool* pool) {
// ignore null key
if (key.isNull())
return 0;
// search a matching key
VariantSlot* slot = getSlot(key); VariantSlot* slot = getSlot(key);
return slot ? slot->data() : addMember(key, pool); if (slot)
return slot->data();
return addMember(key, pool);
} }
inline VariantData* CollectionData::getElement(size_t index) const { inline VariantData* CollectionData::getElement(size_t index) const {

View File

@ -25,7 +25,8 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { inline VariantData *objectGetMember(const CollectionData *obj,
TAdaptedString key) {
if (!obj) if (!obj)
return 0; return 0;
return obj->getMember(key); return obj->getMember(key);
@ -39,20 +40,11 @@ void objectRemove(CollectionData *obj, TAdaptedString key) {
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, inline VariantData *objectGetOrAddMember(CollectionData *obj,
MemoryPool *pool) { TAdaptedString key, MemoryPool *pool) {
if (!obj) if (!obj)
return 0; return 0;
// ignore null key return obj->getOrAddMember(key, pool);
if (key.isNull())
return 0;
// search a matching key
VariantData *var = obj->getMember(key);
if (var)
return var;
return obj->addMember(key, pool);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -129,7 +129,7 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
private: private:
template <typename TAdaptedString> template <typename TAdaptedString>
FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
return VariantConstRef(objectGet(_data, key)); return VariantConstRef(objectGetMember(_data, key));
} }
}; };
@ -180,7 +180,7 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
// getMember(const String&) const // getMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getMember(const TString& key) const { FORCE_INLINE VariantRef getMember(const TString& key) const {
return get_impl(adaptString(key)); return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
} }
// getMember(char*) const // getMember(char*) const
@ -188,14 +188,15 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
// getMember(const __FlashStringHelper*) const // getMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar* key) const { FORCE_INLINE VariantRef getMember(TChar* key) const {
return get_impl(adaptString(key)); return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
} }
// getOrAddMember(const std::string&) const // getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const // getOrAddMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString& key) const { FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
return getOrCreate_impl(adaptString(key)); return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool));
} }
// getOrAddMember(char*) const // getOrAddMember(char*) const
@ -203,7 +204,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
// getOrAddMember(const __FlashStringHelper*) const // getOrAddMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar* key) const { FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
return getOrCreate_impl(adaptString(key)); return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool));
} }
FORCE_INLINE bool operator==(ObjectRef rhs) const { FORCE_INLINE bool operator==(ObjectRef rhs) const {
@ -232,16 +234,6 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
} }
private: private:
template <typename TAdaptedString>
FORCE_INLINE VariantRef get_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGet(_data, key));
}
template <typename TAdaptedString>
FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGetOrCreate(_data, key, _pool));
}
MemoryPool* _pool; MemoryPool* _pool;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -384,7 +384,8 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
// getMember(const String&) const // getMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantConstRef getMember(const TString &key) const { FORCE_INLINE VariantConstRef getMember(const TString &key) const {
return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key))); return VariantConstRef(
objectGetMember(variantAsObject(_data), adaptString(key)));
} }
// getMember(char*) const // getMember(char*) const