You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MicroDexed/third-party/ArduinoJson/extras/tests/JsonDocument/shrinkToFit.cpp

155 lines
3.7 KiB

// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include <stdlib.h> // malloc, free
#include <string>
using ARDUINOJSON_NAMESPACE::addPadding;
class ArmoredAllocator {
public:
ArmoredAllocator() : _ptr(0), _size(0) {}
void* allocate(size_t size) {
_ptr = malloc(size);
_size = size;
return _ptr;
}
void deallocate(void* ptr) {
REQUIRE(ptr == _ptr);
free(ptr);
_ptr = 0;
_size = 0;
}
void* reallocate(void* ptr, size_t new_size) {
REQUIRE(ptr == _ptr);
// 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);
memcpy(new_ptr, _ptr, std::min(new_size, _size));
memset(_ptr, '#', _size); // erase
free(_ptr);
_ptr = new_ptr;
return new_ptr;
}
private:
void* _ptr;
size_t _size;
};
typedef BasicJsonDocument<ArmoredAllocator> ShrinkToFitTestDocument;
void testShrinkToFit(ShrinkToFitTestDocument& doc, std::string expected_json,
size_t expected_size) {
// test twice: shrinkToFit() should be idempotent
for (int i = 0; i < 2; i++) {
doc.shrinkToFit();
REQUIRE(doc.capacity() == expected_size);
REQUIRE(doc.memoryUsage() == expected_size);
std::string json;
serializeJson(doc, json);
REQUIRE(json == expected_json);
}
}
TEST_CASE("BasicJsonDocument::shrinkToFit()") {
ShrinkToFitTestDocument doc(4096);
SECTION("null") {
testShrinkToFit(doc, "null", 0);
}
SECTION("empty object") {
deserializeJson(doc, "{}");
testShrinkToFit(doc, "{}", JSON_OBJECT_SIZE(0));
}
SECTION("empty array") {
deserializeJson(doc, "[]");
testShrinkToFit(doc, "[]", JSON_ARRAY_SIZE(0));
}
SECTION("linked string") {
doc.set("hello");
testShrinkToFit(doc, "\"hello\"", 0);
}
SECTION("owned string") {
doc.set(std::string("abcdefg"));
testShrinkToFit(doc, "\"abcdefg\"", 8);
}
SECTION("linked raw") {
doc.set(serialized("[{},123]"));
testShrinkToFit(doc, "[{},123]", 0);
}
SECTION("owned raw") {
doc.set(serialized(std::string("[{},12]")));
testShrinkToFit(doc, "[{},12]", 8);
}
SECTION("linked key") {
doc["key"] = 42;
testShrinkToFit(doc, "{\"key\":42}", JSON_OBJECT_SIZE(1));
}
SECTION("owned key") {
doc[std::string("abcdefg")] = 42;
testShrinkToFit(doc, "{\"abcdefg\":42}", JSON_OBJECT_SIZE(1) + 8);
}
SECTION("linked string in array") {
doc.add("hello");
testShrinkToFit(doc, "[\"hello\"]", JSON_ARRAY_SIZE(1));
}
SECTION("owned string in array") {
doc.add(std::string("abcdefg"));
testShrinkToFit(doc, "[\"abcdefg\"]", JSON_ARRAY_SIZE(1) + 8);
}
SECTION("linked string in object") {
doc["key"] = "hello";
testShrinkToFit(doc, "{\"key\":\"hello\"}", JSON_OBJECT_SIZE(1));
}
SECTION("owned string in object") {
doc["key"] = std::string("abcdefg");
testShrinkToFit(doc, "{\"key\":\"abcdefg\"}", JSON_ARRAY_SIZE(1) + 8);
}
SECTION("unaligned") {
doc.add(std::string("?")); // two bytes in the string pool
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + 2);
doc.shrinkToFit();
// the new capacity should be padded to align the pointers
REQUIRE(doc.capacity() == JSON_OBJECT_SIZE(1) + sizeof(void*));
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + 2);
REQUIRE(doc[0] == "?");
}
}
TEST_CASE("DynamicJsonDocument::shrinkToFit()") {
DynamicJsonDocument doc(4096);
deserializeJson(doc, "{\"hello\":[\"world\"]");
doc.shrinkToFit();
std::string json;
serializeJson(doc, json);
REQUIRE(json == "{\"hello\":[\"world\"]}");
}