mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-04 14:16:36 +02:00
Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
1360b6a396 | |||
16e51b83ab | |||
aa7cc5351c | |||
30da920135 | |||
bcdf5b7e52 | |||
c711fe592d | |||
9d5c1b3742 | |||
6b26cd0977 | |||
10ec0f21b0 | |||
ff66182dc6 | |||
d02ce2f1bb | |||
2664a2d0da | |||
1f7350658e | |||
41132b701b | |||
712005219c | |||
0bd17aff8a | |||
f3f44d7812 | |||
8385d5fa3a | |||
726f8be341 | |||
fee029b86e | |||
c3504ddf0a | |||
6a878ee444 | |||
c4ec2ba88f | |||
c907ca6e5d | |||
8993a093e9 | |||
d04669d0cc | |||
05fc136915 | |||
8d37939086 | |||
6d2ad4539f | |||
5ab53f42b2 | |||
f448e805e9 | |||
67aa8efd5a | |||
61a5273aea | |||
35a39b8d8f | |||
96b6571352 | |||
74e7dd053f | |||
1f8636d762 | |||
e4cfa701d8 | |||
b85181a6db | |||
6841b80466 | |||
298864bafe | |||
4d7f03836c | |||
c63eb80b95 | |||
0c0bf80074 | |||
144ff3b06e | |||
d6c50c3596 | |||
51b177ce47 | |||
824b7a25ca | |||
2223d40640 | |||
4df29fbac1 | |||
6dc36125c2 | |||
40085609e2 | |||
ebb6d80092 | |||
764ff2cd53 | |||
8ef226bcb8 | |||
63606c0985 | |||
1600d39693 | |||
04c59985a1 | |||
7e58347fbe | |||
0e794a28a1 | |||
6fb52c3638 | |||
b72ef09451 | |||
f7de027617 | |||
bc4c2dde33 | |||
95f05dad66 | |||
3bb0a7aa8e | |||
dcf7eeef28 | |||
3b923b6e4e | |||
8050f7404b | |||
959b1d9e4c | |||
daa279d57b | |||
ae9b7926a2 | |||
1f7a5e6943 | |||
9e354803de |
4
.gitignore
vendored
4
.gitignore
vendored
@ -10,3 +10,7 @@
|
||||
/extras/fuzzing/*_fuzzer.options
|
||||
/extras/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
.vs/
|
||||
|
||||
# Used by CI for Particle
|
||||
/src/*.ino
|
||||
/project.properties
|
||||
|
36
.travis.yml
36
.travis.yml
@ -21,17 +21,17 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8']
|
||||
env: SCRIPT=test _CC=gcc-4.8 _CXX=g++-4.8 SANITIZE=address
|
||||
env: SCRIPT=test _CC=gcc-4.8 _CXX=g++-4.8
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9']
|
||||
env: SCRIPT=test _CC=gcc-4.9 _CXX=g++-4.9 SANITIZE=leak
|
||||
env: SCRIPT=test _CC=gcc-4.9 _CXX=g++-4.9
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=test _CC=gcc-5 _CXX=g++-5 # SANITIZE=undefined
|
||||
env: SCRIPT=test _CC=gcc-5 _CXX=g++-5
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
@ -41,17 +41,17 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-7']
|
||||
env: SCRIPT=test _CC=gcc-7 _CXX=g++-7
|
||||
env: SCRIPT=test _CC=gcc-7 _CXX=g++-7 CXXFLAGS="-fsanitize=leak"
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-8']
|
||||
env: SCRIPT=test _CC=gcc-8 _CXX=g++-8
|
||||
env: SCRIPT=test _CC=gcc-8 _CXX=g++-8 CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fuse-ld=gold"
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-9']
|
||||
env: SCRIPT=test _CC=gcc-9 _CXX=g++-9
|
||||
env: SCRIPT=test _CC=gcc-9 _CXX=g++-9 CXXFLAGS="-fsanitize=address"
|
||||
- addons:
|
||||
apt:
|
||||
packages: ['g++-arm-linux-gnueabihf']
|
||||
@ -61,12 +61,12 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
|
||||
packages: ['clang-3.5']
|
||||
env: SCRIPT=test _CC=clang-3.5 _CXX=clang++-3.5 SANITIZE=address
|
||||
env: SCRIPT=test _CC=clang-3.5 _CXX=clang++-3.5 CXXFLAGS="-fsanitize=address"
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
|
||||
packages: ['clang-3.6']
|
||||
env: SCRIPT=test _CC=clang-3.6 _CXX=clang++-3.6 SANITIZE=leak
|
||||
env: SCRIPT=test _CC=clang-3.6 _CXX=clang++-3.6 CXXFLAGS="-fsanitize=leak"
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
|
||||
@ -76,7 +76,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=test _CC=clang-3.8 _CXX=clang++-3.8 SANITIZE=undefined
|
||||
env: SCRIPT=test _CC=clang-3.8 _CXX=clang++-3.8 CXXFLAGS="-fsanitize=undefined"
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-3.9']
|
||||
@ -107,10 +107,14 @@ matrix:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-8']
|
||||
packages: ['clang-8']
|
||||
env: SCRIPT=test _CC=clang-8 _CXX=clang++-8
|
||||
- addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
packages: ['clang-9']
|
||||
env: SCRIPT=test _CC=clang-9 _CXX=clang++-9
|
||||
- env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
env: SCRIPT=test
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
env: SCRIPT=test
|
||||
@ -119,16 +123,12 @@ matrix:
|
||||
env: SCRIPT=test
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
env: SCRIPT=test SANITIZE=address
|
||||
env: SCRIPT=test CXXFLAGS="-fsanitize=address"
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:samd:mkr1000
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['clang-6.0','llvm-6.0']
|
||||
env: SCRIPT=fuzz CLANG=6.0
|
||||
- env: SCRIPT=particle BOARD=argon
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
57
CHANGELOG.md
57
CHANGELOG.md
@ -1,6 +1,63 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v6.17.2 (2020-11-14)
|
||||
-------
|
||||
|
||||
* Fixed invalid conversion error in `operator|(JsonVariant, char*)` (issue #1432)
|
||||
* Changed the default value of `ARDUINOJSON_ENABLE_PROGMEM` (issue #1433).
|
||||
It now checks that the `pgm_read_XXX` macros are defined before enabling `PROGMEM`.
|
||||
|
||||
v6.17.1 (2020-11-07)
|
||||
-------
|
||||
|
||||
* Fixed error `ambiguous overload for 'operator|'` (issue #1411)
|
||||
* Fixed `operator|(MemberProxy, JsonObject)` (issue #1415)
|
||||
* Allowed more than 32767 values in non-embedded mode (issue #1414)
|
||||
|
||||
v6.17.0 (2020-10-19)
|
||||
-------
|
||||
|
||||
* Added a build failure when nullptr is defined as a macro (issue #1355)
|
||||
* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
|
||||
* Added `DeserializationError::EmptyInput` which tells if the input was empty
|
||||
* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846)
|
||||
* Added `operator|(JsonVariantConst, JsonVariantConst)`
|
||||
* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella)
|
||||
* Moved float convertion tables to PROGMEM
|
||||
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
|
||||
* Fixed error `No such file or directory #include <WString.h>` (issue #1381)
|
||||
|
||||
v6.16.1 (2020-08-04)
|
||||
-------
|
||||
|
||||
* Fixed `deserializeJson()` that stopped reading after `{}` (issue #1335)
|
||||
|
||||
v6.16.0 (2020-08-01)
|
||||
-------
|
||||
|
||||
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
|
||||
* Added string deduplication (issue #1303)
|
||||
* Added `JsonString::operator!=`
|
||||
* Added wildcard key (`*`) for filters (issue #1309)
|
||||
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
|
||||
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
|
||||
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)
|
||||
* Fixed excessive stack usage when compiled with `-Og` (issues #1210 and #1314)
|
||||
* Fixed `Warning[Pa093]: implicit conversion from floating point to integer` on IAR compiler (PR #1328 by @stawiski)
|
||||
|
||||
v6.15.2 (2020-05-15)
|
||||
-------
|
||||
|
||||
* CMake: don't build tests when imported in another project
|
||||
* CMake: made project arch-independent
|
||||
* Visual Studio: fixed error C2766 with flag `/Zc:__cplusplus` (issue #1250)
|
||||
* Added support for `JsonDocument` to `copyArray()` (issue #1255)
|
||||
* Added support for `enum`s in `as<T>()` and `is<T>()` (issue #1256)
|
||||
* Added `JsonVariant` as an input type for `deserializeXxx()`
|
||||
For example, you can do: `deserializeJson(doc2, doc1["payload"])`
|
||||
* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0
|
||||
|
||||
v6.15.1 (2020-04-08)
|
||||
-------
|
||||
|
||||
|
@ -3,42 +3,17 @@
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(ArduinoJson)
|
||||
|
||||
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
|
||||
project(ArduinoJson VERSION 6.17.2)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_definitions(-DARDUINOJSON_DEBUG=1)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
include(CTest)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(extras/tests)
|
||||
add_subdirectory(extras/fuzzing)
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
||||
include(extras/CompileOptions.cmake)
|
||||
add_subdirectory(extras/tests)
|
||||
add_subdirectory(extras/fuzzing)
|
||||
endif()
|
||||
|
12
README.md
12
README.md
@ -2,7 +2,7 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.15.1)
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.17.2)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||
@ -17,7 +17,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
* [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/?utm_source=github&utm_medium=readme)
|
||||
* [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme)
|
||||
* [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/?utm_source=github&utm_medium=readme)
|
||||
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/#filtering?utm_source=github&utm_medium=readme)
|
||||
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#filtering)
|
||||
* Supports single quotes as a string delimiter
|
||||
* Compatible with NDJSON and JSON Lines
|
||||
* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme)
|
||||
@ -31,12 +31,13 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
* [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
|
||||
* [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/?utm_source=github&utm_medium=readme)
|
||||
* [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme)
|
||||
* Deduplicates strings
|
||||
* Versatile
|
||||
* [Supports custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme)
|
||||
* Supports [Arduino's `String`](https://arduinojson.org/v6/api/config/enable_arduino_string/) and [STL's `std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme)
|
||||
* Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme)
|
||||
* [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme)
|
||||
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/#custom-writer?utm_source=github&utm_medium=readme)
|
||||
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer)
|
||||
* Portable
|
||||
* Usable on any C++ project (not limited to Arduino)
|
||||
* Compatible with C++98
|
||||
@ -62,14 +63,15 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
* [Visual Micro](http://www.visualmicro.com/)
|
||||
* [Visual Studio](https://www.visualstudio.com/)
|
||||
* [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/t7KP7I6dVuLhqzDl)
|
||||
* [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/?utm_source=github&utm_medium=readme)
|
||||
* Well designed
|
||||
* [Elegant API](http://127.0.0.1:4000/v6/example/)
|
||||
* [Elegant API](http://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
|
||||
* [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety)
|
||||
* Self-contained (no external dependency)
|
||||
* `const` friendly
|
||||
* [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/?utm_source=github&utm_medium=readme)
|
||||
* [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming)
|
||||
* Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/#integer-overflows?utm_source=github&utm_medium=readme)
|
||||
* Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/?utm_source=github&utm_medium=readme#integer-overflows)
|
||||
* Well tested
|
||||
* [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||
* Continuously tested on
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 6.15.1.{build}
|
||||
version: 6.17.2.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
|
@ -82,7 +82,7 @@ void setup() {
|
||||
DeserializationError error = deserializeJson(doc, client);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ void setup() {
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ void setup() {
|
||||
// Test if parsing succeeded.
|
||||
if (error) {
|
||||
Serial.print("deserializeMsgPack() failed: ");
|
||||
Serial.println(error.c_str());
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
100
extras/CompileOptions.cmake
Normal file
100
extras/CompileOptions.cmake
Normal file
@ -0,0 +1,100 @@
|
||||
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()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8) AND (NOT ${COVERAGE}))
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
|
||||
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(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0) AND (NOT ${COVERAGE}))
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0) AND (NOT ${COVERAGE}))
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_options(
|
||||
/W4 # Set warning level
|
||||
/WX # Treats all compiler warnings as errors.
|
||||
)
|
||||
|
||||
if (NOT MSVC_VERSION LESS 1910) # >= Visual Studio 2017
|
||||
add_compile_options(
|
||||
/Zc:__cplusplus # Enable updated __cplusplus macro
|
||||
)
|
||||
endif()
|
||||
endif()
|
@ -3,12 +3,5 @@
|
||||
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 -DCMAKE_BUILD_TYPE=Release .
|
||||
cmake --build .
|
||||
|
@ -1,26 +1,22 @@
|
||||
#!/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"
|
||||
export CC="clang-${CLANG}"
|
||||
export CXX="clang++-${CLANG}"
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
FUZZER_TARGET="${FUZZER}_fuzzer"
|
||||
FUZZER_PATH="extras/fuzzing/${FUZZER_TARGET}"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${FUZZER}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${FUZZER}_seed_corpus"
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
cmake --build . --target $FUZZER_TARGET
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER_TARGET}.profraw"
|
||||
${FUZZER_PATH} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=60 -timeout=1
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER_TARGET}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER_PATH} -instr-profile=${FUZZER_TARGET}.profdata
|
||||
|
12
extras/ci/particle.sh
Executable file
12
extras/ci/particle.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
cd "$(dirname "$0")/../../"
|
||||
|
||||
npm install -g particle-cli
|
||||
|
||||
particle login -t "${PARTICLE_TOKEN}"
|
||||
|
||||
cp extras/particle/src/smocktest.ino src/
|
||||
cp extras/particle/project.properties ./
|
||||
|
||||
particle compile "$BOARD"
|
@ -1,4 +1,8 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
"$(dirname "$0")/build.sh"
|
||||
export CC="$_CC"
|
||||
export CXX="$_CXX"
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
cmake --build .
|
||||
ctest --output-on-failure .
|
||||
|
@ -6,18 +6,72 @@ if(MSVC)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
add_executable(msgpack_fuzzer
|
||||
add_executable(msgpack_reproducer
|
||||
msgpack_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
reproducer.cpp
|
||||
)
|
||||
target_link_libraries(msgpack_fuzzer
|
||||
target_link_libraries(msgpack_reproducer
|
||||
ArduinoJson
|
||||
)
|
||||
|
||||
add_executable(json_fuzzer
|
||||
add_executable(json_reproducer
|
||||
json_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
reproducer.cpp
|
||||
)
|
||||
target_link_libraries(json_fuzzer
|
||||
target_link_libraries(json_reproducer
|
||||
ArduinoJson
|
||||
)
|
||||
|
||||
# Infer path of llvm-symbolizer from the path of clang
|
||||
string(REPLACE "clang++" "llvm-symbolizer" LLVM_SYMBOLIZER ${CMAKE_CXX_COMPILER})
|
||||
|
||||
macro(add_fuzzer name mode)
|
||||
set(FUZZER "${name}_${mode}_fuzzer")
|
||||
set(CORPUS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${name}_corpus")
|
||||
set(SEED_CORPUS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${name}_seed_corpus")
|
||||
add_executable("${FUZZER}"
|
||||
"${name}_fuzzer.cpp"
|
||||
)
|
||||
target_link_libraries("${FUZZER}"
|
||||
ArduinoJson
|
||||
)
|
||||
set_target_properties("${FUZZER}"
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-fprofile-instr-generate -fcoverage-mapping -fsanitize=${mode},fuzzer -fno-sanitize-recover=all"
|
||||
LINK_FLAGS
|
||||
"-fprofile-instr-generate -fcoverage-mapping -fsanitize=${mode},fuzzer -fno-sanitize-recover=all"
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME
|
||||
"${FUZZER}"
|
||||
COMMAND
|
||||
"${FUZZER}" "${CORPUS_DIR}" "${SEED_CORPUS_DIR}" -max_total_time=5 -timeout=1
|
||||
)
|
||||
|
||||
set_tests_properties("${FUZZER}"
|
||||
PROPERTIES
|
||||
ENVIRONMENT
|
||||
ASAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER}
|
||||
ENVIRONMENT
|
||||
LLVM_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER}
|
||||
ENVIRONMENT
|
||||
MSAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER}
|
||||
ENVIRONMENT
|
||||
UBSAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6)
|
||||
add_fuzzer(json address)
|
||||
add_fuzzer(json undefined)
|
||||
add_fuzzer(msgpack address)
|
||||
add_fuzzer(msgpack undefined)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7)
|
||||
# We're getting false positive with Clang 6
|
||||
add_fuzzer(json memory)
|
||||
add_fuzzer(msgpack memory)
|
||||
endif()
|
||||
|
@ -21,7 +21,7 @@ std::vector<uint8_t> read(const char* path) {
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
size_t size = static_cast<size_t>(ftell(f));
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
std::vector<uint8_t> buffer(size);
|
1
extras/particle/project.properties
Normal file
1
extras/particle/project.properties
Normal file
@ -0,0 +1 @@
|
||||
name=ArduinoJsonCI
|
5
extras/particle/src/smocktest.ino
Normal file
5
extras/particle/src/smocktest.ino
Normal file
@ -0,0 +1,5 @@
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
void setup() {}
|
||||
|
||||
void loop() {}
|
@ -10,6 +10,7 @@ rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
7z a $OUTPUT \
|
||||
-xr!.vs \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/src \
|
||||
|
@ -1,29 +0,0 @@
|
||||
#!/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
|
@ -14,19 +14,22 @@ update_version_in_source () {
|
||||
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*~
|
||||
rm README.md~
|
||||
|
||||
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
|
||||
rm CHANGELOG.md*~
|
||||
rm CHANGELOG.md~
|
||||
|
||||
sed -i~ -bE "s/(project\\s*\\(ArduinoJson\\s+VERSION\\s+).*?\\)/\\1$MAJOR.$MINOR.$REVISION)/" CMakeLists.txt
|
||||
rm CMakeLists.txt~
|
||||
|
||||
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
|
||||
rm library.json*~
|
||||
rm library.json~
|
||||
|
||||
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
|
||||
rm library.properties*~
|
||||
rm library.properties~
|
||||
|
||||
sed -i~ -bE "s/version: .*$/version: $VERSION.{build}/" appveyor.yml
|
||||
rm appveyor.yml*~
|
||||
rm appveyor.yml~
|
||||
|
||||
sed -i~ -bE \
|
||||
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
|
||||
@ -38,7 +41,7 @@ update_version_in_source () {
|
||||
}
|
||||
|
||||
commit_new_version () {
|
||||
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml
|
||||
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml CMakeLists.txt
|
||||
git commit -m "Set version to $VERSION"
|
||||
}
|
||||
|
||||
|
@ -4,76 +4,10 @@
|
||||
|
||||
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()
|
||||
link_libraries(ArduinoJson catch)
|
||||
|
||||
include_directories(Helpers)
|
||||
add_subdirectory(ElementProxy)
|
||||
add_subdirectory(FailingBuilds)
|
||||
add_subdirectory(IntegrationTests)
|
||||
add_subdirectory(JsonArray)
|
||||
add_subdirectory(JsonDeserializer)
|
||||
@ -81,7 +15,6 @@ add_subdirectory(JsonDocument)
|
||||
add_subdirectory(JsonObject)
|
||||
add_subdirectory(JsonSerializer)
|
||||
add_subdirectory(JsonVariant)
|
||||
add_subdirectory(MemberProxy)
|
||||
add_subdirectory(MemoryPool)
|
||||
add_subdirectory(Misc)
|
||||
add_subdirectory(MixedConfiguration)
|
||||
|
@ -1,19 +0,0 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2020
|
||||
# MIT License
|
||||
|
||||
add_executable(ElementProxyTests
|
||||
add.cpp
|
||||
clear.cpp
|
||||
compare.cpp
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(ElementProxyTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(ElementProxy ElementProxyTests)
|
@ -1,34 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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\"]]");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") {
|
||||
char s[] = "world";
|
||||
ep.add(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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]);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("ElementProxy::set()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
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\"]");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") {
|
||||
char s[] = "world";
|
||||
ep.set(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[\"world\"]");
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
ElementProxy<JsonDocument&> ep = doc[1];
|
||||
|
||||
SECTION("set member") {
|
||||
ep["world"] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[null,{\"world\":42}]");
|
||||
}
|
||||
|
||||
SECTION("set element") {
|
||||
ep[2] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[null,[null,null,42]]");
|
||||
}
|
||||
}
|
38
extras/tests/FailingBuilds/CMakeLists.txt
Normal file
38
extras/tests/FailingBuilds/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2020
|
||||
# MIT License
|
||||
|
||||
macro(build_should_fail target)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL TRUE
|
||||
EXCLUDE_FROM_DEFAULT_BUILD TRUE
|
||||
)
|
||||
add_test(
|
||||
NAME
|
||||
${target}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} --build . --target ${target} --config $<CONFIGURATION>
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
set_tests_properties(${target}
|
||||
PROPERTIES
|
||||
WILL_FAIL TRUE
|
||||
)
|
||||
endmacro()
|
||||
|
||||
|
||||
add_executable(Issue978 Issue978.cpp)
|
||||
build_should_fail(Issue978)
|
||||
|
||||
add_executable(Issue1189 Issue1189.cpp)
|
||||
build_should_fail(Issue1189)
|
||||
|
||||
add_executable(read_long_long read_long_long.cpp)
|
||||
set_property(TARGET read_long_long PROPERTY CXX_STANDARD 11)
|
||||
build_should_fail(read_long_long)
|
||||
|
||||
add_executable(write_long_long write_long_long.cpp)
|
||||
set_property(TARGET write_long_long PROPERTY CXX_STANDARD 11)
|
||||
build_should_fail(write_long_long)
|
20
extras/tests/FailingBuilds/read_long_long.cpp
Normal file
20
extras/tests/FailingBuilds/read_long_long.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
|
||||
#error This test requires sizeof(long) < 8
|
||||
#endif
|
||||
|
||||
#if !ARDUINOJSON_HAS_LONG_LONG
|
||||
#error This test requires C++11
|
||||
#endif
|
||||
|
||||
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(long long)
|
||||
int main() {
|
||||
DynamicJsonDocument doc(1024);
|
||||
doc["dummy"].as<long long>();
|
||||
}
|
19
extras/tests/FailingBuilds/write_long_long.cpp
Normal file
19
extras/tests/FailingBuilds/write_long_long.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
|
||||
#error This test requires sizeof(long) < 8
|
||||
#endif
|
||||
|
||||
#if !ARDUINOJSON_HAS_LONG_LONG
|
||||
#error This test requires C++11
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
DynamicJsonDocument doc(1024);
|
||||
doc["dummy"] = static_cast<long long>(42);
|
||||
}
|
8
extras/tests/Helpers/Arduino.h
Normal file
8
extras/tests/Helpers/Arduino.h
Normal file
@ -0,0 +1,8 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/Stream.h"
|
||||
#include "api/String.h"
|
@ -9,6 +9,9 @@
|
||||
// Reproduces Arduino's String class
|
||||
class String {
|
||||
public:
|
||||
String() {}
|
||||
explicit String(const char* s) : _str(s) {}
|
||||
|
||||
String& operator+=(const char* rhs) {
|
||||
_str += rhs;
|
||||
return *this;
|
@ -5,6 +5,8 @@
|
||||
#include <stdint.h> // uint8_t
|
||||
#include <string.h> // strcmp, strlen...
|
||||
|
||||
#define PROGMEM
|
||||
|
||||
class __FlashStringHelper;
|
||||
|
||||
inline const void* convertPtrToFlash(const void* s) {
|
||||
@ -15,9 +17,26 @@ inline const void* convertFlashToPtr(const void* s) {
|
||||
return reinterpret_cast<const char*>(s) - 42;
|
||||
}
|
||||
|
||||
#define F(X) reinterpret_cast<const __FlashStringHelper*>(convertPtrToFlash(X))
|
||||
#define FC(X) reinterpret_cast<const char*>(convertPtrToFlash(X))
|
||||
#define PSTR(X) reinterpret_cast<const char*>(convertPtrToFlash(X))
|
||||
#define F(X) reinterpret_cast<const __FlashStringHelper*>(PSTR(X))
|
||||
|
||||
inline uint8_t pgm_read_byte(const void* p) {
|
||||
return *reinterpret_cast<const uint8_t*>(convertFlashToPtr(p));
|
||||
}
|
||||
|
||||
inline void* pgm_read_ptr(const void* p) {
|
||||
return *reinterpret_cast<void* const*>(convertFlashToPtr(p));
|
||||
}
|
||||
|
||||
inline float pgm_read_float(const void* p) {
|
||||
return *reinterpret_cast<const float*>(convertFlashToPtr(p));
|
||||
}
|
||||
|
||||
inline uint32_t pgm_read_dword(const void* p) {
|
||||
return *reinterpret_cast<const uint32_t*>(convertFlashToPtr(p));
|
||||
}
|
||||
|
||||
#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
|
||||
static type const ARDUINOJSON_CONCAT2(name, _progmem)[] = value; \
|
||||
static type const* name = reinterpret_cast<type const*>( \
|
||||
convertPtrToFlash(ARDUINOJSON_CONCAT2(name, _progmem)));
|
||||
|
@ -16,9 +16,4 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(IntegrationTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(IntegrationTests IntegrationTests)
|
||||
|
@ -19,9 +19,4 @@ add_executable(JsonArrayTests
|
||||
undefined.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonArrayTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(JsonArray JsonArrayTests)
|
||||
|
@ -102,13 +102,13 @@ TEST_CASE("JsonArray::add()") {
|
||||
|
||||
SECTION("should duplicate char*") {
|
||||
array.add(const_cast<char*>("world"));
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
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);
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
|
@ -6,20 +6,57 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("copyArray()") {
|
||||
SECTION("1D -> JsonArray") {
|
||||
SECTION("int[] -> JsonArray") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32];
|
||||
int source[] = {1, 2, 3};
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
REQUIRE(ok);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[1,2,3]") == json);
|
||||
serializeJson(array, json);
|
||||
CHECK(std::string("[1,2,3]") == json);
|
||||
}
|
||||
|
||||
SECTION("1D -> JsonArray, but not enough memory") {
|
||||
SECTION("std::string[] -> JsonArray") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
char json[32];
|
||||
std::string source[] = {"a", "b", "c"};
|
||||
|
||||
bool ok = copyArray(source, array);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(array, json);
|
||||
CHECK(std::string("[\"a\",\"b\",\"c\"]") == json);
|
||||
}
|
||||
|
||||
SECTION("int[] -> JsonDocument") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[32];
|
||||
int source[] = {1, 2, 3};
|
||||
|
||||
bool ok = copyArray(source, doc);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(doc, json);
|
||||
CHECK(std::string("[1,2,3]") == json);
|
||||
}
|
||||
|
||||
SECTION("int[] -> MemberProxy") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[32];
|
||||
int source[] = {1, 2, 3};
|
||||
|
||||
bool ok = copyArray(source, doc["data"]);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(doc, json);
|
||||
CHECK(std::string("{\"data\":[1,2,3]}") == json);
|
||||
}
|
||||
|
||||
SECTION("int[] -> JsonArray, but not enough memory") {
|
||||
const size_t SIZE = JSON_ARRAY_SIZE(2);
|
||||
StaticJsonDocument<SIZE> doc;
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
@ -29,24 +66,48 @@ TEST_CASE("copyArray()") {
|
||||
bool ok = copyArray(source, array);
|
||||
REQUIRE_FALSE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[1,2]") == json);
|
||||
serializeJson(array, json);
|
||||
CHECK(std::string("[1,2]") == json);
|
||||
}
|
||||
|
||||
SECTION("2D -> JsonArray") {
|
||||
SECTION("int[][] -> 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);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[[1,2,3],[4,5,6]]") == json);
|
||||
serializeJson(array, json);
|
||||
CHECK(std::string("[[1,2,3],[4,5,6]]") == json);
|
||||
}
|
||||
|
||||
SECTION("2D -> JsonArray, but not enough memory") {
|
||||
SECTION("int[][] -> MemberProxy") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[32];
|
||||
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
|
||||
bool ok = copyArray(source, doc["data"]);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(doc, json);
|
||||
CHECK(std::string("{\"data\":[[1,2,3],[4,5,6]]}") == json);
|
||||
}
|
||||
|
||||
SECTION("int[][] -> JsonDocument") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[32];
|
||||
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
|
||||
bool ok = copyArray(source, doc);
|
||||
CHECK(ok);
|
||||
|
||||
serializeJson(doc, json);
|
||||
CHECK(std::string("[[1,2,3],[4,5,6]]") == json);
|
||||
}
|
||||
|
||||
SECTION("int[][] -> JsonArray, but not enough memory") {
|
||||
const size_t SIZE =
|
||||
JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2);
|
||||
StaticJsonDocument<SIZE> doc;
|
||||
@ -60,58 +121,159 @@ TEST_CASE("copyArray()") {
|
||||
CAPTURE(doc.memoryUsage());
|
||||
CHECK_FALSE(ok);
|
||||
|
||||
serializeJson(array, json, sizeof(json));
|
||||
REQUIRE(std::string("[[1,2,3],[4,5]]") == json);
|
||||
serializeJson(array, json);
|
||||
CHECK(std::string("[[1,2,3],[4,5]]") == json);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 1D, with more space than needed") {
|
||||
SECTION("JsonArray -> int[], with more space than needed") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[1,2,3]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(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]);
|
||||
CHECK(3 == result);
|
||||
CHECK(1 == destination[0]);
|
||||
CHECK(2 == destination[1]);
|
||||
CHECK(3 == destination[2]);
|
||||
CHECK(0 == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 1D, without enough space") {
|
||||
SECTION("JsonArray -> int[], without enough space") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[1,2,3]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(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]);
|
||||
CHECK(2 == result);
|
||||
CHECK(1 == destination[0]);
|
||||
CHECK(2 == destination[1]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> 2D") {
|
||||
SECTION("JsonArray -> std::string[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[\"a\",\"b\",\"c\"]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
|
||||
std::string destination[4];
|
||||
size_t result = copyArray(array, destination);
|
||||
|
||||
CHECK(3 == result);
|
||||
CHECK("a" == destination[0]);
|
||||
CHECK("b" == destination[1]);
|
||||
CHECK("c" == destination[2]);
|
||||
CHECK("" == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("JsonDocument -> int[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[1,2,3]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
|
||||
int destination[4] = {0};
|
||||
size_t result = copyArray(doc, destination);
|
||||
|
||||
CHECK(3 == result);
|
||||
CHECK(1 == destination[0]);
|
||||
CHECK(2 == destination[1]);
|
||||
CHECK(3 == destination[2]);
|
||||
CHECK(0 == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("MemberProxy -> int[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "{\"data\":[1,2,3]}";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
|
||||
int destination[4] = {0};
|
||||
size_t result = copyArray(doc["data"], destination);
|
||||
|
||||
CHECK(3 == result);
|
||||
CHECK(1 == destination[0]);
|
||||
CHECK(2 == destination[1]);
|
||||
CHECK(3 == destination[2]);
|
||||
CHECK(0 == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("ElementProxy -> int[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[[1,2,3]]";
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
|
||||
int destination[4] = {0};
|
||||
size_t result = copyArray(doc[0], destination);
|
||||
|
||||
CHECK(3 == result);
|
||||
CHECK(1 == destination[0]);
|
||||
CHECK(2 == destination[1]);
|
||||
CHECK(3 == destination[2]);
|
||||
CHECK(0 == destination[3]);
|
||||
}
|
||||
|
||||
SECTION("JsonArray -> int[][]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[[1,2],[3],[4]]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(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]);
|
||||
CHECK(1 == destination[0][0]);
|
||||
CHECK(2 == destination[0][1]);
|
||||
CHECK(3 == destination[1][0]);
|
||||
CHECK(0 == destination[1][1]);
|
||||
CHECK(4 == destination[2][0]);
|
||||
CHECK(0 == destination[2][1]);
|
||||
}
|
||||
|
||||
SECTION("JsonDocument -> int[][]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "[[1,2],[3],[4]]";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
|
||||
int destination[3][2] = {{0}};
|
||||
copyArray(doc, destination);
|
||||
|
||||
CHECK(1 == destination[0][0]);
|
||||
CHECK(2 == destination[0][1]);
|
||||
CHECK(3 == destination[1][0]);
|
||||
CHECK(0 == destination[1][1]);
|
||||
CHECK(4 == destination[2][0]);
|
||||
CHECK(0 == destination[2][1]);
|
||||
}
|
||||
|
||||
SECTION("MemberProxy -> int[][]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
char json[] = "{\"data\":[[1,2],[3],[4]]}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, json);
|
||||
CHECK(err == DeserializationError::Ok);
|
||||
|
||||
int destination[3][2] = {{0}};
|
||||
copyArray(doc["data"], destination);
|
||||
|
||||
CHECK(1 == destination[0][0]);
|
||||
CHECK(2 == destination[0][1]);
|
||||
CHECK(3 == destination[1][0]);
|
||||
CHECK(0 == destination[1][1]);
|
||||
CHECK(4 == destination[2][0]);
|
||||
CHECK(0 == destination[2][1]);
|
||||
}
|
||||
}
|
||||
|
@ -65,4 +65,15 @@ TEST_CASE("JsonArray::remove()") {
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 2);
|
||||
}
|
||||
|
||||
SECTION("In a loop") {
|
||||
for (JsonArray::iterator it = _array.begin(); it != _array.end(); ++it) {
|
||||
if (*it == 2)
|
||||
_array.remove(it);
|
||||
}
|
||||
|
||||
REQUIRE(2 == _array.size());
|
||||
REQUIRE(_array[0] == 1);
|
||||
REQUIRE(_array[1] == 3);
|
||||
}
|
||||
}
|
||||
|
@ -119,13 +119,13 @@ TEST_CASE("JsonArray::operator[]") {
|
||||
|
||||
SECTION("should duplicate char*") {
|
||||
array[0] = const_cast<char*>("world");
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
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);
|
||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,6 @@ add_executable(JsonDeserializerTests
|
||||
string.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonDeserializerTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
set_target_properties(JsonDeserializerTests PROPERTIES UNITY_BUILD OFF)
|
||||
|
||||
add_test(JsonDeserializer JsonDeserializerTests)
|
||||
|
@ -30,20 +30,22 @@ void testBoolification(DeserializationError error, bool expected) {
|
||||
TEST_CASE("DeserializationError") {
|
||||
SECTION("c_str()") {
|
||||
TEST_STRINGIFICATION(Ok);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(EmptyInput);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(NotSupported);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
}
|
||||
|
||||
SECTION("as boolean") {
|
||||
TEST_BOOLIFICATION(Ok, false);
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(InvalidInput, true);
|
||||
TEST_BOOLIFICATION(EmptyInput, true);
|
||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||
TEST_BOOLIFICATION(InvalidInput, true);
|
||||
TEST_BOOLIFICATION(NoMemory, true);
|
||||
TEST_BOOLIFICATION(NotSupported, true);
|
||||
TEST_BOOLIFICATION(TooDeep, true);
|
||||
}
|
||||
|
||||
SECTION("ostream DeserializationError") {
|
||||
@ -58,13 +60,6 @@ TEST_CASE("DeserializationError") {
|
||||
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()) {
|
||||
|
@ -56,7 +56,7 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
||||
|
||||
deserializeJson(doc, " [ \"1234567\" ] ");
|
||||
|
||||
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(8) == doc.memoryUsage());
|
||||
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(7) == doc.memoryUsage());
|
||||
// note: we use a string of 8 bytes to be sure that the StaticMemoryPool
|
||||
// will not insert bytes to enforce alignement
|
||||
}
|
||||
|
@ -62,6 +62,15 @@ TEST_CASE("Filtering") {
|
||||
"null",
|
||||
0
|
||||
},
|
||||
{
|
||||
// Member is a string, but filter wants an array
|
||||
"{\"example\":\"example\"}",
|
||||
"{\"example\":[true]}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":null}",
|
||||
JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
// Input is an array, but filter wants an object
|
||||
"[\"hello\",\"world\"]",
|
||||
@ -214,6 +223,15 @@ TEST_CASE("Filtering") {
|
||||
"{\"example\":{\"outcome\":42}}",
|
||||
2 * JSON_OBJECT_SIZE(1) + 16
|
||||
},
|
||||
{
|
||||
// wildcard
|
||||
"{\"example\":{\"type\":\"int\",\"outcome\":42}}",
|
||||
"{\"*\":{\"outcome\":true}}",
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"{\"example\":{\"outcome\":42}}",
|
||||
2 * JSON_OBJECT_SIZE(1) + 16
|
||||
},
|
||||
{
|
||||
// only the first element of array counts
|
||||
"[1,2,3]",
|
||||
@ -239,7 +257,7 @@ TEST_CASE("Filtering") {
|
||||
10,
|
||||
DeserializationError::Ok,
|
||||
"[{\"example\":1},{\"example\":3}]",
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 16
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8
|
||||
},
|
||||
{
|
||||
"[',2,3]",
|
||||
@ -525,7 +543,7 @@ TEST_CASE("Filtering") {
|
||||
10,
|
||||
DeserializationError::InvalidInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0) + 8
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// incomplete comment after key
|
||||
@ -534,7 +552,7 @@ TEST_CASE("Filtering") {
|
||||
10,
|
||||
DeserializationError::IncompleteInput,
|
||||
"{}",
|
||||
JSON_OBJECT_SIZE(0) + 8
|
||||
JSON_OBJECT_SIZE(0)
|
||||
},
|
||||
{
|
||||
// invalid comment after colon
|
||||
@ -730,20 +748,3 @@ TEST_CASE("Overloads") {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("StringMover::reclaim()") {
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["a"] = true;
|
||||
filter["c"] = true;
|
||||
char input[] = "{\"a\":1,\"b\":2,\"c\":1}";
|
||||
|
||||
StaticJsonDocument<200> doc;
|
||||
deserializeJson(doc, input, DeserializationOption::Filter(filter));
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"a\":1,\"c\":1}");
|
||||
|
||||
CHECK(input[0] == 'a');
|
||||
CHECK(input[1] == 0);
|
||||
CHECK(input[2] == 'c');
|
||||
CHECK(input[3] == 0);
|
||||
}
|
||||
|
@ -3,11 +3,27 @@
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <sstream>
|
||||
|
||||
#include "CustomReader.hpp"
|
||||
|
||||
TEST_CASE("deserializeJson(char*)") {
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
SECTION("should not duplicate strings") {
|
||||
char input[] = "{\"hello\":\"world\"}";
|
||||
|
||||
DeserializationError err = deserializeJson(doc, input);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
CHECK(doc.memoryUsage() == JSON_OBJECT_SIZE(1));
|
||||
CHECK(doc.as<JsonVariant>().memoryUsage() ==
|
||||
JSON_OBJECT_SIZE(1)); // issue #1318
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(const std::string&)") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
@ -126,3 +142,57 @@ TEST_CASE("deserializeJson(CustomReader)") {
|
||||
REQUIRE(doc[0] == 4);
|
||||
REQUIRE(doc[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, MemberProxy)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err = deserializeJson(doc2, doc1["payload"]);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, JsonVariant)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err =
|
||||
deserializeJson(doc2, doc1["payload"].as<JsonVariant>());
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, JsonVariantConst)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1["payload"] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err =
|
||||
deserializeJson(doc2, doc1["payload"].as<JsonVariantConst>());
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeJson(JsonDocument&, ElementProxy)") {
|
||||
DynamicJsonDocument doc1(4096);
|
||||
doc1[0] = "[4,2]";
|
||||
|
||||
DynamicJsonDocument doc2(4096);
|
||||
DeserializationError err = deserializeJson(doc2, doc1[0]);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc2.size() == 2);
|
||||
REQUIRE(doc2[0] == 4);
|
||||
REQUIRE(doc2[1] == 2);
|
||||
}
|
||||
|
@ -27,7 +27,13 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
||||
SECTION("Empty input") {
|
||||
DeserializationError err = deserializeJson(doc, "");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("Only spaces") {
|
||||
DeserializationError err = deserializeJson(doc, " \t\n\r");
|
||||
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("issue #628") {
|
||||
|
@ -290,4 +290,10 @@ TEST_CASE("deserialize JSON object") {
|
||||
REQUIRE(obj.size() == 0);
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Issue #1335") {
|
||||
std::string json("{\"a\":{},\"b\":{}}");
|
||||
deserializeJson(doc, json);
|
||||
CHECK(doc.as<std::string>() == json);
|
||||
}
|
||||
}
|
||||
|
@ -74,16 +74,16 @@ TEST_CASE("Invalid JSON string") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Not enough room to duplicate the string") {
|
||||
DynamicJsonDocument doc(JSON_OBJECT_SIZE(0));
|
||||
TEST_CASE("Not enough room to save the key") {
|
||||
DynamicJsonDocument doc(JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
SECTION("Quoted string") {
|
||||
REQUIRE(deserializeJson(doc, "{\"example\":1}") ==
|
||||
REQUIRE(deserializeJson(doc, "{\"accuracy\":1}") ==
|
||||
DeserializationError::NoMemory);
|
||||
}
|
||||
|
||||
SECTION("Non-quoted string") {
|
||||
REQUIRE(deserializeJson(doc, "{example:1}") ==
|
||||
REQUIRE(deserializeJson(doc, "{accuracy:1}") ==
|
||||
DeserializationError::NoMemory);
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,11 @@ add_executable(JsonDocumentTests
|
||||
containsKey.cpp
|
||||
createNested.cpp
|
||||
DynamicJsonDocument.cpp
|
||||
ElementProxy.cpp
|
||||
isNull.cpp
|
||||
MemberProxy.cpp
|
||||
nesting.cpp
|
||||
overflowed.cpp
|
||||
remove.cpp
|
||||
shrinkToFit.cpp
|
||||
size.cpp
|
||||
@ -18,9 +21,4 @@ add_executable(JsonDocumentTests
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonDocumentTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(JsonDocument JsonDocumentTests)
|
||||
|
206
extras/tests/JsonDocument/ElementProxy.cpp
Normal file
206
extras/tests/JsonDocument/ElementProxy.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// 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\"]]");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") {
|
||||
char s[] = "world";
|
||||
ep.add(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ElementProxy::operator==()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("1 vs 1") {
|
||||
doc.add(1);
|
||||
doc.add(1);
|
||||
|
||||
REQUIRE(doc[0] <= doc[1]);
|
||||
REQUIRE(doc[0] == doc[1]);
|
||||
REQUIRE(doc[0] >= doc[1]);
|
||||
REQUIRE_FALSE(doc[0] != doc[1]);
|
||||
REQUIRE_FALSE(doc[0] < doc[1]);
|
||||
REQUIRE_FALSE(doc[0] > doc[1]);
|
||||
}
|
||||
|
||||
SECTION("1 vs 2") {
|
||||
doc.add(1);
|
||||
doc.add(2);
|
||||
|
||||
REQUIRE(doc[0] != doc[1]);
|
||||
REQUIRE(doc[0] < doc[1]);
|
||||
REQUIRE(doc[0] <= doc[1]);
|
||||
REQUIRE_FALSE(doc[0] == doc[1]);
|
||||
REQUIRE_FALSE(doc[0] > doc[1]);
|
||||
REQUIRE_FALSE(doc[0] >= doc[1]);
|
||||
}
|
||||
|
||||
SECTION("'abc' vs 'bcd'") {
|
||||
doc.add("abc");
|
||||
doc.add("bcd");
|
||||
|
||||
REQUIRE(doc[0] != doc[1]);
|
||||
REQUIRE(doc[0] < doc[1]);
|
||||
REQUIRE(doc[0] <= doc[1]);
|
||||
REQUIRE_FALSE(doc[0] == doc[1]);
|
||||
REQUIRE_FALSE(doc[0] > doc[1]);
|
||||
REQUIRE_FALSE(doc[0] >= doc[1]);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
TEST_CASE("ElementProxy::set()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
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\"]");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") {
|
||||
char s[] = "world";
|
||||
ep.set(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[\"world\"]");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ElementProxy::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
ElementProxy<JsonDocument&> ep = doc[1];
|
||||
|
||||
SECTION("set member") {
|
||||
ep["world"] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[null,{\"world\":42}]");
|
||||
}
|
||||
|
||||
SECTION("set element") {
|
||||
ep[2] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "[null,[null,null,42]]");
|
||||
}
|
||||
}
|
247
extras/tests/JsonDocument/MemberProxy.cpp
Normal file
247
extras/tests/JsonDocument/MemberProxy.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::add()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("add(int)") {
|
||||
mp.add(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
|
||||
}
|
||||
|
||||
SECTION("add(const char*)") {
|
||||
mp.add("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::clear()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("size goes back to zero") {
|
||||
mp.add(42);
|
||||
mp.clear();
|
||||
|
||||
REQUIRE(mp.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("isNull() return true") {
|
||||
mp.add("hello");
|
||||
mp.clear();
|
||||
|
||||
REQUIRE(mp.isNull() == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::operator==()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("1 vs 1") {
|
||||
doc["a"] = 1;
|
||||
doc["b"] = 1;
|
||||
|
||||
REQUIRE(doc["a"] <= doc["b"]);
|
||||
REQUIRE(doc["a"] == doc["b"]);
|
||||
REQUIRE(doc["a"] >= doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] != doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] < doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] > doc["b"]);
|
||||
}
|
||||
|
||||
SECTION("1 vs 2") {
|
||||
doc["a"] = 1;
|
||||
doc["b"] = 2;
|
||||
|
||||
REQUIRE(doc["a"] != doc["b"]);
|
||||
REQUIRE(doc["a"] < doc["b"]);
|
||||
REQUIRE(doc["a"] <= doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] == doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] > doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] >= doc["b"]);
|
||||
}
|
||||
|
||||
SECTION("'abc' vs 'bcd'") {
|
||||
doc["a"] = "abc";
|
||||
doc["b"] = "bcd";
|
||||
|
||||
REQUIRE(doc["a"] != doc["b"]);
|
||||
REQUIRE(doc["a"] < doc["b"]);
|
||||
REQUIRE(doc["a"] <= doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] == doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] > doc["b"]);
|
||||
REQUIRE_FALSE(doc["a"] >= doc["b"]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::containsKey()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("containsKey(const char*)") {
|
||||
mp["key"] = "value";
|
||||
|
||||
REQUIRE(mp.containsKey("key") == true);
|
||||
REQUIRE(mp.containsKey("key") == true);
|
||||
}
|
||||
|
||||
SECTION("containsKey(std::string)") {
|
||||
mp["key"] = "value";
|
||||
|
||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::operator|()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("const char*") {
|
||||
doc["a"] = "hello";
|
||||
|
||||
REQUIRE((doc["a"] | "world") == std::string("hello"));
|
||||
REQUIRE((doc["b"] | "world") == std::string("world"));
|
||||
}
|
||||
|
||||
SECTION("Issue #1411") {
|
||||
doc["sensor"] = "gps";
|
||||
|
||||
const char *test = "test"; // <- the literal must be captured in a variable
|
||||
// to trigger the bug
|
||||
const char *sensor = doc["sensor"] | test; // "gps"
|
||||
|
||||
REQUIRE(sensor == std::string("gps"));
|
||||
}
|
||||
|
||||
SECTION("Issue #1415") {
|
||||
JsonObject object = doc.to<JsonObject>();
|
||||
object["hello"] = "world";
|
||||
|
||||
StaticJsonDocument<0> emptyDoc;
|
||||
JsonObject anotherObject = object["hello"] | emptyDoc.to<JsonObject>();
|
||||
|
||||
REQUIRE(anotherObject.isNull() == false);
|
||||
REQUIRE(anotherObject.size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::remove()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("remove(int)") {
|
||||
mp.add(1);
|
||||
mp.add(2);
|
||||
mp.add(3);
|
||||
|
||||
mp.remove(1);
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "[1,3]");
|
||||
}
|
||||
|
||||
SECTION("remove(const char *)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
mp.remove("a");
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"b\":2}");
|
||||
}
|
||||
|
||||
SECTION("remove(std::string)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
mp.remove(std::string("b"));
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("remove(vla)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
int i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "b");
|
||||
mp.remove(vla);
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::set()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("set(int)") {
|
||||
mp.set(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":42}");
|
||||
}
|
||||
|
||||
SECTION("set(const char*)") {
|
||||
mp.set("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") { // issue #1191
|
||||
char s[] = "world";
|
||||
mp.set(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::size()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("returns 0") {
|
||||
REQUIRE(mp.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("as an array, return 2") {
|
||||
mp.add(1);
|
||||
mp.add(2);
|
||||
|
||||
REQUIRE(mp.size() == 2);
|
||||
}
|
||||
|
||||
SECTION("as an object, return 2") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
REQUIRE(mp.size() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MemberProxy::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument &, const char *> mp = doc["hello"];
|
||||
|
||||
SECTION("set member") {
|
||||
mp["world"] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}");
|
||||
}
|
||||
|
||||
SECTION("set element") {
|
||||
mp[2] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[null,null,42]}");
|
||||
}
|
||||
}
|
@ -212,7 +212,7 @@ TEST_CASE("StaticJsonDocument") {
|
||||
|
||||
SECTION("garbageCollect()") {
|
||||
StaticJsonDocument<256> doc;
|
||||
doc[std::string("example")] = std::string("example");
|
||||
doc[std::string("example")] = std::string("jukebox");
|
||||
doc.remove("example");
|
||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + 16);
|
||||
|
||||
|
79
extras/tests/JsonDocument/overflowed.cpp
Normal file
79
extras/tests/JsonDocument/overflowed.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonDocument::overflowed()") {
|
||||
SECTION("returns false on a fresh object") {
|
||||
StaticJsonDocument<0> doc;
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("returns true after a failed insertion") {
|
||||
StaticJsonDocument<0> doc;
|
||||
doc.add(0);
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after successful insertion") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
doc.add(0);
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("returns true after a failed string copy") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
doc.add(std::string("example"));
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after a successful string copy") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1) + 8> doc;
|
||||
doc.add(std::string("example"));
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("returns true after a failed deserialization") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
|
||||
deserializeJson(doc, "[\"example\"]");
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false after a successful deserialization") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(1) + 8> doc;
|
||||
deserializeJson(doc, "[\"example\"]");
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("returns false after clear()") {
|
||||
StaticJsonDocument<0> doc;
|
||||
doc.add(0);
|
||||
doc.clear();
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("remains false after shrinkToFit()") {
|
||||
DynamicJsonDocument doc(JSON_ARRAY_SIZE(1));
|
||||
doc.add(0);
|
||||
doc.shrinkToFit();
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
|
||||
SECTION("remains true after shrinkToFit()") {
|
||||
DynamicJsonDocument doc(JSON_ARRAY_SIZE(1));
|
||||
doc.add(0);
|
||||
doc.add(0);
|
||||
doc.shrinkToFit();
|
||||
CHECK(doc.overflowed() == true);
|
||||
}
|
||||
|
||||
SECTION("return false after garbageCollect()") {
|
||||
DynamicJsonDocument doc(JSON_ARRAY_SIZE(1));
|
||||
doc.add(0);
|
||||
doc.add(0);
|
||||
doc.garbageCollect();
|
||||
CHECK(doc.overflowed() == false);
|
||||
}
|
||||
}
|
@ -94,8 +94,8 @@ TEST_CASE("BasicJsonDocument::shrinkToFit()") {
|
||||
}
|
||||
|
||||
SECTION("owned raw") {
|
||||
doc.set(serialized(std::string("[{},123]")));
|
||||
testShrinkToFit(doc, "[{},123]", 8);
|
||||
doc.set(serialized(std::string("[{},12]")));
|
||||
testShrinkToFit(doc, "[{},12]", 8);
|
||||
}
|
||||
|
||||
SECTION("linked key") {
|
||||
|
@ -19,9 +19,4 @@ add_executable(JsonObjectTests
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonObjectTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(JsonObject JsonObjectTests)
|
||||
|
@ -107,43 +107,43 @@ TEST_CASE("JsonObject::operator[]") {
|
||||
|
||||
SECTION("should duplicate char* value") {
|
||||
obj["hello"] = const_cast<char*>("world");
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate char* key") {
|
||||
obj[const_cast<char*>("hello")] = "world";
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate char* key&value") {
|
||||
obj[const_cast<char*>("hello")] = const_cast<char*>("world");
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate std::string value") {
|
||||
obj["hello"] = std::string("world");
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate std::string key") {
|
||||
obj[std::string("hello")] = "world";
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate std::string key&value") {
|
||||
obj[std::string("hello")] = std::string("world");
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
||||
}
|
||||
|
||||
SECTION("should duplicate a non-static JsonString key") {
|
||||
obj[JsonString("hello", false)] = "world";
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||
REQUIRE(expectedSize == doc.memoryUsage());
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,4 @@ add_executable(JsonSerializerTests
|
||||
std_string.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonSerializerTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(JsonSerializer JsonSerializerTests)
|
||||
|
@ -24,9 +24,4 @@ add_executable(JsonVariantTests
|
||||
undefined.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JsonVariantTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(JsonVariant JsonVariantTests)
|
||||
|
@ -10,6 +10,8 @@ namespace my {
|
||||
using ARDUINOJSON_NAMESPACE::isinf;
|
||||
} // namespace my
|
||||
|
||||
enum MY_ENUM { ONE = 1, TWO = 2 };
|
||||
|
||||
TEST_CASE("JsonVariant::as()") {
|
||||
static const char* null = 0;
|
||||
|
||||
@ -212,4 +214,10 @@ TEST_CASE("JsonVariant::as()") {
|
||||
REQUIRE(cvar.as<char*>() == std::string("hello"));
|
||||
// REQUIRE(cvar.as<std::string>() == std::string("hello"));
|
||||
}
|
||||
|
||||
SECTION("as<enum>()") {
|
||||
variant.set(1);
|
||||
|
||||
REQUIRE(variant.as<MY_ENUM>() == ONE);
|
||||
}
|
||||
}
|
||||
|
@ -5,460 +5,276 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
template <typename T>
|
||||
void checkEquals(T a, T b) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set(a);
|
||||
// Most code is already covered by arithmeticCompare.cpp.
|
||||
// Here, we're just filling the holes
|
||||
|
||||
REQUIRE(b == variant);
|
||||
REQUIRE(variant == b);
|
||||
REQUIRE(b <= variant);
|
||||
REQUIRE(variant <= b);
|
||||
REQUIRE(b >= variant);
|
||||
REQUIRE(variant >= b);
|
||||
|
||||
REQUIRE_FALSE(b != variant);
|
||||
REQUIRE_FALSE(variant != b);
|
||||
REQUIRE_FALSE(b > variant);
|
||||
REQUIRE_FALSE(variant > b);
|
||||
REQUIRE_FALSE(b < variant);
|
||||
REQUIRE_FALSE(variant < b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void checkGreater(T a, T b) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set(a);
|
||||
|
||||
REQUIRE(variant > b);
|
||||
REQUIRE(b < variant);
|
||||
REQUIRE(variant != b);
|
||||
REQUIRE(b != variant);
|
||||
|
||||
REQUIRE_FALSE(variant < b);
|
||||
REQUIRE_FALSE(b > variant);
|
||||
REQUIRE_FALSE(variant == b);
|
||||
REQUIRE_FALSE(b == variant);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void checkLower(T a, T b) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set(a);
|
||||
|
||||
REQUIRE(variant < b);
|
||||
REQUIRE(b > variant);
|
||||
REQUIRE(variant != b);
|
||||
REQUIRE(b != variant);
|
||||
|
||||
REQUIRE_FALSE(variant > b);
|
||||
REQUIRE_FALSE(b < variant);
|
||||
REQUIRE_FALSE(variant == b);
|
||||
REQUIRE_FALSE(b == variant);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void checkComparisons(T low, T mid, T high) {
|
||||
checkEquals(mid, mid);
|
||||
checkGreater(mid, low);
|
||||
checkLower(mid, high);
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant comparisons") {
|
||||
static const char* null = 0;
|
||||
|
||||
SECTION("Double") {
|
||||
checkComparisons<double>(123.44, 123.45, 123.46);
|
||||
}
|
||||
|
||||
SECTION("Float") {
|
||||
checkComparisons<float>(123.44f, 123.45f, 123.46f);
|
||||
}
|
||||
|
||||
SECTION("SChar") {
|
||||
checkComparisons<signed char>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("SInt") {
|
||||
checkComparisons<signed int>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("SLong") {
|
||||
checkComparisons<signed long>(122L, 123L, 124L);
|
||||
}
|
||||
|
||||
SECTION("SShort") {
|
||||
checkComparisons<signed short>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("UChar") {
|
||||
checkComparisons<unsigned char>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("UInt") {
|
||||
checkComparisons<unsigned int>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("ULong") {
|
||||
checkComparisons<unsigned long>(122L, 123L, 124L);
|
||||
}
|
||||
|
||||
SECTION("UShort") {
|
||||
checkComparisons<unsigned short>(122, 123, 124);
|
||||
}
|
||||
|
||||
SECTION("null") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set(null);
|
||||
|
||||
REQUIRE(variant == variant);
|
||||
REQUIRE_FALSE(variant != variant);
|
||||
|
||||
REQUIRE(variant == null);
|
||||
REQUIRE_FALSE(variant != null);
|
||||
|
||||
REQUIRE(variant != "null");
|
||||
REQUIRE_FALSE(variant == "null");
|
||||
}
|
||||
|
||||
SECTION("StringLiteral") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
deserializeJson(doc, "\"hello\"");
|
||||
JsonVariant variant = doc.as<JsonVariant>();
|
||||
|
||||
REQUIRE(variant == variant);
|
||||
REQUIRE_FALSE(variant != variant);
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE_FALSE(variant != "hello");
|
||||
|
||||
REQUIRE(variant != "world");
|
||||
REQUIRE_FALSE(variant == "world");
|
||||
|
||||
REQUIRE(variant != null);
|
||||
REQUIRE_FALSE(variant == null);
|
||||
|
||||
REQUIRE("hello" == variant);
|
||||
REQUIRE_FALSE("hello" != variant);
|
||||
|
||||
REQUIRE("world" != variant);
|
||||
REQUIRE_FALSE("world" == variant);
|
||||
|
||||
REQUIRE(null != variant);
|
||||
REQUIRE_FALSE(null == variant);
|
||||
}
|
||||
|
||||
SECTION("String") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set("hello");
|
||||
|
||||
REQUIRE(variant == variant);
|
||||
REQUIRE_FALSE(variant != variant);
|
||||
|
||||
REQUIRE(variant == std::string("hello"));
|
||||
REQUIRE_FALSE(variant != std::string("hello"));
|
||||
|
||||
REQUIRE(variant != std::string("world"));
|
||||
REQUIRE_FALSE(variant == std::string("world"));
|
||||
|
||||
REQUIRE(variant != null);
|
||||
REQUIRE_FALSE(variant == null);
|
||||
|
||||
REQUIRE(std::string("hello") == variant);
|
||||
REQUIRE_FALSE(std::string("hello") != variant);
|
||||
|
||||
REQUIRE(std::string("world") != variant);
|
||||
REQUIRE_FALSE(std::string("world") == variant);
|
||||
|
||||
REQUIRE(null != variant);
|
||||
REQUIRE_FALSE(null == variant);
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("VLA equals") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set("hello");
|
||||
|
||||
REQUIRE((vla == variant));
|
||||
REQUIRE((variant == vla));
|
||||
REQUIRE_FALSE((vla != variant));
|
||||
REQUIRE_FALSE((variant != vla));
|
||||
}
|
||||
|
||||
SECTION("VLA differs") {
|
||||
int i = 16;
|
||||
char vla[i];
|
||||
strcpy(vla, "hello");
|
||||
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
variant.set("world");
|
||||
|
||||
REQUIRE((vla != variant));
|
||||
REQUIRE((variant != vla));
|
||||
REQUIRE_FALSE((vla == variant));
|
||||
REQUIRE_FALSE((variant == vla));
|
||||
}
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc1(4096), doc2(4096), doc3(4096);
|
||||
JsonVariant variant1 = doc1.to<JsonVariant>();
|
||||
JsonVariant variant2 = doc2.to<JsonVariant>();
|
||||
JsonVariant variant3 = doc3.to<JsonVariant>();
|
||||
|
||||
SECTION("Variants containing integers") {
|
||||
variant1.set(42);
|
||||
variant2.set(42);
|
||||
variant3.set(666);
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("Variants containing linked strings") {
|
||||
// create two identical strings at different addresses
|
||||
char hello1[] = "hello";
|
||||
char hello2[] = "hello";
|
||||
REQUIRE(hello1 != hello2);
|
||||
|
||||
variant1.set(hello1);
|
||||
variant2.set(hello2);
|
||||
variant3.set("world");
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("Variants containing owned strings") {
|
||||
variant1.set(std::string("hello"));
|
||||
variant2.set(std::string("hello"));
|
||||
variant3.set(std::string("world"));
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("Variants containing linked raws") {
|
||||
// create two identical strings at different addresses
|
||||
char hello1[] = "hello";
|
||||
char hello2[] = "hello";
|
||||
REQUIRE(hello1 != hello2);
|
||||
|
||||
variant1.set(serialized(hello1));
|
||||
variant2.set(serialized(hello2));
|
||||
variant3.set(serialized("world"));
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("Variants containing owned raws") {
|
||||
variant1.set(serialized(std::string("hello")));
|
||||
variant2.set(serialized(std::string("hello")));
|
||||
variant3.set(serialized(std::string("world")));
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("Variants containing mixed strings (issue #1051)") {
|
||||
variant1.set("hello");
|
||||
variant2.set(std::string("hello"));
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant2 == variant1);
|
||||
REQUIRE_FALSE(variant2 != variant1);
|
||||
}
|
||||
|
||||
SECTION("Variants containing double") {
|
||||
variant1.set(42.0);
|
||||
variant2.set(42.0);
|
||||
variant3.set(666.0);
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("BoolInVariant") {
|
||||
variant1.set(true);
|
||||
variant2.set(true);
|
||||
variant3.set(false);
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("ArrayInVariant") {
|
||||
JsonArray array1 = variant1.to<JsonArray>();
|
||||
JsonArray array2 = variant2.to<JsonArray>();
|
||||
|
||||
array1.add(42);
|
||||
array2.add(42);
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
|
||||
SECTION("ObjectInVariant") {
|
||||
JsonObject obj1 = variant1.to<JsonObject>();
|
||||
JsonObject obj2 = variant2.to<JsonObject>();
|
||||
|
||||
obj1["hello"] = "world";
|
||||
obj2["hello"] = "world";
|
||||
|
||||
REQUIRE(variant1 == variant2);
|
||||
REQUIRE_FALSE(variant1 != variant2);
|
||||
|
||||
REQUIRE(variant1 != variant3);
|
||||
REQUIRE_FALSE(variant1 == variant3);
|
||||
}
|
||||
}
|
||||
|
||||
class VariantComparisionFixture {
|
||||
private:
|
||||
TEST_CASE("Compare JsonVariant with value") {
|
||||
StaticJsonDocument<256> doc;
|
||||
JsonVariant variant;
|
||||
JsonVariant a = doc.addElement();
|
||||
|
||||
public:
|
||||
VariantComparisionFixture() : variant(doc.to<JsonVariant>()) {}
|
||||
SECTION("null vs (char*)0") {
|
||||
char* b = 0;
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void setValue(const T& value) {
|
||||
variant.set(value);
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void assertEqualsTo(const T& value) {
|
||||
REQUIRE(variant == value);
|
||||
REQUIRE(value == variant);
|
||||
SECTION("42 vs 42") {
|
||||
a.set(42);
|
||||
int b = 42;
|
||||
|
||||
REQUIRE_FALSE(variant != value);
|
||||
REQUIRE_FALSE(value != variant);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void assertDiffersFrom(const T& value) {
|
||||
REQUIRE(variant != value);
|
||||
REQUIRE(value != variant);
|
||||
|
||||
REQUIRE_FALSE(variant == value);
|
||||
REQUIRE_FALSE(value == variant);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void assertGreaterThan(const T& value) {
|
||||
REQUIRE((variant > value));
|
||||
REQUIRE((variant >= value));
|
||||
REQUIRE(value < variant);
|
||||
REQUIRE(value <= variant);
|
||||
|
||||
REQUIRE_FALSE((variant < value));
|
||||
REQUIRE_FALSE((variant <= value));
|
||||
REQUIRE_FALSE(value > variant);
|
||||
REQUIRE_FALSE(value >= variant);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void assertLowerThan(const T& value) {
|
||||
REQUIRE(variant < value);
|
||||
REQUIRE(variant <= value);
|
||||
REQUIRE(value > variant);
|
||||
REQUIRE(value >= variant);
|
||||
|
||||
REQUIRE_FALSE(variant > value);
|
||||
REQUIRE_FALSE(variant >= value);
|
||||
REQUIRE_FALSE(value < variant);
|
||||
REQUIRE_FALSE(value <= variant);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(VariantComparisionFixture,
|
||||
"Compare variant with another type") {
|
||||
SECTION("null") {
|
||||
assertDiffersFrom(3);
|
||||
assertDiffersFrom("world");
|
||||
}
|
||||
|
||||
SECTION("string") {
|
||||
setValue("hello");
|
||||
assertEqualsTo("hello");
|
||||
assertDiffersFrom(3);
|
||||
assertDiffersFrom("world");
|
||||
assertGreaterThan("helln");
|
||||
assertLowerThan("hellp");
|
||||
}
|
||||
|
||||
SECTION("positive integer") {
|
||||
setValue(42);
|
||||
assertEqualsTo(42);
|
||||
assertDiffersFrom(43);
|
||||
assertGreaterThan(41);
|
||||
assertLowerThan(43);
|
||||
assertDiffersFrom("world");
|
||||
}
|
||||
|
||||
SECTION("negative integer") {
|
||||
setValue(-42);
|
||||
assertEqualsTo(-42);
|
||||
assertDiffersFrom(42);
|
||||
assertGreaterThan(-43);
|
||||
assertLowerThan(-41);
|
||||
assertDiffersFrom("world");
|
||||
}
|
||||
|
||||
SECTION("double") {
|
||||
setValue(42.0);
|
||||
assertEqualsTo(42.0);
|
||||
assertDiffersFrom(42.1);
|
||||
assertGreaterThan(41.0);
|
||||
assertLowerThan(43.0);
|
||||
assertDiffersFrom("42.0");
|
||||
}
|
||||
|
||||
SECTION("true") {
|
||||
setValue(true);
|
||||
assertEqualsTo(true);
|
||||
assertDiffersFrom(false);
|
||||
assertDiffersFrom(1);
|
||||
assertDiffersFrom("true");
|
||||
assertDiffersFrom(1.0);
|
||||
assertGreaterThan(false);
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Compare JsonVariant with JsonVariant") {
|
||||
StaticJsonDocument<256> doc;
|
||||
JsonVariant a = doc.addElement();
|
||||
JsonVariant b = doc.addElement();
|
||||
|
||||
SECTION("'abc' vs 'abc'") {
|
||||
a.set("abc");
|
||||
b.set("abc");
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("'abc' vs 'bcd'") {
|
||||
a.set("abc");
|
||||
b.set("bcd");
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("'bcd' vs 'abc'") {
|
||||
a.set("bcd");
|
||||
b.set("abc");
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("serialized('abc') vs serialized('abc')") {
|
||||
a.set(serialized("abc"));
|
||||
b.set(serialized("abc"));
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("serialized('abc') vs serialized('bcd')") {
|
||||
a.set(serialized("abc"));
|
||||
b.set(serialized("bcd"));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("serialized('bcd') vs serialized('abc')") {
|
||||
a.set(serialized("bcd"));
|
||||
b.set(serialized("abc"));
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("false vs true") {
|
||||
a.set(false);
|
||||
b.set(true);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("false vs -1") {
|
||||
a.set(false);
|
||||
b.set(-1);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("null vs null") {
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42") {
|
||||
a.set(42);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42 vs 42.0") {
|
||||
a.set(42);
|
||||
b.set(42.0);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("42.0 vs 42") {
|
||||
a.set(42.0);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("-42 vs -42") {
|
||||
a.set(-42);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK(a <= b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("-42 vs 42") {
|
||||
a.set(-42);
|
||||
b.set(42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a < b);
|
||||
CHECK(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("42 vs -42") {
|
||||
a.set(42);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("42.0 vs -42") {
|
||||
a.set(42.0);
|
||||
b.set(-42);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK(a > b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
}
|
||||
|
||||
SECTION("[1] vs [1]") {
|
||||
a.add(1);
|
||||
b.add(1);
|
||||
|
||||
CHECK(a <= b);
|
||||
CHECK(a == b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("[1] vs [2]") {
|
||||
a.add(1);
|
||||
b.add(2);
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
|
||||
SECTION("{x:1} vs {x:1}") {
|
||||
a["x"] = 1;
|
||||
b["x"] = 1;
|
||||
|
||||
CHECK(a <= b);
|
||||
CHECK(a == b);
|
||||
CHECK(a >= b);
|
||||
CHECK_FALSE(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a > b);
|
||||
}
|
||||
|
||||
SECTION("{x:1} vs {x:2}") {
|
||||
a["x"] = 1;
|
||||
b["x"] = 2;
|
||||
|
||||
CHECK(a != b);
|
||||
CHECK_FALSE(a < b);
|
||||
CHECK_FALSE(a <= b);
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK_FALSE(a > b);
|
||||
CHECK_FALSE(a >= b);
|
||||
}
|
||||
}
|
||||
|
@ -47,20 +47,20 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
||||
var1.set(str);
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
}
|
||||
|
||||
SECTION("stores std::string by copy") {
|
||||
var1.set(std::string("hello!!"));
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
}
|
||||
|
||||
SECTION("stores Serialized<const char*> by reference") {
|
||||
var1.set(serialized("hello!!", JSON_STRING_SIZE(8)));
|
||||
var1.set(serialized("hello!!", 8));
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc1.memoryUsage() == 0);
|
||||
@ -69,18 +69,18 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
||||
|
||||
SECTION("stores Serialized<char*> by copy") {
|
||||
char str[] = "hello!!";
|
||||
var1.set(serialized(str, 8));
|
||||
var1.set(serialized(str, 7));
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
}
|
||||
|
||||
SECTION("stores Serialized<std::string> by copy") {
|
||||
var1.set(serialized(std::string("hello!!!")));
|
||||
var1.set(serialized(std::string("hello!!")));
|
||||
var2.set(var1);
|
||||
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
enum MYENUM2 { ONE = 1, TWO = 2 };
|
||||
|
||||
template <typename TVariant>
|
||||
void checkIsArray(TVariant var) {
|
||||
REQUIRE(var.template is<JsonArray>());
|
||||
@ -80,6 +82,7 @@ void checkIsInteger(TVariant var) {
|
||||
REQUIRE(var.template is<int>());
|
||||
REQUIRE(var.template is<float>());
|
||||
REQUIRE(var.template is<double>());
|
||||
REQUIRE(var.template is<MYENUM2>());
|
||||
|
||||
REQUIRE_FALSE(var.template is<bool>());
|
||||
REQUIRE_FALSE(var.template is<const char *>());
|
||||
@ -107,6 +110,7 @@ void checkIsString(TVariant var) {
|
||||
REQUIRE_FALSE(var.template is<double>());
|
||||
REQUIRE_FALSE(var.template is<float>());
|
||||
REQUIRE_FALSE(var.template is<long>());
|
||||
REQUIRE_FALSE(var.template is<MYENUM2>());
|
||||
REQUIRE_FALSE(var.template is<JsonArray>());
|
||||
REQUIRE_FALSE(var.template is<JsonObject>());
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
TEST_CASE("JsonVariant::operator|()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
JsonVariant variant = doc["value"].to<JsonVariant>();
|
||||
|
||||
SECTION("undefined") {
|
||||
SECTION("undefined | const char*") {
|
||||
@ -24,6 +24,27 @@ TEST_CASE("JsonVariant::operator|()") {
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == true);
|
||||
}
|
||||
|
||||
SECTION("undefined | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("undefined | MemberProxy") {
|
||||
doc["other"] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("ElementProxy | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = doc["array"][1] | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null") {
|
||||
@ -43,6 +64,20 @@ TEST_CASE("JsonVariant::operator|()") {
|
||||
bool result = variant | true;
|
||||
REQUIRE(result == true);
|
||||
}
|
||||
|
||||
SECTION("null | ElementProxy") {
|
||||
doc["array"][0] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("null | MemberProxy") {
|
||||
doc["other"] = 42;
|
||||
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("int | const char*") {
|
||||
@ -57,6 +92,20 @@ TEST_CASE("JsonVariant::operator|()") {
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | ElementProxy") {
|
||||
variant.set(42);
|
||||
doc["array"][0] = 666;
|
||||
JsonVariantConst result = variant | doc["array"][0];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | MemberProxy") {
|
||||
variant.set(42);
|
||||
doc["other"] = 666;
|
||||
JsonVariantConst result = variant | doc["other"];
|
||||
REQUIRE(result == 42);
|
||||
}
|
||||
|
||||
SECTION("int | int") {
|
||||
variant.set(0);
|
||||
int result = variant | 666;
|
||||
@ -88,6 +137,20 @@ TEST_CASE("JsonVariant::operator|()") {
|
||||
REQUIRE(result == "not default");
|
||||
}
|
||||
|
||||
SECTION("const char* | char*") {
|
||||
char dflt[] = "default";
|
||||
variant.set("not default");
|
||||
std::string result = variant | dflt;
|
||||
REQUIRE(result == "not default");
|
||||
}
|
||||
|
||||
SECTION("int | char*") {
|
||||
char dflt[] = "default";
|
||||
variant.set(42);
|
||||
std::string result = variant | dflt;
|
||||
REQUIRE(result == "default");
|
||||
}
|
||||
|
||||
SECTION("const char* | int") {
|
||||
variant.set("not default");
|
||||
int result = variant | 42;
|
||||
|
@ -7,115 +7,150 @@
|
||||
|
||||
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
|
||||
|
||||
TEST_CASE("JsonVariant and strings") {
|
||||
TEST_CASE("JsonVariant::set() when there is enough memory") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonVariant variant = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("stores const char* by reference") {
|
||||
SECTION("const char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(static_cast<const char *>(str));
|
||||
bool result = variant.set(static_cast<const char *>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "world");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "world"); // stores by pointer
|
||||
}
|
||||
|
||||
SECTION("stores char* by copy") {
|
||||
char str[16];
|
||||
SECTION("(const char*)0") {
|
||||
bool result = variant.set(static_cast<const char *>(0));
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(str);
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.isNull());
|
||||
}
|
||||
|
||||
SECTION("stores unsigned char* by copy") {
|
||||
SECTION("char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(reinterpret_cast<unsigned char *>(str));
|
||||
bool result = variant.set(str);
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
|
||||
SECTION("stores signed char* by copy") {
|
||||
SECTION("(char*)0") {
|
||||
bool result = variant.set(static_cast<char *>(0));
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.isNull());
|
||||
}
|
||||
|
||||
SECTION("unsigned char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(reinterpret_cast<signed char *>(str));
|
||||
bool result = variant.set(reinterpret_cast<unsigned char *>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
|
||||
SECTION("signed char*") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
bool result = variant.set(reinterpret_cast<signed char *>(str));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("stores VLA by copy") {
|
||||
SECTION("VLA") {
|
||||
int n = 16;
|
||||
char str[n];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(str);
|
||||
bool result = variant.set(str);
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("stores std::string by copy") {
|
||||
SECTION("std::string") {
|
||||
std::string str;
|
||||
|
||||
str = "hello";
|
||||
variant.set(str);
|
||||
bool result = variant.set(str);
|
||||
str.replace(0, 5, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
|
||||
SECTION("stores static JsonString by reference") {
|
||||
SECTION("static JsonString") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(JsonString(str, true));
|
||||
bool result = variant.set(JsonString(str, true));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "world");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "world"); // stores by pointer
|
||||
}
|
||||
|
||||
SECTION("stores non-static JsonString by copy") {
|
||||
SECTION("non-static JsonString") {
|
||||
char str[16];
|
||||
|
||||
strcpy(str, "hello");
|
||||
variant.set(JsonString(str, false));
|
||||
bool result = variant.set(JsonString(str, false));
|
||||
strcpy(str, "world");
|
||||
|
||||
REQUIRE(variant == "hello");
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant == "hello"); // stores by copy
|
||||
}
|
||||
|
||||
SECTION("stores an enum as an integer") {
|
||||
SECTION("enum") {
|
||||
ErrorCode code = ERROR_10;
|
||||
|
||||
variant.set(code);
|
||||
bool result = variant.set(code);
|
||||
|
||||
REQUIRE(result == true);
|
||||
REQUIRE(variant.is<int>() == true);
|
||||
REQUIRE(variant.as<int>() == 10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonVariant with not enough memory") {
|
||||
TEST_CASE("JsonVariant::set() with not enough memory") {
|
||||
StaticJsonDocument<1> doc;
|
||||
|
||||
JsonVariant v = doc.to<JsonVariant>();
|
||||
|
||||
SECTION("std::string") {
|
||||
v.set(std::string("hello world!!"));
|
||||
bool result = v.set(std::string("hello world!!"));
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("Serialized<std::string>") {
|
||||
v.set(serialized(std::string("hello world!!")));
|
||||
bool result = v.set(serialized(std::string("hello world!!")));
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char s[] = "hello world!!";
|
||||
bool result = v.set(s);
|
||||
|
||||
REQUIRE(result == false);
|
||||
REQUIRE(v.isNull());
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2020
|
||||
# MIT License
|
||||
|
||||
add_executable(MemberProxyTests
|
||||
add.cpp
|
||||
clear.cpp
|
||||
compare.cpp
|
||||
containsKey.cpp
|
||||
remove.cpp
|
||||
set.cpp
|
||||
size.cpp
|
||||
subscript.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MemberProxyTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(MemberProxy MemberProxyTests)
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::add()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("add(int)") {
|
||||
mp.add(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
|
||||
}
|
||||
|
||||
SECTION("add(const char*)") {
|
||||
mp.add("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::clear()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("size goes back to zero") {
|
||||
mp.add(42);
|
||||
mp.clear();
|
||||
|
||||
REQUIRE(mp.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("isNull() return true") {
|
||||
mp.add("hello");
|
||||
mp.clear();
|
||||
|
||||
REQUIRE(mp.isNull() == true);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::operator==()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
|
||||
SECTION("same values") {
|
||||
doc["key1"] = "value";
|
||||
doc["key2"] = "value";
|
||||
REQUIRE(doc["key1"] == doc["key2"]);
|
||||
REQUIRE_FALSE(doc["key1"] != doc["key2"]);
|
||||
}
|
||||
|
||||
SECTION("different values") {
|
||||
doc["key1"] = "value1";
|
||||
doc["key2"] = "value2";
|
||||
REQUIRE_FALSE(doc["key1"] == doc["key2"]);
|
||||
REQUIRE(doc["key1"] != doc["key2"]);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::containsKey()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("containsKey(const char*)") {
|
||||
mp["key"] = "value";
|
||||
|
||||
REQUIRE(mp.containsKey("key") == true);
|
||||
REQUIRE(mp.containsKey("key") == true);
|
||||
}
|
||||
|
||||
SECTION("containsKey(std::string)") {
|
||||
mp["key"] = "value";
|
||||
|
||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
||||
REQUIRE(mp.containsKey(std::string("key")) == true);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::remove()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("remove(int)") {
|
||||
mp.add(1);
|
||||
mp.add(2);
|
||||
mp.add(3);
|
||||
|
||||
mp.remove(1);
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "[1,3]");
|
||||
}
|
||||
|
||||
SECTION("remove(const char *)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
mp.remove("a");
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"b\":2}");
|
||||
}
|
||||
|
||||
SECTION("remove(std::string)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
mp.remove(std::string("b"));
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
|
||||
#ifdef HAS_VARIABLE_LENGTH_ARRAY
|
||||
SECTION("remove(vla)") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
int i = 4;
|
||||
char vla[i];
|
||||
strcpy(vla, "b");
|
||||
mp.remove(vla);
|
||||
|
||||
REQUIRE(mp.as<std::string>() == "{\"a\":1}");
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::set()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("set(int)") {
|
||||
mp.set(42);
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":42}");
|
||||
}
|
||||
|
||||
SECTION("set(const char*)") {
|
||||
mp.set("world");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
SECTION("set(char[])") { // issue #1191
|
||||
char s[] = "world";
|
||||
mp.set(s);
|
||||
strcpy(s, "!!!!!");
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::size()") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("returns 0") {
|
||||
REQUIRE(mp.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("as an array, return 2") {
|
||||
mp.add(1);
|
||||
mp.add(2);
|
||||
|
||||
REQUIRE(mp.size() == 2);
|
||||
}
|
||||
|
||||
SECTION("as an object, return 2") {
|
||||
mp["a"] = 1;
|
||||
mp["b"] = 2;
|
||||
|
||||
REQUIRE(mp.size() == 2);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemberProxy::operator[]") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||
|
||||
SECTION("set member") {
|
||||
mp["world"] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}");
|
||||
}
|
||||
|
||||
SECTION("set element") {
|
||||
mp[2] = 42;
|
||||
|
||||
REQUIRE(doc.as<std::string>() == "{\"hello\":[null,null,42]}");
|
||||
}
|
||||
}
|
@ -4,15 +4,10 @@
|
||||
|
||||
add_executable(MemoryPoolTests
|
||||
allocVariant.cpp
|
||||
allocString.cpp
|
||||
clear.cpp
|
||||
saveString.cpp
|
||||
size.cpp
|
||||
StringBuilder.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MemoryPoolTests
|
||||
ArduinoJson
|
||||
catch
|
||||
StringCopier.cpp
|
||||
)
|
||||
|
||||
add_test(MemoryPool MemoryPoolTests)
|
||||
|
@ -1,41 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Memory/StringBuilder.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("StringBuilder") {
|
||||
char buffer[4096];
|
||||
|
||||
SECTION("Works when buffer is big enough") {
|
||||
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6)));
|
||||
|
||||
StringBuilder str(&pool);
|
||||
str.append("hello");
|
||||
|
||||
REQUIRE(str.complete() == std::string("hello"));
|
||||
}
|
||||
|
||||
SECTION("Returns null when too small") {
|
||||
MemoryPool pool(buffer, sizeof(void*));
|
||||
|
||||
StringBuilder str(&pool);
|
||||
str.append("hello world!");
|
||||
|
||||
REQUIRE(str.complete() == 0);
|
||||
}
|
||||
|
||||
SECTION("Increases size of memory pool") {
|
||||
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6)));
|
||||
|
||||
StringBuilder str(&pool);
|
||||
str.append('h');
|
||||
str.complete();
|
||||
|
||||
REQUIRE(JSON_STRING_SIZE(2) == pool.size());
|
||||
}
|
||||
}
|
84
extras/tests/MemoryPool/StringCopier.cpp
Normal file
84
extras/tests/MemoryPool/StringCopier.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/StringStorage/StringCopier.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("StringCopier") {
|
||||
char buffer[4096];
|
||||
|
||||
SECTION("Works when buffer is big enough") {
|
||||
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6)));
|
||||
StringCopier str(pool);
|
||||
|
||||
str.startString();
|
||||
str.append("hello");
|
||||
str.append('\0');
|
||||
|
||||
REQUIRE(str.isValid() == true);
|
||||
REQUIRE(str.c_str() == std::string("hello"));
|
||||
}
|
||||
|
||||
SECTION("Returns null when too small") {
|
||||
MemoryPool pool(buffer, sizeof(void*));
|
||||
StringCopier str(pool);
|
||||
|
||||
str.startString();
|
||||
str.append("hello world!");
|
||||
|
||||
REQUIRE(str.isValid() == false);
|
||||
}
|
||||
|
||||
SECTION("Increases size of memory pool") {
|
||||
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6)));
|
||||
StringCopier str(pool);
|
||||
|
||||
str.startString();
|
||||
str.append('h');
|
||||
str.save();
|
||||
|
||||
REQUIRE(1 == pool.size());
|
||||
}
|
||||
}
|
||||
|
||||
static const char* addStringToPool(MemoryPool& pool, const char* s) {
|
||||
StringCopier str(pool);
|
||||
str.startString();
|
||||
str.append(s);
|
||||
str.append('\0');
|
||||
return str.save();
|
||||
}
|
||||
|
||||
TEST_CASE("StringCopier::save() deduplicates strings") {
|
||||
char buffer[4096];
|
||||
MemoryPool pool(buffer, 4096);
|
||||
|
||||
SECTION("Basic") {
|
||||
const char* s1 = addStringToPool(pool, "hello");
|
||||
const char* s2 = addStringToPool(pool, "world");
|
||||
const char* s3 = addStringToPool(pool, "hello");
|
||||
|
||||
REQUIRE(s1 == s3);
|
||||
REQUIRE(s2 != s3);
|
||||
REQUIRE(pool.size() == 12);
|
||||
}
|
||||
|
||||
SECTION("Requires terminator") {
|
||||
const char* s1 = addStringToPool(pool, "hello world");
|
||||
const char* s2 = addStringToPool(pool, "hello");
|
||||
|
||||
REQUIRE(s2 != s1);
|
||||
REQUIRE(pool.size() == 12 + 6);
|
||||
}
|
||||
|
||||
SECTION("Don't overrun") {
|
||||
const char* s1 = addStringToPool(pool, "hello world");
|
||||
const char* s2 = addStringToPool(pool, "wor");
|
||||
|
||||
REQUIRE(s2 != s1);
|
||||
REQUIRE(pool.size() == 12 + 4);
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("MemoryPool::allocFrozenString()") {
|
||||
const size_t poolCapacity = 64;
|
||||
const size_t longestString = poolCapacity;
|
||||
char buffer[poolCapacity];
|
||||
MemoryPool pool(buffer, poolCapacity);
|
||||
|
||||
SECTION("Returns different addresses") {
|
||||
char *a = pool.allocFrozenString(1);
|
||||
char *b = pool.allocFrozenString(1);
|
||||
REQUIRE(a != b);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when full") {
|
||||
void *p1 = pool.allocFrozenString(longestString);
|
||||
REQUIRE(p1 != 0);
|
||||
|
||||
void *p2 = pool.allocFrozenString(1);
|
||||
REQUIRE(p2 == 0);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when pool is too small") {
|
||||
void *p = pool.allocFrozenString(longestString + 1);
|
||||
REQUIRE(0 == p);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when buffer is NULL") {
|
||||
MemoryPool pool2(0, poolCapacity);
|
||||
REQUIRE(0 == pool2.allocFrozenString(2));
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when capacity is 0") {
|
||||
MemoryPool pool2(buffer, 0);
|
||||
REQUIRE(0 == pool2.allocFrozenString(2));
|
||||
}
|
||||
|
||||
SECTION("Returns same address after clear()") {
|
||||
void *a = pool.allocFrozenString(1);
|
||||
pool.clear();
|
||||
void *b = pool.allocFrozenString(1);
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity when fresh") {
|
||||
void *a = pool.allocFrozenString(longestString);
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity after clear") {
|
||||
pool.allocFrozenString(longestString);
|
||||
pool.clear();
|
||||
|
||||
void *a = pool.allocFrozenString(longestString);
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
@ -21,8 +22,8 @@ TEST_CASE("MemoryPool::clear()") {
|
||||
}
|
||||
|
||||
SECTION("Discards allocated strings") {
|
||||
pool.allocFrozenString(10);
|
||||
REQUIRE(pool.size() > 0);
|
||||
pool.saveString(adaptString(const_cast<char *>("123456789")));
|
||||
REQUIRE(pool.size() == 10);
|
||||
|
||||
pool.clear();
|
||||
|
||||
|
81
extras/tests/MemoryPool/saveString.cpp
Normal file
81
extras/tests/MemoryPool/saveString.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
static const char *saveString(MemoryPool &pool, const char *s) {
|
||||
return pool.saveString(adaptString(const_cast<char *>(s)));
|
||||
}
|
||||
|
||||
TEST_CASE("MemoryPool::saveString()") {
|
||||
char buffer[32];
|
||||
MemoryPool pool(buffer, 32);
|
||||
|
||||
SECTION("Duplicates different strings") {
|
||||
const char *a = saveString(pool, "hello");
|
||||
const char *b = saveString(pool, "world");
|
||||
REQUIRE(a != b);
|
||||
REQUIRE(pool.size() == 6 + 6);
|
||||
}
|
||||
|
||||
SECTION("Deduplicates identical strings") {
|
||||
const char *a = saveString(pool, "hello");
|
||||
const char *b = saveString(pool, "hello");
|
||||
REQUIRE(a == b);
|
||||
REQUIRE(pool.size() == 6);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when full") {
|
||||
REQUIRE(pool.capacity() == 32);
|
||||
|
||||
const void *p1 = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
REQUIRE(p1 != 0);
|
||||
REQUIRE(pool.size() == 32);
|
||||
|
||||
const void *p2 = saveString(pool, "b");
|
||||
REQUIRE(p2 == 0);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when pool is too small") {
|
||||
const void *p = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
REQUIRE(0 == p);
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when buffer is NULL") {
|
||||
MemoryPool pool2(0, 32);
|
||||
REQUIRE(0 == saveString(pool2, "a"));
|
||||
}
|
||||
|
||||
SECTION("Returns NULL when capacity is 0") {
|
||||
MemoryPool pool2(buffer, 0);
|
||||
REQUIRE(0 == saveString(pool2, "a"));
|
||||
}
|
||||
|
||||
SECTION("Returns same address after clear()") {
|
||||
const void *a = saveString(pool, "hello");
|
||||
pool.clear();
|
||||
const void *b = saveString(pool, "world");
|
||||
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity when fresh") {
|
||||
const void *a = saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
|
||||
SECTION("Can use full capacity after clear") {
|
||||
saveString(pool, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
pool.clear();
|
||||
|
||||
const void *a = saveString(pool, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
||||
|
||||
REQUIRE(a != 0);
|
||||
}
|
||||
}
|
@ -22,29 +22,6 @@ TEST_CASE("MemoryPool::size()") {
|
||||
REQUIRE(0 == pool.size());
|
||||
}
|
||||
|
||||
SECTION("size() == capacity() after allocExpandableString()") {
|
||||
pool.allocExpandableString();
|
||||
REQUIRE(pool.size() == pool.capacity());
|
||||
}
|
||||
|
||||
SECTION("Decreases after freezeString()") {
|
||||
StringSlot a = pool.allocExpandableString();
|
||||
pool.freezeString(a, 1);
|
||||
REQUIRE(pool.size() == JSON_STRING_SIZE(1));
|
||||
|
||||
StringSlot b = pool.allocExpandableString();
|
||||
pool.freezeString(b, 1);
|
||||
REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(1));
|
||||
}
|
||||
|
||||
SECTION("Increases after allocFrozenString()") {
|
||||
pool.allocFrozenString(0);
|
||||
REQUIRE(pool.size() == JSON_STRING_SIZE(0));
|
||||
|
||||
pool.allocFrozenString(0);
|
||||
REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(0));
|
||||
}
|
||||
|
||||
SECTION("Doesn't grow when memory pool is full") {
|
||||
const size_t variantCount = sizeof(buffer) / sizeof(VariantSlot);
|
||||
|
||||
|
@ -3,56 +3,20 @@
|
||||
# MIT License
|
||||
|
||||
add_executable(MiscTests
|
||||
arithmeticCompare.cpp
|
||||
conflicts.cpp
|
||||
FloatParts.cpp
|
||||
JsonString.cpp
|
||||
Readers.cpp
|
||||
StringAdapters.cpp
|
||||
StringWriter.cpp
|
||||
TypeTraits.cpp
|
||||
unsigned_char.cpp
|
||||
Utf8.cpp
|
||||
Utf16.cpp
|
||||
Utf8.cpp
|
||||
version.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MiscTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
set_target_properties(MiscTests PROPERTIES UNITY_BUILD OFF)
|
||||
|
||||
add_test(Misc MiscTests)
|
||||
|
||||
macro(build_should_fail target)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL TRUE
|
||||
EXCLUDE_FROM_DEFAULT_BUILD TRUE
|
||||
)
|
||||
add_test(
|
||||
NAME
|
||||
${target}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} --build . --target ${target} --config $<CONFIGURATION>
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
set_tests_properties(${target}
|
||||
|
||||
|
||||
|
||||
PROPERTIES
|
||||
WILL_FAIL TRUE)
|
||||
endmacro()
|
||||
|
||||
|
||||
add_executable(Issue978
|
||||
Issue978.cpp
|
||||
)
|
||||
build_should_fail(Issue978)
|
||||
|
||||
add_executable(Issue1189
|
||||
Issue1189.cpp
|
||||
)
|
||||
build_should_fail(Issue1189)
|
||||
|
60
extras/tests/Misc/JsonString.cpp
Normal file
60
extras/tests/Misc/JsonString.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("JsonString") {
|
||||
SECTION("Default constructor creates a null JsonString") {
|
||||
JsonString s;
|
||||
|
||||
CHECK(s.isNull() == true);
|
||||
CHECK(s.c_str() == 0);
|
||||
CHECK(s.isStatic() == true);
|
||||
}
|
||||
|
||||
SECTION("Compare null with null") {
|
||||
JsonString a, b;
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK_FALSE(a != b);
|
||||
}
|
||||
|
||||
SECTION("Compare null with non-null") {
|
||||
JsonString a(0), b("hello");
|
||||
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK(a != b);
|
||||
}
|
||||
|
||||
SECTION("Compare non-null with null") {
|
||||
JsonString a("hello"), b(0);
|
||||
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK(a != b);
|
||||
}
|
||||
|
||||
SECTION("Compare different strings") {
|
||||
JsonString a("hello"), b("world");
|
||||
|
||||
CHECK_FALSE(a == b);
|
||||
CHECK(a != b);
|
||||
}
|
||||
|
||||
SECTION("Compare identical by pointer") {
|
||||
JsonString a("hello"), b("hello");
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK_FALSE(a != b);
|
||||
}
|
||||
|
||||
SECTION("Compare identical by value") {
|
||||
char s1[] = "hello";
|
||||
char s2[] = "hello";
|
||||
JsonString a(s1), b(s2);
|
||||
|
||||
CHECK(a == b);
|
||||
CHECK_FALSE(a != b);
|
||||
}
|
||||
}
|
@ -6,10 +6,11 @@
|
||||
#include "progmem_emulation.hpp"
|
||||
#include "weird_strcmp.hpp"
|
||||
|
||||
#include <ArduinoJson/Strings/ArduinoStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/FlashStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/StlStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/StdStringAdapter.hpp>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
@ -101,7 +102,22 @@ TEST_CASE("FlashStringAdapter") {
|
||||
|
||||
TEST_CASE("std::string") {
|
||||
std::string str("bravo");
|
||||
StlStringAdapter<std::string> adapter = adaptString(str);
|
||||
StdStringAdapter<std::string> adapter = adaptString(str);
|
||||
|
||||
CHECK(adapter.compare(NULL) > 0);
|
||||
CHECK(adapter.compare("alpha") > 0);
|
||||
CHECK(adapter.compare("bravo") == 0);
|
||||
CHECK(adapter.compare("charlie") < 0);
|
||||
|
||||
CHECK(adapter.equals("bravo"));
|
||||
CHECK_FALSE(adapter.equals("charlie"));
|
||||
|
||||
CHECK(adapter.size() == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("Arduino String") {
|
||||
::String str("bravo");
|
||||
ArduinoStringAdapter adapter = adaptString(str);
|
||||
|
||||
CHECK(adapter.compare(NULL) > 0);
|
||||
CHECK(adapter.compare("alpha") > 0);
|
||||
@ -116,7 +132,7 @@ TEST_CASE("std::string") {
|
||||
|
||||
TEST_CASE("custom_string") {
|
||||
custom_string str("bravo");
|
||||
StlStringAdapter<custom_string> adapter = adaptString(str);
|
||||
StdStringAdapter<custom_string> adapter = adaptString(str);
|
||||
|
||||
CHECK(adapter.compare(NULL) > 0);
|
||||
CHECK(adapter.compare("alpha") > 0);
|
||||
@ -145,4 +161,12 @@ TEST_CASE("IsString<T>") {
|
||||
SECTION("const __FlashStringHelper*") {
|
||||
CHECK(IsString<const __FlashStringHelper*>::value == true);
|
||||
}
|
||||
|
||||
SECTION("const char*") {
|
||||
CHECK(IsString<const char*>::value == true);
|
||||
}
|
||||
|
||||
SECTION("const char[]") {
|
||||
CHECK(IsString<const char[8]>::value == true);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,24 @@ TEST_CASE("Polyfills/type_traits") {
|
||||
CHECK(is_const<const char>::value == true);
|
||||
}
|
||||
|
||||
SECTION("is_integral") {
|
||||
CHECK(is_integral<double>::value == false);
|
||||
CHECK(is_integral<float>::value == false);
|
||||
|
||||
CHECK(is_integral<bool>::value == true);
|
||||
CHECK(is_integral<char>::value == true);
|
||||
CHECK(is_integral<signed char>::value == true);
|
||||
CHECK(is_integral<signed int>::value == true);
|
||||
CHECK(is_integral<signed long>::value == true);
|
||||
CHECK(is_integral<signed short>::value == true);
|
||||
CHECK(is_integral<unsigned char>::value == true);
|
||||
CHECK(is_integral<unsigned int>::value == true);
|
||||
CHECK(is_integral<unsigned long>::value == true);
|
||||
CHECK(is_integral<unsigned short>::value == true);
|
||||
|
||||
CHECK(is_integral<UInt>::value == true);
|
||||
}
|
||||
|
||||
SECTION("is_signed") {
|
||||
CHECK(is_signed<char>::value == true);
|
||||
CHECK(is_signed<signed char>::value == true);
|
||||
|
@ -12,12 +12,14 @@ using namespace ARDUINOJSON_NAMESPACE;
|
||||
static void testCodepoint(uint32_t codepoint, std::string expected) {
|
||||
char buffer[4096];
|
||||
MemoryPool pool(buffer, 4096);
|
||||
StringBuilder str(&pool);
|
||||
StringCopier str(pool);
|
||||
str.startString();
|
||||
|
||||
CAPTURE(codepoint);
|
||||
Utf8::encodeCodepoint(codepoint, str);
|
||||
|
||||
REQUIRE(str.complete() == expected);
|
||||
str.append('\0');
|
||||
REQUIRE(str.c_str() == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("Utf8::encodeCodepoint()") {
|
||||
|
103
extras/tests/Misc/arithmeticCompare.cpp
Normal file
103
extras/tests/Misc/arithmeticCompare.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
TEST_CASE("arithmeticCompare()") {
|
||||
SECTION("int vs uint8_t") {
|
||||
CHECK((arithmeticCompare<int, uint8_t>(256, 1) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<int, uint8_t>(41, 42) == COMPARE_RESULT_LESS));
|
||||
CHECK((arithmeticCompare<int, uint8_t>(42, 42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<int, uint8_t>(43, 42) == COMPARE_RESULT_GREATER));
|
||||
}
|
||||
|
||||
SECTION("unsigned vs int") {
|
||||
CHECK((arithmeticCompare<unsigned, int>(0, -1) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<unsigned, int>(42, 41) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<unsigned, int>(42, 42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<unsigned, int>(42, 43) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("float vs int") {
|
||||
CHECK((arithmeticCompare<float, int>(42, 41) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<float, int>(42, 42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<float, int>(42, 43) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("int vs unsigned") {
|
||||
CHECK((arithmeticCompare<int, unsigned>(-1, 0) == COMPARE_RESULT_LESS));
|
||||
CHECK((arithmeticCompare<int, unsigned>(0, 0) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<int, unsigned>(1, 0) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<int, unsigned>(42, 41) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<int, unsigned>(42, 42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<int, unsigned>(42, 43) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("unsigned vs unsigned") {
|
||||
CHECK((arithmeticCompare<unsigned, unsigned>(42, 41) ==
|
||||
COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<unsigned, unsigned>(42, 42) ==
|
||||
COMPARE_RESULT_EQUAL));
|
||||
CHECK(
|
||||
(arithmeticCompare<unsigned, unsigned>(42, 43) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("bool vs bool") {
|
||||
CHECK(
|
||||
(arithmeticCompare<bool, bool>(false, false) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<bool, bool>(true, true) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<bool, bool>(false, true) == COMPARE_RESULT_LESS));
|
||||
CHECK(
|
||||
(arithmeticCompare<bool, bool>(true, false) == COMPARE_RESULT_GREATER));
|
||||
}
|
||||
|
||||
SECTION("bool vs int") {
|
||||
CHECK((arithmeticCompare<bool, int>(false, -1) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<bool, int>(false, 0) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<bool, int>(false, 1) == COMPARE_RESULT_LESS));
|
||||
CHECK((arithmeticCompare<bool, int>(true, 0) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<bool, int>(true, 1) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<bool, int>(true, 2) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("bool vs int") {
|
||||
CHECK((arithmeticCompare<int, bool>(0, false) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<int, bool>(1, true) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompare<int, bool>(1, false) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompare<int, bool>(0, true) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("arithmeticCompareNegateLeft()") {
|
||||
SECTION("unsigned vs int") {
|
||||
CHECK((arithmeticCompareNegateLeft<int>(0, 1) == COMPARE_RESULT_LESS));
|
||||
CHECK((arithmeticCompareNegateLeft<int>(42, -41) == COMPARE_RESULT_LESS));
|
||||
CHECK((arithmeticCompareNegateLeft<int>(42, -42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK(
|
||||
(arithmeticCompareNegateLeft<int>(42, -43) == COMPARE_RESULT_GREATER));
|
||||
}
|
||||
|
||||
SECTION("unsigned vs unsigned") {
|
||||
CHECK(
|
||||
(arithmeticCompareNegateLeft<unsigned>(42, 42) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("arithmeticCompareNegateRight()") {
|
||||
SECTION("int vs unsigned") {
|
||||
CHECK((arithmeticCompareNegateRight<int>(1, 0) == COMPARE_RESULT_GREATER));
|
||||
CHECK(
|
||||
(arithmeticCompareNegateRight<int>(-41, 42) == COMPARE_RESULT_GREATER));
|
||||
CHECK((arithmeticCompareNegateRight<int>(-42, 42) == COMPARE_RESULT_EQUAL));
|
||||
CHECK((arithmeticCompareNegateRight<int>(-43, 42) == COMPARE_RESULT_LESS));
|
||||
}
|
||||
|
||||
SECTION("unsigned vs unsigned") {
|
||||
CHECK((arithmeticCompareNegateRight<unsigned>(42, 42) ==
|
||||
COMPARE_RESULT_GREATER));
|
||||
}
|
||||
}
|
@ -18,17 +18,14 @@ add_executable(MixedConfigurationTests
|
||||
enable_nan_0.cpp
|
||||
enable_nan_1.cpp
|
||||
enable_progmem_1.cpp
|
||||
enable_string_deduplication_0.cpp
|
||||
enable_string_deduplication_1.cpp
|
||||
use_double_0.cpp
|
||||
use_double_1.cpp
|
||||
use_long_long_0.cpp
|
||||
use_long_long_1.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MixedConfigurationTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
set_target_properties(MixedConfigurationTests PROPERTIES UNITY_BUILD OFF)
|
||||
|
||||
add_test(MixedConfiguration MixedConfigurationTests)
|
||||
|
@ -373,16 +373,22 @@ TEST_CASE("Comments in objects") {
|
||||
TEST_CASE("Comments alone") {
|
||||
DynamicJsonDocument doc(2048);
|
||||
|
||||
SECTION("Just a trailing comment") {
|
||||
SECTION("Just a trailing comment with no line break") {
|
||||
DeserializationError err = deserializeJson(doc, "// comment");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
}
|
||||
|
||||
SECTION("Just a trailing comment with no a break") {
|
||||
DeserializationError err = deserializeJson(doc, "// comment\n");
|
||||
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("Just a block comment") {
|
||||
DeserializationError err = deserializeJson(doc, "/*comment*/");
|
||||
|
||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
||||
REQUIRE(err == DeserializationError::EmptyInput);
|
||||
}
|
||||
|
||||
SECTION("Just a slash") {
|
||||
|
@ -53,33 +53,33 @@ TEST_CASE("Flash strings") {
|
||||
}
|
||||
|
||||
TEST_CASE("strlen_P") {
|
||||
CHECK(strlen_P(FC("")) == 0);
|
||||
CHECK(strlen_P(FC("a")) == 1);
|
||||
CHECK(strlen_P(FC("ac")) == 2);
|
||||
CHECK(strlen_P(PSTR("")) == 0);
|
||||
CHECK(strlen_P(PSTR("a")) == 1);
|
||||
CHECK(strlen_P(PSTR("ac")) == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("strncmp_P") {
|
||||
CHECK(strncmp_P("a", FC("b"), 0) == 0);
|
||||
CHECK(strncmp_P("a", FC("b"), 1) == -1);
|
||||
CHECK(strncmp_P("b", FC("a"), 1) == 1);
|
||||
CHECK(strncmp_P("a", FC("a"), 0) == 0);
|
||||
CHECK(strncmp_P("a", FC("b"), 2) == -1);
|
||||
CHECK(strncmp_P("b", FC("a"), 2) == 1);
|
||||
CHECK(strncmp_P("a", FC("a"), 2) == 0);
|
||||
CHECK(strncmp_P("a", PSTR("b"), 0) == 0);
|
||||
CHECK(strncmp_P("a", PSTR("b"), 1) == -1);
|
||||
CHECK(strncmp_P("b", PSTR("a"), 1) == 1);
|
||||
CHECK(strncmp_P("a", PSTR("a"), 0) == 0);
|
||||
CHECK(strncmp_P("a", PSTR("b"), 2) == -1);
|
||||
CHECK(strncmp_P("b", PSTR("a"), 2) == 1);
|
||||
CHECK(strncmp_P("a", PSTR("a"), 2) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("strcmp_P") {
|
||||
CHECK(strcmp_P("a", FC("b")) == -1);
|
||||
CHECK(strcmp_P("b", FC("a")) == 1);
|
||||
CHECK(strcmp_P("a", FC("a")) == 0);
|
||||
CHECK(strcmp_P("aa", FC("ab")) == -1);
|
||||
CHECK(strcmp_P("ab", FC("aa")) == 1);
|
||||
CHECK(strcmp_P("aa", FC("aa")) == 0);
|
||||
CHECK(strcmp_P("a", PSTR("b")) == -1);
|
||||
CHECK(strcmp_P("b", PSTR("a")) == 1);
|
||||
CHECK(strcmp_P("a", PSTR("a")) == 0);
|
||||
CHECK(strcmp_P("aa", PSTR("ab")) == -1);
|
||||
CHECK(strcmp_P("ab", PSTR("aa")) == 1);
|
||||
CHECK(strcmp_P("aa", PSTR("aa")) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("memcpy_P") {
|
||||
char dst[4];
|
||||
CHECK(memcpy_P(dst, FC("ABC"), 4) == dst);
|
||||
CHECK(memcpy_P(dst, PSTR("ABC"), 4) == dst);
|
||||
CHECK(dst[0] == 'A');
|
||||
CHECK(dst[1] == 'B');
|
||||
CHECK(dst[2] == 'C');
|
||||
@ -165,3 +165,22 @@ TEST_CASE("Reader<const __FlashStringHelper*>") {
|
||||
REQUIRE(buffer[6] == 'g');
|
||||
}
|
||||
}
|
||||
|
||||
static void testStringification(DeserializationError error,
|
||||
std::string expected) {
|
||||
const __FlashStringHelper* s = error.f_str();
|
||||
CHECK(reinterpret_cast<const char*>(convertFlashToPtr(s)) == expected);
|
||||
}
|
||||
|
||||
#define TEST_STRINGIFICATION(symbol) \
|
||||
testStringification(DeserializationError::symbol, #symbol)
|
||||
|
||||
TEST_CASE("DeserializationError::f_str()") {
|
||||
TEST_STRINGIFICATION(Ok);
|
||||
TEST_STRINGIFICATION(EmptyInput);
|
||||
TEST_STRINGIFICATION(IncompleteInput);
|
||||
TEST_STRINGIFICATION(InvalidInput);
|
||||
TEST_STRINGIFICATION(NoMemory);
|
||||
TEST_STRINGIFICATION(NotSupported);
|
||||
TEST_STRINGIFICATION(TooDeep);
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include "progmem_emulation.hpp"
|
||||
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 0
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("ARDUINOJSON_ENABLE_STRING_DEDUPLICATION = 0") {
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
SECTION("deserializeJson()") {
|
||||
SECTION("Deduplicate values") {
|
||||
deserializeJson(doc, "[\"example\",\"example\"]");
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 16);
|
||||
CHECK(doc[0].as<char*>() != doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Deduplicate keys") {
|
||||
deserializeJson(doc, "[{\"example\":1},{\"example\":2}]");
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
2 * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(2) + 16);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
|
||||
CHECK(key1 != key2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonDocument") {
|
||||
SECTION("values") {
|
||||
SECTION("std::string") {
|
||||
doc.add(std::string("example"));
|
||||
doc.add(std::string("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 16);
|
||||
CHECK(doc[0].as<char*>() != doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char value[] = "example";
|
||||
doc.add(value);
|
||||
doc.add(value);
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 16);
|
||||
CHECK(doc[0].as<char*>() != doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Arduino String") {
|
||||
doc.add(String("example"));
|
||||
doc.add(String("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 16);
|
||||
CHECK(doc[0].as<char*>() != doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Flash string") {
|
||||
doc.add(F("example"));
|
||||
doc.add(F("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 16);
|
||||
CHECK(doc[0].as<char*>() != doc[1].as<char*>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("keys") {
|
||||
SECTION("std::string") {
|
||||
doc[0][std::string("example")] = 1;
|
||||
doc[1][std::string("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 16);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 != key2);
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char key[] = "example";
|
||||
doc[0][key] = 1;
|
||||
doc[1][key] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 16);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 != key2);
|
||||
}
|
||||
|
||||
SECTION("Arduino String") {
|
||||
doc[0][String("example")] = 1;
|
||||
doc[1][String("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 16);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 != key2);
|
||||
}
|
||||
|
||||
SECTION("Flash string") {
|
||||
doc[0][F("example")] = 1;
|
||||
doc[1][F("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 16);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 != key2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include "progmem_emulation.hpp"
|
||||
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("ARDUINOJSON_ENABLE_STRING_DEDUPLICATION = 1") {
|
||||
StaticJsonDocument<1024> doc;
|
||||
|
||||
SECTION("deserializeJson()") {
|
||||
SECTION("Deduplicate values") {
|
||||
deserializeJson(doc, "[\"example\",\"example\"]");
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 8);
|
||||
CHECK(doc[0].as<char*>() == doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Deduplicate keys") {
|
||||
deserializeJson(doc, "[{\"example\":1},{\"example\":2}]");
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
2 * JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(2) + 8);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 == key2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("JsonDocument") {
|
||||
SECTION("values") {
|
||||
SECTION("std::string") {
|
||||
doc.add(std::string("example"));
|
||||
doc.add(std::string("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 8);
|
||||
CHECK(doc[0].as<char*>() == doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char value[] = "example";
|
||||
doc.add(value);
|
||||
doc.add(value);
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 8);
|
||||
CHECK(doc[0].as<char*>() == doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Arduino String") {
|
||||
doc.add(String("example"));
|
||||
doc.add(String("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 8);
|
||||
CHECK(doc[0].as<char*>() == doc[1].as<char*>());
|
||||
}
|
||||
|
||||
SECTION("Flash string") {
|
||||
doc.add(F("example"));
|
||||
doc.add(F("example"));
|
||||
|
||||
CHECK(doc.memoryUsage() == JSON_ARRAY_SIZE(2) + 8);
|
||||
CHECK(doc[0].as<char*>() == doc[1].as<char*>());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("keys") {
|
||||
SECTION("std::string") {
|
||||
doc[0][std::string("example")] = 1;
|
||||
doc[1][std::string("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 == key2);
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char key[] = "example";
|
||||
doc[0][key] = 1;
|
||||
doc[1][key] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 == key2);
|
||||
}
|
||||
|
||||
SECTION("Arduino String") {
|
||||
doc[0][String("example")] = 1;
|
||||
doc[1][String("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 == key2);
|
||||
}
|
||||
|
||||
SECTION("Flash string") {
|
||||
doc[0][F("example")] = 1;
|
||||
doc[1][F("example")] = 2;
|
||||
|
||||
CHECK(doc.memoryUsage() ==
|
||||
JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(1) + 8);
|
||||
|
||||
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
|
||||
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
|
||||
CHECK(key1 == key2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,28 +3,14 @@
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
template <size_t size_of_long>
|
||||
std::string get_expected_json();
|
||||
|
||||
template <>
|
||||
std::string get_expected_json<4>() {
|
||||
return "{\"A\":2899336981,\"B\":2129924785}";
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string get_expected_json<8>() {
|
||||
return "{\"A\":123456789123456789,\"B\":987654321987654321}";
|
||||
}
|
||||
|
||||
TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
|
||||
DynamicJsonDocument doc(4096);
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
root["A"] = 123456789123456789;
|
||||
root["B"] = 987654321987654321;
|
||||
doc["A"] = 42;
|
||||
doc["B"] = 84;
|
||||
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(json == get_expected_json<sizeof(long)>());
|
||||
REQUIRE(json == "{\"A\":42,\"B\":84}");
|
||||
}
|
||||
|
@ -8,15 +8,12 @@ add_executable(MsgPackDeserializerTests
|
||||
deserializeStaticVariant.cpp
|
||||
deserializeVariant.cpp
|
||||
doubleToFloat.cpp
|
||||
filter.cpp
|
||||
incompleteInput.cpp
|
||||
input_types.cpp
|
||||
misc.cpp
|
||||
nestingLimit.cpp
|
||||
notSupported.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MsgPackDeserializerTests
|
||||
ArduinoJson
|
||||
catch
|
||||
)
|
||||
|
||||
add_test(MsgPackDeserializer MsgPackDeserializerTests)
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
template <size_t Capacity>
|
||||
static void check(const char* input, DeserializationError expected) {
|
||||
StaticJsonDocument<Capacity> variant;
|
||||
StaticJsonDocument<Capacity> doc;
|
||||
|
||||
DeserializationError error = deserializeMsgPack(variant, input);
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
CAPTURE(input);
|
||||
REQUIRE(error == expected);
|
||||
@ -17,7 +17,7 @@ static void check(const char* input, DeserializationError expected) {
|
||||
|
||||
template <size_t Size>
|
||||
static void checkString(const char* input, DeserializationError expected) {
|
||||
check<JSON_STRING_SIZE(Size)>(input, expected);
|
||||
check<Size>(input, expected);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeMsgPack(StaticJsonDocument&)") {
|
||||
|
1119
extras/tests/MsgPackDeserializer/filter.cpp
Normal file
1119
extras/tests/MsgPackDeserializer/filter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user