add.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2025, Benoit BLANCHON
  3. // MIT License
  4. #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
  5. #define ARDUINOJSON_ENABLE_PROGMEM 1
  6. #include <ArduinoJson.h>
  7. #include <catch.hpp>
  8. #include "Allocators.hpp"
  9. #include "Literals.hpp"
  10. using ArduinoJson::detail::sizeofArray;
  11. TEST_CASE("JsonDocument::add(T)") {
  12. SpyingAllocator spy;
  13. JsonDocument doc(&spy);
  14. SECTION("integer") {
  15. doc.add(42);
  16. REQUIRE(doc.as<std::string>() == "[42]");
  17. REQUIRE(spy.log() == AllocatorLog{
  18. Allocate(sizeofPool()),
  19. });
  20. }
  21. SECTION("string literal") {
  22. doc.add("hello");
  23. REQUIRE(doc.as<std::string>() == "[\"hello\"]");
  24. REQUIRE(spy.log() == AllocatorLog{
  25. Allocate(sizeofPool()),
  26. Allocate(sizeofStaticStringPool()),
  27. });
  28. }
  29. SECTION("const char*") {
  30. const char* value = "hello";
  31. doc.add(value);
  32. REQUIRE(doc.as<std::string>() == "[\"hello\"]");
  33. REQUIRE(spy.log() == AllocatorLog{
  34. Allocate(sizeofPool()),
  35. Allocate(sizeofString("hello")),
  36. });
  37. }
  38. SECTION("std::string") {
  39. doc.add("example"_s);
  40. doc.add("example"_s);
  41. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  42. REQUIRE(spy.log() == AllocatorLog{
  43. Allocate(sizeofPool()),
  44. Allocate(sizeofString("example")),
  45. });
  46. }
  47. SECTION("char*") {
  48. char value[] = "example";
  49. doc.add(value);
  50. doc.add(value);
  51. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  52. REQUIRE(spy.log() == AllocatorLog{
  53. Allocate(sizeofPool()),
  54. Allocate(sizeofString("example")),
  55. });
  56. }
  57. SECTION("Arduino String") {
  58. doc.add(String("example"));
  59. doc.add(String("example"));
  60. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  61. REQUIRE(spy.log() == AllocatorLog{
  62. Allocate(sizeofPool()),
  63. Allocate(sizeofString("example")),
  64. });
  65. }
  66. SECTION("Flash string") {
  67. doc.add(F("example"));
  68. doc.add(F("example"));
  69. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  70. REQUIRE(spy.log() == AllocatorLog{
  71. Allocate(sizeofPool()),
  72. Allocate(sizeofString("example")),
  73. });
  74. }
  75. #ifdef HAS_VARIABLE_LENGTH_ARRAY
  76. SECTION("VLA") {
  77. size_t i = 16;
  78. char vla[i];
  79. strcpy(vla, "example");
  80. doc.add(vla);
  81. doc.add(vla);
  82. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  83. REQUIRE("example"_s == doc[0]);
  84. REQUIRE(spy.log() == AllocatorLog{
  85. Allocate(sizeofPool()),
  86. Allocate(sizeofString("example")),
  87. });
  88. }
  89. #endif
  90. }
  91. TEST_CASE("JsonDocument::add<T>()") {
  92. JsonDocument doc;
  93. SECTION("JsonArray") {
  94. JsonArray array = doc.add<JsonArray>();
  95. array.add(1);
  96. array.add(2);
  97. REQUIRE(doc.as<std::string>() == "[[1,2]]");
  98. }
  99. SECTION("JsonVariant") {
  100. JsonVariant variant = doc.add<JsonVariant>();
  101. variant.set(42);
  102. REQUIRE(doc.as<std::string>() == "[42]");
  103. }
  104. }
  105. TEST_CASE("JsonObject::add(JsonObject) ") {
  106. JsonDocument doc1;
  107. doc1["hello"_s] = "world"_s;
  108. TimebombAllocator allocator(10);
  109. SpyingAllocator spy(&allocator);
  110. JsonDocument doc2(&spy);
  111. SECTION("success") {
  112. bool result = doc2.add(doc1.as<JsonObject>());
  113. REQUIRE(result == true);
  114. REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
  115. REQUIRE(spy.log() == AllocatorLog{
  116. Allocate(sizeofPool()),
  117. Allocate(sizeofString("hello")),
  118. Allocate(sizeofString("world")),
  119. });
  120. }
  121. SECTION("partial failure") { // issue #2081
  122. allocator.setCountdown(2);
  123. bool result = doc2.add(doc1.as<JsonObject>());
  124. REQUIRE(result == false);
  125. REQUIRE(doc2.as<std::string>() == "[]");
  126. REQUIRE(spy.log() == AllocatorLog{
  127. Allocate(sizeofPool()),
  128. Allocate(sizeofString("hello")),
  129. AllocateFail(sizeofString("world")),
  130. Deallocate(sizeofString("hello")),
  131. });
  132. }
  133. SECTION("complete failure") {
  134. allocator.setCountdown(0);
  135. bool result = doc2.add(doc1.as<JsonObject>());
  136. REQUIRE(result == false);
  137. REQUIRE(doc2.as<std::string>() == "[]");
  138. REQUIRE(spy.log() == AllocatorLog{
  139. AllocateFail(sizeofPool()),
  140. });
  141. }
  142. }