| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- // ArduinoJson - https://arduinojson.org
- // Copyright © 2014-2025, Benoit BLANCHON
- // MIT License
- #include <ArduinoJson.h>
- #include <catch.hpp>
- #include <stdlib.h> // malloc, free
- #include <string>
- #include "Allocators.hpp"
- #include "Literals.hpp"
- using ArduinoJson::detail::sizeofArray;
- using ArduinoJson::detail::sizeofObject;
- class ArmoredAllocator : public Allocator {
- public:
- virtual ~ArmoredAllocator() {}
- void* allocate(size_t size) override {
- return malloc(size);
- }
- void deallocate(void* ptr) override {
- free(ptr);
- }
- void* reallocate(void* ptr, size_t new_size) override {
- // 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);
- memset(new_ptr, '#', new_size); // erase
- if (ptr) {
- memcpy(new_ptr, ptr, std::min(new_size, new_size));
- free(ptr);
- }
- return new_ptr;
- }
- };
- TEST_CASE("JsonDocument::shrinkToFit()") {
- ArmoredAllocator armoredAllocator;
- SpyingAllocator spyingAllocator(&armoredAllocator);
- JsonDocument doc(&spyingAllocator);
- SECTION("null") {
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "null");
- REQUIRE(spyingAllocator.log() == AllocatorLog{});
- }
- SECTION("empty object") {
- deserializeJson(doc, "{}");
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "{}");
- REQUIRE(spyingAllocator.log() == AllocatorLog{});
- }
- SECTION("empty array") {
- deserializeJson(doc, "[]");
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "[]");
- REQUIRE(spyingAllocator.log() == AllocatorLog{});
- }
- SECTION("linked string") {
- doc.set("hello");
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "hello");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofStaticStringPool()),
- Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
- });
- }
- SECTION("owned string") {
- doc.set("abcdefg"_s);
- REQUIRE(doc.as<std::string>() == "abcdefg");
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "abcdefg");
- REQUIRE(spyingAllocator.log() == AllocatorLog{
- Allocate(sizeofString("abcdefg")),
- });
- }
- SECTION("raw string") {
- doc.set(serialized("[{},12]"));
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "[{},12]");
- REQUIRE(spyingAllocator.log() == AllocatorLog{
- Allocate(sizeofString("[{},12]")),
- });
- }
- SECTION("linked key") {
- doc["key"] = 42;
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "{\"key\":42}");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofStaticStringPool()),
- Reallocate(sizeofPool(), sizeofObject(1)),
- Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
- });
- }
- SECTION("owned key") {
- doc["abcdefg"_s] = 42;
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofString("abcdefg")),
- Reallocate(sizeofPool(), sizeofObject(1)),
- });
- }
- SECTION("linked string in array") {
- doc.add("hello");
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "[\"hello\"]");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofStaticStringPool()),
- Reallocate(sizeofPool(), sizeofArray(1)),
- Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
- });
- }
- SECTION("owned string in array") {
- doc.add("abcdefg"_s);
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofString("abcdefg")),
- Reallocate(sizeofPool(), sizeofArray(1)),
- });
- }
- SECTION("linked string in object") {
- doc["key"] = "hello";
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "{\"key\":\"hello\"}");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofStaticStringPool()),
- Reallocate(sizeofPool(), sizeofObject(1)),
- Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(2)),
- });
- }
- SECTION("owned string in object") {
- doc["key1"_s] = "value"_s;
- doc.shrinkToFit();
- REQUIRE(doc.as<std::string>() == "{\"key1\":\"value\"}");
- REQUIRE(spyingAllocator.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofString("key1")),
- Allocate(sizeofString("value")),
- Reallocate(sizeofPool(), sizeofPool(2)),
- });
- }
- }
|