subscript.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. TEST_CASE("JsonObject::operator[]") {
  8. SpyingAllocator spy;
  9. JsonDocument doc(&spy);
  10. JsonObject obj = doc.to<JsonObject>();
  11. SECTION("int") {
  12. obj["hello"] = 123;
  13. REQUIRE(123 == obj["hello"].as<int>());
  14. REQUIRE(true == obj["hello"].is<int>());
  15. REQUIRE(false == obj["hello"].is<bool>());
  16. }
  17. SECTION("volatile int") { // issue #415
  18. volatile int i = 123;
  19. obj["hello"] = i;
  20. REQUIRE(123 == obj["hello"].as<int>());
  21. REQUIRE(true == obj["hello"].is<int>());
  22. REQUIRE(false == obj["hello"].is<bool>());
  23. }
  24. SECTION("double") {
  25. obj["hello"] = 123.45;
  26. REQUIRE(true == obj["hello"].is<double>());
  27. REQUIRE(false == obj["hello"].is<long>());
  28. REQUIRE(123.45 == obj["hello"].as<double>());
  29. }
  30. SECTION("bool") {
  31. obj["hello"] = true;
  32. REQUIRE(true == obj["hello"].is<bool>());
  33. REQUIRE(false == obj["hello"].is<long>());
  34. REQUIRE(true == obj["hello"].as<bool>());
  35. }
  36. SECTION("const char*") {
  37. obj["hello"] = "h3110";
  38. REQUIRE(true == obj["hello"].is<const char*>());
  39. REQUIRE(false == obj["hello"].is<long>());
  40. REQUIRE(std::string("h3110") == obj["hello"].as<const char*>());
  41. }
  42. SECTION("array") {
  43. JsonDocument doc2;
  44. JsonArray arr = doc2.to<JsonArray>();
  45. obj["hello"] = arr;
  46. REQUIRE(arr == obj["hello"].as<JsonArray>());
  47. REQUIRE(true == obj["hello"].is<JsonArray>());
  48. REQUIRE(false == obj["hello"].is<JsonObject>());
  49. }
  50. SECTION("object") {
  51. JsonDocument doc2;
  52. JsonObject obj2 = doc2.to<JsonObject>();
  53. obj["hello"] = obj2;
  54. REQUIRE(obj2 == obj["hello"].as<JsonObject>());
  55. REQUIRE(true == obj["hello"].is<JsonObject>());
  56. REQUIRE(false == obj["hello"].is<JsonArray>());
  57. }
  58. SECTION("array subscript") {
  59. JsonDocument doc2;
  60. JsonArray arr = doc2.to<JsonArray>();
  61. arr.add(42);
  62. obj["a"] = arr[0];
  63. REQUIRE(42 == obj["a"]);
  64. }
  65. SECTION("object subscript") {
  66. JsonDocument doc2;
  67. JsonObject obj2 = doc2.to<JsonObject>();
  68. obj2["x"] = 42;
  69. obj["a"] = obj2["x"];
  70. REQUIRE(42 == obj["a"]);
  71. }
  72. SECTION("char key[]") { // issue #423
  73. char key[] = "hello";
  74. obj[key] = 42;
  75. REQUIRE(42 == obj[key]);
  76. }
  77. SECTION("should not duplicate const char*") {
  78. obj["hello"] = "world";
  79. REQUIRE(spy.log() == AllocatorLog{Allocate(sizeofPool())});
  80. }
  81. SECTION("should duplicate char* value") {
  82. obj["hello"] = const_cast<char*>("world");
  83. REQUIRE(spy.log() == AllocatorLog{
  84. Allocate(sizeofPool()),
  85. Allocate(sizeofString("world")),
  86. });
  87. }
  88. SECTION("should duplicate char* key") {
  89. obj[const_cast<char*>("hello")] = "world";
  90. REQUIRE(spy.log() == AllocatorLog{
  91. Allocate(sizeofString("hello")),
  92. Allocate(sizeofPool()),
  93. });
  94. }
  95. SECTION("should duplicate char* key&value") {
  96. obj[const_cast<char*>("hello")] = const_cast<char*>("world");
  97. REQUIRE(spy.log() == AllocatorLog{
  98. Allocate(sizeofString("hello")),
  99. Allocate(sizeofPool()),
  100. Allocate(sizeofString("world")),
  101. });
  102. }
  103. SECTION("should duplicate std::string value") {
  104. obj["hello"] = std::string("world");
  105. REQUIRE(spy.log() == AllocatorLog{
  106. Allocate(sizeofPool()),
  107. Allocate(sizeofString("world")),
  108. });
  109. }
  110. SECTION("should duplicate std::string key") {
  111. obj[std::string("hello")] = "world";
  112. REQUIRE(spy.log() == AllocatorLog{
  113. Allocate(sizeofString("hello")),
  114. Allocate(sizeofPool()),
  115. });
  116. }
  117. SECTION("should duplicate std::string key&value") {
  118. obj[std::string("hello")] = std::string("world");
  119. REQUIRE(spy.log() == AllocatorLog{
  120. Allocate(sizeofString("hello")),
  121. Allocate(sizeofPool()),
  122. Allocate(sizeofString("world")),
  123. });
  124. }
  125. SECTION("should duplicate a non-static JsonString key") {
  126. obj[JsonString("hello", JsonString::Copied)] = "world";
  127. REQUIRE(spy.log() == AllocatorLog{
  128. Allocate(sizeofString("hello")),
  129. Allocate(sizeofPool()),
  130. });
  131. }
  132. SECTION("should not duplicate a static JsonString key") {
  133. obj[JsonString("hello", JsonString::Linked)] = "world";
  134. REQUIRE(spy.log() == AllocatorLog{
  135. Allocate(sizeofPool()),
  136. });
  137. }
  138. SECTION("should ignore null key") {
  139. // object must have a value to make a call to strcmp()
  140. obj["dummy"] = 42;
  141. const char* null = 0;
  142. obj[null] = 666;
  143. REQUIRE(obj.size() == 1);
  144. REQUIRE(obj[null] == null);
  145. }
  146. SECTION("obj[key].to<JsonArray>()") {
  147. JsonArray arr = obj["hello"].to<JsonArray>();
  148. REQUIRE(arr.isNull() == false);
  149. }
  150. #if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
  151. !defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
  152. SECTION("obj[VLA] = str") {
  153. size_t i = 16;
  154. char vla[i];
  155. strcpy(vla, "hello");
  156. obj[vla] = "world";
  157. REQUIRE(std::string("world") == obj["hello"]);
  158. }
  159. SECTION("obj[str] = VLA") { // issue #416
  160. size_t i = 32;
  161. char vla[i];
  162. strcpy(vla, "world");
  163. obj["hello"] = vla;
  164. REQUIRE(std::string("world") == obj["hello"].as<const char*>());
  165. }
  166. SECTION("obj.set(VLA, str)") {
  167. size_t i = 16;
  168. char vla[i];
  169. strcpy(vla, "hello");
  170. obj[vla] = "world";
  171. REQUIRE(std::string("world") == obj["hello"]);
  172. }
  173. SECTION("obj.set(str, VLA)") {
  174. size_t i = 32;
  175. char vla[i];
  176. strcpy(vla, "world");
  177. obj["hello"].set(vla);
  178. REQUIRE(std::string("world") == obj["hello"].as<const char*>());
  179. }
  180. SECTION("obj[VLA]") {
  181. size_t i = 16;
  182. char vla[i];
  183. strcpy(vla, "hello");
  184. deserializeJson(doc, "{\"hello\":\"world\"}");
  185. obj = doc.as<JsonObject>();
  186. REQUIRE(std::string("world") == obj[vla]);
  187. }
  188. #endif
  189. SECTION("chain") {
  190. obj["hello"]["world"] = 123;
  191. REQUIRE(123 == obj["hello"]["world"].as<int>());
  192. REQUIRE(true == obj["hello"]["world"].is<int>());
  193. REQUIRE(false == obj["hello"]["world"].is<bool>());
  194. }
  195. }