2021-03-29 17:14:01 +02:00
|
|
|
// ArduinoJson - https://arduinojson.org
|
2023-02-16 11:45:01 +01:00
|
|
|
// Copyright © 2014-2023, Benoit BLANCHON
|
2019-11-07 15:40:20 +01:00
|
|
|
// MIT License
|
|
|
|
|
|
|
|
#include <ArduinoJson.h>
|
|
|
|
#include <catch.hpp>
|
|
|
|
|
|
|
|
#include <stdlib.h> // malloc, free
|
|
|
|
#include <string>
|
|
|
|
|
2023-04-02 16:47:37 +02:00
|
|
|
#include "Allocators.hpp"
|
|
|
|
|
2023-03-29 19:18:06 +02:00
|
|
|
using ArduinoJson::detail::sizeofArray;
|
|
|
|
using ArduinoJson::detail::sizeofObject;
|
2023-04-02 16:47:37 +02:00
|
|
|
using ArduinoJson::detail::sizeofString;
|
2023-03-29 19:18:06 +02:00
|
|
|
|
2023-03-20 14:47:27 +01:00
|
|
|
class ArmoredAllocator : public Allocator {
|
2019-11-07 15:40:20 +01:00
|
|
|
public:
|
2023-03-20 14:47:27 +01:00
|
|
|
virtual ~ArmoredAllocator() {}
|
2019-11-07 15:40:20 +01:00
|
|
|
|
2023-03-20 14:47:27 +01:00
|
|
|
void* allocate(size_t size) override {
|
2023-04-07 18:27:29 +02:00
|
|
|
return malloc(size);
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
2023-03-20 14:47:27 +01:00
|
|
|
void deallocate(void* ptr) override {
|
2019-11-07 15:40:20 +01:00
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
|
2023-03-20 14:47:27 +01:00
|
|
|
void* reallocate(void* ptr, size_t new_size) override {
|
2019-11-07 15:40:20 +01:00
|
|
|
// don't call realloc, instead alloc a new buffer and erase the old one
|
|
|
|
// this way we make sure we support relocation
|
|
|
|
void* new_ptr = malloc(new_size);
|
2023-04-07 18:27:29 +02:00
|
|
|
memset(new_ptr, '#', new_size); // erase
|
2023-07-17 14:46:00 +02:00
|
|
|
if (ptr) {
|
|
|
|
memcpy(new_ptr, ptr, std::min(new_size, new_size));
|
|
|
|
free(ptr);
|
|
|
|
}
|
2019-11-07 15:40:20 +01:00
|
|
|
return new_ptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-03-20 10:49:01 +01:00
|
|
|
TEST_CASE("JsonDocument::shrinkToFit()") {
|
2023-03-20 14:47:27 +01:00
|
|
|
ArmoredAllocator armoredAllocator;
|
2023-04-02 16:47:37 +02:00
|
|
|
SpyingAllocator spyingAllocator(&armoredAllocator);
|
|
|
|
JsonDocument doc(4096, &spyingAllocator);
|
2019-11-07 15:40:20 +01:00
|
|
|
|
|
|
|
SECTION("null") {
|
2023-04-02 16:47:37 +02:00
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "null");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("empty object") {
|
|
|
|
deserializeJson(doc, "{}");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "{}");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("empty array") {
|
|
|
|
deserializeJson(doc, "[]");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "[]");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("linked string") {
|
|
|
|
doc.set("hello");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "hello");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("owned string") {
|
|
|
|
doc.set(std::string("abcdefg"));
|
2023-04-11 10:03:47 +02:00
|
|
|
REQUIRE(doc.as<std::string>() == "abcdefg");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "abcdefg");
|
|
|
|
REQUIRE(spyingAllocator.log() ==
|
2023-07-17 14:39:57 +02:00
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
2023-05-02 10:03:37 +02:00
|
|
|
SECTION("raw string") {
|
|
|
|
doc.set(serialized("[{},12]"));
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "[{},12]");
|
|
|
|
REQUIRE(spyingAllocator.log() ==
|
2023-07-17 14:39:57 +02:00
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("linked key") {
|
|
|
|
doc["key"] = 42;
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "{\"key\":42}");
|
|
|
|
REQUIRE(spyingAllocator.log() ==
|
2023-07-17 14:39:57 +02:00
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(),
|
|
|
|
sizeofObject(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("owned key") {
|
|
|
|
doc[std::string("abcdefg")] = 42;
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
|
|
|
|
REQUIRE(spyingAllocator.log() ==
|
2023-07-17 14:39:57 +02:00
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7))
|
|
|
|
<< AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(),
|
|
|
|
sizeofObject(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("linked string in array") {
|
|
|
|
doc.add("hello");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(
|
|
|
|
spyingAllocator.log() ==
|
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(), sizeofArray(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("owned string in array") {
|
|
|
|
doc.add(std::string("abcdefg"));
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(
|
|
|
|
spyingAllocator.log() ==
|
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Allocate(sizeofString(7))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(), sizeofArray(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("linked string in object") {
|
|
|
|
doc["key"] = "hello";
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "{\"key\":\"hello\"}");
|
|
|
|
REQUIRE(spyingAllocator.log() ==
|
2023-07-17 14:39:57 +02:00
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(),
|
|
|
|
sizeofObject(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("owned string in object") {
|
|
|
|
doc["key"] = std::string("abcdefg");
|
2023-04-02 16:47:37 +02:00
|
|
|
|
|
|
|
doc.shrinkToFit();
|
|
|
|
|
|
|
|
REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
|
2023-07-17 14:39:57 +02:00
|
|
|
REQUIRE(
|
|
|
|
spyingAllocator.log() ==
|
|
|
|
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
|
|
|
|
<< AllocatorLog::Allocate(sizeofPool())
|
|
|
|
<< AllocatorLog::Allocate(sizeofString(7))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPool(), sizeofPool(1))
|
|
|
|
<< AllocatorLog::Reallocate(sizeofPoolList(),
|
|
|
|
sizeofPoolList(1)));
|
2019-11-07 15:40:20 +01:00
|
|
|
}
|
|
|
|
}
|