mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-16 03:52:16 +02:00
Remove memoryUsage()
This commit is contained in:
@ -22,3 +22,4 @@ HEAD
|
|||||||
* `JsonDocument`'s capacity grows as needed, no need to pass it to the constructor anymore
|
* `JsonDocument`'s capacity grows as needed, no need to pass it to the constructor anymore
|
||||||
* `JsonDocument`'s allocator is not monotonic anymore, removed values get recycled
|
* `JsonDocument`'s allocator is not monotonic anymore, removed values get recycled
|
||||||
* Show a link to the documentation when user passes an unsupported input type
|
* Show a link to the documentation when user passes an unsupported input type
|
||||||
|
* Remove `JsonDocument::memoryUsage()`
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
#if !ARDUINOJSON_ENABLE_STRING_VIEW
|
#if !ARDUINOJSON_ENABLE_STRING_VIEW
|
||||||
# error ARDUINOJSON_ENABLE_STRING_VIEW must be set to 1
|
# error ARDUINOJSON_ENABLE_STRING_VIEW must be set to 1
|
||||||
#endif
|
#endif
|
||||||
@ -11,7 +13,8 @@ using ArduinoJson::detail::sizeofArray;
|
|||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("string_view") {
|
TEST_CASE("string_view") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
JsonVariant variant = doc.to<JsonVariant>();
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
SECTION("deserializeJson()") {
|
SECTION("deserializeJson()") {
|
||||||
@ -56,18 +59,14 @@ TEST_CASE("string_view") {
|
|||||||
|
|
||||||
SECTION("String deduplication") {
|
SECTION("String deduplication") {
|
||||||
doc.add(std::string_view("example one", 7));
|
doc.add(std::string_view("example one", 7));
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(1) + sizeofString(7));
|
|
||||||
|
|
||||||
doc.add(std::string_view("example two", 7));
|
doc.add(std::string_view("example two", 7));
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
|
|
||||||
doc.add(std::string_view("example\0tree", 12));
|
doc.add(std::string_view("example\0tree", 12));
|
||||||
REQUIRE(doc.memoryUsage() ==
|
|
||||||
sizeofArray(3) + sizeofString(7) + sizeofString(12));
|
|
||||||
|
|
||||||
doc.add(std::string_view("example\0tree and a half", 12));
|
doc.add(std::string_view("example\0tree and a half", 12));
|
||||||
REQUIRE(doc.memoryUsage() ==
|
|
||||||
sizeofArray(4) + sizeofString(7) + sizeofString(12));
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7))
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(12)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("as<std::string_view>()") {
|
SECTION("as<std::string_view>()") {
|
||||||
|
@ -117,11 +117,16 @@ class SpyingAllocator : public ArduinoJson::Allocator {
|
|||||||
: upstream_(upstream) {}
|
: upstream_(upstream) {}
|
||||||
virtual ~SpyingAllocator() {}
|
virtual ~SpyingAllocator() {}
|
||||||
|
|
||||||
|
size_t allocatedBytes() const {
|
||||||
|
return allocatedBytes_;
|
||||||
|
}
|
||||||
|
|
||||||
void* allocate(size_t n) override {
|
void* allocate(size_t n) override {
|
||||||
auto block = reinterpret_cast<AllocatedBlock*>(
|
auto block = reinterpret_cast<AllocatedBlock*>(
|
||||||
upstream_->allocate(sizeof(AllocatedBlock) + n - 1));
|
upstream_->allocate(sizeof(AllocatedBlock) + n - 1));
|
||||||
if (block) {
|
if (block) {
|
||||||
log_ << AllocatorLog::Allocate(n);
|
log_ << AllocatorLog::Allocate(n);
|
||||||
|
allocatedBytes_ += n;
|
||||||
block->size = n;
|
block->size = n;
|
||||||
return block->payload;
|
return block->payload;
|
||||||
} else {
|
} else {
|
||||||
@ -132,6 +137,7 @@ class SpyingAllocator : public ArduinoJson::Allocator {
|
|||||||
|
|
||||||
void deallocate(void* p) override {
|
void deallocate(void* p) override {
|
||||||
auto block = AllocatedBlock::fromPayload(p);
|
auto block = AllocatedBlock::fromPayload(p);
|
||||||
|
allocatedBytes_ -= block->size;
|
||||||
log_ << AllocatorLog::Deallocate(block ? block->size : 0);
|
log_ << AllocatorLog::Deallocate(block ? block->size : 0);
|
||||||
upstream_->deallocate(block);
|
upstream_->deallocate(block);
|
||||||
}
|
}
|
||||||
@ -144,6 +150,7 @@ class SpyingAllocator : public ArduinoJson::Allocator {
|
|||||||
if (block) {
|
if (block) {
|
||||||
log_ << AllocatorLog::Reallocate(oldSize, n);
|
log_ << AllocatorLog::Reallocate(oldSize, n);
|
||||||
block->size = n;
|
block->size = n;
|
||||||
|
allocatedBytes_ += n - oldSize;
|
||||||
return block->payload;
|
return block->payload;
|
||||||
} else {
|
} else {
|
||||||
log_ << AllocatorLog::ReallocateFail(oldSize, n);
|
log_ << AllocatorLog::ReallocateFail(oldSize, n);
|
||||||
@ -177,6 +184,7 @@ class SpyingAllocator : public ArduinoJson::Allocator {
|
|||||||
|
|
||||||
AllocatorLog log_;
|
AllocatorLog log_;
|
||||||
Allocator* upstream_;
|
Allocator* upstream_;
|
||||||
|
size_t allocatedBytes_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControllableAllocator : public ArduinoJson::Allocator {
|
class ControllableAllocator : public ArduinoJson::Allocator {
|
||||||
|
@ -11,7 +11,6 @@ add_executable(JsonArrayTests
|
|||||||
equals.cpp
|
equals.cpp
|
||||||
isNull.cpp
|
isNull.cpp
|
||||||
iterator.cpp
|
iterator.cpp
|
||||||
memoryUsage.cpp
|
|
||||||
nesting.cpp
|
nesting.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
size.cpp
|
size.cpp
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonArray::add()") {
|
TEST_CASE("JsonArray::add()") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
JsonArray array = doc.to<JsonArray>();
|
JsonArray array = doc.to<JsonArray>();
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
@ -99,43 +102,49 @@ TEST_CASE("JsonArray::add()") {
|
|||||||
|
|
||||||
SECTION("should not duplicate const char*") {
|
SECTION("should not duplicate const char*") {
|
||||||
array.add("world");
|
array.add("world");
|
||||||
const size_t expectedSize = sizeofArray(1);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char*") {
|
SECTION("should duplicate char*") {
|
||||||
array.add(const_cast<char*>("world"));
|
array.add(const_cast<char*>("world"));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array.add(std::string("world"));
|
array.add(std::string("world"));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(const char*)") {
|
SECTION("should duplicate serialized(const char*)") {
|
||||||
array.add(serialized("{}"));
|
array.add(serialized("{}"));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(2);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(char*)") {
|
SECTION("should duplicate serialized(char*)") {
|
||||||
array.add(serialized(const_cast<char*>("{}")));
|
array.add(serialized(const_cast<char*>("{}")));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(2);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(std::string)") {
|
SECTION("should duplicate serialized(std::string)") {
|
||||||
array.add(serialized(std::string("{}")));
|
array.add(serialized(std::string("{}")));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(2);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate serialized(std::string)") {
|
SECTION("should duplicate serialized(std::string)") {
|
||||||
array.add(serialized(std::string("\0XX", 3)));
|
array.add(serialized(std::string("\0XX", 3)));
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(3);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(3)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <catch.hpp>
|
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
|
||||||
using ArduinoJson::detail::sizeofString;
|
|
||||||
|
|
||||||
TEST_CASE("JsonArray::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
JsonArray arr = doc.to<JsonArray>();
|
|
||||||
|
|
||||||
SECTION("return 0 if uninitialized") {
|
|
||||||
JsonArray unitialized;
|
|
||||||
REQUIRE(unitialized.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofArray(0) if empty") {
|
|
||||||
REQUIRE(arr.memoryUsage() == sizeofArray(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofArray(1) after add") {
|
|
||||||
arr.add("hello");
|
|
||||||
REQUIRE(arr.memoryUsage() == sizeofArray(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the string") {
|
|
||||||
arr.add(std::string("hello"));
|
|
||||||
REQUIRE(arr.memoryUsage() == sizeofArray(1) + sizeofString(5));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the nested array") {
|
|
||||||
JsonArray nested = arr.createNestedArray();
|
|
||||||
nested.add(42);
|
|
||||||
REQUIRE(arr.memoryUsage() == 2 * sizeofArray(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the nested arrect") {
|
|
||||||
JsonObject nested = arr.createNestedObject();
|
|
||||||
nested["hello"] = "world";
|
|
||||||
REQUIRE(arr.memoryUsage() == sizeofObject(1) + sizeofArray(1));
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,11 +6,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonArray::operator[]") {
|
TEST_CASE("JsonArray::operator[]") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
JsonArray array = doc.to<JsonArray>();
|
JsonArray array = doc.to<JsonArray>();
|
||||||
|
|
||||||
SECTION("Pad with null") {
|
SECTION("Pad with null") {
|
||||||
@ -115,20 +118,22 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
|
|
||||||
SECTION("should not duplicate const char*") {
|
SECTION("should not duplicate const char*") {
|
||||||
array[0] = "world";
|
array[0] = "world";
|
||||||
const size_t expectedSize = sizeofArray(1);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char*") {
|
SECTION("should duplicate char*") {
|
||||||
array[0] = const_cast<char*>("world");
|
array[0] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array[0] = std::string("world");
|
array[0] = std::string("world");
|
||||||
const size_t expectedSize = sizeofArray(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array[0].to<JsonObject>()") {
|
SECTION("array[0].to<JsonObject>()") {
|
||||||
|
@ -11,7 +11,8 @@ using ArduinoJson::detail::sizeofArray;
|
|||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("deserialize JSON array") {
|
TEST_CASE("deserialize JSON array") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("An empty array") {
|
SECTION("An empty array") {
|
||||||
DeserializationError err = deserializeJson(doc, "[]");
|
DeserializationError err = deserializeJson(doc, "[]");
|
||||||
@ -253,16 +254,19 @@ TEST_CASE("deserialize JSON array") {
|
|||||||
JsonArray arr = doc.as<JsonArray>();
|
JsonArray arr = doc.as<JsonArray>();
|
||||||
|
|
||||||
REQUIRE(arr.size() == 0);
|
REQUIRE(arr.size() == 0);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(0));
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Deallocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserialize JSON array under memory constraints") {
|
TEST_CASE("deserialize JSON array under memory constraints") {
|
||||||
TimebombAllocator allocator(100);
|
TimebombAllocator timebomb(100);
|
||||||
|
SpyingAllocator allocator(&timebomb);
|
||||||
JsonDocument doc(&allocator);
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("empty array requires no allocation") {
|
SECTION("empty array requires no allocation") {
|
||||||
allocator.setCountdown(0);
|
timebomb.setCountdown(0);
|
||||||
char input[] = "[]";
|
char input[] = "[]";
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(doc, input);
|
DeserializationError err = deserializeJson(doc, input);
|
||||||
@ -271,7 +275,7 @@ TEST_CASE("deserialize JSON array under memory constraints") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("allocation of pool list fails") {
|
SECTION("allocation of pool list fails") {
|
||||||
allocator.setCountdown(0);
|
timebomb.setCountdown(0);
|
||||||
char input[] = "[1]";
|
char input[] = "[1]";
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(doc, input);
|
DeserializationError err = deserializeJson(doc, input);
|
||||||
@ -281,7 +285,7 @@ TEST_CASE("deserialize JSON array under memory constraints") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("allocation of pool fails") {
|
SECTION("allocation of pool fails") {
|
||||||
allocator.setCountdown(0);
|
timebomb.setCountdown(0);
|
||||||
char input[] = "[1]";
|
char input[] = "[1]";
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(doc, input);
|
DeserializationError err = deserializeJson(doc, input);
|
||||||
@ -291,7 +295,7 @@ TEST_CASE("deserialize JSON array under memory constraints") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("allocation of string fails in array") {
|
SECTION("allocation of string fails in array") {
|
||||||
allocator.setCountdown(1);
|
timebomb.setCountdown(1);
|
||||||
char input[] = "[0,\"hi!\"]";
|
char input[] = "[0,\"hi!\"]";
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(doc, input);
|
DeserializationError err = deserializeJson(doc, input);
|
||||||
@ -303,6 +307,10 @@ TEST_CASE("deserialize JSON array under memory constraints") {
|
|||||||
SECTION("don't store space characters") {
|
SECTION("don't store space characters") {
|
||||||
deserializeJson(doc, " [ \"1234567\" ] ");
|
deserializeJson(doc, " [ \"1234567\" ] ");
|
||||||
|
|
||||||
REQUIRE(sizeofArray(1) + sizeofString(7) == doc.memoryUsage());
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(
|
||||||
|
sizeofString(31), sizeofString(7)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
@ -689,8 +691,9 @@ TEST_CASE("Filtering") {
|
|||||||
for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
|
for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
|
||||||
CAPTURE(i);
|
CAPTURE(i);
|
||||||
|
|
||||||
|
SpyingAllocator allocator;
|
||||||
JsonDocument filter;
|
JsonDocument filter;
|
||||||
JsonDocument doc;
|
JsonDocument doc(&allocator);
|
||||||
TestCase& tc = testCases[i];
|
TestCase& tc = testCases[i];
|
||||||
|
|
||||||
CAPTURE(tc.filter);
|
CAPTURE(tc.filter);
|
||||||
@ -703,7 +706,9 @@ TEST_CASE("Filtering") {
|
|||||||
tc.nestingLimit)) == tc.error);
|
tc.nestingLimit)) == tc.error);
|
||||||
|
|
||||||
CHECK(doc.as<std::string>() == tc.output);
|
CHECK(doc.as<std::string>() == tc.output);
|
||||||
CHECK(doc.memoryUsage() == tc.memoryUsage);
|
|
||||||
|
doc.shrinkToFit();
|
||||||
|
CHECK(allocator.allocatedBytes() == tc.memoryUsage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,20 +7,30 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
#include "CustomReader.hpp"
|
#include "CustomReader.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("deserializeJson(char*)") {
|
TEST_CASE("deserializeJson(char*)") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
char input[] = "{\"hello\":\"world\"}";
|
char input[] = "{\"hello\":\"world\"}";
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(doc, input);
|
DeserializationError err = deserializeJson(doc, input);
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
CHECK(doc.memoryUsage() == sizeofObject(1) + 2 * sizeofString(5));
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||||
|
sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||||
|
sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserializeJson(unsigned char*, unsigned int)") { // issue #1897
|
TEST_CASE("deserializeJson(unsigned char*, unsigned int)") { // issue #1897
|
||||||
|
@ -5,12 +5,15 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using namespace Catch::Matchers;
|
using namespace Catch::Matchers;
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
|
|
||||||
TEST_CASE("deserializeJson(JsonDocument&)") {
|
TEST_CASE("deserializeJson(JsonDocument&)") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("Edge cases") {
|
SECTION("Edge cases") {
|
||||||
SECTION("null char*") {
|
SECTION("null char*") {
|
||||||
@ -114,6 +117,8 @@ TEST_CASE("deserializeJson(JsonDocument&)") {
|
|||||||
deserializeJson(doc, "{}");
|
deserializeJson(doc, "{}");
|
||||||
|
|
||||||
REQUIRE(doc.is<JsonObject>());
|
REQUIRE(doc.is<JsonObject>());
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(0));
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Deallocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ using ArduinoJson::detail::sizeofObject;
|
|||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("deserialize JSON object") {
|
TEST_CASE("deserialize JSON object") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("An empty object") {
|
SECTION("An empty object") {
|
||||||
DeserializationError err = deserializeJson(doc, "{}");
|
DeserializationError err = deserializeJson(doc, "{}");
|
||||||
@ -282,8 +283,28 @@ TEST_CASE("deserialize JSON object") {
|
|||||||
DeserializationError err = deserializeJson(doc, "{a:{b:{c:1}},a:2}");
|
DeserializationError err = deserializeJson(doc, "{a:{b:{c:1}},a:2}");
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
REQUIRE(doc["a"] == 2);
|
REQUIRE(doc.as<std::string>() == "{\"a\":2}");
|
||||||
REQUIRE(doc.memoryUsage() == 3 * sizeofObject(1) + sizeofString(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog()
|
||||||
|
// a
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31), sizeofString(1))
|
||||||
|
// pool
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
// b
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31), sizeofString(1))
|
||||||
|
// c
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31), sizeofString(1))
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
// remove b & c
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(1)) * 2
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Repeated key with zero copy mode") { // issue #1697
|
SECTION("Repeated key with zero copy mode") { // issue #1697
|
||||||
@ -310,7 +331,21 @@ TEST_CASE("deserialize JSON object") {
|
|||||||
|
|
||||||
REQUIRE(doc.is<JsonObject>());
|
REQUIRE(doc.is<JsonObject>());
|
||||||
REQUIRE(obj.size() == 0);
|
REQUIRE(obj.size() == 0);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(0));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog()
|
||||||
|
// string "hello"
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31), sizeofString(5))
|
||||||
|
// pool
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
// string "world"
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31), sizeofString(5))
|
||||||
|
// free pool
|
||||||
|
<< AllocatorLog::Deallocate(sizeofPool())
|
||||||
|
// free "hello" and "world"
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Issue #1335") {
|
SECTION("Issue #1335") {
|
||||||
|
@ -155,21 +155,42 @@ TEST_CASE("String allocation fails") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Deduplicate values") {
|
TEST_CASE("Deduplicate values") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
deserializeJson(doc, "[\"example\",\"example\"]");
|
deserializeJson(doc, "[\"example\",\"example\"]");
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
// pool
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
// string "example"
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||||
|
sizeofString(7))
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Deduplicate keys") {
|
TEST_CASE("Deduplicate keys") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
deserializeJson(doc, "[{\"example\":1},{\"example\":2}]");
|
deserializeJson(doc, "[{\"example\":1},{\"example\":2}]");
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() ==
|
|
||||||
2 * sizeofObject(1) + sizeofArray(2) + sizeofString(7));
|
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
CHECK(key1 == key2);
|
CHECK(key1 == key2);
|
||||||
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
// pool
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
// string "example"
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||||
|
sizeofString(7))
|
||||||
|
// string builder
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ add_executable(JsonDocumentTests
|
|||||||
isNull.cpp
|
isNull.cpp
|
||||||
issue1120.cpp
|
issue1120.cpp
|
||||||
MemberProxy.cpp
|
MemberProxy.cpp
|
||||||
memoryUsage.cpp
|
|
||||||
nesting.cpp
|
nesting.cpp
|
||||||
overflowed.cpp
|
overflowed.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
|
@ -189,21 +189,6 @@ TEST_CASE("ElementProxy::size()") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ElementProxy::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
doc.add();
|
|
||||||
ElementProxy ep = doc[0];
|
|
||||||
|
|
||||||
SECTION("returns 0 for null") {
|
|
||||||
REQUIRE(ep.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("returns size for string") {
|
|
||||||
ep.set(std::string("hello"));
|
|
||||||
REQUIRE(ep.memoryUsage() == sizeofString(5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ElementProxy::operator[]") {
|
TEST_CASE("ElementProxy::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
ElementProxy ep = doc[1];
|
ElementProxy ep = doc[1];
|
||||||
|
@ -239,20 +239,6 @@ TEST_CASE("MemberProxy::size()") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MemberProxy::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
MemberProxy mp = doc["hello"];
|
|
||||||
|
|
||||||
SECTION("returns 0 when null") {
|
|
||||||
REQUIRE(mp.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("return the size for a string") {
|
|
||||||
mp.set(std::string("hello"));
|
|
||||||
REQUIRE(mp.memoryUsage() == sizeofString(5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("MemberProxy::operator[]") {
|
TEST_CASE("MemberProxy::operator[]") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
MemberProxy mp = doc["hello"];
|
MemberProxy mp = doc["hello"];
|
||||||
@ -329,18 +315,20 @@ TEST_CASE("MemberProxy::createNestedObject(key)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Deduplicate keys") {
|
TEST_CASE("Deduplicate keys") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
doc[0][std::string("example")] = 1;
|
doc[0][std::string("example")] = 1;
|
||||||
doc[1][std::string("example")] = 2;
|
doc[1][std::string("example")] = 2;
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() ==
|
|
||||||
sizeofArray(2) + 2 * sizeofObject(1) + sizeofString(7));
|
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
CHECK(key1 == key2);
|
CHECK(key1 == key2);
|
||||||
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("char*") {
|
SECTION("char*") {
|
||||||
@ -348,42 +336,46 @@ TEST_CASE("Deduplicate keys") {
|
|||||||
doc[0][key] = 1;
|
doc[0][key] = 1;
|
||||||
doc[1][key] = 2;
|
doc[1][key] = 2;
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() ==
|
|
||||||
sizeofArray(2) + 2 * sizeofObject(1) + sizeofString(7));
|
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
CHECK(key1 == key2);
|
CHECK(key1 == key2);
|
||||||
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Arduino String") {
|
SECTION("Arduino String") {
|
||||||
doc[0][String("example")] = 1;
|
doc[0][String("example")] = 1;
|
||||||
doc[1][String("example")] = 2;
|
doc[1][String("example")] = 2;
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() ==
|
|
||||||
sizeofArray(2) + 2 * sizeofObject(1) + sizeofString(7));
|
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
CHECK(key1 == key2);
|
CHECK(key1 == key2);
|
||||||
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Flash string") {
|
SECTION("Flash string") {
|
||||||
doc[0][F("example")] = 1;
|
doc[0][F("example")] = 1;
|
||||||
doc[1][F("example")] = 2;
|
doc[1][F("example")] = 2;
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() ==
|
|
||||||
sizeofArray(2) + 2 * sizeofObject(1) + sizeofString(7));
|
|
||||||
|
|
||||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||||
CHECK(key1 == key2);
|
CHECK(key1 == key2);
|
||||||
|
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("MemberProxy under memory constraints") {
|
TEST_CASE("MemberProxy under memory constraints") {
|
||||||
ControllableAllocator allocator;
|
ControllableAllocator allocator;
|
||||||
JsonDocument doc(&allocator);
|
SpyingAllocator spy(&allocator);
|
||||||
|
JsonDocument doc(&spy);
|
||||||
|
|
||||||
SECTION("key allocation fails") {
|
SECTION("key allocation fails") {
|
||||||
allocator.disable();
|
allocator.disable();
|
||||||
@ -392,7 +384,8 @@ TEST_CASE("MemberProxy under memory constraints") {
|
|||||||
|
|
||||||
REQUIRE(doc.is<JsonObject>());
|
REQUIRE(doc.is<JsonObject>());
|
||||||
REQUIRE(doc.size() == 0);
|
REQUIRE(doc.size() == 0);
|
||||||
REQUIRE(doc.memoryUsage() == 0);
|
|
||||||
REQUIRE(doc.overflowed() == true);
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::AllocateFail(sizeofString(5)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,30 +8,39 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::add()") {
|
TEST_CASE("JsonDocument::add()") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("integer") {
|
SECTION("integer") {
|
||||||
doc.add(42);
|
doc.add(42);
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "[42]");
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
doc.add("hello");
|
doc.add("hello");
|
||||||
|
|
||||||
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::string") {
|
SECTION("std::string") {
|
||||||
doc.add(std::string("example"));
|
doc.add(std::string("example"));
|
||||||
doc.add(std::string("example"));
|
doc.add(std::string("example"));
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("char*") {
|
SECTION("char*") {
|
||||||
@ -39,23 +48,29 @@ TEST_CASE("JsonDocument::add()") {
|
|||||||
doc.add(value);
|
doc.add(value);
|
||||||
doc.add(value);
|
doc.add(value);
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Arduino String") {
|
SECTION("Arduino String") {
|
||||||
doc.add(String("example"));
|
doc.add(String("example"));
|
||||||
doc.add(String("example"));
|
doc.add(String("example"));
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Flash string") {
|
SECTION("Flash string") {
|
||||||
doc.add(F("example"));
|
doc.add(F("example"));
|
||||||
doc.add(F("example"));
|
doc.add(F("example"));
|
||||||
|
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
|
|
||||||
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(7)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,12 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
|||||||
|
|
||||||
SECTION("when allocation succeeds") {
|
SECTION("when allocation succeeds") {
|
||||||
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(2) + 2 * sizeofString(7));
|
|
||||||
doc.remove("blanket");
|
doc.remove("blanket");
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
bool result = doc.garbageCollect();
|
bool result = doc.garbageCollect();
|
||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(7));
|
|
||||||
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7))
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7))
|
||||||
@ -37,7 +35,6 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
|||||||
|
|
||||||
SECTION("when allocation fails") {
|
SECTION("when allocation fails") {
|
||||||
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(2) + 2 * sizeofString(7));
|
|
||||||
doc.remove("blanket");
|
doc.remove("blanket");
|
||||||
controllableAllocator.disable();
|
controllableAllocator.disable();
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
@ -45,7 +42,6 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
|||||||
bool result = doc.garbageCollect();
|
bool result = doc.garbageCollect();
|
||||||
|
|
||||||
REQUIRE(result == false);
|
REQUIRE(result == false);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(2) + sizeofString(7));
|
|
||||||
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
||||||
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <catch.hpp>
|
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
|
||||||
|
|
||||||
TEST_CASE("JsonDocument::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
|
|
||||||
SECTION("starts at zero") {
|
|
||||||
REQUIRE(doc.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofArray(0)") {
|
|
||||||
doc.to<JsonArray>();
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofArray(1)") {
|
|
||||||
doc.to<JsonArray>().add(42);
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofArray(1) + sizeofArray(0)") {
|
|
||||||
doc.to<JsonArray>().createNestedArray();
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(1) + sizeofArray(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Increases after adding value to array") {
|
|
||||||
JsonArray arr = doc.to<JsonArray>();
|
|
||||||
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(0));
|
|
||||||
arr.add(42);
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(1));
|
|
||||||
arr.add(43);
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Increases after adding value to object") {
|
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(0));
|
|
||||||
obj["a"] = 1;
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1));
|
|
||||||
obj["b"] = 2;
|
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(2));
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ add_executable(JsonObjectTests
|
|||||||
invalid.cpp
|
invalid.cpp
|
||||||
isNull.cpp
|
isNull.cpp
|
||||||
iterator.cpp
|
iterator.cpp
|
||||||
memoryUsage.cpp
|
|
||||||
nesting.cpp
|
nesting.cpp
|
||||||
remove.cpp
|
remove.cpp
|
||||||
size.cpp
|
size.cpp
|
||||||
|
@ -7,61 +7,80 @@
|
|||||||
|
|
||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonObject::set()") {
|
TEST_CASE("JsonObject::set()") {
|
||||||
JsonDocument doc1;
|
SpyingAllocator allocator;
|
||||||
JsonDocument doc2;
|
JsonDocument doc1(&allocator);
|
||||||
|
JsonDocument doc2(&allocator);
|
||||||
|
|
||||||
JsonObject obj1 = doc1.to<JsonObject>();
|
JsonObject obj1 = doc1.to<JsonObject>();
|
||||||
JsonObject obj2 = doc2.to<JsonObject>();
|
JsonObject obj2 = doc2.to<JsonObject>();
|
||||||
|
|
||||||
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";
|
||||||
|
allocator.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy local string value") {
|
SECTION("copy local string value") {
|
||||||
obj1["hello"] = std::string("world");
|
obj1["hello"] = std::string("world");
|
||||||
|
allocator.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy local key") {
|
SECTION("copy local key") {
|
||||||
obj1[std::string("hello")] = "world";
|
obj1[std::string("hello")] = "world";
|
||||||
|
allocator.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy string from deserializeJson()") {
|
SECTION("copy string from deserializeJson()") {
|
||||||
deserializeJson(doc1, "{'hello':'world'}");
|
deserializeJson(doc1, "{'hello':'world'}");
|
||||||
|
allocator.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy string from deserializeMsgPack()") {
|
SECTION("copy string from deserializeMsgPack()") {
|
||||||
deserializeMsgPack(doc1, "\x81\xA5hello\xA5world");
|
deserializeMsgPack(doc1, "\x81\xA5hello\xA5world");
|
||||||
|
allocator.clearLog();
|
||||||
|
|
||||||
bool success = obj2.set(obj1);
|
bool success = obj2.set(obj1);
|
||||||
|
|
||||||
REQUIRE(success == true);
|
REQUIRE(success == true);
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should work with JsonObjectConst") {
|
SECTION("should work with JsonObjectConst") {
|
||||||
@ -69,13 +88,12 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
|
|
||||||
obj2.set(static_cast<JsonObjectConst>(obj1));
|
obj2.set(static_cast<JsonObjectConst>(obj1));
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == doc2.memoryUsage());
|
|
||||||
REQUIRE(obj2["hello"] == std::string("world"));
|
REQUIRE(obj2["hello"] == std::string("world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy fails in the middle of an object") {
|
SECTION("copy fails in the middle of an object") {
|
||||||
TimebombAllocator allocator(2);
|
TimebombAllocator timebomb(2);
|
||||||
JsonDocument doc3(&allocator);
|
JsonDocument doc3(&timebomb);
|
||||||
JsonObject obj3 = doc3.to<JsonObject>();
|
JsonObject obj3 = doc3.to<JsonObject>();
|
||||||
|
|
||||||
obj1[std::string("a")] = 1;
|
obj1[std::string("a")] = 1;
|
||||||
@ -88,8 +106,8 @@ TEST_CASE("JsonObject::set()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy fails in the middle of an array") {
|
SECTION("copy fails in the middle of an array") {
|
||||||
TimebombAllocator allocator(1);
|
TimebombAllocator timebomb(1);
|
||||||
JsonDocument doc3(&allocator);
|
JsonDocument doc3(&timebomb);
|
||||||
JsonObject obj3 = doc3.to<JsonObject>();
|
JsonObject obj3 = doc3.to<JsonObject>();
|
||||||
|
|
||||||
obj1["hello"][0] = std::string("world");
|
obj1["hello"][0] = std::string("world");
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <catch.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
|
||||||
using ArduinoJson::detail::sizeofString;
|
|
||||||
|
|
||||||
TEST_CASE("JsonObject::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
SECTION("return 0 if uninitialized") {
|
|
||||||
JsonObject unitialized;
|
|
||||||
REQUIRE(unitialized.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofObject(0) for empty object") {
|
|
||||||
REQUIRE(obj.memoryUsage() == sizeofObject(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("sizeofObject(1) after add") {
|
|
||||||
obj["hello"] = 42;
|
|
||||||
REQUIRE(obj.memoryUsage() == sizeofObject(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the key") {
|
|
||||||
obj[std::string("hello")] = 42;
|
|
||||||
REQUIRE(obj.memoryUsage() == sizeofObject(1) + sizeofString(5));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the nested array") {
|
|
||||||
JsonArray nested = obj.createNestedArray("nested");
|
|
||||||
nested.add(42);
|
|
||||||
REQUIRE(obj.memoryUsage() == sizeofObject(1) + sizeofArray(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("includes the size of the nested object") {
|
|
||||||
JsonObject nested = obj.createNestedObject("nested");
|
|
||||||
nested["hello"] = "world";
|
|
||||||
REQUIRE(obj.memoryUsage() == 2 * sizeofObject(1));
|
|
||||||
}
|
|
||||||
}
|
|
@ -83,28 +83,4 @@ TEST_CASE("std::string") {
|
|||||||
eraseString(value);
|
eraseString(value);
|
||||||
REQUIRE(std::string("world") == obj["hello"]);
|
REQUIRE(std::string("world") == obj["hello"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("memoryUsage() increases when adding a new key") {
|
|
||||||
std::string key1("hello"), key2("world");
|
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
obj[key1] = 1;
|
|
||||||
size_t sizeBefore = doc.memoryUsage();
|
|
||||||
obj[key2] = 2;
|
|
||||||
size_t sizeAfter = doc.memoryUsage();
|
|
||||||
|
|
||||||
REQUIRE(sizeAfter - sizeBefore >= key2.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("memoryUsage() remains when adding the same key") {
|
|
||||||
std::string key("hello");
|
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
obj[key] = 1;
|
|
||||||
size_t sizeBefore = doc.memoryUsage();
|
|
||||||
obj[key] = 2;
|
|
||||||
size_t sizeAfter = doc.memoryUsage();
|
|
||||||
|
|
||||||
REQUIRE(sizeBefore == sizeAfter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
using ArduinoJson::detail::sizeofObject;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonObject::operator[]") {
|
TEST_CASE("JsonObject::operator[]") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
JsonObject obj = doc.to<JsonObject>();
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
@ -103,56 +106,65 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
SECTION("should not duplicate const char*") {
|
SECTION("should not duplicate const char*") {
|
||||||
obj["hello"] = "world";
|
obj["hello"] = "world";
|
||||||
const size_t expectedSize = sizeofObject(1);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* value") {
|
SECTION("should duplicate char* value") {
|
||||||
obj["hello"] = const_cast<char*>("world");
|
obj["hello"] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = sizeofObject(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* key") {
|
SECTION("should duplicate char* key") {
|
||||||
obj[const_cast<char*>("hello")] = "world";
|
obj[const_cast<char*>("hello")] = "world";
|
||||||
const size_t expectedSize = sizeofObject(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* key&value") {
|
SECTION("should duplicate char* key&value") {
|
||||||
obj[const_cast<char*>("hello")] = const_cast<char*>("world");
|
obj[const_cast<char*>("hello")] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = sizeofObject(1) + 2 * sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string value") {
|
SECTION("should duplicate std::string value") {
|
||||||
obj["hello"] = std::string("world");
|
obj["hello"] = std::string("world");
|
||||||
const size_t expectedSize = sizeofObject(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key") {
|
SECTION("should duplicate std::string key") {
|
||||||
obj[std::string("hello")] = "world";
|
obj[std::string("hello")] = "world";
|
||||||
const size_t expectedSize = sizeofObject(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key&value") {
|
SECTION("should duplicate std::string key&value") {
|
||||||
obj[std::string("hello")] = std::string("world");
|
obj[std::string("hello")] = std::string("world");
|
||||||
const size_t expectedSize = sizeofObject(1) + 2 * sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate a non-static JsonString key") {
|
SECTION("should duplicate a non-static JsonString key") {
|
||||||
obj[JsonString("hello", JsonString::Copied)] = "world";
|
obj[JsonString("hello", JsonString::Copied)] = "world";
|
||||||
const size_t expectedSize = sizeofObject(1) + sizeofString(5);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should not duplicate a static JsonString key") {
|
SECTION("should not duplicate a static JsonString key") {
|
||||||
obj[JsonString("hello", JsonString::Linked)] = "world";
|
obj[JsonString("hello", JsonString::Linked)] = "world";
|
||||||
const size_t expectedSize = sizeofObject(1);
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
<< AllocatorLog::Allocate(sizeofPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should ignore null key") {
|
SECTION("should ignore null key") {
|
||||||
|
@ -51,7 +51,6 @@ TEST_CASE("serialize JsonObject to std::string") {
|
|||||||
TEST_CASE("serialize an std::string containing a NUL") {
|
TEST_CASE("serialize an std::string containing a NUL") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc.set(std::string("hello\0world", 11));
|
doc.set(std::string("hello\0world", 11));
|
||||||
CHECK(doc.memoryUsage() == sizeofString(11));
|
|
||||||
|
|
||||||
std::string json;
|
std::string json;
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
|
@ -13,7 +13,6 @@ add_executable(JsonVariantTests
|
|||||||
createNested.cpp
|
createNested.cpp
|
||||||
is.cpp
|
is.cpp
|
||||||
isnull.cpp
|
isnull.cpp
|
||||||
memoryUsage.cpp
|
|
||||||
misc.cpp
|
misc.cpp
|
||||||
nesting.cpp
|
nesting.cpp
|
||||||
nullptr.cpp
|
nullptr.cpp
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::clear()") {
|
TEST_CASE("JsonVariant::clear()") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
JsonVariant var = doc.to<JsonVariant>();
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
|
|
||||||
SECTION("size goes back to zero") {
|
SECTION("size goes back to zero") {
|
||||||
@ -28,9 +31,10 @@ TEST_CASE("JsonVariant::clear()") {
|
|||||||
|
|
||||||
SECTION("releases owned string") {
|
SECTION("releases owned string") {
|
||||||
var.set(std::string("hello"));
|
var.set(std::string("hello"));
|
||||||
REQUIRE(doc.memoryUsage() == sizeofString(5));
|
|
||||||
|
|
||||||
var.clear();
|
var.clear();
|
||||||
REQUIRE(doc.memoryUsage() == 0);
|
|
||||||
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == 0);
|
|
||||||
REQUIRE(doc2.memoryUsage() == 0);
|
|
||||||
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +54,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
||||||
}
|
}
|
||||||
@ -70,8 +66,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == 0);
|
|
||||||
REQUIRE(doc2.overflowed() == true);
|
REQUIRE(doc2.overflowed() == true);
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString((7))));
|
||||||
@ -83,8 +77,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
||||||
}
|
}
|
||||||
@ -95,8 +87,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
||||||
}
|
}
|
||||||
@ -108,8 +98,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
||||||
}
|
}
|
||||||
@ -120,8 +108,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString((7))));
|
||||||
}
|
}
|
||||||
@ -133,8 +119,6 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == sizeofString(7));
|
|
||||||
REQUIRE(doc2.memoryUsage() == 0);
|
|
||||||
REQUIRE(doc2.overflowed() == true);
|
REQUIRE(doc2.overflowed() == true);
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString((7))));
|
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString((7))));
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <catch.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
|
||||||
using ArduinoJson::detail::sizeofObject;
|
|
||||||
using ArduinoJson::detail::sizeofString;
|
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::memoryUsage()") {
|
|
||||||
JsonDocument doc;
|
|
||||||
JsonVariant var = doc.to<JsonVariant>();
|
|
||||||
|
|
||||||
SECTION("returns 0 if uninitialized") {
|
|
||||||
JsonVariant unitialized;
|
|
||||||
REQUIRE(unitialized.memoryUsage() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("returns size of object") {
|
|
||||||
JsonObject obj = var.to<JsonObject>();
|
|
||||||
obj["hello"] = 42;
|
|
||||||
REQUIRE(var.memoryUsage() == sizeofObject(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("returns size of array") {
|
|
||||||
JsonArray arr = var.to<JsonArray>();
|
|
||||||
arr.add(42);
|
|
||||||
REQUIRE(var.memoryUsage() == sizeofArray(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("returns size of owned string") {
|
|
||||||
var.set(std::string("hello"));
|
|
||||||
REQUIRE(var.memoryUsage() == sizeofString(5));
|
|
||||||
REQUIRE(var.memoryUsage() == doc.memoryUsage());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("returns size of raw string") {
|
|
||||||
var.set(serialized("hello"));
|
|
||||||
REQUIRE(var.memoryUsage() == sizeofString(5));
|
|
||||||
REQUIRE(var.memoryUsage() == doc.memoryUsage());
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,11 +6,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::sizeofArray;
|
using ArduinoJson::detail::sizeofArray;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::remove(int)") {
|
TEST_CASE("JsonVariant::remove(int)") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
|
|
||||||
SECTION("release top level strings") {
|
SECTION("release top level strings") {
|
||||||
doc.add(std::string("hello"));
|
doc.add(std::string("hello"));
|
||||||
@ -19,19 +22,23 @@ TEST_CASE("JsonVariant::remove(int)") {
|
|||||||
|
|
||||||
JsonVariant var = doc.as<JsonVariant>();
|
JsonVariant var = doc.as<JsonVariant>();
|
||||||
REQUIRE(var.as<std::string>() == "[\"hello\",\"hello\",\"world\"]");
|
REQUIRE(var.as<std::string>() == "[\"hello\",\"hello\",\"world\"]");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(3) + 2 * sizeofString(5));
|
|
||||||
|
|
||||||
|
allocator.clearLog();
|
||||||
var.remove(1);
|
var.remove(1);
|
||||||
REQUIRE(var.as<std::string>() == "[\"hello\",\"world\"]");
|
REQUIRE(var.as<std::string>() == "[\"hello\",\"world\"]");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(3) + 2 * sizeofString(5));
|
REQUIRE(allocator.log() == AllocatorLog());
|
||||||
|
|
||||||
|
allocator.clearLog();
|
||||||
var.remove(1);
|
var.remove(1);
|
||||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(3) + 1 * sizeofString(5));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
|
|
||||||
|
allocator.clearLog();
|
||||||
var.remove(0);
|
var.remove(0);
|
||||||
REQUIRE(var.as<std::string>() == "[]");
|
REQUIRE(var.as<std::string>() == "[]");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofArray(3));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("release strings in nested array") {
|
SECTION("release strings in nested array") {
|
||||||
@ -39,11 +46,13 @@ TEST_CASE("JsonVariant::remove(int)") {
|
|||||||
|
|
||||||
JsonVariant var = doc.as<JsonVariant>();
|
JsonVariant var = doc.as<JsonVariant>();
|
||||||
REQUIRE(var.as<std::string>() == "[[\"hello\"]]");
|
REQUIRE(var.as<std::string>() == "[[\"hello\"]]");
|
||||||
REQUIRE(doc.memoryUsage() == 2 * sizeofArray(1) + sizeofString(5));
|
|
||||||
|
|
||||||
|
allocator.clearLog();
|
||||||
var.remove(0);
|
var.remove(0);
|
||||||
|
|
||||||
REQUIRE(var.as<std::string>() == "[]");
|
REQUIRE(var.as<std::string>() == "[]");
|
||||||
REQUIRE(doc.memoryUsage() == 2 * sizeofArray(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,34 +177,41 @@ TEST_CASE("JsonVariant::set(JsonDocument)") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set() releases the previous value") {
|
TEST_CASE("JsonVariant::set() releases the previous value") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
doc["hello"] = std::string("world");
|
doc["hello"] = std::string("world");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(5));
|
allocator.clearLog();
|
||||||
|
|
||||||
JsonVariant v = doc["hello"];
|
JsonVariant v = doc["hello"];
|
||||||
|
|
||||||
SECTION("int") {
|
SECTION("int") {
|
||||||
v.set(42);
|
v.set(42);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("bool") {
|
SECTION("bool") {
|
||||||
v.set(false);
|
v.set(false);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
v.set("hello");
|
v.set("hello");
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("float") {
|
SECTION("float") {
|
||||||
v.set(1.2);
|
v.set(1.2);
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1));
|
REQUIRE(allocator.log() ==
|
||||||
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Serialized<const char*>") {
|
SECTION("Serialized<const char*>") {
|
||||||
v.set(serialized("[]"));
|
v.set(serialized("[]"));
|
||||||
REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(2));
|
REQUIRE(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(5))
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,8 @@ struct PrintableString : public Printable {
|
|||||||
|
|
||||||
TEST_CASE("Printable") {
|
TEST_CASE("Printable") {
|
||||||
SECTION("Doesn't overflow") {
|
SECTION("Doesn't overflow") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
const char* value = "example";
|
const char* value = "example";
|
||||||
|
|
||||||
doc.set(666); // to make sure we override the value
|
doc.set(666); // to make sure we override the value
|
||||||
@ -64,8 +65,10 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.as<std::string>() == value);
|
CHECK(doc.as<std::string>() == value);
|
||||||
CHECK(printable.totalBytesWritten() == 7);
|
CHECK(printable.totalBytesWritten() == 7);
|
||||||
CHECK(doc.overflowed() == false);
|
CHECK(doc.overflowed() == false);
|
||||||
CHECK(doc.memoryUsage() == sizeofString(7));
|
CHECK(allocator.log() == AllocatorLog()
|
||||||
CHECK(doc.as<JsonVariant>().memoryUsage() == sizeofString(7));
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(
|
||||||
|
sizeofString(31), sizeofString(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Via Print::write(const char* size_t)") {
|
SECTION("Via Print::write(const char* size_t)") {
|
||||||
@ -74,8 +77,10 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.as<std::string>() == value);
|
CHECK(doc.as<std::string>() == value);
|
||||||
CHECK(printable.totalBytesWritten() == 7);
|
CHECK(printable.totalBytesWritten() == 7);
|
||||||
CHECK(doc.overflowed() == false);
|
CHECK(doc.overflowed() == false);
|
||||||
CHECK(doc.memoryUsage() == sizeofString(7));
|
CHECK(allocator.log() == AllocatorLog()
|
||||||
CHECK(doc.as<JsonVariant>().memoryUsage() == sizeofString(7));
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(
|
||||||
|
sizeofString(31), sizeofString(7)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +100,6 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.isNull());
|
CHECK(doc.isNull());
|
||||||
CHECK(printable.totalBytesWritten() == 0);
|
CHECK(printable.totalBytesWritten() == 0);
|
||||||
CHECK(doc.overflowed() == true);
|
CHECK(doc.overflowed() == true);
|
||||||
CHECK(doc.memoryUsage() == 0);
|
|
||||||
CHECK(spyingAllocator.log() ==
|
CHECK(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||||
}
|
}
|
||||||
@ -109,7 +113,6 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.isNull());
|
CHECK(doc.isNull());
|
||||||
CHECK(printable.totalBytesWritten() == 0);
|
CHECK(printable.totalBytesWritten() == 0);
|
||||||
CHECK(doc.overflowed() == true);
|
CHECK(doc.overflowed() == true);
|
||||||
CHECK(doc.memoryUsage() == 0);
|
|
||||||
CHECK(spyingAllocator.log() ==
|
CHECK(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||||
}
|
}
|
||||||
@ -132,7 +135,6 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.isNull());
|
CHECK(doc.isNull());
|
||||||
CHECK(printable.totalBytesWritten() == 31);
|
CHECK(printable.totalBytesWritten() == 31);
|
||||||
CHECK(doc.overflowed() == true);
|
CHECK(doc.overflowed() == true);
|
||||||
CHECK(doc.memoryUsage() == 0);
|
|
||||||
CHECK(spyingAllocator.log() ==
|
CHECK(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||||
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
||||||
@ -149,7 +151,6 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(doc.isNull());
|
CHECK(doc.isNull());
|
||||||
CHECK(printable.totalBytesWritten() == 31);
|
CHECK(printable.totalBytesWritten() == 31);
|
||||||
CHECK(doc.overflowed() == true);
|
CHECK(doc.overflowed() == true);
|
||||||
CHECK(doc.memoryUsage() == 0);
|
|
||||||
CHECK(spyingAllocator.log() ==
|
CHECK(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||||
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
||||||
@ -167,12 +168,19 @@ TEST_CASE("Printable") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("String deduplication") {
|
SECTION("String deduplication") {
|
||||||
JsonDocument doc;
|
SpyingAllocator allocator;
|
||||||
|
JsonDocument doc(&allocator);
|
||||||
doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
|
doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
|
||||||
doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
|
doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
|
||||||
REQUIRE(doc.size() == 2);
|
REQUIRE(doc.size() == 2);
|
||||||
CHECK(doc[0] == "Hello World!");
|
CHECK(doc[0] == "Hello World!");
|
||||||
CHECK(doc[1] == "Hello World!");
|
CHECK(doc[1] == "Hello World!");
|
||||||
CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(12));
|
CHECK(allocator.log() == AllocatorLog()
|
||||||
|
<< AllocatorLog::Allocate(sizeofPool())
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||||
|
sizeofString(12))
|
||||||
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
|
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -145,12 +145,6 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the array.
|
|
||||||
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
return data_ ? data_->memoryUsage(resources_) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
@ -66,12 +66,6 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the array.
|
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
return data_ ? data_->memoryUsage(resources_) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
@ -88,7 +88,6 @@ class CollectionData {
|
|||||||
return iterator(resources->getSlot(head_), head_);
|
return iterator(resources->getSlot(head_), head_);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memoryUsage(const ResourceManager*) const;
|
|
||||||
size_t size(const ResourceManager*) const;
|
size_t size(const ResourceManager*) const;
|
||||||
size_t nesting(const ResourceManager*) const;
|
size_t nesting(const ResourceManager*) const;
|
||||||
|
|
||||||
|
@ -105,17 +105,6 @@ inline void CollectionData::remove(iterator it, ResourceManager* resources) {
|
|||||||
releaseSlot({it.slot_, it.currentId_}, resources);
|
releaseSlot({it.slot_, it.currentId_}, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t CollectionData::memoryUsage(
|
|
||||||
const ResourceManager* resources) const {
|
|
||||||
size_t total = 0;
|
|
||||||
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
|
||||||
total += sizeof(VariantSlot) + it->memoryUsage(resources);
|
|
||||||
if (it.ownsKey())
|
|
||||||
total += sizeofString(strlen(it.key()));
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
|
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
|
||||||
size_t maxChildNesting = 0;
|
size_t maxChildNesting = 0;
|
||||||
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
||||||
|
@ -128,12 +128,6 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
return getSlot().isNull();
|
return getSlot().isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of used bytes in the memory pool.
|
|
||||||
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
|
|
||||||
size_t memoryUsage() const {
|
|
||||||
return resources_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns trues if the memory pool was too small.
|
// Returns trues if the memory pool was too small.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
|
@ -53,12 +53,6 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
|||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the object.
|
|
||||||
// https://arduinojson.org/v6/api/jsonobject/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
return data_ ? data_->memoryUsage(resources_) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the object.
|
// Returns the depth (nesting level) of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/nesting/
|
// https://arduinojson.org/v6/api/jsonobject/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
@ -42,12 +42,6 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
|||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the object.
|
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
return data_ ? data_->memoryUsage(resources_) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the object.
|
// Returns the depth (nesting level) of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
|
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
@ -47,12 +47,6 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
return !data_;
|
return !data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the value.
|
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
return data_ ? data_->memoryUsage(resources_) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the value.
|
// Returns the depth (nesting level) of the value.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
|
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
@ -274,19 +274,6 @@ class VariantData {
|
|||||||
return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
|
return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memoryUsage(const ResourceManager* resources) const {
|
|
||||||
switch (type()) {
|
|
||||||
case VALUE_IS_OWNED_STRING:
|
|
||||||
case VALUE_IS_RAW_STRING:
|
|
||||||
return sizeofString(content_.asOwnedString->length);
|
|
||||||
case VALUE_IS_OBJECT:
|
|
||||||
case VALUE_IS_ARRAY:
|
|
||||||
return content_.asCollection.memoryUsage(resources);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nesting(const ResourceManager* resources) const {
|
size_t nesting(const ResourceManager* resources) const {
|
||||||
auto collection = asCollection();
|
auto collection = asCollection();
|
||||||
if (collection)
|
if (collection)
|
||||||
|
@ -130,13 +130,6 @@ class VariantRefBase : public VariantTag {
|
|||||||
return VariantData::size(getData(), getResourceManager());
|
return VariantData::size(getData(), getResourceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the value.
|
|
||||||
// https://arduinojson.org/v6/api/jsonvariant/memoryusage/
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
|
||||||
VariantData* data = getData();
|
|
||||||
return data ? data->memoryUsage(getResourceManager()) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the value.
|
// Returns the depth (nesting level) of the value.
|
||||||
// https://arduinojson.org/v6/api/jsonvariant/nesting/
|
// https://arduinojson.org/v6/api/jsonvariant/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
|
Reference in New Issue
Block a user