Moved ancillary files to extras/ (fixes #1011)

This commit is contained in:
Benoit Blanchon
2019-09-03 15:11:05 +02:00
parent ed18e77655
commit b47ac27ac6
226 changed files with 19 additions and 54 deletions

View File

@ -0,0 +1,21 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2019
# MIT License
add_executable(JsonDeserializerTests
array.cpp
array_static.cpp
DeserializationError.cpp
incomplete_input.cpp
input_types.cpp
number.cpp
invalid_input.cpp
misc.cpp
nestingLimit.cpp
object.cpp
object_static.cpp
string.cpp
)
target_link_libraries(JsonDeserializerTests catch)
add_test(JsonDeserializer JsonDeserializerTests)

View File

@ -0,0 +1,137 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
void testStringification(DeserializationError error, std::string expected) {
REQUIRE(error.c_str() == expected);
}
void testBoolification(DeserializationError error, bool expected) {
// DeserializationError on left-hand side
CHECK(error == expected);
CHECK(error != !expected);
CHECK(!error == !expected);
// DeserializationError on right-hand side
CHECK(expected == error);
CHECK(!expected != error);
CHECK(!expected == !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(TooDeep);
TEST_STRINGIFICATION(NoMemory);
TEST_STRINGIFICATION(InvalidInput);
TEST_STRINGIFICATION(IncompleteInput);
TEST_STRINGIFICATION(NotSupported);
}
SECTION("as boolean") {
TEST_BOOLIFICATION(Ok, false);
TEST_BOOLIFICATION(TooDeep, true);
TEST_BOOLIFICATION(NoMemory, true);
TEST_BOOLIFICATION(InvalidInput, true);
TEST_BOOLIFICATION(IncompleteInput, true);
TEST_BOOLIFICATION(NotSupported, 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("out of range") {
int code = 666;
DeserializationError err(
*reinterpret_cast<DeserializationError::Code*>(&code));
REQUIRE(err.c_str() == std::string("???"));
}
SECTION("switch") {
DeserializationError err = DeserializationError::InvalidInput;
switch (err.code()) {
case DeserializationError::InvalidInput:
SUCCEED();
break;
default:
FAIL();
break;
}
}
SECTION("Comparisons") {
DeserializationError invalidInput(DeserializationError::InvalidInput);
DeserializationError ok(DeserializationError::Ok);
SECTION("DeserializationError == bool") {
REQUIRE(invalidInput == true);
REQUIRE(ok == false);
}
SECTION("bool == DeserializationError") {
REQUIRE(true == invalidInput);
REQUIRE(false == ok);
}
SECTION("DeserializationError != bool") {
REQUIRE(invalidInput != false);
REQUIRE(ok != true);
}
SECTION("bool != DeserializationError") {
REQUIRE(false != invalidInput);
REQUIRE(true != ok);
}
SECTION("Negations") {
REQUIRE(!invalidInput == false);
REQUIRE(!ok == true);
}
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);
}
}
}

View File

@ -0,0 +1,402 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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<char*>() == 0);
REQUIRE(arr[1].as<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("Block comments") {
SECTION("Before opening bracket") {
DeserializationError err =
deserializeJson(doc, "/*COMMENT*/ [\"hello\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("After opening bracket") {
DeserializationError err =
deserializeJson(doc, "[/*COMMENT*/ \"hello\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("Before closing bracket") {
DeserializationError err = deserializeJson(doc, "[\"hello\"/*COMMENT*/]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("After closing bracket") {
DeserializationError err = deserializeJson(doc, "[\"hello\"]/*COMMENT*/");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("Before comma") {
DeserializationError err =
deserializeJson(doc, "[\"hello\"/*COMMENT*/,\"world\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(2 == arr.size());
REQUIRE(arr[0] == "hello");
REQUIRE(arr[1] == "world");
}
SECTION("After comma") {
DeserializationError err =
deserializeJson(doc, "[\"hello\",/*COMMENT*/ \"world\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(2 == arr.size());
REQUIRE(arr[0] == "hello");
REQUIRE(arr[1] == "world");
}
SECTION("/*/") {
DeserializationError err = deserializeJson(doc, "[/*/\n]");
REQUIRE(err == DeserializationError::IncompleteInput);
}
SECTION("Unfinished comment") {
DeserializationError err = deserializeJson(doc, "[/*COMMENT]");
REQUIRE(err == DeserializationError::IncompleteInput);
}
SECTION("Final slash missing") {
DeserializationError err = deserializeJson(doc, "[/*COMMENT*]");
REQUIRE(err == DeserializationError::IncompleteInput);
}
}
SECTION("Trailing comments") {
SECTION("Before opening bracket") {
DeserializationError err =
deserializeJson(doc, "//COMMENT\n\t[\"hello\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("After opening bracket") {
DeserializationError err = deserializeJson(doc, "[//COMMENT\n\"hello\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("Before closing bracket") {
DeserializationError err =
deserializeJson(doc, "[\"hello\"//COMMENT\r\n]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("After closing bracket") {
DeserializationError err = deserializeJson(doc, "[\"hello\"]//COMMENT\n");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "hello");
}
SECTION("Before comma") {
DeserializationError err =
deserializeJson(doc, "[\"hello\"//COMMENT\n,\"world\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(2 == arr.size());
REQUIRE(arr[0] == "hello");
REQUIRE(arr[1] == "world");
}
SECTION("After comma") {
DeserializationError err =
deserializeJson(doc, "[\"hello\",//COMMENT\n\"world\"]");
JsonArray arr = doc.as<JsonArray>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(2 == arr.size());
REQUIRE(arr[0] == "hello");
REQUIRE(arr[1] == "world");
}
SECTION("Invalid comment") {
DeserializationError err = deserializeJson(doc, "[/COMMENT\n]");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("End document with comment") {
DeserializationError err = deserializeJson(doc, "[//COMMENT");
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));
}
}

View File

@ -0,0 +1,89 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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(8) == 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);
}
}

View File

@ -0,0 +1,27 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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"};
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);
}
}

View File

@ -0,0 +1,115 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include <sstream>
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 /* comment */ ] ");
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' // comment\n }");
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)") {
int 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

View File

@ -0,0 +1,35 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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,",
"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[] = {"nulL", "tru3", "fals3"};
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);
}
}

