forked from bblanchon/ArduinoJson
Moved ancillary files to extras/
(fixes #1011)
This commit is contained in:
20
extras/ci/arduino.sh
Executable file
20
extras/ci/arduino.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
sleep 3
|
||||
export DISPLAY=:1.0
|
||||
|
||||
mkdir -p /tmp/arduino
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
export PATH=$PATH:/tmp/arduino/
|
||||
|
||||
if [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
arduino --install-boards arduino:samd
|
||||
fi
|
||||
|
||||
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino; do
|
||||
arduino --verify --board $BOARD $EXAMPLE
|
||||
done
|
14
extras/ci/build.sh
Executable file
14
extras/ci/build.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
export CC="$_CC"
|
||||
export CXX="$_CXX"
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
cmake --build .
|
9
extras/ci/coverage.sh
Executable file
9
extras/ci/coverage.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
cmake -DCOVERAGE=true .
|
||||
make
|
||||
make test
|
||||
|
||||
pip install --user cpp-coveralls 'requests[security]'
|
||||
pwd
|
||||
coveralls --include 'src' --gcov-options '\-lp'
|
26
extras/ci/fuzz.sh
Executable file
26
extras/ci/fuzz.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/extras/fuzzing/
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,undefined,fuzzer -fno-sanitize-recover=all"
|
||||
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
FUZZER="${NAME}_fuzzer"
|
||||
FUZZER_CPP="${FUZZING_DIR}/${NAME}_fuzzer.cpp"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${NAME}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${NAME}_seed_corpus"
|
||||
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
20
extras/ci/platformio.sh
Executable file
20
extras/ci/platformio.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
pip install --user platformio
|
||||
|
||||
case $BOARD in
|
||||
uno)
|
||||
platformio lib install 868 # SD library
|
||||
platformio lib install 872 # Ethernet library
|
||||
;;
|
||||
esp01)
|
||||
platformio lib uninstall 161 || true
|
||||
platformio lib uninstall 868 || true
|
||||
platformio lib uninstall 872 || true
|
||||
;;
|
||||
esac
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino;
|
||||
do
|
||||
platformio ci $EXAMPLE -l '.' -b $BOARD
|
||||
done
|
4
extras/ci/test.sh
Executable file
4
extras/ci/test.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
"$(dirname "$0")/build.sh"
|
||||
ctest --output-on-failure .
|
17
extras/fuzzing/CMakeLists.txt
Normal file
17
extras/fuzzing/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
add_executable(msgpack_fuzzer
|
||||
msgpack_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
||||
|
||||
add_executable(json_fuzzer
|
||||
json_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
22
extras/fuzzing/Makefile
Normal file
22
extras/fuzzing/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options \
|
||||
$(OUT)/msgpack_fuzzer \
|
||||
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/msgpack_fuzzer.options
|
||||
|
||||
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/%_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
50
extras/fuzzing/fuzzer_main.cpp
Normal file
50
extras/fuzzing/fuzzer_main.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
// This file is NOT use by Google's OSS fuzz
|
||||
// I only use it to reproduce the bugs found
|
||||
|
||||
#include <stdint.h> // size_t
|
||||
#include <stdio.h> // fopen et al.
|
||||
#include <stdlib.h> // exit
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
std::vector<uint8_t> read(const char* path) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
std::cerr << "Failed to open " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (fread(buffer.data(), 1, size, f) != size) {
|
||||
fclose(f);
|
||||
std::cerr << "Failed to read " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: msgpack_fuzzer files" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::cout << "Loading " << argv[i] << std::endl;
|
||||
std::vector<uint8_t> buffer = read(argv[i]);
|
||||
LLVMFuzzerTestOneInput(buffer.data(), buffer.size());
|
||||
}
|
||||
return 0;
|
||||
}
|
2
extras/fuzzing/json_corpus/.gitignore
vendored
Normal file
2
extras/fuzzing/json_corpus/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
11
extras/fuzzing/json_fuzzer.cpp
Normal file
11
extras/fuzzing/json_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
10
extras/fuzzing/json_seed_corpus/Comments.json
Normal file
10
extras/fuzzing/json_seed_corpus/Comments.json
Normal file
@ -0,0 +1,10 @@
|
||||
//comment
|
||||
/*comment*/
|
||||
[ //comment
|
||||
/*comment*/"comment"/*comment*/,//comment
|
||||
/*comment*/{//comment
|
||||
/* comment*/"key"//comment
|
||||
: //comment
|
||||
"value"//comment
|
||||
}/*comment*/
|
||||
]//comment
|
1
extras/fuzzing/json_seed_corpus/EmptyArray.json
Normal file
1
extras/fuzzing/json_seed_corpus/EmptyArray.json
Normal file
@ -0,0 +1 @@
|
||||
[]
|
1
extras/fuzzing/json_seed_corpus/EmptyObject.json
Normal file
1
extras/fuzzing/json_seed_corpus/EmptyObject.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
1
extras/fuzzing/json_seed_corpus/ExcessiveNesting.json
Normal file
1
extras/fuzzing/json_seed_corpus/ExcessiveNesting.json
Normal file
@ -0,0 +1 @@
|
||||
[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20,[21,[22,[23,[24,[25,[26,[27,[28,[29,[30,[31,[32,[33,[34,[35,[36,[37,[38,[39,[40,[41,[42,[43,[44,[45,[46,[47,[48,[49,[50,[51,[52,[53,[54,[55,[56,[57,[58,[59,[60,[61,[62,[63,[64,[65,[66,[67,[68,[69,[70,[71,[72,[73,[74,[75,[76,[77,[78,[79,[80,[81,[82,[83,[84,[85,[86,[87,[88,[89,[90,[91,[92,[93,[94,[95,[96,[97,[98,[99,[100,[101,[102,[103,[104,[105,[106,[107,[108,[109,[110,[111,[112,[113,[114,[115,[116,[117,[118,[119,[120]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
|
1
extras/fuzzing/json_seed_corpus/IntegerOverflow.json
Normal file
1
extras/fuzzing/json_seed_corpus/IntegerOverflow.json
Normal file
@ -0,0 +1 @@
|
||||
9720730739393920739
|
24
extras/fuzzing/json_seed_corpus/Numbers.json
Normal file
24
extras/fuzzing/json_seed_corpus/Numbers.json
Normal file
@ -0,0 +1,24 @@
|
||||
[
|
||||
123,
|
||||
-123,
|
||||
123.456,
|
||||
-123.456,
|
||||
12e34,
|
||||
12e-34,
|
||||
12e+34,
|
||||
12E34,
|
||||
12E-34,
|
||||
12E+34,
|
||||
12.34e56,
|
||||
12.34e-56,
|
||||
12.34e+56,
|
||||
12.34E56,
|
||||
12.34E-56,
|
||||
12.34E+56,
|
||||
NaN,
|
||||
-NaN,
|
||||
+NaN,
|
||||
Infinity,
|
||||
+Infinity,
|
||||
-Infinity
|
||||
]
|
53
extras/fuzzing/json_seed_corpus/OpenWeatherMap.json
Normal file
53
extras/fuzzing/json_seed_corpus/OpenWeatherMap.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
"coord": {
|
||||
"lon": -0.13,
|
||||
"lat": 51.51
|
||||
},
|
||||
"weather": [
|
||||
{
|
||||
"id": 301,
|
||||
"main": "Drizzle",
|
||||
"description": "drizzle",
|
||||
"icon": "09n"
|
||||
},
|
||||
{
|
||||
"id": 701,
|
||||
"main": "Mist",
|
||||
"description": "mist",
|
||||
"icon": "50n"
|
||||
},
|
||||
{
|
||||
"id": 741,
|
||||
"main": "Fog",
|
||||
"description": "fog",
|
||||
"icon": "50n"
|
||||
}
|
||||
],
|
||||
"base": "stations",
|
||||
"main": {
|
||||
"temp": 281.87,
|
||||
"pressure": 1032,
|
||||
"humidity": 100,
|
||||
"temp_min": 281.15,
|
||||
"temp_max": 283.15
|
||||
},
|
||||
"visibility": 2900,
|
||||
"wind": {
|
||||
"speed": 1.5
|
||||
},
|
||||
"clouds": {
|
||||
"all": 90
|
||||
},
|
||||
"dt": 1483820400,
|
||||
"sys": {
|
||||
"type": 1,
|
||||
"id": 5091,
|
||||
"message": 0.0226,
|
||||
"country": "GB",
|
||||
"sunrise": 1483776245,
|
||||
"sunset": 1483805443
|
||||
},
|
||||
"id": 2643743,
|
||||
"name": "London",
|
||||
"cod": 200
|
||||
}
|
8
extras/fuzzing/json_seed_corpus/Strings.json
Normal file
8
extras/fuzzing/json_seed_corpus/Strings.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
"hello",
|
||||
'hello',
|
||||
hello,
|
||||
{"hello":"world"},
|
||||
{'hello':'world'},
|
||||
{hello:world}
|
||||
]
|
90
extras/fuzzing/json_seed_corpus/WeatherUnderground.json
Normal file
90
extras/fuzzing/json_seed_corpus/WeatherUnderground.json
Normal file
@ -0,0 +1,90 @@
|
||||
{
|
||||
"response": {
|
||||
"version": "0.1",
|
||||
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
|
||||
"features": {
|
||||
"conditions": 1
|
||||
}
|
||||
},
|
||||
"current_observation": {
|
||||
"image": {
|
||||
"url": "http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png",
|
||||
"title": "Weather Underground",
|
||||
"link": "http://www.wunderground.com"
|
||||
},
|
||||
"display_location": {
|
||||
"full": "San Francisco, CA",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"state_name": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"zip": "94101",
|
||||
"latitude": "37.77500916",
|
||||
"longitude": "-122.41825867",
|
||||
"elevation": "47.00000000"
|
||||
},
|
||||
"observation_location": {
|
||||
"full": "SOMA - Near Van Ness, San Francisco, California",
|
||||
"city": "SOMA - Near Van Ness, San Francisco",
|
||||
"state": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"latitude": "37.773285",
|
||||
"longitude": "-122.417725",
|
||||
"elevation": "49 ft"
|
||||
},
|
||||
"estimated": {},
|
||||
"station_id": "KCASANFR58",
|
||||
"observation_time": "Last Updated on June 27, 5:27 PM PDT",
|
||||
"observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700",
|
||||
"observation_epoch": "1340843233",
|
||||
"local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700",
|
||||
"local_epoch": "1340843234",
|
||||
"local_tz_short": "PDT",
|
||||
"local_tz_long": "America/Los_Angeles",
|
||||
"local_tz_offset": "-0700",
|
||||
"weather": "Partly Cloudy",
|
||||
"temperature_string": "66.3 F (19.1 C)",
|
||||
"temp_f": 66.3,
|
||||
"temp_c": 19.1,
|
||||
"relative_humidity": "65%",
|
||||
"wind_string": "From the NNW at 22.0 MPH Gusting to 28.0 MPH",
|
||||
"wind_dir": "NNW",
|
||||
"wind_degrees": 346,
|
||||
"wind_mph": 22,
|
||||
"wind_gust_mph": "28.0",
|
||||
"wind_kph": 35.4,
|
||||
"wind_gust_kph": "45.1",
|
||||
"pressure_mb": "1013",
|
||||
"pressure_in": "29.93",
|
||||
"pressure_trend": "+",
|
||||
"dewpoint_string": "54 F (12 C)",
|
||||
"dewpoint_f": 54,
|
||||
"dewpoint_c": 12,
|
||||
"heat_index_string": "NA",
|
||||
"heat_index_f": "NA",
|
||||
"heat_index_c": "NA",
|
||||
"windchill_string": "NA",
|
||||
"windchill_f": "NA",
|
||||
"windchill_c": "NA",
|
||||
"feelslike_string": "66.3 F (19.1 C)",
|
||||
"feelslike_f": "66.3",
|
||||
"feelslike_c": "19.1",
|
||||
"visibility_mi": "10.0",
|
||||
"visibility_km": "16.1",
|
||||
"solarradiation": "",
|
||||
"UV": "5",
|
||||
"precip_1hr_string": "0.00 in ( 0 mm)",
|
||||
"precip_1hr_in": "0.00",
|
||||
"precip_1hr_metric": " 0",
|
||||
"precip_today_string": "0.00 in (0 mm)",
|
||||
"precip_today_in": "0.00",
|
||||
"precip_today_metric": "0",
|
||||
"icon": "partlycloudy",
|
||||
"icon_url": "http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",
|
||||
"forecast_url": "http://www.wunderground.com/US/CA/San_Francisco.html",
|
||||
"history_url": "http://www.wunderground.com/history/airport/KCASANFR58/2012/6/27/DailyHistory.html",
|
||||
"ob_url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=37.773285,-122.417725"
|
||||
}
|
||||
}
|
2
extras/fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
2
extras/fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
11
extras/fuzzing/msgpack_fuzzer.cpp
Normal file
11
extras/fuzzing/msgpack_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeMsgPack(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
extras/fuzzing/msgpack_seed_corpus/array16
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/array16
Normal file
Binary file not shown.
BIN
extras/fuzzing/msgpack_seed_corpus/array32
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/array32
Normal file
Binary file not shown.
1
extras/fuzzing/msgpack_seed_corpus/false
Normal file
1
extras/fuzzing/msgpack_seed_corpus/false
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/fixarray
Normal file
1
extras/fuzzing/msgpack_seed_corpus/fixarray
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>hello<EFBFBD>world
|
1
extras/fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
1
extras/fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
1
extras/fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
@ -0,0 +1 @@
|
||||
|
1
extras/fuzzing/msgpack_seed_corpus/fixmap
Normal file
1
extras/fuzzing/msgpack_seed_corpus/fixmap
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>one<01>two
|
1
extras/fuzzing/msgpack_seed_corpus/fixstr
Normal file
1
extras/fuzzing/msgpack_seed_corpus/fixstr
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello world
|
1
extras/fuzzing/msgpack_seed_corpus/float32
Normal file
1
extras/fuzzing/msgpack_seed_corpus/float32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@H<><48>
|
1
extras/fuzzing/msgpack_seed_corpus/float64
Normal file
1
extras/fuzzing/msgpack_seed_corpus/float64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@ !<21><><EFBFBD>o
|
1
extras/fuzzing/msgpack_seed_corpus/int16
Normal file
1
extras/fuzzing/msgpack_seed_corpus/int16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/int32
Normal file
1
extras/fuzzing/msgpack_seed_corpus/int32
Normal file
@ -0,0 +1 @@
|
||||
Ҷi<EFBFBD>.
|
1
extras/fuzzing/msgpack_seed_corpus/int64
Normal file
1
extras/fuzzing/msgpack_seed_corpus/int64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/int8
Normal file
1
extras/fuzzing/msgpack_seed_corpus/int8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
BIN
extras/fuzzing/msgpack_seed_corpus/map16
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/map16
Normal file
Binary file not shown.
BIN
extras/fuzzing/msgpack_seed_corpus/map32
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/map32
Normal file
Binary file not shown.
1
extras/fuzzing/msgpack_seed_corpus/nil
Normal file
1
extras/fuzzing/msgpack_seed_corpus/nil
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
BIN
extras/fuzzing/msgpack_seed_corpus/str16
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/str16
Normal file
Binary file not shown.
BIN
extras/fuzzing/msgpack_seed_corpus/str32
Normal file
BIN
extras/fuzzing/msgpack_seed_corpus/str32
Normal file
Binary file not shown.
1
extras/fuzzing/msgpack_seed_corpus/str8
Normal file
1
extras/fuzzing/msgpack_seed_corpus/str8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello
|
1
extras/fuzzing/msgpack_seed_corpus/true
Normal file
1
extras/fuzzing/msgpack_seed_corpus/true
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/uint16
Normal file
1
extras/fuzzing/msgpack_seed_corpus/uint16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>09
|
1
extras/fuzzing/msgpack_seed_corpus/uint32
Normal file
1
extras/fuzzing/msgpack_seed_corpus/uint32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx
|
1
extras/fuzzing/msgpack_seed_corpus/uint64
Normal file
1
extras/fuzzing/msgpack_seed_corpus/uint64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
extras/fuzzing/msgpack_seed_corpus/uint8
Normal file
1
extras/fuzzing/msgpack_seed_corpus/uint8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
20
extras/scripts/build-arduino-package.sh
Executable file
20
extras/scripts/build-arduino-package.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd $(dirname $0)/../../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/src \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/ArduinoJson.h
|
81
extras/scripts/build-single-header.sh
Executable file
81
extras/scripts/build-single-header.sh
Executable file
@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
TAG=$(git describe)
|
||||
RE_RELATIVE_INCLUDE='^#include[[:space:]]*"(.*)"'
|
||||
RE_ABSOLUTE_INCLUDE='^#include[[:space:]]*<(ArduinoJson/.*)>'
|
||||
RE_SYSTEM_INCLUDE='^#include[[:space:]]*<(.*)>'
|
||||
RE_EMPTY='^(#pragma[[:space:]]+once)?[[:space:]]*(//.*)?$'
|
||||
SRC_DIRECTORY="$(realpath "$(dirname $0)/../../src")"
|
||||
|
||||
|
||||
declare -A INCLUDED
|
||||
|
||||
process()
|
||||
{
|
||||
local PARENT=$1
|
||||
local FOLDER=$(dirname $1)
|
||||
local SHOW_COMMENT=$2
|
||||
while IFS= read -r LINE; do
|
||||
if [[ $LINE =~ $RE_ABSOLUTE_INCLUDE ]]; then
|
||||
local CHILD=${BASH_REMATCH[1]}
|
||||
local CHILD_PATH
|
||||
CHILD_PATH=$(realpath "$SRC_DIRECTORY/$CHILD")
|
||||
echo "$PARENT -> $CHILD" >&2
|
||||
if [[ ! ${INCLUDED[$CHILD_PATH]} ]]; then
|
||||
INCLUDED[$CHILD_PATH]=true
|
||||
process "$CHILD" false
|
||||
fi
|
||||
elif [[ $LINE =~ $RE_RELATIVE_INCLUDE ]]; then
|
||||
local CHILD=${BASH_REMATCH[1]}
|
||||
pushd "$FOLDER" > /dev/null
|
||||
local CHILD_PATH
|
||||
CHILD_PATH=$(realpath "$CHILD")
|
||||
echo "$PARENT -> $CHILD" >&2
|
||||
if [[ ! ${INCLUDED[$CHILD_PATH]} ]]; then
|
||||
INCLUDED[$CHILD_PATH]=true
|
||||
process "$CHILD" false
|
||||
fi
|
||||
popd > /dev/null
|
||||
elif [[ $LINE =~ $RE_SYSTEM_INCLUDE ]]; then
|
||||
local CHILD=${BASH_REMATCH[1]}
|
||||
echo "$PARENT -> <$CHILD>" >&2
|
||||
if [[ ! ${INCLUDED[$CHILD]} ]]; then
|
||||
echo "#include <$CHILD>"
|
||||
INCLUDED[$CHILD]=true
|
||||
fi
|
||||
elif [[ "${SHOW_COMMENT}" = "true" ]] ; then
|
||||
echo "$LINE"
|
||||
elif [[ ! $LINE =~ $RE_EMPTY ]]; then
|
||||
echo "$LINE"
|
||||
fi
|
||||
done < $PARENT
|
||||
}
|
||||
|
||||
simplify_namespaces() {
|
||||
perl -p0i -e 's|\} // namespace ARDUINOJSON_NAMESPACE\r?\nnamespace ARDUINOJSON_NAMESPACE \{\r?\n||igs' "$1"
|
||||
}
|
||||
|
||||
cd $(dirname $0)/../
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.h true > ../ArduinoJson-$TAG.h
|
||||
simplify_namespaces ../ArduinoJson-$TAG.h
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.h"
|
||||
int main() {
|
||||
StaticJsonDocument<300> doc;
|
||||
deserializeJson(doc, "{}");
|
||||
}
|
||||
END
|
||||
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.hpp true > ../ArduinoJson-$TAG.hpp
|
||||
simplify_namespaces ../ArduinoJson-$TAG.hpp
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.hpp"
|
||||
int main() {
|
||||
ArduinoJson::StaticJsonDocument<300> doc;
|
||||
ArduinoJson::deserializeJson(doc, "{}");
|
||||
}
|
||||
END
|
29
extras/scripts/create-build-envs.sh
Executable file
29
extras/scripts/create-build-envs.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PATH="$PATH:/Applications/CMake.app/Contents/bin/"
|
||||
|
||||
cd $(dirname $0)/../..
|
||||
ROOT=$(pwd)
|
||||
|
||||
mkdir "build"
|
||||
cd build
|
||||
BUILD=$(pwd)
|
||||
|
||||
build-env()
|
||||
{
|
||||
cd $BUILD
|
||||
mkdir "$1"
|
||||
cd "$1"
|
||||
cmake "$ROOT" -G "$2"
|
||||
}
|
||||
|
||||
if [[ $(uname) == MINGW* ]]
|
||||
then
|
||||
build-env "Make" "MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "VisualStudio" "Visual Studio 14 2015"
|
||||
else
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "Make" "Unix Makefiles"
|
||||
build-env "Xcode" "Xcode"
|
||||
fi
|
18
extras/scripts/publish-particle-library.sh
Executable file
18
extras/scripts/publish-particle-library.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/../.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
61
extras/scripts/publish.sh
Executable file
61
extras/scripts/publish.sh
Executable file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
VERSION="$1"
|
||||
DATE=$(date +%F)
|
||||
TAG="v$VERSION"
|
||||
VERSION_REGEX="[0-9a-z\\.\\-]+"
|
||||
|
||||
update_version_in_source () {
|
||||
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
|
||||
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
|
||||
|
||||
sed -i~ -bE "s/version=$VERSION_REGEX/version=$VERSION/; s|ardu-badge.com/ArduinoJson/$VERSION_REGEX|ardu-badge.com/ArduinoJson/$VERSION|; " README.md
|
||||
rm README.md*~
|
||||
|
||||
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
|
||||
rm CHANGELOG.md*~
|
||||
|
||||
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
|
||||
rm library.json*~
|
||||
|
||||
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
|
||||
rm library.properties*~
|
||||
|
||||
sed -i~ -bE "s/version: .*$/version: $VERSION.{build}/" appveyor.yml
|
||||
rm appveyor.yml*~
|
||||
|
||||
sed -i~ -bE \
|
||||
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MINOR .*$/ARDUINOJSON_VERSION_MINOR $MINOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_REVISION .*$/ARDUINOJSON_VERSION_REVISION $REVISION/" \
|
||||
src/ArduinoJson/version.hpp
|
||||
rm src/ArduinoJson/version.hpp*~
|
||||
}
|
||||
|
||||
commit_new_version () {
|
||||
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml
|
||||
git commit -m "Set version to $VERSION"
|
||||
}
|
||||
|
||||
add_tag () {
|
||||
CHANGES=$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' CHANGELOG.md)
|
||||
git tag -m "ArduinoJson $VERSION"$'\n'"$CHANGES" "$TAG"
|
||||
}
|
||||
|
||||
push () {
|
||||
git push --follow-tags
|
||||
}
|
||||
|
||||
update_version_in_source
|
||||
commit_new_version
|
||||
add_tag
|
||||
push
|
||||
|
||||
scripts/build-arduino-package.sh
|
||||
scripts/build-single-header.sh
|
||||
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"
|
60
extras/scripts/wandbox/JsonGeneratorExample.cpp
Normal file
60
extras/scripts/wandbox/JsonGeneratorExample.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Add values in the document
|
||||
//
|
||||
doc["sensor"] = "gps";
|
||||
doc["time"] = 1351824120;
|
||||
|
||||
// Add an array.
|
||||
//
|
||||
JsonArray data = doc.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
// Generate the minified JSON and send it to STDOUT
|
||||
//
|
||||
serializeJson(doc, std::cout);
|
||||
// The above line prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
// Start a new line
|
||||
std::cout << std::endl;
|
||||
|
||||
// Generate the prettified JSON and send it to STDOUT
|
||||
//
|
||||
serializeJsonPretty(doc, std::cout);
|
||||
// The above line prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
}
|
59
extras/scripts/wandbox/JsonParserExample.cpp
Normal file
59
extras/scripts/wandbox/JsonParserExample.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||
// the input buffer.
|
||||
// If you use another type of input, ArduinoJson must copy the strings from
|
||||
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||
// JsonDocument.
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
68
extras/scripts/wandbox/MsgPackParserExample.cpp
Normal file
68
extras/scripts/wandbox/MsgPackParserExample.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 300 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// MessagePack input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
|
||||
// This MessagePack document contains:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [48.75608, 2.302038]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
29
extras/scripts/wandbox/publish.sh
Executable file
29
extras/scripts/wandbox/publish.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
ARDUINOJSON_H="$1"
|
||||
|
||||
read_string() {
|
||||
jq --slurp --raw-input '.' "$1"
|
||||
}
|
||||
|
||||
compile() {
|
||||
FILE_PATH="$(dirname $0)/$1.cpp"
|
||||
cat >parameters.json <<END
|
||||
{
|
||||
"code":$(read_string "$FILE_PATH"),
|
||||
"codes": [{"file":"ArduinoJson.h","code":$(read_string "$ARDUINOJSON_H")}],
|
||||
"options": "warning",
|
||||
"compiler": "gcc-4.9.3",
|
||||
"save": true
|
||||
}
|
||||
END
|
||||
URL=$(curl -sS -H "Content-type: application/json" -d @parameters.json https://wandbox.org/api/compile.json | jq --raw-output .url)
|
||||
rm parameters.json
|
||||
echo " $1: $URL"
|
||||
}
|
||||
|
||||
compile "JsonGeneratorExample"
|
||||
compile "JsonParserExample"
|
||||
compile "MsgPackParserExample"
|
90
extras/tests/CMakeLists.txt
Normal file
90
extras/tests/CMakeLists.txt
Normal file
@ -0,0 +1,90 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_subdirectory(catch)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_compile_options(
|
||||
-pedantic
|
||||
-Wall
|
||||
-Wcast-align
|
||||
-Wcast-qual
|
||||
-Wconversion
|
||||
-Wctor-dtor-privacy
|
||||
-Wdisabled-optimization
|
||||
-Werror
|
||||
-Wextra
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Wnon-virtual-dtor
|
||||
-Wold-style-cast
|
||||
-Woverloaded-virtual
|
||||
-Wparentheses
|
||||
-Wredundant-decls
|
||||
-Wshadow
|
||||
-Wsign-promo
|
||||
-Wstrict-aliasing
|
||||
-Wundef
|
||||
)
|
||||
|
||||
if(NOT MINGW)
|
||||
add_compile_options(
|
||||
-std=c++98
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
add_compile_options(
|
||||
-Wstrict-null-sentinel
|
||||
-Wno-vla # Allow VLA in tests
|
||||
)
|
||||
add_definitions(-DHAS_VARIABLE_LENGTH_ARRAY)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5)
|
||||
add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6)
|
||||
add_compile_options(-Wnoexcept)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(
|
||||
-Wc++11-compat
|
||||
-Wdeprecated-register
|
||||
-Wno-vla-extension # Allow VLA in tests
|
||||
)
|
||||
add_definitions(
|
||||
-DHAS_VARIABLE_LENGTH_ARRAY
|
||||
-DSUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_options(
|
||||
/W4 # Set warning level
|
||||
/WX # Treats all compiler warnings as errors.
|
||||
)
|
||||
endif()
|
||||
|
||||
add_subdirectory(ElementProxy)
|
||||
add_subdirectory(IntegrationTests)
|
||||
add_subdirectory(JsonArray)
|
||||
add_subdirectory(JsonDeserializer)
|
||||
add_subdirectory(JsonDocument)
|
||||
add_subdirectory(JsonObject)
|
||||
add_subdirectory(JsonSerializer)
|
||||
add_subdirectory(JsonVariant)
|
||||
add_subdirectory(MemberProxy)
|
||||
add_subdirectory(MemoryPool)
|
||||
add_subdirectory(Misc)
|
||||
add_subdirectory(MixedConfiguration)
|
||||
add_subdirectory(MsgPackDeserializer)
|
||||
add_subdirectory(MsgPackSerializer)
|
||||
add_subdirectory(Numbers)
|
||||
add_subdirectory(TextFormatter)
|
15
extras/tests/ElementProxy/CMakeLists.txt
Normal file
15
extras/tests/ElementProxy/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_executable(ElementProxyTests
|
||||
add.cpp
|
||||
clear.cpp
|
||||
compare.cpp
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(ElementProxyTests catch)
|
||||
add_test(ElementProxy ElementProxyTests)
|
26
extras/tests/ElementProxy/add.cpp
Normal file
26
extras/tests/ElementProxy/add.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::add()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
doc.addElement();
|
||||
ElementProxy<JsonDocument&> ep = doc[0];
|
||||
|
||||
SECTION("add(int)") {
|
||||
ep.add(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[[42]]");
|
||||
}
|
||||
|
||||
SECTION("add(const char*)") {
|
||||
ep.add("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
||||
}
|
||||
}
|
28
extras/tests/ElementProxy/clear.cpp
Normal file
28
extras/tests/ElementProxy/clear.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::clear()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
doc.addElement();
|
||||
ElementProxy<JsonDocument&> ep = doc[0];
|
||||
|
||||
SECTION("size goes back to zero") {
|
||||
ep.add(42);
|
||||
ep.clear();
|
||||
|
||||
REQUIRE(ep.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("isNull() return true") {
|
||||
ep.add("hello");
|
||||
ep.clear();
|
||||
|
||||
REQUIRE(ep.isNull() == true);
|
||||
}
|
||||
}
|
28
extras/tests/ElementProxy/compare.cpp
Normal file
28
extras/tests/ElementProxy/compare.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::operator==()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("same value") {
|
||||
doc.add(1);
|
||||
doc.add(1);
|
||||
|
||||
REQUIRE(doc[0] == doc[1]);
|
||||
REQUIRE_FALSE(doc[0] != doc[1]);
|
||||
}
|
||||
|
||||
SECTION("different values") {
|
||||
doc.add(1);
|
||||
doc.add(2);
|
||||
|
||||
REQUIRE_FALSE(doc[0] == doc[1]);
|
||||
REQUIRE(doc[0] != doc[1]);
|
||||
}
|
||||
}
|
56
extras/tests/ElementProxy/remove.cpp
Normal file
56
extras/tests/ElementProxy/remove.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::remove()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
doc.addElement();
|
||||
ElementProxy<JsonDocument&> ep = doc[0];
|
||||
|
||||
SECTION("remove(int)") {
|
||||
ep.add(1);
|
||||
ep.add(2);
|
||||
ep.add(3);
|
||||
|
||||
ep.remove(1);
|
||||
|
||||
REQUIRE(ep.as<std::string>() == "[1,3]");
|
||||
}
|
||||
|
||||
SECTION("remove(const char *)") {
|
||||
ep["a"] = 1;
|
||||
ep["b"] = 2;
|
||||
|
||||
ep.remove("a");
|
||||
|
||||
REQUIRE(ep.as<std::string>() == "{\"b\":2}");
|
||||
}
|
||||
|
||||
SECTION("remove(std::string)") {
|
||||
ep["a"] = 1;
|
||||
ep["b"] = 2;
|
||||
|
||||
ep.remove(std::string("b"));
|
||||
|
||||
REQUIRE(ep.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("remove(vla)") {
|
||||
ep["a"] = 1;
|
||||
ep["b"] = 2;
|
||||
|
||||
int i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "b");
|
||||
ep.remove(vla);
|
||||
|
||||
REQUIRE(ep.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
#endif
|
||||
}
|
26
extras/tests/ElementProxy/set.cpp
Normal file
26
extras/tests/ElementProxy/set.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::set()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
doc.addElement();
|
||||
ElementProxy<JsonDocument&> ep = doc[0];
|
||||
|
||||
SECTION("set(int)") {
|
||||
ep.set(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[42]");
|
||||
}
|
||||
|
||||
SECTION("set(const char*)") {
|
||||
ep.set("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[\"world\"]");
|
||||
}
|
||||
}
|
30
extras/tests/ElementProxy/size.cpp
Normal file
30
extras/tests/ElementProxy/size.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::size()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
doc.addElement();
|
||||
ElementProxy<JsonDocument&> ep = doc[0];
|
||||
|
||||
SECTION("returns 0") {
|
||||
REQUIRE(ep.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("as an array, returns 2") {
|
||||
ep.add(1);
|
||||
ep.add(2);
|
||||
REQUIRE(ep.size() == 2);
|
||||
}
|
||||
|
||||
SECTION("as an object, returns 2") {
|
||||
ep["a"] = 1;
|
||||
ep["b"] = 2;
|
||||
REQUIRE(ep.size() == 2);
|
||||
}
|
||||
}
|
19
extras/tests/IntegrationTests/CMakeLists.txt
Normal file
19
extras/tests/IntegrationTests/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_executable(IntegrationTests
|
||||
gbathree.cpp
|
||||
issue772.cpp
|
||||
round_trip.cpp
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
target_compile_options(IntegrationTests
|
||||
PUBLIC
|
||||
-fsingle-precision-constant # issue 544
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(IntegrationTests catch)
|
||||
add_test(IntegrationTests IntegrationTests)
|
210
extras/tests/IntegrationTests/gbathree.cpp
Normal file
210
extras/tests/IntegrationTests/gbathree.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Gbathree") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
DeserializationError error = deserializeJson(
|
||||
doc,
|
||||
"{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,"
|
||||
"\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_"
|
||||
"baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":"
|
||||
"10000,\"actintensity1\":50,\"actintensity2\":255,\"measintensity\":"
|
||||
"255,\"calintensity\":255,\"pulses\":[50,50,50],\"act\":[2,1,2,2],"
|
||||
"\"red\":[2,2,2,2],\"detectors\":[[34,34,34,34],[34,34,34,34],[34,"
|
||||
"34,34,34],[34,34,34,34]],\"alta\":[2,2,2,2],\"altb\":[2,2,2,2],"
|
||||
"\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,"
|
||||
"15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],"
|
||||
"[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
SECTION("Success") {
|
||||
REQUIRE(error == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("ProtocolName") {
|
||||
REQUIRE("fluorescence" == root["protocol_name"]);
|
||||
}
|
||||
|
||||
SECTION("Repeats") {
|
||||
REQUIRE(1 == root["repeats"]);
|
||||
}
|
||||
|
||||
SECTION("Wait") {
|
||||
REQUIRE(0 == root["wait"]);
|
||||
}
|
||||
|
||||
SECTION("Measurements") {
|
||||
REQUIRE(3 == root["measurements"]);
|
||||
}
|
||||
|
||||
SECTION("Meas2_Light") {
|
||||
REQUIRE(15 == root["meas2_light"]);
|
||||
}
|
||||
|
||||
SECTION("Meas1_Baseline") {
|
||||
REQUIRE(0 == root["meas1_baseline"]);
|
||||
}
|
||||
|
||||
SECTION("Act_Light") {
|
||||
REQUIRE(20 == root["act_light"]);
|
||||
}
|
||||
|
||||
SECTION("Pulsesize") {
|
||||
REQUIRE(25 == root["pulsesize"]);
|
||||
}
|
||||
|
||||
SECTION("Pulsedistance") {
|
||||
REQUIRE(10000 == root["pulsedistance"]);
|
||||
}
|
||||
|
||||
SECTION("Actintensity1") {
|
||||
REQUIRE(50 == root["actintensity1"]);
|
||||
}
|
||||
|
||||
SECTION("Actintensity2") {
|
||||
REQUIRE(255 == root["actintensity2"]);
|
||||
}
|
||||
|
||||
SECTION("Measintensity") {
|
||||
REQUIRE(255 == root["measintensity"]);
|
||||
}
|
||||
|
||||
SECTION("Calintensity") {
|
||||
REQUIRE(255 == root["calintensity"]);
|
||||
}
|
||||
|
||||
SECTION("Pulses") {
|
||||
// "pulses":[50,50,50]
|
||||
|
||||
JsonArray array = root["pulses"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(3 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
REQUIRE(50 == array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Act") {
|
||||
// "act":[2,1,2,2]
|
||||
|
||||
JsonArray array = root["act"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(4 == array.size());
|
||||
REQUIRE(2 == array[0]);
|
||||
REQUIRE(1 == array[1]);
|
||||
REQUIRE(2 == array[2]);
|
||||
REQUIRE(2 == array[3]);
|
||||
}
|
||||
|
||||
SECTION("Detectors") {
|
||||
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
|
||||
|
||||
JsonArray array = root["detectors"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
JsonArray nestedArray = array[i];
|
||||
REQUIRE(4 == nestedArray.size());
|
||||
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
REQUIRE(34 == nestedArray[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Alta") {
|
||||
// alta:[2,2,2,2]
|
||||
|
||||
JsonArray array = root["alta"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
REQUIRE(2 == array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Altb") {
|
||||
// altb:[2,2,2,2]
|
||||
|
||||
JsonArray array = root["altb"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
REQUIRE(2 == array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Measlights") {
|
||||
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray array = root["measlights"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
JsonArray nestedArray = array[i];
|
||||
|
||||
REQUIRE(4 == nestedArray.size());
|
||||
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
REQUIRE(15 == nestedArray[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Measlights2") {
|
||||
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray array = root["measlights2"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
JsonArray nestedArray = array[i];
|
||||
REQUIRE(4 == nestedArray.size());
|
||||
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
REQUIRE(15 == nestedArray[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Altc") {
|
||||
// altc:[2,2,2,2]
|
||||
|
||||
JsonArray array = root["altc"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
REQUIRE(2 == array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Altd") {
|
||||
// altd:[2,2,2,2]
|
||||
|
||||
JsonArray array = root["altd"];
|
||||
REQUIRE(array.isNull() == false);
|
||||
|
||||
REQUIRE(4 == array.size());
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
REQUIRE(2 == array[i]);
|
||||
}
|
||||
}
|
||||
}
|
28
extras/tests/IntegrationTests/issue772.cpp
Normal file
28
extras/tests/IntegrationTests/issue772.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
// https://github.com/bblanchon/ArduinoJson/issues/772
|
||||
|
||||
TEST_CASE("Issue772") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err;
|
||||
std::string data =
|
||||
"{\"state\":{\"reported\":{\"timestamp\":\"2018-07-02T09:40:12Z\","
|
||||
"\"mac\":\"2C3AE84FC076\",\"firmwareVersion\":\"v0.2.7-5-gf4d4d78\","
|
||||
"\"visibleLight\":261,\"infraRed\":255,\"ultraViolet\":0.02,"
|
||||
"\"Temperature\":26.63,\"Pressure\":101145.7,\"Humidity\":54.79883,"
|
||||
"\"Vbat\":4.171261,\"soilMoisture\":0,\"ActB\":0}}}";
|
||||
err = deserializeJson(doc1, data);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
|
||||
data = "";
|
||||
serializeMsgPack(doc1, data);
|
||||
err = deserializeMsgPack(doc2, data);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
82
extras/tests/IntegrationTests/round_trip.cpp
Normal file
82
extras/tests/IntegrationTests/round_trip.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
void check(std::string originalJson) {
|
||||
DynamicJsonDocument doc(16384);
|
||||
|
||||
std::string prettyJson;
|
||||
deserializeJson(doc, originalJson);
|
||||
serializeJsonPretty(doc, prettyJson);
|
||||
|
||||
std::string finalJson;
|
||||
deserializeJson(doc, originalJson);
|
||||
serializeJson(doc, finalJson);
|
||||
|
||||
REQUIRE(originalJson == finalJson);
|
||||
}
|
||||
|
||||
TEST_CASE("Round Trip: parse -> prettyPrint -> parse -> print") {
|
||||
SECTION("OpenWeatherMap") {
|
||||
check(
|
||||
"{\"coord\":{\"lon\":145.77,\"lat\":-16.92},\"sys\":{\"type\":1,\"id\":"
|
||||
"8166,\"message\":0.1222,\"country\":\"AU\",\"sunrise\":1414784325,"
|
||||
"\"sunset\":1414830137},\"weather\":[{\"id\":801,\"main\":\"Clouds\","
|
||||
"\"description\":\"few clouds\",\"icon\":\"02n\"}],\"base\":\"cmc "
|
||||
"stations\",\"main\":{\"temp\":296.15,\"pressure\":1014,\"humidity\":"
|
||||
"83,\"temp_min\":296.15,\"temp_max\":296.15},\"wind\":{\"speed\":2.22,"
|
||||
"\"deg\":114.501},\"clouds\":{\"all\":20},\"dt\":1414846800,\"id\":"
|
||||
"2172797,\"name\":\"Cairns\",\"cod\":200}");
|
||||
}
|
||||
|
||||
SECTION("YahooQueryLanguage") {
|
||||
check(
|
||||
"{\"query\":{\"count\":40,\"created\":\"2014-11-01T14:16:49Z\","
|
||||
"\"lang\":\"fr-FR\",\"results\":{\"item\":[{\"title\":\"Burkina army "
|
||||
"backs Zida as interim leader\"},{\"title\":\"British jets intercept "
|
||||
"Russian bombers\"},{\"title\":\"Doubts chip away at nation's most "
|
||||
"trusted agencies\"},{\"title\":\"Cruise ship stuck off Norway, no "
|
||||
"damage\"},{\"title\":\"U.S. military launches 10 air strikes in "
|
||||
"Syria, Iraq\"},{\"title\":\"Blackout hits Bangladesh as line from "
|
||||
"India fails\"},{\"title\":\"Burkina Faso president in Ivory Coast "
|
||||
"after ouster\"},{\"title\":\"Kurds in Turkey rally to back city "
|
||||
"besieged by IS\"},{\"title\":\"A majority of Scots would vote for "
|
||||
"independence now:poll\"},{\"title\":\"Tunisia elections possible "
|
||||
"model for region\"},{\"title\":\"Islamic State kills 85 more members "
|
||||
"of Iraqi tribe\"},{\"title\":\"Iraqi officials:IS extremists line "
|
||||
"up, kill 50\"},{\"title\":\"Burkina Faso army backs presidential "
|
||||
"guard official to lead transition\"},{\"title\":\"Kurdish peshmerga "
|
||||
"arrive with weapons in Syria's Kobani\"},{\"title\":\"Driver sought "
|
||||
"in crash that killed 3 on Halloween\"},{\"title\":\"Ex-Marine arrives "
|
||||
"in US after release from Mexico jail\"},{\"title\":\"UN panel "
|
||||
"scrambling to finish climate report\"},{\"title\":\"Investigators, "
|
||||
"Branson go to spacecraft crash site\"},{\"title\":\"Soldiers vie for "
|
||||
"power after Burkina Faso president quits\"},{\"title\":\"For a man "
|
||||
"without a party, turnout is big test\"},{\"title\":\"'We just had a "
|
||||
"hunch':US marshals nab Eric Frein\"},{\"title\":\"Boko Haram leader "
|
||||
"threatens to kill German hostage\"},{\"title\":\"Nurse free to move "
|
||||
"about as restrictions eased\"},{\"title\":\"Former Burkina president "
|
||||
"Compaore arrives in Ivory Coast:sources\"},{\"title\":\"Libyan port "
|
||||
"rebel leader refuses to hand over oil ports to rival "
|
||||
"group\"},{\"title\":\"Iraqi peshmerga fighters prepare for Syria "
|
||||
"battle\"},{\"title\":\"1 Dem Senate candidate welcoming Obama's "
|
||||
"help\"},{\"title\":\"Bikers cancel party after police recover "
|
||||
"bar\"},{\"title\":\"New question in Texas:Can Davis survive "
|
||||
"defeat?\"},{\"title\":\"Ukraine rebels to hold election, despite "
|
||||
"criticism\"},{\"title\":\"Iraqi officials say Islamic State group "
|
||||
"lines up, kills 50 tribesmen, women in Anbar "
|
||||
"province\"},{\"title\":\"James rebounds, leads Cavaliers past "
|
||||
"Bulls\"},{\"title\":\"UK warns travelers they could be terror "
|
||||
"targets\"},{\"title\":\"Hello Kitty celebrates 40th "
|
||||
"birthday\"},{\"title\":\"A look at people killed during space "
|
||||
"missions\"},{\"title\":\"Nigeria's purported Boko Haram leader says "
|
||||
"has 'married off' girls:AFP\"},{\"title\":\"Mexico orders immediate "
|
||||
"release of Marine veteran\"},{\"title\":\"As election closes in, "
|
||||
"Obama on center stage\"},{\"title\":\"Body of Zambian president "
|
||||
"arrives home\"},{\"title\":\"South Africa arrests 2 Vietnamese for "
|
||||
"poaching\"}]}}}");
|
||||
}
|
||||
}
|
23
extras/tests/JsonArray/CMakeLists.txt
Normal file
23
extras/tests/JsonArray/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_executable(JsonArrayTests
|
||||
add.cpp
|
||||
copyArray.cpp
|
||||
createNested.cpp
|
||||
equals.cpp
|
||||
get.cpp
|
||||
isNull.cpp
|
||||
iterator.cpp
|
||||
memoryUsage.cpp
|
||||
nesting.cpp
|
||||
remove.cpp
|
||||
size.cpp
|
||||
std_string.cpp
|
||||
subscript.cpp
|
||||
undefined.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonArrayTests catch)
|
||||
add_test(JsonArray JsonArrayTests)
|
138
extras/tests/JsonArray/add.cpp
Normal file
138
extras/tests/JsonArray/add.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::add()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("int") {
|
||||
array.add(123);
|
||||
REQUIRE(123 == array[0].as<int>());
|
||||
REQUIRE(array[0].is<int>());
|
||||
REQUIRE(array[0].is<double>());
|
||||
}
|
||||
|
||||
SECTION("double") {
|
||||
array.add(123.45);
|
||||
REQUIRE(123.45 == array[0].as<double>());
|
||||
REQUIRE(array[0].is<double>());
|
||||
REQUIRE_FALSE(array[0].is<bool>());
|
||||
}
|
||||
|
||||
SECTION("bool") {
|
||||
array.add(true);
|
||||
REQUIRE(true == array[0].as<bool>());
|
||||
REQUIRE(array[0].is<bool>());
|
||||
REQUIRE_FALSE(array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
const char* str = "hello";
|
||||
array.add(str);
|
||||
REQUIRE(str == array[0].as<std::string>());
|
||||
REQUIRE(array[0].is<const char*>());
|
||||
REQUIRE_FALSE(array[0].is<int>());
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("vla") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
array.add(vla);
|
||||
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("nested array") {
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonArray arr = doc2.to<JsonArray>();
|
||||
|
||||
array.add(arr);
|
||||
|
||||
REQUIRE(arr == array[0].as<JsonArray>());
|
||||
REQUIRE(array[0].is<JsonArray>());
|
||||
REQUIRE_FALSE(array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("nested object") {
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
|
||||
array.add(obj);
|
||||
|
||||
REQUIRE(obj == array[0].as<JsonObject>());
|
||||
REQUIRE(array[0].is<JsonObject>());
|
||||
REQUIRE_FALSE(array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("array subscript") {
|
||||
const char* str = "hello";
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonArray arr = doc2.to<JsonArray>();
|
||||
arr.add(str);
|
||||
|
||||
array.add(arr[0]);
|
||||
|
||||
REQUIRE(str == array[0]);
|
||||
}
|
||||
|
||||
SECTION("object subscript") {
|
||||
const char* str = "hello";
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
obj["x"] = str;
|
||||
|
||||
array.add(obj["x"]);
|
||||
|
||||
REQUIRE(str == array[0]);
|
||||
}
|
||||
|
||||
SECTION("should not duplicate const char*") {
|
||||
array.add("world");
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate char*") {
|
||||
array.add(const_cast<char*>("world"));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate std::string") {
|
||||
array.add(std::string("world"));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should not duplicate serialized(const char*)") {
|
||||
array.add(serialized("{}"));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate serialized(char*)") {
|
||||
array.add(serialized(const_cast<char*>("{}")));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(2);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate serialized(std::string)") {
|
||||
array.add(serialized(std::string("{}")));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(2);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate serialized(std::string)") {
|
||||
array.add(serialized(std::string("\0XX", 3)));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(3);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
}
|
117
extras/tests/JsonArray/copyArray.cpp
Normal file
117
extras/tests/JsonArray/copyArray.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("copyArray()") {
|
||||
SECTION("1D -> JsonArray") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32];
|
||||
int source[] = {1, 2, 3};
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
REQUIRE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[1,2,3]") == json);
|
||||
}
|
||||
|
||||
SECTION("1D -> JsonArray, but not enough memory") {
|
||||
const size_t SIZE = JSON_ARRAY_SIZE(2);
|
||||
StaticJsonDocument<SIZE> doc;
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32];
|
||||
int source[] = {1, 2, 3};
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
REQUIRE_FALSE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[1,2]") == json);
|
||||
}
|
||||
|
||||
SECTION("2D -> JsonArray") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32];
|
||||
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
REQUIRE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[[1,2,3],[4,5,6]]") == json);
|
||||
}
|
||||
|
||||
SECTION("2D -> JsonArray, but not enough memory") {
|
||||
const size_t SIZE =
|
||||
JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2);
|
||||
StaticJsonDocument<SIZE> doc;
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32] = "";
|
||||
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
|
||||
CAPTURE(SIZE)
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
CAPTURE(doc.memoryUsage());
|
||||
CHECK_FALSE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[[1,2,3],[4,5]]") == json);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 1D, with more space than needed") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[1,2,3]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
|
||||
int destination[4] = {0};
|
||||
size_t result = copyArray(array, destination);
|
||||
|
||||
REQUIRE(3 == result);
|
||||
REQUIRE(1 == destination[0]);
|
||||
REQUIRE(2 == destination[1]);
|
||||
REQUIRE(3 == destination[2]);
|
||||
REQUIRE(0 == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 1D, without enough space") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[1,2,3]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
|
||||
int destination[2] = {0};
|
||||
size_t result = copyArray(array, destination);
|
||||
|
||||
REQUIRE(2 == result);
|
||||
REQUIRE(1 == destination[0]);
|
||||
REQUIRE(2 == destination[1]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 2D") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[[1,2],[3],[4]]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
|
||||
int destination[3][2] = {{0}};
|
||||
copyArray(array, destination);
|
||||
|
||||
REQUIRE(1 == destination[0][0]);
|
||||
REQUIRE(2 == destination[0][1]);
|
||||
REQUIRE(3 == destination[1][0]);
|
||||
REQUIRE(0 == destination[1][1]);
|
||||
REQUIRE(4 == destination[2][0]);
|
||||
REQUIRE(0 == destination[2][1]);
|
||||
}
|
||||
}
|
21
extras/tests/JsonArray/createNested.cpp
Normal file
21
extras/tests/JsonArray/createNested.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray basics") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("CreateNestedArray") {
|
||||
JsonArray arr = array.createNestedArray();
|
||||
REQUIRE(arr == array[0].as<JsonArray>());
|
||||
}
|
||||
|
||||
SECTION("CreateNestedObject") {
|
||||
JsonObject obj = array.createNestedObject();
|
||||
REQUIRE(obj == array[0].as<JsonObject>());
|
||||
}
|
||||
}
|
50
extras/tests/JsonArray/equals.cpp
Normal file
50
extras/tests/JsonArray/equals.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::operator==()") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
JsonArray array1 = doc1.to<JsonArray>();
|
||||
JsonArrayConst array1c = array1;
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonArray array2 = doc2.to<JsonArray>();
|
||||
JsonArrayConst array2c = array2;
|
||||
|
||||
SECTION("should return false when arrays differ") {
|
||||
array1.add("coucou");
|
||||
array2.add(1);
|
||||
|
||||
REQUIRE_FALSE(array1 == array2);
|
||||
REQUIRE_FALSE(array1c == array2c);
|
||||
}
|
||||
|
||||
SECTION("should return false when LHS has more elements") {
|
||||
array1.add(1);
|
||||
array1.add(2);
|
||||
array2.add(1);
|
||||
|
||||
REQUIRE_FALSE(array1 == array2);
|
||||
REQUIRE_FALSE(array1c == array2c);
|
||||
}
|
||||
|
||||
SECTION("should return false when RKS has more elements") {
|
||||
array1.add(1);
|
||||
array2.add(1);
|
||||
array2.add(2);
|
||||
|
||||
REQUIRE_FALSE(array1 == array2);
|
||||
REQUIRE_FALSE(array1c == array2c);
|
||||
}
|
||||
|
||||
SECTION("should return true when arrays equal") {
|
||||
array1.add("coucou");
|
||||
array2.add("coucou");
|
||||
|
||||
REQUIRE(array1 == array2);
|
||||
REQUIRE(array1c == array2c);
|
||||
}
|
||||
}
|
16
extras/tests/JsonArray/get.cpp
Normal file
16
extras/tests/JsonArray/get.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::get()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
deserializeJson(doc, "[1,2,3]");
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
|
||||
SECTION("Overflow") {
|
||||
REQUIRE(array.getElement(3).isNull());
|
||||
}
|
||||
}
|
34
extras/tests/JsonArray/isNull.cpp
Normal file
34
extras/tests/JsonArray/isNull.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::isNull()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("returns true") {
|
||||
JsonArray arr;
|
||||
REQUIRE(arr.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false") {
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
REQUIRE(arr.isNull() == false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonArrayConst::isNull()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("returns true") {
|
||||
JsonArrayConst arr;
|
||||
REQUIRE(arr.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false") {
|
||||
JsonArrayConst arr = doc.to<JsonArray>();
|
||||
REQUIRE(arr.isNull() == false);
|
||||
}
|
||||
}
|
36
extras/tests/JsonArray/iterator.cpp
Normal file
36
extras/tests/JsonArray/iterator.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
template <typename TArray>
|
||||
static void run_iterator_test() {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
|
||||
JsonArray tmp = doc.to<JsonArray>();
|
||||
tmp.add(12);
|
||||
tmp.add(34);
|
||||
|
||||
TArray array = tmp;
|
||||
typename TArray::iterator it = array.begin();
|
||||
typename TArray::iterator end = array.end();
|
||||
|
||||
REQUIRE(end != it);
|
||||
REQUIRE(12 == it->template as<int>());
|
||||
REQUIRE(12 == static_cast<int>(*it));
|
||||
++it;
|
||||
REQUIRE(end != it);
|
||||
REQUIRE(34 == it->template as<int>());
|
||||
REQUIRE(34 == static_cast<int>(*it));
|
||||
++it;
|
||||
REQUIRE(end == it);
|
||||
}
|
||||
|
||||
TEST_CASE("JsonArray::begin()/end()") {
|
||||
run_iterator_test<JsonArray>();
|
||||
}
|
||||
|
||||
TEST_CASE("JsonArrayConst::begin()/end()") {
|
||||
run_iterator_test<JsonArrayConst>();
|
||||
}
|
42
extras/tests/JsonArray/memoryUsage.cpp
Normal file
42
extras/tests/JsonArray/memoryUsage.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::memoryUsage()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
|
||||
SECTION("return 0 if uninitialized") {
|
||||
JsonArray unitialized;
|
||||
REQUIRE(unitialized.memoryUsage() == 0);
|
||||
}
|
||||
|
||||
SECTION("JSON_ARRAY_SIZE(0) if empty") {
|
||||
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("JSON_ARRAY_SIZE(1) after add") {
|
||||
arr.add("hello");
|
||||
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(1));
|
||||
}
|
||||
|
||||
SECTION("includes the size of the string") {
|
||||
arr.add(std::string("hello"));
|
||||
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(1) + 6);
|
||||
}
|
||||
|
||||
SECTION("includes the size of the nested array") {
|
||||
JsonArray nested = arr.createNestedArray();
|
||||
nested.add(42);
|
||||
REQUIRE(arr.memoryUsage() == 2 * JSON_ARRAY_SIZE(1));
|
||||
}
|
||||
|
||||
SECTION("includes the size of the nested arrect") {
|
||||
JsonObject nested = arr.createNestedObject();
|
||||
nested["hello"] = "world";
|
||||
REQUIRE(arr.memoryUsage() == JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1));
|
||||
}
|
||||
}
|
35
extras/tests/JsonArray/nesting.cpp
Normal file
35
extras/tests/JsonArray/nesting.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::nesting()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
|
||||
SECTION("return 0 if uninitialized") {
|
||||
JsonArray unitialized;
|
||||
REQUIRE(unitialized.nesting() == 0);
|
||||
}
|
||||
|
||||
SECTION("returns 1 for empty array") {
|
||||
REQUIRE(arr.nesting() == 1);
|
||||
}
|
||||
|
||||
SECTION("returns 1 for flat array") {
|
||||
arr.add("hello");
|
||||
REQUIRE(arr.nesting() == 1);
|
||||
}
|
||||
|
||||
SECTION("returns 2 with nested array") {
|
||||
arr.createNestedArray();
|
||||
REQUIRE(arr.nesting() == 2);
|
||||
}
|
||||
|
||||
SECTION("returns 2 with nested object") {
|
||||
arr.createNestedObject();
|
||||
REQUIRE(arr.nesting() == 2);
|
||||
}
|
||||
}
|
68
extras/tests/JsonArray/remove.cpp
Normal file
68
extras/tests/JsonArray/remove.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::remove()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray _array = doc.to<JsonArray>();
|
||||
_array.add(1);
|
||||
_array.add(2);
|
||||
_array.add(3);
|
||||
|
||||
SECTION("RemoveFirstByIndex") {
|
||||
_array.remove(0);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 2);
|
||||
REQUIRE(_array[1] == 3);
|
||||
}
|
||||
|
||||
SECTION("RemoveMiddleByIndex") {
|
||||
_array.remove(1);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 3);
|
||||
}
|
||||
|
||||
SECTION("RemoveLastByIndex") {
|
||||
_array.remove(2);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("RemoveFirstByIterator") {
|
||||
JsonArray::iterator it = _array.begin();
|
||||
_array.remove(it);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 2);
|
||||
REQUIRE(_array[1] == 3);
|
||||
}
|
||||
|
||||
SECTION("RemoveMiddleByIterator") {
|
||||
JsonArray::iterator it = _array.begin();
|
||||
++it;
|
||||
_array.remove(it);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 3);
|
||||
}
|
||||
|
||||
SECTION("RemoveLastByIterator") {
|
||||
JsonArray::iterator it = _array.begin();
|
||||
++it;
|
||||
++it;
|
||||
_array.remove(it);
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 2);
|
||||
}
|
||||
}
|
31
extras/tests/JsonArray/size.cpp
Normal file
31
extras/tests/JsonArray/size.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::size()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("returns 0 is empty") {
|
||||
REQUIRE(0U == array.size());
|
||||
}
|
||||
|
||||
SECTION("increases after add()") {
|
||||
array.add("hello");
|
||||
REQUIRE(1U == array.size());
|
||||
|
||||
array.add("world");
|
||||
REQUIRE(2U == array.size());
|
||||
}
|
||||
|
||||
SECTION("remains the same after replacing an element") {
|
||||
array.add("hello");
|
||||
REQUIRE(1U == array.size());
|
||||
|
||||
array[0] = "hello";
|
||||
REQUIRE(1U == array.size());
|
||||
}
|
||||
}
|
31
extras/tests/JsonArray/std_string.cpp
Normal file
31
extras/tests/JsonArray/std_string.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void eraseString(std::string &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
TEST_CASE("std::string") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("add()") {
|
||||
std::string value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("operator[]") {
|
||||
std::string value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
}
|
162
extras/tests/JsonArray/subscript.cpp
Normal file
162
extras/tests/JsonArray/subscript.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdint.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonArray::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
array.add(0);
|
||||
|
||||
SECTION("int") {
|
||||
array[0] = 123;
|
||||
REQUIRE(123 == array[0].as<int>());
|
||||
REQUIRE(true == array[0].is<int>());
|
||||
REQUIRE(false == array[0].is<bool>());
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
SECTION("long long") {
|
||||
array[0] = 9223372036854775807;
|
||||
REQUIRE(9223372036854775807 == array[0].as<int64_t>());
|
||||
REQUIRE(true == array[0].is<int64_t>());
|
||||
REQUIRE(false == array[0].is<int32_t>());
|
||||
REQUIRE(false == array[0].is<bool>());
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("double") {
|
||||
array[0] = 123.45;
|
||||
REQUIRE(123.45 == array[0].as<double>());
|
||||
REQUIRE(true == array[0].is<double>());
|
||||
REQUIRE(false == array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("bool") {
|
||||
array[0] = true;
|
||||
REQUIRE(true == array[0].as<bool>());
|
||||
REQUIRE(true == array[0].is<bool>());
|
||||
REQUIRE(false == array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
const char* str = "hello";
|
||||
|
||||
array[0] = str;
|
||||
REQUIRE(str == array[0].as<const char*>());
|
||||
REQUIRE(str == array[0].as<char*>()); // <- short hand
|
||||
REQUIRE(true == array[0].is<const char*>());
|
||||
REQUIRE(false == array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("nested array") {
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonArray arr2 = doc2.to<JsonArray>();
|
||||
|
||||
array[0] = arr2;
|
||||
|
||||
REQUIRE(arr2 == array[0].as<JsonArray>());
|
||||
REQUIRE(true == array[0].is<JsonArray>());
|
||||
REQUIRE(false == array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("nested object") {
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
|
||||
array[0] = obj;
|
||||
|
||||
REQUIRE(obj == array[0].as<JsonObject>());
|
||||
REQUIRE(true == array[0].is<JsonObject>());
|
||||
REQUIRE(false == array[0].is<int>());
|
||||
}
|
||||
|
||||
SECTION("array subscript") {
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonArray arr2 = doc2.to<JsonArray>();
|
||||
const char* str = "hello";
|
||||
|
||||
arr2.add(str);
|
||||
|
||||
array[0] = arr2[0];
|
||||
|
||||
REQUIRE(str == array[0]);
|
||||
}
|
||||
|
||||
SECTION("object subscript") {
|
||||
const char* str = "hello";
|
||||
DynamicJsonDocument doc2(4096);
|
||||
JsonObject obj = doc2.to<JsonObject>();
|
||||
|
||||
obj["x"] = str;
|
||||
|
||||
array[0] = obj["x"];
|
||||
|
||||
REQUIRE(str == array[0]);
|
||||
}
|
||||
|
||||
SECTION("should not duplicate const char*") {
|
||||
array[0] = "world";
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate char*") {
|
||||
array[0] = const_cast<char*>("world");
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate std::string") {
|
||||
array[0] = std::string("world");
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("array[0].to<JsonObject>()") {
|
||||
JsonObject obj = array[0].to<JsonObject>();
|
||||
REQUIRE(obj.isNull() == false);
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("set(VLA)") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
array.add("hello");
|
||||
array[0].set(vla);
|
||||
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
|
||||
SECTION("operator=(VLA)") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "world");
|
||||
|
||||
array.add("hello");
|
||||
array[0] = vla;
|
||||
|
||||
REQUIRE(std::string("world") == array[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("JsonArrayConst::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
array.add(0);
|
||||
|
||||
SECTION("int") {
|
||||
array[0] = 123;
|
||||
JsonArrayConst carr = array;
|
||||
|
||||
REQUIRE(123 == carr[0].as<int>());
|
||||
REQUIRE(true == carr[0].is<int>());
|
||||
REQUIRE(false == carr[0].is<bool>());
|
||||
}
|
||||
}
|
35
extras/tests/JsonArray/undefined.cpp
Normal file
35
extras/tests/JsonArray/undefined.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
TEST_CASE("Undefined JsonArray") {
|
||||
JsonArray array;
|
||||
|
||||
SECTION("SubscriptFails") {
|
||||
REQUIRE(array[0].isNull());
|
||||
}
|
||||
|
||||
SECTION("AddFails") {
|
||||
array.add(1);
|
||||
REQUIRE(0 == array.size());
|
||||
}
|
||||
|
||||
SECTION("CreateNestedArrayFails") {
|
||||
REQUIRE(array.createNestedArray().isNull());
|
||||
}
|
||||
|
||||
SECTION("CreateNestedObjectFails") {
|
||||
REQUIRE(array.createNestedObject().isNull());
|
||||
}
|
||||
|
||||
SECTION("PrintToWritesBrackets") {
|
||||
char buffer[32];
|
||||
serializeJson(array, buffer, sizeof(buffer));
|
||||
REQUIRE_THAT(buffer, Equals("null"));
|
||||
}
|
||||
}
|
21
extras/tests/JsonDeserializer/CMakeLists.txt
Normal file
21
extras/tests/JsonDeserializer/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_executable(JsonDeserializerTests
|
||||
array.cpp
|
||||
array_static.cpp
|
||||
DeserializationError.cpp
|
||||
incomplete_input.cpp
|
||||
input_types.cpp
|
||||
number.cpp
|
||||
invalid_input.cpp
|
||||
misc.cpp
|
||||
nestingLimit.cpp
|
||||
object.cpp
|
||||
object_static.cpp
|
||||
string.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonDeserializerTests catch)
|
||||
add_test(JsonDeserializer JsonDeserializerTests)
|
137
extras/tests/JsonDeserializer/DeserializationError.cpp
Normal file
137
extras/tests/JsonDeserializer/DeserializationError.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
void testStringification(DeserializationError error, std::string expected) {
|
||||
REQUIRE(error.c_str() == expected);
|
||||
}
|
||||
|
||||
void testBoolification(DeserializationError error, bool expected) {
|
||||
// DeserializationError on left-hand side
|
||||
CHECK(error == expected);
|
||||
CHECK(error != !expected);
|
||||
CHECK(!error == !expected);
|
||||
|
||||
// DeserializationError on right-hand side
|
||||
CHECK(expected == error);
|
||||
CHECK(!expected != error);
|
||||
CHECK(!expected == !error);
|
||||
}
|
||||
|
||||
#define TEST_STRINGIFICATION(symbol) \
|
||||
testStringification(DeserializationError::symbol, #symbol)
|
||||
|
||||
#define TEST_BOOLIFICATION(symbol, expected) \
|
||||
testBoolification(DeserializationError::symbol, expected)
|
||||
|
||||
TEST_CASE("DeserializationError") {
|
||||
SECTION("c_str()") {
|
||||
TEST_STRINGIFICATION(Ok);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
TEST_STRINGIFICATION(NotSupported);
|
||||
}
|
||||
|
||||
SECTION("as boolean") {
|
||||
TEST_BOOLIFICATION(Ok, false);
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(InvalidInput, true);
|
||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||
TEST_BOOLIFICATION(NotSupported, true);
|
||||
}
|
||||
|
||||
SECTION("ostream DeserializationError") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError(DeserializationError::InvalidInput);
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
}
|
||||
|
||||
SECTION("ostream DeserializationError::Code") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError::InvalidInput;
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
}
|
||||
|
||||
SECTION("out of range") {
|
||||
int code = 666;
|
||||
DeserializationError err(
|
||||
*reinterpret_cast<DeserializationError::Code*>(&code));
|
||||
REQUIRE(err.c_str() == std::string("???"));
|
||||
}
|
||||
|
||||
SECTION("switch") {
|
||||
DeserializationError err = DeserializationError::InvalidInput;
|
||||
switch (err.code()) {
|
||||
case DeserializationError::InvalidInput:
|
||||
SUCCEED();
|
||||
break;
|
||||
default:
|
||||
FAIL();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Comparisons") {
|
||||
DeserializationError invalidInput(DeserializationError::InvalidInput);
|
||||
DeserializationError ok(DeserializationError::Ok);
|
||||
|
||||
SECTION("DeserializationError == bool") {
|
||||
REQUIRE(invalidInput == true);
|
||||
REQUIRE(ok == false);
|
||||
}
|
||||
|
||||
SECTION("bool == DeserializationError") {
|
||||
REQUIRE(true == invalidInput);
|
||||
REQUIRE(false == ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError != bool") {
|
||||
REQUIRE(invalidInput != false);
|
||||
REQUIRE(ok != true);
|
||||
}
|
||||
|
||||
SECTION("bool != DeserializationError") {
|
||||
REQUIRE(false != invalidInput);
|
||||
REQUIRE(true != ok);
|
||||
}
|
||||
|
||||
SECTION("Negations") {
|
||||
REQUIRE(!invalidInput == false);
|
||||
REQUIRE(!ok == true);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError == Code") {
|
||||
REQUIRE(invalidInput == DeserializationError::InvalidInput);
|
||||
REQUIRE(ok == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Code == DeserializationError") {
|
||||
REQUIRE(DeserializationError::InvalidInput == invalidInput);
|
||||
REQUIRE(DeserializationError::Ok == ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError != Code") {
|
||||
REQUIRE(invalidInput != DeserializationError::Ok);
|
||||
REQUIRE(ok != DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Code != DeserializationError") {
|
||||
REQUIRE(DeserializationError::Ok != invalidInput);
|
||||
REQUIRE(DeserializationError::InvalidInput != ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError == DeserializationError") {
|
||||
REQUIRE_FALSE(invalidInput == ok);
|
||||
}
|
||||
|
||||
SECTION("DeserializationError != DeserializationError") {
|
||||
REQUIRE(invalidInput != ok);
|
||||
}
|
||||
}
|
||||
}
|
402
extras/tests/JsonDeserializer/array.cpp
Normal file
402
extras/tests/JsonDeserializer/array.cpp
Normal file
@ -0,0 +1,402 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON array") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("An empty array") {
|
||||
DeserializationError err = deserializeJson(doc, "[]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(0 == arr.size());
|
||||
}
|
||||
|
||||
SECTION("Spaces") {
|
||||
SECTION("Before the opening bracket") {
|
||||
DeserializationError err = deserializeJson(doc, " []");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(0 == arr.size());
|
||||
}
|
||||
|
||||
SECTION("Before first value") {
|
||||
DeserializationError err = deserializeJson(doc, "[ \t\r\n42]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == 42);
|
||||
}
|
||||
|
||||
SECTION("After first value") {
|
||||
DeserializationError err = deserializeJson(doc, "[42 \t\r\n]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Values types") {
|
||||
SECTION("On integer") {
|
||||
DeserializationError err = deserializeJson(doc, "[42]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == 42);
|
||||
}
|
||||
|
||||
SECTION("Two integers") {
|
||||
DeserializationError err = deserializeJson(doc, "[42,84]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == 42);
|
||||
REQUIRE(arr[1] == 84);
|
||||
}
|
||||
|
||||
SECTION("Double") {
|
||||
DeserializationError err = deserializeJson(doc, "[4.2,1e2]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == 4.2);
|
||||
REQUIRE(arr[1] == 1e2);
|
||||
}
|
||||
|
||||
SECTION("Unsigned long") {
|
||||
DeserializationError err = deserializeJson(doc, "[4294967295]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == 4294967295UL);
|
||||
}
|
||||
|
||||
SECTION("Boolean") {
|
||||
DeserializationError err = deserializeJson(doc, "[true,false]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == true);
|
||||
REQUIRE(arr[1] == false);
|
||||
}
|
||||
|
||||
SECTION("Null") {
|
||||
DeserializationError err = deserializeJson(doc, "[null,null]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0].as<char*>() == 0);
|
||||
REQUIRE(arr[1].as<char*>() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Quotes") {
|
||||
SECTION("Double quotes") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[ \"hello\" , \"world\" ]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("Single quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "[ 'hello' , 'world' ]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("No quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "[ hello , world ]");
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Double quotes (empty strings)") {
|
||||
DeserializationError err = deserializeJson(doc, "[\"\",\"\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "");
|
||||
REQUIRE(arr[1] == "");
|
||||
}
|
||||
|
||||
SECTION("Single quotes (empty strings)") {
|
||||
DeserializationError err = deserializeJson(doc, "[\'\',\'\']");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "");
|
||||
REQUIRE(arr[1] == "");
|
||||
}
|
||||
|
||||
SECTION("No quotes (empty strings)") {
|
||||
DeserializationError err = deserializeJson(doc, "[,]");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Closing single quotes missing") {
|
||||
DeserializationError err = deserializeJson(doc, "[\"]");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Closing double quotes missing") {
|
||||
DeserializationError err = deserializeJson(doc, "[\']");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Block comments") {
|
||||
SECTION("Before opening bracket") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "/*COMMENT*/ [\"hello\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("After opening bracket") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[/*COMMENT*/ \"hello\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("Before closing bracket") {
|
||||
DeserializationError err = deserializeJson(doc, "[\"hello\"/*COMMENT*/]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("After closing bracket") {
|
||||
DeserializationError err = deserializeJson(doc, "[\"hello\"]/*COMMENT*/");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[\"hello\"/*COMMENT*/,\"world\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[\"hello\",/*COMMENT*/ \"world\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("/*/") {
|
||||
DeserializationError err = deserializeJson(doc, "[/*/\n]");
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Unfinished comment") {
|
||||
DeserializationError err = deserializeJson(doc, "[/*COMMENT]");
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Final slash missing") {
|
||||
DeserializationError err = deserializeJson(doc, "[/*COMMENT*]");
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Trailing comments") {
|
||||
SECTION("Before opening bracket") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "//COMMENT\n\t[\"hello\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("After opening bracket") {
|
||||
DeserializationError err = deserializeJson(doc, "[//COMMENT\n\"hello\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("Before closing bracket") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[\"hello\"//COMMENT\r\n]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("After closing bracket") {
|
||||
DeserializationError err = deserializeJson(doc, "[\"hello\"]//COMMENT\n");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[\"hello\"//COMMENT\n,\"world\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "[\"hello\",//COMMENT\n\"world\"]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(2 == arr.size());
|
||||
REQUIRE(arr[0] == "hello");
|
||||
REQUIRE(arr[1] == "world");
|
||||
}
|
||||
|
||||
SECTION("Invalid comment") {
|
||||
DeserializationError err = deserializeJson(doc, "[/COMMENT\n]");
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("End document with comment") {
|
||||
DeserializationError err = deserializeJson(doc, "[//COMMENT");
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null-terminator") {
|
||||
SECTION("After opening bracket") {
|
||||
DeserializationError err = deserializeJson(doc, "[");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
DeserializationError err = deserializeJson(doc, "[1");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(doc, "[1,");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature end of input") {
|
||||
const char* input = "[1,2]";
|
||||
|
||||
SECTION("After opening bracket") {
|
||||
DeserializationError err = deserializeJson(doc, input, 1);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
DeserializationError err = deserializeJson(doc, input, 2);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(doc, input, 3);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("Nested objects") {
|
||||
char jsonString[] =
|
||||
" [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, jsonString);
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
JsonObject object1 = arr[0];
|
||||
const JsonObject object2 = arr[1];
|
||||
JsonObject object3 = arr[2];
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
|
||||
REQUIRE(object1.isNull() == false);
|
||||
REQUIRE(object2.isNull() == false);
|
||||
REQUIRE(object3.isNull() == true);
|
||||
|
||||
REQUIRE(2 == object1.size());
|
||||
REQUIRE(2 == object2.size());
|
||||
REQUIRE(0 == object3.size());
|
||||
|
||||
REQUIRE(1 == object1["a"].as<int>());
|
||||
REQUIRE(2 == object1["b"].as<int>());
|
||||
REQUIRE(3 == object2["c"].as<int>());
|
||||
REQUIRE(4 == object2["d"].as<int>());
|
||||
REQUIRE(0 == object3["e"].as<int>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonArray") {
|
||||
deserializeJson(doc, "[1,2,3,4]");
|
||||
deserializeJson(doc, "[]");
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(arr.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
}
|
89
extras/tests/JsonDeserializer/array_static.cpp
Normal file
89
extras/tests/JsonDeserializer/array_static.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
SECTION("BufferOfTheRightSizeForEmptyArray") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "[]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForArrayWithOneValue") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "[1]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithOneValue") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
char input[] = "[1]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForArrayWithNestedObject") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0) + JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "[{}]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForArrayWithNestedObject") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "[{}]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("CopyStringNotSpaces") {
|
||||
StaticJsonDocument<100> doc;
|
||||
|
||||
deserializeJson(doc, " [ \"1234567\" ] ");
|
||||
|
||||
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(8) == doc.memoryUsage());
|
||||
// note: we use a string of 8 bytes to be sure that the StaticMemoryPool
|
||||
// will not insert bytes to enforce alignement
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonArray") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(4)> doc;
|
||||
char input[] = "[1,2,3,4]";
|
||||
|
||||
deserializeJson(doc, input);
|
||||
deserializeJson(doc, "[]");
|
||||
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
REQUIRE(arr.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Array") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
|
||||
char input[] = "[1,2]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonArray>());
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
|
||||
REQUIRE(arr[0] == 1);
|
||||
REQUIRE(arr[1] == 2);
|
||||
}
|
||||
}
|
27
extras/tests/JsonDeserializer/incomplete_input.cpp
Normal file
27
extras/tests/JsonDeserializer/incomplete_input.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Truncated JSON input") {
|
||||
const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000",
|
||||
// false
|
||||
"f", "fa", "fal", "fals",
|
||||
// true
|
||||
"t", "tr", "tru",
|
||||
// null
|
||||
"n", "nu", "nul"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) ==
|
||||
DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
115
extras/tests/JsonDeserializer/input_types.cpp
Normal file
115
extras/tests/JsonDeserializer/input_types.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("deserializeJson(const std::string&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("should accept const string") {
|
||||
const std::string input("[42]");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should accept temporary string") {
|
||||
DeserializationError err = deserializeJson(doc, std::string("[42]"));
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("should duplicate content") {
|
||||
std::string input("[\"hello\"]");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
input[2] = 'X'; // alter the string tomake sure we made a copy
|
||||
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(std::string("hello") == array[0]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(std::istream&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("array") {
|
||||
std::istringstream json(" [ 42 /* comment */ ] ");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
JsonArray arr = doc.as<JsonArray>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == arr.size());
|
||||
REQUIRE(42 == arr[0]);
|
||||
}
|
||||
|
||||
SECTION("object") {
|
||||
std::istringstream json(" { hello : 'world' // comment\n }");
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(1 == obj.size());
|
||||
REQUIRE(std::string("world") == obj["hello"]);
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace of an empty object") {
|
||||
std::istringstream json("{}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing brace") {
|
||||
std::istringstream json("{\"hello\":\"world\"}123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket of an empty array") {
|
||||
std::istringstream json("[]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing bracket") {
|
||||
std::istringstream json("[\"hello\",\"world\"]123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
|
||||
SECTION("Should not read after the closing quote") {
|
||||
std::istringstream json("\"hello\"123");
|
||||
|
||||
deserializeJson(doc, json);
|
||||
|
||||
REQUIRE('1' == char(json.get()));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
TEST_CASE("deserializeJson(VLA)") {
|
||||
int i = 9;
|
||||
char vla[i];
|
||||
strcpy(vla, "{\"a\":42}");
|
||||
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
DeserializationError err = deserializeJson(doc, vla);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
#endif
|
35
extras/tests/JsonDeserializer/invalid_input.cpp
Normal file
35
extras/tests/JsonDeserializer/invalid_input.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Invalid JSON input") {
|
||||
const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'", "'\\u000G'",
|
||||
"'\\u000/'", "\\x1234", "6a9", "1,",
|
||||
"2]", "3}"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid JSON input that should pass") {
|
||||
const char* testCases[] = {"nulL", "tru3", "fals3"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::Ok);
|
||||
}
|
||||
}
|
143
extras/tests/JsonDeserializer/misc.cpp
Normal file
143
extras/tests/JsonDeserializer/misc.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Edge cases") {
|
||||
SECTION("null char*") {
|
||||
DeserializationError err = deserializeJson(doc, static_cast<char*>(0));
|
||||
|
||||
REQUIRE(err != DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("null const char*") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, static_cast<const char*>(0));
|
||||
|
||||
REQUIRE(err != DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Empty input") {
|
||||
DeserializationError err = deserializeJson(doc, "");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("issue #628") {
|
||||
DeserializationError err = deserializeJson(doc, "null");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == false);
|
||||
}
|
||||
|
||||
SECTION("Garbage") {
|
||||
DeserializationError err = deserializeJson(doc, "%*$£¤");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Booleans") {
|
||||
SECTION("True") {
|
||||
DeserializationError err = deserializeJson(doc, "true");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<bool>());
|
||||
REQUIRE(doc.as<bool>() == true);
|
||||
}
|
||||
|
||||
SECTION("False") {
|
||||
DeserializationError err = deserializeJson(doc, "false");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<bool>());
|
||||
REQUIRE(doc.as<bool>() == false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Comments") {
|
||||
SECTION("Just a trailing comment") {
|
||||
DeserializationError err = deserializeJson(doc, "// comment");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a block comment") {
|
||||
DeserializationError err = deserializeJson(doc, "/*comment*/");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a slash") {
|
||||
DeserializationError err = deserializeJson(doc, "/");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null-terminator") {
|
||||
SECTION("In escape sequence") {
|
||||
DeserializationError err = deserializeJson(doc, "\"\\");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In block comment") {
|
||||
DeserializationError err = deserializeJson(doc, "/* comment");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "\"hello");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "'hello");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature end of input") {
|
||||
SECTION("In escape sequence") {
|
||||
DeserializationError err = deserializeJson(doc, "\"\\n\"", 2);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In block comment") {
|
||||
DeserializationError err = deserializeJson(doc, "/* comment */", 10);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In double quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "\"hello\"", 6);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("In single quoted string") {
|
||||
DeserializationError err = deserializeJson(doc, "'hello'", 6);
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonVariant") {
|
||||
deserializeJson(doc, "[1,2,3]");
|
||||
deserializeJson(doc, "{}");
|
||||
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
}
|
101
extras/tests/JsonDeserializer/nestingLimit.cpp
Normal file
101
extras/tests/JsonDeserializer/nestingLimit.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
#define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression);
|
||||
#define SHOULD_FAIL(expression) \
|
||||
REQUIRE(DeserializationError::TooDeep == expression);
|
||||
|
||||
TEST_CASE("JsonDeserializer nesting") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Input = const char*") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, "\"toto\"", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "123", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "true", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("char* and size_t") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, "\"toto\"", 6, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "123", 3, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "true", 4, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[]", 2, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{}", 2, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", 8, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", 8, nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", 10, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", 11, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", 11, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", 10, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", 12, nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Input = std::string") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("\"toto\""), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("123"), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("true"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("[\"toto\"]"), nesting));
|
||||
SHOULD_WORK(deserializeJson(doc, std::string("{\"toto\":1}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":{}}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("{\"toto\":[]}"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[[\"toto\"]]"), nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, std::string("[{\"toto\":1}]"), nesting));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Input = std::istream") {
|
||||
SECTION("limit = 0") {
|
||||
DeserializationOption::NestingLimit nesting(0);
|
||||
std::istringstream good("true");
|
||||
std::istringstream bad("[]");
|
||||
SHOULD_WORK(deserializeJson(doc, good, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
|
||||
}
|
||||
|
||||
SECTION("limit = 1") {
|
||||
DeserializationOption::NestingLimit nesting(1);
|
||||
std::istringstream good("[\"toto\"]");
|
||||
std::istringstream bad("{\"toto\":{}}");
|
||||
SHOULD_WORK(deserializeJson(doc, good, nesting));
|
||||
SHOULD_FAIL(deserializeJson(doc, bad, nesting));
|
||||
}
|
||||
}
|
||||
}
|
133
extras/tests/JsonDeserializer/number.cpp
Normal file
133
extras/tests/JsonDeserializer/number.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#define ARDUINOJSON_ENABLE_NAN 1
|
||||
#define ARDUINOJSON_ENABLE_INFINITY 1
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <limits.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
namespace my {
|
||||
using ARDUINOJSON_NAMESPACE::isinf;
|
||||
using ARDUINOJSON_NAMESPACE::isnan;
|
||||
} // namespace my
|
||||
|
||||
TEST_CASE("deserialize an integer") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("Integer") {
|
||||
SECTION("0") {
|
||||
DeserializationError err = deserializeJson(doc, "0");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<int>() == true);
|
||||
REQUIRE(doc.as<int>() == 0);
|
||||
REQUIRE(doc.as<std::string>() == "0"); // issue #808
|
||||
}
|
||||
|
||||
SECTION("Negative") {
|
||||
DeserializationError err = deserializeJson(doc, "-42");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<int>());
|
||||
REQUIRE_FALSE(doc.is<bool>());
|
||||
REQUIRE(doc.as<int>() == -42);
|
||||
}
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
SECTION("LONG_MAX") {
|
||||
DeserializationError err = deserializeJson(doc, "2147483647");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == true);
|
||||
REQUIRE(doc.as<long>() == LONG_MAX);
|
||||
}
|
||||
|
||||
SECTION("LONG_MAX + 1") {
|
||||
DeserializationError err = deserializeJson(doc, "2147483648");
|
||||
|
||||
CAPTURE(LONG_MIN);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LONG_MIN == -2147483648
|
||||
SECTION("LONG_MIN") {
|
||||
DeserializationError err = deserializeJson(doc, "-2147483648");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == true);
|
||||
REQUIRE(doc.as<long>() == LONG_MIN);
|
||||
}
|
||||
|
||||
SECTION("LONG_MIN - 1") {
|
||||
DeserializationError err = deserializeJson(doc, "-2147483649");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == 4294967295
|
||||
SECTION("ULONG_MAX") {
|
||||
DeserializationError err = deserializeJson(doc, "4294967295");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<unsigned long>() == true);
|
||||
REQUIRE(doc.as<unsigned long>() == ULONG_MAX);
|
||||
REQUIRE(doc.is<long>() == false);
|
||||
}
|
||||
|
||||
SECTION("ULONG_MAX + 1") {
|
||||
DeserializationError err = deserializeJson(doc, "4294967296");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<unsigned long>() == false);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("Floats") {
|
||||
SECTION("Double") {
|
||||
DeserializationError err = deserializeJson(doc, "-1.23e+4");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE_FALSE(doc.is<int>());
|
||||
REQUIRE(doc.is<double>());
|
||||
REQUIRE(doc.as<double>() == Approx(-1.23e+4));
|
||||
}
|
||||
|
||||
SECTION("NaN") {
|
||||
DeserializationError err = deserializeJson(doc, "NaN");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isnan(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("+Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "+Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
|
||||
SECTION("-Infinity") {
|
||||
DeserializationError err = deserializeJson(doc, "-Infinity");
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<float>() == true);
|
||||
REQUIRE(my::isinf(doc.as<float>()));
|
||||
}
|
||||
}
|
||||
}
|
498
extras/tests/JsonDeserializer/object.cpp
Normal file
498
extras/tests/JsonDeserializer/object.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON object") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("An empty object") {
|
||||
DeserializationError err = deserializeJson(doc, "{}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Quotes") {
|
||||
SECTION("Double quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\":\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Single quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{'key':'value'}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("No quotes") {
|
||||
DeserializationError err = deserializeJson(doc, "{key:'value'}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("No quotes, allow underscore in key") {
|
||||
DeserializationError err = deserializeJson(doc, "{_k_e_y_:42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["_k_e_y_"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Spaces") {
|
||||
SECTION("Before the key") {
|
||||
DeserializationError err = deserializeJson(doc, "{ \"key\":\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("After the key") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\" :\"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Before the value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\": \"value\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("After the value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\":\"value\" }");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 1);
|
||||
REQUIRE(obj["key"] == "value");
|
||||
}
|
||||
|
||||
SECTION("Before the colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
|
||||
SECTION("After the colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Values types") {
|
||||
SECTION("String") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == "value1");
|
||||
REQUIRE(obj["key2"] == "value2");
|
||||
}
|
||||
|
||||
SECTION("Integer") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":42,\"key2\":-42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == 42);
|
||||
REQUIRE(obj["key2"] == -42);
|
||||
}
|
||||
|
||||
SECTION("Double") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":12.345,\"key2\":-7E89}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == 12.345);
|
||||
REQUIRE(obj["key2"] == -7E89);
|
||||
}
|
||||
|
||||
SECTION("Booleans") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":true,\"key2\":false}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"] == true);
|
||||
REQUIRE(obj["key2"] == false);
|
||||
}
|
||||
|
||||
SECTION("Null") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"key1\":null,\"key2\":null}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 2);
|
||||
REQUIRE(obj["key1"].as<char*>() == 0);
|
||||
REQUIRE(obj["key2"].as<char*>() == 0);
|
||||
}
|
||||
|
||||
SECTION("Array") {
|
||||
char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } ";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, jsonString);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
JsonArray array1 = obj["ab"];
|
||||
const JsonArray array2 = obj["cd"];
|
||||
JsonArray array3 = obj["ef"];
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
|
||||
REQUIRE(array1.isNull() == false);
|
||||
REQUIRE(array2.isNull() == false);
|
||||
REQUIRE(array3.isNull() == true);
|
||||
|
||||
REQUIRE(2 == array1.size());
|
||||
REQUIRE(2 == array2.size());
|
||||
REQUIRE(0 == array3.size());
|
||||
|
||||
REQUIRE(1 == array1[0].as<int>());
|
||||
REQUIRE(2 == array1[1].as<int>());
|
||||
|
||||
REQUIRE(3 == array2[0].as<int>());
|
||||
REQUIRE(4 == array2[1].as<int>());
|
||||
|
||||
REQUIRE(0 == array3[0].as<int>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Premature null terminator") {
|
||||
SECTION("After opening brace") {
|
||||
DeserializationError err = deserializeJson(doc, "{");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After key") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\"");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\",");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Misc") {
|
||||
SECTION("A quoted key without value") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("A non-quoted key without value") {
|
||||
DeserializationError err = deserializeJson(doc, "{key}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("A dangling comma") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"key1\":\"value1\",}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("null as a key") {
|
||||
DeserializationError err = deserializeJson(doc, "{null:\"value\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Repeated key") {
|
||||
DeserializationError err = deserializeJson(doc, "{a:{b:{c:1}},a:2}");
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Block comments") {
|
||||
SECTION("Before opening brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "/*COMMENT*/ {\"hello\":\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{/*COMMENT*/\"hello\":\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\"/*COMMENT*/:\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":/*COMMENT*/\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"/*COMMENT*/}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}/*COMMENT*/");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
DeserializationError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\"/*COMMENT*/,\"answer\":42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\",/*COMMENT*/\"answer\":42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Trailing comments") {
|
||||
SECTION("Before opening brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "//COMMENT\n {\"hello\":\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{//COMMENT\n\"hello\":\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\"//COMMENT\n:\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\"://COMMENT\n\"world\"}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"//COMMENT\n}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}//COMMENT\n");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
DeserializationError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\"//COMMENT\n,\"answer\":42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err = deserializeJson(
|
||||
doc, "{\"hello\":\"world\",//COMMENT\n\"answer\":42}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
REQUIRE(obj["answer"] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Dangling slash") {
|
||||
SECTION("Before opening brace") {
|
||||
DeserializationError err = deserializeJson(doc, "/{\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After opening brace") {
|
||||
DeserializationError err = deserializeJson(doc, "{/\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Before colon") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\"/:\"world\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After colon") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":/\"world\"}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("Before closing brace") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"/}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After closing brace") {
|
||||
DeserializationError err = deserializeJson(doc, "{\"hello\":\"world\"}/");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(obj["hello"] == "world");
|
||||
}
|
||||
|
||||
SECTION("Before comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\"/,\"answer\":42}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
|
||||
SECTION("After comma") {
|
||||
DeserializationError err =
|
||||
deserializeJson(doc, "{\"hello\":\"world\",/\"answer\":42}");
|
||||
|
||||
REQUIRE(err == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
||||
deserializeJson(doc, "{}");
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
REQUIRE(doc.is<JsonObject>());
|
||||
REQUIRE(obj.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
}
|
64
extras/tests/JsonDeserializer/object_static.cpp
Normal file
64
extras/tests/JsonDeserializer/object_static.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserialize JSON object with StaticJsonDocument") {
|
||||
SECTION("BufferOfTheRightSizeForEmptyObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "{}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForObjectWithOneValue") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":1}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithOneValue") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
char input[] = "{\"a\":1}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("TooSmallBufferForObjectWithNestedObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0) + JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":[]}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("BufferOfTheRightSizeForObjectWithNestedObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0)> doc;
|
||||
char input[] = "{\"a\":[]}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
}
|
||||
|
||||
SECTION("Should clear the JsonObject") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
|
||||
char input[] = "{\"hello\":\"world\"}";
|
||||
|
||||
deserializeJson(doc, input);
|
||||
deserializeJson(doc, "{}");
|
||||
|
||||
REQUIRE(doc.as<JsonObject>().size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
}
|
72
extras/tests/JsonDeserializer/string.cpp
Normal file
72
extras/tests/JsonDeserializer/string.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_DECODE_UNICODE 1
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("Valid JSON strings value") {
|
||||
struct TestCase {
|
||||
const char* input;
|
||||
const char* expectedOutput;
|
||||
};
|
||||
|
||||
TestCase testCases[] = {
|
||||
{"\"hello world\"", "hello world"},
|
||||
{"\'hello world\'", "hello world"},
|
||||
{"\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"", "1\"2\\3/4\b5\f6\n7\r8\t9"},
|
||||
{"'\\u0041'", "A"},
|
||||
{"'\\u00e4'", "\xc3\xa4"}, // ä
|
||||
{"'\\u00E4'", "\xc3\xa4"}, // ä
|
||||
{"'\\u3042'", "\xe3\x81\x82"}, // あ
|
||||
|
||||
};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const TestCase& testCase = testCases[i];
|
||||
CAPTURE(testCase.input);
|
||||
DeserializationError err = deserializeJson(doc, testCase.input);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.as<std::string>() == testCase.expectedOutput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Truncated JSON string") {
|
||||
const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) ==
|
||||
DeserializationError::IncompleteInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid JSON string") {
|
||||
const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'",
|
||||
"'\\u000G'", "'\\u000/'", "\\x1234"};
|
||||
const size_t testCount = sizeof(testCases) / sizeof(testCases[0]);
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
for (size_t i = 0; i < testCount; i++) {
|
||||
const char* input = testCases[i];
|
||||
CAPTURE(input);
|
||||
REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Not enough room to duplicate the string") {
|
||||
DynamicJsonDocument doc(4);
|
||||
|
||||
REQUIRE(deserializeJson(doc, "\"hello world!\"") ==
|
||||
DeserializationError::NoMemory);
|
||||
REQUIRE(doc.isNull() == true);
|
||||
}
|
49
extras/tests/JsonDocument/BasicJsonDocument.cpp
Normal file
49
extras/tests/JsonDocument/BasicJsonDocument.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdlib.h> // malloc, free
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
using ARDUINOJSON_NAMESPACE::addPadding;
|
||||
|
||||
class SpyingAllocator {
|
||||
public:
|
||||
SpyingAllocator(std::ostream& log) : _log(log) {}
|
||||
|
||||
void* allocate(size_t n) {
|
||||
_log << "A" << n;
|
||||
return malloc(n);
|
||||
}
|
||||
void deallocate(void* p) {
|
||||
_log << "F";
|
||||
free(p);
|
||||
}
|
||||
|
||||
private:
|
||||
SpyingAllocator& operator=(const SpyingAllocator& src);
|
||||
|
||||
std::ostream& _log;
|
||||
};
|
||||
|
||||
typedef BasicJsonDocument<SpyingAllocator> MyJsonDocument;
|
||||
|
||||
TEST_CASE("BasicJsonDocument") {
|
||||
std::stringstream log;
|
||||
|
||||
SECTION("Construct/Destruct") {
|
||||
{ MyJsonDocument doc(4096, log); }
|
||||
REQUIRE(log.str() == "A4096F");
|
||||
}
|
||||
|
||||
SECTION("Copy construct") {
|
||||
{
|
||||
MyJsonDocument doc1(4096, log);
|
||||
doc1.set(std::string("The size of this string is 32!!"));
|
||||
MyJsonDocument doc2(doc1);
|
||||
}
|
||||
REQUIRE(log.str() == "A4096A32FF");
|
||||
}
|
||||
}
|
21
extras/tests/JsonDocument/CMakeLists.txt
Normal file
21
extras/tests/JsonDocument/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
add_executable(JsonDocumentTests
|
||||
add.cpp
|
||||
BasicJsonDocument.cpp
|
||||
compare.cpp
|
||||
containsKey.cpp
|
||||
createNested.cpp
|
||||
DynamicJsonDocument.cpp
|
||||
isNull.cpp
|
||||
nesting.cpp
|
||||
remove.cpp
|
||||
size.cpp
|
||||
StaticJsonDocument.cpp
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonDocumentTests catch)
|
||||
add_test(JsonDocument JsonDocumentTests)
|
209
extras/tests/JsonDocument/DynamicJsonDocument.cpp
Normal file
209
extras/tests/JsonDocument/DynamicJsonDocument.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using ARDUINOJSON_NAMESPACE::addPadding;
|
||||
|
||||
static void REQUIRE_JSON(JsonDocument& doc, const std::string& expected) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
REQUIRE(json == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("DynamicJsonDocument") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("serializeJson()") {
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
obj["hello"] = "world";
|
||||
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("memoryUsage()") {
|
||||
SECTION("starts at zero") {
|
||||
REQUIRE(doc.memoryUsage() == 0);
|
||||
}
|
||||
|
||||
SECTION("JSON_ARRAY_SIZE(0)") {
|
||||
doc.to<JsonArray>();
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("JSON_ARRAY_SIZE(1)") {
|
||||
doc.to<JsonArray>().add(42);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1));
|
||||
}
|
||||
|
||||
SECTION("JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(0)") {
|
||||
doc.to<JsonArray>().createNestedArray();
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(0));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("capacity()") {
|
||||
SECTION("matches constructor argument") {
|
||||
DynamicJsonDocument doc2(256);
|
||||
REQUIRE(doc2.capacity() == 256);
|
||||
}
|
||||
|
||||
SECTION("rounds up constructor argument") {
|
||||
DynamicJsonDocument doc2(253);
|
||||
REQUIRE(doc2.capacity() == 256);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("memoryUsage()") {
|
||||
SECTION("Increases after adding value to array") {
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
|
||||
arr.add(42);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1));
|
||||
arr.add(43);
|
||||
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
|
||||
}
|
||||
|
||||
SECTION("Increases after adding value to object") {
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
obj["a"] = 1;
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1));
|
||||
obj["b"] = 2;
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("DynamicJsonDocument constructor") {
|
||||
SECTION("Copy constructor") {
|
||||
DynamicJsonDocument doc1(1234);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
DynamicJsonDocument doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
|
||||
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
|
||||
}
|
||||
|
||||
SECTION("Construct from StaticJsonDocument") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
DynamicJsonDocument doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonObject") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
JsonObject obj = doc1.to<JsonObject>();
|
||||
obj["hello"] = "world";
|
||||
|
||||
DynamicJsonDocument doc2 = obj;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonArray") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
JsonArray arr = doc1.to<JsonArray>();
|
||||
arr.add("hello");
|
||||
|
||||
DynamicJsonDocument doc2 = arr;
|
||||
|
||||
REQUIRE_JSON(doc2, "[\"hello\"]");
|
||||
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonVariant") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
deserializeJson(doc1, "42");
|
||||
|
||||
DynamicJsonDocument doc2 = doc1.as<JsonVariant>();
|
||||
|
||||
REQUIRE_JSON(doc2, "42");
|
||||
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("DynamicJsonDocument assignment") {
|
||||
SECTION("Copy assignment preserves the buffer when capacity is sufficient") {
|
||||
DynamicJsonDocument doc1(1234);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
DynamicJsonDocument doc2(doc1.capacity());
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
REQUIRE(doc2.capacity() == doc1.capacity());
|
||||
}
|
||||
|
||||
SECTION("Copy assignment realloc the buffer when capacity is insufficient") {
|
||||
DynamicJsonDocument doc1(1234);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
DynamicJsonDocument doc2(8);
|
||||
|
||||
REQUIRE(doc2.capacity() < doc1.memoryUsage());
|
||||
doc2 = doc1;
|
||||
REQUIRE(doc2.capacity() >= doc1.memoryUsage());
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from StaticJsonDocument") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc2.to<JsonVariant>().set(666);
|
||||
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonObject") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
JsonObject obj = doc1.to<JsonObject>();
|
||||
obj["hello"] = "world";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc2 = obj;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
REQUIRE(doc2.capacity() == 4096);
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonArray") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
JsonArray arr = doc1.to<JsonArray>();
|
||||
arr.add("hello");
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc2 = arr;
|
||||
|
||||
REQUIRE_JSON(doc2, "[\"hello\"]");
|
||||
REQUIRE(doc2.capacity() == 4096);
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonVariant") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
deserializeJson(doc1, "42");
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc2 = doc1.as<JsonVariant>();
|
||||
|
||||
REQUIRE_JSON(doc2, "42");
|
||||
REQUIRE(doc2.capacity() == 4096);
|
||||
}
|
||||
}
|
212
extras/tests/JsonDocument/StaticJsonDocument.cpp
Normal file
212
extras/tests/JsonDocument/StaticJsonDocument.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void REQUIRE_JSON(JsonDocument& doc, const std::string& expected) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
REQUIRE(json == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("StaticJsonDocument") {
|
||||
SECTION("capacity()") {
|
||||
SECTION("matches template argument") {
|
||||
StaticJsonDocument<256> doc;
|
||||
REQUIRE(doc.capacity() == 256);
|
||||
}
|
||||
|
||||
SECTION("rounds up template argument") {
|
||||
StaticJsonDocument<253> doc;
|
||||
REQUIRE(doc.capacity() == 256);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("serializeJson()") {
|
||||
StaticJsonDocument<200> doc;
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
obj["hello"] = "world";
|
||||
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Copy assignment") {
|
||||
StaticJsonDocument<200> doc1, doc2;
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc2, "{\"hello\":\"world\"}");
|
||||
|
||||
doc1 = doc2;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Contructor") {
|
||||
SECTION("Copy constructor") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1;
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Construct from StaticJsonDocument of different size") {
|
||||
StaticJsonDocument<300> doc1;
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Construct from DynamicJsonDocument") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonObject") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1.as<JsonObject>();
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonArray") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
deserializeJson(doc1, "[\"hello\",\"world\"]");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1.as<JsonArray>();
|
||||
|
||||
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
|
||||
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
SECTION("Construct from JsonVariant") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
deserializeJson(doc1, "42");
|
||||
|
||||
StaticJsonDocument<200> doc2 = doc1.as<JsonVariant>();
|
||||
|
||||
REQUIRE_JSON(doc2, "42");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Assignment") {
|
||||
SECTION("Copy assignment") {
|
||||
StaticJsonDocument<200> doc1, doc2;
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
doc2 = doc1;
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from StaticJsonDocument of different capacity") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
StaticJsonDocument<300> doc2;
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
doc2 = doc1;
|
||||
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from DynamicJsonDocument") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
doc2 = doc1;
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonArray") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "[\"hello\",\"world\"]");
|
||||
|
||||
doc2 = doc1.as<JsonArray>();
|
||||
|
||||
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
|
||||
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonArrayConst") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "[\"hello\",\"world\"]");
|
||||
|
||||
doc2 = doc1.as<JsonArrayConst>();
|
||||
|
||||
deserializeJson(doc1, "[\"HELLO\",\"WORLD\"]");
|
||||
REQUIRE_JSON(doc2, "[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonObject") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
doc2 = doc1.as<JsonObject>();
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonObjectConst") {
|
||||
StaticJsonDocument<200> doc1;
|
||||
DynamicJsonDocument doc2(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||
|
||||
doc2 = doc1.as<JsonObjectConst>();
|
||||
|
||||
deserializeJson(doc1, "{\"HELLO\":\"WORLD\"}");
|
||||
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonVariant") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "42");
|
||||
|
||||
StaticJsonDocument<200> doc2;
|
||||
doc2 = doc1.as<JsonVariant>();
|
||||
|
||||
REQUIRE_JSON(doc2, "42");
|
||||
}
|
||||
|
||||
SECTION("Assign from JsonVariantConst") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1.to<JsonVariant>().set(666);
|
||||
deserializeJson(doc1, "42");
|
||||
|
||||
StaticJsonDocument<200> doc2;
|
||||
doc2 = doc1.as<JsonVariantConst>();
|
||||
|
||||
REQUIRE_JSON(doc2, "42");
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user