From 08cac13c43dd3554f2d10124a7183d4f9fe9f1ec Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 8 Jan 2024 18:48:11 +0100 Subject: [PATCH] Add more tests for `JsonObjectConst` --- extras/tests/CMakeLists.txt | 1 + extras/tests/JsonObject/containsKey.cpp | 6 -- extras/tests/JsonObject/equals.cpp | 8 --- extras/tests/JsonObject/isNull.cpp | 26 -------- extras/tests/JsonObject/iterator.cpp | 37 ----------- extras/tests/JsonObject/subscript.cpp | 10 --- extras/tests/JsonObjectConst/CMakeLists.txt | 20 ++++++ extras/tests/JsonObjectConst/containsKey.cpp | 32 ++++++++++ extras/tests/JsonObjectConst/equals.cpp | 65 ++++++++++++++++++++ extras/tests/JsonObjectConst/isNull.cpp | 32 ++++++++++ extras/tests/JsonObjectConst/iterator.cpp | 39 ++++++++++++ extras/tests/JsonObjectConst/nesting.cpp | 35 +++++++++++ extras/tests/JsonObjectConst/size.cpp | 22 +++++++ extras/tests/JsonObjectConst/subscript.cpp | 33 ++++++++++ src/ArduinoJson/Object/JsonObjectConst.hpp | 4 +- 15 files changed, 281 insertions(+), 89 deletions(-) create mode 100644 extras/tests/JsonObjectConst/CMakeLists.txt create mode 100644 extras/tests/JsonObjectConst/containsKey.cpp create mode 100644 extras/tests/JsonObjectConst/equals.cpp create mode 100644 extras/tests/JsonObjectConst/isNull.cpp create mode 100644 extras/tests/JsonObjectConst/iterator.cpp create mode 100644 extras/tests/JsonObjectConst/nesting.cpp create mode 100644 extras/tests/JsonObjectConst/size.cpp create mode 100644 extras/tests/JsonObjectConst/subscript.cpp diff --git a/extras/tests/CMakeLists.txt b/extras/tests/CMakeLists.txt index d413deee..b4d86ac1 100644 --- a/extras/tests/CMakeLists.txt +++ b/extras/tests/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(JsonArray) add_subdirectory(JsonDeserializer) add_subdirectory(JsonDocument) add_subdirectory(JsonObject) +add_subdirectory(JsonObjectConst) add_subdirectory(JsonSerializer) add_subdirectory(JsonVariant) add_subdirectory(ResourceManager) diff --git a/extras/tests/JsonObject/containsKey.cpp b/extras/tests/JsonObject/containsKey.cpp index 135871f7..a5e20e95 100644 --- a/extras/tests/JsonObject/containsKey.cpp +++ b/extras/tests/JsonObject/containsKey.cpp @@ -15,12 +15,6 @@ TEST_CASE("JsonObject::containsKey()") { REQUIRE(true == obj.containsKey("hello")); } - SECTION("works with JsonObjectConst") { - JsonObjectConst cobj = obj; - REQUIRE(false == cobj.containsKey("world")); - REQUIRE(true == cobj.containsKey("hello")); - } - SECTION("returns false after remove()") { obj.remove("hello"); diff --git a/extras/tests/JsonObject/equals.cpp b/extras/tests/JsonObject/equals.cpp index 9f2427b3..0ec46737 100644 --- a/extras/tests/JsonObject/equals.cpp +++ b/extras/tests/JsonObject/equals.cpp @@ -8,18 +8,15 @@ TEST_CASE("JsonObject::operator==()") { JsonDocument doc1; JsonObject obj1 = doc1.to(); - JsonObjectConst obj1c = obj1; JsonDocument doc2; JsonObject obj2 = doc2.to(); - JsonObjectConst obj2c = obj2; SECTION("should return false when objs differ") { obj1["hello"] = "coucou"; obj2["world"] = 1; REQUIRE_FALSE(obj1 == obj2); - REQUIRE_FALSE(obj1c == obj2c); } SECTION("should return false when LHS has more elements") { @@ -28,7 +25,6 @@ TEST_CASE("JsonObject::operator==()") { obj2["hello"] = "coucou"; REQUIRE_FALSE(obj1 == obj2); - REQUIRE_FALSE(obj1c == obj2c); } SECTION("should return false when RKS has more elements") { @@ -37,7 +33,6 @@ TEST_CASE("JsonObject::operator==()") { obj2["world"] = 666; REQUIRE_FALSE(obj1 == obj2); - REQUIRE_FALSE(obj1c == obj2c); } SECTION("should return true when objs equal") { @@ -48,20 +43,17 @@ TEST_CASE("JsonObject::operator==()") { obj2["hello"] = "world"; REQUIRE(obj1 == obj2); - REQUIRE(obj1c == obj2c); } SECTION("should return false when RHS is null") { JsonObject null; REQUIRE_FALSE(obj1 == null); - REQUIRE_FALSE(obj1c == null); } SECTION("should return false when LHS is null") { JsonObject null; REQUIRE_FALSE(null == obj2); - REQUIRE_FALSE(null == obj2c); } } diff --git a/extras/tests/JsonObject/isNull.cpp b/extras/tests/JsonObject/isNull.cpp index e98e4b4b..51f7880a 100644 --- a/extras/tests/JsonObject/isNull.cpp +++ b/extras/tests/JsonObject/isNull.cpp @@ -18,19 +18,6 @@ TEST_CASE("JsonObject::isNull()") { } } -TEST_CASE("JsonObjectConst::isNull()") { - SECTION("returns true") { - JsonObjectConst obj; - REQUIRE(obj.isNull() == true); - } - - SECTION("returns false") { - JsonDocument doc; - JsonObjectConst obj = doc.to(); - REQUIRE(obj.isNull() == false); - } -} - TEST_CASE("JsonObject::operator bool()") { SECTION("returns false") { JsonObject obj; @@ -43,16 +30,3 @@ TEST_CASE("JsonObject::operator bool()") { REQUIRE(static_cast(obj) == true); } } - -TEST_CASE("JsonObjectConst::operator bool()") { - SECTION("returns false") { - JsonObjectConst obj; - REQUIRE(static_cast(obj) == false); - } - - SECTION("returns true") { - JsonDocument doc; - JsonObjectConst obj = doc.to(); - REQUIRE(static_cast(obj) == true); - } -} diff --git a/extras/tests/JsonObject/iterator.cpp b/extras/tests/JsonObject/iterator.cpp index 79796c79..4918d275 100644 --- a/extras/tests/JsonObject/iterator.cpp +++ b/extras/tests/JsonObject/iterator.cpp @@ -5,8 +5,6 @@ #include #include -using namespace Catch::Matchers; - TEST_CASE("JsonObject::begin()/end()") { JsonDocument doc; JsonObject obj = doc.to(); @@ -36,38 +34,3 @@ TEST_CASE("JsonObject::begin()/end()") { REQUIRE(null.begin() == null.end()); } } - -TEST_CASE("JsonObjectConst::begin()/end()") { - JsonDocument doc; - JsonObject obj = doc.to(); - obj["ab"] = 12; - obj["cd"] = 34; - - JsonObjectConst cobj = obj; - - SECTION("Iteration") { - JsonObjectConst::iterator it = cobj.begin(); - REQUIRE(cobj.end() != it); - REQUIRE(it->key() == "ab"); - REQUIRE(12 == it->value()); - - ++it; - REQUIRE(cobj.end() != it); - JsonPairConst pair = *it; - REQUIRE(pair.key() == "cd"); - REQUIRE(34 == pair.value()); - - ++it; - REQUIRE(cobj.end() == it); - } - - SECTION("Dereferencing end() is safe") { - REQUIRE(cobj.end()->key().isNull()); - REQUIRE(cobj.end()->value().isNull()); - } - - SECTION("null JsonObjectConst") { - JsonObjectConst null; - REQUIRE(null.begin() == null.end()); - } -} diff --git a/extras/tests/JsonObject/subscript.cpp b/extras/tests/JsonObject/subscript.cpp index adc05e89..2f8c95f9 100644 --- a/extras/tests/JsonObject/subscript.cpp +++ b/extras/tests/JsonObject/subscript.cpp @@ -7,8 +7,6 @@ #include "Allocators.hpp" -using ArduinoJson::detail::sizeofObject; - TEST_CASE("JsonObject::operator[]") { SpyingAllocator spy; JsonDocument doc(&spy); @@ -252,11 +250,3 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(false == obj["hello"]["world"].is()); } } - -TEST_CASE("JsonObjectConst::operator[]") { - JsonDocument doc; - doc["hello"] = "world"; - JsonObjectConst obj = doc.as(); - - REQUIRE(obj["hello"] == "world"); // issue #2019 -} diff --git a/extras/tests/JsonObjectConst/CMakeLists.txt b/extras/tests/JsonObjectConst/CMakeLists.txt new file mode 100644 index 00000000..dadb910e --- /dev/null +++ b/extras/tests/JsonObjectConst/CMakeLists.txt @@ -0,0 +1,20 @@ +# ArduinoJson - https://arduinojson.org +# Copyright © 2014-2024, Benoit BLANCHON +# MIT License + +add_executable(JsonObjectConstTests + containsKey.cpp + equals.cpp + isNull.cpp + iterator.cpp + nesting.cpp + size.cpp + subscript.cpp +) + +add_test(JsonObjectConst JsonObjectConstTests) + +set_tests_properties(JsonObjectConst + PROPERTIES + LABELS "Catch" +) diff --git a/extras/tests/JsonObjectConst/containsKey.cpp b/extras/tests/JsonObjectConst/containsKey.cpp new file mode 100644 index 00000000..3b639417 --- /dev/null +++ b/extras/tests/JsonObjectConst/containsKey.cpp @@ -0,0 +1,32 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +TEST_CASE("JsonObjectConst::containsKey()") { + JsonDocument doc; + doc["hello"] = 42; + auto obj = doc.as(); + + SECTION("supports const char*") { + REQUIRE(false == obj.containsKey("world")); + REQUIRE(true == obj.containsKey("hello")); + } + + SECTION("supports std::string") { + REQUIRE(false == obj.containsKey(std::string("world"))); + REQUIRE(true == obj.containsKey(std::string("hello"))); + } + +#ifdef HAS_VARIABLE_LENGTH_ARRAY + SECTION("supports VLA") { + size_t i = 16; + char vla[i]; + strcpy(vla, "hello"); + + REQUIRE(true == obj.containsKey(vla)); + } +#endif +} diff --git a/extras/tests/JsonObjectConst/equals.cpp b/extras/tests/JsonObjectConst/equals.cpp new file mode 100644 index 00000000..0efa3cf9 --- /dev/null +++ b/extras/tests/JsonObjectConst/equals.cpp @@ -0,0 +1,65 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +TEST_CASE("JsonObjectConst::operator==()") { + JsonDocument doc1; + JsonObjectConst obj1 = doc1.to(); + + JsonDocument doc2; + JsonObjectConst obj2 = doc2.to(); + + SECTION("should return false when objs differ") { + doc1["hello"] = "coucou"; + doc2["world"] = 1; + + REQUIRE_FALSE(obj1 == obj2); + } + + SECTION("should return false when LHS has more elements") { + doc1["hello"] = "coucou"; + doc1["world"] = 666; + doc2["hello"] = "coucou"; + + REQUIRE_FALSE(obj1 == obj2); + } + + SECTION("should return false when RKS has more elements") { + doc1["hello"] = "coucou"; + doc2["hello"] = "coucou"; + doc2["world"] = 666; + + REQUIRE_FALSE(obj1 == obj2); + } + + SECTION("should return true when objs equal") { + doc1["hello"] = "world"; + doc1["anwser"] = 42; + // insert in different order + doc2["anwser"] = 42; + doc2["hello"] = "world"; + + REQUIRE(obj1 == obj2); + } + + SECTION("should return false when RHS is null") { + JsonObjectConst null; + + REQUIRE_FALSE(obj1 == null); + } + + SECTION("should return false when LHS is null") { + JsonObjectConst null; + + REQUIRE_FALSE(null == obj2); + } + + SECTION("should return true when both are null") { + JsonObjectConst null1, null2; + + REQUIRE(null1 == null2); + } +} diff --git a/extras/tests/JsonObjectConst/isNull.cpp b/extras/tests/JsonObjectConst/isNull.cpp new file mode 100644 index 00000000..c689cce5 --- /dev/null +++ b/extras/tests/JsonObjectConst/isNull.cpp @@ -0,0 +1,32 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +TEST_CASE("JsonObjectConst::isNull()") { + SECTION("returns true") { + JsonObjectConst obj; + REQUIRE(obj.isNull() == true); + } + + SECTION("returns false") { + JsonDocument doc; + JsonObjectConst obj = doc.to(); + REQUIRE(obj.isNull() == false); + } +} + +TEST_CASE("JsonObjectConst::operator bool()") { + SECTION("returns false") { + JsonObjectConst obj; + REQUIRE(static_cast(obj) == false); + } + + SECTION("returns true") { + JsonDocument doc; + JsonObjectConst obj = doc.to(); + REQUIRE(static_cast(obj) == true); + } +} diff --git a/extras/tests/JsonObjectConst/iterator.cpp b/extras/tests/JsonObjectConst/iterator.cpp new file mode 100644 index 00000000..0ad911ef --- /dev/null +++ b/extras/tests/JsonObjectConst/iterator.cpp @@ -0,0 +1,39 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +TEST_CASE("JsonObjectConst::begin()/end()") { + JsonDocument doc; + JsonObjectConst obj = doc.to(); + doc["ab"] = 12; + doc["cd"] = 34; + + SECTION("Iteration") { + JsonObjectConst::iterator it = obj.begin(); + REQUIRE(obj.end() != it); + REQUIRE(it->key() == "ab"); + REQUIRE(12 == it->value()); + + ++it; + REQUIRE(obj.end() != it); + JsonPairConst pair = *it; + REQUIRE(pair.key() == "cd"); + REQUIRE(34 == pair.value()); + + ++it; + REQUIRE(obj.end() == it); + } + + SECTION("Dereferencing end() is safe") { + REQUIRE(obj.end()->key().isNull()); + REQUIRE(obj.end()->value().isNull()); + } + + SECTION("null JsonObjectConst") { + JsonObjectConst null; + REQUIRE(null.begin() == null.end()); + } +} diff --git a/extras/tests/JsonObjectConst/nesting.cpp b/extras/tests/JsonObjectConst/nesting.cpp new file mode 100644 index 00000000..7bddd8f5 --- /dev/null +++ b/extras/tests/JsonObjectConst/nesting.cpp @@ -0,0 +1,35 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +TEST_CASE("JsonObjectConst::nesting()") { + JsonDocument doc; + JsonObjectConst obj = doc.to(); + + SECTION("return 0 if unbound") { + JsonObjectConst unbound; + REQUIRE(unbound.nesting() == 0); + } + + SECTION("returns 1 for empty object") { + REQUIRE(obj.nesting() == 1); + } + + SECTION("returns 1 for flat object") { + doc["hello"] = "world"; + REQUIRE(obj.nesting() == 1); + } + + SECTION("returns 2 with nested array") { + doc["nested"].to(); + REQUIRE(obj.nesting() == 2); + } + + SECTION("returns 2 with nested object") { + doc["nested"].to(); + REQUIRE(obj.nesting() == 2); + } +} diff --git a/extras/tests/JsonObjectConst/size.cpp b/extras/tests/JsonObjectConst/size.cpp new file mode 100644 index 00000000..25de11a4 --- /dev/null +++ b/extras/tests/JsonObjectConst/size.cpp @@ -0,0 +1,22 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include +#include + +TEST_CASE("JsonObjectConst::size()") { + JsonDocument doc; + JsonObjectConst obj = doc.to(); + + SECTION("returns 0 when empty") { + REQUIRE(0 == obj.size()); + } + + SECTION("returns the number of members") { + doc["hello"] = 1; + doc["world"] = 2; + REQUIRE(2 == obj.size()); + } +} diff --git a/extras/tests/JsonObjectConst/subscript.cpp b/extras/tests/JsonObjectConst/subscript.cpp new file mode 100644 index 00000000..917b54a6 --- /dev/null +++ b/extras/tests/JsonObjectConst/subscript.cpp @@ -0,0 +1,33 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2024, Benoit BLANCHON +// MIT License + +#include +#include + +#include "Allocators.hpp" + +TEST_CASE("JsonObjectConst::operator[]") { + JsonDocument doc; + doc["hello"] = "world"; + JsonObjectConst obj = doc.as(); + + SECTION("supports const char*") { + REQUIRE(obj["hello"] == "world"); // issue #2019 + } + + SECTION("supports std::string") { + REQUIRE(obj[std::string("hello")] == "world"); // issue #2019 + } + +#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \ + !defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR) + SECTION("supports VLA") { + size_t i = 16; + char vla[i]; + strcpy(vla, "hello"); + + REQUIRE(std::string("world") == obj[vla]); + } +#endif +} diff --git a/src/ArduinoJson/Object/JsonObjectConst.hpp b/src/ArduinoJson/Object/JsonObjectConst.hpp index 16f30437..8f2c8bb1 100644 --- a/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -27,7 +27,7 @@ class JsonObjectConst : public detail::VariantOperators { : data_(data), resources_(resources) {} operator JsonVariantConst() const { - return JsonVariantConst(collectionToVariant(data_), resources_); + return JsonVariantConst(getData(), resources_); } // Returns true if the reference is unbound. @@ -45,7 +45,7 @@ class JsonObjectConst : public detail::VariantOperators { // Returns the depth (nesting level) of the object. // https://arduinojson.org/v7/api/jsonobjectconst/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_), resources_); + return detail::VariantData::nesting(getData(), resources_); } // Returns the number of members in the object.