forked from bblanchon/ArduinoJson
Store the strings in the heap
This commit is contained in:
@ -6,6 +6,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
using ArduinoJson::detail::sizeofObject;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
@ -96,42 +98,67 @@ TEST_CASE("Invalid JSON string") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Not enough room to save the key") {
|
||||
JsonDocument doc(sizeofObject(1) + sizeofString(7));
|
||||
TEST_CASE("Allocation of the key fails") {
|
||||
TimebombAllocator timebombAllocator(1);
|
||||
SpyingAllocator spyingAllocator(&timebombAllocator);
|
||||
JsonDocument doc(1024, &spyingAllocator);
|
||||
|
||||
SECTION("Quoted string") {
|
||||
SECTION("Quoted string, first member") {
|
||||
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
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Non-quoted string") {
|
||||
REQUIRE(deserializeJson(doc, "{example:1}") == DeserializationError::Ok);
|
||||
REQUIRE(deserializeJson(doc, "{accuracy:1}") ==
|
||||
SECTION("Quoted string, second member") {
|
||||
timebombAllocator.setCountdown(2);
|
||||
REQUIRE(deserializeJson(doc, "{\"hello\":1,\"world\"}") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||
sizeofString(5))
|
||||
<< AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Non-Quoted string, first member") {
|
||||
REQUIRE(deserializeJson(doc, "{example:1}") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Non-Quoted string, second member") {
|
||||
timebombAllocator.setCountdown(2);
|
||||
REQUIRE(deserializeJson(doc, "{hello:1,world}") ==
|
||||
DeserializationError::NoMemory); // fails in the second string
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||
sizeofString(5))
|
||||
<< AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Empty memory pool") {
|
||||
// NOLINTNEXTLINE(clang-analyzer-optin.portability.UnixAPI)
|
||||
JsonDocument doc(0);
|
||||
TEST_CASE("String allocation fails") {
|
||||
SpyingAllocator spyingAllocator(FailingAllocator::instance());
|
||||
JsonDocument doc(0, &spyingAllocator);
|
||||
|
||||
SECTION("Input is const char*") {
|
||||
REQUIRE(deserializeJson(doc, "\"hello\"") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(deserializeJson(doc, "\"\"") == DeserializationError::NoMemory);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Input is const char*") {
|
||||
char hello[] = "\"hello\"";
|
||||
REQUIRE(deserializeJson(doc, hello) == DeserializationError::Ok);
|
||||
char empty[] = "\"hello\"";
|
||||
REQUIRE(deserializeJson(doc, empty) == DeserializationError::Ok);
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,63 +9,59 @@
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
using ArduinoJson::detail::sizeofObject;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
|
||||
TEST_CASE("JsonDocument assignment") {
|
||||
SpyingAllocator spyingAllocator;
|
||||
|
||||
SECTION("Copy assignment same capacity") {
|
||||
{
|
||||
JsonDocument doc1(1024, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(1024, &spyingAllocator);
|
||||
JsonDocument doc1(1024, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(1024, &spyingAllocator);
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
doc2 = doc1;
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Deallocate(1024)
|
||||
<< AllocatorLog::Deallocate(1024));
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(5)) // hello
|
||||
<< AllocatorLog::Allocate(sizeofString(5)) // world
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("Copy assignment reallocates when capacity is smaller") {
|
||||
{
|
||||
JsonDocument doc1(4096, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(8, &spyingAllocator);
|
||||
JsonDocument doc1(4096, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(8, &spyingAllocator);
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
doc2 = doc1;
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(8)
|
||||
<< AllocatorLog::Deallocate(8)
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Deallocate(8)
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(5)) // hello
|
||||
<< AllocatorLog::Allocate(sizeofString(5)) // world
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("Copy assignment reallocates when capacity is larger") {
|
||||
{
|
||||
JsonDocument doc1(1024, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(4096, &spyingAllocator);
|
||||
JsonDocument doc1(1024, &spyingAllocator);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
JsonDocument doc2(4096, &spyingAllocator);
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
doc2 = doc1;
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096)
|
||||
<< AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Deallocate(1024)
|
||||
<< AllocatorLog::Deallocate(1024));
|
||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Deallocate(4096)
|
||||
<< AllocatorLog::Allocate(1024)
|
||||
<< AllocatorLog::Allocate(sizeofString(5)) // hello
|
||||
<< AllocatorLog::Allocate(sizeofString(5)) // world
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("Move assign") {
|
||||
@ -79,11 +75,13 @@ TEST_CASE("JsonDocument assignment") {
|
||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||
REQUIRE(doc1.as<std::string>() == "null");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(8)
|
||||
<< AllocatorLog::Deallocate(8)
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Allocate(8)
|
||||
<< AllocatorLog::Deallocate(8)
|
||||
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonObject") {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using ArduinoJson::detail::addPadding;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
|
||||
TEST_CASE("JsonDocument constructor") {
|
||||
SpyingAllocator spyingAllocator;
|
||||
@ -29,11 +30,15 @@ TEST_CASE("JsonDocument constructor") {
|
||||
REQUIRE(doc1.as<std::string>() == "The size of this string is 32!!");
|
||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(4096)
|
||||
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
}
|
||||
|
||||
SECTION("JsonDocument(JsonDocument&&)") {
|
||||
@ -46,9 +51,11 @@ TEST_CASE("JsonDocument constructor") {
|
||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||
REQUIRE(doc1.as<std::string>() == "null");
|
||||
}
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
}
|
||||
|
||||
SECTION("JsonDocument(JsonObject)") {
|
||||
@ -82,7 +89,9 @@ TEST_CASE("JsonDocument constructor") {
|
||||
JsonDocument doc2(doc1.as<JsonVariant>(), &spyingAllocator);
|
||||
|
||||
REQUIRE(doc2.as<std::string>() == "hello");
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
|
||||
addPadding(doc1.memoryUsage())));
|
||||
REQUIRE(
|
||||
spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(addPadding(doc1.memoryUsage()))
|
||||
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||
}
|
||||
}
|
||||
|
@ -21,16 +21,19 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
||||
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
||||
REQUIRE(doc.memoryUsage() == sizeofObject(2) + 2 * sizeofString(7));
|
||||
doc.remove("blanket");
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
bool result = doc.garbageCollect();
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(7));
|
||||
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Deallocate(sizeofString(7))
|
||||
<< AllocatorLog::Deallocate(sizeofString(7))
|
||||
<< AllocatorLog::Deallocate(4096));
|
||||
}
|
||||
|
||||
SECTION("when allocation fails") {
|
||||
@ -38,6 +41,7 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
||||
REQUIRE(doc.memoryUsage() == sizeofObject(2) + 2 * sizeofString(7));
|
||||
doc.remove("blanket");
|
||||
controllableAllocator.disable();
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
bool result = doc.garbageCollect();
|
||||
|
||||
@ -46,7 +50,6 @@ TEST_CASE("JsonDocument::garbageCollect()") {
|
||||
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog()
|
||||
<< AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::AllocateFail(4096));
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
|
||||
TEST_CASE("JsonDocument::overflowed()") {
|
||||
SECTION("returns false on a fresh object") {
|
||||
@ -27,13 +28,15 @@ TEST_CASE("JsonDocument::overflowed()") {
|
||||
}
|
||||
|
||||
SECTION("returns true after a failed string copy") {
|
||||
JsonDocument doc(sizeofArray(1));
|
||||
ControllableAllocator allocator;
|
||||
JsonDocument doc(sizeofArray(1), &allocator);
|
||||
allocator.disable();
|
||||
doc.add(std::string("example"));
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after a successful string copy") {
|
||||
JsonDocument doc(sizeofArray(1) + sizeofString(7));
|
||||
JsonDocument doc(sizeofArray(1));
|
||||
doc.add(std::string("example"));
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
@ -46,12 +49,12 @@ TEST_CASE("JsonDocument::overflowed()") {
|
||||
|
||||
SECTION("returns true after a failed deserialization") {
|
||||
JsonDocument doc(sizeofArray(1));
|
||||
deserializeJson(doc, "[\"example\"]");
|
||||
deserializeJson(doc, "[1, 2]");
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after a successful deserialization") {
|
||||
JsonDocument doc(sizeofArray(1) + sizeofString(7));
|
||||
JsonDocument doc(sizeofArray(1));
|
||||
deserializeJson(doc, "[\"example\"]");
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
@ -86,13 +86,15 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
||||
|
||||
SECTION("owned string") {
|
||||
doc.set(std::string("abcdefg"));
|
||||
REQUIRE(doc.as<std::string>() == "abcdefg");
|
||||
|
||||
doc.shrinkToFit();
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "abcdefg");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(4096, sizeofString(7)));
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Reallocate(4096, 0));
|
||||
}
|
||||
|
||||
SECTION("linked raw") {
|
||||
@ -114,7 +116,8 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
||||
REQUIRE(doc.as<std::string>() == "[{},12]");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(4096, sizeofString(7)));
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Reallocate(4096, 0));
|
||||
}
|
||||
|
||||
SECTION("linked key") {
|
||||
@ -136,8 +139,8 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
||||
REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(
|
||||
4096, sizeofObject(1) + sizeofString(7)));
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Reallocate(4096, sizeofObject(1)));
|
||||
}
|
||||
|
||||
SECTION("linked string in array") {
|
||||
@ -159,8 +162,8 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
||||
REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(
|
||||
4096, sizeofArray(1) + sizeofString(7)));
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Reallocate(4096, sizeofArray(1)));
|
||||
}
|
||||
|
||||
SECTION("linked string in object") {
|
||||
@ -182,21 +185,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
|
||||
REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(
|
||||
4096, sizeofObject(1) + sizeofString(7)));
|
||||
}
|
||||
|
||||
SECTION("unaligned") {
|
||||
doc.add(std::string("?")); // two bytes in the string pool
|
||||
REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(1));
|
||||
|
||||
doc.shrinkToFit();
|
||||
|
||||
// the new capacity should be padded to align the pointers
|
||||
REQUIRE(doc[0] == "?");
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||
<< AllocatorLog::Reallocate(
|
||||
4096, sizeofArray(1) + sizeof(void*)));
|
||||
<< AllocatorLog::Allocate(sizeofString(7))
|
||||
<< AllocatorLog::Reallocate(4096, sizeofObject(1)));
|
||||
}
|
||||
}
|
||||
|
@ -77,24 +77,25 @@ TEST_CASE("JsonObject::set()") {
|
||||
JsonDocument doc3(sizeofObject(1));
|
||||
JsonObject obj3 = doc3.to<JsonObject>();
|
||||
|
||||
obj1[std::string("hello")] = "world";
|
||||
obj1["a"] = 1;
|
||||
obj1["b"] = 2;
|
||||
|
||||
bool success = obj3.set(obj1);
|
||||
|
||||
REQUIRE(success == false);
|
||||
REQUIRE(doc3.as<std::string>() == "{}");
|
||||
REQUIRE(doc3.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
|
||||
SECTION("destination too small to store the value") {
|
||||
JsonDocument doc3(sizeofObject(1));
|
||||
JsonObject obj3 = doc3.to<JsonObject>();
|
||||
|
||||
obj1["hello"] = std::string("world");
|
||||
obj1["hello"][1] = "world";
|
||||
|
||||
bool success = obj3.set(obj1);
|
||||
|
||||
REQUIRE(success == false);
|
||||
REQUIRE(doc3.as<std::string>() == "{\"hello\":null}");
|
||||
REQUIRE(doc3.as<std::string>() == "{\"hello\":[]}");
|
||||
}
|
||||
|
||||
SECTION("destination is null") {
|
||||
|
@ -10,6 +10,11 @@ TEST_CASE("VariantData") {
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_CASE("StringNode") {
|
||||
REQUIRE(std::is_standard_layout<ArduinoJson::detail::StringNode>::value ==
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant from JsonArray") {
|
||||
SECTION("JsonArray is null") {
|
||||
JsonArray arr;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
||||
|
||||
TEST_CASE("JsonVariant::set() when there is enough memory") {
|
||||
@ -128,7 +130,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::set() with not enough memory") {
|
||||
JsonDocument doc(1);
|
||||
JsonDocument doc(1, FailingAllocator::instance());
|
||||
|
||||
JsonVariant v = doc.to<JsonVariant>();
|
||||
|
||||
|
@ -5,11 +5,30 @@
|
||||
#include <ArduinoJson/StringStorage/StringCopier.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using namespace ArduinoJson::detail;
|
||||
|
||||
TEST_CASE("StringCopier") {
|
||||
SECTION("Works when buffer is big enough") {
|
||||
MemoryPool pool(addPadding(sizeofString(5)));
|
||||
ControllableAllocator controllableAllocator;
|
||||
SpyingAllocator spyingAllocator(&controllableAllocator);
|
||||
MemoryPool pool(0, &spyingAllocator);
|
||||
|
||||
SECTION("Empty string") {
|
||||
StringCopier str(&pool);
|
||||
|
||||
str.startString();
|
||||
str.save();
|
||||
|
||||
REQUIRE(pool.size() == sizeofString(0));
|
||||
REQUIRE(pool.overflowed() == false);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||
sizeofString(0)));
|
||||
}
|
||||
|
||||
SECTION("Short string fits in first allocation") {
|
||||
StringCopier str(&pool);
|
||||
|
||||
str.startString();
|
||||
@ -18,38 +37,60 @@ TEST_CASE("StringCopier") {
|
||||
REQUIRE(str.isValid() == true);
|
||||
REQUIRE(str.str() == "hello");
|
||||
REQUIRE(pool.overflowed() == false);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Returns null when too small") {
|
||||
MemoryPool pool(sizeof(void*));
|
||||
SECTION("Long string needs reallocation") {
|
||||
StringCopier str(&pool);
|
||||
|
||||
str.startString();
|
||||
str.append("hello world!");
|
||||
str.append(
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua.");
|
||||
|
||||
REQUIRE(str.isValid() == false);
|
||||
REQUIRE(pool.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("Increases size of memory pool") {
|
||||
MemoryPool pool(addPadding(sizeofString(6)));
|
||||
StringCopier str(&pool);
|
||||
|
||||
str.startString();
|
||||
str.save();
|
||||
|
||||
REQUIRE(1 == pool.size());
|
||||
REQUIRE(str.isValid() == true);
|
||||
REQUIRE(str.str() ==
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua.");
|
||||
REQUIRE(pool.overflowed() == false);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::Reallocate(sizeofString(31),
|
||||
sizeofString(63))
|
||||
<< AllocatorLog::Reallocate(sizeofString(63),
|
||||
sizeofString(127)));
|
||||
}
|
||||
|
||||
SECTION("Works when memory pool is 0 bytes") {
|
||||
MemoryPool pool(0);
|
||||
SECTION("Realloc fails") {
|
||||
StringCopier str(&pool);
|
||||
|
||||
str.startString();
|
||||
controllableAllocator.disable();
|
||||
str.append(
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua.");
|
||||
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
||||
sizeofString(63))
|
||||
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||
REQUIRE(str.isValid() == false);
|
||||
REQUIRE(pool.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("Initial allocation fails") {
|
||||
StringCopier str(&pool);
|
||||
|
||||
controllableAllocator.disable();
|
||||
str.startString();
|
||||
|
||||
REQUIRE(str.isValid() == false);
|
||||
REQUIRE(pool.overflowed() == true);
|
||||
REQUIRE(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
}
|
||||
|
||||
static const char* addStringToPool(MemoryPool& pool, const char* s) {
|
||||
|
@ -39,13 +39,6 @@ TEST_CASE("MemoryPool::saveString()") {
|
||||
const char* a = saveString(pool, "hello\0world", 11);
|
||||
const char* b = saveString(pool, "hello\0world", 11);
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
SECTION("Reuse part of a string if it ends with NUL") {
|
||||
const char* a = saveString(pool, "hello\0world", 11);
|
||||
const char* b = saveString(pool, "hello");
|
||||
REQUIRE(a == b);
|
||||
REQUIRE(pool.size() == 12);
|
||||
REQUIRE(pool.size() == sizeofString(11));
|
||||
}
|
||||
|
||||
@ -56,52 +49,8 @@ TEST_CASE("MemoryPool::saveString()") {
|
||||
REQUIRE(pool.size() == sizeofString(5) + sizeofString(11));
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when full") {
|
||||
REQUIRE(pool.capacity() == 32);
|
||||
|
||||
const void* p1 = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
REQUIRE(p1 != 0);
|
||||
REQUIRE(pool.size() == 32);
|
||||
|
||||
const void* p2 = saveString(pool, "b");
|
||||
REQUIRE(p2 == 0);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when pool is too small") {
|
||||
const void* p = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
REQUIRE(0 == p);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when buffer is NULL") {
|
||||
SECTION("Returns NULL when allocation fails") {
|
||||
MemoryPool pool2(32, FailingAllocator::instance());
|
||||
REQUIRE(0 == saveString(pool2, "a"));
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when capacity is 0") {
|
||||
MemoryPool pool2(0);
|
||||
REQUIRE(0 == saveString(pool2, "a"));
|
||||
}
|
||||
|
||||
SECTION("Returns same address after clear()") {
|
||||
const void* a = saveString(pool, "hello");
|
||||
pool.clear();
|
||||
const void* b = saveString(pool, "world");
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity when fresh") {
|
||||
const void* a = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity after clear") {
|
||||
saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
pool.clear();
|
||||
|
||||
const void* a = saveString(pool, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
|
||||
@ -52,7 +54,7 @@ struct PrintableString : public Printable {
|
||||
TEST_CASE("Printable") {
|
||||
SECTION("Doesn't overflow") {
|
||||
JsonDocument doc(8);
|
||||
const char* value = "example"; // == 7 chars
|
||||
const char* value = "example";
|
||||
|
||||
doc.set(666); // to make sure we override the value
|
||||
|
||||
@ -77,53 +79,82 @@ TEST_CASE("Printable") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Overflows early") {
|
||||
JsonDocument doc(8);
|
||||
const char* value = "hello world"; // > 8 chars
|
||||
SECTION("First allocation fails") {
|
||||
SpyingAllocator spyingAllocator(FailingAllocator::instance());
|
||||
JsonDocument doc(0, &spyingAllocator);
|
||||
const char* value = "hello world";
|
||||
|
||||
doc.set(666); // to make sure we override the value
|
||||
|
||||
SECTION("Via Print::write(char)") {
|
||||
PrintableString<PrintOneCharacterAtATime> printable(value);
|
||||
CHECK(doc.set(printable) == false);
|
||||
CHECK(doc.isNull());
|
||||
CHECK(printable.totalBytesWritten() == 8);
|
||||
CHECK(doc.overflowed() == true);
|
||||
CHECK(doc.memoryUsage() == 0);
|
||||
}
|
||||
|
||||
SECTION("Via Print::write(const char*, size_t)") {
|
||||
PrintableString<PrintAllAtOnce> printable(value);
|
||||
CHECK(doc.set(printable) == false);
|
||||
bool success = doc.set(printable);
|
||||
|
||||
CHECK(success == false);
|
||||
CHECK(doc.isNull());
|
||||
CHECK(printable.totalBytesWritten() == 0);
|
||||
CHECK(doc.overflowed() == true);
|
||||
CHECK(doc.memoryUsage() == 0);
|
||||
CHECK(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Via Print::write(const char*, size_t)") {
|
||||
PrintableString<PrintAllAtOnce> printable(value);
|
||||
|
||||
bool success = doc.set(printable);
|
||||
|
||||
CHECK(success == false);
|
||||
CHECK(doc.isNull());
|
||||
CHECK(printable.totalBytesWritten() == 0);
|
||||
CHECK(doc.overflowed() == true);
|
||||
CHECK(doc.memoryUsage() == 0);
|
||||
CHECK(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Overflows adding terminator") {
|
||||
JsonDocument doc(8);
|
||||
const char* value = "overflow"; // == 8 chars
|
||||
SECTION("Reallocation fails") {
|
||||
TimebombAllocator timebombAllocator(1);
|
||||
SpyingAllocator spyingAllocator(&timebombAllocator);
|
||||
JsonDocument doc(0, &spyingAllocator);
|
||||
const char* value = "Lorem ipsum dolor sit amet, cons"; // > 31 chars
|
||||
|
||||
doc.set(666); // to make sure we override the value
|
||||
|
||||
SECTION("Via Print::write(char)") {
|
||||
PrintableString<PrintOneCharacterAtATime> printable(value);
|
||||
CHECK(doc.set(printable) == false);
|
||||
|
||||
bool success = doc.set(printable);
|
||||
|
||||
CHECK(success == false);
|
||||
CHECK(doc.isNull());
|
||||
CHECK(printable.totalBytesWritten() == 8);
|
||||
CHECK(printable.totalBytesWritten() == 31);
|
||||
CHECK(doc.overflowed() == true);
|
||||
CHECK(doc.memoryUsage() == 0);
|
||||
CHECK(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
||||
sizeofString(63))
|
||||
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||
}
|
||||
|
||||
SECTION("Via Print::write(const char*, size_t)") {
|
||||
PrintableString<PrintAllAtOnce> printable(value);
|
||||
CHECK(doc.set(printable) == false);
|
||||
|
||||
bool success = doc.set(printable);
|
||||
|
||||
CHECK(success == false);
|
||||
CHECK(doc.isNull());
|
||||
CHECK(printable.totalBytesWritten() == 0);
|
||||
CHECK(printable.totalBytesWritten() == 31);
|
||||
CHECK(doc.overflowed() == true);
|
||||
CHECK(doc.memoryUsage() == 0);
|
||||
CHECK(spyingAllocator.log() ==
|
||||
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
|
||||
<< AllocatorLog::ReallocateFail(sizeofString(31),
|
||||
sizeofString(63))
|
||||
<< AllocatorLog::Deallocate(sizeofString(31)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
using ArduinoJson::detail::sizeofObject;
|
||||
using ArduinoJson::detail::sizeofString;
|
||||
@ -20,9 +22,10 @@ static void checkValue(const char* input, T expected) {
|
||||
REQUIRE(doc.as<T>() == expected);
|
||||
}
|
||||
|
||||
static void checkError(size_t capacity, const char* input,
|
||||
DeserializationError expected) {
|
||||
JsonDocument doc(capacity);
|
||||
static void checkError(size_t capacity, size_t timebombCountDown,
|
||||
const char* input, DeserializationError expected) {
|
||||
TimebombAllocator timebombAllocator(timebombCountDown);
|
||||
JsonDocument doc(capacity, &timebombAllocator);
|
||||
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
@ -144,133 +147,120 @@ TEST_CASE("deserialize MsgPack value") {
|
||||
|
||||
TEST_CASE("deserializeMsgPack() under memory constaints") {
|
||||
SECTION("single values always fit") {
|
||||
checkError(0, "\xc0", DeserializationError::Ok); // nil
|
||||
checkError(0, "\xc2", DeserializationError::Ok); // false
|
||||
checkError(0, "\xc3", DeserializationError::Ok); // true
|
||||
checkError(0, "\xcc\x00", DeserializationError::Ok); // uint 8
|
||||
checkError(0, "\xcd\x30\x39", DeserializationError::Ok); // uint 16
|
||||
checkError(0, "\xCE\x12\x34\x56\x78", DeserializationError::Ok); // uint 32
|
||||
checkError(0, 0, "\xc0", DeserializationError::Ok); // nil
|
||||
checkError(0, 0, "\xc2", DeserializationError::Ok); // false
|
||||
checkError(0, 0, "\xc3", DeserializationError::Ok); // true
|
||||
checkError(0, 0, "\xcc\x00", DeserializationError::Ok); // uint 8
|
||||
checkError(0, 0, "\xcd\x30\x39", DeserializationError::Ok); // uint 16
|
||||
checkError(0, 0, "\xCE\x12\x34\x56\x78",
|
||||
DeserializationError::Ok); // uint 32
|
||||
}
|
||||
|
||||
SECTION("fixstr") {
|
||||
checkError(8, "\xA0", DeserializationError::Ok);
|
||||
checkError(8, "\xA7ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(8, "\xA8ZZZZZZZZ", DeserializationError::NoMemory);
|
||||
checkError(16, "\xAFZZZZZZZZZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(16, "\xB0ZZZZZZZZZZZZZZZZ", DeserializationError::NoMemory);
|
||||
checkError(0, 2, "\xA7ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(0, 0, "\xA7ZZZZZZZ", DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("str 8") {
|
||||
checkError(8, "\xD9\x00", DeserializationError::Ok);
|
||||
checkError(8, "\xD9\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(8, "\xD9\x08ZZZZZZZZ", DeserializationError::NoMemory);
|
||||
checkError(16, "\xD9\x0FZZZZZZZZZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(16, "\xD9\x10ZZZZZZZZZZZZZZZZ", DeserializationError::NoMemory);
|
||||
checkError(0, 2, "\xD9\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(0, 0, "\xD9\x07ZZZZZZZ", DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("str 16") {
|
||||
checkError(8, "\xDA\x00\x00", DeserializationError::Ok);
|
||||
checkError(8, "\xDA\x00\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(8, "\xDA\x00\x08ZZZZZZZZ", DeserializationError::NoMemory);
|
||||
checkError(16, "\xDA\x00\x0FZZZZZZZZZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(16, "\xDA\x00\x10ZZZZZZZZZZZZZZZZ",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(0, 2, "\xDA\x00\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(0, 0, "\xDA\x00\x07ZZZZZZZ", DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("str 32") {
|
||||
checkError(8, "\xDB\x00\x00\x00\x00", DeserializationError::Ok);
|
||||
checkError(8, "\xDB\x00\x00\x00\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(8, "\xDB\x00\x00\x00\x08ZZZZZZZZ",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(16, "\xDB\x00\x00\x00\x0FZZZZZZZZZZZZZZZ",
|
||||
DeserializationError::Ok);
|
||||
checkError(16, "\xDB\x00\x00\x00\x10ZZZZZZZZZZZZZZZZ",
|
||||
checkError(0, 2, "\xDB\x00\x00\x00\x07ZZZZZZZ", DeserializationError::Ok);
|
||||
checkError(0, 0, "\xDB\x00\x00\x00\x07ZZZZZZZ",
|
||||
DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("fixarray") {
|
||||
checkError(sizeofArray(0), "\x90", DeserializationError::Ok); // []
|
||||
checkError(sizeofArray(0), "\x91\x01",
|
||||
checkError(sizeofArray(0), 1, "\x90", DeserializationError::Ok); // []
|
||||
checkError(sizeofArray(0), 1, "\x91\x01",
|
||||
DeserializationError::NoMemory); // [1]
|
||||
checkError(sizeofArray(1), "\x91\x01",
|
||||
checkError(sizeofArray(1), 1, "\x91\x01",
|
||||
DeserializationError::Ok); // [1]
|
||||
checkError(sizeofArray(1), "\x92\x01\x02",
|
||||
checkError(sizeofArray(1), 1, "\x92\x01\x02",
|
||||
DeserializationError::NoMemory); // [1,2]
|
||||
}
|
||||
|
||||
SECTION("array 16") {
|
||||
checkError(sizeofArray(0), "\xDC\x00\x00", DeserializationError::Ok);
|
||||
checkError(sizeofArray(0), "\xDC\x00\x01\x01",
|
||||
checkError(sizeofArray(0), 1, "\xDC\x00\x00", DeserializationError::Ok);
|
||||
checkError(sizeofArray(0), 1, "\xDC\x00\x01\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofArray(1), "\xDC\x00\x01\x01", DeserializationError::Ok);
|
||||
checkError(sizeofArray(1), "\xDC\x00\x02\x01\x02",
|
||||
checkError(sizeofArray(1), 1, "\xDC\x00\x01\x01", DeserializationError::Ok);
|
||||
checkError(sizeofArray(1), 1, "\xDC\x00\x02\x01\x02",
|
||||
DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("array 32") {
|
||||
checkError(sizeofArray(0), "\xDD\x00\x00\x00\x00",
|
||||
checkError(sizeofArray(0), 1, "\xDD\x00\x00\x00\x00",
|
||||
DeserializationError::Ok);
|
||||
checkError(sizeofArray(0), "\xDD\x00\x00\x00\x01\x01",
|
||||
checkError(sizeofArray(0), 1, "\xDD\x00\x00\x00\x01\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofArray(1), "\xDD\x00\x00\x00\x01\x01",
|
||||
checkError(sizeofArray(1), 1, "\xDD\x00\x00\x00\x01\x01",
|
||||
DeserializationError::Ok);
|
||||
checkError(sizeofArray(1), "\xDD\x00\x00\x00\x02\x01\x02",
|
||||
checkError(sizeofArray(1), 1, "\xDD\x00\x00\x00\x02\x01\x02",
|
||||
DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("fixmap") {
|
||||
SECTION("{}") {
|
||||
checkError(sizeofObject(0), "\x80", DeserializationError::Ok);
|
||||
checkError(sizeofObject(0), 0, "\x80", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(sizeofObject(0), "\x81\xA1H\x01",
|
||||
checkError(sizeofObject(0), 0, "\x81\xA1H\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(1) + sizeofString(2), "\x81\xA1H\x01",
|
||||
checkError(sizeofObject(1) + sizeofString(2), 3, "\x81\xA1H\x01",
|
||||
DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(sizeofObject(1) + sizeofString(2), "\x82\xA1H\x01\xA1W\x02",
|
||||
checkError(sizeofObject(1) + sizeofString(2), 3, "\x82\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(2) + 2 * sizeofString(2),
|
||||
checkError(sizeofObject(2) + 2 * sizeofString(2), 5,
|
||||
"\x82\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("map 16") {
|
||||
SECTION("{}") {
|
||||
checkError(sizeofObject(0), "\xDE\x00\x00", DeserializationError::Ok);
|
||||
checkError(sizeofObject(0), 0, "\xDE\x00\x00", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(sizeofObject(0), "\xDE\x00\x01\xA1H\x01",
|
||||
checkError(sizeofObject(1) + sizeofString(2), 1, "\xDE\x00\x01\xA1H\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(1) + sizeofString(2), "\xDE\x00\x01\xA1H\x01",
|
||||
checkError(sizeofObject(1) + sizeofString(2), 3, "\xDE\x00\x01\xA1H\x01",
|
||||
DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(sizeofObject(1) + sizeofString(2),
|
||||
checkError(sizeofObject(1) + sizeofString(2), 3,
|
||||
"\xDE\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(2) + 2 * sizeofObject(1),
|
||||
checkError(sizeofObject(2) + 2 * sizeofObject(1), 5,
|
||||
"\xDE\x00\x02\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("map 32") {
|
||||
SECTION("{}") {
|
||||
checkError(sizeofObject(0), "\xDF\x00\x00\x00\x00",
|
||||
checkError(sizeofObject(0), 0, "\xDF\x00\x00\x00\x00",
|
||||
DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(sizeofObject(0), "\xDF\x00\x00\x00\x01\xA1H\x01",
|
||||
checkError(sizeofObject(1) + sizeofString(2), 1,
|
||||
"\xDF\x00\x00\x00\x01\xA1H\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(1) + sizeofString(2),
|
||||
checkError(sizeofObject(1) + sizeofString(2), 3,
|
||||
"\xDF\x00\x00\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(sizeofObject(1) + sizeofString(2),
|
||||
checkError(sizeofObject(1) + 2 * sizeofString(2), 3,
|
||||
"\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(sizeofObject(2) + 2 * sizeofObject(1),
|
||||
checkError(sizeofObject(2) + 2 * sizeofObject(1), 5,
|
||||
"\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::Ok);
|
||||
}
|
||||
|
Reference in New Issue
Block a user