printable.cpp 5.5 KB

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