123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // 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\"]}");
- }
|