View File

@ -0,0 +1,143 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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::IncompleteInput);
}
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("Comments") {
SECTION("Just a trailing comment") {
DeserializationError err = deserializeJson(doc, "// comment");
REQUIRE(err == DeserializationError::IncompleteInput);
}
SECTION("Just a block comment") {
DeserializationError err = deserializeJson(doc, "/*comment*/");
REQUIRE(err == DeserializationError::IncompleteInput);
}
SECTION("Just a slash") {
DeserializationError err = deserializeJson(doc, "/");
REQUIRE(err == DeserializationError::InvalidInput);
}
}
SECTION("Premature null-terminator") {
SECTION("In escape sequence") {
DeserializationError err = deserializeJson(doc, "\"\\");
REQUIRE(err == DeserializationError::IncompleteInput);
}
SECTION("In block comment") {
DeserializationError err = deserializeJson(doc, "/* comment");
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 block comment") {
DeserializationError err = deserializeJson(doc, "/* comment */", 10);
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));
}
}

View File

@ -0,0 +1,101 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#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));
}
}
}

View File

@ -0,0 +1,133 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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_NAMESPACE::isinf;
using ARDUINOJSON_NAMESPACE::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>()));
}
}
}

View File

@ -0,0 +1,498 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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 colon") {
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 colon") {
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<char*>() == 0);
REQUIRE(obj["key2"].as<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);
}
}
SECTION("Block comments") {
SECTION("Before opening brace") {
DeserializationError err =
deserializeJson(doc, "/*COMMENT*/ {\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After opening brace") {
DeserializationError err =
deserializeJson(doc, "{/*COMMENT*/\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before colon") {
DeserializationError err =
deserializeJson(doc, "{\"hello\"/*COMMENT*/:\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After colon") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":/*COMMENT*/\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before closing brace") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\"/*COMMENT*/}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After closing brace") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\"}/*COMMENT*/");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before comma") {
DeserializationError err = deserializeJson(
doc, "{\"hello\":\"world\"/*COMMENT*/,\"answer\":42}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
REQUIRE(obj["answer"] == 42);
}
SECTION("After comma") {
DeserializationError err = deserializeJson(
doc, "{\"hello\":\"world\",/*COMMENT*/\"answer\":42}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
REQUIRE(obj["answer"] == 42);
}
}
SECTION("Trailing comments") {
SECTION("Before opening brace") {
DeserializationError err =
deserializeJson(doc, "//COMMENT\n {\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After opening brace") {
DeserializationError err =
deserializeJson(doc, "{//COMMENT\n\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before colon") {
DeserializationError err =
deserializeJson(doc, "{\"hello\"//COMMENT\n:\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After colon") {
DeserializationError err =
deserializeJson(doc, "{\"hello\"://COMMENT\n\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before closing brace") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\"//COMMENT\n}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("After closing brace") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\"}//COMMENT\n");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before comma") {
DeserializationError err = deserializeJson(
doc, "{\"hello\":\"world\"//COMMENT\n,\"answer\":42}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
REQUIRE(obj["answer"] == 42);
}
SECTION("After comma") {
DeserializationError err = deserializeJson(
doc, "{\"hello\":\"world\",//COMMENT\n\"answer\":42}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
REQUIRE(obj["answer"] == 42);
}
}
SECTION("Dangling slash") {
SECTION("Before opening brace") {
DeserializationError err = deserializeJson(doc, "/{\"hello\":\"world\"}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("After opening brace") {
DeserializationError err = deserializeJson(doc, "{/\"hello\":\"world\"}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("Before colon") {
DeserializationError err = deserializeJson(doc, "{\"hello\"/:\"world\"}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("After colon") {
DeserializationError err = deserializeJson(doc, "{\"hello\":/\"world\"}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("Before closing brace") {
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"/}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("After closing brace") {
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"}/");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(obj["hello"] == "world");
}
SECTION("Before comma") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\"/,\"answer\":42}");
REQUIRE(err == DeserializationError::InvalidInput);
}
SECTION("After comma") {
DeserializationError err =
deserializeJson(doc, "{\"hello\":\"world\",/\"answer\":42}");
REQUIRE(err == DeserializationError::InvalidInput);
}
}
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));
}
}

View File

@ -0,0 +1,64 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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));
}
}

View File

@ -0,0 +1,72 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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"},
{"\"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"}, // あ
};
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);
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.as<std::string>() == testCase.expectedOutput);
}
}
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 duplicate the string") {
DynamicJsonDocument doc(4);
REQUIRE(deserializeJson(doc, "\"hello world!\"") ==
DeserializationError::NoMemory);
REQUIRE(doc.isNull() == true);
}