Initial commit of Arduino libraries
This commit is contained in:
33
ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt
Normal file
33
ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
# ArduinoJson - https://arduinojson.org
|
||||
# Copyright © 2014-2025, Benoit BLANCHON
|
||||
# MIT License
|
||||
|
||||
add_executable(JsonVariantTests
|
||||
add.cpp
|
||||
as.cpp
|
||||
clear.cpp
|
||||
compare.cpp
|
||||
converters.cpp
|
||||
copy.cpp
|
||||
is.cpp
|
||||
isnull.cpp
|
||||
misc.cpp
|
||||
nesting.cpp
|
||||
nullptr.cpp
|
||||
or.cpp
|
||||
overflow.cpp
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
stl_containers.cpp
|
||||
subscript.cpp
|
||||
types.cpp
|
||||
unbound.cpp
|
||||
)
|
||||
|
||||
add_test(JsonVariant JsonVariantTests)
|
||||
|
||||
set_tests_properties(JsonVariant
|
||||
PROPERTIES
|
||||
LABELS "Catch"
|
||||
)
|
||||
128
ArduinoJson/extras/tests/JsonVariant/add.cpp
Normal file
128
ArduinoJson/extras/tests/JsonVariant/add.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("JsonVariant::add(T)") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("add integer to new variant") {
|
||||
var.add(42);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[42]");
|
||||
}
|
||||
|
||||
SECTION("add const char* to new variant") {
|
||||
var.add("hello");
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||
}
|
||||
|
||||
SECTION("add std::string to new variant") {
|
||||
var.add("hello"_s);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||
}
|
||||
|
||||
SECTION("add integer to integer") {
|
||||
var.set(123);
|
||||
|
||||
var.add(456); // no-op
|
||||
|
||||
REQUIRE(var.as<std::string>() == "123");
|
||||
}
|
||||
|
||||
SECTION("add integer to object") {
|
||||
var["val"] = 123;
|
||||
|
||||
var.add(456); // no-op
|
||||
|
||||
REQUIRE(var.as<std::string>() == "{\"val\":123}");
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("supports VLAs") {
|
||||
size_t i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
var.add(vla);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::add<T>()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("JsonArray") {
|
||||
JsonArray array = var.add<JsonArray>();
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
REQUIRE(doc.as<std::string>() == "[[1,2]]");
|
||||
}
|
||||
|
||||
SECTION("JsonVariant") {
|
||||
JsonVariant variant = var.add<JsonVariant>();
|
||||
variant.set(42);
|
||||
REQUIRE(doc.as<std::string>() == "[42]");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonObject::add(JsonObject) ") {
|
||||
JsonDocument doc1;
|
||||
doc1["hello"_s] = "world"_s;
|
||||
|
||||
TimebombAllocator allocator(10);
|
||||
SpyingAllocator spy(&allocator);
|
||||
JsonDocument doc2(&spy);
|
||||
JsonVariant variant = doc2.to<JsonVariant>();
|
||||
|
||||
SECTION("success") {
|
||||
bool result = variant.add(doc1.as<JsonObject>());
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofPool()),
|
||||
Allocate(sizeofString("hello")),
|
||||
Allocate(sizeofString("world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("partial failure") { // issue #2081
|
||||
allocator.setCountdown(2);
|
||||
|
||||
bool result = variant.add(doc1.as<JsonObject>());
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(doc2.as<std::string>() == "[]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofPool()),
|
||||
Allocate(sizeofString("hello")),
|
||||
AllocateFail(sizeofString("world")),
|
||||
Deallocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("complete failure") {
|
||||
allocator.setCountdown(0);
|
||||
|
||||
bool result = variant.add(doc1.as<JsonObject>());
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(doc2.as<std::string>() == "[]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
AllocateFail(sizeofPool()),
|
||||
});
|
||||
}
|
||||
}
|
||||
327
ArduinoJson/extras/tests/JsonVariant/as.cpp
Normal file
327
ArduinoJson/extras/tests/JsonVariant/as.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Literals.hpp"
|
||||
|
||||
namespace my {
|
||||
using ArduinoJson::detail::isinf;
|
||||
} // namespace my
|
||||
|
||||
enum MY_ENUM { ONE = 1, TWO = 2 };
|
||||
|
||||
TEST_CASE("JsonVariant::as()") {
|
||||
static const char* null = 0;
|
||||
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("not set") {
|
||||
REQUIRE(false == variant.as<bool>());
|
||||
REQUIRE(0 == variant.as<int>());
|
||||
REQUIRE(0.0f == variant.as<float>());
|
||||
REQUIRE(0 == variant.as<const char*>());
|
||||
REQUIRE("null" == variant.as<std::string>());
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(float)") {
|
||||
variant.set(4.2f);
|
||||
|
||||
REQUIRE(variant.as<bool>());
|
||||
REQUIRE(0 == variant.as<const char*>());
|
||||
REQUIRE(variant.as<std::string>() == "4.2");
|
||||
REQUIRE(variant.as<long>() == 4L);
|
||||
REQUIRE(variant.as<float>() == 4.2f);
|
||||
REQUIRE(variant.as<unsigned>() == 4U);
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(double)") {
|
||||
variant.set(4.2);
|
||||
|
||||
REQUIRE(variant.as<bool>());
|
||||
REQUIRE(0 == variant.as<const char*>());
|
||||
REQUIRE(variant.as<std::string>() == "4.2");
|
||||
REQUIRE(variant.as<long>() == 4L);
|
||||
REQUIRE(variant.as<double>() == 4.2);
|
||||
REQUIRE(variant.as<unsigned>() == 4U);
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(0.0)") {
|
||||
variant.set(0.0);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<long>() == 0L);
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(false)") {
|
||||
variant.set(false);
|
||||
|
||||
REQUIRE(false == variant.as<bool>());
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<long>() == 0L);
|
||||
REQUIRE(variant.as<std::string>() == "false");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(true)") {
|
||||
variant.set(true);
|
||||
|
||||
REQUIRE(variant.as<bool>());
|
||||
REQUIRE(variant.as<double>() == 1.0);
|
||||
REQUIRE(variant.as<long>() == 1L);
|
||||
REQUIRE(variant.as<std::string>() == "true");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(uint32_t)") {
|
||||
variant.set(4294967295U);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == 4294967295.0);
|
||||
REQUIRE(variant.as<int32_t>() == 0);
|
||||
REQUIRE(variant.as<uint32_t>() == 4294967295U);
|
||||
REQUIRE(variant.as<uint64_t>() == 4294967295U);
|
||||
REQUIRE(variant.as<std::string>() == "4294967295");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(int32_t)") {
|
||||
variant.set(-2147483648LL);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == -2147483648LL);
|
||||
REQUIRE(variant.as<int32_t>() == -2147483648LL);
|
||||
REQUIRE(variant.as<int64_t>() == -2147483648LL);
|
||||
REQUIRE(variant.as<uint32_t>() == 0);
|
||||
REQUIRE(variant.as<uint64_t>() == 0);
|
||||
REQUIRE(variant.as<std::string>() == "-2147483648");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(uint64_t)") {
|
||||
variant.set(4294967296U);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == 4294967296.0);
|
||||
REQUIRE(variant.as<int32_t>() == 0);
|
||||
REQUIRE(variant.as<uint32_t>() == 0);
|
||||
REQUIRE(variant.as<uint64_t>() == 4294967296U);
|
||||
REQUIRE(variant.as<std::string>() == "4294967296");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(int64_t)") {
|
||||
variant.set(-2147483649LL);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == -2147483649LL);
|
||||
REQUIRE(variant.as<int32_t>() == 0);
|
||||
REQUIRE(variant.as<int64_t>() == -2147483649LL);
|
||||
REQUIRE(variant.as<uint32_t>() == 0);
|
||||
REQUIRE(variant.as<uint64_t>() == 0);
|
||||
REQUIRE(variant.as<std::string>() == "-2147483649");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("set(0L)") {
|
||||
variant.set(0L);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<std::string>() == "0");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(0UL)") {
|
||||
variant.set(0UL);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<std::string>() == "0");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(null)") {
|
||||
variant.set(null);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<long>() == 0L);
|
||||
REQUIRE(variant.as<std::string>() == "null");
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(\"42\")") {
|
||||
variant.set("42");
|
||||
|
||||
REQUIRE(variant.as<long>() == 42L);
|
||||
REQUIRE(variant.as<double>() == 42);
|
||||
REQUIRE(variant.as<JsonString>() == "42");
|
||||
REQUIRE(variant.as<JsonString>().isStatic() == true);
|
||||
}
|
||||
|
||||
SECTION("set(\"hello\")") {
|
||||
variant.set("hello");
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<long>() == 0L);
|
||||
REQUIRE(variant.as<const char*>() == "hello"_s);
|
||||
REQUIRE(variant.as<const char*>() == "hello"_s);
|
||||
REQUIRE(variant.as<std::string>() == "hello"_s);
|
||||
REQUIRE(variant.as<JsonString>() == "hello");
|
||||
}
|
||||
|
||||
SECTION("set(std::string(\"4.2\")) (tiny string optimization)") {
|
||||
variant.set("4.2"_s);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<long>() == 4L);
|
||||
REQUIRE(variant.as<double>() == Approx(4.2));
|
||||
REQUIRE(variant.as<const char*>() == "4.2"_s);
|
||||
REQUIRE(variant.as<std::string>() == "4.2"_s);
|
||||
REQUIRE(variant.as<JsonString>() == "4.2");
|
||||
REQUIRE(variant.as<JsonString>().isStatic() == false);
|
||||
}
|
||||
|
||||
SECTION("set(std::string(\"123.45\"))") {
|
||||
variant.set("123.45"_s);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<long>() == 123L);
|
||||
REQUIRE(variant.as<double>() == Approx(123.45));
|
||||
REQUIRE(variant.as<const char*>() == "123.45"_s);
|
||||
REQUIRE(variant.as<std::string>() == "123.45"_s);
|
||||
REQUIRE(variant.as<JsonString>() == "123.45");
|
||||
REQUIRE(variant.as<JsonString>().isStatic() == false);
|
||||
}
|
||||
|
||||
SECTION("set(\"true\")") {
|
||||
variant.set("true");
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<int>() == 0);
|
||||
REQUIRE(variant.as<JsonString>() == "true");
|
||||
}
|
||||
|
||||
SECTION("set(-1e300)") {
|
||||
variant.set(-1e300);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == -1e300);
|
||||
REQUIRE(variant.as<float>() < 0);
|
||||
REQUIRE(my::isinf(variant.as<float>()));
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(1e300)") {
|
||||
variant.set(1e300);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == 1e300);
|
||||
REQUIRE(variant.as<float>() > 0);
|
||||
REQUIRE(my::isinf(variant.as<float>()));
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(1e-300)") {
|
||||
variant.set(1e-300);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == 1e-300);
|
||||
REQUIRE(variant.as<float>() == 0);
|
||||
REQUIRE(variant.as<JsonString>().isNull());
|
||||
}
|
||||
|
||||
SECTION("set(serialized(\"hello\"))") {
|
||||
variant.set(serialized("hello"));
|
||||
|
||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("to<JsonObject>()") {
|
||||
JsonObject obj = variant.to<JsonObject>();
|
||||
obj["key"] = "value";
|
||||
|
||||
SECTION("as<bool>()") {
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
}
|
||||
|
||||
SECTION("as<std::string>()") {
|
||||
REQUIRE(variant.as<std::string>() == "{\"key\":\"value\"}"_s);
|
||||
}
|
||||
|
||||
SECTION("ObjectAsJsonObject") {
|
||||
JsonObject o = variant.as<JsonObject>();
|
||||
REQUIRE(o.size() == 1);
|
||||
REQUIRE(o["key"] == "value"_s);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("to<JsonArray>()") {
|
||||
JsonArray arr = variant.to<JsonArray>();
|
||||
arr.add(4);
|
||||
arr.add(2);
|
||||
|
||||
SECTION("as<bool>()") {
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
}
|
||||
|
||||
SECTION("as<std::string>()") {
|
||||
REQUIRE(variant.as<std::string>() == "[4,2]"_s);
|
||||
}
|
||||
|
||||
SECTION("as<JsonArray>()") {
|
||||
JsonArray a = variant.as<JsonArray>();
|
||||
REQUIRE(a.size() == 2);
|
||||
REQUIRE(a[0] == 4);
|
||||
REQUIRE(a[1] == 2);
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
SECTION("Smallest int64 negative") {
|
||||
variant.set("-9223372036854775808");
|
||||
REQUIRE(variant.as<long long>() == -9223372036854775807 - 1);
|
||||
}
|
||||
|
||||
SECTION("Biggest int64 positive") {
|
||||
variant.set("9223372036854775807");
|
||||
REQUIRE(variant.as<long long>() == 9223372036854775807);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("as<enum>()") {
|
||||
variant.set(1);
|
||||
|
||||
REQUIRE(variant.as<MY_ENUM>() == ONE);
|
||||
}
|
||||
}
|
||||
40
ArduinoJson/extras/tests/JsonVariant/clear.cpp
Normal file
40
ArduinoJson/extras/tests/JsonVariant/clear.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("JsonVariant::clear()") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("size goes back to zero") {
|
||||
var.add(42);
|
||||
var.clear();
|
||||
|
||||
REQUIRE(var.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("isNull() return true") {
|
||||
var.add("hello");
|
||||
var.clear();
|
||||
|
||||
REQUIRE(var.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("releases owned string") {
|
||||
var.set("hello"_s);
|
||||
var.clear();
|
||||
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
Deallocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
}
|
||||
352
ArduinoJson/extras/tests/JsonVariant/compare.cpp
Normal file
352
ArduinoJson/extras/tests/JsonVariant/compare.cpp
Normal file
@@ -0,0 +1,352 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
// Most code is already covered by arithmeticCompare.cpp.
|
||||
// Here, we're just filling the holes
|
||||
|
||||
TEST_CASE("Compare JsonVariant with value") {
|
||||
JsonDocument doc;
|
||||
JsonVariant a = doc.add<JsonVariant>();
|
||||
|
||||
SECTION("null vs (char*)0") {
|
||||
char* b = 0;
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42") {
|
||||
a.set(42);
|
||||
int b = 42;
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Compare JsonVariant with JsonVariant") {
|
||||
JsonDocument doc;
|
||||
JsonVariant a = doc.add<JsonVariant>();
|
||||
JsonVariant b = doc.add<JsonVariant>();
|
||||
|
||||
SECTION("'abc' vs 'abc'") {
|
||||
a.set("abc");
|
||||
b.set("abc");
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("'abc' vs 'bcd'") {
|
||||
a.set("abc");
|
||||
b.set("bcd");
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("'bcd' vs 'abc'") {
|
||||
a.set("bcd");
|
||||
b.set("abc");
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("serialized('abc') vs serialized('abc')") {
|
||||
a.set(serialized("abc"));
|
||||
b.set(serialized("abc"));
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("serialized('abc') vs serialized('bcd')") {
|
||||
a.set(serialized("abc"));
|
||||
b.set(serialized("bcd"));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("serialized('bcd') vs serialized('abc')") {
|
||||
a.set(serialized("bcd"));
|
||||
b.set(serialized("abc"));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("MsgPackBinary('abc') vs MsgPackBinary('abc')") {
|
||||
a.set(MsgPackBinary("abc", 4));
|
||||
b.set(MsgPackBinary("abc", 4));
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("MsgPackBinary('abc') vs MsgPackBinary('bcd')") {
|
||||
a.set(MsgPackBinary("abc", 4));
|
||||
b.set(MsgPackBinary("bcd", 4));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("MsgPackBinary('bcd') vs MsgPackBinary('abc')") {
|
||||
a.set(MsgPackBinary("bcd", 4));
|
||||
b.set(MsgPackBinary("abc", 4));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("false vs true") {
|
||||
a.set(false);
|
||||
b.set(true);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("false vs -1") {
|
||||
a.set(false);
|
||||
b.set(-1);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("null vs null") {
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42") {
|
||||
a.set(42);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42U") {
|
||||
a.set(42);
|
||||
b.set(42U);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42.0") {
|
||||
a.set(42);
|
||||
b.set(42.0);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42.0 vs 42") {
|
||||
a.set(42.0);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("-42 vs -42") {
|
||||
a.set(-42);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("-42 vs 42") {
|
||||
a.set(-42);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("42 vs -42") {
|
||||
a.set(42);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("42.0 vs -42") {
|
||||
a.set(42.0);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("42U vs 42U") {
|
||||
a.set(42U);
|
||||
b.set(42U);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42U vs 42") {
|
||||
a.set(42U);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("[1] vs [1]") {
|
||||
a.add(1);
|
||||
b.add(1);
|
||||
|
||||
CHECK(a <= b);
|
||||
CHECK(a == b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("[1] vs [2]") {
|
||||
a.add(1);
|
||||
b.add(2);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("{x:1} vs {x:1}") {
|
||||
a["x"] = 1;
|
||||
b["x"] = 1;
|
||||
|
||||
CHECK(a <= b);
|
||||
CHECK(a == b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("{x:1} vs {x:2}") {
|
||||
a["x"] = 1;
|
||||
b["x"] = 2;
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
}
|
||||
142
ArduinoJson/extras/tests/JsonVariant/converters.cpp
Normal file
142
ArduinoJson/extras/tests/JsonVariant/converters.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
namespace {
|
||||
struct Date {
|
||||
int day;
|
||||
int month;
|
||||
int year;
|
||||
};
|
||||
|
||||
void convertToJson(const Date& src, JsonVariant dst) {
|
||||
dst["day"] = src.day;
|
||||
dst["month"] = src.month;
|
||||
dst["year"] = src.year;
|
||||
}
|
||||
|
||||
void convertFromJson(JsonVariantConst src, Date& dst) {
|
||||
dst.day = src["day"];
|
||||
dst.month = src["month"];
|
||||
dst.year = src["year"];
|
||||
}
|
||||
|
||||
bool canConvertFromJson(JsonVariantConst src, const Date&) {
|
||||
return src["day"].is<int>() && src["month"].is<int>() &&
|
||||
src["year"].is<int>();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Custom converter with overloading") {
|
||||
JsonDocument doc;
|
||||
|
||||
SECTION("convert JSON to Date") {
|
||||
doc["date"]["day"] = 2;
|
||||
doc["date"]["month"] = 3;
|
||||
doc["date"]["year"] = 2021;
|
||||
|
||||
Date date = doc["date"];
|
||||
|
||||
REQUIRE(date.day == 2);
|
||||
REQUIRE(date.month == 3);
|
||||
REQUIRE(date.year == 2021);
|
||||
}
|
||||
|
||||
SECTION("is<Date>() returns true") {
|
||||
doc["date"]["day"] = 2;
|
||||
doc["date"]["month"] = 3;
|
||||
doc["date"]["year"] = 2021;
|
||||
|
||||
REQUIRE(doc["date"].is<Date>());
|
||||
}
|
||||
|
||||
SECTION("is<Date>() returns false") {
|
||||
doc["date"]["day"] = 2;
|
||||
doc["date"]["month"] = 3;
|
||||
doc["date"]["year"] = "2021";
|
||||
|
||||
REQUIRE(doc["date"].is<Date>() == false);
|
||||
}
|
||||
|
||||
SECTION("convert Date to JSON") {
|
||||
Date date = {19, 3, 2021};
|
||||
doc["date"] = date;
|
||||
|
||||
REQUIRE(doc["date"]["day"] == 19);
|
||||
REQUIRE(doc["date"]["month"] == 3);
|
||||
REQUIRE(doc["date"]["year"] == 2021);
|
||||
}
|
||||
}
|
||||
|
||||
class Complex {
|
||||
public:
|
||||
explicit Complex(double r, double i) : real_(r), imag_(i) {}
|
||||
|
||||
double real() const {
|
||||
return real_;
|
||||
}
|
||||
|
||||
double imag() const {
|
||||
return imag_;
|
||||
}
|
||||
|
||||
private:
|
||||
double real_, imag_;
|
||||
};
|
||||
|
||||
namespace ArduinoJson {
|
||||
template <>
|
||||
struct Converter<Complex> {
|
||||
static void toJson(const Complex& src, JsonVariant dst) {
|
||||
dst["real"] = src.real();
|
||||
dst["imag"] = src.imag();
|
||||
}
|
||||
|
||||
static Complex fromJson(JsonVariantConst src) {
|
||||
return Complex(src["real"], src["imag"]);
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
return src["real"].is<double>() && src["imag"].is<double>();
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
||||
|
||||
TEST_CASE("Custom converter with specialization") {
|
||||
JsonDocument doc;
|
||||
|
||||
SECTION("convert JSON to Complex") {
|
||||
doc["value"]["real"] = 2;
|
||||
doc["value"]["imag"] = 3;
|
||||
|
||||
Complex value = doc["value"];
|
||||
|
||||
REQUIRE(value.real() == 2);
|
||||
REQUIRE(value.imag() == 3);
|
||||
}
|
||||
|
||||
SECTION("is<Complex>() returns true") {
|
||||
doc["value"]["real"] = 2;
|
||||
doc["value"]["imag"] = 3;
|
||||
|
||||
REQUIRE(doc["value"].is<Complex>());
|
||||
}
|
||||
|
||||
SECTION("is<Complex>() returns false") {
|
||||
doc["value"]["real"] = 2;
|
||||
doc["value"]["imag"] = "3";
|
||||
|
||||
REQUIRE(doc["value"].is<Complex>() == false);
|
||||
}
|
||||
|
||||
SECTION("convert value to JSON") {
|
||||
doc["value"] = Complex(19, 3);
|
||||
|
||||
REQUIRE(doc["value"]["real"] == 19);
|
||||
REQUIRE(doc["value"]["imag"] == 3);
|
||||
}
|
||||
}
|
||||
142
ArduinoJson/extras/tests/JsonVariant/copy.cpp
Normal file
142
ArduinoJson/extras/tests/JsonVariant/copy.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
#include "Allocators.hpp"
|
||||
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("JsonVariant::set(JsonVariant)") {
|
||||
KillswitchAllocator killswitch;
|
||||
SpyingAllocator spyingAllocator(&killswitch);
|
||||
JsonDocument doc1(&spyingAllocator);
|
||||
JsonDocument doc2(&spyingAllocator);
|
||||
JsonVariant var1 = doc1.to<JsonVariant>();
|
||||
JsonVariant var2 = doc2.to<JsonVariant>();
|
||||
|
||||
SECTION("stores JsonArray by copy") {
|
||||
JsonArray arr = doc2.to<JsonArray>();
|
||||
JsonObject obj = arr.add<JsonObject>();
|
||||
obj["hello"] = "world";
|
||||
|
||||
var1.set(arr);
|
||||
|
||||
arr[0] = 666;
|
||||
REQUIRE(var1.as<std::string>() == "[{\"hello\":\"world\"}]");
|
||||
}
|
||||
|
||||
SECTION("stores JsonObject by copy") {
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
JsonArray arr = obj["value"].to<JsonArray>();
|
||||
arr.add(42);
|
||||
|
||||
var1.set(obj);
|
||||
|
||||
obj["value"] = 666;
|
||||
REQUIRE(var1.as<std::string>() == "{\"value\":[42]}");
|
||||
}
|
||||
|
||||
SECTION("stores const char* by reference") {
|
||||
var1.set("hello!!");
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("stores char* by copy") {
|
||||
char str[] = "hello!!";
|
||||
var1.set(str);
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("fails gracefully if string allocation fails") {
|
||||
char str[] = "hello!!";
|
||||
var1.set(str);
|
||||
killswitch.on();
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc2.overflowed() == true);
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
AllocateFail(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("stores std::string by copy") {
|
||||
var1.set("hello!!"_s);
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("stores Serialized<const char*> by copy") {
|
||||
var1.set(serialized("hello!!", 7));
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("stores Serialized<char*> by copy") {
|
||||
char str[] = "hello!!";
|
||||
var1.set(serialized(str, 7));
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("stores Serialized<std::string> by copy") {
|
||||
var1.set(serialized("hello!!"_s));
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("fails gracefully if raw string allocation fails") {
|
||||
var1.set(serialized("hello!!"_s));
|
||||
killswitch.on();
|
||||
spyingAllocator.clearLog();
|
||||
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc2.overflowed() == true);
|
||||
REQUIRE(spyingAllocator.log() == AllocatorLog{
|
||||
AllocateFail(sizeofString("hello!!")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("destination is unbound") {
|
||||
JsonVariant unboundVariant;
|
||||
|
||||
unboundVariant.set(var1);
|
||||
|
||||
REQUIRE(unboundVariant.isUnbound());
|
||||
REQUIRE(unboundVariant.isNull());
|
||||
}
|
||||
}
|
||||
164
ArduinoJson/extras/tests/JsonVariant/is.cpp
Normal file
164
ArduinoJson/extras/tests/JsonVariant/is.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
enum MYENUM2 { ONE = 1, TWO = 2 };
|
||||
|
||||
TEST_CASE("JsonVariant::is<T>()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("unbound") {
|
||||
variant = JsonVariant();
|
||||
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<JsonVariant>() == false);
|
||||
CHECK(variant.is<JsonVariantConst>() == false);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
}
|
||||
|
||||
SECTION("null") {
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("true") {
|
||||
variant.set(true);
|
||||
|
||||
CHECK(variant.is<bool>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("false") {
|
||||
variant.set(false);
|
||||
|
||||
CHECK(variant.is<bool>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("int") {
|
||||
variant.set(42);
|
||||
|
||||
CHECK(variant.is<int>() == true);
|
||||
CHECK(variant.is<short>() == true);
|
||||
CHECK(variant.is<long>() == true);
|
||||
CHECK(variant.is<double>() == true);
|
||||
CHECK(variant.is<float>() == true);
|
||||
CHECK(variant.is<MYENUM2>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
}
|
||||
|
||||
SECTION("double") {
|
||||
variant.set(4.2);
|
||||
|
||||
CHECK(variant.is<double>() == true);
|
||||
CHECK(variant.is<float>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<std::string>() == false);
|
||||
CHECK(variant.is<JsonString>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
variant.set("4.2");
|
||||
|
||||
CHECK(variant.is<const char*>() == true);
|
||||
CHECK(variant.is<const char*>() == true);
|
||||
CHECK(variant.is<std::string>() == true);
|
||||
CHECK(variant.is<JsonString>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<double>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("JsonArray") {
|
||||
variant.to<JsonArray>();
|
||||
|
||||
CHECK(variant.is<JsonArray>() == true);
|
||||
CHECK(variant.is<JsonArrayConst>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<JsonObject>() == false);
|
||||
CHECK(variant.is<JsonObjectConst>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
}
|
||||
|
||||
SECTION("JsonObject") {
|
||||
variant.to<JsonObject>();
|
||||
|
||||
CHECK(variant.is<JsonObject>() == true);
|
||||
CHECK(variant.is<JsonObjectConst>() == true);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
CHECK(variant.is<JsonArray>() == false);
|
||||
CHECK(variant.is<JsonArrayConst>() == false);
|
||||
CHECK(variant.is<int>() == false);
|
||||
CHECK(variant.is<float>() == false);
|
||||
CHECK(variant.is<bool>() == false);
|
||||
CHECK(variant.is<const char*>() == false);
|
||||
CHECK(variant.is<MYENUM2>() == false);
|
||||
CHECK(variant.is<JsonVariant>() == true);
|
||||
CHECK(variant.is<JsonVariantConst>() == true);
|
||||
}
|
||||
}
|
||||
72
ArduinoJson/extras/tests/JsonVariant/isnull.cpp
Normal file
72
ArduinoJson/extras/tests/JsonVariant/isnull.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonVariant::isNull()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("returns true when Undefined") {
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false when Integer") {
|
||||
variant.set(42);
|
||||
|
||||
REQUIRE(variant.isNull() == false);
|
||||
}
|
||||
|
||||
SECTION("returns false when EmptyArray") {
|
||||
JsonDocument doc2;
|
||||
JsonArray array = doc2.to<JsonArray>();
|
||||
|
||||
variant.set(array);
|
||||
REQUIRE(variant.isNull() == false);
|
||||
}
|
||||
|
||||
SECTION("returns false when EmptyObject") {
|
||||
JsonDocument doc2;
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
|
||||
variant.set(obj);
|
||||
REQUIRE(variant.isNull() == false);
|
||||
}
|
||||
|
||||
SECTION("returns true after set(JsonArray())") {
|
||||
variant.set(JsonArray());
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns true after set(JsonObject())") {
|
||||
variant.set(JsonObject());
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after set('hello')") {
|
||||
variant.set("hello");
|
||||
REQUIRE(variant.isNull() == false);
|
||||
}
|
||||
|
||||
SECTION("returns true after set((char*)0)") {
|
||||
variant.set(static_cast<char*>(0));
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns true after set((const char*)0)") {
|
||||
variant.set(static_cast<const char*>(0));
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns true after set(serialized((char*)0))") {
|
||||
variant.set(serialized(static_cast<char*>(0)));
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns true after set(serialized((const char*)0))") {
|
||||
variant.set(serialized(static_cast<const char*>(0)));
|
||||
REQUIRE(variant.isNull() == true);
|
||||
}
|
||||
}
|
||||
60
ArduinoJson/extras/tests/JsonVariant/misc.cpp
Normal file
60
ArduinoJson/extras/tests/JsonVariant/misc.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("VariantData") {
|
||||
REQUIRE(std::is_standard_layout<ArduinoJson::detail::VariantData>::value ==
|
||||
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;
|
||||
JsonVariant v = arr;
|
||||
REQUIRE(v.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("JsonArray is not null") {
|
||||
JsonDocument doc;
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
arr.add(12);
|
||||
arr.add(34);
|
||||
|
||||
JsonVariant v = arr;
|
||||
|
||||
REQUIRE(v.is<JsonArray>() == true);
|
||||
REQUIRE(v.size() == 2);
|
||||
REQUIRE(v[0] == 12);
|
||||
REQUIRE(v[1] == 34);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant from JsonObject") {
|
||||
SECTION("JsonObject is null") {
|
||||
JsonObject obj;
|
||||
JsonVariant v = obj;
|
||||
REQUIRE(v.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("JsonObject is not null") {
|
||||
JsonDocument doc;
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
obj["a"] = 12;
|
||||
obj["b"] = 34;
|
||||
|
||||
JsonVariant v = obj;
|
||||
|
||||
REQUIRE(v.is<JsonObject>() == true);
|
||||
REQUIRE(v.size() == 2);
|
||||
REQUIRE(v["a"] == 12);
|
||||
REQUIRE(v["b"] == 34);
|
||||
}
|
||||
}
|
||||
31
ArduinoJson/extras/tests/JsonVariant/nesting.cpp
Normal file
31
ArduinoJson/extras/tests/JsonVariant/nesting.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonVariant::nesting()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("return 0 if uninitialized") {
|
||||
JsonVariant unitialized;
|
||||
REQUIRE(unitialized.nesting() == 0);
|
||||
}
|
||||
|
||||
SECTION("returns 0 for string") {
|
||||
var.set("hello");
|
||||
REQUIRE(var.nesting() == 0);
|
||||
}
|
||||
|
||||
SECTION("returns 1 for empty object") {
|
||||
var.to<JsonObject>();
|
||||
REQUIRE(var.nesting() == 1);
|
||||
}
|
||||
|
||||
SECTION("returns 1 for empty array") {
|
||||
var.to<JsonArray>();
|
||||
REQUIRE(var.nesting() == 1);
|
||||
}
|
||||
}
|
||||
43
ArduinoJson/extras/tests/JsonVariant/nullptr.cpp
Normal file
43
ArduinoJson/extras/tests/JsonVariant/nullptr.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("nullptr") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("JsonVariant == nullptr") {
|
||||
REQUIRE(variant == nullptr);
|
||||
REQUIRE_FALSE(variant != nullptr);
|
||||
}
|
||||
|
||||
SECTION("JsonVariant != nullptr") {
|
||||
variant.set(42);
|
||||
|
||||
REQUIRE_FALSE(variant == nullptr);
|
||||
REQUIRE(variant != nullptr);
|
||||
}
|
||||
|
||||
SECTION("JsonVariant.set(nullptr)") {
|
||||
variant.set(42);
|
||||
variant.set(nullptr);
|
||||
|
||||
REQUIRE(variant.isNull());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant.set(nullptr) with unbound reference") {
|
||||
JsonVariant unboundReference;
|
||||
|
||||
unboundReference.set(nullptr);
|
||||
|
||||
REQUIRE(variant.isNull());
|
||||
}
|
||||
|
||||
SECTION("JsonVariant.is<nullptr_t>()") {
|
||||
variant.set(42);
|
||||
REQUIRE(variant.is<std::nullptr_t>() == false);
|
||||
|
||||
variant.clear();
|
||||
REQUIRE(variant.is<std::nullptr_t>() == true);
|
||||
}
|
||||
}
|
||||
159
ArduinoJson/extras/tests/JsonVariant/or.cpp
Normal file
159
ArduinoJson/extras/tests/JsonVariant/or.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonVariant::operator|()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc["value"].to<JsonVariant>();
|
||||
|
||||
SECTION("null") {
|
||||
SECTION("null | const char*") {
|
||||
std::string result = variant | "default";
|
||||
REQUIRE(result == "default");
|
||||
}
|
||||
|
||||
SECTION("null | int") {
|
||||
int result = variant | 42;
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("null | bool") {
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == true);
|
||||
}
|
||||
|
||||
SECTION("null | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("null | MemberProxy") {
|
||||
doc["other"] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("ElementProxy | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = doc["array"][1] | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null") {
|
||||
variant.set(static_cast<const char*>(0));
|
||||
|
||||
SECTION("null | const char*") {
|
||||
std::string result = variant | "default";
|
||||
REQUIRE(result == "default");
|
||||
}
|
||||
|
||||
SECTION("null | int") {
|
||||
int result = variant | 42;
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("null | bool") {
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == true);
|
||||
}
|
||||
|
||||
SECTION("null | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("null | MemberProxy") {
|
||||
doc["other"] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("int | const char*") {
|
||||
variant.set(42);
|
||||
std::string result = variant | "default";
|
||||
REQUIRE(result == "default");
|
||||
}
|
||||
|
||||
SECTION("int | uint8_t (out of range)") {
|
||||
variant.set(666);
|
||||
uint8_t result = variant | static_cast<uint8_t>(42);
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | ElementProxy") {
|
||||
variant.set(42);
|
||||
doc["array"][0] = 666;
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | MemberProxy") {
|
||||
variant.set(42);
|
||||
doc["other"] = 666;
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | int") {
|
||||
variant.set(0);
|
||||
int result = variant | 666;
|
||||
REQUIRE(result == 0);
|
||||
}
|
||||
|
||||
SECTION("double | int") {
|
||||
// NOTE: changed the behavior to fix #981
|
||||
variant.set(666.0);
|
||||
int result = variant | 42;
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("bool | bool") {
|
||||
variant.set(false);
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == false);
|
||||
}
|
||||
|
||||
SECTION("int | bool") {
|
||||
variant.set(0);
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == true);
|
||||
}
|
||||
|
||||
SECTION("const char* | const char*") {
|
||||
variant.set("not default");
|
||||
std::string result = variant | "default";
|
||||
REQUIRE(result == "not default");
|
||||
}
|
||||
|
||||
SECTION("const char* | char*") {
|
||||
char dflt[] = "default";
|
||||
variant.set("not default");
|
||||
std::string result = variant | dflt;
|
||||
REQUIRE(result == "not default");
|
||||
}
|
||||
|
||||
SECTION("int | char*") {
|
||||
char dflt[] = "default";
|
||||
variant.set(42);
|
||||
std::string result = variant | dflt;
|
||||
REQUIRE(result == "default");
|
||||
}
|
||||
|
||||
SECTION("const char* | int") {
|
||||
variant.set("not default");
|
||||
int result = variant | 42;
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
}
|
||||
72
ArduinoJson/extras/tests/JsonVariant/overflow.cpp
Normal file
72
ArduinoJson/extras/tests/JsonVariant/overflow.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
void shouldBeOk(TIn value) {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
var.set(value);
|
||||
REQUIRE(var.as<TOut>() == TOut(value));
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
void shouldOverflow(TIn value) {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
var.set(value);
|
||||
REQUIRE(var.as<TOut>() == 0);
|
||||
REQUIRE(var.is<TOut>() == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Handle integer overflow in stored integer") {
|
||||
SECTION("int8_t") {
|
||||
// ok
|
||||
shouldBeOk<int8_t>(-128);
|
||||
shouldBeOk<int8_t>(42.0);
|
||||
shouldBeOk<int8_t>(127);
|
||||
|
||||
// too low
|
||||
shouldOverflow<int8_t>(-128.1);
|
||||
shouldOverflow<int8_t>(-129);
|
||||
|
||||
// too high
|
||||
shouldOverflow<int8_t>(128);
|
||||
shouldOverflow<int8_t>(127.1);
|
||||
}
|
||||
|
||||
SECTION("int16_t") {
|
||||
// ok
|
||||
shouldBeOk<int16_t>(-32768);
|
||||
shouldBeOk<int16_t>(-32767.9);
|
||||
shouldBeOk<int16_t>(32766.9);
|
||||
shouldBeOk<int16_t>(32767);
|
||||
|
||||
// too low
|
||||
shouldOverflow<int16_t>(-32768.1);
|
||||
shouldOverflow<int16_t>(-32769);
|
||||
|
||||
// too high
|
||||
shouldOverflow<int16_t>(32767.1);
|
||||
shouldOverflow<int16_t>(32768);
|
||||
}
|
||||
|
||||
SECTION("uint8_t") {
|
||||
// ok
|
||||
shouldBeOk<uint8_t>(1);
|
||||
shouldBeOk<uint8_t>(42.0);
|
||||
shouldBeOk<uint8_t>(255);
|
||||
|
||||
// too low
|
||||
shouldOverflow<uint8_t>(-1);
|
||||
shouldOverflow<uint8_t>(-0.1);
|
||||
|
||||
// to high
|
||||
shouldOverflow<uint8_t>(255.1);
|
||||
shouldOverflow<uint8_t>(256);
|
||||
shouldOverflow<uint8_t>(257);
|
||||
}
|
||||
}
|
||||
128
ArduinoJson/extras/tests/JsonVariant/remove.cpp
Normal file
128
ArduinoJson/extras/tests/JsonVariant/remove.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Literals.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofArray;
|
||||
|
||||
TEST_CASE("JsonVariant::remove(int)") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
|
||||
SECTION("release top level strings") {
|
||||
doc.add("hello"_s);
|
||||
doc.add("hello"_s);
|
||||
doc.add("world"_s);
|
||||
|
||||
JsonVariant var = doc.as<JsonVariant>();
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\",\"hello\",\"world\"]");
|
||||
|
||||
spy.clearLog();
|
||||
var.remove(1);
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\",\"world\"]");
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
|
||||
spy.clearLog();
|
||||
var.remove(1);
|
||||
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
});
|
||||
|
||||
spy.clearLog();
|
||||
var.remove(0);
|
||||
REQUIRE(var.as<std::string>() == "[]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("release strings in nested array") {
|
||||
doc[0][0] = "hello"_s;
|
||||
|
||||
JsonVariant var = doc.as<JsonVariant>();
|
||||
REQUIRE(var.as<std::string>() == "[[\"hello\"]]");
|
||||
|
||||
spy.clearLog();
|
||||
var.remove(0);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[]");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::remove(const char *)") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
var["a"] = 1;
|
||||
var["b"] = 2;
|
||||
|
||||
var.remove("a");
|
||||
|
||||
REQUIRE(var.as<std::string>() == "{\"b\":2}");
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::remove(std::string)") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
var["a"] = 1;
|
||||
var["b"] = 2;
|
||||
|
||||
var.remove("b"_s);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
TEST_CASE("JsonVariant::remove(VLA)") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
var["a"] = 1;
|
||||
var["b"] = 2;
|
||||
size_t i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "b");
|
||||
|
||||
var.remove("b"_s);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("JsonVariant::remove(JsonVariant) from object") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
var["a"] = "a";
|
||||
var["b"] = 2;
|
||||
var["c"] = "b";
|
||||
|
||||
var.remove(var["c"]);
|
||||
|
||||
REQUIRE(var.as<std::string>() == "{\"a\":\"a\",\"c\":\"b\"}");
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::remove(JsonVariant) from array") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
var[0] = 3;
|
||||
var[1] = 2;
|
||||
var[2] = 1;
|
||||
|
||||
var.remove(var[2]);
|
||||
var.remove(var[3]); // noop
|
||||
|
||||
REQUIRE(var.as<std::string>() == "[3,1]");
|
||||
}
|
||||
407
ArduinoJson/extras/tests/JsonVariant/set.cpp
Normal file
407
ArduinoJson/extras/tests/JsonVariant/set.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Literals.hpp"
|
||||
|
||||
using ArduinoJson::detail::sizeofObject;
|
||||
|
||||
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
||||
|
||||
TEST_CASE("JsonVariant::set() when there is enough memory") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("string literal") {
|
||||
bool result = variant.set("hello\0world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
CHECK(variant ==
|
||||
"hello"_s); // linked string cannot contain '\0' at the moment
|
||||
CHECK(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(static_cast<const char*>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("(const char*)0") {
|
||||
bool result = variant.set(static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.isNull());
|
||||
REQUIRE(variant.as<const char*>() == nullptr);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(str);
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("char* (tiny string optimization)") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "abc");
|
||||
bool result = variant.set(str);
|
||||
strcpy(str, "def");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "abc"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("(char*)0") {
|
||||
bool result = variant.set(static_cast<char*>(0));
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.isNull());
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("unsigned char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(reinterpret_cast<unsigned char*>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("signed char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(reinterpret_cast<signed char*>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("VLA") {
|
||||
size_t n = 16;
|
||||
char str[n];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(str);
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("std::string") {
|
||||
std::string str = "hello\0world"_s;
|
||||
bool result = variant.set(str);
|
||||
str.replace(0, 5, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello\0world"_s); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello?world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("static JsonString") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(JsonString(str, true));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "world"); // stores by pointer
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("non-static JsonString") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(JsonString(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Allocate(sizeofString("hello")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("enum") {
|
||||
ErrorCode code = ERROR_10;
|
||||
|
||||
bool result = variant.set(code);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.is<int>() == true);
|
||||
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(-2147483649LL));
|
||||
doc.shrinkToFit();
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.is<int64_t>() == true);
|
||||
REQUIRE(variant.as<int64_t>() == -2147483649LL);
|
||||
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\"}");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::set() with not enough memory") {
|
||||
JsonDocument doc(FailingAllocator::instance());
|
||||
|
||||
JsonVariant v = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("std::string") {
|
||||
bool result = v.set("hello world!!"_s);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("Serialized<std::string>") {
|
||||
bool result = v.set(serialized("hello world!!"_s));
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char s[] = "hello world!!";
|
||||
bool result = v.set(s);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("float") {
|
||||
bool result = v.set(1.2f);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(v.is<float>());
|
||||
}
|
||||
|
||||
SECTION("double") {
|
||||
bool result = v.set(1.2);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("int32_t") {
|
||||
bool result = v.set(-42);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(v.is<int32_t>());
|
||||
}
|
||||
|
||||
SECTION("int64_t") {
|
||||
bool result = v.set(-2147483649LL);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("uint32_t") {
|
||||
bool result = v.set(42);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(v.is<uint32_t>());
|
||||
}
|
||||
|
||||
SECTION("uint64_t") {
|
||||
bool result = v.set(4294967296U);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::set() releases the previous value") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
doc["hello"] = "world"_s;
|
||||
spy.clearLog();
|
||||
|
||||
JsonVariant v = doc["hello"];
|
||||
|
||||
SECTION("int") {
|
||||
v.set(42);
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("bool") {
|
||||
v.set(false);
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
v.set("hello");
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("float") {
|
||||
v.set(1.2);
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("Serialized<const char*>") {
|
||||
v.set(serialized("[]"));
|
||||
REQUIRE(spy.log() == AllocatorLog{
|
||||
Deallocate(sizeofString("world")),
|
||||
Allocate(sizeofString("[]")),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant::set() reuses extension slot") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
variant.set(1.2);
|
||||
doc.shrinkToFit();
|
||||
spy.clearLog();
|
||||
|
||||
SECTION("double") {
|
||||
bool result = variant.set(3.4);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("int64_t") {
|
||||
bool result = variant.set(-2147483649LL);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("uint64_t") {
|
||||
bool result = variant.set(4294967296U);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
}
|
||||
36
ArduinoJson/extras/tests/JsonVariant/size.cpp
Normal file
36
ArduinoJson/extras/tests/JsonVariant/size.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonVariant::size()") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("unbound reference") {
|
||||
JsonVariant unbound;
|
||||
|
||||
CHECK(unbound.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("int") {
|
||||
variant.set(42);
|
||||
|
||||
CHECK(variant.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("string") {
|
||||
variant.set("hello");
|
||||
|
||||
CHECK(variant.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("object") {
|
||||
variant["a"] = 1;
|
||||
variant["b"] = 2;
|
||||
|
||||
CHECK(variant.size() == 2);
|
||||
}
|
||||
}
|
||||
138
ArduinoJson/extras/tests/JsonVariant/stl_containers.cpp
Normal file
138
ArduinoJson/extras/tests/JsonVariant/stl_containers.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ArduinoJson {
|
||||
template <typename T>
|
||||
struct Converter<std::vector<T>> {
|
||||
static void toJson(const std::vector<T>& src, JsonVariant dst) {
|
||||
JsonArray array = dst.to<JsonArray>();
|
||||
for (T item : src)
|
||||
array.add(item);
|
||||
}
|
||||
|
||||
static std::vector<T> fromJson(JsonVariantConst src) {
|
||||
std::vector<T> dst;
|
||||
for (T item : src.as<JsonArrayConst>())
|
||||
dst.push_back(item);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
JsonArrayConst array = src;
|
||||
bool result = array;
|
||||
for (JsonVariantConst item : array)
|
||||
result &= item.is<T>();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct Converter<std::array<T, N>> {
|
||||
static void toJson(const std::array<T, N>& src, JsonVariant dst) {
|
||||
JsonArray array = dst.to<JsonArray>();
|
||||
for (T item : src)
|
||||
array.add(item);
|
||||
}
|
||||
|
||||
static std::array<T, N> fromJson(JsonVariantConst src) {
|
||||
std::array<T, N> dst;
|
||||
dst.fill(0);
|
||||
size_t idx = 0;
|
||||
for (T item : src.as<JsonArrayConst>())
|
||||
dst[idx++] = item;
|
||||
return dst;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
JsonArrayConst array = src;
|
||||
bool result = array;
|
||||
size_t size = 0;
|
||||
for (JsonVariantConst item : array) {
|
||||
result &= item.is<T>();
|
||||
size++;
|
||||
}
|
||||
return result && size == N;
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
||||
|
||||
TEST_CASE("vector<int>") {
|
||||
SECTION("toJson") {
|
||||
std::vector<int> v = {1, 2};
|
||||
|
||||
JsonDocument doc;
|
||||
doc.set(v);
|
||||
REQUIRE(doc.as<std::string>() == "[1,2]");
|
||||
}
|
||||
|
||||
SECTION("fromJson") {
|
||||
JsonDocument doc;
|
||||
doc.add(1);
|
||||
doc.add(2);
|
||||
|
||||
auto v = doc.as<std::vector<int>>();
|
||||
REQUIRE(v.size() == 2);
|
||||
CHECK(v[0] == 1);
|
||||
CHECK(v[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("checkJson") {
|
||||
JsonDocument doc;
|
||||
CHECK(doc.is<std::vector<int>>() == false);
|
||||
|
||||
doc.add(1);
|
||||
doc.add(2);
|
||||
CHECK(doc.is<std::vector<int>>() == true);
|
||||
|
||||
doc.add("foo");
|
||||
CHECK(doc.is<std::vector<int>>() == false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("array<int, 2>") {
|
||||
using array_type = std::array<int, 2>;
|
||||
|
||||
SECTION("toJson") {
|
||||
array_type v;
|
||||
v[0] = 1;
|
||||
v[1] = 2;
|
||||
|
||||
JsonDocument doc;
|
||||
doc.set(v);
|
||||
REQUIRE(doc.as<std::string>() == "[1,2]");
|
||||
}
|
||||
|
||||
SECTION("fromJson") {
|
||||
JsonDocument doc;
|
||||
doc.add(1);
|
||||
doc.add(2);
|
||||
|
||||
auto v = doc.as<array_type>();
|
||||
REQUIRE(v.size() == 2);
|
||||
CHECK(v[0] == 1);
|
||||
CHECK(v[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("checkJson") {
|
||||
JsonDocument doc;
|
||||
CHECK(doc.is<array_type>() == false);
|
||||
|
||||
doc.add(1);
|
||||
CHECK(doc.is<array_type>() == false);
|
||||
|
||||
doc.add(2);
|
||||
CHECK(doc.is<array_type>() == true);
|
||||
|
||||
doc[0] = "foo";
|
||||
CHECK(doc.is<array_type>() == false);
|
||||
}
|
||||
}
|
||||
159
ArduinoJson/extras/tests/JsonVariant/subscript.cpp
Normal file
159
ArduinoJson/extras/tests/JsonVariant/subscript.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("JsonVariant::operator[]") {
|
||||
JsonDocument doc;
|
||||
JsonVariant var = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("The JsonVariant is null") {
|
||||
REQUIRE(0 == var.size());
|
||||
REQUIRE(var["0"].isNull());
|
||||
REQUIRE(var[0].isNull());
|
||||
}
|
||||
|
||||
SECTION("The JsonVariant is a string") {
|
||||
var.set("hello world");
|
||||
REQUIRE(0 == var.size());
|
||||
REQUIRE(var["0"].isNull());
|
||||
REQUIRE(var[0].isNull());
|
||||
}
|
||||
|
||||
SECTION("The JsonVariant is a JsonArray") {
|
||||
JsonArray array = var.to<JsonArray>();
|
||||
|
||||
SECTION("get value") {
|
||||
array.add("element at index 0");
|
||||
array.add("element at index 1");
|
||||
|
||||
REQUIRE(2 == var.size());
|
||||
var[0].as<std::string>();
|
||||
// REQUIRE("element at index 0"_s == );
|
||||
REQUIRE("element at index 1"_s == var[1]);
|
||||
REQUIRE("element at index 0"_s ==
|
||||
var[static_cast<unsigned char>(0)]); // issue #381
|
||||
REQUIRE(var[666].isNull());
|
||||
REQUIRE(var[3].isNull());
|
||||
REQUIRE(var["0"].isNull());
|
||||
}
|
||||
|
||||
SECTION("set value") {
|
||||
array.add("hello");
|
||||
|
||||
var[1] = "world";
|
||||
|
||||
REQUIRE(var.size() == 2);
|
||||
REQUIRE("world"_s == var[1]);
|
||||
}
|
||||
|
||||
SECTION("set value in a nested object") {
|
||||
array.add<JsonObject>();
|
||||
|
||||
var[0]["hello"] = "world";
|
||||
|
||||
REQUIRE(1 == var.size());
|
||||
REQUIRE(1 == var[0].size());
|
||||
REQUIRE("world"_s == var[0]["hello"]);
|
||||
}
|
||||
|
||||
SECTION("variant[0] when variant contains an integer") {
|
||||
var.set(123);
|
||||
|
||||
var[0] = 345; // no-op
|
||||
|
||||
REQUIRE(var.is<int>());
|
||||
REQUIRE(var.as<int>() == 123);
|
||||
}
|
||||
|
||||
SECTION("use JsonVariant as index") {
|
||||
array.add("A");
|
||||
array.add("B");
|
||||
array.add(1);
|
||||
|
||||
REQUIRE(var[var[2]] == "B");
|
||||
REQUIRE(var[var[3]].isNull());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("The JsonVariant is a JsonObject") {
|
||||
JsonObject object = var.to<JsonObject>();
|
||||
|
||||
SECTION("get value") {
|
||||
object["a"] = "element at key \"a\"";
|
||||
object["b"] = "element at key \"b\"";
|
||||
|
||||
REQUIRE(2 == var.size());
|
||||
REQUIRE("element at key \"a\""_s == var["a"]);
|
||||
REQUIRE("element at key \"b\""_s == var["b"]);
|
||||
REQUIRE(var["c"].isNull());
|
||||
REQUIRE(var[0].isNull());
|
||||
}
|
||||
|
||||
SECTION("set value, key is a const char*") {
|
||||
var["hello"] = "world";
|
||||
|
||||
REQUIRE(1 == var.size());
|
||||
REQUIRE("world"_s == var["hello"]);
|
||||
}
|
||||
|
||||
SECTION("set value, key is a char[]") {
|
||||
char key[] = "hello";
|
||||
var[key] = "world";
|
||||
key[0] = '!'; // make sure the key is duplicated
|
||||
|
||||
REQUIRE(1 == var.size());
|
||||
REQUIRE("world"_s == var["hello"]);
|
||||
}
|
||||
|
||||
SECTION("var[key].to<JsonArray>()") {
|
||||
JsonArray arr = var["hello"].to<JsonArray>();
|
||||
REQUIRE(arr.isNull() == false);
|
||||
}
|
||||
|
||||
SECTION("use JsonVariant as key") {
|
||||
object["a"] = "A";
|
||||
object["ab"] = "AB";
|
||||
object["ab\0c"_s] = "ABC";
|
||||
object["key1"] = "a";
|
||||
object["key2"] = "ab";
|
||||
object["key3"] = "ab\0c"_s;
|
||||
object["key4"] = "foo";
|
||||
|
||||
REQUIRE(var[var["key1"]] == "A");
|
||||
REQUIRE(var[var["key2"]] == "AB");
|
||||
REQUIRE(var[var["key3"]] == "ABC");
|
||||
REQUIRE(var[var["key4"]].isNull());
|
||||
REQUIRE(var[var["key5"]].isNull());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
|
||||
!defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
|
||||
SECTION("key is a VLA") {
|
||||
size_t i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
JsonVariant variant = doc.as<JsonVariant>();
|
||||
|
||||
REQUIRE("world"_s == variant[vla]);
|
||||
}
|
||||
|
||||
SECTION("key is a VLA, const JsonVariant") {
|
||||
size_t i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
const JsonVariant variant = doc.as<JsonVariant>();
|
||||
|
||||
REQUIRE("world"_s == variant[vla]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
168
ArduinoJson/extras/tests/JsonVariant/types.cpp
Normal file
168
ArduinoJson/extras/tests/JsonVariant/types.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
#include <limits>
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Literals.hpp"
|
||||
|
||||
template <typename T>
|
||||
void checkReference(T& expected) {
|
||||
JsonVariant variant = expected;
|
||||
REQUIRE(expected == variant.as<T&>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void checkNumericType() {
|
||||
JsonDocument docMin, docMax;
|
||||
JsonVariant variantMin = docMin.to<JsonVariant>();
|
||||
JsonVariant variantMax = docMax.to<JsonVariant>();
|
||||
|
||||
T min = std::numeric_limits<T>::min();
|
||||
T max = std::numeric_limits<T>::max();
|
||||
|
||||
variantMin.set(min);
|
||||
variantMax.set(max);
|
||||
|
||||
REQUIRE(min == variantMin.as<T>());
|
||||
REQUIRE(max == variantMax.as<T>());
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant set()/get()") {
|
||||
SpyingAllocator spy;
|
||||
JsonDocument doc(&spy);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
SECTION("SizeOfJsonInteger") {
|
||||
REQUIRE(8 == sizeof(JsonInteger));
|
||||
}
|
||||
#endif
|
||||
|
||||
// /!\ Most test were moved to `JsonVariant/set.cpp`
|
||||
// TODO: move the remaining tests too
|
||||
|
||||
SECTION("False") {
|
||||
variant.set(false);
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("True") {
|
||||
variant.set(true);
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(spy.log() == AllocatorLog{});
|
||||
}
|
||||
|
||||
SECTION("Double") {
|
||||
checkNumericType<double>();
|
||||
}
|
||||
SECTION("Float") {
|
||||
checkNumericType<float>();
|
||||
}
|
||||
SECTION("SChar") {
|
||||
checkNumericType<signed char>();
|
||||
}
|
||||
SECTION("SInt") {
|
||||
checkNumericType<signed int>();
|
||||
}
|
||||
SECTION("SLong") {
|
||||
checkNumericType<signed long>();
|
||||
}
|
||||
SECTION("SShort") {
|
||||
checkNumericType<signed short>();
|
||||
}
|
||||
SECTION("UChar") {
|
||||
checkNumericType<unsigned char>();
|
||||
}
|
||||
SECTION("UInt") {
|
||||
checkNumericType<unsigned int>();
|
||||
}
|
||||
SECTION("ULong") {
|
||||
checkNumericType<unsigned long>();
|
||||
}
|
||||
SECTION("UShort") {
|
||||
checkNumericType<unsigned short>();
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
SECTION("LongLong") {
|
||||
checkNumericType<unsigned long long>();
|
||||
}
|
||||
SECTION("ULongLong") {
|
||||
checkNumericType<unsigned long long>();
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("Int8") {
|
||||
checkNumericType<int8_t>();
|
||||
}
|
||||
SECTION("Uint8") {
|
||||
checkNumericType<uint8_t>();
|
||||
}
|
||||
SECTION("Int16") {
|
||||
checkNumericType<int16_t>();
|
||||
}
|
||||
SECTION("Uint16") {
|
||||
checkNumericType<uint16_t>();
|
||||
}
|
||||
SECTION("Int32") {
|
||||
checkNumericType<int32_t>();
|
||||
}
|
||||
SECTION("Uint32") {
|
||||
checkNumericType<uint32_t>();
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
SECTION("Int64") {
|
||||
checkNumericType<int64_t>();
|
||||
}
|
||||
SECTION("Uint64") {
|
||||
checkNumericType<uint64_t>();
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("CanStoreObject") {
|
||||
JsonDocument doc2;
|
||||
JsonObject object = doc2.to<JsonObject>();
|
||||
|
||||
variant.set(object);
|
||||
REQUIRE(variant.is<JsonObject>());
|
||||
REQUIRE(variant.as<JsonObject>() == object);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("volatile") {
|
||||
JsonDocument doc;
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("volatile bool") { // issue #2029
|
||||
volatile bool f = true;
|
||||
variant.set(f);
|
||||
CHECK(variant.is<bool>() == true);
|
||||
CHECK(variant.as<bool>() == true);
|
||||
}
|
||||
|
||||
SECTION("volatile int") {
|
||||
volatile int f = 42;
|
||||
variant.set(f);
|
||||
CHECK(variant.is<int>() == true);
|
||||
CHECK(variant.as<int>() == 42);
|
||||
}
|
||||
|
||||
SECTION("volatile float") { // issue #1557
|
||||
volatile float f = 3.14f;
|
||||
variant.set(f);
|
||||
CHECK(variant.is<float>() == true);
|
||||
CHECK(variant.as<float>() == 3.14f);
|
||||
}
|
||||
|
||||
SECTION("volatile double") {
|
||||
volatile double f = 3.14;
|
||||
variant.set(f);
|
||||
CHECK(variant.is<double>() == true);
|
||||
CHECK(variant.as<double>() == 3.14);
|
||||
}
|
||||
}
|
||||
80
ArduinoJson/extras/tests/JsonVariant/unbound.cpp
Normal file
80
ArduinoJson/extras/tests/JsonVariant/unbound.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("Unbound JsonVariant") {
|
||||
JsonVariant variant;
|
||||
|
||||
SECTION("as<T>()") {
|
||||
CHECK(variant.as<bool>() == false);
|
||||
CHECK(variant.as<int>() == 0);
|
||||
CHECK(variant.as<float>() == 0.0f);
|
||||
CHECK(variant.as<const char*>() == 0);
|
||||
CHECK(variant.as<std::string>() == "null");
|
||||
CHECK(variant.as<JsonVariant>().isNull());
|
||||
CHECK(variant.as<JsonVariantConst>().isNull());
|
||||
CHECK(variant.as<JsonArray>().isNull());
|
||||
CHECK(variant.as<JsonArrayConst>().isNull());
|
||||
CHECK(variant.as<JsonObject>().isNull());
|
||||
CHECK(variant.as<JsonObjectConst>().isNull());
|
||||
CHECK(variant.as<JsonString>().isNull());
|
||||
CHECK(variant.as<MsgPackBinary>().data() == nullptr);
|
||||
CHECK(variant.as<MsgPackBinary>().size() == 0);
|
||||
CHECK(variant.as<MsgPackExtension>().data() == nullptr);
|
||||
CHECK(variant.as<MsgPackExtension>().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("is<T>()") {
|
||||
CHECK_FALSE(variant.is<bool>());
|
||||
CHECK_FALSE(variant.is<int>());
|
||||
CHECK_FALSE(variant.is<float>());
|
||||
CHECK_FALSE(variant.is<const char*>());
|
||||
CHECK_FALSE(variant.is<std::string>());
|
||||
CHECK_FALSE(variant.is<JsonVariant>());
|
||||
CHECK_FALSE(variant.is<JsonVariantConst>());
|
||||
CHECK_FALSE(variant.is<JsonArray>());
|
||||
CHECK_FALSE(variant.is<JsonArrayConst>());
|
||||
CHECK_FALSE(variant.is<JsonObject>());
|
||||
CHECK_FALSE(variant.is<JsonObjectConst>());
|
||||
CHECK_FALSE(variant.is<JsonString>());
|
||||
}
|
||||
|
||||
SECTION("set()") {
|
||||
CHECK_FALSE(variant.set("42"));
|
||||
CHECK_FALSE(variant.set(42.0));
|
||||
CHECK_FALSE(variant.set(42L));
|
||||
CHECK_FALSE(variant.set(42U));
|
||||
CHECK_FALSE(variant.set(serialized("42")));
|
||||
CHECK_FALSE(variant.set(serialized("42"_s)));
|
||||
CHECK_FALSE(variant.set(true));
|
||||
CHECK_FALSE(variant.set(MsgPackBinary("hello", 5)));
|
||||
CHECK_FALSE(variant.set(MsgPackExtension(1, "hello", 5)));
|
||||
}
|
||||
|
||||
SECTION("add()") {
|
||||
CHECK_FALSE(variant.add("42"));
|
||||
CHECK_FALSE(variant.add(42.0));
|
||||
CHECK_FALSE(variant.add(42L));
|
||||
CHECK_FALSE(variant.add(42U));
|
||||
CHECK_FALSE(variant.add(serialized("42")));
|
||||
CHECK_FALSE(variant.add(true));
|
||||
}
|
||||
|
||||
SECTION("operator[]") {
|
||||
CHECK(variant[0].isNull());
|
||||
CHECK(variant["key"].isNull());
|
||||
CHECK_FALSE(variant[0].set(1));
|
||||
CHECK_FALSE(variant["key"].set(1));
|
||||
CHECK_FALSE(variant["key"_s].set(1));
|
||||
}
|
||||
|
||||
SECTION("remove()") {
|
||||
variant.remove(0);
|
||||
variant.remove("hello");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user