add.cpp 6.1 KB

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