printable.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2025, Benoit BLANCHON
  3. // MIT License
  4. #include <Arduino.h>
  5. #include <catch.hpp>
  6. #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
  7. #include <ArduinoJson.h>
  8. #include "Allocators.hpp"
  9. using ArduinoJson::detail::sizeofArray;
  10. struct PrintOneCharacterAtATime {
  11. static size_t printStringTo(const std::string& s, Print& p) {
  12. size_t result = 0;
  13. for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
  14. size_t n = p.write(uint8_t(*it));
  15. if (n == 0)
  16. break;
  17. result += n;
  18. }
  19. return result;
  20. }
  21. };
  22. struct PrintAllAtOnce {
  23. static size_t printStringTo(const std::string& s, Print& p) {
  24. return p.write(s.data(), s.size());
  25. }
  26. };
  27. template <typename PrintPolicy>
  28. struct PrintableString : public Printable {
  29. PrintableString(const char* s) : str_(s), total_(0) {}
  30. virtual size_t printTo(Print& p) const {
  31. size_t result = PrintPolicy::printStringTo(str_, p);
  32. total_ += result;
  33. return result;
  34. }
  35. size_t totalBytesWritten() const {
  36. return total_;
  37. }
  38. private:
  39. std::string str_;
  40. mutable size_t total_;
  41. };
  42. TEST_CASE("Printable") {
  43. SECTION("Doesn't overflow") {
  44. SpyingAllocator spy;
  45. JsonDocument doc(&spy);
  46. const char* value = "example";
  47. doc.set(666); // to make sure we override the value
  48. SECTION("Via Print::write(char)") {
  49. PrintableString<PrintOneCharacterAtATime> printable(value);
  50. CHECK(doc.set(printable) == true);
  51. CHECK(doc.as<std::string>() == value);
  52. CHECK(printable.totalBytesWritten() == 7);
  53. CHECK(doc.overflowed() == false);
  54. CHECK(spy.log() ==
  55. AllocatorLog{
  56. Allocate(sizeofStringBuffer()),
  57. Reallocate(sizeofStringBuffer(), sizeofString("example")),
  58. });
  59. }
  60. SECTION("Via Print::write(const char* size_t)") {
  61. PrintableString<PrintAllAtOnce> printable(value);
  62. CHECK(doc.set(printable) == true);
  63. CHECK(doc.as<std::string>() == value);
  64. CHECK(printable.totalBytesWritten() == 7);
  65. CHECK(doc.overflowed() == false);
  66. CHECK(spy.log() ==
  67. AllocatorLog{
  68. Allocate(sizeofStringBuffer()),
  69. Reallocate(sizeofStringBuffer(), sizeofString("example")),
  70. });
  71. }
  72. }
  73. SECTION("First allocation fails") {
  74. SpyingAllocator spy(FailingAllocator::instance());
  75. JsonDocument doc(&spy);
  76. const char* value = "hello world";
  77. doc.set(666); // to make sure we override the value
  78. SECTION("Via Print::write(char)") {
  79. PrintableString<PrintOneCharacterAtATime> printable(value);
  80. bool success = doc.set(printable);
  81. CHECK(success == false);
  82. CHECK(doc.isNull());
  83. CHECK(printable.totalBytesWritten() == 0);
  84. CHECK(doc.overflowed() == true);
  85. CHECK(spy.log() == AllocatorLog{
  86. AllocateFail(sizeofStringBuffer()),
  87. });
  88. }
  89. SECTION("Via Print::write(const char*, size_t)") {
  90. PrintableString<PrintAllAtOnce> printable(value);
  91. bool success = doc.set(printable);
  92. CHECK(success == false);
  93. CHECK(doc.isNull());
  94. CHECK(printable.totalBytesWritten() == 0);
  95. CHECK(doc.overflowed() == true);
  96. CHECK(spy.log() == AllocatorLog{
  97. AllocateFail(sizeofStringBuffer()),
  98. });
  99. }
  100. }
  101. SECTION("Reallocation fails") {
  102. TimebombAllocator timebomb(1);
  103. SpyingAllocator spy(&timebomb);
  104. JsonDocument doc(&spy);
  105. const char* value = "Lorem ipsum dolor sit amet, cons"; // > 31 chars
  106. doc.set(666); // to make sure we override the value
  107. SECTION("Via Print::write(char)") {
  108. PrintableString<PrintOneCharacterAtATime> printable(value);
  109. bool success = doc.set(printable);
  110. CHECK(success == false);
  111. CHECK(doc.isNull());
  112. CHECK(printable.totalBytesWritten() == 31);
  113. CHECK(doc.overflowed() == true);
  114. CHECK(spy.log() ==
  115. AllocatorLog{
  116. Allocate(sizeofStringBuffer()),
  117. ReallocateFail(sizeofStringBuffer(), sizeofStringBuffer(2)),
  118. Deallocate(sizeofStringBuffer()),
  119. });
  120. }
  121. SECTION("Via Print::write(const char*, size_t)") {
  122. PrintableString<PrintAllAtOnce> printable(value);
  123. bool success = doc.set(printable);
  124. CHECK(success == false);
  125. CHECK(doc.isNull());
  126. CHECK(printable.totalBytesWritten() == 31);
  127. CHECK(doc.overflowed() == true);
  128. CHECK(spy.log() ==
  129. AllocatorLog{
  130. Allocate(sizeofStringBuffer()),
  131. ReallocateFail(sizeofStringBuffer(), sizeofStringBuffer(2)),
  132. Deallocate(sizeofStringBuffer()),
  133. });
  134. }
  135. }
  136. SECTION("Null variant") {
  137. JsonVariant var;
  138. PrintableString<PrintOneCharacterAtATime> printable = "Hello World!";
  139. CHECK(var.set(printable) == false);
  140. CHECK(var.isNull());
  141. CHECK(printable.totalBytesWritten() == 0);
  142. }
  143. SECTION("String deduplication") {
  144. SpyingAllocator spy;
  145. JsonDocument doc(&spy);
  146. doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
  147. doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
  148. REQUIRE(doc.size() == 2);
  149. CHECK(doc[0] == "Hello World!");
  150. CHECK(doc[1] == "Hello World!");
  151. CHECK(spy.log() ==
  152. AllocatorLog{
  153. Allocate(sizeofPool()),
  154. Allocate(sizeofStringBuffer()),
  155. Reallocate(sizeofStringBuffer(), sizeofString("Hello World!")),
  156. Allocate(sizeofStringBuffer()),
  157. Deallocate(sizeofStringBuffer()),
  158. });
  159. }
  160. }