shrinkToFit.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2024, 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. using ArduinoJson::detail::sizeofArray;
  10. using ArduinoJson::detail::sizeofObject;
  11. class ArmoredAllocator : public Allocator {
  12. public:
  13. virtual ~ArmoredAllocator() {}
  14. void* allocate(size_t size) override {
  15. return malloc(size);
  16. }
  17. void deallocate(void* ptr) override {
  18. free(ptr);
  19. }
  20. void* reallocate(void* ptr, size_t new_size) override {
  21. // don't call realloc, instead alloc a new buffer and erase the old one
  22. // this way we make sure we support relocation
  23. void* new_ptr = malloc(new_size);
  24. memset(new_ptr, '#', new_size); // erase
  25. if (ptr) {
  26. memcpy(new_ptr, ptr, std::min(new_size, new_size));
  27. free(ptr);
  28. }
  29. return new_ptr;
  30. }
  31. };
  32. TEST_CASE("JsonDocument::shrinkToFit()") {
  33. ArmoredAllocator armoredAllocator;
  34. SpyingAllocator spyingAllocator(&armoredAllocator);
  35. JsonDocument doc(&spyingAllocator);
  36. SECTION("null") {
  37. doc.shrinkToFit();
  38. REQUIRE(doc.as<std::string>() == "null");
  39. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  40. }
  41. SECTION("empty object") {
  42. deserializeJson(doc, "{}");
  43. doc.shrinkToFit();
  44. REQUIRE(doc.as<std::string>() == "{}");
  45. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  46. }
  47. SECTION("empty array") {
  48. deserializeJson(doc, "[]");
  49. doc.shrinkToFit();
  50. REQUIRE(doc.as<std::string>() == "[]");
  51. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  52. }
  53. SECTION("linked string") {
  54. doc.set("hello");
  55. doc.shrinkToFit();
  56. REQUIRE(doc.as<std::string>() == "hello");
  57. REQUIRE(spyingAllocator.log() == AllocatorLog{});
  58. }
  59. SECTION("owned string") {
  60. doc.set(std::string("abcdefg"));
  61. REQUIRE(doc.as<std::string>() == "abcdefg");
  62. doc.shrinkToFit();
  63. REQUIRE(doc.as<std::string>() == "abcdefg");
  64. REQUIRE(spyingAllocator.log() == AllocatorLog{
  65. Allocate(sizeofString("abcdefg")),
  66. });
  67. }
  68. SECTION("raw string") {
  69. doc.set(serialized("[{},12]"));
  70. doc.shrinkToFit();
  71. REQUIRE(doc.as<std::string>() == "[{},12]");
  72. REQUIRE(spyingAllocator.log() == AllocatorLog{
  73. Allocate(sizeofString("[{},12]")),
  74. });
  75. }
  76. SECTION("linked key") {
  77. doc["key"] = 42;
  78. doc.shrinkToFit();
  79. REQUIRE(doc.as<std::string>() == "{\"key\":42}");
  80. REQUIRE(spyingAllocator.log() ==
  81. AllocatorLog{
  82. Allocate(sizeofPool()),
  83. Reallocate(sizeofPool(), sizeofObject(1)),
  84. });
  85. }
  86. SECTION("owned key") {
  87. doc[std::string("abcdefg")] = 42;
  88. doc.shrinkToFit();
  89. REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
  90. REQUIRE(spyingAllocator.log() ==
  91. AllocatorLog{
  92. Allocate(sizeofString("abcdefg")),
  93. Allocate(sizeofPool()),
  94. Reallocate(sizeofPool(), sizeofObject(1)),
  95. });
  96. }
  97. SECTION("linked string in array") {
  98. doc.add("hello");
  99. doc.shrinkToFit();
  100. REQUIRE(doc.as<std::string>() == "[\"hello\"]");
  101. REQUIRE(spyingAllocator.log() ==
  102. AllocatorLog{
  103. Allocate(sizeofPool()),
  104. Reallocate(sizeofPool(), sizeofArray(1)),
  105. });
  106. }
  107. SECTION("owned string in array") {
  108. doc.add(std::string("abcdefg"));
  109. doc.shrinkToFit();
  110. REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
  111. REQUIRE(spyingAllocator.log() ==
  112. AllocatorLog{
  113. Allocate(sizeofPool()),
  114. Allocate(sizeofString("abcdefg")),
  115. Reallocate(sizeofPool(), sizeofArray(1)),
  116. });
  117. }
  118. SECTION("linked string in object") {
  119. doc["key"] = "hello";
  120. doc.shrinkToFit();
  121. REQUIRE(doc.as<std::string>() == "{\"key\":\"hello\"}");
  122. REQUIRE(spyingAllocator.log() ==
  123. AllocatorLog{
  124. Allocate(sizeofPool()),
  125. Reallocate(sizeofPool(), sizeofObject(1)),
  126. });
  127. }
  128. SECTION("owned string in object") {
  129. doc["key"] = std::string("abcdefg");
  130. doc.shrinkToFit();
  131. REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
  132. REQUIRE(spyingAllocator.log() ==
  133. AllocatorLog{
  134. Allocate(sizeofPool()),
  135. Allocate(sizeofString("abcdefg")),
  136. Reallocate(sizeofPool(), sizeofPool(1)),
  137. });
  138. }
  139. }