From 0643c2e708f6a4c6c5cdb32202f184b4f8faa002 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 1 Apr 2023 19:10:35 +0200 Subject: [PATCH] Test: gather JsonDocument constructor and assignment tests --- extras/tests/JsonDocument/CMakeLists.txt | 2 +- extras/tests/JsonDocument/allocator.cpp | 173 ------------------- extras/tests/JsonDocument/assignment.cpp | 84 +++++++-- extras/tests/JsonDocument/constructor.cpp | 53 +++++- extras/tests/JsonDocument/garbageCollect.cpp | 47 +++++ 5 files changed, 164 insertions(+), 195 deletions(-) delete mode 100644 extras/tests/JsonDocument/allocator.cpp create mode 100644 extras/tests/JsonDocument/garbageCollect.cpp diff --git a/extras/tests/JsonDocument/CMakeLists.txt b/extras/tests/JsonDocument/CMakeLists.txt index 2aa81c2d..24097f6c 100644 --- a/extras/tests/JsonDocument/CMakeLists.txt +++ b/extras/tests/JsonDocument/CMakeLists.txt @@ -4,7 +4,6 @@ add_executable(JsonDocumentTests add.cpp - allocator.cpp assignment.cpp capacity.cpp cast.cpp @@ -13,6 +12,7 @@ add_executable(JsonDocumentTests containsKey.cpp createNested.cpp ElementProxy.cpp + garbageCollect.cpp isNull.cpp issue1120.cpp MemberProxy.cpp diff --git a/extras/tests/JsonDocument/allocator.cpp b/extras/tests/JsonDocument/allocator.cpp deleted file mode 100644 index 0e9f7402..00000000 --- a/extras/tests/JsonDocument/allocator.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// ArduinoJson - https://arduinojson.org -// Copyright © 2014-2023, Benoit BLANCHON -// MIT License - -#include -#include // malloc, free -#include -#include - -#include "Allocators.hpp" - -using ArduinoJson::detail::sizeofObject; - -TEST_CASE("JsonDocument's allocator") { - SpyingAllocator spyingAllocator; - ControllableAllocator controllableAllocator; - - SECTION("Construct/Destruct") { - { JsonDocument doc(4096, &spyingAllocator); } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(4096) - << AllocatorLog::Deallocate(4096)); - } - - SECTION("Copy construct") { - { - JsonDocument doc1(4096, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - - JsonDocument doc2(doc1); - - REQUIRE(doc1.as() == "The size of this string is 32!!"); - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc2.capacity() == 4096); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(4096) - << AllocatorLog::Allocate(4096) - << AllocatorLog::Deallocate(4096) - << AllocatorLog::Deallocate(4096)); - } - - SECTION("Move construct") { - { - JsonDocument doc1(4096, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - - JsonDocument doc2(std::move(doc1)); - - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc1.as() == "null"); - REQUIRE(doc1.capacity() == 0); - REQUIRE(doc2.capacity() == 4096); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(4096) - << AllocatorLog::Deallocate(4096)); - } - - SECTION("Copy assign larger") { - { - JsonDocument doc1(4096, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - JsonDocument doc2(8, &spyingAllocator); - - doc2 = doc1; - - REQUIRE(doc1.as() == "The size of this string is 32!!"); - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc2.capacity() == 4096); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(4096) - << AllocatorLog::Allocate(8) - << AllocatorLog::Deallocate(8) - << AllocatorLog::Allocate(4096) - << AllocatorLog::Deallocate(4096) - << AllocatorLog::Deallocate(4096)); - } - - SECTION("Copy assign smaller") { - { - JsonDocument doc1(1024, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - JsonDocument doc2(4096, &spyingAllocator); - - doc2 = doc1; - - REQUIRE(doc1.as() == "The size of this string is 32!!"); - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc2.capacity() == 1024); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(1024) - << AllocatorLog::Allocate(4096) - << AllocatorLog::Deallocate(4096) - << AllocatorLog::Allocate(1024) - << AllocatorLog::Deallocate(1024) - << AllocatorLog::Deallocate(1024)); - } - - SECTION("Copy assign same size") { - { - JsonDocument doc1(1024, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - JsonDocument doc2(1024, &spyingAllocator); - - doc2 = doc1; - - REQUIRE(doc1.as() == "The size of this string is 32!!"); - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc2.capacity() == 1024); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(1024) - << AllocatorLog::Allocate(1024) - << AllocatorLog::Deallocate(1024) - << AllocatorLog::Deallocate(1024)); - } - - SECTION("Move assign") { - { - JsonDocument doc1(4096, &spyingAllocator); - doc1.set(std::string("The size of this string is 32!!")); - JsonDocument doc2(8, &spyingAllocator); - - doc2 = std::move(doc1); - - REQUIRE(doc2.as() == "The size of this string is 32!!"); - REQUIRE(doc1.as() == "null"); - REQUIRE(doc1.capacity() == 0); - REQUIRE(doc2.capacity() == 4096); - } - REQUIRE(spyingAllocator.log() == AllocatorLog() - << AllocatorLog::Allocate(4096) - << AllocatorLog::Allocate(8) - << AllocatorLog::Deallocate(8) - << AllocatorLog::Deallocate(4096)); - } - - SECTION("garbageCollect()") { - JsonDocument doc(4096, &controllableAllocator); - - SECTION("when allocation succeeds") { - deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}"); - REQUIRE(doc.capacity() == 4096); - REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); - doc.remove("blanket"); - - bool result = doc.garbageCollect(); - - REQUIRE(result == true); - REQUIRE(doc.memoryUsage() == sizeofObject(1) + 8); - REQUIRE(doc.capacity() == 4096); - REQUIRE(doc.as() == "{\"dancing\":2}"); - } - - SECTION("when allocation fails") { - deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}"); - REQUIRE(doc.capacity() == 4096); - REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); - doc.remove("blanket"); - controllableAllocator.disable(); - - bool result = doc.garbageCollect(); - - REQUIRE(result == false); - REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); - REQUIRE(doc.capacity() == 4096); - REQUIRE(doc.as() == "{\"dancing\":2}"); - } - } -} diff --git a/extras/tests/JsonDocument/assignment.cpp b/extras/tests/JsonDocument/assignment.cpp index 631ae715..574ece9c 100644 --- a/extras/tests/JsonDocument/assignment.cpp +++ b/extras/tests/JsonDocument/assignment.cpp @@ -5,30 +5,90 @@ #include #include +#include "Allocators.hpp" + using ArduinoJson::detail::sizeofArray; using ArduinoJson::detail::sizeofObject; TEST_CASE("JsonDocument assignment") { + SpyingAllocator spyingAllocator; + + SECTION("Copy assignment same capacity") { + { + JsonDocument doc1(1024, &spyingAllocator); + deserializeJson(doc1, "{\"hello\":\"world\"}"); + JsonDocument doc2(1024, &spyingAllocator); + + doc2 = doc1; + + REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); + REQUIRE(doc2.capacity() == doc1.capacity()); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(1024) + << AllocatorLog::Allocate(1024) + << AllocatorLog::Deallocate(1024) + << AllocatorLog::Deallocate(1024)); + } + SECTION("Copy assignment reallocates when capacity is smaller") { - JsonDocument doc1(1234); - deserializeJson(doc1, "{\"hello\":\"world\"}"); - JsonDocument doc2(8); + { + JsonDocument doc1(4096, &spyingAllocator); + deserializeJson(doc1, "{\"hello\":\"world\"}"); + JsonDocument doc2(8, &spyingAllocator); - doc2 = doc1; + doc2 = doc1; - REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); - REQUIRE(doc2.capacity() == doc1.capacity()); + REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); + REQUIRE(doc2.capacity() == doc1.capacity()); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(4096) + << AllocatorLog::Allocate(8) + << AllocatorLog::Deallocate(8) + << AllocatorLog::Allocate(4096) + << AllocatorLog::Deallocate(4096) + << AllocatorLog::Deallocate(4096)); } SECTION("Copy assignment reallocates when capacity is larger") { - JsonDocument doc1(100); - deserializeJson(doc1, "{\"hello\":\"world\"}"); - JsonDocument doc2(1234); + { + JsonDocument doc1(1024, &spyingAllocator); + deserializeJson(doc1, "{\"hello\":\"world\"}"); + JsonDocument doc2(4096, &spyingAllocator); - doc2 = doc1; + doc2 = doc1; - REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); - REQUIRE(doc2.capacity() == doc1.capacity()); + REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); + REQUIRE(doc2.capacity() == doc1.capacity()); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(1024) + << AllocatorLog::Allocate(4096) + << AllocatorLog::Deallocate(4096) + << AllocatorLog::Allocate(1024) + << AllocatorLog::Deallocate(1024) + << AllocatorLog::Deallocate(1024)); + } + + SECTION("Move assign") { + { + JsonDocument doc1(4096, &spyingAllocator); + doc1.set(std::string("The size of this string is 32!!")); + JsonDocument doc2(8, &spyingAllocator); + + doc2 = std::move(doc1); + + REQUIRE(doc2.as() == "The size of this string is 32!!"); + REQUIRE(doc1.as() == "null"); + REQUIRE(doc1.capacity() == 0); + REQUIRE(doc2.capacity() == 4096); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(4096) + << AllocatorLog::Allocate(8) + << AllocatorLog::Deallocate(8) + << AllocatorLog::Deallocate(4096)); } SECTION("Assign from JsonObject") { diff --git a/extras/tests/JsonDocument/constructor.cpp b/extras/tests/JsonDocument/constructor.cpp index 5026fc40..59d73b06 100644 --- a/extras/tests/JsonDocument/constructor.cpp +++ b/extras/tests/JsonDocument/constructor.cpp @@ -5,21 +5,56 @@ #include #include +#include "Allocators.hpp" + using ArduinoJson::detail::addPadding; TEST_CASE("JsonDocument constructor") { - SECTION("Copy constructor") { - JsonDocument doc1(1234); - deserializeJson(doc1, "{\"hello\":\"world\"}"); + SpyingAllocator spyingAllocator; - JsonDocument doc2 = doc1; - - REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); - - REQUIRE(doc2.capacity() == doc1.capacity()); + SECTION("JsonDocument(size_t)") { + { JsonDocument doc(4096, &spyingAllocator); } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(4096) + << AllocatorLog::Deallocate(4096)); } - SECTION("Construct from JsonObject") { + SECTION("JsonDocument(const JsonDocument&)") { + { + JsonDocument doc1(4096, &spyingAllocator); + doc1.set(std::string("The size of this string is 32!!")); + + JsonDocument doc2(doc1); + + REQUIRE(doc1.as() == "The size of this string is 32!!"); + REQUIRE(doc2.as() == "The size of this string is 32!!"); + REQUIRE(doc2.capacity() == 4096); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(4096) + << AllocatorLog::Allocate(4096) + << AllocatorLog::Deallocate(4096) + << AllocatorLog::Deallocate(4096)); + } + + SECTION("JsonDocument(JsonDocument&&)") { + { + JsonDocument doc1(4096, &spyingAllocator); + doc1.set(std::string("The size of this string is 32!!")); + + JsonDocument doc2(std::move(doc1)); + + REQUIRE(doc2.as() == "The size of this string is 32!!"); + REQUIRE(doc1.as() == "null"); + REQUIRE(doc1.capacity() == 0); + REQUIRE(doc2.capacity() == 4096); + } + REQUIRE(spyingAllocator.log() == AllocatorLog() + << AllocatorLog::Allocate(4096) + << AllocatorLog::Deallocate(4096)); + } + + SECTION("JsonDocument(JsonObject)") { JsonDocument doc1(200); JsonObject obj = doc1.to(); obj["hello"] = "world"; diff --git a/extras/tests/JsonDocument/garbageCollect.cpp b/extras/tests/JsonDocument/garbageCollect.cpp new file mode 100644 index 00000000..27e564db --- /dev/null +++ b/extras/tests/JsonDocument/garbageCollect.cpp @@ -0,0 +1,47 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2023, Benoit BLANCHON +// MIT License + +#include +#include // malloc, free +#include +#include + +#include "Allocators.hpp" + +using ArduinoJson::detail::sizeofObject; + +TEST_CASE("JsonDocument::garbageCollect()") { + SpyingAllocator spyingAllocator; + ControllableAllocator controllableAllocator; + JsonDocument doc(4096, &controllableAllocator); + + SECTION("when allocation succeeds") { + deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}"); + REQUIRE(doc.capacity() == 4096); + REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); + doc.remove("blanket"); + + bool result = doc.garbageCollect(); + + REQUIRE(result == true); + REQUIRE(doc.memoryUsage() == sizeofObject(1) + 8); + REQUIRE(doc.capacity() == 4096); + REQUIRE(doc.as() == "{\"dancing\":2}"); + } + + SECTION("when allocation fails") { + deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}"); + REQUIRE(doc.capacity() == 4096); + REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); + doc.remove("blanket"); + controllableAllocator.disable(); + + bool result = doc.garbageCollect(); + + REQUIRE(result == false); + REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16); + REQUIRE(doc.capacity() == 4096); + REQUIRE(doc.as() == "{\"dancing\":2}"); + } +}