added library json

This commit is contained in:
hidaba
2023-05-14 11:02:22 +02:00
parent c60123ce97
commit ab8de582d8
421 changed files with 51080 additions and 6 deletions

View File

@ -0,0 +1,29 @@
# ArduinoJson - https://arduinojson.org
# Copyright © 2014-2023, Benoit BLANCHON
# MIT License
add_executable(MiscTests
arithmeticCompare.cpp
conflicts.cpp
FloatParts.cpp
JsonString.cpp
NoArduinoHeader.cpp
printable.cpp
Readers.cpp
StringAdapters.cpp
StringWriter.cpp
TypeTraits.cpp
unsigned_char.cpp
Utf16.cpp
Utf8.cpp
version.cpp
)
set_target_properties(MiscTests PROPERTIES UNITY_BUILD OFF)
add_test(Misc MiscTests)
set_tests_properties(Misc
PROPERTIES
LABELS "Catch"
)

View File

@ -0,0 +1,44 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Numbers/FloatParts.hpp>
#include <catch.hpp>
using namespace ArduinoJson::detail;
TEST_CASE("FloatParts<double>") {
SECTION("1.7976931348623157E+308") {
FloatParts<double> parts(1.7976931348623157E+308);
REQUIRE(parts.integral == 1);
REQUIRE(parts.decimal == 797693135);
REQUIRE(parts.decimalPlaces == 9);
REQUIRE(parts.exponent == 308);
}
SECTION("4.94065645841247e-324") {
FloatParts<double> parts(4.94065645841247e-324);
REQUIRE(parts.integral == 4);
REQUIRE(parts.decimal == 940656458);
REQUIRE(parts.decimalPlaces == 9);
REQUIRE(parts.exponent == -324);
}
}
TEST_CASE("FloatParts<float>") {
SECTION("3.4E+38") {
FloatParts<float> parts(3.4E+38f);
REQUIRE(parts.integral == 3);
REQUIRE(parts.decimal == 4);
REQUIRE(parts.decimalPlaces == 1);
REQUIRE(parts.exponent == 38);
}
SECTION("1.17549435e38") {
FloatParts<float> parts(1.17549435e-38f);
REQUIRE(parts.integral == 1);
REQUIRE(parts.decimal == 175494);
REQUIRE(parts.decimalPlaces == 6);
REQUIRE(parts.exponent == -38);
}
}

View File

@ -0,0 +1,103 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include <sstream>
TEST_CASE("JsonString") {
SECTION("Default constructor creates a null JsonString") {
JsonString s;
CHECK(s.isNull() == true);
CHECK(s.c_str() == 0);
CHECK(s.isLinked() == true);
CHECK(s == JsonString());
CHECK(s != "");
}
SECTION("Null converts to false") {
JsonString s;
CHECK(bool(s) == false);
}
SECTION("Empty string converts to true") {
JsonString s("");
CHECK(bool(s) == true);
}
SECTION("Non-empty string converts to true") {
JsonString s("");
CHECK(bool(s) == true);
}
SECTION("Null strings equals each others") {
JsonString a, b;
CHECK(a == b);
CHECK_FALSE(a != b);
}
SECTION("Null and empty strings differ") {
JsonString a, b("");
CHECK_FALSE(a == b);
CHECK(a != b);
CHECK_FALSE(b == a);
CHECK(b != a);
}
SECTION("Null and non-empty strings differ") {
JsonString a, b("hello");
CHECK_FALSE(a == b);
CHECK(a != b);
CHECK_FALSE(b == a);
CHECK(b != a);
}
SECTION("Compare different strings") {
JsonString a("hello"), b("world");
CHECK_FALSE(a == b);
CHECK(a != b);
}
SECTION("Compare identical by pointer") {
JsonString a("hello"), b("hello");
CHECK(a == b);
CHECK_FALSE(a != b);
}
SECTION("Compare identical by value") {
char s1[] = "hello";
char s2[] = "hello";
JsonString a(s1), b(s2);
CHECK(a == b);
CHECK_FALSE(a != b);
}
SECTION("std::stream") {
std::stringstream ss;
ss << JsonString("hello world!");
CHECK(ss.str() == "hello world!");
}
SECTION("Construct with a size") {
JsonString s("hello world", 5);
CHECK(s.size() == 5);
CHECK(s.isLinked() == true);
CHECK(s == "hello");
CHECK(s != "hello world");
}
}

View File

@ -0,0 +1,20 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#define ARDUINO 1
#define ARDUINOJSON_ENABLE_PROGMEM 0
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("Arduino.h") {
#ifdef ARDUINO_H_INCLUDED
FAIL("Arduino.h should not be included");
#else
INFO("Arduino.h not included");
#endif
}

View File

