add.cpp 4.7 KB

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