| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // ArduinoJson - https://arduinojson.org
- // Copyright © 2014-2025, Benoit BLANCHON
- // MIT License
- #include <ArduinoJson.h>
- #include <catch.hpp>
- #include "Allocators.hpp"
- using namespace ArduinoJson::detail;
- TEST_CASE("deserialize JSON array") {
- SpyingAllocator spy;
- JsonDocument doc(&spy);
- SECTION("An empty array") {
- DeserializationError err = deserializeJson(doc, "[]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(0 == arr.size());
- }
- SECTION("Spaces") {
- SECTION("Before the opening bracket") {
- DeserializationError err = deserializeJson(doc, " []");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(0 == arr.size());
- }
- SECTION("Before first value") {
- DeserializationError err = deserializeJson(doc, "[ \t\r\n42]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(1 == arr.size());
- REQUIRE(arr[0] == 42);
- }
- SECTION("After first value") {
- DeserializationError err = deserializeJson(doc, "[42 \t\r\n]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(1 == arr.size());
- REQUIRE(arr[0] == 42);
- }
- }
- SECTION("Values types") {
- SECTION("On integer") {
- DeserializationError err = deserializeJson(doc, "[42]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(1 == arr.size());
- REQUIRE(arr[0] == 42);
- }
- SECTION("Two integers") {
- DeserializationError err = deserializeJson(doc, "[42,84]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == 42);
- REQUIRE(arr[1] == 84);
- }
- SECTION("Float") {
- DeserializationError err = deserializeJson(doc, "[4.2,1e2]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0].as<float>() == Approx(4.2f));
- REQUIRE(arr[1] == 1e2f);
- REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofPool()),
- Reallocate(sizeofPool(), sizeofPool(2)),
- });
- }
- SECTION("Double") {
- DeserializationError err = deserializeJson(doc, "[4.2123456,-7E89]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0].as<double>() == Approx(4.2123456));
- REQUIRE(arr[1] == -7E89);
- REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofPool<VariantData>()),
- Allocate(sizeofPool<EightByteValue>()),
- Reallocate(sizeofPool<VariantData>(),
- sizeofPool<VariantData>(2)),
- Reallocate(sizeofPool<EightByteValue>(),
- sizeofPool<EightByteValue>(2)),
- });
- }
- SECTION("Unsigned long") {
- DeserializationError err = deserializeJson(doc, "[4294967295]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(1 == arr.size());
- REQUIRE(arr[0] == 4294967295UL);
- }
- SECTION("Boolean") {
- DeserializationError err = deserializeJson(doc, "[true,false]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == true);
- REQUIRE(arr[1] == false);
- }
- SECTION("Null") {
- DeserializationError err = deserializeJson(doc, "[null,null]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0].as<const char*>() == 0);
- REQUIRE(arr[1].as<const char*>() == 0);
- }
- }
- SECTION("Quotes") {
- SECTION("Double quotes") {
- DeserializationError err =
- deserializeJson(doc, "[ \"hello\" , \"world\" ]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == "hello");
- REQUIRE(arr[1] == "world");
- }
- SECTION("Single quotes") {
- DeserializationError err = deserializeJson(doc, "[ 'hello' , 'world' ]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == "hello");
- REQUIRE(arr[1] == "world");
- }
- SECTION("No quotes") {
- DeserializationError err = deserializeJson(doc, "[ hello , world ]");
- REQUIRE(err == DeserializationError::InvalidInput);
- }
- SECTION("Double quotes (empty strings)") {
- DeserializationError err = deserializeJson(doc, "[\"\",\"\"]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == "");
- REQUIRE(arr[1] == "");
- }
- SECTION("Single quotes (empty strings)") {
- DeserializationError err = deserializeJson(doc, "[\'\',\'\']");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == "");
- REQUIRE(arr[1] == "");
- }
- SECTION("No quotes (empty strings)") {
- DeserializationError err = deserializeJson(doc, "[,]");
- REQUIRE(err == DeserializationError::InvalidInput);
- }
- SECTION("Closing single quotes missing") {
- DeserializationError err = deserializeJson(doc, "[\"]");
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- SECTION("Closing double quotes missing") {
- DeserializationError err = deserializeJson(doc, "[\']");
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- }
- SECTION("Premature null-terminator") {
- SECTION("After opening bracket") {
- DeserializationError err = deserializeJson(doc, "[");
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- SECTION("After value") {
- DeserializationError err = deserializeJson(doc, "[1");
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- SECTION("After comma") {
- DeserializationError err = deserializeJson(doc, "[1,");
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- }
- SECTION("Premature end of input") {
- const char* input = "[1,2]";
- SECTION("After opening bracket") {
- DeserializationError err = deserializeJson(doc, input, 1);
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- SECTION("After value") {
- DeserializationError err = deserializeJson(doc, input, 2);
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- SECTION("After comma") {
- DeserializationError err = deserializeJson(doc, input, 3);
- REQUIRE(err == DeserializationError::IncompleteInput);
- }
- }
- SECTION("Misc") {
- SECTION("Nested objects") {
- char jsonString[] =
- " [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";
- DeserializationError err = deserializeJson(doc, jsonString);
- JsonArray arr = doc.as<JsonArray>();
- JsonObject object1 = arr[0];
- const JsonObject object2 = arr[1];
- JsonObject object3 = arr[2];
- REQUIRE(err == DeserializationError::Ok);
- REQUIRE(object1.isNull() == false);
- REQUIRE(object2.isNull() == false);
- REQUIRE(object3.isNull() == true);
- REQUIRE(2 == object1.size());
- REQUIRE(2 == object2.size());
- REQUIRE(0 == object3.size());
- REQUIRE(1 == object1["a"].as<int>());
- REQUIRE(2 == object1["b"].as<int>());
- REQUIRE(3 == object2["c"].as<int>());
- REQUIRE(4 == object2["d"].as<int>());
- REQUIRE(0 == object3["e"].as<int>());
- }
- }
- SECTION("Should clear the JsonArray") {
- deserializeJson(doc, "[1,2,3,4]");
- spy.clearLog();
- deserializeJson(doc, "[]");
- JsonArray arr = doc.as<JsonArray>();
- REQUIRE(arr.size() == 0);
- REQUIRE(spy.log() == AllocatorLog{
- Deallocate(sizeofArray(4)),
- });
- }
- }
- TEST_CASE("deserialize JSON array under memory constraints") {
- TimebombAllocator timebomb(100);
- SpyingAllocator spy(&timebomb);
- JsonDocument doc(&spy);
- SECTION("empty array requires no allocation") {
- timebomb.setCountdown(0);
- char input[] = "[]";
- DeserializationError err = deserializeJson(doc, input);
- REQUIRE(err == DeserializationError::Ok);
- }
- SECTION("allocation of pool list fails") {
- timebomb.setCountdown(0);
- char input[] = "[1]";
- DeserializationError err = deserializeJson(doc, input);
- REQUIRE(err == DeserializationError::NoMemory);
- REQUIRE(doc.as<std::string>() == "[]");
- }
- SECTION("allocation of pool fails") {
- timebomb.setCountdown(0);
- char input[] = "[1]";
- DeserializationError err = deserializeJson(doc, input);
- REQUIRE(err == DeserializationError::NoMemory);
- REQUIRE(doc.as<std::string>() == "[]");
- }
- SECTION("allocation of string fails in array") {
- timebomb.setCountdown(1);
- char input[] = "[0,\"hi!\"]";
- DeserializationError err = deserializeJson(doc, input);
- REQUIRE(err == DeserializationError::NoMemory);
- REQUIRE(doc.as<std::string>() == "[0,null]");
- }
- SECTION("don't store space characters") {
- deserializeJson(doc, " [ \"1234567\" ] ");
- REQUIRE(spy.log() ==
- AllocatorLog{
- Allocate(sizeofPool()),
- Allocate(sizeofStringBuffer()),
- Reallocate(sizeofStringBuffer(), sizeofString("1234567")),
- Reallocate(sizeofPool(), sizeofArray(1)),
- });
- }
- }
|