added library json
This commit is contained in:
@ -0,0 +1,28 @@
|
||||
# ArduinoJson - https://arduinojson.org
|
||||
# Copyright © 2014-2023, Benoit BLANCHON
|
||||
# MIT License
|
||||
|
||||
add_executable(JsonDeserializerTests
|
||||
array.cpp
|
||||
array_static.cpp
|
||||
DeserializationError.cpp
|
||||
filter.cpp
|
||||
incomplete_input.cpp
|
||||
input_types.cpp
|
||||
invalid_input.cpp
|
||||
misc.cpp
|
||||
nestingLimit.cpp
|
||||
number.cpp
|
||||
object.cpp
|
||||
object_static.cpp
|
||||
string.cpp
|
||||
)
|
||||
|
||||
set_target_properties(JsonDeserializerTests PROPERTIES UNITY_BUILD OFF)
|
||||
|
||||
add_test(JsonDeserializer JsonDeserializerTests)
|
||||
|
||||
set_tests_properties(JsonDeserializer
|
||||
PROPERTIES
|
||||
LABELS "Catch"
|
||||
)
|
||||
@ -0,0 +1,122 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
void testStringification(DeserializationError error, std::string expected) {
|
||||
REQUIRE(error.c_str() == expected);
|
||||
}
|
||||
|
||||
void testBoolification(DeserializationError error, bool expected) {
|
||||
// DeserializationError on left-hand side
|
||||
CHECK(bool(error) == expected);
|
||||
CHECK(bool(error) != !expected);
|
||||
CHECK(!bool(error) == !expected);
|
||||
|
||||
// DeserializationError on right-hand side
|
||||
CHECK(expected == bool(error));
|
||||
CHECK(!expected != bool(error));
|
||||
CHECK(!expected == !bool(error));
|
||||
}
|
||||
|
||||
#define TEST_STRINGIFICATION(symbol) \
|
||||
testStringification(DeserializationError::symbol, #symbol)
|
||||
|
||||
#define TEST_BOOLIFICATION(symbol, expected) \
|
||||
testBoolification(DeserializationError::symbol, expected)
|
||||
|
||||
TEST_CASE("DeserializationError") {
|
||||
SECTION("c_str()") {
|
||||
TEST_STRINGIFICATION(Ok);
|
||||
TEST_STRINGIFICATION(EmptyInput);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
}
|
||||
|
||||
SECTION("as boolean") {
|
||||
TEST_BOOLIFICATION(Ok, false);
|
||||
TEST_BOOLIFICATION(EmptyInput, true);
|
||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||
TEST_BOOLIFICATION(InvalidInput, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
}
|
||||
|
||||
SECTION("ostream DeserializationError") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError(DeserializationError::InvalidInput);
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
}
|
||||
|
||||
SECTION("ostream DeserializationError::Code") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError::InvalidInput;
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
}
|
||||
|
||||
SECTION("switch") {
|
||||
DeserializationError err = DeserializationError::InvalidInput;
|
||||
switch (err.code()) {
|
||||
case DeserializationError::InvalidInput:
|
||||
SUCCEED();
|
||||
break;
|
||||
default:
|
||||
FAIL();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Use in a condition") {
|
||||
DeserializationError invalidInput(DeserializationError::InvalidInput);
|
||||
DeserializationError ok(DeserializationError::Ok);
|
||||
|
||||
SECTION("if (!err)") {
|
||||
if (!invalidInput)
|
||||
FAIL();
|
||||
}
|
||||
|
||||
SECTION("if (err)") {
|
||||
if (ok)
|
||||
FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Comparisons") {
|
||||
DeserializationError invalidInput(DeserializationError::InvalidInput);
|
||||
DeserializationError ok(DeserializationError::Ok);
|
||||
|
||||
SECTION("DeserializationError == Code") {
|
||||
REQUIRE(invalidInput == DeserializationError::InvalidInput);
|
||||
REQUIRE(ok == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Code == DeserializationError") {
|
||||
REQUIRE(DeserializationError::InvalidInput == invalidInput);
|
||||
REQUIRE(DeserializationError::Ok == ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError != Code") {
|
||||
REQUIRE(invalidInput != DeserializationError::Ok);
|
||||
REQUIRE(ok != DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Code != DeserializationError") {
|
||||
REQUIRE(DeserializationError::Ok != invalidInput);
|
||||
REQUIRE(DeserializationError::InvalidInput != ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError == DeserializationError") {
|
||||
REQUIRE_FALSE(invalidInput == ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError != DeserializationError") {
|
||||
REQUIRE(invalidInput != ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
253
libraries/ArduinoJson/extras/tests/JsonDeserializer/array.cpp
Normal file
253
libraries/ArduinoJson/extras/tests/JsonDeserializer/array.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON array") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
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("Double") {
|
||||
DeserializationError err = deserializeJson(doc, "[4.2,1e2]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == 4.2);
|
||||
REQUIRE(arr[1] == 1e2);
|
||||
}
|
||||
|
||||
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]");
|
||||
deserializeJson(doc, "[]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(arr.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
SECTION("BufferOfTheRightSizeForEmptyArray") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "[]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForArrayWithOneValue") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "[1]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithOneValue") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
char input[] = "[1]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForArrayWithNestedObject") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0) + JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "[{}]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithNestedObject") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "[{}]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("CopyStringNotSpaces") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
deserializeJson(doc, " [ \"1234567\" ] ");
|
||||
|
||||
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(7) == doc.memoryUsage());
|
||||
// note: we use a string of 8 bytes to be sure that the StaticMemoryPool
|
||||
// will not insert bytes to enforce alignement
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonArray") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(4)> doc;
|
||||
char input[] = "[1,2,3,4]";
|
||||
|
||||
deserializeJson(doc, input);
|
||||
deserializeJson(doc, "[]");
|
||||
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
REQUIRE(arr.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Array") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
|
||||
char input[] = "[1,2]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonArray>());
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
|
||||
REQUIRE(arr[0] == 1);
|
||||
REQUIRE(arr[1] == 2);
|
||||
}
|
||||
}
|
||||
809
libraries/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp
Normal file
809
libraries/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp
Normal file
@ -0,0 +1,809 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_ENABLE_COMMENTS 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("Filtering") {
|
||||
struct TestCase {
|
||||
const char* input;
|
||||
const char* filter;
|
||||
uint8_t nestingLimit;
|
||||
DeserializationError error;
|
||||
const char* output;
|
||||
size_t memoryUsage;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
TestCase testCases[] = {
|
||||
{
|
||||
"{\"hello\":\"world\"}", // 1. input
|
||||
"null", // 2. filter
|
||||
10, // 3. nestingLimit
|
||||
DeserializationError::Ok, // 4. error
|
||||
"null", // 5. output
|
||||
0 // 6. memoryUsage
|
||||
},
|
||||
{
|
||||
"{\"hello\":\"world\"}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
"{\"abcdefg\":\"hijklmn\"}",
|
||||
"true",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"abcdefg\":\"hijklmn\"}",
|
||||
JSON_OBJECT_SIZE(1) + 16
|
||||
},
|
||||
{
|
||||
"{\"hello\":\"world\"}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// Input in an object, but filter wants an array
|
||||
"{\"hello\":\"world\"}",
|
||||
"[]",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// Member is a string, but filter wants an array
|
||||
"{\"example\":\"example\"}",
|
||||
"{\"example\":[true]}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":null}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// Member is a number, but filter wants an array
|
||||
"{\"example\":42}",
|
||||
"{\"example\":[true]}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":null}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// Input is an array, but filter wants an object
|
||||
"[\"hello\",\"world\"]",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// Input is a bool, but filter wants an object
|
||||
"true",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// Input is a string, but filter wants an object
|
||||
"\"hello\"",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// skip an integer
|
||||
"{\"an_integer\":666,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// skip a float
|
||||
"{\"a_float\":12.34e-6,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// skip false
|
||||
"{\"a_bool\":false,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// skip true
|
||||
"{\"a_bool\":true,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// skip null
|
||||
"{\"a_bool\":null,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip a double-quoted string
|
||||
"{\"a_double_quoted_string\":\"hello\",example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip a single-quoted string
|
||||
"{\"a_single_quoted_string\":'hello',example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an empty array
|
||||
"{\"an_empty_array\":[],example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an empty array with spaces in it
|
||||
"{\"an_empty_array\":[\t],example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an array
|
||||
"{\"an_array\":[1,2,3],example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an array with spaces in it
|
||||
"{\"an_array\": [ 1 , 2 , 3 ] ,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an empty object
|
||||
"{\"an_empty_object\":{},example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an empty object with spaces in it
|
||||
"{\"an_empty_object\":{ },example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// can skip an object
|
||||
"{\"an_object\":{a:1,'b':2,\"c\":3},example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// skip an object with spaces in it
|
||||
"{\"an_object\" : { a : 1 , 'b' : 2 , \"c\" : 3 } ,example:42}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":42}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
"{\"an_integer\": 0,\"example\":{\"type\":\"int\",\"outcome\":42}}",
|
||||
"{\"example\":{\"outcome\":true}}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":{\"outcome\":42}}",
|
||||
2 * JSON_OBJECT_SIZE(1) + 16
|
||||
},
|
||||
{
|
||||
// wildcard
|
||||
"{\"example\":{\"type\":\"int\",\"outcome\":42}}",
|
||||
"{\"*\":{\"outcome\":true}}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":{\"outcome\":42}}",
|
||||
2 * JSON_OBJECT_SIZE(1) + 16
|
||||
},
|
||||
{
|
||||
// exclusion filter (issue #1628)
|
||||
"{\"example\":1,\"ignored\":2}",
|
||||
"{\"*\":true,\"ignored\":false}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":1}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// only the first element of array counts
|
||||
"[1,2,3]",
|
||||
"[true, false]",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"[1,2,3]",
|
||||
JSON_ARRAY_SIZE(3)
|
||||
},
|
||||
{
|
||||
// only the first element of array counts
|
||||
"[1,2,3]",
|
||||
"[false, true]",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// filter members of object in array
|
||||
"[{\"example\":1,\"ignore\":2},{\"example\":3,\"ignore\":4}]",
|
||||
"[{\"example\":true}]",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"[{\"example\":1},{\"example\":3}]",
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
"[',2,3]",
|
||||
"[false,true]",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
"[\",2,3]",
|
||||
"[false,true]",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// detect errors in skipped value
|
||||
"[!,2,\\]",
|
||||
"[false]",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// detect incomplete string event if it's skipped
|
||||
"\"ABC",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// detect incomplete string event if it's skipped
|
||||
"'ABC",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// handle escaped quotes
|
||||
"'A\\'BC'",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// handle escaped quotes
|
||||
"\"A\\\"BC\"",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// detect incomplete string in presence of escaped quotes
|
||||
"'A\\'BC",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// detect incomplete string in presence of escaped quotes
|
||||
"\"A\\\"BC",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// skip empty array
|
||||
"[]",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// skip empty array with spaces
|
||||
" [ ] ",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// bubble up element error even if array is skipped
|
||||
"[1,'2,3]",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// bubble up member error even if object is skipped
|
||||
"{'hello':'worl}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// bubble up colon error even if object is skipped
|
||||
"{'hello','world'}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// bubble up key error even if object is skipped
|
||||
"{'hello:1}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// detect invalid value in skipped object
|
||||
"{'hello':!}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// ignore invalid value in skipped object
|
||||
"{'hello':\\}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored objects
|
||||
"{}",
|
||||
"false",
|
||||
0,
|
||||
DeserializationError::TooDeep,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored objects
|
||||
"{'hello':{}}",
|
||||
"false",
|
||||
1,
|
||||
DeserializationError::TooDeep,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored values in objects
|
||||
"{'hello':{}}",
|
||||
"{}",
|
||||
1,
|
||||
DeserializationError::TooDeep,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored arrays
|
||||
"[]",
|
||||
"false",
|
||||
0,
|
||||
DeserializationError::TooDeep,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored arrays
|
||||
"[[]]",
|
||||
"false",
|
||||
1,
|
||||
DeserializationError::TooDeep,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// check nesting limit even for ignored values in arrays
|
||||
"[[]]",
|
||||
"[]",
|
||||
1,
|
||||
DeserializationError::TooDeep,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// supports back-slash at the end of skipped string
|
||||
"\"hell\\",
|
||||
"false",
|
||||
1,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// invalid comment at after an element in a skipped array
|
||||
"[1/]",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// incomplete comment at after an element in a skipped array
|
||||
"[1/*]",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// missing comma in a skipped array
|
||||
"[1 2]",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// invalid comment at the beginning of array
|
||||
"[/1]",
|
||||
"[false]",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// incomplete comment at the begining of an array
|
||||
"[/*]",
|
||||
"[false]",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"[]",
|
||||
JSON_ARRAY_SIZE(0)
|
||||
},
|
||||
{
|
||||
// invalid comment before key
|
||||
"{/1:2}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// incomplete comment before key
|
||||
"{/*:2}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// invalid comment after key
|
||||
"{\"example\"/1:2}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// incomplete comment after key
|
||||
"{\"example\"/*:2}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// invalid comment after colon
|
||||
"{\"example\":/12}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// incomplete comment after colon
|
||||
"{\"example\":/*2}",
|
||||
"{}",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// comment next to an integer
|
||||
"{\"ignore\":1//,\"example\":2\n}",
|
||||
"{\"example\":true}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// invalid comment after opening brace of a skipped object
|
||||
"{/1:2}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// incomplete after opening brace of a skipped object
|
||||
"{/*:2}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// invalid comment after key of a skipped object
|
||||
"{\"example\"/:2}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// incomplete comment after key of a skipped object
|
||||
"{\"example\"/*:2}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// invalid comment after value in a skipped object
|
||||
"{\"example\":2/}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// incomplete comment after value of a skipped object
|
||||
"{\"example\":2/*}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// incomplete comment after comma in skipped object
|
||||
"{\"example\":2,/*}",
|
||||
"false",
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"null",
|
||||
0
|
||||
},
|
||||
}; // clang-format on
|
||||
|
||||
for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
|
||||
CAPTURE(i);
|
||||
|
||||
DynamicJsonDocument filter(256);
|
||||
DynamicJsonDocument doc(256);
|
||||
TestCase& tc = testCases[i];
|
||||
|
||||
CAPTURE(tc.filter);
|
||||
REQUIRE(deserializeJson(filter, tc.filter) == DeserializationError::Ok);
|
||||
|
||||
CAPTURE(tc.input);
|
||||
CAPTURE(tc.nestingLimit);
|
||||
CHECK(deserializeJson(doc, tc.input, DeserializationOption::Filter(filter),
|
||||
DeserializationOption::NestingLimit(
|
||||
tc.nestingLimit)) == tc.error);
|
||||
|
||||
CHECK(doc.as<std::string>() == tc.output);
|
||||
CHECK(doc.memoryUsage() == tc.memoryUsage);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Zero-copy mode") { // issue #1697
|
||||
char input[] = "{\"include\":42,\"exclude\":666}";
|
||||
|
||||
StaticJsonDocument<256> filter;
|
||||
filter["include"] = true;
|
||||
|
||||
StaticJsonDocument<256> doc;
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, input, DeserializationOption::Filter(filter));
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(doc.as<std::string>() == "{\"include\":42}");
|
||||
}
|
||||
|
||||
TEST_CASE("Overloads") {
|
||||
StaticJsonDocument<256> doc;
|
||||
StaticJsonDocument<256> filter;
|
||||
|
||||
using namespace DeserializationOption;
|
||||
|
||||
// deserializeJson(..., Filter)
|
||||
|
||||
SECTION("const char*, Filter") {
|
||||
deserializeJson(doc, "{}", Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("const char*, size_t, Filter") {
|
||||
deserializeJson(doc, "{}", 2, Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("const std::string&, Filter") {
|
||||
deserializeJson(doc, std::string("{}"), Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("std::istream&, Filter") {
|
||||
std::stringstream s("{}");
|
||||
deserializeJson(doc, s, Filter(filter));
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("char[n], Filter") {
|
||||
size_t i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "{}");
|
||||
deserializeJson(doc, vla, Filter(filter));
|
||||
}
|
||||
#endif
|
||||
|
||||
// deserializeJson(..., Filter, NestingLimit)
|
||||
|
||||
SECTION("const char*, Filter, NestingLimit") {
|
||||
deserializeJson(doc, "{}", Filter(filter), NestingLimit(5));
|
||||
}
|
||||
|
||||
SECTION("const char*, size_t, Filter, NestingLimit") {
|
||||
deserializeJson(doc, "{}", 2, Filter(filter), NestingLimit(5));
|
||||
}
|
||||
|
||||
SECTION("const std::string&, Filter, NestingLimit") {
|
||||
deserializeJson(doc, std::string("{}"), Filter(filter), NestingLimit(5));
|
||||
}
|
||||
|
||||
SECTION("std::istream&, Filter, NestingLimit") {
|
||||
std::stringstream s("{}");
|
||||
deserializeJson(doc, s, Filter(filter), NestingLimit(5));
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("char[n], Filter, NestingLimit") {
|
||||
size_t i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "{}");
|
||||
deserializeJson(doc, vla, Filter(filter), NestingLimit(5));
|
||||
}
|
||||
#endif
|
||||
|
||||
// deserializeJson(..., NestingLimit, Filter)
|
||||
|
||||
SECTION("const char*, NestingLimit, Filter") {
|
||||
deserializeJson(doc, "{}", NestingLimit(5), Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("const char*, size_t, NestingLimit, Filter") {
|
||||
deserializeJson(doc, "{}", 2, NestingLimit(5), Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("const std::string&, NestingLimit, Filter") {
|
||||
deserializeJson(doc, std::string("{}"), NestingLimit(5), Filter(filter));
|
||||
}
|
||||
|
||||
SECTION("std::istream&, NestingLimit, Filter") {
|
||||
std::stringstream s("{}");
|
||||
deserializeJson(doc, s, NestingLimit(5), Filter(filter));
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("char[n], NestingLimit, Filter") {
|
||||
size_t i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "{}");
|
||||
deserializeJson(doc, vla, NestingLimit(5), Filter(filter));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Truncated JSON input") {
|
||||
const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000",
|
||||
// false
|
||||
"f", "fa", "fal", "fals",
|
||||
// true
|
||||
"t", "tr", "tru",
|
||||
// null
|
||||
"n", "nu", "nul",
|
||||
// object
|
||||
"{", "{a", "{a:", "{a:1", "{a:1,", "{a:1,"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) ==
|
||||
DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,222 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
#include "CustomReader.hpp"
|
||||
|
||||
TEST_CASE("deserializeJson(char*)") {
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
SECTION("should not duplicate strings") {
|
||||
char input[] = "{\"hello\":\"world\"}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(doc.memoryUsage() == JSON_OBJECT_SIZE(1));
|
||||
CHECK(doc.as<JsonVariant>().memoryUsage() ==
|
||||
JSON_OBJECT_SIZE(1)); // issue #1318
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(unsigned char*, unsigned int)") { // issue #1897
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
unsigned char input[] = "{\"hello\":\"world\"}";
|
||||
unsigned char* input_ptr = input;
|
||||
unsigned int size = sizeof(input);
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input_ptr, size);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(uint8_t*, size_t)") { // issue #1898
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
uint8_t input[] = "{\"hello\":\"world\"}";
|
||||
uint8_t* input_ptr = input;
|
||||
size_t size = sizeof(input);
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input_ptr, size);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(const std::string&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("should accept const string") {
|
||||
const std::string input("[42]");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should accept temporary string") {
|
||||
DeserializationError err = deserializeJson(doc, std::string("[42]"));
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should duplicate content") {
|
||||
std::string input("[\"hello\"]");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
input[2] = 'X'; // alter the string tomake sure we made a copy
|
||||
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(std::istream&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("array") {
|
||||
std::istringstream json(" [ 42 ] ");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(42 == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("object") {
|
||||
std::istringstream json(" { hello : 'world' }");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == obj.size());
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace of an empty object") {
|
||||
std::istringstream json("{}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace") {
|
||||
std::istringstream json("{\"hello\":\"world\"}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket of an empty array") {
|
||||
std::istringstream json("[]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket") {
|
||||
std::istringstream json("[\"hello\",\"world\"]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing quote") {
|
||||
std::istringstream json("\"hello\"123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
TEST_CASE("deserializeJson(VLA)") {
|
||||
size_t i = 9;
|
||||
char vla[i];
|
||||
strcpy(vla, "{\"a\":42}");
|
||||
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
DeserializationError err = deserializeJson(doc, vla);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("deserializeJson(CustomReader)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
CustomReader reader("[4,2]");
|
||||
DeserializationError err = deserializeJson(doc, reader);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.size() == 2);
|
||||
REQUIRE(doc[0] == 4);
|
||||
REQUIRE(doc[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, MemberProxy)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err = deserializeJson(doc2, doc1["payload"]);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, JsonVariant)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err =
|
||||
deserializeJson(doc2, doc1["payload"].as<JsonVariant>());
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, JsonVariantConst)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err =
|
||||
deserializeJson(doc2, doc1["payload"].as<JsonVariantConst>());
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, ElementProxy)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1[0] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err = deserializeJson(doc2, doc1[0]);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Invalid JSON input") {
|
||||
const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'", "'\\u000G'",
|
||||
"'\\u000/'", "\\x1234", "6a9", "1,",
|
||||
"nulL", "tru3", "fals3", "2]",
|
||||
"3}"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid JSON input that should pass") {
|
||||
const char* testCases[] = {
|
||||
"'\\ud83d'", // leading surrogate without a trailing surrogate
|
||||
"'\\udda4'", // trailing surrogate without a leading surrogate
|
||||
"'\\ud83d\\ud83d'", // two leading surrogates
|
||||
};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
117
libraries/ArduinoJson/extras/tests/JsonDeserializer/misc.cpp
Normal file
117
libraries/ArduinoJson/extras/tests/JsonDeserializer/misc.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Edge cases") {
|
||||
SECTION("null char*") {
|
||||
DeserializationError err = deserializeJson(doc, static_cast<char*>(0));
|
||||
|
||||
REQUIRE(err != DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("null const char*") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(err != DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Empty input") {
|
||||
DeserializationError err = deserializeJson(doc, "");
|
||||
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("Only spaces") {
|
||||
DeserializationError err = deserializeJson(doc, " \t\n\r");
|
||||
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("issue #628") {
|
||||
DeserializationError err = deserializeJson(doc, "null");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == false);
|
||||
}
|
||||
|
||||
SECTION("Garbage") {
|
||||
DeserializationError err = deserializeJson(doc, "%*$£¤");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Booleans") {
|
||||
SECTION("True") {
|
||||
DeserializationError err = deserializeJson(doc, "true");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<bool>());
|
||||
REQUIRE(doc.as<bool>() == true);
|
||||
}
|
||||
|
||||
SECTION("False") {
|
||||
DeserializationError err = deserializeJson(doc, "false");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<bool>());
|
||||
REQUIRE(doc.as<bool>() == false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null-terminator") {
|
||||
SECTION("In escape sequence") {
|
||||
DeserializationError err = deserializeJson(doc, "\"\\");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "\"hello");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "'hello");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature end of input") {
|
||||
SECTION("In escape sequence") {
|
||||
DeserializationError err = deserializeJson(doc, "\"\\n\"", 2);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "\"hello\"", 6);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "'hello'", 6);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonVariant") {
|
||||
deserializeJson(doc, "[1,2,3]");
|
||||
deserializeJson(doc, "{}");
|
||||
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression);
|
||||
#define SHOULD_FAIL(expression) \
|
||||
REQUIRE(DeserializationError::TooDeep == expression);
|
||||
|
||||
TEST_CASE("JsonDeserializer nesting") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Input = const char*") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, "\"toto\"", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "123", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "true", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("char* and size_t") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, "\"toto\"", 6, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "123", 3, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "true", 4, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[]", 2, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{}", 2, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", 8, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", 8, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", 11, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", 11, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", 10, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", 12, nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Input = std::string") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("\"toto\""), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("123"), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("true"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":{}}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":[]}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[[\"toto\"]]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[{\"toto\":1}]"), nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Input = std::istream") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
std::istringstream good("true");
|
||||
std::istringstream bad("[]");
|
||||
SHOULD_WORK(deserializeJson(doc, good, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
std::istringstream good("[\"toto\"]");
|
||||
std::istringstream bad("{\"toto\":{}}");
|
||||
SHOULD_WORK(deserializeJson(doc, good, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
|
||||
}
|
||||
}
|
||||
}
|
||||
133
libraries/ArduinoJson/extras/tests/JsonDeserializer/number.cpp
Normal file
133
libraries/ArduinoJson/extras/tests/JsonDeserializer/number.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#define ARDUINOJSON_ENABLE_NAN 1
|
||||
#define ARDUINOJSON_ENABLE_INFINITY 1
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <limits.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
namespace my {
|
||||
using ArduinoJson::detail::isinf;
|
||||
using ArduinoJson::detail::isnan;
|
||||
} // namespace my
|
||||
|
||||
TEST_CASE("deserialize an integer") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Integer") {
|
||||
SECTION("0") {
|
||||
DeserializationError err = deserializeJson(doc, "0");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<int>() == true);
|
||||
REQUIRE(doc.as<int>() == 0);
|
||||
REQUIRE(doc.as<std::string>() == "0"); // issue #808
|
||||
}
|
||||
|
||||
SECTION("Negative") {
|
||||
DeserializationError err = deserializeJson(doc, "-42");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<int>());
|
||||
REQUIRE_FALSE(doc.is<bool>());
|
||||
REQUIRE(doc.as<int>() == -42);
|
||||
}
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
SECTION("LONG_MAX") {
|
||||
DeserializationError err = deserializeJson(doc, "2147483647");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == true);
|
||||
REQUIRE(doc.as<long>() == LONG_MAX);
|
||||
}
|
||||
|
||||
SECTION("LONG_MAX + 1") {
|
||||
DeserializationError err = deserializeJson(doc, "2147483648");
|
||||
|
||||
CAPTURE(LONG_MIN);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LONG_MIN == -2147483648
|
||||
SECTION("LONG_MIN") {
|
||||
DeserializationError err = deserializeJson(doc, "-2147483648");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == true);
|
||||
REQUIRE(doc.as<long>() == LONG_MIN);
|
||||
}
|
||||
|
||||
SECTION("LONG_MIN - 1") {
|
||||
DeserializationError err = deserializeJson(doc, "-2147483649");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == 4294967295
|
||||
SECTION("ULONG_MAX") {
|
||||
DeserializationError err = deserializeJson(doc, "4294967295");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<unsigned long>() == true);
|
||||
REQUIRE(doc.as<unsigned long>() == ULONG_MAX);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
}
|
||||
|
||||
SECTION("ULONG_MAX + 1") {
|
||||
DeserializationError err = deserializeJson(doc, "4294967296");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<unsigned long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("Floats") {
|
||||
SECTION("Double") {
|
||||
DeserializationError err = deserializeJson(doc, "-1.23e+4");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE_FALSE(doc.is<int>());
|
||||
REQUIRE(doc.is<double>());
|
||||
REQUIRE(doc.as<double>() == Approx(-1.23e+4));
|
||||
}
|
||||
|
||||
SECTION("NaN") {
|
||||
DeserializationError err = deserializeJson(doc, "NaN");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isnan(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("+Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "+Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("-Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "-Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
315
libraries/ArduinoJson/extras/tests/JsonDeserializer/object.cpp
Normal file
315
libraries/ArduinoJson/extras/tests/JsonDeserializer/object.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON object") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("An empty object") {
|
||||
DeserializationError err = deserializeJson(doc, "{}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Quotes") {
|
||||
SECTION("Double quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\":\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Single quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{'key':'value'}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("No quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{key:'value'}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("No quotes, allow underscore in key") {
|
||||
DeserializationError err = deserializeJson(doc, "{_k_e_y_:42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["_k_e_y_"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Spaces") {
|
||||
SECTION("Before the key") {
|
||||
DeserializationError err = deserializeJson(doc, "{ \"key\":\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("After the key") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\" :\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Before the value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\": \"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("After the value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\":\"value\" }");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Before the comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
|
||||
SECTION("After the comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\", \"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Values types") {
|
||||
SECTION("String") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
|
||||
SECTION("Integer") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":42,\"key2\":-42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == 42);
|
||||
REQUIRE(obj["key2"] == -42);
|
||||
}
|
||||
|
||||
SECTION("Double") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":12.345,\"key2\":-7E89}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == 12.345);
|
||||
REQUIRE(obj["key2"] == -7E89);
|
||||
}
|
||||
|
||||
SECTION("Booleans") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":true,\"key2\":false}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == true);
|
||||
REQUIRE(obj["key2"] == false);
|
||||
}
|
||||
|
||||
SECTION("Null") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":null,\"key2\":null}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"].as<const char*>() == 0);
|
||||
REQUIRE(obj["key2"].as<const char*>() == 0);
|
||||
}
|
||||
|
||||
SECTION("Array") {
|
||||
char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } ";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, jsonString);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
JsonArray array1 = obj["ab"];
|
||||
const JsonArray array2 = obj["cd"];
|
||||
JsonArray array3 = obj["ef"];
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
|
||||
REQUIRE(array1.isNull() == false);
|
||||
REQUIRE(array2.isNull() == false);
|
||||
REQUIRE(array3.isNull() == true);
|
||||
|
||||
REQUIRE(2 == array1.size());
|
||||
REQUIRE(2 == array2.size());
|
||||
REQUIRE(0 == array3.size());
|
||||
|
||||
REQUIRE(1 == array1[0].as<int>());
|
||||
REQUIRE(2 == array1[1].as<int>());
|
||||
|
||||
REQUIRE(3 == array2[0].as<int>());
|
||||
REQUIRE(4 == array2[1].as<int>());
|
||||
|
||||
REQUIRE(0 == array3[0].as<int>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null terminator") {
|
||||
SECTION("After opening brace") {
|
||||
DeserializationError err = deserializeJson(doc, "{");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After key") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\"");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\",");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("A quoted key without value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("A non-quoted key without value") {
|
||||
DeserializationError err = deserializeJson(doc, "{key}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("A dangling comma") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key1\":\"value1\",}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("null as a key") {
|
||||
DeserializationError err = deserializeJson(doc, "{null:\"value\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Repeated key") {
|
||||
DeserializationError err = deserializeJson(doc, "{a:{b:{c:1}},a:2}");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc["a"] == 2);
|
||||
}
|
||||
|
||||
SECTION("Repeated key with zero copy mode") { // issue #1697
|
||||
char input[] = "{a:{b:{c:1}},a:2}";
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc["a"] == 2);
|
||||
}
|
||||
|
||||
SECTION("NUL in keys") { // we don't support NULs in keys
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"x\\u0000a\":1,\"x\\u0000b\":2}");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.as<std::string>() == "{\"x\":2}");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
deserializeJson(doc, "{}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Issue #1335") {
|
||||
std::string json("{\"a\":{},\"b\":{}}");
|
||||
deserializeJson(doc, json);
|
||||
CHECK(doc.as<std::string>() == json);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON object with StaticJsonDocument") {
|
||||
SECTION("BufferOfTheRightSizeForEmptyObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "{}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForObjectWithOneValue") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":1}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithOneValue") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
char input[] = "{\"a\":1}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForObjectWithNestedObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0) + JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":[]}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithNestedObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":[]}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
char input[] = "{\"hello\":\"world\"}";
|
||||
|
||||
deserializeJson(doc, input);
|
||||
deserializeJson(doc, "{}");
|
||||
|
||||
REQUIRE(doc.as<JsonObject>().size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
}
|
||||
132
libraries/ArduinoJson/extras/tests/JsonDeserializer/string.cpp
Normal file
132
libraries/ArduinoJson/extras/tests/JsonDeserializer/string.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2023, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Valid JSON strings value") {
|
||||
struct TestCase {
|
||||
const char* input;
|
||||
const char* expectedOutput;
|
||||
};
|
||||
|
||||
TestCase testCases[] = {
|
||||
{"\"hello world\"", "hello world"},
|
||||
{"\'hello world\'", "hello world"},
|
||||
{"'\"'", "\""},
|
||||
{"'\\\\'", "\\"},
|
||||
{"'\\/'", "/"},
|
||||
{"'\\b'", "\b"},
|
||||
{"'\\f'", "\f"},
|
||||
{"'\\n'", "\n"},
|
||||
{"'\\r'", "\r"},
|
||||
{"'\\t'", "\t"},
|
||||
{"\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"", "1\"2\\3/4\b5\f6\n7\r8\t9"},
|
||||
{"'\\u0041'", "A"},
|
||||
{"'\\u00e4'", "\xc3\xa4"}, // ä
|
||||
{"'\\u00E4'", "\xc3\xa4"}, // ä
|
||||
{"'\\u3042'", "\xe3\x81\x82"}, // あ
|
||||
{"'\\ud83d\\udda4'", "\xf0\x9f\x96\xa4"}, // 🖤
|
||||
{"'\\uF053'", "\xef\x81\x93"}, // issue #1173
|
||||
{"'\\uF015'", "\xef\x80\x95"}, // issue #1173
|
||||
{"'\\uF054'", "\xef\x81\x94"}, // issue #1173
|
||||
};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const TestCase& testCase = testCases[i];
|
||||
CAPTURE(testCase.input);
|
||||
DeserializationError err = deserializeJson(doc, testCase.input);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
CHECK(doc.as<std::string>() == testCase.expectedOutput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("\\u0000") {
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
DeserializationError err = deserializeJson(doc, "\"wx\\u0000yz\"");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
|
||||
const char* result = doc.as<const char*>();
|
||||
CHECK(result[0] == 'w');
|
||||
CHECK(result[1] == 'x');
|
||||
CHECK(result[2] == 0);
|
||||
CHECK(result[3] == 'y');
|
||||
CHECK(result[4] == 'z');
|
||||
CHECK(result[5] == 0);
|
||||
|
||||
CHECK(doc.as<JsonString>().size() == 5);
|
||||
CHECK(doc.as<std::string>().size() == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("Truncated JSON string") {
|
||||
const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) ==
|
||||
DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid JSON string") {
|
||||
const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'",
|
||||
"'\\u000G'", "'\\u000/'", "'\\x1234'"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Not enough room to save the key") {
|
||||
DynamicJsonDocument doc(JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
SECTION("Quoted string") {
|
||||
REQUIRE(deserializeJson(doc, "{\"example\":1}") ==
|
||||
DeserializationError::Ok);
|
||||
REQUIRE(deserializeJson(doc, "{\"accuracy\":1}") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(deserializeJson(doc, "{\"hello\":1,\"world\"}") ==
|
||||
DeserializationError::NoMemory); // fails in the second string
|
||||
}
|
||||
|
||||
SECTION("Non-quoted string") {
|
||||
REQUIRE(deserializeJson(doc, "{example:1}") == DeserializationError::Ok);
|
||||
REQUIRE(deserializeJson(doc, "{accuracy:1}") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(deserializeJson(doc, "{hello:1,world}") ==
|
||||
DeserializationError::NoMemory); // fails in the second string
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Empty memory pool") {
|
||||
// NOLINTNEXTLINE(clang-analyzer-optin.portability.UnixAPI)
|
||||
DynamicJsonDocument doc(0);
|
||||
|
||||
SECTION("Input is const char*") {
|
||||
REQUIRE(deserializeJson(doc, "\"hello\"") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(deserializeJson(doc, "\"\"") == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("Input is const char*") {
|
||||
char hello[] = "\"hello\"";
|
||||
REQUIRE(deserializeJson(doc, hello) == DeserializationError::Ok);
|
||||
char empty[] = "\"hello\"";
|
||||
REQUIRE(deserializeJson(doc, empty) == DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user