forked from bblanchon/ArduinoJson
WIP
This commit is contained in:
@ -13,7 +13,8 @@ using ArduinoJson::detail::sizeofObject;
|
|||||||
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set() when there is enough memory") {
|
TEST_CASE("JsonVariant::set() when there is enough memory") {
|
||||||
JsonDocument doc;
|
SpyingAllocator spy;
|
||||||
|
JsonDocument doc(&spy);
|
||||||
JsonVariant variant = doc.to<JsonVariant>();
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
SECTION("const char*") {
|
SECTION("const char*") {
|
||||||
@ -25,6 +26,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "world"); // stores by pointer
|
REQUIRE(variant == "world"); // stores by pointer
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("(const char*)0") {
|
SECTION("(const char*)0") {
|
||||||
@ -32,6 +34,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.isNull());
|
REQUIRE(variant.isNull());
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("char*") {
|
SECTION("char*") {
|
||||||
@ -43,6 +46,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("(char*)0") {
|
SECTION("(char*)0") {
|
||||||
@ -50,6 +56,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.isNull());
|
REQUIRE(variant.isNull());
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("unsigned char*") {
|
SECTION("unsigned char*") {
|
||||||
@ -61,6 +68,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("signed char*") {
|
SECTION("signed char*") {
|
||||||
@ -72,6 +82,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||||
@ -85,6 +98,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -97,6 +113,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("static JsonString") {
|
SECTION("static JsonString") {
|
||||||
@ -108,6 +127,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "world"); // stores by pointer
|
REQUIRE(variant == "world"); // stores by pointer
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-static JsonString") {
|
SECTION("non-static JsonString") {
|
||||||
@ -119,6 +139,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
|
|
||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant == "hello"); // stores by copy
|
REQUIRE(variant == "hello"); // stores by copy
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofString("hello")),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("enum") {
|
SECTION("enum") {
|
||||||
@ -129,6 +152,89 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
|
|||||||
REQUIRE(result == true);
|
REQUIRE(result == true);
|
||||||
REQUIRE(variant.is<int>() == true);
|
REQUIRE(variant.is<int>() == true);
|
||||||
REQUIRE(variant.as<int>() == 10);
|
REQUIRE(variant.as<int>() == 10);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("float") {
|
||||||
|
bool result = variant.set(1.2f);
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<float>() == true);
|
||||||
|
REQUIRE(variant.as<float>() == 1.2f);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("double") {
|
||||||
|
bool result = variant.set(1.2);
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<double>() == true);
|
||||||
|
REQUIRE(variant.as<double>() == 1.2);
|
||||||
|
REQUIRE(spy.log() ==
|
||||||
|
AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("int32_t") {
|
||||||
|
bool result = variant.set(int32_t(42));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<int32_t>() == true);
|
||||||
|
REQUIRE(variant.as<int32_t>() == 42);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("int64_t") {
|
||||||
|
bool result = variant.set(int64_t(-2147483649));
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<int64_t>() == true);
|
||||||
|
REQUIRE(variant.as<int64_t>() == -2147483649);
|
||||||
|
REQUIRE(spy.log() ==
|
||||||
|
AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("uint32_t") {
|
||||||
|
bool result = variant.set(uint32_t(42));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<uint32_t>() == true);
|
||||||
|
REQUIRE(variant.as<uint32_t>() == 42);
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("uint64_t") {
|
||||||
|
bool result = variant.set(uint64_t(4294967296));
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(variant.is<uint64_t>() == true);
|
||||||
|
REQUIRE(variant.as<uint64_t>() == 4294967296);
|
||||||
|
REQUIRE(spy.log() ==
|
||||||
|
AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("JsonDocument") {
|
||||||
|
JsonDocument doc1;
|
||||||
|
doc1["hello"] = "world";
|
||||||
|
|
||||||
|
// Should copy the doc
|
||||||
|
variant.set(doc1);
|
||||||
|
doc1.clear();
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,22 +264,20 @@ TEST_CASE("JsonVariant::set() with not enough memory") {
|
|||||||
REQUIRE(result == false);
|
REQUIRE(result == false);
|
||||||
REQUIRE(v.isNull());
|
REQUIRE(v.isNull());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set(JsonDocument)") {
|
SECTION("float") {
|
||||||
JsonDocument doc1;
|
bool result = v.set(1.2f);
|
||||||
doc1["hello"] = "world";
|
|
||||||
|
|
||||||
JsonDocument doc2;
|
REQUIRE(result == true);
|
||||||
JsonVariant v = doc2.to<JsonVariant>();
|
REQUIRE(v.is<float>());
|
||||||
|
}
|
||||||
|
|
||||||
// Should copy the doc
|
SECTION("double") {
|
||||||
v.set(doc1);
|
bool result = v.set(1.2);
|
||||||
doc1.clear();
|
|
||||||
|
|
||||||
std::string json;
|
REQUIRE(result == false);
|
||||||
serializeJson(doc2, json);
|
REQUIRE(v.isNull());
|
||||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonVariant::set() releases the previous value") {
|
TEST_CASE("JsonVariant::set() releases the previous value") {
|
||||||
@ -220,3 +324,30 @@ TEST_CASE("JsonVariant::set() releases the previous value") {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Extension slots") {
|
||||||
|
SpyingAllocator spy;
|
||||||
|
JsonDocument doc(&spy);
|
||||||
|
|
||||||
|
SECTION("double requires two slot") {
|
||||||
|
int i = ARDUINOJSON_POOL_CAPACITY - 1;
|
||||||
|
|
||||||
|
// make sure the pool is full
|
||||||
|
doc[i] = 1;
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
});
|
||||||
|
|
||||||
|
// replace with a float => no allocation
|
||||||
|
spy.clearLog();
|
||||||
|
doc[i] = 1.2f;
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{});
|
||||||
|
|
||||||
|
// replace with a double => new pool needed
|
||||||
|
spy.clearLog();
|
||||||
|
doc[i] = 1.2;
|
||||||
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
|
Allocate(sizeofPool()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -137,8 +137,7 @@ struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
|
|||||||
return false;
|
return false;
|
||||||
auto resources = getResourceManager(dst);
|
auto resources = getResourceManager(dst);
|
||||||
data->clear(resources);
|
data->clear(resources);
|
||||||
data->setFloat(src, resources);
|
return data->setFloat(src, resources);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static T fromJson(JsonVariantConst src) {
|
static T fromJson(JsonVariantConst src) {
|
||||||
|
@ -416,14 +416,15 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<sizeof(T) == 4> setFloat(T value, ResourceManager*) {
|
enable_if_t<sizeof(T) == 4, bool> setFloat(T value, ResourceManager*) {
|
||||||
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_FLOAT;
|
type_ = VALUE_IS_FLOAT;
|
||||||
content_.asFloat = value;
|
content_.asFloat = value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<sizeof(T) == 8> setFloat(T value, ResourceManager*);
|
enable_if_t<sizeof(T) == 8, bool> setFloat(T value, ResourceManager*);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<is_signed<T>::value> setInteger(T value,
|
enable_if_t<is_signed<T>::value> setInteger(T value,
|
||||||
|
@ -65,8 +65,8 @@ inline const VariantExtension* VariantData::getExtension(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<sizeof(T) == 8> VariantData::setFloat(T value,
|
enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
|
||||||
ResourceManager* resources) {
|
T value, ResourceManager* resources) {
|
||||||
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
(void)resources; // silence warning
|
(void)resources; // silence warning
|
||||||
|
|
||||||
@ -78,16 +78,17 @@ enable_if_t<sizeof(T) == 8> VariantData::setFloat(T value,
|
|||||||
content_.asFloat = valueAsFloat;
|
content_.asFloat = valueAsFloat;
|
||||||
} else {
|
} else {
|
||||||
auto extension = resources->allocExtension();
|
auto extension = resources->allocExtension();
|
||||||
if (extension) {
|
if (!extension)
|
||||||
type_ = VALUE_IS_DOUBLE;
|
return false;
|
||||||
content_.asSlotId = extension.id();
|
type_ = VALUE_IS_DOUBLE;
|
||||||
extension->asDouble = value;
|
content_.asSlotId = extension.id();
|
||||||
}
|
extension->asDouble = value;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
type_ = VALUE_IS_FLOAT;
|
type_ = VALUE_IS_FLOAT;
|
||||||
content_.asFloat = valueAsFloat;
|
content_.asFloat = valueAsFloat;
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Reference in New Issue
Block a user