shrinkToFit.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2025, Benoit BLANCHON
  3. // MIT License
  4. #include <ArduinoJson.h>
  5. #include <catch.hpp>
  6. #include <stdlib.h> // malloc, free
  7. #include <string>
  8. #include "Allocators.hpp"
  9. #include "Literals.hpp"
  10. using ArduinoJson::detail::sizeofArray;
  11. using ArduinoJson::detail::sizeofObject;
  12. class ArmoredAllocator : public Allocator {
  13. public:
  14. virtual ~ArmoredAllocator() {}
  15. void* allocate(size_t size) override {
  16. return malloc(size);
  17. }
  18. void deallocate(void* ptr) override {
  19. free(ptr);
  20. }
  21. void* reallocate(void* ptr, size_t new_size) override {
  22. // don't call realloc, instead alloc a new buffer and erase the old one
  23. // this way we make sure we support relocation
  24. void* new_ptr = malloc(new_size);
  25. memset(new_ptr, '#', new_size); // erase
  26. if (ptr) {
  27. memcpy(new_ptr, ptr, std::min(new_size, new_size));
  28. free(ptr);
  29. }
  30. return new_ptr;
  31. }
  32. };
  33. TEST_CASE("JsonDocument::shrinkToFit()") {
  34. ArmoredAllocator armoredAllocator;
  35. SpyingAllocator spyingAllocator(&armoredAllocator);
  36. JsonDocument doc(&spyingAllocator);
  37. SECTION("null") {
  38. doc.shrinkToFit();
  39. REQUIRE(doc.as<std::string>() == "null");
  40. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  41. }
  42. SECTION("empty object") {
  43. deserializeJson(doc, "{}");
  44. doc.shrinkToFit();
  45. REQUIRE(doc.as<std::string>() == "{}");
  46. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  47. }
  48. SECTION("empty array") {
  49. deserializeJson(doc, "[]");
  50. doc.shrinkToFit();
  51. REQUIRE(doc.as<std::string>() == "[]");
  52. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  53. }
  54. SECTION("string") {
  55. doc.set("abcdefg");
  56. REQUIRE(doc.as<std::string>() == "abcdefg");
  57. doc.shrinkToFit();
  58. REQUIRE(doc.as<std::string>() == "abcdefg");
  59. REQUIRE(spyingAllocator.log() == AllocatorLog{
  60. Allocate(sizeofString("abcdefg")),
  61. });
  62. }
  63. SECTION("raw string") {
  64. doc.set(serialized("[{},12]"));
  65. doc.shrinkToFit();
  66. REQUIRE(doc.as<std::string>() == "[{},12]");
  67. REQUIRE(spyingAllocator.log() == AllocatorLog{
  68. Allocate(sizeofString("[{},12]")),
  69. });
  70. }
  71. SECTION("object key") {
  72. doc["abcdefg"_s] = 42;
  73. doc.shrinkToFit();
  74. REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
  75. REQUIRE(spyingAllocator.log() ==
  76. AllocatorLog{
  77. Allocate(sizeofPool()),
  78. Allocate(sizeofString("abcdefg")),
  79. Reallocate(sizeofPool(), sizeofObject(1)),
  80. });
  81. }
  82. SECTION("string in array") {
  83. doc.add("abcdefg"_s);
  84. doc.shrinkToFit();
  85. REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
  86. REQUIRE(spyingAllocator.log() ==
  87. AllocatorLog{
  88. Allocate(sizeofPool()),
  89. Allocate(sizeofString("abcdefg")),
  90. Reallocate(sizeofPool(), sizeofArray(1)),
  91. });
  92. }
  93. SECTION("string in object") {
  94. doc["key"] = "abcdefg"_s;
  95. doc.shrinkToFit();
  96. REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
  97. REQUIRE(spyingAllocator.log() ==
  98. AllocatorLog{
  99. Allocate(sizeofPool()),
  100. Allocate(sizeofString("abcdefg")),
  101. Reallocate(sizeofPool(), sizeofPool(2)),
  102. });
  103. }
  104. }