Permet de lire les données de la passerelle enphase pour piloter la chauffe d'un cumulus via un relais statique.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

385 lines
11 KiB

// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include "Allocators.hpp"
using ArduinoJson::detail::sizeofObject;
TEST_CASE("deserialize JSON object") {
SpyingAllocator spy;
JsonDocument doc(&spy);
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.as<std::string>() == "{\"a\":2}");
REQUIRE(spy.log() ==
AllocatorLog{
Allocate(sizeofStringBuffer()),
Reallocate(sizeofStringBuffer(), sizeofString("a")),
Allocate(sizeofPool()),
Allocate(sizeofStringBuffer()),
Reallocate(sizeofStringBuffer(), sizeofString("b")),
Allocate(sizeofStringBuffer()),
Reallocate(sizeofStringBuffer(), sizeofString("c")),
Allocate(sizeofStringBuffer()),
Deallocate(sizeofString("b")),
Deallocate(sizeofString("c")),
Deallocate(sizeofStringBuffer()),
Reallocate(sizeofPool(), sizeofObject(2) + sizeofObject(1)),
});
}
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\"}");
spy.clearLog();
deserializeJson(doc, "{}");
REQUIRE(doc.is<JsonObject>());
REQUIRE(doc.size() == 0);
REQUIRE(spy.log() == AllocatorLog{
Deallocate(sizeofObject(1)),
Deallocate(sizeofString("hello")),
Deallocate(sizeofString("world")),
});
}
SECTION("Issue #1335") {
std::string json("{\"a\":{},\"b\":{}}");
deserializeJson(doc, json);
CHECK(doc.as<std::string>() == json);
}
}
TEST_CASE("deserialize JSON object under memory constraints") {
TimebombAllocator timebomb(1024);
JsonDocument doc(&timebomb);
SECTION("empty object requires no allocation") {
timebomb.setCountdown(0);
char input[] = "{}";
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.as<std::string>() == "{}");
}
SECTION("key allocation fails") {
timebomb.setCountdown(0);
char input[] = "{\"a\":1}";
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::NoMemory);
REQUIRE(doc.as<std::string>() == "{}");
}
SECTION("pool allocation fails") {
timebomb.setCountdown(2);
char input[] = "{\"a\":1}";
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::NoMemory);
REQUIRE(doc.as<std::string>() == "{}");
}
SECTION("string allocation fails") {
timebomb.setCountdown(3);
char input[] = "{\"a\":\"b\"}";
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::NoMemory);
REQUIRE(doc.as<std::string>() == "{\"a\":null}");
}
}