@ -0,0 +1,227 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <Arduino.h>
#include <ArduinoJson.hpp>
#include <catch.hpp>
#include <sstream>
using namespace ArduinoJson::detail;
TEST_CASE("Reader<std::istringstream>") {
SECTION("read()") {
std::istringstream src("\x01\xFF");
Reader<std::istringstream> reader(src);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
std::istringstream src("ABC");
Reader<std::istringstream> reader(src);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
std::istringstream src("ABCDEF");
Reader<std::istringstream> reader(src);
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("BoundedReader<const char*>") {
SECTION("read") {
BoundedReader<const char*> reader("\x01\xFF", 2);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
BoundedReader<const char*> reader("ABCD", 3);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
BoundedReader<const char*> reader("ABCDEF", 6);
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("Reader<const char*>") {
SECTION("read()") {
Reader<const char*> reader("\x01\xFF\x00\x12");
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == 0);
REQUIRE(reader.read() == 0x12);
}
SECTION("readBytes() all at once") {
Reader<const char*> reader("ABCD");
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 3) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
Reader<const char*> reader("ABCDEF");
char buffer[8] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 2) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
TEST_CASE("IteratorReader") {
SECTION("read()") {
std::string src("\x01\xFF");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
std::string src("ABC");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
std::string src("ABCDEF");
IteratorReader<std::string::const_iterator> reader(src.begin(), src.end());
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}
class StreamStub : public Stream {
public:
StreamStub(const char* s) : stream_(s) {}
int read() {
return stream_.get();
}
size_t readBytes(char* buffer, size_t length) {
stream_.read(buffer, static_cast<std::streamsize>(length));
return static_cast<size_t>(stream_.gcount());
}
private:
std::istringstream stream_;
};
TEST_CASE("Reader<Stream>") {
SECTION("read()") {
StreamStub src("\x01\xFF");
Reader<StreamStub> reader(src);
REQUIRE(reader.read() == 0x01);
REQUIRE(reader.read() == 0xFF);
REQUIRE(reader.read() == -1);
}
SECTION("readBytes() all at once") {
StreamStub src("ABC");
Reader<StreamStub> reader(src);
char buffer[8] = "abcd";
REQUIRE(reader.readBytes(buffer, 4) == 3);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'd');
}
SECTION("readBytes() in two parts") {
StreamStub src("ABCDEF");
Reader<StreamStub> reader(src);
char buffer[12] = "abcdefg";
REQUIRE(reader.readBytes(buffer, 4) == 4);
REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
REQUIRE(buffer[0] == 'A');
REQUIRE(buffer[1] == 'B');
REQUIRE(buffer[2] == 'C');
REQUIRE(buffer[3] == 'D');
REQUIRE(buffer[4] == 'E');
REQUIRE(buffer[5] == 'F');
REQUIRE(buffer[6] == 'g');
}
}

View File

@ -0,0 +1,190 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <Arduino.h>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <catch.hpp>
#include "custom_string.hpp"
#include "weird_strcmp.hpp"
using namespace ArduinoJson::detail;
TEST_CASE("ZeroTerminatedRamString") {
SECTION("null") {
ZeroTerminatedRamString s = adaptString(static_cast<const char*>(0));
CHECK(s.isNull() == true);
CHECK(s.size() == 0);
}
SECTION("non-null") {
ZeroTerminatedRamString s = adaptString("bravo");
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
}
TEST_CASE("SizedRamString") {
SECTION("null") {
SizedRamString s = adaptString(static_cast<const char*>(0), 10);
CHECK(s.isNull() == true);
}
SECTION("non-null") {
SizedRamString s = adaptString("bravo", 5);
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
}
TEST_CASE("FlashString") {
SECTION("null") {
FlashString s = adaptString(static_cast<const __FlashStringHelper*>(0));
CHECK(s.isNull() == true);
CHECK(s.size() == 0);
}
SECTION("non-null") {
FlashString s = adaptString(F("bravo"));
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
}
TEST_CASE("std::string") {
std::string orig("bravo");
SizedRamString s = adaptString(orig);
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
TEST_CASE("Arduino String") {
::String orig("bravo");
SizedRamString s = adaptString(orig);
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
TEST_CASE("custom_string") {
custom_string orig("bravo");
SizedRamString s = adaptString(orig);
CHECK(s.isNull() == false);
CHECK(s.size() == 5);
}
struct EmptyStruct {};
TEST_CASE("IsString<T>") {
CHECK(IsString<std::string>::value == true);
CHECK(IsString<std::basic_string<wchar_t>>::value == false);
CHECK(IsString<custom_string>::value == true);
CHECK(IsString<const __FlashStringHelper*>::value == true);
CHECK(IsString<const char*>::value == true);
CHECK(IsString<const char[8]>::value == true);
CHECK(IsString<::String>::value == true);
CHECK(IsString<::StringSumHelper>::value == true);
CHECK(IsString<const EmptyStruct*>::value == false);
}
TEST_CASE("stringCompare") {
SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
CHECK(stringCompare(adaptString("bravo"), adaptString("alpha")) > 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo")) == 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("charlie")) < 0);
}
SECTION("ZeroTerminatedRamString vs SizedRamString") {
CHECK(stringCompare(adaptString("bravo"), adaptString("alpha?", 5)) > 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 4)) > 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 5)) == 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 6)) < 0);
CHECK(stringCompare(adaptString("bravo"), adaptString("charlie?", 7)) < 0);
}
SECTION("SizedRamString vs SizedRamString") {
// clang-format off
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("alpha?", 5)) > 0);
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo?", 5)) == 0);
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("charlie?", 7)) < 0);
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 4)) > 0);
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 5)) == 0);
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 6)) < 0);
// clang-format on
}
SECTION("FlashString vs FlashString") {
// clang-format off
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("alpha"))) > 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("bravo"))) == 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("charlie"))) < 0);
// clang-format on
}
SECTION("FlashString vs SizedRamString") {
// clang-format off
CHECK(stringCompare(adaptString(F("bravo")), adaptString("alpha?", 5)) > 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo?", 5)) == 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString("charlie?", 7)) < 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 4)) > 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 5)) == 0);
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 6)) < 0);
// clang-format on
}
SECTION("ZeroTerminatedRamString vs FlashString") {
// clang-format off
CHECK(stringCompare(adaptString("bravo"), adaptString(F("alpha?"), 5)) > 0);
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 4)) > 0);
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 5)) == 0);
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 6)) < 0);
CHECK(stringCompare(adaptString("bravo"), adaptString(F("charlie?"), 7)) < 0);
// clang-format on
}
}
TEST_CASE("stringEquals()") {
SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
CHECK(stringEquals(adaptString("bravo"), adaptString("brav")) == false);
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo")) == true);
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!")) == false);
}
SECTION("ZeroTerminatedRamString vs SizedRamString") {
// clang-format off
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 4)) == false);
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 5)) == true);
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 6)) == false);
// clang-format on
}
SECTION("FlashString vs SizedRamString") {
// clang-format off
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 4)) == false);
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 5)) == true);
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 6)) == false);
// clang-format on
}
SECTION("SizedRamString vs SizedRamString") {
// clang-format off
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 4)) == false);
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 5)) == true);
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 6)) == false);
// clang-format on
}
}

