string.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // ArduinoJson - https://arduinojson.org
  2. // Copyright © 2014-2023, Benoit BLANCHON
  3. // MIT License
  4. #define ARDUINOJSON_DECODE_UNICODE 1
  5. #include <ArduinoJson.h>
  6. #include <catch.hpp>
  7. #include "Allocators.hpp"
  8. using ArduinoJson::detail::sizeofArray;
  9. using ArduinoJson::detail::sizeofObject;
  10. using ArduinoJson::detail::sizeofString;
  11. TEST_CASE("Valid JSON strings value") {
  12. struct TestCase {
  13. const char* input;
  14. const char* expectedOutput;
  15. };
  16. TestCase testCases[] = {
  17. {"\"hello world\"", "hello world"},
  18. {"\'hello world\'", "hello world"},
  19. {"'\"'", "\""},
  20. {"'\\\\'", "\\"},
  21. {"'\\/'", "/"},
  22. {"'\\b'", "\b"},
  23. {"'\\f'", "\f"},
  24. {"'\\n'", "\n"},
  25. {"'\\r'", "\r"},
  26. {"'\\t'", "\t"},
  27. {"\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"", "1\"2\\3/4\b5\f6\n7\r8\t9"},
  28. {"'\\u0041'", "A"},
  29. {"'\\u00e4'", "\xc3\xa4"}, // ä
  30. {"'\\u00E4'", "\xc3\xa4"}, // ä
  31. {"'\\u3042'", "\xe3\x81\x82"}, // あ
  32. {"'\\ud83d\\udda4'", "\xf0\x9f\x96\xa4"}, // 🖤
  33. {"'\\uF053'", "\xef\x81\x93"}, // issue #1173
  34. {"'\\uF015'", "\xef\x80\x95"}, // issue #1173
  35. {"'\\uF054'", "\xef\x81\x94"}, // issue #1173
  36. };
  37. const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
  38. JsonDocument doc;
  39. for (size_t i = 0; i < testCount; i++) {
  40. const TestCase& testCase = testCases[i];
  41. CAPTURE(testCase.input);
  42. DeserializationError err = deserializeJson(doc, testCase.input);
  43. CHECK(err == DeserializationError::Ok);
  44. CHECK(doc.as<std::string>() == testCase.expectedOutput);
  45. }
  46. }
  47. TEST_CASE("\\u0000") {
  48. JsonDocument doc;
  49. DeserializationError err = deserializeJson(doc, "\"wx\\u0000yz\"");
  50. REQUIRE(err == DeserializationError::Ok);
  51. const char* result = doc.as<const char*>();
  52. CHECK(result[0] == 'w');
  53. CHECK(result[1] == 'x');
  54. CHECK(result[2] == 0);
  55. CHECK(result[3] == 'y');
  56. CHECK(result[4] == 'z');
  57. CHECK(result[5] == 0);
  58. CHECK(doc.as<JsonString>().size() == 5);
  59. CHECK(doc.as<std::string>().size() == 5);
  60. }
  61. TEST_CASE("Truncated JSON string") {
  62. const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000"};
  63. const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
  64. JsonDocument doc;
  65. for (size_t i = 0; i < testCount; i++) {
  66. const char* input = testCases[i];
  67. CAPTURE(input);
  68. REQUIRE(deserializeJson(doc, input) ==
  69. DeserializationError::IncompleteInput);
  70. }
  71. }
  72. TEST_CASE("Invalid JSON string") {
  73. const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'",
  74. "'\\u000G'", "'\\u000/'", "'\\x1234'"};
  75. const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
  76. JsonDocument doc;
  77. for (size_t i = 0; i < testCount; i++) {
  78. const char* input = testCases[i];
  79. CAPTURE(input);
  80. REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput);
  81. }
  82. }
  83. TEST_CASE("Allocation of the key fails") {
  84. TimebombAllocator timebombAllocator(0);
  85. SpyingAllocator spyingAllocator(&timebombAllocator);
  86. JsonDocument doc(&spyingAllocator);
  87. SECTION("Quoted string, first member") {
  88. REQUIRE(deserializeJson(doc, "{\"example\":1}") ==
  89. DeserializationError::NoMemory);
  90. REQUIRE(spyingAllocator.log() ==
  91. AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
  92. }
  93. SECTION("Quoted string, second member") {
  94. timebombAllocator.setCountdown(4);
  95. REQUIRE(deserializeJson(doc, "{\"hello\":1,\"world\"}") ==
  96. DeserializationError::NoMemory);
  97. REQUIRE(spyingAllocator.log() ==
  98. AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
  99. << AllocatorLog::Reallocate(sizeofString(31),
  100. sizeofString(5))
  101. << AllocatorLog::Allocate(sizeofPoolList())
  102. << AllocatorLog::Allocate(sizeofPool())
  103. << AllocatorLog::AllocateFail(sizeofString(31)));
  104. }
  105. SECTION("Non-Quoted string, first member") {
  106. REQUIRE(deserializeJson(doc, "{example:1}") ==
  107. DeserializationError::NoMemory);
  108. REQUIRE(spyingAllocator.log() ==
  109. AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
  110. }
  111. SECTION("Non-Quoted string, second member") {
  112. timebombAllocator.setCountdown(4);
  113. REQUIRE(deserializeJson(doc, "{hello:1,world}") ==
  114. DeserializationError::NoMemory);
  115. REQUIRE(spyingAllocator.log() ==
  116. AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
  117. << AllocatorLog::Reallocate(sizeofString(31),
  118. sizeofString(5))
  119. << AllocatorLog::Allocate(sizeofPoolList())
  120. << AllocatorLog::Allocate(sizeofPool())
  121. << AllocatorLog::AllocateFail(sizeofString(31)));
  122. }
  123. }
  124. TEST_CASE("String allocation fails") {
  125. SpyingAllocator spyingAllocator(FailingAllocator::instance());
  126. JsonDocument doc(&spyingAllocator);
  127. SECTION("Input is const char*") {
  128. REQUIRE(deserializeJson(doc, "\"hello\"") ==
  129. DeserializationError::NoMemory);
  130. REQUIRE(spyingAllocator.log() ==
  131. AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
  132. }
  133. }
  134. TEST_CASE("Deduplicate values") {
  135. JsonDocument doc;
  136. deserializeJson(doc, "[\"example\",\"example\"]");
  137. CHECK(doc.memoryUsage() == sizeofArray(2) + sizeofString(7));
  138. CHECK(doc[0].as<const char*>() == doc[1].as<const char*>());
  139. }
  140. TEST_CASE("Deduplicate keys") {
  141. JsonDocument doc;
  142. deserializeJson(doc, "[{\"example\":1},{\"example\":2}]");
  143. CHECK(doc.memoryUsage() ==
  144. 2 * sizeofObject(1) + sizeofArray(2) + sizeofString(7));
  145. const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
  146. const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
  147. CHECK(key1 == key2);
  148. }