add.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2024, Benoit BLANCHON
  3. // MIT License
  4. #include <ArduinoJson.h>
  5. #include <catch.hpp>
  6. #include "Allocators.hpp"
  7. #include "Literals.hpp"
  8. using ArduinoJson::detail::sizeofArray;
  9. TEST_CASE("JsonArray::add(T)") {
  10. SpyingAllocator spy;
  11. JsonDocument doc(&spy);
  12. JsonArray array = doc.to<JsonArray>();
  13. SECTION("int") {
  14. array.add(123);
  15. REQUIRE(123 == array[0].as<int>());
  16. REQUIRE(array[0].is<int>());
  17. REQUIRE(array[0].is<double>());
  18. }
  19. SECTION("double") {
  20. array.add(123.45);
  21. REQUIRE(123.45 == array[0].as<double>());
  22. REQUIRE(array[0].is<double>());
  23. REQUIRE_FALSE(array[0].is<bool>());
  24. }
  25. SECTION("bool") {
  26. array.add(true);
  27. REQUIRE(true == array[0].as<bool>());
  28. REQUIRE(array[0].is<bool>());
  29. REQUIRE_FALSE(array[0].is<int>());
  30. }
  31. SECTION("const char*") {
  32. const char* str = "hello";
  33. array.add(str);
  34. REQUIRE(str == array[0].as<std::string>());
  35. REQUIRE(array[0].is<const char*>());
  36. REQUIRE_FALSE(array[0].is<int>());
  37. }
  38. #ifdef HAS_VARIABLE_LENGTH_ARRAY
  39. SECTION("vla") {
  40. size_t i = 16;
  41. char vla[i];
  42. strcpy(vla, "world");
  43. array.add(vla);
  44. REQUIRE("world"_s == array[0]);
  45. }
  46. #endif
  47. SECTION("nested array") {
  48. JsonDocument doc2;
  49. JsonArray arr = doc2.to<JsonArray>();
  50. array.add(arr);
  51. REQUIRE(arr == array[0].as<JsonArray>());
  52. REQUIRE(array[0].is<JsonArray>());
  53. REQUIRE_FALSE(array[0].is<int>());
  54. }
  55. SECTION("nested object") {
  56. JsonDocument doc2;
  57. JsonObject obj = doc2.to<JsonObject>();
  58. array.add(obj);
  59. REQUIRE(obj == array[0].as<JsonObject>());
  60. REQUIRE(array[0].is<JsonObject>());
  61. REQUIRE_FALSE(array[0].is<int>());
  62. }
  63. SECTION("array subscript") {
  64. const char* str = "hello";
  65. JsonDocument doc2;
  66. JsonArray arr = doc2.to<JsonArray>();
  67. arr.add(str);
  68. array.add(arr[0]);
  69. REQUIRE(str == array[0]);
  70. }
  71. SECTION("object subscript") {
  72. const char* str = "hello";
  73. JsonDocument doc2;
  74. JsonObject obj = doc2.to<JsonObject>();
  75. obj["x"] = str;
  76. array.add(obj["x"]);
  77. REQUIRE(str == array[0]);
  78. }
  79. SECTION("should not duplicate const char*") {
  80. array.add("world");
  81. REQUIRE(spy.log() == AllocatorLog{
  82. Allocate(sizeofPool()),
  83. });
  84. }
  85. SECTION("should duplicate char*") {
  86. array.add(const_cast<char*>("world"));
  87. REQUIRE(spy.log() == AllocatorLog{
  88. Allocate(sizeofPool()),
  89. Allocate(sizeofString("world")),
  90. });
  91. }
  92. SECTION("should duplicate std::string") {
  93. array.add("world"_s);
  94. REQUIRE(spy.log() == AllocatorLog{
  95. Allocate(sizeofPool()),
  96. Allocate(sizeofString("world")),
  97. });
  98. }
  99. SECTION("should duplicate serialized(const char*)") {
  100. array.add(serialized("{}"));
  101. REQUIRE(spy.log() == AllocatorLog{
  102. Allocate(sizeofPool()),
  103. Allocate(sizeofString("{}")),
  104. });
  105. }
  106. SECTION("should duplicate serialized(char*)") {
  107. array.add(serialized(const_cast<char*>("{}")));
  108. REQUIRE(spy.log() == AllocatorLog{
  109. Allocate(sizeofPool()),
  110. Allocate(sizeofString("{}")),
  111. });
  112. }
  113. SECTION("should duplicate serialized(std::string)") {
  114. array.add(serialized("{}"_s));
  115. REQUIRE(spy.log() == AllocatorLog{
  116. Allocate(sizeofPool()),
  117. Allocate(sizeofString("{}")),
  118. });
  119. }
  120. SECTION("should duplicate serialized(std::string)") {
  121. array.add(serialized("\0XX"_s));
  122. REQUIRE(spy.log() == AllocatorLog{
  123. Allocate(sizeofPool()),
  124. Allocate(sizeofString(" XX")),
  125. });
  126. }
  127. }
  128. TEST_CASE("JsonArray::add<T>()") {
  129. JsonDocument doc;
  130. JsonArray array = doc.to<JsonArray>();
  131. SECTION("add<JsonArray>()") {
  132. JsonArray nestedArray = array.add<JsonArray>();
  133. nestedArray.add(1);
  134. nestedArray.add(2);
  135. REQUIRE(doc.as<std::string>() == "[[1,2]]");
  136. }
  137. SECTION("add<JsonObject>()") {
  138. JsonObject nestedObject = array.add<JsonObject>();
  139. nestedObject["a"] = 1;
  140. nestedObject["b"] = 2;
  141. REQUIRE(doc.as<std::string>() == "[{\"a\":1,\"b\":2}]");
  142. }
  143. SECTION("add<JsonVariant>()") {
  144. JsonVariant nestedVariant = array.add<JsonVariant>();
  145. nestedVariant.set(42);
  146. REQUIRE(doc.as<std::string>() == "[42]");
  147. }
  148. }
  149. TEST_CASE("JsonObject::add(JsonObject) ") {
  150. JsonDocument doc1;
  151. doc1["key1"_s] = "value1"_s;
  152. TimebombAllocator allocator(10);
  153. SpyingAllocator spy(&allocator);
  154. JsonDocument doc2(&spy);
  155. JsonArray array = doc2.to<JsonArray>();
  156. SECTION("success") {
  157. bool result = array.add(doc1.as<JsonObject>());
  158. REQUIRE(result == true);
  159. REQUIRE(doc2.as<std::string>() == "[{\"key1\":\"value1\"}]");
  160. REQUIRE(spy.log() == AllocatorLog{
  161. Allocate(sizeofPool()),
  162. Allocate(sizeofString("key1")),
  163. Allocate(sizeofString("value1")),
  164. });
  165. }
  166. SECTION("partial failure") { // issue #2081
  167. allocator.setCountdown(2);
  168. bool result = array.add(doc1.as<JsonObject>());
  169. REQUIRE(result == false);
  170. REQUIRE(doc2.as<std::string>() == "[]");
  171. REQUIRE(spy.log() == AllocatorLog{
  172. Allocate(sizeofPool()),
  173. Allocate(sizeofString("key1")),
  174. AllocateFail(sizeofString("value1")),
  175. Deallocate(sizeofString("key1")),
  176. });
  177. }
  178. SECTION("complete failure") {
  179. allocator.setCountdown(0);
  180. bool result = array.add(doc1.as<JsonObject>());
  181. REQUIRE(result == false);
  182. REQUIRE(doc2.as<std::string>() == "[]");
  183. REQUIRE(spy.log() == AllocatorLog{
  184. AllocateFail(sizeofPool()),
  185. });
  186. }
  187. }