subscript.cpp 6.5 KB

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