View File

@ -0,0 +1,156 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <Arduino.h>
#define ARDUINOJSON_STRING_BUFFER_SIZE 5
#include <ArduinoJson.h>
#include <catch.hpp>
#include "custom_string.hpp"
using namespace ArduinoJson::detail;
template <typename StringWriter>
static size_t print(StringWriter& writer, const char* s) {
return writer.write(reinterpret_cast<const uint8_t*>(s), strlen(s));
}
template <typename StringWriter>
static size_t print(StringWriter& writer, char c) {
return writer.write(static_cast<uint8_t>(c));
}
template <typename StringWriter, typename String>
void common_tests(StringWriter& writer, const String& output) {
SECTION("InitialState") {
REQUIRE(std::string("") == output);
}
SECTION("EmptyString") {
REQUIRE(0 == print(writer, ""));
REQUIRE(std::string("") == output);
}
SECTION("OneString") {
REQUIRE(4 == print(writer, "ABCD"));
REQUIRE(std::string("ABCD") == output);
}
SECTION("TwoStrings") {
REQUIRE(4 == print(writer, "ABCD"));
REQUIRE(4 == print(writer, "EFGH"));
REQUIRE(std::string("ABCDEFGH") == output);
}
}
TEST_CASE("StaticStringWriter") {
char output[20] = {0};
StaticStringWriter writer(output, sizeof(output));
common_tests(writer, static_cast<const char*>(output));
SECTION("OverCapacity") {
REQUIRE(20 == print(writer, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
REQUIRE(0 == print(writer, "ABC"));
REQUIRE(0 == print(writer, 'D'));
REQUIRE("ABCDEFGHIJKLMNOPQRST" == std::string(output, 20));
}
}
TEST_CASE("Writer<std::string>") {
std::string output;
Writer<std::string> writer(output);
common_tests(writer, output);
}
TEST_CASE("Writer<String>") {
::String output;
Writer<::String> writer(output);
SECTION("write(char)") {
SECTION("writes to temporary buffer") {
// accumulate in buffer
writer.write('a');
writer.write('b');
writer.write('c');
writer.write('d');
REQUIRE(output == "");
// flush when full
writer.write('e');
REQUIRE(output == "abcd");
// flush on destruction
writer.write('f');
writer.~Writer();
REQUIRE(output == "abcdef");
}
SECTION("returns 1 on success") {
for (int i = 0; i < ARDUINOJSON_STRING_BUFFER_SIZE; i++) {
REQUIRE(writer.write('x') == 1);
}
}
SECTION("returns 0 on error") {
output.limitCapacityTo(1);
REQUIRE(writer.write('a') == 1);
REQUIRE(writer.write('b') == 1);
REQUIRE(writer.write('c') == 1);
REQUIRE(writer.write('d') == 1);
REQUIRE(writer.write('e') == 0);
REQUIRE(writer.write('f') == 0);
}
}
SECTION("write(char*, size_t)") {
SECTION("empty string") {
REQUIRE(0 == print(writer, ""));
writer.flush();
REQUIRE(output == "");
}
SECTION("writes to temporary buffer") {
// accumulate in buffer
print(writer, "abc");
REQUIRE(output == "");
// flush when full, and continue to accumulate
print(writer, "de");
REQUIRE(output == "abcd");
// flush on destruction
writer.~Writer();
REQUIRE(output == "abcde");
}
}
}
TEST_CASE("Writer<custom_string>") {
custom_string output;
Writer<custom_string> writer(output);
REQUIRE(4 == print(writer, "ABCD"));
REQUIRE("ABCD" == output);
}
TEST_CASE("serializeJson(doc, String)") {
StaticJsonDocument<1024> doc;
doc["hello"] = "world";
::String output;
SECTION("sufficient capacity") {
serializeJson(doc, output);
REQUIRE(output == "{\"hello\":\"world\"}");
}
SECTION("unsufficient capacity") { // issue #1561
output.limitCapacityTo(10);
serializeJson(doc, output);
REQUIRE(output == "{\"hello\"");
}
}

View File

@ -0,0 +1,216 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include <sstream>
using namespace ArduinoJson::detail;
class EmptyClass {};
enum EmptyEnum {};
TEST_CASE("Polyfills/type_traits") {
SECTION("is_base_of") {
REQUIRE_FALSE(
static_cast<bool>(is_base_of<std::istream, std::ostringstream>::value));
REQUIRE(
static_cast<bool>(is_base_of<std::istream, std::istringstream>::value));
}
SECTION("is_array") {
REQUIRE_FALSE(is_array<const char*>::value);
REQUIRE(is_array<const char[]>::value);
REQUIRE(is_array<const char[10]>::value);
}
SECTION("is_const") {
CHECK(is_const<char>::value == false);
CHECK(is_const<const char>::value == true);
}
SECTION("is_integral") {
CHECK(is_integral<double>::value == false);
CHECK(is_integral<float>::value == false);
CHECK(is_integral<const double>::value == false);
CHECK(is_integral<const float>::value == false);
CHECK(is_integral<volatile double>::value == false);
CHECK(is_integral<volatile float>::value == false);
CHECK(is_integral<const volatile double>::value == false);
CHECK(is_integral<const volatile float>::value == false);
CHECK(is_integral<bool>::value == true);
CHECK(is_integral<char>::value == true);
CHECK(is_integral<signed char>::value == true);
CHECK(is_integral<signed int>::value == true);
CHECK(is_integral<signed long>::value == true);
CHECK(is_integral<signed short>::value == true);
CHECK(is_integral<unsigned char>::value == true);
CHECK(is_integral<unsigned int>::value == true);
CHECK(is_integral<unsigned long>::value == true);
CHECK(is_integral<unsigned short>::value == true);
CHECK(is_integral<const bool>::value == true);
CHECK(is_integral<const char>::value == true);
CHECK(is_integral<const signed char>::value == true);
CHECK(is_integral<const signed int>::value == true);
CHECK(is_integral<const signed long>::value == true);
CHECK(is_integral<const signed short>::value == true);
CHECK(is_integral<const unsigned char>::value == true);
CHECK(is_integral<const unsigned int>::value == true);
CHECK(is_integral<const unsigned long>::value == true);
CHECK(is_integral<const unsigned short>::value == true);
CHECK(is_integral<volatile bool>::value == true);
CHECK(is_integral<volatile char>::value == true);
CHECK(is_integral<volatile signed char>::value == true);
CHECK(is_integral<volatile signed int>::value == true);
CHECK(is_integral<volatile signed long>::value == true);
CHECK(is_integral<volatile signed short>::value == true);
CHECK(is_integral<volatile unsigned char>::value == true);
CHECK(is_integral<volatile unsigned int>::value == true);
CHECK(is_integral<volatile unsigned long>::value == true);
CHECK(is_integral<volatile unsigned short>::value == true);
CHECK(is_integral<const volatile bool>::value == true);
CHECK(is_integral<const volatile char>::value == true);
CHECK(is_integral<const volatile signed char>::value == true);
CHECK(is_integral<const volatile signed int>::value == true);
CHECK(is_integral<const volatile signed long>::value == true);
CHECK(is_integral<const volatile signed short>::value == true);
CHECK(is_integral<const volatile unsigned char>::value == true);
CHECK(is_integral<const volatile unsigned int>::value == true);
CHECK(is_integral<const volatile unsigned long>::value == true);
CHECK(is_integral<const volatile unsigned short>::value == true);
CHECK(is_integral<JsonUInt>::value == true);
}
SECTION("is_signed") {
CHECK(is_signed<char>::value == true);
CHECK(is_signed<signed char>::value == true);
CHECK(is_signed<signed int>::value == true);
CHECK(is_signed<signed short>::value == true);
CHECK(is_signed<signed long>::value == true);
CHECK(is_signed<float>::value == true);
CHECK(is_signed<double>::value == true);
CHECK(is_signed<bool>::value == false);
CHECK(is_signed<const char>::value == true);
CHECK(is_signed<const signed char>::value == true);
CHECK(is_signed<const signed int>::value == true);
CHECK(is_signed<const signed short>::value == true);
CHECK(is_signed<const signed long>::value == true);
CHECK(is_signed<const float>::value == true);
CHECK(is_signed<const double>::value == true);
CHECK(is_signed<const bool>::value == false);
CHECK(is_signed<volatile char>::value == true);
CHECK(is_signed<volatile signed char>::value == true);
CHECK(is_signed<volatile signed int>::value == true);
CHECK(is_signed<volatile signed short>::value == true);
CHECK(is_signed<volatile signed long>::value == true);
CHECK(is_signed<volatile float>::value == true);
CHECK(is_signed<volatile double>::value == true);
CHECK(is_signed<volatile bool>::value == false);
CHECK(is_signed<const volatile char>::value == true);
CHECK(is_signed<const volatile signed char>::value == true);
CHECK(is_signed<const volatile signed int>::value == true);
CHECK(is_signed<const volatile signed short>::value == true);
CHECK(is_signed<const volatile signed long>::value == true);
CHECK(is_signed<const volatile float>::value == true);
CHECK(is_signed<const volatile double>::value == true);
CHECK(is_signed<const volatile bool>::value == false);
}
SECTION("is_unsigned") {
CHECK(is_unsigned<unsigned char>::value == true);
CHECK(is_unsigned<unsigned int>::value == true);
CHECK(is_unsigned<unsigned short>::value == true);
CHECK(is_unsigned<unsigned long>::value == true);
CHECK(is_unsigned<bool>::value == true);
CHECK(is_unsigned<char>::value == false);
CHECK(is_unsigned<float>::value == false);
CHECK(is_unsigned<double>::value == false);
CHECK(is_unsigned<const unsigned char>::value == true);
CHECK(is_unsigned<const unsigned int>::value == true);
CHECK(is_unsigned<const unsigned short>::value == true);
CHECK(is_unsigned<const unsigned long>::value == true);
CHECK(is_unsigned<const bool>::value == true);
CHECK(is_unsigned<const char>::value == false);
CHECK(is_unsigned<const float>::value == false);
CHECK(is_unsigned<const double>::value == false);
CHECK(is_unsigned<volatile unsigned char>::value == true);
CHECK(is_unsigned<volatile unsigned int>::value == true);
CHECK(is_unsigned<volatile unsigned short>::value == true);
CHECK(is_unsigned<volatile unsigned long>::value == true);
CHECK(is_unsigned<volatile bool>::value == true);
CHECK(is_unsigned<volatile char>::value == false);
CHECK(is_unsigned<volatile float>::value == false);
CHECK(is_unsigned<volatile double>::value == false);
CHECK(is_unsigned<const volatile unsigned char>::value == true);
CHECK(is_unsigned<const volatile unsigned int>::value == true);
CHECK(is_unsigned<const volatile unsigned short>::value == true);
CHECK(is_unsigned<const volatile unsigned long>::value == true);
CHECK(is_unsigned<const volatile bool>::value == true);
CHECK(is_unsigned<const volatile char>::value == false);
CHECK(is_unsigned<const volatile float>::value == false);
CHECK(is_unsigned<const volatile double>::value == false);
}
SECTION("is_floating_point") {
CHECK(is_floating_point<int>::value == false);
CHECK(is_floating_point<float>::value == true);
CHECK(is_floating_point<double>::value == true);
CHECK(is_floating_point<const float>::value == true);
CHECK(is_floating_point<const double>::value == true);
CHECK(is_floating_point<volatile float>::value == true);
CHECK(is_floating_point<volatile double>::value == true);
CHECK(is_floating_point<const volatile float>::value == true);
CHECK(is_floating_point<const volatile double>::value == true);
}
SECTION("is_convertible") {
CHECK(is_convertible<short, int>::value == true);
CHECK(is_convertible<int, int>::value == true);
CHECK(is_convertible<EmptyEnum, int>::value == true);
CHECK(is_convertible<int*, int>::value == false);
CHECK(is_convertible<EmptyClass, int>::value == false);
CHECK(is_convertible<DeserializationError, JsonVariantConst>::value ==
false);
CHECK(is_convertible<JsonPair, JsonVariantConst>::value == false);
CHECK(is_convertible<JsonVariant, JsonVariantConst>::value == true);
CHECK(is_convertible<JsonVariantConst, JsonVariantConst>::value == true);
CHECK(is_convertible<JsonArray, JsonVariantConst>::value == true);
CHECK(is_convertible<ElementProxy<JsonArray>, JsonVariantConst>::value ==
true);
CHECK(is_convertible<JsonArrayConst, JsonVariantConst>::value == true);
CHECK(is_convertible<JsonObject, JsonVariantConst>::value == true);
CHECK(is_convertible<MemberProxy<JsonObject, const char*>,
JsonVariantConst>::value == true);
CHECK(is_convertible<JsonObjectConst, JsonVariantConst>::value == true);
CHECK(is_convertible<DynamicJsonDocument, JsonVariantConst>::value == true);
CHECK(is_convertible<StaticJsonDocument<10>, JsonVariantConst>::value ==
true);
}
SECTION("is_class") {
CHECK(is_class<int>::value == false);
CHECK(is_class<EmptyEnum>::value == false);
CHECK(is_class<int*>::value == false);
CHECK(is_class<EmptyClass>::value == true);
}
SECTION("is_enum") {
CHECK(is_enum<int>::value == false);
CHECK(is_enum<EmptyEnum>::value == true);
CHECK(is_enum<int*>::value == false);
CHECK(is_enum<EmptyClass>::value == false);
CHECK(is_enum<bool>::value == false);
CHECK(is_enum<double>::value == false);
}
}

View File

@ -0,0 +1,68 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Json/Utf16.hpp>
#include <catch.hpp>
using namespace ArduinoJson::detail;
static void testUtf16Codepoint(uint16_t codeunit, uint32_t expectedCodepoint) {
Utf16::Codepoint cp;
REQUIRE(cp.append(codeunit) == true);
REQUIRE(cp.value() == expectedCodepoint);
}
static void testUtf16Codepoint(uint16_t codeunit1, uint16_t codeunit2,
uint32_t expectedCodepoint) {
Utf16::Codepoint cp;
REQUIRE(cp.append(codeunit1) == false);
REQUIRE(cp.append(codeunit2) == true);
REQUIRE(cp.value() == expectedCodepoint);
}
TEST_CASE("Utf16::Codepoint()") {
SECTION("U+0000") {
testUtf16Codepoint(0x0000, 0x000000);
}
SECTION("U+0001") {
testUtf16Codepoint(0x0001, 0x000001);
}
SECTION("U+D7FF") {
testUtf16Codepoint(0xD7FF, 0x00D7FF);
}
SECTION("U+E000") {
testUtf16Codepoint(0xE000, 0x00E000);
}
SECTION("U+FFFF") {
testUtf16Codepoint(0xFFFF, 0x00FFFF);
}
SECTION("U+010000") {
testUtf16Codepoint(0xD800, 0xDC00, 0x010000);
}
SECTION("U+010001") {
testUtf16Codepoint(0xD800, 0xDC01, 0x010001);
}
SECTION("U+0103FF") {
testUtf16Codepoint(0xD800, 0xDFFF, 0x0103FF);
}
SECTION("U+010400") {
testUtf16Codepoint(0xD801, 0xDC00, 0x010400);
}
SECTION("U+010400") {
testUtf16Codepoint(0xDBFF, 0xDC00, 0x10FC00);
}
SECTION("U+10FFFF") {
testUtf16Codepoint(0xDBFF, 0xDFFF, 0x10FFFF);
}
}

View File

@ -0,0 +1,60 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#include <string>
using namespace ArduinoJson::detail;
static void testCodepoint(uint32_t codepoint, std::string expected) {
char buffer[4096];
MemoryPool pool(buffer, 4096);
StringCopier str(&pool);
str.startString();
CAPTURE(codepoint);
Utf8::encodeCodepoint(codepoint, str);
REQUIRE(str.str().c_str() == expected);
}
TEST_CASE("Utf8::encodeCodepoint()") {
SECTION("U+0000") {
testCodepoint(0x0000, "");
}
SECTION("U+0001") {
testCodepoint(0x0001, "\x01");
}
SECTION("U+007F") {
testCodepoint(0x007F, "\x7f");
}
SECTION("U+0080") {
testCodepoint(0x0080, "\xc2\x80");
}
SECTION("U+07FF") {
testCodepoint(0x07FF, "\xdf\xbf");
}
SECTION("U+0800") {
testCodepoint(0x0800, "\xe0\xa0\x80");
}
SECTION("U+FFFF") {
testCodepoint(0xFFFF, "\xef\xbf\xbf");
}
SECTION("U+10000") {
testCodepoint(0x10000, "\xf0\x90\x80\x80");
}
SECTION("U+10FFFF") {
testCodepoint(0x10FFFF, "\xf4\x8f\xbf\xbf");
}
}

View File

@ -0,0 +1,97 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <catch.hpp>
using namespace ArduinoJson::detail;
TEST_CASE("arithmeticCompare()") {
SECTION("int vs uint8_t") {
CHECK(arithmeticCompare<int, uint8_t>(256, 1) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<int, uint8_t>(41, 42) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompare<int, uint8_t>(42, 42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<int, uint8_t>(43, 42) == COMPARE_RESULT_GREATER);
}
SECTION("unsigned vs int") {
CHECK(arithmeticCompare<unsigned, int>(0, -1) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<unsigned, int>(42, 41) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<unsigned, int>(42, 42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<unsigned, int>(42, 43) == COMPARE_RESULT_LESS);
}
SECTION("float vs int") {
CHECK(arithmeticCompare<float, int>(42, 41) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<float, int>(42, 42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<float, int>(42, 43) == COMPARE_RESULT_LESS);
}
SECTION("int vs unsigned") {
CHECK(arithmeticCompare<int, unsigned>(-1, 0) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompare<int, unsigned>(0, 0) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<int, unsigned>(1, 0) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<int, unsigned>(42, 41) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<int, unsigned>(42, 42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<int, unsigned>(42, 43) == COMPARE_RESULT_LESS);
}
SECTION("unsigned vs unsigned") {
CHECK(arithmeticCompare<unsigned, unsigned>(42, 41) ==
COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<unsigned, unsigned>(42, 42) ==
COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<unsigned, unsigned>(42, 43) == COMPARE_RESULT_LESS);
}
SECTION("bool vs bool") {
CHECK(arithmeticCompare<bool, bool>(false, false) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<bool, bool>(true, true) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<bool, bool>(false, true) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompare<bool, bool>(true, false) == COMPARE_RESULT_GREATER);
}
SECTION("bool vs int") {
CHECK(arithmeticCompare<bool, int>(false, -1) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<bool, int>(false, 0) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<bool, int>(false, 1) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompare<bool, int>(true, 0) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<bool, int>(true, 1) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<bool, int>(true, 2) == COMPARE_RESULT_LESS);
}
SECTION("bool vs int") {
CHECK(arithmeticCompare<int, bool>(0, false) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<int, bool>(1, true) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompare<int, bool>(1, false) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompare<int, bool>(0, true) == COMPARE_RESULT_LESS);
}
}
TEST_CASE("arithmeticCompareNegateLeft()") {
SECTION("unsigned vs int") {
CHECK(arithmeticCompareNegateLeft<int>(0, 1) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompareNegateLeft<int>(42, -41) == COMPARE_RESULT_LESS);
CHECK(arithmeticCompareNegateLeft<int>(42, -42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompareNegateLeft<int>(42, -43) == COMPARE_RESULT_GREATER);
}
SECTION("unsigned vs unsigned") {
CHECK(arithmeticCompareNegateLeft<unsigned>(42, 42) == COMPARE_RESULT_LESS);
}
}
TEST_CASE("arithmeticCompareNegateRight()") {
SECTION("int vs unsigned") {
CHECK(arithmeticCompareNegateRight<int>(1, 0) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompareNegateRight<int>(-41, 42) == COMPARE_RESULT_GREATER);
CHECK(arithmeticCompareNegateRight<int>(-42, 42) == COMPARE_RESULT_EQUAL);
CHECK(arithmeticCompareNegateRight<int>(-43, 42) == COMPARE_RESULT_LESS);
}
SECTION("unsigned vs unsigned") {
CHECK(arithmeticCompareNegateRight<unsigned>(42, 42) ==
COMPARE_RESULT_GREATER);
}
}

View File

@ -0,0 +1,59 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
// Include any header that might use the conflicting macros
#include <cmath>
#include <iostream>
#include <string>
// All cores
#define bit()
#define constrain()
#define DEFAULT
#define DISABLED
#define HIGH
#define INPUT
#define LOW
#define max()
#define min()
#define OUTPUT
#define round()
#define sq()
#define word()
#define bitRead()
#define bitSet()
#define bitClear()
#define bitWrite()
#define interrupts()
#define lowByte()
#define highByte()
#define DEC
#define HEX
#define OCT
#define BIN
#define cbi()
#define sbi()
// ESP8266
#define _max()
#define _min()
// Realtek Ameba
#define isdigit(c) (((c) >= '0') && ((c) <= '9'))
#define isprint(c)
#define isxdigit(c)
#define isspace(c)
#define isupper(c)
#define islower(c)
#define isalpha(c)
// issue #839
#define BLOCKSIZE
#define CAPACITY
// issue #1905
#define _current
// catch.hpp mutes several warnings, this file also allows to detect them
#include "ArduinoJson.h"

View File

@ -0,0 +1,12 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#pragma once
#include <string>
struct custom_char_traits : std::char_traits<char> {};
struct custom_allocator : std::allocator<char> {};
typedef std::basic_string<char, custom_char_traits, custom_allocator>
custom_string;

View File

@ -0,0 +1,144 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <Arduino.h>
#include <catch.hpp>
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#include <ArduinoJson.h>
struct PrintOneCharacterAtATime {
static size_t printStringTo(const std::string& s, Print& p) {
size_t result = 0;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
size_t n = p.write(uint8_t(*it));
if (n == 0)
break;
result += n;
}
return result;
}
};
struct PrintAllAtOnce {
static size_t printStringTo(const std::string& s, Print& p) {
return p.write(s.data(), s.size());
}
};
template <typename PrintPolicy>
struct PrintableString : public Printable {
PrintableString(const char* s) : str_(s), total_(0) {}
virtual size_t printTo(Print& p) const {
size_t result = PrintPolicy::printStringTo(str_, p);
total_ += result;
return result;
}
size_t totalBytesWritten() const {
return total_;
}
private:
std::string str_;
mutable size_t total_;
};
TEST_CASE("Printable") {
SECTION("Doesn't overflow") {
StaticJsonDocument<8> doc;
const char* value = "example"; // == 7 chars
doc.set(666); // to make sure we override the value
SECTION("Via Print::write(char)") {
PrintableString<PrintOneCharacterAtATime> printable(value);
CHECK(doc.set(printable) == true);
CHECK(doc.as<std::string>() == value);
CHECK(printable.totalBytesWritten() == 7);
CHECK(doc.overflowed() == false);
CHECK(doc.memoryUsage() == 8);
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
}
SECTION("Via Print::write(const char* size_t)") {
PrintableString<PrintAllAtOnce> printable(value);
CHECK(doc.set(printable) == true);
CHECK(doc.as<std::string>() == value);
CHECK(printable.totalBytesWritten() == 7);
CHECK(doc.overflowed() == false);
CHECK(doc.memoryUsage() == 8);
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
}
}
SECTION("Overflows early") {
StaticJsonDocument<8> doc;
const char* value = "hello world"; // > 8 chars
doc.set(666); // to make sure we override the value
SECTION("Via Print::write(char)") {
PrintableString<PrintOneCharacterAtATime> printable(value);
CHECK(doc.set(printable) == false);
CHECK(doc.isNull());
CHECK(printable.totalBytesWritten() == 8);
CHECK(doc.overflowed() == true);
CHECK(doc.memoryUsage() == 0);
}
SECTION("Via Print::write(const char*, size_t)") {
PrintableString<PrintAllAtOnce> printable(value);
CHECK(doc.set(printable) == false);
CHECK(doc.isNull());
CHECK(printable.totalBytesWritten() == 0);
CHECK(doc.overflowed() == true);
CHECK(doc.memoryUsage() == 0);
}
}
SECTION("Overflows adding terminator") {
StaticJsonDocument<8> doc;
const char* value = "overflow"; // == 8 chars
doc.set(666); // to make sure we override the value
SECTION("Via Print::write(char)") {
PrintableString<PrintOneCharacterAtATime> printable(value);
CHECK(doc.set(printable) == false);
CHECK(doc.isNull());
CHECK(printable.totalBytesWritten() == 8);
CHECK(doc.overflowed() == true);
CHECK(doc.memoryUsage() == 0);
}
SECTION("Via Print::write(const char*, size_t)") {
PrintableString<PrintAllAtOnce> printable(value);
CHECK(doc.set(printable) == false);
CHECK(doc.isNull());
CHECK(printable.totalBytesWritten() == 0);
CHECK(doc.overflowed() == true);
CHECK(doc.memoryUsage() == 0);
}
}
SECTION("Null variant") {
JsonVariant var;
PrintableString<PrintOneCharacterAtATime> printable = "Hello World!";
CHECK(var.set(printable) == false);
CHECK(var.isNull());
CHECK(printable.totalBytesWritten() == 0);
}
SECTION("String deduplication") {
StaticJsonDocument<128> doc;
doc.add(PrintableString<PrintOneCharacterAtATime>("Hello World!"));
doc.add(PrintableString<PrintAllAtOnce>("Hello World!"));
REQUIRE(doc.size() == 2);
CHECK(doc[0] == "Hello World!");
CHECK(doc[1] == "Hello World!");
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 13);
}
}

View File

@ -0,0 +1,271 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#if defined(__clang__)
# define CONFLICTS_WITH_BUILTIN_OPERATOR
#endif
TEST_CASE("unsigned char[]") {
SECTION("deserializeJson()") {
unsigned char input[] = "{\"a\":42}";
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
DeserializationError err = deserializeJson(doc, input);
REQUIRE(err == DeserializationError::Ok);
}
SECTION("deserializeMsgPack()") {
unsigned char input[] = "\xDE\x00\x01\xA5Hello\xA5world";
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
DeserializationError err = deserializeMsgPack(doc, input);
REQUIRE(err == DeserializationError::Ok);
}
SECTION("serializeMsgPack(unsigned char[])") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeMsgPack(doc, buffer);
REQUIRE(n == 13);
REQUIRE(memcmp(buffer, "\x81\xA5hello\xA5world", 13) == 0);
}
SECTION("serializeMsgPack(unsigned char*)") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeMsgPack(doc, buffer, sizeof(buffer));
REQUIRE(n == 13);
REQUIRE(memcmp(buffer, "\x81\xA5hello\xA5world", 13) == 0);
}
SECTION("serializeJson(unsigned char[])") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeJson(doc, buffer);
REQUIRE(n == 17);
REQUIRE(memcmp(buffer, "{\"hello\":\"world\"}", n) == 0);
}
SECTION("serializeJson(unsigned char*)") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeJson(doc, buffer, sizeof(buffer));
REQUIRE(n == 17);
REQUIRE(memcmp(buffer, "{\"hello\":\"world\"}", n) == 0);
}
SECTION("serializeJsonPretty(unsigned char[])") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeJsonPretty(doc, buffer);
REQUIRE(n == 24);
}
SECTION("serializeJsonPretty(unsigned char*)") {
unsigned char buffer[32];
StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
doc["hello"] = "world";
size_t n = serializeJsonPretty(doc, buffer, sizeof(buffer));
REQUIRE(n == 24);
}
SECTION("JsonVariant") {
DynamicJsonDocument doc(4096);
SECTION("set") {
unsigned char value[] = "42";
JsonVariant variant = doc.to<JsonVariant>();
variant.set(value);
REQUIRE(42 == variant.as<int>());
}
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
SECTION("operator[]") {
unsigned char key[] = "hello";
deserializeJson(doc, "{\"hello\":\"world\"}");
JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[key]);
}
#endif
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
SECTION("operator[] const") {
unsigned char key[] = "hello";
deserializeJson(doc, "{\"hello\":\"world\"}");
const JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[key]);
}
#endif
SECTION("operator==") {
unsigned char comparand[] = "hello";
JsonVariant variant = doc.to<JsonVariant>();
variant.set("hello");
REQUIRE(comparand == variant);
REQUIRE(variant == comparand);
REQUIRE_FALSE(comparand != variant);
REQUIRE_FALSE(variant != comparand);
}
SECTION("operator!=") {
unsigned char comparand[] = "hello";
JsonVariant variant = doc.to<JsonVariant>();
variant.set("world");
REQUIRE(comparand != variant);
REQUIRE(variant != comparand);
REQUIRE_FALSE(comparand == variant);
REQUIRE_FALSE(variant == comparand);
}
}
SECTION("JsonObject") {
#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR
SECTION("operator[]") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
obj[key] = "world";
REQUIRE(std::string("world") == obj["hello"]);
}
SECTION("JsonObject::operator[] const") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(std::string("world") == obj[key]);
}
#endif
SECTION("containsKey()") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
REQUIRE(true == obj.containsKey(key));
}
SECTION("remove()") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject obj = doc.as<JsonObject>();
obj.remove(key);
REQUIRE(0 == obj.size());
}
SECTION("createNestedArray()") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
obj.createNestedArray(key);
}
SECTION("createNestedObject()") {
unsigned char key[] = "hello";
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
obj.createNestedObject(key);
}
}
SECTION("MemberProxy") {
SECTION("operator=") { // issue #416
unsigned char value[] = "world";
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
obj["hello"] = value;
REQUIRE(std::string("world") == obj["hello"]);
}
SECTION("set()") {
unsigned char value[] = "world";
DynamicJsonDocument doc(4096);
JsonObject obj = doc.to<JsonObject>();
obj["hello"].set(value);
REQUIRE(std::string("world") == obj["hello"]);
}
}
SECTION("JsonArray") {
SECTION("add()") {
unsigned char value[] = "world";
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
arr.add(value);
REQUIRE(std::string("world") == arr[0]);
}
}
SECTION("ElementProxy") {
SECTION("set()") {
unsigned char value[] = "world";
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
arr.add("hello");
arr[0].set(value);
REQUIRE(std::string("world") == arr[0]);
}
SECTION("operator=") {
unsigned char value[] = "world";
DynamicJsonDocument doc(4096);
JsonArray arr = doc.to<JsonArray>();
arr.add("hello");
arr[0] = value;
REQUIRE(std::string("world") == arr[0]);
}
}
}

View File

@ -0,0 +1,18 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/version.hpp>
#include <catch.hpp>
#include <sstream>
using Catch::Matchers::StartsWith;
TEST_CASE("ARDUINOJSON_VERSION") {
std::stringstream version;
version << ARDUINOJSON_VERSION_MAJOR << "." << ARDUINOJSON_VERSION_MINOR
<< "." << ARDUINOJSON_VERSION_REVISION;
REQUIRE_THAT(ARDUINOJSON_VERSION, StartsWith(version.str()));
}

View File

@ -0,0 +1,31 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Namespace.hpp>
#include <string.h> // strcmp, strncmp
// Issue #1198: strcmp() implementation that returns a value larger than 8-bit
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
int strcmp(const char* a, const char* b) {
int result = ::strcmp(a, b);
if (result > 0)
return 2147483647;
if (result < 0)
return -214748364;
return 0;
}
int strncmp(const char* a, const char* b, size_t n) {
int result = ::strncmp(a, b, n);
if (result > 0)
return 2147483647;
if (result < 0)
return -214748364;
return 0;
}
ARDUINOJSON_END_PRIVATE_NAMESPACE