Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
542a48a16a | ||
|
|
606098f45d | ||
|
|
67b9f1936d | ||
|
|
bb9d87ad55 | ||
|
|
e7a60d8961 | ||
|
|
470197bd0b | ||
|
|
d3e7f9da67 | ||
|
|
97280bbcfc | ||
|
|
e9fde3e116 | ||
|
|
54bf5f20e9 | ||
|
|
2fa8ea0f74 | ||
|
|
a0ef5a194c | ||
|
|
04b11d78ff | ||
|
|
8173c370f6 | ||
|
|
b6550b35c3 | ||
|
|
b5128b1610 | ||
|
|
963efb1f09 | ||
|
|
d6005e59a5 | ||
|
|
e1b6a23049 | ||
|
|
be61091401 | ||
|
|
e4366688f7 | ||
|
|
5dfd2c9bdf | ||
|
|
5879eb0be3 | ||
|
|
3d104f1d43 | ||
|
|
6bbcdc1ec5 | ||
|
|
7b6cba23f3 | ||
|
|
24c588cd25 | ||
|
|
f209be1142 | ||
|
|
768d66560e | ||
|
|
15925469c6 | ||
|
|
f922426ec3 | ||
|
|
2daab5a4c2 | ||
|
|
8ea0ee502d | ||
|
|
fa0299f03a | ||
|
|
36745ed296 | ||
|
|
f0455b401d | ||
|
|
e0d809312b | ||
|
|
bfd6678800 | ||
|
|
9639f0dfb3 | ||
|
|
625370a1ad | ||
|
|
357baeff5a | ||
|
|
42be2edd4c | ||
|
|
c8d01fa7b9 | ||
|
|
2c82f25272 | ||
|
|
df9fd6237e | ||
|
|
776880bc49 | ||
|
|
740b66f225 | ||
|
|
58cbf4b3ef | ||
|
|
ae7aaed4ac | ||
|
|
442058f8ed | ||
|
|
afba1d3fcb | ||
|
|
941714c99c | ||
|
|
a485aa8d27 | ||
|
|
6e6e1c9b1f | ||
|
|
f76f9efe58 | ||
|
|
463ffb21bc | ||
|
|
29c5f32d42 | ||
|
|
e0ff1a837c | ||
|
|
87dea32e81 | ||
|
|
bd3bd37e96 | ||
|
|
04c6c886eb | ||
|
|
8b833c452a | ||
|
|
1d66ab9f7a | ||
|
|
a79d634ccb | ||
|
|
6d1254baba | ||
|
|
b688119aa4 | ||
|
|
29a4ef6c5c | ||
|
|
71af209ea9 | ||
|
|
79fd4dfbd8 | ||
|
|
cda84ba323 | ||
|
|
034244a291 | ||
|
|
1e896eb91e | ||
|
|
94331a355d | ||
|
|
aa7f5ad8b1 | ||
|
|
585a39a235 | ||
|
|
b4571360df | ||
|
|
eef8059003 | ||
|
|
6f3554f040 | ||
|
|
0cf7ebaa57 | ||
|
|
d2564c6100 | ||
|
|
039cedaf8e | ||
|
|
628a5eae50 | ||
|
|
f40f81c87e | ||
|
|
c0922c7aac | ||
|
|
35f22e8596 | ||
|
|
a78eaa27b5 | ||
|
|
5e67f7af01 | ||
|
|
f791c5fd2e | ||
|
|
ca80a71c28 | ||
|
|
dfc2c1abe5 | ||
|
|
92ee1d56eb | ||
|
|
4871e39415 | ||
|
|
7b42c973bd | ||
|
|
c9e5d56c9c | ||
|
|
01386b3977 | ||
|
|
b76f5506d7 | ||
|
|
03de590372 | ||
|
|
37fdcd893d | ||
|
|
46174879ef | ||
|
|
5db41313ba | ||
|
|
1c4ca6d7b1 | ||
|
|
d02e67d4a9 | ||
|
|
ce30526ee8 | ||
|
|
efe1d52629 | ||
|
|
a2e923de32 | ||
|
|
4d90331718 | ||
|
|
997bc5d1ab | ||
|
|
31963723d3 | ||
|
|
407e8dbb8e | ||
|
|
b1c1fe9d39 | ||
|
|
b76861dde5 | ||
|
|
6150ffb9dc | ||
|
|
be05dbe618 | ||
|
|
4b37082e36 | ||
|
|
117fd59abd | ||
|
|
ff612e0e39 | ||
|
|
0b34ddd47a | ||
|
|
fa4fd334b2 | ||
|
|
d3c6ed08d6 | ||
|
|
00046f6ff1 | ||
|
|
38f562af2a | ||
|
|
2d3374c8b2 | ||
|
|
bd75ef9f27 | ||
|
|
ff592c6d50 | ||
|
|
91b6e223d9 | ||
|
|
d80329034e | ||
|
|
3944ecd470 | ||
|
|
be5cf0e3ba | ||
|
|
5541e6f6f9 | ||
|
|
263e6af48d | ||
|
|
4444ef9396 | ||
|
|
3586767c05 | ||
|
|
8b39570009 | ||
|
|
e29d6b5f41 | ||
|
|
25ccf7f908 |
15
.github/CONTRIBUTING.md
vendored
@@ -6,6 +6,10 @@ This project started as a little excuse to exercise some of the cool new C++11 f
|
||||
|
||||
To make it as easy as possible for you to contribute and for me to keep an overview, here are a few guidelines which should help us avoid all kinds of unnecessary work or disappointment. And of course, this document is subject to discussion, so please [create an issue](https://github.com/nlohmann/json/issues/new) or a pull request if you find a way to improve it!
|
||||
|
||||
## Private reports
|
||||
|
||||
Usually, all issues are tracked publicly on [Github](https://github.com/nlohmann/json/issues). If you want to make a private report (e.g., for a vulnerability or to attach an example that is not meant to be publisheed), please send an email to <mail@nlohmann.me>.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Please [create an issue](https://github.com/nlohmann/json/issues/new), assuming one does not already exist, and describe your concern. Note you need a [GitHub account](https://github.com/signup/free) for this.
|
||||
@@ -37,16 +41,10 @@ There are currently two files which need to be edited:
|
||||
|
||||
2. [`test/src/unit.cpp`](https://github.com/nlohmann/json/blob/master/test/unit.cpp) - This contains the [Catch](https://github.com/philsquared/Catch) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code.
|
||||
|
||||
If you add or change a feature, please also add a unit test to this file. The unit tests can be compiled with
|
||||
If you add or change a feature, please also add a unit test to this file. The unit tests can be compiled and executed with
|
||||
|
||||
```sh
|
||||
make
|
||||
```
|
||||
|
||||
and can be executed with
|
||||
|
||||
```sh
|
||||
./json_unit
|
||||
make check
|
||||
```
|
||||
|
||||
The test cases are also executed with several different compilers on [Travis](https://travis-ci.org/nlohmann/json) once you open a pull request.
|
||||
@@ -57,6 +55,7 @@ Please understand that I cannot accept pull requests changing only file `src/jso
|
||||
## Note
|
||||
|
||||
- If you open a pull request, the code will be automatically tested with [Valgrind](http://valgrind.org)'s Memcheck tool to detect memory leaks. Please be aware that the execution with Valgrind _may_ in rare cases yield different behavior than running the code directly. This can result in failing unit tests which run successfully without Valgrind.
|
||||
- There is a Makefile target `make pretty` which runs [Artistic Style](http://astyle.sourceforge.net) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
|
||||
|
||||
## Please don't
|
||||
|
||||
|
||||
10
.gitignore
vendored
@@ -1,16 +1,16 @@
|
||||
json_unit
|
||||
json_benchmarks
|
||||
|
||||
fuzz-testing
|
||||
|
||||
*.dSYM
|
||||
*.o
|
||||
*.gcno
|
||||
*.gcda
|
||||
|
||||
working
|
||||
|
||||
html
|
||||
doc/xml
|
||||
doc/html
|
||||
me.nlohmann.json.docset
|
||||
|
||||
android
|
||||
doc/xml
|
||||
|
||||
benchmarks/files/numbers/*.json
|
||||
|
||||
414
.travis.yml
@@ -1,176 +1,308 @@
|
||||
#########################
|
||||
# project configuration #
|
||||
#########################
|
||||
|
||||
# C++ project
|
||||
language: cpp
|
||||
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
|
||||
###################
|
||||
# global settings #
|
||||
###################
|
||||
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
|
||||
|
||||
# from http://stackoverflow.com/a/32127147/266378
|
||||
|
||||
################
|
||||
# build matrix #
|
||||
################
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9', 'valgrind', 'python-pip', 'python-yaml']
|
||||
before_script:
|
||||
- pip install --user git+git://github.com/eddyxu/cpp-coveralls.git
|
||||
after_success:
|
||||
- make clean
|
||||
- touch src/json.hpp
|
||||
- make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER
|
||||
- ./json_unit "*"
|
||||
- coveralls --exclude test/src/catch.hpp --exclude test/src/unit.cpp --include src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
env: COMPILER=g++-4.9
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'valgrind']
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "nlohmann/json"
|
||||
description: "Build submitted via Travis CI"
|
||||
notification_email: niels.lohmann@gmail.com
|
||||
build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
|
||||
build_command: "make"
|
||||
branch_pattern: coverity_scan
|
||||
env: COMPILER=g++-5
|
||||
# Valgrind
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6', 'valgrind']
|
||||
env: COMPILER=g++-6
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- COMPILER=g++-4.9
|
||||
- SPECIAL=valgrind
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: [g++-4.9, valgrind]
|
||||
after_success:
|
||||
- valgrind --error-exitcode=1 --leak-check=full test/json_unit
|
||||
|
||||
# from https://github.com/travis-ci/travis-ci/issues/6120
|
||||
- os: linux
|
||||
env:
|
||||
- LLVM_VERSION=3.8.0
|
||||
- LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz
|
||||
- COMPILER=clang++
|
||||
- CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1"
|
||||
- CXXFLAGS=-lc++
|
||||
- PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH
|
||||
- LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH
|
||||
before_install:
|
||||
- wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH
|
||||
- mkdir $HOME/clang-$LLVM_VERSION
|
||||
- tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1
|
||||
# cppcheck
|
||||
|
||||
# Clang 3.5 is not able to compile the code,
|
||||
# see https://travis-ci.org/nlohmann/json/jobs/126720186
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- COMPILER=g++-4.9
|
||||
- SPECIAL=cppcheck
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: [g++-4.9, cppcheck]
|
||||
after_success:
|
||||
- make cppcheck
|
||||
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
|
||||
# packages: ['clang-3.6', 'valgrind']
|
||||
# env: COMPILER=clang++-3.6
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
|
||||
# packages: ['clang-3.7', 'valgrind']
|
||||
# env: COMPILER=clang++-3.7
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
|
||||
# packages: ['clang-3.8', 'valgrind']
|
||||
# env: COMPILER=clang++-3.8
|
||||
# Coveralls (http://gronlier.fr/blog/2015/01/adding-code-coverage-to-your-c-project/)
|
||||
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise']
|
||||
# packages: ['clang-3.9', 'valgrind']
|
||||
# env: COMPILER=clang++-3.9
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9', 'ruby']
|
||||
before_script:
|
||||
- wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz
|
||||
- tar xf lcov_1.11.orig.tar.gz
|
||||
- sudo make -C lcov-1.11/ install
|
||||
- gem install coveralls-lcov
|
||||
after_success:
|
||||
- make clean
|
||||
- CXXFLAGS="--coverage -g -O0" CPPFLAGS="-DNDEBUG" make
|
||||
- test/json_unit "*"
|
||||
- coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
|
||||
- lcov --directory src --directory test/src --capture --output-file coverage.info --rc lcov_branch_coverage=1 --no-external
|
||||
- lcov --remove coverage.info 'test/src/*' --output-file coverage.info --rc lcov_branch_coverage=1
|
||||
- lcov --list coverage.info --rc lcov_branch_coverage=1
|
||||
- coveralls-lcov --repo-token F9bs4Nop10JRgqPQXRcifyQKYhb3FczkS coverage.info
|
||||
env:
|
||||
- COMPILER=g++-4.9
|
||||
- SPECIAL=coveralls
|
||||
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.1
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
# Coverity (only for branch coverity_scan)
|
||||
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.2
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'valgrind']
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "nlohmann/json"
|
||||
description: "Build submitted via Travis CI"
|
||||
notification_email: niels.lohmann@gmail.com
|
||||
build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
|
||||
build_command: "make"
|
||||
branch_pattern: coverity_scan
|
||||
env:
|
||||
- COMPILER=g++-5
|
||||
- SPECIAL=coverity
|
||||
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.3
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
# OSX / Clang
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.1
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.2
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.2
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
- os: osx
|
||||
osx_image: beta-xcode6.3
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang
|
||||
- CXXFLAGS=-lstdc++
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.2
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
|
||||
# Linux / GCC
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: COMPILER=g++-4.9
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: g++-4.9
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: COMPILER=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: g++-5
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: COMPILER=g++-6
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: g++-6
|
||||
|
||||
# Linux / Clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.6.0
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.6.1
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.6.2
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.7.0
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.7.1
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.8.0
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
env: LLVM_VERSION=3.8.1
|
||||
compiler: clang
|
||||
|
||||
#####################
|
||||
# installation step #
|
||||
#####################
|
||||
|
||||
# set directories to cache
|
||||
cache:
|
||||
directories:
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.2
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.1
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.0
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.0
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.0
|
||||
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1
|
||||
|
||||
|
||||
install:
|
||||
# create deps dir if not existing
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- mkdir -p ${DEPS_DIR}
|
||||
|
||||
# make sure CXX is correctly set
|
||||
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
|
||||
|
||||
# install LLVM/clang when LLVM_VERSION is set
|
||||
- |
|
||||
if [[ "${LLVM_VERSION}" != "" ]]; then
|
||||
LLVM_DIR=${DEPS_DIR}/llvm-${LLVM_VERSION}
|
||||
if [[ -z "$(ls -A ${LLVM_DIR})" ]]; then
|
||||
travis_retry wget --quiet https://cmake.org/files/v3.6/cmake-3.6.1.tar.gz
|
||||
tar xfz cmake-3.6.1.tar.gz
|
||||
(cd cmake-3.6.1 && ./configure --prefix=${LLVM_DIR}/cmake && make install)
|
||||
export PATH="${LLVM_DIR}/cmake/bin:${PATH}"
|
||||
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
|
||||
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
|
||||
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
|
||||
CLANG_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz"
|
||||
mkdir -p ${LLVM_DIR} ${LLVM_DIR}/build ${LLVM_DIR}/projects/libcxx ${LLVM_DIR}/projects/libcxxabi ${LLVM_DIR}/clang
|
||||
travis_retry wget --quiet -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}
|
||||
travis_retry wget --quiet -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/projects/libcxx
|
||||
travis_retry wget --quiet -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/projects/libcxxabi
|
||||
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/clang
|
||||
(cd ${LLVM_DIR}/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_DIR}/install -DCMAKE_CXX_COMPILER=clang++)
|
||||
(cd ${LLVM_DIR}/build/projects/libcxx && make install -j2)
|
||||
(cd ${LLVM_DIR}/build/projects/libcxxabi && make install -j2)
|
||||
fi
|
||||
export CXXFLAGS="-nostdinc++ -isystem ${LLVM_DIR}/install/include/c++/v1"
|
||||
export LDFLAGS="-L ${LLVM_DIR}/install/lib -l c++ -l c++abi"
|
||||
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_DIR}/install/lib"
|
||||
export PATH="${LLVM_DIR}/clang/bin:${PATH}"
|
||||
fi
|
||||
|
||||
################
|
||||
# build script #
|
||||
################
|
||||
|
||||
script:
|
||||
# show OS/compiler version
|
||||
- uname -a
|
||||
- $COMPILER --version
|
||||
- make CXX=$COMPILER
|
||||
- ./json_unit "*"
|
||||
- if [ `which valgrind` ]; then
|
||||
valgrind --error-exitcode=1 --leak-check=full ./json_unit ;
|
||||
fi
|
||||
- $CXX --version
|
||||
|
||||
# compile
|
||||
- make
|
||||
|
||||
# execute unit tests
|
||||
- test/json_unit "*"
|
||||
|
||||
# check if homebrew works (only checks develop branch)
|
||||
- if [ `which brew` ]; then
|
||||
brew update ;
|
||||
brew tap nlohmann/json ;
|
||||
brew install nlohmann_json --HEAD ;
|
||||
brew test nlohmann_json ;
|
||||
fi
|
||||
|
||||
#language: cpp
|
||||
#
|
||||
#dist: trusty
|
||||
#sudo: required
|
||||
#
|
||||
#env:
|
||||
# global:
|
||||
# # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# # via the "travis encrypt" command using the project repo's public key
|
||||
# - secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
|
||||
#
|
||||
## from http://stackoverflow.com/a/32127147/266378
|
||||
#matrix:
|
||||
# include:
|
||||
# - os: linux
|
||||
# compiler: gcc
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test']
|
||||
# packages: ['g++-4.9', 'valgrind', 'python-pip', 'python-yaml']
|
||||
# before_script:
|
||||
# - pip install --user git+git://github.com/eddyxu/cpp-coveralls.git
|
||||
# after_success:
|
||||
# - make clean
|
||||
# - touch src/json.hpp
|
||||
# - make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER
|
||||
# - test/json_unit "*"
|
||||
# - coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
|
||||
# env: COMPILER=g++-4.9
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: gcc
|
||||
# before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ['ubuntu-toolchain-r-test']
|
||||
# packages: ['g++-5', 'valgrind']
|
||||
# coverity_scan:
|
||||
# project:
|
||||
# name: "nlohmann/json"
|
||||
# description: "Build submitted via Travis CI"
|
||||
# notification_email: niels.lohmann@gmail.com
|
||||
# build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
|
||||
# build_command: "make"
|
||||
# branch_pattern: coverity_scan
|
||||
# env: COMPILER=g++-5
|
||||
#
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
# define the project
|
||||
project(nlohmann_json VERSION 2.0.2 LANGUAGES CXX)
|
||||
project(nlohmann_json VERSION 2.0.6 LANGUAGES CXX)
|
||||
|
||||
enable_testing()
|
||||
|
||||
@@ -31,7 +31,8 @@ endif()
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file("cmake/config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}"
|
||||
INSTALL_DESTINATION ${JSON_CONFIG_DESTINATION})
|
||||
INSTALL_DESTINATION ${JSON_CONFIG_DESTINATION}
|
||||
PATH_VARS JSON_INCLUDE_DESTINATION)
|
||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
37
ChangeLog.md
@@ -1,7 +1,42 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-30)
|
||||
## [v2.0.6](https://github.com/nlohmann/json/releases/tag/v2.0.6) (2016-10-15)
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.5...v2.0.6)
|
||||
|
||||
- Add nested object capability to pointers [\#323](https://github.com/nlohmann/json/issues/323)
|
||||
- make has\_mapped\_type struct friendly [\#324](https://github.com/nlohmann/json/pull/324) ([vpetrigo](https://github.com/vpetrigo))
|
||||
|
||||
- Fix usage examples' comments for std::multiset [\#322](https://github.com/nlohmann/json/issues/322)
|
||||
- json\_unit runs forever when executed in build directory [\#319](https://github.com/nlohmann/json/issues/319)
|
||||
|
||||
- Fix usage examples' comments for std::multiset [\#321](https://github.com/nlohmann/json/pull/321) ([vasild](https://github.com/vasild))
|
||||
- Include dir relocation [\#318](https://github.com/nlohmann/json/pull/318) ([ChristophJud](https://github.com/ChristophJud))
|
||||
- trivial documentation fix [\#313](https://github.com/nlohmann/json/pull/313) ([5tefan](https://github.com/5tefan))
|
||||
|
||||
## [v2.0.5](https://github.com/nlohmann/json/releases/tag/v2.0.5) (2016-09-14)
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.4...v2.0.5)
|
||||
|
||||
- make json\_benchmarks no longer working in 2.0.4 [\#310](https://github.com/nlohmann/json/issues/310)
|
||||
|
||||
## [v2.0.4](https://github.com/nlohmann/json/releases/tag/v2.0.4) (2016-09-11)
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.3...v2.0.4)
|
||||
|
||||
- Parsing fails without space at end of file [\#306](https://github.com/nlohmann/json/issues/306)
|
||||
|
||||
- Unused variable warning [\#304](https://github.com/nlohmann/json/issues/304)
|
||||
|
||||
## [v2.0.3](https://github.com/nlohmann/json/releases/tag/v2.0.3) (2016-08-31)
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.2...v2.0.3)
|
||||
|
||||
- Support for iterator-range parsing [\#290](https://github.com/nlohmann/json/issues/290)
|
||||
|
||||
- warning C4706: assignment within conditional expression [\#295](https://github.com/nlohmann/json/issues/295)
|
||||
- Horribly inconsistent behavior between const/non-const reference in operator \[\] \(\) [\#289](https://github.com/nlohmann/json/issues/289)
|
||||
|
||||
- unit-constructor1.cpp: Fix floating point truncation warning [\#300](https://github.com/nlohmann/json/pull/300) ([t-b](https://github.com/t-b))
|
||||
|
||||
## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-31)
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...v2.0.2)
|
||||
|
||||
- value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283)
|
||||
|
||||
24
Makefile
@@ -12,18 +12,23 @@ clean:
|
||||
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM
|
||||
rm -fr benchmarks/files/numbers/*.json
|
||||
$(MAKE) clean -Cdoc
|
||||
$(MAKE) clean -Ctest
|
||||
|
||||
|
||||
##########################################################################
|
||||
# unit tests
|
||||
##########################################################################
|
||||
|
||||
# additional flags
|
||||
FLAGS = -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wfloat-equal
|
||||
# build unit tests
|
||||
json_unit:
|
||||
@$(MAKE) -C test
|
||||
|
||||
# build unit tests (TODO: Does this want its own makefile?)
|
||||
json_unit: test/src/unit.cpp src/json.hpp test/src/catch.hpp
|
||||
$(CXX) -std=c++11 $(CXXFLAGS) $(FLAGS) $(CPPFLAGS) -I src -I test $< $(LDFLAGS) -o $@
|
||||
# run unit tests
|
||||
check: json_unit
|
||||
test/json_unit "*"
|
||||
|
||||
check-fast: json_unit
|
||||
test/json_unit
|
||||
|
||||
|
||||
##########################################################################
|
||||
@@ -59,8 +64,10 @@ fuzz: test/src/fuzz.cpp src/json.hpp
|
||||
|
||||
# call cppcheck on the main header file
|
||||
cppcheck:
|
||||
cppcheck --enable=all --inconclusive --std=c++11 src/json.hpp
|
||||
cppcheck --enable=warning --inconclusive --force --std=c++11 src/json.hpp --error-exitcode=1
|
||||
|
||||
clang_sanitize: clean
|
||||
CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE)
|
||||
|
||||
##########################################################################
|
||||
# maintainer targets
|
||||
@@ -77,7 +84,8 @@ pretty:
|
||||
--indent-col1-comments --pad-oper --pad-header --align-pointer=type \
|
||||
--align-reference=type --add-brackets --convert-tabs --close-templates \
|
||||
--lineend=linux --preserve-date --suffix=none --formatted \
|
||||
src/json.hpp src/json.hpp.re2c test/src/unit.cpp test/src/fuzz.cpp benchmarks/benchmarks.cpp doc/examples/*.cpp
|
||||
src/json.hpp src/json.hpp.re2c test/src/*.cpp \
|
||||
benchmarks/benchmarks.cpp doc/examples/*.cpp
|
||||
|
||||
|
||||
##########################################################################
|
||||
@@ -87,7 +95,7 @@ pretty:
|
||||
# benchmarks
|
||||
json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp src/json.hpp
|
||||
cd benchmarks/files/numbers ; python generate.py
|
||||
$(CXX) -std=c++11 $(CXXFLAGS) -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
|
||||
$(CXX) -std=c++11 $(CXXFLAGS) -DNDEBUG -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
|
||||
./json_benchmarks
|
||||
|
||||
|
||||
|
||||
43
README.md
@@ -1,14 +1,14 @@
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
|
||||
[](https://travis-ci.org/nlohmann/json)
|
||||
[](https://ci.appveyor.com/project/nlohmann/json)
|
||||
[](https://ci.appveyor.com/project/nlohmann/json)
|
||||
[](https://coveralls.io/r/nlohmann/json)
|
||||
[](https://scan.coverity.com/projects/nlohmann-json)
|
||||
[](http://melpon.org/wandbox/permlink/p5o4znPnGHJpDVqN)
|
||||
[](http://melpon.org/wandbox/permlink/3BIhBw91FUVuHE1D)
|
||||
[](http://nlohmann.github.io/json)
|
||||
[](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
[](http://github.com/nlohmann/json/issues)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/289)
|
||||
|
||||
## Design goals
|
||||
|
||||
@@ -18,7 +18,7 @@ There are myriads of [JSON](http://json.org) libraries out there, and each may e
|
||||
|
||||
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/src/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
||||
|
||||
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks.
|
||||
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289).
|
||||
|
||||
Other aspects were not so important to us:
|
||||
|
||||
@@ -283,8 +283,8 @@ json j_uset(c_uset); // only one entry for "one" is used
|
||||
// maybe ["two", "three", "four", "one"]
|
||||
|
||||
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
|
||||
json j_mset(c_mset); // only one entry for "one" is used
|
||||
// maybe ["one", "two", "four"]
|
||||
json j_mset(c_mset); // both entries for "one" are used
|
||||
// maybe ["one", "two", "one", "four"]
|
||||
|
||||
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
|
||||
json j_umset(c_umset); // both entries for "one" are used
|
||||
@@ -416,7 +416,13 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||
| GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 |
|
||||
| GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 |
|
||||
| GCC 6.1.1 | Ubuntu 14.04.4 LTS | g++-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 |
|
||||
| Clang 3.6.0 | Ubuntu 14.04.4 LTS | clang version 3.6.0 (tags/RELEASE_360/final) |
|
||||
| Clang 3.6.1 | Ubuntu 14.04.4 LTS | clang version 3.6.1 (tags/RELEASE_361/final) |
|
||||
| Clang 3.6.2 | Ubuntu 14.04.4 LTS | clang version 3.6.2 (tags/RELEASE_362/final) |
|
||||
| Clang 3.7.0 | Ubuntu 14.04.4 LTS | clang version 3.7.0 (tags/RELEASE_370/final) |
|
||||
| Clang 3.7.1 | Ubuntu 14.04.4 LTS | clang version 3.7.1 (tags/RELEASE_371/final) |
|
||||
| Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) |
|
||||
| Clang 3.8.1 | Ubuntu 14.04.4 LTS | clang version 3.8.1 (tags/RELEASE_381/final) |
|
||||
| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) |
|
||||
@@ -424,7 +430,7 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||
| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) |
|
||||
| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) |
|
||||
| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
|
||||
| Clang Xcode 8.0 | Darwin Kernel Version 15.5.0 (OSX 10.11.5) | Apple LLVM version 8.0.0 (clang-800.0.24.1) |
|
||||
| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 (OSX 10.11.6) | Apple LLVM version 8.0.0 (clang-800.0.38) |
|
||||
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 |
|
||||
|
||||
|
||||
@@ -486,13 +492,19 @@ I deeply appreciate the help of the following people.
|
||||
- [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
||||
- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
||||
- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
||||
- [Thomas Braun](https://github.com/t-b) fixed a warning in a test case.
|
||||
- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290).
|
||||
- [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
|
||||
- [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
|
||||
- [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
|
||||
- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable.
|
||||
|
||||
Thanks a lot for helping out!
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert).
|
||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
|
||||
- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
|
||||
|
||||
|
||||
@@ -501,11 +513,20 @@ Thanks a lot for helping out!
|
||||
To compile and run the tests, you need to execute
|
||||
|
||||
```sh
|
||||
$ make
|
||||
$ ./json_unit "*"
|
||||
$ make check
|
||||
|
||||
===============================================================================
|
||||
All tests passed (8905012 assertions in 32 test cases)
|
||||
All tests passed (8905168 assertions in 35 test cases)
|
||||
```
|
||||
|
||||
Alternatively, you can use [https://cmake.org](CMake) and run
|
||||
|
||||
```sh
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ ctest
|
||||
```
|
||||
|
||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@PACKAGE_INIT@
|
||||
set_and_check(JSON_INCLUDE_DIR "@PACKAGE_JSON_INCLUDE_DESTINATION@")
|
||||
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0024 OLD)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@JSON_TARGETS_FILENAME@)
|
||||
cmake_policy(POP)
|
||||
cmake_policy(POP)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "JSON for Modern C++"
|
||||
PROJECT_NUMBER = 2.0.2
|
||||
PROJECT_NUMBER = 2.0.6
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = .
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/p5o4znPnGHJpDVqN"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/wvAQItW0g01kx5YJ"><b>online</b></a>
|
||||
@@ -1,12 +0,0 @@
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create a JSON value with default null value
|
||||
json j;
|
||||
|
||||
// serialize the JSON null value
|
||||
std::cout << j << '\n';
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/dRptmFmhvpsYB49t"><b>online</b></a>
|
||||
@@ -1 +0,0 @@
|
||||
null
|
||||
@@ -39,7 +39,7 @@ int main()
|
||||
|
||||
// create an array from std::multiset
|
||||
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
|
||||
json j_mset(c_mset); // only one entry for "one" is used
|
||||
json j_mset(c_mset); // both entries for "one" are used
|
||||
|
||||
// create an array from std::unordered_multiset
|
||||
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/MghSilgvyh4ZJShY"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/3BIhBw91FUVuHE1D"><b>online</b></a>
|
||||
@@ -27,7 +27,8 @@ int main()
|
||||
ss << text;
|
||||
|
||||
// create JSON from stream
|
||||
json j_complete(ss);
|
||||
json j_complete(ss); // deprecated!
|
||||
// shall be replaced by: json j_complete = json::parse(ss);
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
|
||||
|
||||
@@ -51,5 +52,6 @@ int main()
|
||||
|
||||
// create JSON from stream (with callback)
|
||||
json j_filtered(ss, cb);
|
||||
// shall be replaced by: json j_filtered = json::parse(ss, cb);
|
||||
std::cout << std::setw(4) << j_filtered << '\n';
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/VzSqLszbnoWE92dD"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/R6dzpKXlxrttShf7"><b>online</b></a>
|
||||
@@ -4,9 +4,12 @@ using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// create a JSON null value
|
||||
json j(nullptr);
|
||||
// implicitly create a JSON null value
|
||||
json j1;
|
||||
|
||||
// explicitly create a JSON null value
|
||||
json j2(nullptr);
|
||||
|
||||
// serialize the JSON null value
|
||||
std::cout << j << '\n';
|
||||
std::cout << j1 << '\n' << j2 << '\n';
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/PMMpoM0ujdJDsuta"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/9Tvfs2dJBW8m8ihA"><b>online</b></a>
|
||||
@@ -1 +1,2 @@
|
||||
null
|
||||
null
|
||||
|
||||
@@ -40,7 +40,7 @@ int main()
|
||||
// output the changed array
|
||||
std::cout << j["array"] << '\n';
|
||||
|
||||
// "change" the arry element past the end
|
||||
// "change" the array element past the end
|
||||
j["/array/-"_json_pointer] = 55;
|
||||
// output the changed array
|
||||
std::cout << j["array"] << '\n';
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/xzFX3E4gYBXFwd04"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/AYgVTzCodPApT4hT"><b>online</b></a>
|
||||
28
doc/examples/parse__array__parser_callback_t.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
char text[] = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": 100
|
||||
},
|
||||
"Animated" : false,
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
// parse and serialize JSON
|
||||
json j_complete = json::parse(text);
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
}
|
||||
1
doc/examples/parse__array__parser_callback_t.link
Normal file
@@ -0,0 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/CwZnqGqte14SYJ5s"><b>online</b></a>
|
||||
20
doc/examples/parse__array__parser_callback_t.output
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"Image": {
|
||||
"Animated": false,
|
||||
"Height": 600,
|
||||
"IDs": [
|
||||
116,
|
||||
943,
|
||||
234,
|
||||
38793
|
||||
],
|
||||
"Thumbnail": {
|
||||
"Height": 125,
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Width": 100
|
||||
},
|
||||
"Title": "View from 15th Floor",
|
||||
"Width": 800
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text given as std::vector
|
||||
std::vector<uint8_t> text = {'[', '1', ',', '2', ',', '3', ']', '\0'};
|
||||
|
||||
// parse and serialize JSON
|
||||
json j_complete = json::parse(text);
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/F8VaVFyys87qQRt5"><b>online</b></a>
|
||||
@@ -0,0 +1,6 @@
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
|
||||
13
doc/examples/parse__iteratortype__parser_callback_t.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text given as std::vector
|
||||
std::vector<uint8_t> text = {'[', '1', ',', '2', ',', '3', ']', '\0'};
|
||||
|
||||
// parse and serialize JSON
|
||||
json j_complete = json::parse(text.begin(), text.end());
|
||||
std::cout << std::setw(4) << j_complete << "\n\n";
|
||||
}
|
||||
1
doc/examples/parse__iteratortype__parser_callback_t.link
Normal file
@@ -0,0 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/ojh4Eeol4G9RgeRV"><b>online</b></a>
|
||||
@@ -0,0 +1,6 @@
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
|
||||
@@ -5,7 +5,7 @@ using json = nlohmann::json;
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
std::string text = R"(
|
||||
auto text = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
@@ -44,4 +44,4 @@ int main()
|
||||
// parse (with callback) and serialize JSON
|
||||
json j_filtered = json::parse(text, cb);
|
||||
std::cout << std::setw(4) << j_filtered << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/SrKpkE9ivmvd2OUy"><b>online</b></a>
|
||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/n888UNQlMFduURhE"><b>online</b></a>
|
||||
BIN
doc/images/scanner.png
Normal file
|
After Width: | Height: | Size: 645 KiB |
@@ -268,4 +268,4 @@ The container functions known from STL have been extended to support the differe
|
||||
@author [Niels Lohmann](http://nlohmann.me)
|
||||
@see https://github.com/nlohmann/json to download the source code
|
||||
|
||||
@version 2.0.2
|
||||
@version 2.0.6
|
||||
|
||||
BIN
doc/json.gif
|
Before Width: | Height: | Size: 440 KiB After Width: | Height: | Size: 439 KiB |
749
src/json.hpp
@@ -3,6 +3,36 @@ set(JSON_UNITTEST_TARGET_NAME "json_unit")
|
||||
add_executable(${JSON_UNITTEST_TARGET_NAME}
|
||||
"src/catch.hpp"
|
||||
"src/unit.cpp"
|
||||
"src/unit-algorithms.cpp"
|
||||
"src/unit-allocator.cpp"
|
||||
"src/unit-capacity.cpp"
|
||||
"src/unit-class_const_iterator.cpp"
|
||||
"src/unit-class_iterator.cpp"
|
||||
"src/unit-class_lexer.cpp"
|
||||
"src/unit-class_parser.cpp"
|
||||
"src/unit-comparison.cpp"
|
||||
"src/unit-concepts.cpp"
|
||||
"src/unit-constructor1.cpp"
|
||||
"src/unit-constructor2.cpp"
|
||||
"src/unit-convenience.cpp"
|
||||
"src/unit-conversions.cpp"
|
||||
"src/unit-deserialization.cpp"
|
||||
"src/unit-element_access1.cpp"
|
||||
"src/unit-element_access2.cpp"
|
||||
"src/unit-inspection.cpp"
|
||||
"src/unit-iterator_wrapper.cpp"
|
||||
"src/unit-iterators1.cpp"
|
||||
"src/unit-iterators2.cpp"
|
||||
"src/unit-json_patch.cpp"
|
||||
"src/unit-json_pointer.cpp"
|
||||
"src/unit-modifiers.cpp"
|
||||
"src/unit-pointer_access.cpp"
|
||||
"src/unit-readme.cpp"
|
||||
"src/unit-reference_access.cpp"
|
||||
"src/unit-regression.cpp"
|
||||
"src/unit-serialization.cpp"
|
||||
"src/unit-testsuites.cpp"
|
||||
"src/unit-unicode.cpp"
|
||||
)
|
||||
|
||||
set_target_properties(${JSON_UNITTEST_TARGET_NAME} PROPERTIES
|
||||
|
||||
54
test/Makefile
Normal file
@@ -0,0 +1,54 @@
|
||||
##########################################################################
|
||||
# unit tests
|
||||
##########################################################################
|
||||
|
||||
# additional flags
|
||||
CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wno-ctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wno-float-equal
|
||||
CPPFLAGS += -I ../src -I .
|
||||
|
||||
SOURCES = src/unit.cpp \
|
||||
src/unit-algorithms.cpp \
|
||||
src/unit-allocator.cpp \
|
||||
src/unit-capacity.cpp \
|
||||
src/unit-class_const_iterator.cpp \
|
||||
src/unit-class_iterator.cpp \
|
||||
src/unit-class_lexer.cpp \
|
||||
src/unit-class_parser.cpp \
|
||||
src/unit-comparison.cpp \
|
||||
src/unit-concepts.cpp \
|
||||
src/unit-constructor1.cpp \
|
||||
src/unit-constructor2.cpp \
|
||||
src/unit-convenience.cpp \
|
||||
src/unit-conversions.cpp \
|
||||
src/unit-deserialization.cpp \
|
||||
src/unit-element_access1.cpp \
|
||||
src/unit-element_access2.cpp \
|
||||
src/unit-inspection.cpp \
|
||||
src/unit-iterator_wrapper.cpp \
|
||||
src/unit-iterators1.cpp \
|
||||
src/unit-iterators2.cpp \
|
||||
src/unit-json_patch.cpp \
|
||||
src/unit-json_pointer.cpp \
|
||||
src/unit-modifiers.cpp \
|
||||
src/unit-pointer_access.cpp \
|
||||
src/unit-readme.cpp \
|
||||
src/unit-reference_access.cpp \
|
||||
src/unit-regression.cpp \
|
||||
src/unit-serialization.cpp \
|
||||
src/unit-unicode.cpp \
|
||||
src/unit-testsuites.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
all: json_unit
|
||||
|
||||
json_unit: $(OBJECTS) ../src/json.hpp src/catch.hpp
|
||||
@echo "[CXXLD] $@"
|
||||
@$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
%.o: %.cpp ../src/json.hpp src/catch.hpp
|
||||
@echo "[CXX] $@"
|
||||
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda)
|
||||
1
test/data/regression/broken_file.json
Normal file
@@ -0,0 +1 @@
|
||||
{"AmbientOcclusion":false,"AnisotropicFiltering":16,"FOV":90,"FullScreen":true,"MipmapLevel":4,"RenderDistance":4,"VSync":true,"WindowResX":1920,"WindowResY":1080}
|
||||
1000002
test/data/regression/floats.json
Normal file
1000002
test/data/regression/signed_ints.json
Normal file
1000002
test/data/regression/unsigned_ints.json
Normal file
1
test/data/regression/working_file.json
Normal file
@@ -0,0 +1 @@
|
||||
{"AmbientOcclusion":false,"AnisotropicFiltering":16,"FOV":90,"FullScreen":true,"MipmapLevel":4,"RenderDistance":4,"VSync":true,"WindowResX":1920,"WindowResY":1080}
|
||||
BIN
test/reports/2016-08-29-fuzz/exec_speed.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
test/reports/2016-08-29-fuzz/fuzz.tiff
Normal file
BIN
test/reports/2016-08-29-fuzz/high_freq.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
10
test/reports/2016-08-29-fuzz/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
|
||||
<tr><td style="width: 18ex"><b>Banner:</b></td><td>fuzz</td></tr>
|
||||
<tr><td><b>Directory:</b></td><td>fuzz-testing/out</td></tr>
|
||||
<tr><td><b>Generated on:</b></td><td>Mo 29 Aug 2016 22:14:22 CEST</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
<img src="high_freq.png" width=1000 height=300><p>
|
||||
<img src="low_freq.png" width=1000 height=200><p>
|
||||
<img src="exec_speed.png" width=1000 height=200>
|
||||
|
||||
BIN
test/reports/2016-08-29-fuzz/low_freq.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
31
test/reports/2016-09-09-nativejson_benchmark/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Results of the latest benchmark from <https://github.com/miloyip/nativejson-benchmark>.
|
||||
|
||||
See <https://github.com/nlohmann/json/issues/307> for discussion.
|
||||
|
||||
Original post at 2016-09-09 to <json@yahoogroups.com>:
|
||||
|
||||
> Hi,
|
||||
>
|
||||
> This benchmark evaluated conformance, parse/stringify speed/memory, and
|
||||
> code size. It can also be viewed as a long list of open source C/C++ JSON
|
||||
> libraries.
|
||||
>
|
||||
> You can run the benchmark on your own machine by checkout this project.
|
||||
>
|
||||
> https://github.com/miloyip/nativejson-benchmark
|
||||
>
|
||||
> You can also view some sample results here:
|
||||
>
|
||||
> https://rawgit.com/miloyip/nativejson-benchmark/master/sample/conformance.html
|
||||
> https://rawgit.com/miloyip/nativejson-benchmark/master/sample/performance_Corei7-4980HQ@2.80GHz_mac64_clang7.0.html
|
||||
>
|
||||
> If you make a new library, you may use this for testing conformance and
|
||||
> performance. Afterwards, please submit a pull request.
|
||||
>
|
||||
> Enjoy!
|
||||
>
|
||||
> --
|
||||
> Milo Yip
|
||||
>
|
||||
> https://github.com/miloyip/
|
||||
> http://twitter.com/miloyip/
|
||||
@@ -0,0 +1,670 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
|
||||
<meta charset='utf-8'>
|
||||
|
||||
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-3a71f36dec04358c4f2f42280fb2cf5c38856f935a3f609eab0a1ae31b1d635a.css" media="all" rel="stylesheet" />
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-5c885e880e980dc7f119393287b84906d930ccaff83f6bff8ae2c086b87ca4d8.css" media="all" rel="stylesheet" />
|
||||
|
||||
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-4ef7bbe907458c89cb1f7f5c5e6c4cd87e03acf66b1817325e644920d2a83330.css" media="all" rel="stylesheet" />
|
||||
|
||||
|
||||
<link as="script" href="https://assets-cdn.github.com/assets/frameworks-88471af1fec40ff9418efbe2ddd15b6896af8d772f8179004c254dffc25ea490.js" rel="preload" />
|
||||
|
||||
<link as="script" href="https://assets-cdn.github.com/assets/github-e18e11a943ff2eb9394c72d4ec8b76592c454915b5839ae177d422777a046e29.js" rel="preload" />
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>nativejson-benchmark/conformance_Nlohmann (C++11).md at master · miloyip/nativejson-benchmark · GitHub</title>
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
|
||||
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
|
||||
<meta property="fb:app_id" content="1401488693436528">
|
||||
|
||||
<meta content="https://avatars2.githubusercontent.com/u/1195774?v=3&s=400" name="twitter:image:src" /><meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="miloyip/nativejson-benchmark" name="twitter:title" /><meta content="nativejson-benchmark - C/C++ JSON parser/generator benchmark" name="twitter:description" />
|
||||
<meta content="https://avatars2.githubusercontent.com/u/1195774?v=3&s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="miloyip/nativejson-benchmark" property="og:title" /><meta content="https://github.com/miloyip/nativejson-benchmark" property="og:url" /><meta content="nativejson-benchmark - C/C++ JSON parser/generator benchmark" property="og:description" />
|
||||
<meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
|
||||
<meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
|
||||
<link rel="assets" href="https://assets-cdn.github.com/">
|
||||
|
||||
<meta name="pjax-timeout" content="1000">
|
||||
|
||||
<meta name="request-id" content="D4563DA7:75ED:525C921:57D6FEBB" data-pjax-transient>
|
||||
|
||||
<meta name="msapplication-TileImage" content="/windows-tile.png">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="selected-link" value="repo_source" data-pjax-transient>
|
||||
|
||||
<meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
|
||||
<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
|
||||
<meta name="google-analytics" content="UA-3769691-2">
|
||||
|
||||
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="D4563DA7:75ED:525C921:57D6FEBB" name="octolytics-dimension-request_id" />
|
||||
<meta content="/<user-name>/<repo-name>/blob/show" data-pjax-transient="true" name="analytics-location" />
|
||||
|
||||
|
||||
|
||||
<meta class="js-ga-set" name="dimension1" content="Logged Out">
|
||||
|
||||
|
||||
|
||||
<meta name="hostname" content="github.com">
|
||||
<meta name="user-login" content="">
|
||||
|
||||
<meta name="expected-hostname" content="github.com">
|
||||
<meta name="js-proxy-site-detection-payload" content="N2RkMmY1ZjE1MTA4MzRhYTA5NDNkMjliNDU3OTA3ZTdlMGNmNDZjN2QyODBiZjM3MmYzMjFjNzY1ZjIwNjY4NHx7InJlbW90ZV9hZGRyZXNzIjoiMjEyLjg2LjYxLjE2NyIsInJlcXVlc3RfaWQiOiJENDU2M0RBNzo3NUVEOjUyNUM5MjE6NTdENkZFQkIiLCJ0aW1lc3RhbXAiOjE0NzM3MDc3MDh9">
|
||||
|
||||
|
||||
<link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#4078c0">
|
||||
<link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">
|
||||
|
||||
<meta name="html-safe-nonce" content="deea0f406df2fb95709865c5ee80a255d8c47fa9">
|
||||
<meta content="736eea9d74cf34fe850d2180e8a5f0a1cc7bc0be" name="form-nonce" />
|
||||
|
||||
<meta http-equiv="x-pjax-version" content="f302977937abe3fe1c9a4d4bed913565">
|
||||
|
||||
|
||||
|
||||
<meta name="description" content="nativejson-benchmark - C/C++ JSON parser/generator benchmark">
|
||||
<meta name="go-import" content="github.com/miloyip/nativejson-benchmark git https://github.com/miloyip/nativejson-benchmark.git">
|
||||
|
||||
<meta content="1195774" name="octolytics-dimension-user_id" /><meta content="miloyip" name="octolytics-dimension-user_login" /><meta content="22976798" name="octolytics-dimension-repository_id" /><meta content="miloyip/nativejson-benchmark" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="22976798" name="octolytics-dimension-repository_network_root_id" /><meta content="miloyip/nativejson-benchmark" name="octolytics-dimension-repository_network_root_nwo" />
|
||||
<link href="https://github.com/miloyip/nativejson-benchmark/commits/master.atom" rel="alternate" title="Recent Commits to nativejson-benchmark:master" type="application/atom+xml">
|
||||
|
||||
|
||||
<link rel="canonical" href="https://github.com/miloyip/nativejson-benchmark/blob/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" data-pjax-transient>
|
||||
</head>
|
||||
|
||||
|
||||
<body class="logged-out env-production vis-public page-blob">
|
||||
<div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div>
|
||||
<a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="site-header js-details-container" role="banner">
|
||||
<div class="container-responsive">
|
||||
<a class="header-logo-invertocat" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark">
|
||||
<svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
|
||||
</a>
|
||||
|
||||
<button class="btn-link float-right site-header-toggle js-details-target" type="button" aria-label="Toggle navigation">
|
||||
<svg aria-hidden="true" class="octicon octicon-three-bars" height="24" version="1.1" viewBox="0 0 12 16" width="18"><path d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"></path></svg>
|
||||
</button>
|
||||
|
||||
<div class="site-header-menu">
|
||||
<nav class="site-header-nav site-header-nav-main">
|
||||
<a href="/personal" class="js-selected-navigation-item nav-item nav-item-personal" data-ga-click="Header, click, Nav menu - item:personal" data-selected-links="/personal /personal">
|
||||
Personal
|
||||
</a> <a href="/open-source" class="js-selected-navigation-item nav-item nav-item-opensource" data-ga-click="Header, click, Nav menu - item:opensource" data-selected-links="/open-source /open-source">
|
||||
Open source
|
||||
</a> <a href="/business" class="js-selected-navigation-item nav-item nav-item-business" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/partners /business/features /business/customers /business">
|
||||
Business
|
||||
</a> <a href="/explore" class="js-selected-navigation-item nav-item nav-item-explore" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship /explore">
|
||||
Explore
|
||||
</a> </nav>
|
||||
|
||||
<div class="site-header-actions">
|
||||
<a class="btn btn-primary site-header-actions-btn" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a>
|
||||
<a class="btn site-header-actions-btn mr-2" href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark%2Fblob%2Fmaster%2Fsample%2Fconformance_Nlohmann%2520%28C%252B%252B11%29.md" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a>
|
||||
</div>
|
||||
|
||||
<nav class="site-header-nav site-header-nav-secondary">
|
||||
<a class="nav-item" href="/pricing">Pricing</a>
|
||||
<a class="nav-item" href="/blog">Blog</a>
|
||||
<a class="nav-item" href="https://help.github.com">Support</a>
|
||||
<a class="nav-item header-search-link" href="https://github.com/search">Search GitHub</a>
|
||||
<div class="header-search scoped-search site-scoped-search js-site-search" role="search">
|
||||
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="/miloyip/nativejson-benchmark/search" class="js-site-search-form" data-scoped-search-url="/miloyip/nativejson-benchmark/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
|
||||
<label class="form-control header-search-wrapper js-chromeless-input-container">
|
||||
<div class="header-search-scope">This repository</div>
|
||||
<input type="text"
|
||||
class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable"
|
||||
data-hotkey="s"
|
||||
name="q"
|
||||
placeholder="Search"
|
||||
aria-label="Search this repository"
|
||||
data-unscoped-placeholder="Search GitHub"
|
||||
data-scoped-placeholder="Search"
|
||||
autocapitalize="off">
|
||||
</label>
|
||||
</form></div>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<div id="start-of-content" class="accessibility-aid"></div>
|
||||
|
||||
<div id="js-flash-container">
|
||||
</div>
|
||||
|
||||
|
||||
<div role="main">
|
||||
<div itemscope itemtype="http://schema.org/SoftwareSourceCode">
|
||||
<div id="js-repo-pjax-container" data-pjax-container>
|
||||
|
||||
<div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav">
|
||||
<div class="container repohead-details-container">
|
||||
|
||||
|
||||
|
||||
<ul class="pagehead-actions">
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to watch a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"></path></svg>
|
||||
Watch
|
||||
</a>
|
||||
<a class="social-count" href="/miloyip/nativejson-benchmark/watchers"
|
||||
aria-label="40 users are watching this repository">
|
||||
40
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to star a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"></path></svg>
|
||||
Star
|
||||
</a>
|
||||
|
||||
<a class="social-count js-social-count" href="/miloyip/nativejson-benchmark/stargazers"
|
||||
aria-label="352 users starred this repository">
|
||||
352
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fmiloyip%2Fnativejson-benchmark"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to fork a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>
|
||||
Fork
|
||||
</a>
|
||||
|
||||
<a href="/miloyip/nativejson-benchmark/network" class="social-count"
|
||||
aria-label="59 users are forked this repository">
|
||||
59
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h1 class="public ">
|
||||
<svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"></path></svg>
|
||||
<span class="author" itemprop="author"><a href="/miloyip" class="url fn" rel="author">miloyip</a></span><!--
|
||||
--><span class="path-divider">/</span><!--
|
||||
--><strong itemprop="name"><a href="/miloyip/nativejson-benchmark" data-pjax="#js-repo-pjax-container">nativejson-benchmark</a></strong>
|
||||
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
<nav class="reponav js-repo-nav js-sidenav-container-pjax"
|
||||
itemscope
|
||||
itemtype="http://schema.org/BreadcrumbList"
|
||||
role="navigation"
|
||||
data-pjax="#js-repo-pjax-container">
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/miloyip/nativejson-benchmark" aria-selected="true" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /miloyip/nativejson-benchmark" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"></path></svg>
|
||||
<span itemprop="name">Code</span>
|
||||
<meta itemprop="position" content="1">
|
||||
</a> </span>
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/miloyip/nativejson-benchmark/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /miloyip/nativejson-benchmark/issues" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg>
|
||||
<span itemprop="name">Issues</span>
|
||||
<span class="counter">8</span>
|
||||
<meta itemprop="position" content="2">
|
||||
</a> </span>
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/miloyip/nativejson-benchmark/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /miloyip/nativejson-benchmark/pulls" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>
|
||||
<span itemprop="name">Pull requests</span>
|
||||
<span class="counter">1</span>
|
||||
<meta itemprop="position" content="3">
|
||||
</a> </span>
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/miloyip/nativejson-benchmark/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="pulse /miloyip/nativejson-benchmark/pulse">
|
||||
<svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0v2h3.6l.9-1.8.9 5.4L9 8.5l1.6 1.5H14V8z"></path></svg>
|
||||
Pulse
|
||||
</a>
|
||||
<a href="/miloyip/nativejson-benchmark/graphs" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors /miloyip/nativejson-benchmark/graphs">
|
||||
<svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"></path></svg>
|
||||
Graphs
|
||||
</a>
|
||||
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container new-discussion-timeline experiment-repo-nav">
|
||||
<div class="repository-content">
|
||||
|
||||
|
||||
|
||||
<a href="/miloyip/nativejson-benchmark/blob/95f27ebcf9a96c7ca4cee26467ed5420140090fb/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a>
|
||||
|
||||
<!-- blob contrib key: blob_contributors:v21:0bf9e3593dedd91db6c9dc69e13b7f95 -->
|
||||
|
||||
<div class="file-navigation js-zeroclipboard-container">
|
||||
|
||||
<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left">
|
||||
<button class="btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w"
|
||||
|
||||
type="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true">
|
||||
<i>Branch:</i>
|
||||
<span class="js-select-button css-truncate-target">master</span>
|
||||
</button>
|
||||
|
||||
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true">
|
||||
|
||||
<div class="select-menu-modal">
|
||||
<div class="select-menu-header">
|
||||
<svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
|
||||
<span class="select-menu-title">Switch branches/tags</span>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-filters">
|
||||
<div class="select-menu-text-filter">
|
||||
<input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
|
||||
</div>
|
||||
<div class="select-menu-tabs">
|
||||
<ul>
|
||||
<li class="select-menu-tab">
|
||||
<a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a>
|
||||
</li>
|
||||
<li class="select-menu-tab">
|
||||
<a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu">
|
||||
|
||||
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
|
||||
|
||||
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/Stixjson/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="Stixjson"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
Stixjson
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/ccan/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="ccan"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
ccan
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/jbson/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="jbson"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
jbson
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/jute/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="jute"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
jute
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/lastjson/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="lastjson"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
lastjson
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/libjson/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="libjson"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
libjson
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open selected"
|
||||
href="/miloyip/nativejson-benchmark/blob/master/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="master"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
master
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/qt/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="qt"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
qt
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/tunnuz/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="tunnuz"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
tunnuz
|
||||
</span>
|
||||
</a>
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/blob/ujson/sample/conformance_Nlohmann%20(C++11).md"
|
||||
data-name="ujson"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
|
||||
ujson
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-no-results">Nothing to show</div>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
|
||||
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
|
||||
|
||||
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open "
|
||||
href="/miloyip/nativejson-benchmark/tree/v1.0.0/sample/conformance_Nlohmann%20(C%2B%2B11).md"
|
||||
data-name="v1.0.0"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target" title="v1.0.0">
|
||||
v1.0.0
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-no-results">Nothing to show</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group float-right">
|
||||
<a href="/miloyip/nativejson-benchmark/find/master"
|
||||
class="js-pjax-capture-input btn btn-sm"
|
||||
data-pjax
|
||||
data-hotkey="t">
|
||||
Find file
|
||||
</a>
|
||||
<button aria-label="Copy file path to clipboard" class="js-zeroclipboard btn btn-sm zeroclipboard-button tooltipped tooltipped-s" data-copied-hint="Copied!" type="button">Copy path</button>
|
||||
</div>
|
||||
<div class="breadcrumb js-zeroclipboard-target">
|
||||
<span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/miloyip/nativejson-benchmark"><span>nativejson-benchmark</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a href="/miloyip/nativejson-benchmark/tree/master/sample"><span>sample</span></a></span><span class="separator">/</span><strong class="final-path">conformance_Nlohmann (C++11).md</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="commit-tease">
|
||||
<span class="float-right">
|
||||
<a class="commit-tease-sha" href="/miloyip/nativejson-benchmark/commit/a4a9f10f41c515d6abb0f019ab9f5d021ed4bb9e" data-pjax>
|
||||
a4a9f10
|
||||
</a>
|
||||
<relative-time datetime="2016-09-09T03:15:21Z">Sep 9, 2016</relative-time>
|
||||
</span>
|
||||
<div>
|
||||
<img alt="@miloyip" class="avatar" height="20" src="https://avatars3.githubusercontent.com/u/1195774?v=3&s=40" width="20" />
|
||||
<a href="/miloyip" class="user-mention" rel="author">miloyip</a>
|
||||
<a href="/miloyip/nativejson-benchmark/commit/a4a9f10f41c515d6abb0f019ab9f5d021ed4bb9e" class="message" data-pjax="true" title="Update sample result for 41 libraries
|
||||
|
||||
Fixed #43">Update sample result for 41 libraries</a>
|
||||
</div>
|
||||
|
||||
<div class="commit-tease-contributors">
|
||||
<button type="button" class="btn-link muted-link contributors-toggle" data-facebox="#blob_contributors_box">
|
||||
<strong>1</strong>
|
||||
contributor
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="blob_contributors_box" style="display:none">
|
||||
<h2 class="facebox-header" data-facebox-id="facebox-header">Users who have contributed to this file</h2>
|
||||
<ul class="facebox-user-list" data-facebox-id="facebox-description">
|
||||
<li class="facebox-user-list-item">
|
||||
<img alt="@miloyip" height="24" src="https://avatars1.githubusercontent.com/u/1195774?v=3&s=48" width="24" />
|
||||
<a href="/miloyip">miloyip</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file">
|
||||
<div class="file-header">
|
||||
<div class="file-actions">
|
||||
|
||||
<div class="btn-group">
|
||||
<a href="/miloyip/nativejson-benchmark/raw/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm " id="raw-url">Raw</a>
|
||||
<a href="/miloyip/nativejson-benchmark/blame/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm js-update-url-with-hash">Blame</a>
|
||||
<a href="/miloyip/nativejson-benchmark/commits/master/sample/conformance_Nlohmann%20(C%2B%2B11).md" class="btn btn-sm " rel="nofollow">History</a>
|
||||
</div>
|
||||
|
||||
|
||||
<button type="button" class="btn-octicon disabled tooltipped tooltipped-nw"
|
||||
aria-label="You must be signed in to make or propose changes">
|
||||
<svg aria-hidden="true" class="octicon octicon-pencil" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"></path></svg>
|
||||
</button>
|
||||
<button type="button" class="btn-octicon btn-octicon-danger disabled tooltipped tooltipped-nw"
|
||||
aria-label="You must be signed in to make or propose changes">
|
||||
<svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="file-info">
|
||||
59 lines (37 sloc)
|
||||
<span class="file-info-divider"></span>
|
||||
545 Bytes
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="readme" class="readme blob instapaper_body">
|
||||
<article class="markdown-body entry-content" itemprop="text"><h1><a id="user-content-conformance-of-nlohmann-c11" class="anchor" href="#conformance-of-nlohmann-c11" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conformance of Nlohmann (C++11)</h1>
|
||||
|
||||
<h2><a id="user-content-1-parse-validation" class="anchor" href="#1-parse-validation" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>1. Parse Validation</h2>
|
||||
|
||||
<p>Summary: 34 of 34 are correct.</p>
|
||||
|
||||
<h2><a id="user-content-2-parse-double" class="anchor" href="#2-parse-double" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>2. Parse Double</h2>
|
||||
|
||||
<p>Summary: 66 of 66 are correct.</p>
|
||||
|
||||
<h2><a id="user-content-3-parse-string" class="anchor" href="#3-parse-string" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>3. Parse String</h2>
|
||||
|
||||
<p>Summary: 9 of 9 are correct.</p>
|
||||
|
||||
<h2><a id="user-content-4-roundtrip" class="anchor" href="#4-roundtrip" aria-hidden="true"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>4. Roundtrip</h2>
|
||||
|
||||
<ul>
|
||||
<li>Fail:</li>
|
||||
</ul>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">5e-324</span>]</pre></div>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">4.94065645841247e-324</span>]</pre></div>
|
||||
|
||||
<ul>
|
||||
<li>Fail:</li>
|
||||
</ul>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.225073858507201e-308</span>]</pre></div>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072e-308</span>]</pre></div>
|
||||
|
||||
<ul>
|
||||
<li>Fail:</li>
|
||||
</ul>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072014e-308</span>]</pre></div>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">2.2250738585072e-308</span>]</pre></div>
|
||||
|
||||
<ul>
|
||||
<li>Fail:</li>
|
||||
</ul>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">1.7976931348623157e308</span>]</pre></div>
|
||||
|
||||
<div class="highlight highlight-source-js"><pre>[<span class="pl-c1">1.79769313486232e+308</span>]</pre></div>
|
||||
|
||||
<p>Summary: 23 of 27 are correct.</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="d-none">Jump to Line</button>
|
||||
<div id="jump-to-line" style="display:none">
|
||||
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
|
||||
<input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line…" aria-label="Jump to line" autofocus>
|
||||
<button type="submit" class="btn">Go</button>
|
||||
</form></div>
|
||||
|
||||
</div>
|
||||
<div class="modal-backdrop js-touch-events"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container site-footer-container">
|
||||
<div class="site-footer" role="contentinfo">
|
||||
<ul class="site-footer-links float-right">
|
||||
<li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li>
|
||||
<li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
|
||||
<li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
|
||||
<li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>
|
||||
<li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
|
||||
<li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<a href="https://github.com" aria-label="Homepage" class="site-footer-mark" title="GitHub">
|
||||
<svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
|
||||
</a>
|
||||
<ul class="site-footer-links">
|
||||
<li>© 2016 <span title="0.18611s from github-fe151-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
|
||||
<li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>
|
||||
<li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>
|
||||
<li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li>
|
||||
<li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
|
||||
<li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="ajax-error-message" class="ajax-error-message flash flash-error">
|
||||
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg>
|
||||
<button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
|
||||
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
|
||||
</button>
|
||||
You can't perform that action at this time.
|
||||
</div>
|
||||
|
||||
|
||||
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/compat-40e365359d1c4db1e36a55be458e60f2b7c24d58b5a00ae13398480e7ba768e0.js"></script>
|
||||
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-88471af1fec40ff9418efbe2ddd15b6896af8d772f8179004c254dffc25ea490.js"></script>
|
||||
<script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-e18e11a943ff2eb9394c72d4ec8b76592c454915b5839ae177d422777a046e29.js"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none">
|
||||
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"></path></svg>
|
||||
<span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
|
||||
<span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
|
||||
</div>
|
||||
<div class="facebox" id="facebox" style="display:none;">
|
||||
<div class="facebox-popup">
|
||||
<div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
|
||||
</div>
|
||||
<button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
|
||||
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 182 KiB |
BIN
test/reports/2016-10-02-fuzz/exec_speed.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
test/reports/2016-10-02-fuzz/fuzz.tiff
Normal file
BIN
test/reports/2016-10-02-fuzz/high_freq.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
10
test/reports/2016-10-02-fuzz/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
|
||||
<tr><td style="width: 18ex"><b>Banner:</b></td><td>fuzz</td></tr>
|
||||
<tr><td><b>Directory:</b></td><td>fuzz-testing/out</td></tr>
|
||||
<tr><td><b>Generated on:</b></td><td>Sun Oct 2 08:51:02 CEST 2016</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
<img src="high_freq.png" width=1000 height=300><p>
|
||||
<img src="low_freq.png" width=1000 height=200><p>
|
||||
<img src="exec_speed.png" width=1000 height=200>
|
||||
|
||||
BIN
test/reports/2016-10-02-fuzz/low_freq.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||
| | |__ | | | | | | version 2.0.2
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Run "make fuzz_testing" and follow the instructions.
|
||||
|
||||
318
test/src/unit-algorithms.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("algorithms")
|
||||
{
|
||||
json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
|
||||
json j_object = {{"one", 1}, {"two", 2}};
|
||||
|
||||
SECTION("non-modifying sequence operations")
|
||||
{
|
||||
SECTION("std::all_of")
|
||||
{
|
||||
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
|
||||
{
|
||||
return value.size() > 0;
|
||||
}));
|
||||
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
|
||||
{
|
||||
return value.type() == json::value_t::number_integer;
|
||||
}));
|
||||
}
|
||||
|
||||
SECTION("std::any_of")
|
||||
{
|
||||
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
|
||||
{
|
||||
return value.is_string() and value.get<std::string>() == "foo";
|
||||
}));
|
||||
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
|
||||
{
|
||||
return value.get<int>() > 1;
|
||||
}));
|
||||
}
|
||||
|
||||
SECTION("std::none_of")
|
||||
{
|
||||
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
|
||||
{
|
||||
return value.size() == 0;
|
||||
}));
|
||||
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
|
||||
{
|
||||
return value.get<int>() <= 0;
|
||||
}));
|
||||
}
|
||||
|
||||
SECTION("std::for_each")
|
||||
{
|
||||
SECTION("reading")
|
||||
{
|
||||
int sum = 0;
|
||||
|
||||
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
|
||||
{
|
||||
if (value.is_number())
|
||||
{
|
||||
sum += static_cast<int>(value);
|
||||
}
|
||||
});
|
||||
|
||||
CHECK(sum == 45);
|
||||
}
|
||||
|
||||
SECTION("writing")
|
||||
{
|
||||
auto add17 = [](json & value)
|
||||
{
|
||||
if (value.is_array())
|
||||
{
|
||||
value.push_back(17);
|
||||
}
|
||||
};
|
||||
|
||||
std::for_each(j_array.begin(), j_array.end(), add17);
|
||||
|
||||
CHECK(j_array[6] == json({1, 2, 3, 17}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("std::count")
|
||||
{
|
||||
CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1);
|
||||
}
|
||||
|
||||
SECTION("std::count_if")
|
||||
{
|
||||
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
|
||||
{
|
||||
return (value.is_number());
|
||||
}) == 3);
|
||||
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
|
||||
{
|
||||
return true;
|
||||
}) == 9);
|
||||
}
|
||||
|
||||
SECTION("std::mismatch")
|
||||
{
|
||||
json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
|
||||
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
|
||||
CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
|
||||
CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
|
||||
}
|
||||
|
||||
SECTION("std::equal")
|
||||
{
|
||||
SECTION("using operator==")
|
||||
{
|
||||
CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
|
||||
CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
|
||||
CHECK(not std::equal(j_array.begin(), j_array.end(), j_object.begin()));
|
||||
}
|
||||
|
||||
SECTION("using user-defined comparison")
|
||||
{
|
||||
// compare objects only by size of its elements
|
||||
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
|
||||
CHECK(not std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
|
||||
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
|
||||
[](const json & a, const json & b)
|
||||
{
|
||||
return (a.size() == b.size());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("std::find")
|
||||
{
|
||||
auto it = std::find(j_array.begin(), j_array.end(), json(false));
|
||||
CHECK(std::distance(j_array.begin(), it) == 5);
|
||||
}
|
||||
|
||||
SECTION("std::find_if")
|
||||
{
|
||||
auto it = std::find_if(j_array.begin(), j_array.end(),
|
||||
[](const json & value)
|
||||
{
|
||||
return value.is_boolean();
|
||||
});
|
||||
CHECK(std::distance(j_array.begin(), it) == 4);
|
||||
}
|
||||
|
||||
SECTION("std::find_if_not")
|
||||
{
|
||||
auto it = std::find_if_not(j_array.begin(), j_array.end(),
|
||||
[](const json & value)
|
||||
{
|
||||
return value.is_number();
|
||||
});
|
||||
CHECK(std::distance(j_array.begin(), it) == 3);
|
||||
}
|
||||
|
||||
SECTION("std::adjacent_find")
|
||||
{
|
||||
CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
|
||||
CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
|
||||
[](const json & v1, const json & v2)
|
||||
{
|
||||
return v1.type() == v2.type();
|
||||
}) == j_array.begin());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("modifying sequence operations")
|
||||
{
|
||||
SECTION("std::reverse")
|
||||
{
|
||||
std::reverse(j_array.begin(), j_array.end());
|
||||
CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
|
||||
}
|
||||
|
||||
SECTION("std::rotate")
|
||||
{
|
||||
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
|
||||
CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
|
||||
}
|
||||
|
||||
SECTION("std::partition")
|
||||
{
|
||||
auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
|
||||
{
|
||||
return v.is_string();
|
||||
});
|
||||
CHECK(std::distance(j_array.begin(), it) == 2);
|
||||
CHECK(not it[2].is_string());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("sorting operations")
|
||||
{
|
||||
SECTION("std::sort")
|
||||
{
|
||||
SECTION("with standard comparison")
|
||||
{
|
||||
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
|
||||
std::sort(j.begin(), j.end());
|
||||
CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
|
||||
}
|
||||
|
||||
SECTION("with user-defined comparison")
|
||||
{
|
||||
json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
|
||||
std::sort(j.begin(), j.end(), [](const json & a, const json & b)
|
||||
{
|
||||
return a.size() < b.size();
|
||||
});
|
||||
CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
|
||||
}
|
||||
|
||||
SECTION("sorting an object")
|
||||
{
|
||||
json j({{"one", 1}, {"two", 2}});
|
||||
CHECK_THROWS_AS(std::sort(j.begin(), j.end()), std::domain_error);
|
||||
CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "cannot use offsets with object iterators");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("std::partial_sort")
|
||||
{
|
||||
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
|
||||
std::partial_sort(j.begin(), j.begin() + 4, j.end());
|
||||
CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("set operations")
|
||||
{
|
||||
SECTION("std::merge")
|
||||
{
|
||||
{
|
||||
json j1 = {2, 4, 6, 8};
|
||||
json j2 = {1, 2, 3, 5, 7};
|
||||
json j3;
|
||||
|
||||
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||
CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("std::set_difference")
|
||||
{
|
||||
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
json j2 = {1, 2, 3, 5, 7};
|
||||
json j3;
|
||||
|
||||
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||
CHECK(j3 == json({4, 6, 8}));
|
||||
}
|
||||
|
||||
SECTION("std::set_intersection")
|
||||
{
|
||||
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
json j2 = {1, 2, 3, 5, 7};
|
||||
json j3;
|
||||
|
||||
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||
CHECK(j3 == json({1, 2, 3, 5, 7}));
|
||||
}
|
||||
|
||||
SECTION("std::set_union")
|
||||
{
|
||||
json j1 = {2, 4, 6, 8};
|
||||
json j2 = {1, 2, 3, 5, 7};
|
||||
json j3;
|
||||
|
||||
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||
CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
|
||||
}
|
||||
|
||||
SECTION("std::set_symmetric_difference")
|
||||
{
|
||||
json j1 = {2, 4, 6, 8};
|
||||
json j2 = {1, 2, 3, 5, 7};
|
||||
json j3;
|
||||
|
||||
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||
CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("heap operations")
|
||||
{
|
||||
std::make_heap(j_array.begin(), j_array.end());
|
||||
CHECK(std::is_heap(j_array.begin(), j_array.end()));
|
||||
std::sort_heap(j_array.begin(), j_array.end());
|
||||
CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
|
||||
}
|
||||
}
|
||||
234
test/src/unit-allocator.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
// special test case to check if memory is leaked if constructor throws
|
||||
|
||||
template<class T>
|
||||
struct bad_allocator : std::allocator<T>
|
||||
{
|
||||
template<class... Args>
|
||||
void construct(T*, Args&& ...)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("bad_alloc")
|
||||
{
|
||||
SECTION("bad_alloc")
|
||||
{
|
||||
// create JSON type using the throwing allocator
|
||||
using bad_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
bad_allocator>;
|
||||
|
||||
// creating an object should throw
|
||||
CHECK_THROWS_AS(bad_json j(bad_json::value_t::object), std::bad_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
bool next_construct_fails = false;
|
||||
bool next_destroy_fails = false;
|
||||
bool next_deallocate_fails = false;
|
||||
|
||||
template<class T>
|
||||
struct my_allocator : std::allocator<T>
|
||||
{
|
||||
template<class... Args>
|
||||
void construct(T* p, Args&& ... args)
|
||||
{
|
||||
if (next_construct_fails)
|
||||
{
|
||||
next_construct_fails = false;
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
else
|
||||
{
|
||||
::new(reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (next_deallocate_fails)
|
||||
{
|
||||
next_deallocate_fails = false;
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy(T* p)
|
||||
{
|
||||
if (next_destroy_fails)
|
||||
{
|
||||
next_destroy_fails = false;
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
else
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("controlled bad_alloc")
|
||||
{
|
||||
// create JSON type using the throwing allocator
|
||||
using my_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
my_allocator>;
|
||||
|
||||
SECTION("class json_value")
|
||||
{
|
||||
SECTION("json_value(value_t)")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
auto t = my_json::value_t::object;
|
||||
CHECK_NOTHROW(my_json::json_value j(t));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
SECTION("array")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
auto t = my_json::value_t::array;
|
||||
CHECK_NOTHROW(my_json::json_value j(t));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
SECTION("string")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
auto t = my_json::value_t::string;
|
||||
CHECK_NOTHROW(my_json::json_value j(t));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("json_value(const string_t&)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
my_json::string_t v("foo");
|
||||
CHECK_NOTHROW(my_json::json_value j(v));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
|
||||
/*
|
||||
SECTION("json_value(const object_t&)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
my_json::object_t v {{"foo", "bar"}};
|
||||
CHECK_NOTHROW(my_json::json_value j(v));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
SECTION("json_value(const array_t&)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
my_json::array_t v = {"foo", "bar", "baz"};
|
||||
CHECK_NOTHROW(my_json::json_value j(v));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
SECTION("class basic_json")
|
||||
{
|
||||
SECTION("basic_json(const CompatibleObjectType&)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
std::map<std::string, std::string> v {{"foo", "bar"}};
|
||||
CHECK_NOTHROW(my_json j(v));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
|
||||
SECTION("basic_json(const CompatibleArrayType&)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
std::vector<std::string> v {"foo", "bar", "baz"};
|
||||
CHECK_NOTHROW(my_json j(v));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json j(v), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
|
||||
SECTION("basic_json(const typename string_t::value_type*)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
CHECK_NOTHROW(my_json v("foo"));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json v("foo"), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
|
||||
SECTION("basic_json(const typename string_t::value_type*)")
|
||||
{
|
||||
next_construct_fails = false;
|
||||
std::string s("foo");
|
||||
CHECK_NOTHROW(my_json v(s));
|
||||
next_construct_fails = true;
|
||||
CHECK_THROWS_AS(my_json v(s), std::bad_alloc);
|
||||
next_construct_fails = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
562
test/src/unit-capacity.cpp
Normal file
@@ -0,0 +1,562 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("capacity")
|
||||
{
|
||||
SECTION("empty()")
|
||||
{
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "hello world";
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("empty array")
|
||||
{
|
||||
json j = json::array();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == true);
|
||||
CHECK(j_const.empty() == true);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("empty object")
|
||||
{
|
||||
json j = json::object();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == true);
|
||||
CHECK(j_const.empty() == true);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled object")
|
||||
{
|
||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (float)")
|
||||
{
|
||||
json j = 23.42;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == false);
|
||||
CHECK(j_const.empty() == false);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of empty")
|
||||
{
|
||||
CHECK(j.empty() == true);
|
||||
CHECK(j_const.empty() == true);
|
||||
}
|
||||
|
||||
SECTION("definition of empty")
|
||||
{
|
||||
CHECK(j.empty() == (j.begin() == j.end()));
|
||||
CHECK(j_const.empty() == (j_const.begin() == j_const.end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("size()")
|
||||
{
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 1);
|
||||
CHECK(j_const.size() == 1);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "hello world";
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 1);
|
||||
CHECK(j_const.size() == 1);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("empty array")
|
||||
{
|
||||
json j = json::array();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 0);
|
||||
CHECK(j_const.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(j_const.size() == 3);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("empty object")
|
||||
{
|
||||
json j = json::object();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 0);
|
||||
CHECK(j_const.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled object")
|
||||
{
|
||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(j_const.size() == 3);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 1);
|
||||
CHECK(j_const.size() == 1);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 1);
|
||||
CHECK(j_const.size() == 1);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (float)")
|
||||
{
|
||||
json j = 23.42;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 1);
|
||||
CHECK(j_const.size() == 1);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of size")
|
||||
{
|
||||
CHECK(j.size() == 0);
|
||||
CHECK(j_const.size() == 0);
|
||||
}
|
||||
|
||||
SECTION("definition of size")
|
||||
{
|
||||
CHECK(std::distance(j.begin(), j.end()) == j.size());
|
||||
CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
|
||||
CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
|
||||
CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("max_size()")
|
||||
{
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 1);
|
||||
CHECK(j_const.max_size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "hello world";
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 1);
|
||||
CHECK(j_const.max_size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("empty array")
|
||||
{
|
||||
json j = json::array();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() >= j.size());
|
||||
CHECK(j_const.max_size() >= j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() >= j.size());
|
||||
CHECK(j_const.max_size() >= j_const.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("empty object")
|
||||
{
|
||||
json j = json::object();
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() >= j.size());
|
||||
CHECK(j_const.max_size() >= j_const.size());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("filled object")
|
||||
{
|
||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() >= j.size());
|
||||
CHECK(j_const.max_size() >= j_const.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 1);
|
||||
CHECK(j_const.max_size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 1);
|
||||
CHECK(j_const.max_size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (float)")
|
||||
{
|
||||
json j = 23.42;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 1);
|
||||
CHECK(j_const.max_size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
json j_const(j);
|
||||
|
||||
SECTION("result of max_size")
|
||||
{
|
||||
CHECK(j.max_size() == 0);
|
||||
CHECK(j_const.max_size() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
417
test/src/unit-class_const_iterator.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("const_iterator class")
|
||||
{
|
||||
SECTION("construction")
|
||||
{
|
||||
SECTION("constructor")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it(&j);
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::const_iterator it(&j);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::const_iterator it(&j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("copy assignment")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it(&j);
|
||||
json::const_iterator it2(&j);
|
||||
it2 = it;
|
||||
}
|
||||
|
||||
SECTION("copy constructor from non-const iterator")
|
||||
{
|
||||
SECTION("create from uninitialized iterator")
|
||||
{
|
||||
const json::iterator it {};
|
||||
json::const_iterator cit(it);
|
||||
}
|
||||
|
||||
SECTION("create from initialized iterator")
|
||||
{
|
||||
json j;
|
||||
const json::iterator it = j.begin();
|
||||
json::const_iterator cit(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("initialization")
|
||||
{
|
||||
SECTION("set_begin")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.cbegin());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::const_iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.cbegin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::const_iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.cbegin());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("set_end")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.cend());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::const_iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.cend());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::const_iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.cend());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("element access")
|
||||
{
|
||||
SECTION("operator*")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK_THROWS_AS(*it, std::out_of_range);
|
||||
CHECK_THROWS_WITH(*it, "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(*it == json(17));
|
||||
it = j.cend();
|
||||
CHECK_THROWS_AS(*it, std::out_of_range);
|
||||
CHECK_THROWS_WITH(*it, "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(*it == json("bar"));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(*it == json(1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("operator->")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK_THROWS_AS(it->type_name(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(it->type_name(), "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it->type_name() == "number");
|
||||
it = j.cend();
|
||||
CHECK_THROWS_AS(it->type_name(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(it->type_name(), "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it->type_name() == "string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it->type_name() == "number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("increment/decrement")
|
||||
{
|
||||
SECTION("post-increment")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it++;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
it++;
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it++;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
it++;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pre-increment")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
++it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
++it;
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
++it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
++it;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cbegin();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("post-decrement")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it--;
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
it--;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
it--;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pre-decrement")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
--it;
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
--it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
--it;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::const_iterator it = j.cend();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
401
test/src/unit-class_iterator.cpp
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("iterator class")
|
||||
{
|
||||
SECTION("construction")
|
||||
{
|
||||
SECTION("constructor")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it(&j);
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::iterator it(&j);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::iterator it(&j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("copy assignment")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it(&j);
|
||||
json::iterator it2(&j);
|
||||
it2 = it;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("initialization")
|
||||
{
|
||||
SECTION("set_begin")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.begin());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.begin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::iterator it(&j);
|
||||
it.set_begin();
|
||||
CHECK(it == j.begin());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("set_end")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
json::iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j(json::value_t::array);
|
||||
json::iterator it(&j);
|
||||
it.set_end();
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("element access")
|
||||
{
|
||||
SECTION("operator*")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.begin();
|
||||
CHECK_THROWS_AS(*it, std::out_of_range);
|
||||
CHECK_THROWS_WITH(*it, "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(*it == json(17));
|
||||
it = j.end();
|
||||
CHECK_THROWS_AS(*it, std::out_of_range);
|
||||
CHECK_THROWS_WITH(*it, "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(*it == json("bar"));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(*it == json(1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("operator->")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.begin();
|
||||
CHECK_THROWS_AS(it->type_name(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(it->type_name(), "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it->type_name() == "number");
|
||||
it = j.end();
|
||||
CHECK_THROWS_AS(it->type_name(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(it->type_name(), "cannot get value");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it->type_name() == "string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it->type_name() == "number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("increment/decrement")
|
||||
{
|
||||
SECTION("post-increment")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it++;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
it++;
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it++;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
it++;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it++;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pre-increment")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
++it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
++it;
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
++it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
++it;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.begin();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
++it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("post-decrement")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
it--;
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
it--;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
it--;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
it--;
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pre-decrement")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j(json::value_t::null);
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
json j(17);
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.primitive_iterator == 1);
|
||||
--it;
|
||||
CHECK(it.m_it.primitive_iterator == 0);
|
||||
--it;
|
||||
CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j({{"foo", "bar"}});
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
|
||||
--it;
|
||||
CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j({1, 2, 3, 4});
|
||||
json::iterator it = j.end();
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
--it;
|
||||
CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
|
||||
CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
183
test/src/unit-class_lexer.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("lexer class")
|
||||
{
|
||||
SECTION("scan")
|
||||
{
|
||||
SECTION("structural characters")
|
||||
{
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("["),
|
||||
1).scan() == json::lexer::token_type::begin_array);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("]"),
|
||||
1).scan() == json::lexer::token_type::end_array);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("{"),
|
||||
1).scan() == json::lexer::token_type::begin_object);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("}"),
|
||||
1).scan() == json::lexer::token_type::end_object);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(","),
|
||||
1).scan() == json::lexer::token_type::value_separator);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(":"),
|
||||
1).scan() == json::lexer::token_type::name_separator);
|
||||
}
|
||||
|
||||
SECTION("literal names")
|
||||
{
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("null"),
|
||||
4).scan() == json::lexer::token_type::literal_null);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("true"),
|
||||
4).scan() == json::lexer::token_type::literal_true);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("false"),
|
||||
5).scan() == json::lexer::token_type::literal_false);
|
||||
}
|
||||
|
||||
SECTION("numbers")
|
||||
{
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("0"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("1"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("2"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("3"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("4"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("5"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("6"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("7"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("8"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("9"),
|
||||
1).scan() == json::lexer::token_type::value_number);
|
||||
}
|
||||
|
||||
SECTION("whitespace")
|
||||
{
|
||||
// result is end_of_input, because not token is following
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(" "),
|
||||
1).scan() == json::lexer::token_type::end_of_input);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("\t"),
|
||||
1).scan() == json::lexer::token_type::end_of_input);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("\n"),
|
||||
1).scan() == json::lexer::token_type::end_of_input);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>("\r"),
|
||||
1).scan() == json::lexer::token_type::end_of_input);
|
||||
CHECK(json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(" \t\n\r\n\t "),
|
||||
7).scan() == json::lexer::token_type::end_of_input);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("token_type_name")
|
||||
{
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::uninitialized) == "<uninitialized>");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_true) == "true literal");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_false) == "false literal");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "']'");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "'}'");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == "':'");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == "','");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == "<parse error>");
|
||||
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "end of input");
|
||||
}
|
||||
|
||||
SECTION("parse errors on first character")
|
||||
{
|
||||
for (int c = 1; c < 128; ++c)
|
||||
{
|
||||
// create string from the ASCII code
|
||||
const auto s = std::string(1, c);
|
||||
// store scan() result
|
||||
const auto res = json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(s.c_str()),
|
||||
1).scan();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
// single characters that are valid tokens
|
||||
case ('['):
|
||||
case (']'):
|
||||
case ('{'):
|
||||
case ('}'):
|
||||
case (','):
|
||||
case (':'):
|
||||
case ('0'):
|
||||
case ('1'):
|
||||
case ('2'):
|
||||
case ('3'):
|
||||
case ('4'):
|
||||
case ('5'):
|
||||
case ('6'):
|
||||
case ('7'):
|
||||
case ('8'):
|
||||
case ('9'):
|
||||
{
|
||||
CHECK(res != json::lexer::token_type::parse_error);
|
||||
break;
|
||||
}
|
||||
|
||||
// whitespace
|
||||
case (' '):
|
||||
case ('\t'):
|
||||
case ('\n'):
|
||||
case ('\r'):
|
||||
{
|
||||
CHECK(res == json::lexer::token_type::end_of_input);
|
||||
break;
|
||||
}
|
||||
|
||||
// anything else is not expected
|
||||
default:
|
||||
{
|
||||
CHECK(res == json::lexer::token_type::parse_error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("to_unicode")
|
||||
{
|
||||
CHECK(json::lexer::to_unicode(0x1F4A9) == "💩");
|
||||
CHECK_THROWS_AS(json::lexer::to_unicode(0x200000), std::out_of_range);
|
||||
CHECK_THROWS_WITH(json::lexer::to_unicode(0x200000), "code points above 0x10FFFF are invalid");
|
||||
}
|
||||
}
|
||||
803
test/src/unit-class_parser.cpp
Normal file
@@ -0,0 +1,803 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <valarray>
|
||||
|
||||
TEST_CASE("parser class")
|
||||
{
|
||||
SECTION("parse")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
CHECK(json::parser("null").parse() == json(nullptr));
|
||||
}
|
||||
|
||||
SECTION("true")
|
||||
{
|
||||
CHECK(json::parser("true").parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("false")
|
||||
{
|
||||
CHECK(json::parser("false").parse() == json(false));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("empty array")
|
||||
{
|
||||
CHECK(json::parser("[]").parse() == json(json::value_t::array));
|
||||
CHECK(json::parser("[ ]").parse() == json(json::value_t::array));
|
||||
}
|
||||
|
||||
SECTION("nonempty array")
|
||||
{
|
||||
CHECK(json::parser("[true, false, null]").parse() == json({true, false, nullptr}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("empty object")
|
||||
{
|
||||
CHECK(json::parser("{}").parse() == json(json::value_t::object));
|
||||
CHECK(json::parser("{ }").parse() == json(json::value_t::object));
|
||||
}
|
||||
|
||||
SECTION("nonempty object")
|
||||
{
|
||||
CHECK(json::parser("{\"\": true, \"one\": 1, \"two\": null}").parse() == json({{"", true}, {"one", 1}, {"two", nullptr}}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
// empty string
|
||||
CHECK(json::parser("\"\"").parse() == json(json::value_t::string));
|
||||
|
||||
SECTION("errors")
|
||||
{
|
||||
// error: tab in string
|
||||
CHECK_THROWS_AS(json::parser("\"\t\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), "parse error - unexpected '\"'");
|
||||
// error: newline in string
|
||||
CHECK_THROWS_AS(json::parser("\"\n\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\r\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), "parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), "parse error - unexpected '\"'");
|
||||
// error: backspace in string
|
||||
CHECK_THROWS_AS(json::parser("\"\b\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'");
|
||||
// improve code coverage
|
||||
CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument);
|
||||
// unescaped control characters
|
||||
CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), std::invalid_argument);
|
||||
}
|
||||
|
||||
SECTION("escaped")
|
||||
{
|
||||
// quotation mark "\""
|
||||
auto r1 = R"("\"")"_json;
|
||||
CHECK(json::parser("\"\\\"\"").parse() == r1);
|
||||
// reverse solidus "\\"
|
||||
auto r2 = R"("\\")"_json;
|
||||
CHECK(json::parser("\"\\\\\"").parse() == r2);
|
||||
// solidus
|
||||
CHECK(json::parser("\"\\/\"").parse() == R"("/")"_json);
|
||||
// backspace
|
||||
CHECK(json::parser("\"\\b\"").parse() == json("\b"));
|
||||
// formfeed
|
||||
CHECK(json::parser("\"\\f\"").parse() == json("\f"));
|
||||
// newline
|
||||
CHECK(json::parser("\"\\n\"").parse() == json("\n"));
|
||||
// carriage return
|
||||
CHECK(json::parser("\"\\r\"").parse() == json("\r"));
|
||||
// horizontal tab
|
||||
CHECK(json::parser("\"\\t\"").parse() == json("\t"));
|
||||
|
||||
CHECK(json::parser("\"\\u0001\"").parse().get<json::string_t>() == "\x01");
|
||||
CHECK(json::parser("\"\\u000a\"").parse().get<json::string_t>() == "\n");
|
||||
CHECK(json::parser("\"\\u00b0\"").parse().get<json::string_t>() == "°");
|
||||
CHECK(json::parser("\"\\u0c00\"").parse().get<json::string_t>() == "ఀ");
|
||||
CHECK(json::parser("\"\\ud000\"").parse().get<json::string_t>() == "퀀");
|
||||
CHECK(json::parser("\"\\u000E\"").parse().get<json::string_t>() == "\x0E");
|
||||
CHECK(json::parser("\"\\u00F0\"").parse().get<json::string_t>() == "ð");
|
||||
CHECK(json::parser("\"\\u0100\"").parse().get<json::string_t>() == "Ā");
|
||||
CHECK(json::parser("\"\\u2000\"").parse().get<json::string_t>() == " ");
|
||||
CHECK(json::parser("\"\\uFFFF\"").parse().get<json::string_t>() == "");
|
||||
CHECK(json::parser("\"\\u20AC\"").parse().get<json::string_t>() == "€");
|
||||
CHECK(json::parser("\"€\"").parse().get<json::string_t>() == "€");
|
||||
CHECK(json::parser("\"🎈\"").parse().get<json::string_t>() == "🎈");
|
||||
|
||||
CHECK(json::parse("\"\\ud80c\\udc60\"").get<json::string_t>() == u8"\U00013060");
|
||||
CHECK(json::parse("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number")
|
||||
{
|
||||
SECTION("integers")
|
||||
{
|
||||
SECTION("without exponent")
|
||||
{
|
||||
CHECK(json::parser("-128").parse() == json(-128));
|
||||
CHECK(json::parser("-0").parse() == json(-0));
|
||||
CHECK(json::parser("0").parse() == json(0));
|
||||
CHECK(json::parser("128").parse() == json(128));
|
||||
}
|
||||
|
||||
SECTION("with exponent")
|
||||
{
|
||||
CHECK(json::parser("0e1").parse() == json(0e1));
|
||||
CHECK(json::parser("0E1").parse() == json(0e1));
|
||||
|
||||
CHECK(json::parser("10000E-4").parse() == json(10000e-4));
|
||||
CHECK(json::parser("10000E-3").parse() == json(10000e-3));
|
||||
CHECK(json::parser("10000E-2").parse() == json(10000e-2));
|
||||
CHECK(json::parser("10000E-1").parse() == json(10000e-1));
|
||||
CHECK(json::parser("10000E0").parse() == json(10000e0));
|
||||
CHECK(json::parser("10000E1").parse() == json(10000e1));
|
||||
CHECK(json::parser("10000E2").parse() == json(10000e2));
|
||||
CHECK(json::parser("10000E3").parse() == json(10000e3));
|
||||
CHECK(json::parser("10000E4").parse() == json(10000e4));
|
||||
|
||||
CHECK(json::parser("10000e-4").parse() == json(10000e-4));
|
||||
CHECK(json::parser("10000e-3").parse() == json(10000e-3));
|
||||
CHECK(json::parser("10000e-2").parse() == json(10000e-2));
|
||||
CHECK(json::parser("10000e-1").parse() == json(10000e-1));
|
||||
CHECK(json::parser("10000e0").parse() == json(10000e0));
|
||||
CHECK(json::parser("10000e1").parse() == json(10000e1));
|
||||
CHECK(json::parser("10000e2").parse() == json(10000e2));
|
||||
CHECK(json::parser("10000e3").parse() == json(10000e3));
|
||||
CHECK(json::parser("10000e4").parse() == json(10000e4));
|
||||
|
||||
CHECK(json::parser("-0e1").parse() == json(-0e1));
|
||||
CHECK(json::parser("-0E1").parse() == json(-0e1));
|
||||
CHECK(json::parser("-0E123").parse() == json(-0e123));
|
||||
}
|
||||
|
||||
SECTION("edge cases")
|
||||
{
|
||||
// From RFC7159, Section 6:
|
||||
// Note that when such software is used, numbers that are
|
||||
// integers and are in the range [-(2**53)+1, (2**53)-1]
|
||||
// are interoperable in the sense that implementations will
|
||||
// agree exactly on their numeric values.
|
||||
|
||||
// -(2**53)+1
|
||||
CHECK(json::parser("-9007199254740991").parse().get<int64_t>() == -9007199254740991);
|
||||
// (2**53)-1
|
||||
CHECK(json::parser("9007199254740991").parse().get<int64_t>() == 9007199254740991);
|
||||
}
|
||||
|
||||
SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
|
||||
{
|
||||
// While RFC7159, Section 6 specifies a preference for support
|
||||
// for ranges in range of IEEE 754-2008 binary64 (double precision)
|
||||
// this does not accommodate 64 bit integers without loss of accuracy.
|
||||
// As 64 bit integers are now widely used in software, it is desirable
|
||||
// to expand support to to the full 64 bit (signed and unsigned) range
|
||||
// i.e. -(2**63) -> (2**64)-1.
|
||||
|
||||
// -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
|
||||
CHECK(json::parser("-9223372036854775808").parse().get<int64_t>() == -9223372036854775807 - 1);
|
||||
// (2**63)-1
|
||||
CHECK(json::parser("9223372036854775807").parse().get<int64_t>() == 9223372036854775807);
|
||||
// (2**64)-1
|
||||
CHECK(json::parser("18446744073709551615").parse().get<uint64_t>() == 18446744073709551615u);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("floating-point")
|
||||
{
|
||||
SECTION("without exponent")
|
||||
{
|
||||
CHECK(json::parser("-128.5").parse() == json(-128.5));
|
||||
CHECK(json::parser("0.999").parse() == json(0.999));
|
||||
CHECK(json::parser("128.5").parse() == json(128.5));
|
||||
CHECK(json::parser("-0.0").parse() == json(-0.0));
|
||||
}
|
||||
|
||||
SECTION("with exponent")
|
||||
{
|
||||
CHECK(json::parser("-128.5E3").parse() == json(-128.5E3));
|
||||
CHECK(json::parser("-128.5E-3").parse() == json(-128.5E-3));
|
||||
CHECK(json::parser("-0.0e1").parse() == json(-0.0e1));
|
||||
CHECK(json::parser("-0.0E1").parse() == json(-0.0e1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("invalid numbers")
|
||||
{
|
||||
CHECK_THROWS_AS(json::parser("01").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("--1").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1E").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1E-").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1.E1").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-1E").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0E#").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0E-#").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0#").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0.0:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0.0Z").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0E123:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0e0-:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0e-:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0f").parse(), std::invalid_argument);
|
||||
|
||||
// numbers must not begin with "+"
|
||||
CHECK_THROWS_AS(json::parser("+1").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument);
|
||||
|
||||
CHECK_THROWS_WITH(json::parser("01").parse(),
|
||||
"parse error - unexpected number literal; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'");
|
||||
CHECK_THROWS_WITH(json::parser("1.").parse(),
|
||||
"parse error - unexpected '.'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1E").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1E-").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1.E1").parse(),
|
||||
"parse error - unexpected '.'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-1E").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0E#").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0E-#").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0#").parse(),
|
||||
"parse error - unexpected '#'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0.0:").parse(),
|
||||
"parse error - unexpected ':'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0.0Z").parse(),
|
||||
"parse error - unexpected 'Z'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0E123:").parse(),
|
||||
"parse error - unexpected ':'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0e0-:").parse(),
|
||||
"parse error - unexpected '-'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0e-:").parse(),
|
||||
"parse error - unexpected 'e'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-0f").parse(),
|
||||
"parse error - unexpected 'f'; expected end of input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("parse errors")
|
||||
{
|
||||
// unexpected end of number
|
||||
CHECK_THROWS_AS(json::parser("0.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("--").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-0.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("-:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("0.:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("e.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1e.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1e/").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1e:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("0.").parse(),
|
||||
"parse error - unexpected '.'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'");
|
||||
CHECK_THROWS_WITH(json::parser("--").parse(),
|
||||
"parse error - unexpected '-'");
|
||||
CHECK_THROWS_WITH(json::parser("-0.").parse(),
|
||||
"parse error - unexpected '.'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("-.").parse(),
|
||||
"parse error - unexpected '-'");
|
||||
CHECK_THROWS_WITH(json::parser("-:").parse(),
|
||||
"parse error - unexpected '-'");
|
||||
CHECK_THROWS_WITH(json::parser("0.:").parse(),
|
||||
"parse error - unexpected '.'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("e.").parse(),
|
||||
"parse error - unexpected 'e'");
|
||||
CHECK_THROWS_WITH(json::parser("1e.").parse(),
|
||||
"parse error - unexpected 'e'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1e/").parse(),
|
||||
"parse error - unexpected 'e'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1e:").parse(),
|
||||
"parse error - unexpected 'e'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1E.").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1E/").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("1E:").parse(),
|
||||
"parse error - unexpected 'E'; expected end of input");
|
||||
|
||||
// unexpected end of null
|
||||
CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("nu").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("nul").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("n").parse(), "parse error - unexpected 'n'");
|
||||
CHECK_THROWS_WITH(json::parser("nu").parse(),
|
||||
"parse error - unexpected 'n'");
|
||||
CHECK_THROWS_WITH(json::parser("nul").parse(),
|
||||
"parse error - unexpected 'n'");
|
||||
|
||||
// unexpected end of true
|
||||
CHECK_THROWS_AS(json::parser("t").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("tr").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("tru").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("t").parse(), "parse error - unexpected 't'");
|
||||
CHECK_THROWS_WITH(json::parser("tr").parse(),
|
||||
"parse error - unexpected 't'");
|
||||
CHECK_THROWS_WITH(json::parser("tru").parse(),
|
||||
"parse error - unexpected 't'");
|
||||
|
||||
// unexpected end of false
|
||||
CHECK_THROWS_AS(json::parser("f").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("fa").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("fal").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("fals").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("f").parse(), "parse error - unexpected 'f'");
|
||||
CHECK_THROWS_WITH(json::parser("fa").parse(),
|
||||
"parse error - unexpected 'f'");
|
||||
CHECK_THROWS_WITH(json::parser("fal").parse(),
|
||||
"parse error - unexpected 'f'");
|
||||
CHECK_THROWS_WITH(json::parser("fals").parse(),
|
||||
"parse error - unexpected 'f'");
|
||||
|
||||
// missing/unexpected end of array
|
||||
CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("[").parse(),
|
||||
"parse error - unexpected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("[1").parse(),
|
||||
"parse error - unexpected end of input; expected ']'");
|
||||
CHECK_THROWS_WITH(json::parser("[1,").parse(),
|
||||
"parse error - unexpected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("[1,]").parse(),
|
||||
"parse error - unexpected ']'");
|
||||
CHECK_THROWS_WITH(json::parser("]").parse(), "parse error - unexpected ']'");
|
||||
|
||||
// missing/unexpected end of object
|
||||
CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("{").parse(),
|
||||
"parse error - unexpected end of input; expected string literal");
|
||||
CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(),
|
||||
"parse error - unexpected end of input; expected ':'");
|
||||
CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(),
|
||||
"parse error - unexpected end of input");
|
||||
CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(),
|
||||
"parse error - unexpected '}'");
|
||||
CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(),
|
||||
"parse error - unexpected '}'; expected string literal");
|
||||
CHECK_THROWS_WITH(json::parser("}").parse(), "parse error - unexpected '}'");
|
||||
|
||||
// missing/unexpected end of string
|
||||
CHECK_THROWS_AS(json::parser("\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u0").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u01").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser("\"\\u012").parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser("\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u0").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u01").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser("\"\\u012").parse(),
|
||||
"parse error - unexpected '\"'");
|
||||
|
||||
// invalid escapes
|
||||
for (int c = 1; c < 128; ++c)
|
||||
{
|
||||
auto s = std::string("\"\\") + std::string(1, c) + "\"";
|
||||
|
||||
switch (c)
|
||||
{
|
||||
// valid escapes
|
||||
case ('"'):
|
||||
case ('\\'):
|
||||
case ('/'):
|
||||
case ('b'):
|
||||
case ('f'):
|
||||
case ('n'):
|
||||
case ('r'):
|
||||
case ('t'):
|
||||
{
|
||||
CHECK_NOTHROW(json::parser(s.c_str()).parse());
|
||||
break;
|
||||
}
|
||||
|
||||
// \u must be followed with four numbers, so we skip it here
|
||||
case ('u'):
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// any other combination of backslash and character is invalid
|
||||
default:
|
||||
{
|
||||
CHECK_THROWS_AS(json::parser(s.c_str()).parse(), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parser(s.c_str()).parse(), "parse error - unexpected '\"'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// invalid \uxxxx escapes
|
||||
{
|
||||
// check whether character is a valid hex character
|
||||
const auto valid = [](int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ('0'):
|
||||
case ('1'):
|
||||
case ('2'):
|
||||
case ('3'):
|
||||
case ('4'):
|
||||
case ('5'):
|
||||
case ('6'):
|
||||
case ('7'):
|
||||
case ('8'):
|
||||
case ('9'):
|
||||
case ('a'):
|
||||
case ('b'):
|
||||
case ('c'):
|
||||
case ('d'):
|
||||
case ('e'):
|
||||
case ('f'):
|
||||
case ('A'):
|
||||
case ('B'):
|
||||
case ('C'):
|
||||
case ('D'):
|
||||
case ('E'):
|
||||
case ('F'):
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int c = 1; c < 128; ++c)
|
||||
{
|
||||
std::string s = "\"\\u";
|
||||
|
||||
// create a string with the iterated character at each position
|
||||
auto s1 = s + "000" + std::string(1, c) + "\"";
|
||||
auto s2 = s + "00" + std::string(1, c) + "0\"";
|
||||
auto s3 = s + "0" + std::string(1, c) + "00\"";
|
||||
auto s4 = s + std::string(1, c) + "000\"";
|
||||
|
||||
if (valid(c))
|
||||
{
|
||||
CHECK_NOTHROW(json::parser(s1.c_str()).parse());
|
||||
CHECK_NOTHROW(json::parser(s2.c_str()).parse());
|
||||
CHECK_NOTHROW(json::parser(s3.c_str()).parse());
|
||||
CHECK_NOTHROW(json::parser(s4.c_str()).parse());
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_THROWS_AS(json::parser(s1.c_str()).parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser(s2.c_str()).parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser(s3.c_str()).parse(), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parser(s4.c_str()).parse(), std::invalid_argument);
|
||||
|
||||
CHECK_THROWS_WITH(json::parser(s1.c_str()).parse(), "parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser(s2.c_str()).parse(), "parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser(s3.c_str()).parse(), "parse error - unexpected '\"'");
|
||||
CHECK_THROWS_WITH(json::parser(s4.c_str()).parse(), "parse error - unexpected '\"'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// missing part of a surrogate pair
|
||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\""), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "missing low surrogate");
|
||||
// invalid surrogate pair
|
||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""),
|
||||
"missing or wrong low surrogate");
|
||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""),
|
||||
"missing or wrong low surrogate");
|
||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""),
|
||||
"missing or wrong low surrogate");
|
||||
}
|
||||
|
||||
SECTION("callback function")
|
||||
{
|
||||
auto s_object = R"(
|
||||
{
|
||||
"foo": 2,
|
||||
"bar": {
|
||||
"baz": 1
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
auto s_array = R"(
|
||||
[1,2,[3,4,5],4,5]
|
||||
)";
|
||||
|
||||
SECTION("filter nothing")
|
||||
{
|
||||
json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
|
||||
{
|
||||
return true;
|
||||
});
|
||||
|
||||
CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}}));
|
||||
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
|
||||
{
|
||||
return true;
|
||||
});
|
||||
|
||||
CHECK (j_array == json({1, 2, {3, 4, 5}, 4, 5}));
|
||||
}
|
||||
|
||||
SECTION("filter everything")
|
||||
{
|
||||
json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
|
||||
{
|
||||
return false;
|
||||
});
|
||||
|
||||
// the top-level object will be discarded, leaving a null
|
||||
CHECK (j_object.is_null());
|
||||
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
|
||||
{
|
||||
return false;
|
||||
});
|
||||
|
||||
// the top-level array will be discarded, leaving a null
|
||||
CHECK (j_array.is_null());
|
||||
}
|
||||
|
||||
SECTION("filter specific element")
|
||||
{
|
||||
json j_object = json::parse(s_object, [](int, json::parse_event_t, const json & j)
|
||||
{
|
||||
// filter all number(2) elements
|
||||
if (j == json(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
|
||||
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t, const json & j)
|
||||
{
|
||||
if (j == json(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
|
||||
}
|
||||
|
||||
SECTION("filter specific events")
|
||||
{
|
||||
SECTION("first closing event")
|
||||
{
|
||||
{
|
||||
json j_object = json::parse(s_object, [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
static bool first = true;
|
||||
if (e == json::parse_event_t::object_end and first)
|
||||
{
|
||||
first = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// the first completed object will be discarded
|
||||
CHECK (j_object == json({{"foo", 2}}));
|
||||
}
|
||||
|
||||
{
|
||||
json j_array = json::parse(s_array, [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
static bool first = true;
|
||||
if (e == json::parse_event_t::array_end and first)
|
||||
{
|
||||
first = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// the first completed array will be discarded
|
||||
CHECK (j_array == json({1, 2, 4, 5}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("special cases")
|
||||
{
|
||||
// the following test cases cover the situation in which an empty
|
||||
// object and array is discarded only after the closing character
|
||||
// has been read
|
||||
|
||||
json j_empty_object = json::parse("{}", [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
if (e == json::parse_event_t::object_end)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
CHECK(j_empty_object == json());
|
||||
|
||||
json j_empty_array = json::parse("[]", [](int, json::parse_event_t e, const json&)
|
||||
{
|
||||
if (e == json::parse_event_t::array_end)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
CHECK(j_empty_array == json());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("constructing from contiguous containers")
|
||||
{
|
||||
SECTION("from std::vector")
|
||||
{
|
||||
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::array")
|
||||
{
|
||||
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from array")
|
||||
{
|
||||
uint8_t v[] = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from char literal")
|
||||
{
|
||||
CHECK(json::parser("true").parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::string")
|
||||
{
|
||||
std::string v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::initializer_list")
|
||||
{
|
||||
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::valarray")
|
||||
{
|
||||
std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
246
test/src/unit-comparison.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("lexicographical comparison operators")
|
||||
{
|
||||
SECTION("types")
|
||||
{
|
||||
std::vector<json::value_t> j_types =
|
||||
{
|
||||
json::value_t::null,
|
||||
json::value_t::boolean,
|
||||
json::value_t::number_integer,
|
||||
json::value_t::number_unsigned,
|
||||
json::value_t::number_float,
|
||||
json::value_t::object,
|
||||
json::value_t::array,
|
||||
json::value_t::string
|
||||
};
|
||||
|
||||
SECTION("comparison: less")
|
||||
{
|
||||
std::vector<std::vector<bool>> expected =
|
||||
{
|
||||
{false, true, true, true, true, true, true, true},
|
||||
{false, false, true, true, true, true, true, true},
|
||||
{false, false, false, false, false, true, true, true},
|
||||
{false, false, false, false, false, true, true, true},
|
||||
{false, false, false, false, false, true, true, true},
|
||||
{false, false, false, false, false, false, true, true},
|
||||
{false, false, false, false, false, false, false, true},
|
||||
{false, false, false, false, false, false, false, false}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < j_types.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_types.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check precomputed values
|
||||
CHECK(operator<(j_types[i], j_types[j]) == expected[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("values")
|
||||
{
|
||||
json j_values =
|
||||
{
|
||||
nullptr, nullptr,
|
||||
17, 42,
|
||||
8u, 13u,
|
||||
3.14159, 23.42,
|
||||
"foo", "bar",
|
||||
true, false,
|
||||
{1, 2, 3}, {"one", "two", "three"},
|
||||
{{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}
|
||||
};
|
||||
|
||||
SECTION("comparison: equal")
|
||||
{
|
||||
std::vector<std::vector<bool>> expected =
|
||||
{
|
||||
{true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check precomputed values
|
||||
CHECK( (j_values[i] == j_values[j]) == expected[i][j] );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison with discarded elements
|
||||
json j_discarded(json::value_t::discarded);
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
CHECK( (j_values[i] == j_discarded) == false);
|
||||
CHECK( (j_discarded == j_values[i]) == false);
|
||||
CHECK( (j_discarded == j_discarded) == false);
|
||||
}
|
||||
|
||||
// compare with null pointer
|
||||
json j_null;
|
||||
CHECK(j_null == nullptr);
|
||||
CHECK(nullptr == j_null);
|
||||
}
|
||||
|
||||
SECTION("comparison: not equal")
|
||||
{
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check definition
|
||||
CHECK( (j_values[i] != j_values[j]) == not(j_values[i] == j_values[j]) );
|
||||
}
|
||||
}
|
||||
|
||||
// compare with null pointer
|
||||
json j_null;
|
||||
CHECK( (j_null != nullptr) == false);
|
||||
CHECK( (nullptr != j_null) == false);
|
||||
CHECK( (j_null != nullptr) == not(j_null == nullptr));
|
||||
CHECK( (nullptr != j_null) == not(nullptr == j_null));
|
||||
}
|
||||
|
||||
SECTION("comparison: less")
|
||||
{
|
||||
std::vector<std::vector<bool>> expected =
|
||||
{
|
||||
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{false, false, false, true, false, false, false, true, true, true, false, false, true, true, true, true},
|
||||
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, true},
|
||||
{false, false, true, true, false, true, false, true, true, true, false, false, true, true, true, true},
|
||||
{false, false, true, true, false, false, false, true, true, true, false, false, true, true, true, true},
|
||||
{false, false, true, true, true, true, false, true, true, true, false, false, true, true, true, true},
|
||||
{false, false, false, true, false, false, false, false, true, true, false, false, true, true, true, true},
|
||||
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
|
||||
{false, false, true, true, true, true, true, true, true, true, false, false, true, true, true, true},
|
||||
{false, false, true, true, true, true, true, true, true, true, true, false, true, true, true, true},
|
||||
{false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, false},
|
||||
{false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false},
|
||||
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
|
||||
{false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, false}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check precomputed values
|
||||
CHECK( (j_values[i] < j_values[j]) == expected[i][j] );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison with discarded elements
|
||||
json j_discarded(json::value_t::discarded);
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CHECK( (j_values[i] < j_discarded) == false);
|
||||
CHECK( (j_discarded < j_values[i]) == false);
|
||||
CHECK( (j_discarded < j_discarded) == false);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("comparison: less than or equal equal")
|
||||
{
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check definition
|
||||
CHECK( (j_values[i] <= j_values[j]) == not(j_values[j] < j_values[i]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("comparison: greater than")
|
||||
{
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check definition
|
||||
CHECK( (j_values[i] > j_values[j]) == (j_values[j] < j_values[i]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("comparison: greater than or equal")
|
||||
{
|
||||
for (size_t i = 0; i < j_values.size(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < j_values.size(); ++j)
|
||||
{
|
||||
CAPTURE(i);
|
||||
CAPTURE(j);
|
||||
// check definition
|
||||
CHECK( (j_values[i] >= j_values[j]) == not(j_values[i] < j_values[j]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
169
test/src/unit-concepts.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("concepts")
|
||||
{
|
||||
SECTION("container requirements for json")
|
||||
{
|
||||
// X: container class: json
|
||||
// T: type of objects: json
|
||||
// a, b: values of type X: json
|
||||
|
||||
// TABLE 96 - Container Requirements
|
||||
|
||||
// X::value_type must return T
|
||||
CHECK((std::is_same<json::value_type, json>::value));
|
||||
|
||||
// X::reference must return lvalue of T
|
||||
CHECK((std::is_same<json::reference, json&>::value));
|
||||
|
||||
// X::const_reference must return const lvalue of T
|
||||
CHECK((std::is_same<json::const_reference, const json&>::value));
|
||||
|
||||
// X::iterator must return iterator whose value_type is T
|
||||
CHECK((std::is_same<json::iterator::value_type, json>::value));
|
||||
// X::iterator must meet the forward iterator requirements
|
||||
CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
|
||||
// X::iterator must be convertible to X::const_iterator
|
||||
CHECK((std::is_convertible<json::iterator, json::const_iterator>::value));
|
||||
|
||||
// X::const_iterator must return iterator whose value_type is T
|
||||
CHECK((std::is_same<json::const_iterator::value_type, json>::value));
|
||||
// X::const_iterator must meet the forward iterator requirements
|
||||
CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
|
||||
|
||||
// X::difference_type must return a signed integer
|
||||
CHECK((std::is_signed<json::difference_type>::value));
|
||||
// X::difference_type must be identical to X::iterator::difference_type
|
||||
CHECK((std::is_same<json::difference_type, json::iterator::difference_type>::value));
|
||||
// X::difference_type must be identical to X::const_iterator::difference_type
|
||||
CHECK((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
|
||||
|
||||
// X::size_type must return an unsigned integer
|
||||
CHECK((std::is_unsigned<json::size_type>::value));
|
||||
// X::size_type can represent any non-negative value of X::difference_type
|
||||
CHECK(std::numeric_limits<json::difference_type>::max() <=
|
||||
std::numeric_limits<json::size_type>::max());
|
||||
|
||||
// the expression "X u" has the post-condition "u.empty()"
|
||||
{
|
||||
json u;
|
||||
CHECK(u.empty());
|
||||
}
|
||||
|
||||
// the expression "X()" has the post-condition "X().empty()"
|
||||
CHECK(json().empty());
|
||||
}
|
||||
|
||||
SECTION("class json")
|
||||
{
|
||||
SECTION("DefaultConstructible")
|
||||
{
|
||||
CHECK(std::is_nothrow_default_constructible<json>::value);
|
||||
}
|
||||
|
||||
SECTION("MoveConstructible")
|
||||
{
|
||||
CHECK(std::is_nothrow_move_constructible<json>::value);
|
||||
}
|
||||
|
||||
SECTION("CopyConstructible")
|
||||
{
|
||||
CHECK(std::is_copy_constructible<json>::value);
|
||||
}
|
||||
|
||||
SECTION("MoveAssignable")
|
||||
{
|
||||
CHECK(std::is_nothrow_move_assignable<json>::value);
|
||||
}
|
||||
|
||||
SECTION("CopyAssignable")
|
||||
{
|
||||
CHECK(std::is_copy_assignable<json>::value);
|
||||
}
|
||||
|
||||
SECTION("Destructible")
|
||||
{
|
||||
CHECK(std::is_nothrow_destructible<json>::value);
|
||||
}
|
||||
|
||||
SECTION("StandardLayoutType")
|
||||
{
|
||||
CHECK(std::is_standard_layout<json>::value);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("class iterator")
|
||||
{
|
||||
SECTION("CopyConstructible")
|
||||
{
|
||||
CHECK(std::is_nothrow_copy_constructible<json::iterator>::value);
|
||||
CHECK(std::is_nothrow_copy_constructible<json::const_iterator>::value);
|
||||
}
|
||||
|
||||
SECTION("CopyAssignable")
|
||||
{
|
||||
// STL iterators used by json::iterator don't pass this test in Debug mode
|
||||
#if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
|
||||
CHECK(std::is_nothrow_copy_assignable<json::iterator>::value);
|
||||
CHECK(std::is_nothrow_copy_assignable<json::const_iterator>::value);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("Destructible")
|
||||
{
|
||||
CHECK(std::is_nothrow_destructible<json::iterator>::value);
|
||||
CHECK(std::is_nothrow_destructible<json::const_iterator>::value);
|
||||
}
|
||||
|
||||
SECTION("Swappable")
|
||||
{
|
||||
{
|
||||
json j {1, 2, 3};
|
||||
json::iterator it1 = j.begin();
|
||||
json::iterator it2 = j.end();
|
||||
std::swap(it1, it2);
|
||||
CHECK(it1 == j.end());
|
||||
CHECK(it2 == j.begin());
|
||||
}
|
||||
{
|
||||
json j {1, 2, 3};
|
||||
json::const_iterator it1 = j.cbegin();
|
||||
json::const_iterator it2 = j.cend();
|
||||
std::swap(it1, it2);
|
||||
CHECK(it1 == j.end());
|
||||
CHECK(it2 == j.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1311
test/src/unit-constructor1.cpp
Normal file
191
test/src/unit-constructor2.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("other constructors and destructor")
|
||||
{
|
||||
SECTION("copy constructor")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
json j {{"foo", 1}, {"bar", false}};
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j {"foo", 1, 42.23, false};
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j(nullptr);
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j(true);
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j("Hello world");
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j(42);
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j(42u);
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j(42.23);
|
||||
json k(j);
|
||||
CHECK(j == k);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("move constructor")
|
||||
{
|
||||
json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
|
||||
CHECK(j.type() == json::value_t::object);
|
||||
json k(std::move(j));
|
||||
CHECK(k.type() == json::value_t::object);
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
}
|
||||
|
||||
SECTION("copy assignment")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
json j {{"foo", 1}, {"bar", false}};
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j {"foo", 1, 42.23, false};
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j(nullptr);
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j(true);
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j("Hello world");
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j(42);
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j(42u);
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j(42.23);
|
||||
json k;
|
||||
k = j;
|
||||
CHECK(j == k);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("destructor")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
auto j = new json {{"foo", 1}, {"bar", false}};
|
||||
delete j;
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
auto j = new json {"foo", 1, 1u, false, 23.42};
|
||||
delete j;
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
auto j = new json("Hello world");
|
||||
delete j;
|
||||
}
|
||||
}
|
||||
}
|
||||
92
test/src/unit-convenience.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("convenience functions")
|
||||
{
|
||||
SECTION("type name as string")
|
||||
{
|
||||
CHECK(json(json::value_t::null).type_name() == "null");
|
||||
CHECK(json(json::value_t::object).type_name() == "object");
|
||||
CHECK(json(json::value_t::array).type_name() == "array");
|
||||
CHECK(json(json::value_t::number_integer).type_name() == "number");
|
||||
CHECK(json(json::value_t::number_unsigned).type_name() == "number");
|
||||
CHECK(json(json::value_t::number_float).type_name() == "number");
|
||||
CHECK(json(json::value_t::boolean).type_name() == "boolean");
|
||||
CHECK(json(json::value_t::string).type_name() == "string");
|
||||
CHECK(json(json::value_t::discarded).type_name() == "discarded");
|
||||
}
|
||||
|
||||
SECTION("string escape")
|
||||
{
|
||||
CHECK(json::escape_string("\"") == "\\\"");
|
||||
CHECK(json::escape_string("\\") == "\\\\");
|
||||
CHECK(json::escape_string("\b") == "\\b");
|
||||
CHECK(json::escape_string("\f") == "\\f");
|
||||
CHECK(json::escape_string("\n") == "\\n");
|
||||
CHECK(json::escape_string("\r") == "\\r");
|
||||
CHECK(json::escape_string("\t") == "\\t");
|
||||
|
||||
CHECK(json::escape_string("\x01") == "\\u0001");
|
||||
CHECK(json::escape_string("\x02") == "\\u0002");
|
||||
CHECK(json::escape_string("\x03") == "\\u0003");
|
||||
CHECK(json::escape_string("\x04") == "\\u0004");
|
||||
CHECK(json::escape_string("\x05") == "\\u0005");
|
||||
CHECK(json::escape_string("\x06") == "\\u0006");
|
||||
CHECK(json::escape_string("\x07") == "\\u0007");
|
||||
CHECK(json::escape_string("\x08") == "\\b");
|
||||
CHECK(json::escape_string("\x09") == "\\t");
|
||||
CHECK(json::escape_string("\x0a") == "\\n");
|
||||
CHECK(json::escape_string("\x0b") == "\\u000b");
|
||||
CHECK(json::escape_string("\x0c") == "\\f");
|
||||
CHECK(json::escape_string("\x0d") == "\\r");
|
||||
CHECK(json::escape_string("\x0e") == "\\u000e");
|
||||
CHECK(json::escape_string("\x0f") == "\\u000f");
|
||||
CHECK(json::escape_string("\x10") == "\\u0010");
|
||||
CHECK(json::escape_string("\x11") == "\\u0011");
|
||||
CHECK(json::escape_string("\x12") == "\\u0012");
|
||||
CHECK(json::escape_string("\x13") == "\\u0013");
|
||||
CHECK(json::escape_string("\x14") == "\\u0014");
|
||||
CHECK(json::escape_string("\x15") == "\\u0015");
|
||||
CHECK(json::escape_string("\x16") == "\\u0016");
|
||||
CHECK(json::escape_string("\x17") == "\\u0017");
|
||||
CHECK(json::escape_string("\x18") == "\\u0018");
|
||||
CHECK(json::escape_string("\x19") == "\\u0019");
|
||||
CHECK(json::escape_string("\x1a") == "\\u001a");
|
||||
CHECK(json::escape_string("\x1b") == "\\u001b");
|
||||
CHECK(json::escape_string("\x1c") == "\\u001c");
|
||||
CHECK(json::escape_string("\x1d") == "\\u001d");
|
||||
CHECK(json::escape_string("\x1e") == "\\u001e");
|
||||
CHECK(json::escape_string("\x1f") == "\\u001f");
|
||||
}
|
||||
}
|
||||
1014
test/src/unit-conversions.cpp
Normal file
255
test/src/unit-deserialization.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <valarray>
|
||||
|
||||
TEST_CASE("deserialization")
|
||||
{
|
||||
SECTION("successful deserialization")
|
||||
{
|
||||
SECTION("stream")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
|
||||
json j = json::parse(ss);
|
||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
|
||||
SECTION("string literal")
|
||||
{
|
||||
auto s = "[\"foo\",1,2,3,false,{\"one\":1}]";
|
||||
json j = json::parse(s);
|
||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
|
||||
SECTION("string_t")
|
||||
{
|
||||
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}]";
|
||||
json j = json::parse(s);
|
||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
|
||||
SECTION("operator<<")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
|
||||
json j;
|
||||
j << ss;
|
||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
|
||||
SECTION("operator>>")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
|
||||
json j;
|
||||
ss >> j;
|
||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
|
||||
SECTION("user-defined string literal")
|
||||
{
|
||||
CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("unsuccessful deserialization")
|
||||
{
|
||||
SECTION("stream")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||
CHECK_THROWS_AS(json::parse(ss), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parse(ss), "parse error - unexpected end of input");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||
CHECK_THROWS_AS(json::parse(s), std::invalid_argument);
|
||||
CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'");
|
||||
}
|
||||
|
||||
SECTION("operator<<")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||
json j;
|
||||
CHECK_THROWS_AS(j << ss, std::invalid_argument);
|
||||
CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
|
||||
}
|
||||
|
||||
SECTION("operator>>")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||
json j;
|
||||
CHECK_THROWS_AS(ss >> j, std::invalid_argument);
|
||||
CHECK_THROWS_WITH(ss >> j, "parse error - unexpected end of input");
|
||||
}
|
||||
|
||||
SECTION("user-defined string literal")
|
||||
{
|
||||
CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument);
|
||||
CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
|
||||
"parse error - unexpected end of input; expected ']'");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("contiguous containers")
|
||||
{
|
||||
SECTION("directly")
|
||||
{
|
||||
SECTION("from std::vector")
|
||||
{
|
||||
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(v) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::array")
|
||||
{
|
||||
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
|
||||
CHECK(json::parse(v) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from array")
|
||||
{
|
||||
uint8_t v[] = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(v) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from chars")
|
||||
{
|
||||
uint8_t* v = new uint8_t[5];
|
||||
v[0] = 't';
|
||||
v[1] = 'r';
|
||||
v[2] = 'u';
|
||||
v[3] = 'e';
|
||||
v[4] = '\0';
|
||||
CHECK(json::parse(v) == json(true));
|
||||
delete[] v;
|
||||
}
|
||||
|
||||
SECTION("from std::string")
|
||||
{
|
||||
std::string v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(v) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::initializer_list")
|
||||
{
|
||||
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(v) == json(true));
|
||||
}
|
||||
|
||||
SECTION("empty container")
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
CHECK_THROWS_AS(json::parse(v), std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("via iterator range")
|
||||
{
|
||||
SECTION("from std::vector")
|
||||
{
|
||||
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::array")
|
||||
{
|
||||
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from array")
|
||||
{
|
||||
uint8_t v[] = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::string")
|
||||
{
|
||||
std::string v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::initializer_list")
|
||||
{
|
||||
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("from std::valarray")
|
||||
{
|
||||
std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
|
||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||
}
|
||||
|
||||
SECTION("with empty range")
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
// these cases are required for 100% line coverage
|
||||
SECTION("error cases")
|
||||
{
|
||||
SECTION("case 1")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||
}
|
||||
|
||||
SECTION("case 2")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||
}
|
||||
|
||||
SECTION("case 3")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||
}
|
||||
|
||||
SECTION("case 4")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
947
test/src/unit-element_access1.cpp
Normal file
@@ -0,0 +1,947 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("element access 1")
|
||||
{
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
const json j_const = j;
|
||||
|
||||
SECTION("access specified element with bounds checking")
|
||||
{
|
||||
SECTION("access within bounds")
|
||||
{
|
||||
CHECK(j.at(0) == json(1));
|
||||
CHECK(j.at(1) == json(1u));
|
||||
CHECK(j.at(2) == json(true));
|
||||
CHECK(j.at(3) == json(nullptr));
|
||||
CHECK(j.at(4) == json("string"));
|
||||
CHECK(j.at(5) == json(42.23));
|
||||
CHECK(j.at(6) == json(json::object()));
|
||||
CHECK(j.at(7) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.at(0) == json(1));
|
||||
CHECK(j_const.at(1) == json(1u));
|
||||
CHECK(j_const.at(2) == json(true));
|
||||
CHECK(j_const.at(3) == json(nullptr));
|
||||
CHECK(j_const.at(4) == json("string"));
|
||||
CHECK(j_const.at(5) == json(42.23));
|
||||
CHECK(j_const.at(6) == json(json::object()));
|
||||
CHECK(j_const.at(7) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access outside bounds")
|
||||
{
|
||||
CHECK_THROWS_AS(j.at(8), std::out_of_range);
|
||||
CHECK_THROWS_AS(j_const.at(8), std::out_of_range);
|
||||
|
||||
CHECK_THROWS_WITH(j.at(8), "array index 8 is out of range");
|
||||
CHECK_THROWS_WITH(j_const.at(8), "array index 8 is out of range");
|
||||
}
|
||||
|
||||
SECTION("access on non-array type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonarray(json::value_t::null);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with null");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonarray(json::value_t::boolean);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with boolean");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonarray(json::value_t::string);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with string");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with string");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonarray(json::value_t::object);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with object");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with object");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_integer);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_unsigned);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_float);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("front and back")
|
||||
{
|
||||
CHECK(j.front() == json(1));
|
||||
CHECK(j_const.front() == json(1));
|
||||
CHECK(j.back() == json({1, 2, 3}));
|
||||
CHECK(j_const.back() == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access specified element")
|
||||
{
|
||||
SECTION("access within bounds")
|
||||
{
|
||||
CHECK(j[0] == json(1));
|
||||
CHECK(j[1] == json(1u));
|
||||
CHECK(j[2] == json(true));
|
||||
CHECK(j[3] == json(nullptr));
|
||||
CHECK(j[4] == json("string"));
|
||||
CHECK(j[5] == json(42.23));
|
||||
CHECK(j[6] == json(json::object()));
|
||||
CHECK(j[7] == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const[0] == json(1));
|
||||
CHECK(j_const[1] == json(1u));
|
||||
CHECK(j_const[2] == json(true));
|
||||
CHECK(j_const[3] == json(nullptr));
|
||||
CHECK(j_const[4] == json("string"));
|
||||
CHECK(j_const[5] == json(42.23));
|
||||
CHECK(j_const[6] == json(json::object()));
|
||||
CHECK(j_const[7] == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access on non-array type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
SECTION("standard tests")
|
||||
{
|
||||
json j_nonarray(json::value_t::null);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_NOTHROW(j_nonarray[0]);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with null");
|
||||
}
|
||||
|
||||
SECTION("implicit transformation to properly filled array")
|
||||
{
|
||||
json j_nonarray;
|
||||
j_nonarray[3] = 42;
|
||||
CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonarray(json::value_t::boolean);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with boolean");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonarray(json::value_t::string);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with string");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with string");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonarray(json::value_t::object);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with object");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with object");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_integer);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_unsigned);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_float);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remove specified element")
|
||||
{
|
||||
SECTION("remove element by index")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(0);
|
||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(1);
|
||||
CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(2);
|
||||
CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(3);
|
||||
CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(4);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(5);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(6);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
jarray.erase(7);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
CHECK_THROWS_AS(jarray.erase(8), std::out_of_range);
|
||||
CHECK_THROWS_WITH(jarray.erase(8), "array index 8 is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remove element by iterator")
|
||||
{
|
||||
SECTION("erase(begin())")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::iterator it2 = jarray.erase(jarray.begin());
|
||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(1u));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::const_iterator it2 = jarray.erase(jarray.cbegin());
|
||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(1u));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase(begin(), end())")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
|
||||
CHECK(jarray == json::array());
|
||||
CHECK(it2 == jarray.end());
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
|
||||
CHECK(jarray == json::array());
|
||||
CHECK(it2 == jarray.cend());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase(begin(), begin())")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::iterator it2 = jarray.erase(jarray.begin(), jarray.begin());
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(1));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase at offset")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::iterator it = jarray.begin() + 4;
|
||||
json::iterator it2 = jarray.erase(it);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(42.23));
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::const_iterator it = jarray.cbegin() + 4;
|
||||
json::const_iterator it2 = jarray.erase(it);
|
||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json(42.23));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase subrange")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::iterator it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
|
||||
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json::object());
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json::const_iterator it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
|
||||
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
|
||||
CHECK(*it2 == json::object());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("different arrays")
|
||||
{
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json jarray2 = {"foo", "bar"};
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.begin()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray.begin(), jarray2.end()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray.end()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray2.end()),
|
||||
"iterators do not fit current value");
|
||||
}
|
||||
{
|
||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
||||
json jarray2 = {"foo", "bar"};
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), std::domain_error);
|
||||
CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray.cbegin(), jarray2.cend()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray.cend()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray2.cend()),
|
||||
"iterators do not fit current value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remove element by index in non-array type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with string");
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonobject(json::value_t::object);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with object");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("other values")
|
||||
{
|
||||
SECTION("front and back")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
json j;
|
||||
CHECK_THROWS_AS(j.front(), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.back(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.front(), "cannot get value");
|
||||
CHECK_THROWS_WITH(j.back(), "cannot get value");
|
||||
}
|
||||
{
|
||||
const json j{};
|
||||
CHECK_THROWS_AS(j.front(), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.back(), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.front(), "cannot get value");
|
||||
CHECK_THROWS_WITH(j.back(), "cannot get value");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
{
|
||||
json j = "foo";
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
{
|
||||
const json j = "bar";
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (boolean)")
|
||||
{
|
||||
{
|
||||
json j = false;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
{
|
||||
const json j = true;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
{
|
||||
json j = 17;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
{
|
||||
const json j = 17;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
{
|
||||
json j = 17u;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
{
|
||||
const json j = 17u;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (floating point)")
|
||||
{
|
||||
{
|
||||
json j = 23.42;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
{
|
||||
const json j = 23.42;
|
||||
CHECK(j.front() == j);
|
||||
CHECK(j.back() == j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase with one valid iterator")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
json j;
|
||||
CHECK_THROWS_AS(j.erase(j.begin()), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null");
|
||||
}
|
||||
{
|
||||
json j;
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin()), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
{
|
||||
json j = "foo";
|
||||
json::iterator it = j.erase(j.begin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = "bar";
|
||||
json::const_iterator it = j.erase(j.cbegin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (boolean)")
|
||||
{
|
||||
{
|
||||
json j = false;
|
||||
json::iterator it = j.erase(j.begin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = true;
|
||||
json::const_iterator it = j.erase(j.cbegin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
{
|
||||
json j = 17;
|
||||
json::iterator it = j.erase(j.begin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 17;
|
||||
json::const_iterator it = j.erase(j.cbegin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
{
|
||||
json j = 17u;
|
||||
json::iterator it = j.erase(j.begin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 17u;
|
||||
json::const_iterator it = j.erase(j.cbegin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (floating point)")
|
||||
{
|
||||
{
|
||||
json j = 23.42;
|
||||
json::iterator it = j.erase(j.begin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 23.42;
|
||||
json::const_iterator it = j.erase(j.cbegin());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase with one invalid iterator")
|
||||
{
|
||||
SECTION("string")
|
||||
{
|
||||
{
|
||||
json j = "foo";
|
||||
CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
|
||||
}
|
||||
{
|
||||
json j = "bar";
|
||||
CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (boolean)")
|
||||
{
|
||||
{
|
||||
json j = false;
|
||||
CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
|
||||
}
|
||||
{
|
||||
json j = true;
|
||||
CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
{
|
||||
json j = 17;
|
||||
CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
|
||||
}
|
||||
{
|
||||
json j = 17;
|
||||
CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
{
|
||||
json j = 17u;
|
||||
CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
|
||||
}
|
||||
{
|
||||
json j = 17u;
|
||||
CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (floating point)")
|
||||
{
|
||||
{
|
||||
json j = 23.42;
|
||||
CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
|
||||
}
|
||||
{
|
||||
json j = 23.42;
|
||||
CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase with two valid iterators")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
json j;
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.end()), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "cannot use erase() with null");
|
||||
}
|
||||
{
|
||||
json j;
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "cannot use erase() with null");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
{
|
||||
json j = "foo";
|
||||
json::iterator it = j.erase(j.begin(), j.end());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = "bar";
|
||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (boolean)")
|
||||
{
|
||||
{
|
||||
json j = false;
|
||||
json::iterator it = j.erase(j.begin(), j.end());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = true;
|
||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
{
|
||||
json j = 17;
|
||||
json::iterator it = j.erase(j.begin(), j.end());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 17;
|
||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
{
|
||||
json j = 17u;
|
||||
json::iterator it = j.erase(j.begin(), j.end());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 17u;
|
||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (floating point)")
|
||||
{
|
||||
{
|
||||
json j = 23.42;
|
||||
json::iterator it = j.erase(j.begin(), j.end());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
{
|
||||
json j = 23.42;
|
||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
CHECK(it == j.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase with two invalid iterators")
|
||||
{
|
||||
SECTION("string")
|
||||
{
|
||||
{
|
||||
json j = "foo";
|
||||
CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
|
||||
}
|
||||
{
|
||||
json j = "bar";
|
||||
CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (boolean)")
|
||||
{
|
||||
{
|
||||
json j = false;
|
||||
CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
|
||||
}
|
||||
{
|
||||
json j = true;
|
||||
CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
{
|
||||
json j = 17;
|
||||
CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
|
||||
}
|
||||
{
|
||||
json j = 17;
|
||||
CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
{
|
||||
json j = 17u;
|
||||
CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
|
||||
}
|
||||
{
|
||||
json j = 17u;
|
||||
CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (floating point)")
|
||||
{
|
||||
{
|
||||
json j = 23.42;
|
||||
CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
|
||||
}
|
||||
{
|
||||
json j = 23.42;
|
||||
CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
|
||||
CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
|
||||
CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
959
test/src/unit-element_access2.cpp
Normal file
@@ -0,0 +1,959 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("element access 2")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", json::object()}, {"array", {1, 2, 3}}};
|
||||
const json j_const = j;
|
||||
|
||||
SECTION("access specified element with bounds checking")
|
||||
{
|
||||
SECTION("access within bounds")
|
||||
{
|
||||
CHECK(j.at("integer") == json(1));
|
||||
CHECK(j.at("unsigned") == json(1u));
|
||||
CHECK(j.at("boolean") == json(true));
|
||||
CHECK(j.at("null") == json(nullptr));
|
||||
CHECK(j.at("string") == json("hello world"));
|
||||
CHECK(j.at("floating") == json(42.23));
|
||||
CHECK(j.at("object") == json(json::object()));
|
||||
CHECK(j.at("array") == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.at("integer") == json(1));
|
||||
CHECK(j_const.at("unsigned") == json(1u));
|
||||
CHECK(j_const.at("boolean") == json(true));
|
||||
CHECK(j_const.at("null") == json(nullptr));
|
||||
CHECK(j_const.at("string") == json("hello world"));
|
||||
CHECK(j_const.at("floating") == json(42.23));
|
||||
CHECK(j_const.at("object") == json(json::object()));
|
||||
CHECK(j_const.at("array") == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access outside bounds")
|
||||
{
|
||||
CHECK_THROWS_AS(j.at("foo"), std::out_of_range);
|
||||
CHECK_THROWS_AS(j_const.at("foo"), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at("foo"), "key 'foo' not found");
|
||||
CHECK_THROWS_WITH(j_const.at("foo"), "key 'foo' not found");
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with null");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with boolean");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with string");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with array");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with array");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("access specified element with default value")
|
||||
{
|
||||
SECTION("given a key")
|
||||
{
|
||||
SECTION("access existing value")
|
||||
{
|
||||
CHECK(j.value("integer", 2) == 1);
|
||||
CHECK(j.value("integer", 1.0) == Approx(1));
|
||||
CHECK(j.value("unsigned", 2) == 1u);
|
||||
CHECK(j.value("unsigned", 1.0) == Approx(1u));
|
||||
CHECK(j.value("null", json(1)) == json());
|
||||
CHECK(j.value("boolean", false) == true);
|
||||
CHECK(j.value("string", "bar") == "hello world");
|
||||
CHECK(j.value("string", std::string("bar")) == "hello world");
|
||||
CHECK(j.value("floating", 12.34) == Approx(42.23));
|
||||
CHECK(j.value("floating", 12) == 42);
|
||||
CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j.value("array", json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.value("integer", 2) == 1);
|
||||
CHECK(j_const.value("integer", 1.0) == Approx(1));
|
||||
CHECK(j_const.value("unsigned", 2) == 1u);
|
||||
CHECK(j_const.value("unsigned", 1.0) == Approx(1u));
|
||||
CHECK(j_const.value("boolean", false) == true);
|
||||
CHECK(j_const.value("string", "bar") == "hello world");
|
||||
CHECK(j_const.value("string", std::string("bar")) == "hello world");
|
||||
CHECK(j_const.value("floating", 12.34) == Approx(42.23));
|
||||
CHECK(j_const.value("floating", 12) == 42);
|
||||
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access non-existing value")
|
||||
{
|
||||
CHECK(j.value("_", 2) == 2);
|
||||
CHECK(j.value("_", 2u) == 2u);
|
||||
CHECK(j.value("_", false) == false);
|
||||
CHECK(j.value("_", "bar") == "bar");
|
||||
CHECK(j.value("_", 12.34) == Approx(12.34));
|
||||
CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j.value("_", json({10, 100})) == json({10, 100}));
|
||||
|
||||
CHECK(j_const.value("_", 2) == 2);
|
||||
CHECK(j_const.value("_", 2u) == 2u);
|
||||
CHECK(j_const.value("_", false) == false);
|
||||
CHECK(j_const.value("_", "bar") == "bar");
|
||||
CHECK(j_const.value("_", 12.34) == Approx(12.34));
|
||||
CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j_const.value("_", json({10, 100})) == json({10, 100}));
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with null");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with boolean");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with string");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with array");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with array");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("given a JSON pointer")
|
||||
{
|
||||
SECTION("access existing value")
|
||||
{
|
||||
CHECK(j.value("/integer"_json_pointer, 2) == 1);
|
||||
CHECK(j.value("/integer"_json_pointer, 1.0) == Approx(1));
|
||||
CHECK(j.value("/unsigned"_json_pointer, 2) == 1u);
|
||||
CHECK(j.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
|
||||
CHECK(j.value("/null"_json_pointer, json(1)) == json());
|
||||
CHECK(j.value("/boolean"_json_pointer, false) == true);
|
||||
CHECK(j.value("/string"_json_pointer, "bar") == "hello world");
|
||||
CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||
CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||
CHECK(j.value("/floating"_json_pointer, 12) == 42);
|
||||
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.value("/integer"_json_pointer, 2) == 1);
|
||||
CHECK(j_const.value("/integer"_json_pointer, 1.0) == Approx(1));
|
||||
CHECK(j_const.value("/unsigned"_json_pointer, 2) == 1u);
|
||||
CHECK(j_const.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
|
||||
CHECK(j_const.value("/boolean"_json_pointer, false) == true);
|
||||
CHECK(j_const.value("/string"_json_pointer, "bar") == "hello world");
|
||||
CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||
CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||
CHECK(j_const.value("/floating"_json_pointer, 12) == 42);
|
||||
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j_const.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
SECTION("access non-existing value")
|
||||
{
|
||||
CHECK(j.value("/not/existing"_json_pointer, 2) == 2);
|
||||
CHECK(j.value("/not/existing"_json_pointer, 2u) == 2u);
|
||||
CHECK(j.value("/not/existing"_json_pointer, false) == false);
|
||||
CHECK(j.value("/not/existing"_json_pointer, "bar") == "bar");
|
||||
CHECK(j.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
|
||||
CHECK(j.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100}));
|
||||
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, 2) == 2);
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, 2u) == 2u);
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, false) == false);
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, "bar") == "bar");
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||
CHECK(j_const.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100}));
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with null");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with boolean");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||
"cannot use value() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with string");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||
"cannot use value() with string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with array");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with array");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||
"cannot use value() with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||
"cannot use value() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||
"cannot use value() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("front and back")
|
||||
{
|
||||
// "array" is the smallest key
|
||||
CHECK(j.front() == json({1, 2, 3}));
|
||||
CHECK(j_const.front() == json({1, 2, 3}));
|
||||
// "unsigned" is the largest key
|
||||
CHECK(j.back() == json(1u));
|
||||
CHECK(j_const.back() == json(1u));
|
||||
}
|
||||
|
||||
SECTION("access specified element")
|
||||
{
|
||||
SECTION("access within bounds")
|
||||
{
|
||||
CHECK(j["integer"] == json(1));
|
||||
CHECK(j[json::object_t::key_type("integer")] == j["integer"]);
|
||||
|
||||
CHECK(j["unsigned"] == json(1u));
|
||||
CHECK(j[json::object_t::key_type("unsigned")] == j["unsigned"]);
|
||||
|
||||
CHECK(j["boolean"] == json(true));
|
||||
CHECK(j[json::object_t::key_type("boolean")] == j["boolean"]);
|
||||
|
||||
CHECK(j["null"] == json(nullptr));
|
||||
CHECK(j[json::object_t::key_type("null")] == j["null"]);
|
||||
|
||||
CHECK(j["string"] == json("hello world"));
|
||||
CHECK(j[json::object_t::key_type("string")] == j["string"]);
|
||||
|
||||
CHECK(j["floating"] == json(42.23));
|
||||
CHECK(j[json::object_t::key_type("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j["object"] == json(json::object()));
|
||||
CHECK(j[json::object_t::key_type("object")] == j["object"]);
|
||||
|
||||
CHECK(j["array"] == json({1, 2, 3}));
|
||||
CHECK(j[json::object_t::key_type("array")] == j["array"]);
|
||||
|
||||
CHECK(j_const["integer"] == json(1));
|
||||
CHECK(j_const[json::object_t::key_type("integer")] == j["integer"]);
|
||||
|
||||
CHECK(j_const["boolean"] == json(true));
|
||||
CHECK(j_const[json::object_t::key_type("boolean")] == j["boolean"]);
|
||||
|
||||
CHECK(j_const["null"] == json(nullptr));
|
||||
CHECK(j_const[json::object_t::key_type("null")] == j["null"]);
|
||||
|
||||
CHECK(j_const["string"] == json("hello world"));
|
||||
CHECK(j_const[json::object_t::key_type("string")] == j["string"]);
|
||||
|
||||
CHECK(j_const["floating"] == json(42.23));
|
||||
CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j_const["object"] == json(json::object()));
|
||||
CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
|
||||
|
||||
CHECK(j_const["array"] == json({1, 2, 3}));
|
||||
CHECK(j_const[json::object_t::key_type("array")] == j["array"]);
|
||||
}
|
||||
|
||||
SECTION("access on non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
json j_nonobject2(json::value_t::null);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_NOTHROW(j_nonobject["foo"]);
|
||||
CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with null");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with boolean");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with boolean");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with boolean");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with string");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with string");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with string");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with array");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], "cannot use operator[] with array");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with array");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with array");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_const_nonobject(j_nonobject);
|
||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
|
||||
CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
|
||||
"cannot use operator[] with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remove specified element")
|
||||
{
|
||||
SECTION("remove element by key")
|
||||
{
|
||||
CHECK(j.find("integer") != j.end());
|
||||
CHECK(j.erase("integer") == 1);
|
||||
CHECK(j.find("integer") == j.end());
|
||||
CHECK(j.erase("integer") == 0);
|
||||
|
||||
CHECK(j.find("unsigned") != j.end());
|
||||
CHECK(j.erase("unsigned") == 1);
|
||||
CHECK(j.find("unsigned") == j.end());
|
||||
CHECK(j.erase("unsigned") == 0);
|
||||
|
||||
CHECK(j.find("boolean") != j.end());
|
||||
CHECK(j.erase("boolean") == 1);
|
||||
CHECK(j.find("boolean") == j.end());
|
||||
CHECK(j.erase("boolean") == 0);
|
||||
|
||||
CHECK(j.find("null") != j.end());
|
||||
CHECK(j.erase("null") == 1);
|
||||
CHECK(j.find("null") == j.end());
|
||||
CHECK(j.erase("null") == 0);
|
||||
|
||||
CHECK(j.find("string") != j.end());
|
||||
CHECK(j.erase("string") == 1);
|
||||
CHECK(j.find("string") == j.end());
|
||||
CHECK(j.erase("string") == 0);
|
||||
|
||||
CHECK(j.find("floating") != j.end());
|
||||
CHECK(j.erase("floating") == 1);
|
||||
CHECK(j.find("floating") == j.end());
|
||||
CHECK(j.erase("floating") == 0);
|
||||
|
||||
CHECK(j.find("object") != j.end());
|
||||
CHECK(j.erase("object") == 1);
|
||||
CHECK(j.find("object") == j.end());
|
||||
CHECK(j.erase("object") == 0);
|
||||
|
||||
CHECK(j.find("array") != j.end());
|
||||
CHECK(j.erase("array") == 1);
|
||||
CHECK(j.find("array") == j.end());
|
||||
CHECK(j.erase("array") == 0);
|
||||
}
|
||||
|
||||
SECTION("remove element by iterator")
|
||||
{
|
||||
SECTION("erase(begin())")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::iterator it2 = jobject.erase(jobject.begin());
|
||||
CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
|
||||
CHECK(*it2 == json(1));
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::const_iterator it2 = jobject.erase(jobject.cbegin());
|
||||
CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
|
||||
CHECK(*it2 == json(1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase(begin(), end())")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
|
||||
CHECK(jobject == json::object());
|
||||
CHECK(it2 == jobject.end());
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
|
||||
CHECK(jobject == json::object());
|
||||
CHECK(it2 == jobject.cend());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase(begin(), begin())")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
|
||||
CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
|
||||
CHECK(*it2 == json("a"));
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
|
||||
CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
|
||||
CHECK(*it2 == json("a"));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase at offset")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::iterator it = jobject.find("b");
|
||||
json::iterator it2 = jobject.erase(it);
|
||||
CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
|
||||
CHECK(*it2 == json(17));
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
json::const_iterator it = jobject.find("b");
|
||||
json::const_iterator it2 = jobject.erase(it);
|
||||
CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
|
||||
CHECK(*it2 == json(17));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("erase subrange")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
||||
json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
|
||||
CHECK(jobject == json({{"a", "a"}, {"e", true}}));
|
||||
CHECK(*it2 == json(true));
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
||||
json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
|
||||
CHECK(jobject == json({{"a", "a"}, {"e", true}}));
|
||||
CHECK(*it2 == json(true));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("different objects")
|
||||
{
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
||||
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.begin()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), std::domain_error);
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject.begin(), jobject2.end()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject.end()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject2.end()),
|
||||
"iterators do not fit current value");
|
||||
}
|
||||
{
|
||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
||||
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error);
|
||||
CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::domain_error);
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject.cbegin(), jobject2.cend()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject.cend()),
|
||||
"iterators do not fit current value");
|
||||
CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject2.cend()),
|
||||
"iterators do not fit current value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("remove element by key in non-object type")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with null");
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with boolean");
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with string");
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with array");
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number");
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("find an element in an object")
|
||||
{
|
||||
SECTION("existing element")
|
||||
{
|
||||
for (auto key :
|
||||
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
|
||||
})
|
||||
{
|
||||
CHECK(j.find(key) != j.end());
|
||||
CHECK(*j.find(key) == j.at(key));
|
||||
CHECK(j_const.find(key) != j_const.end());
|
||||
CHECK(*j_const.find(key) == j_const.at(key));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("nonexisting element")
|
||||
{
|
||||
CHECK(j.find("foo") == j.end());
|
||||
CHECK(j_const.find("foo") == j_const.end());
|
||||
}
|
||||
|
||||
SECTION("all types")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonarray(json::value_t::null);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonarray(json::value_t::string);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonarray(json::value_t::object);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonarray(json::value_t::array);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonarray(json::value_t::boolean);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_integer);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_unsigned);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonarray(json::value_t::number_float);
|
||||
const json j_nonarray_const(j_nonarray);
|
||||
CHECK(j_nonarray.find("foo") == j_nonarray.end());
|
||||
CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("count keys in an object")
|
||||
{
|
||||
SECTION("existing element")
|
||||
{
|
||||
for (auto key :
|
||||
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
|
||||
})
|
||||
{
|
||||
CHECK(j.count(key) == 1);
|
||||
CHECK(j_const.count(key) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("nonexisting element")
|
||||
{
|
||||
CHECK(j.count("foo") == 0);
|
||||
CHECK(j_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("all types")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j_nonobject(json::value_t::null);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j_nonobject(json::value_t::string);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j_nonobject(json::value_t::object);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j_nonobject(json::value_t::array);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j_nonobject(json::value_t::boolean);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_integer);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_unsigned);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j_nonobject(json::value_t::number_float);
|
||||
const json j_nonobject_const(j_nonobject);
|
||||
CHECK(j_nonobject.count("foo") == 0);
|
||||
CHECK(j_nonobject_const.count("foo") == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
373
test/src/unit-inspection.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("object inspection")
|
||||
{
|
||||
SECTION("convenience type checker")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
json j {{"foo", 1}, {"bar", false}};
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(not j.is_primitive());
|
||||
CHECK(j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j {"foo", 1, 1u, 42.23, false};
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(not j.is_primitive());
|
||||
CHECK(j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j(nullptr);
|
||||
CHECK(j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j(true);
|
||||
CHECK(not j.is_null());
|
||||
CHECK(j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j("Hello world");
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j(42);
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(j.is_number());
|
||||
CHECK(j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j(42u);
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(j.is_number());
|
||||
CHECK(j.is_number_integer());
|
||||
CHECK(j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j(42.23);
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(not j.is_discarded());
|
||||
CHECK(j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
|
||||
SECTION("discarded")
|
||||
{
|
||||
json j(json::value_t::discarded);
|
||||
CHECK(not j.is_null());
|
||||
CHECK(not j.is_boolean());
|
||||
CHECK(not j.is_number());
|
||||
CHECK(not j.is_number_integer());
|
||||
CHECK(not j.is_number_unsigned());
|
||||
CHECK(not j.is_number_float());
|
||||
CHECK(not j.is_object());
|
||||
CHECK(not j.is_array());
|
||||
CHECK(not j.is_string());
|
||||
CHECK(j.is_discarded());
|
||||
CHECK(not j.is_primitive());
|
||||
CHECK(not j.is_structured());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("serialization")
|
||||
{
|
||||
json j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
|
||||
|
||||
SECTION("no indent / indent=-1")
|
||||
{
|
||||
CHECK(j.dump() ==
|
||||
"{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
|
||||
|
||||
CHECK(j.dump() == j.dump(-1));
|
||||
}
|
||||
|
||||
SECTION("indent=0")
|
||||
{
|
||||
CHECK(j.dump(0) ==
|
||||
"{\n\"array\": [\n1,\n2,\n3,\n4\n],\n\"boolean\": false,\n\"null\": null,\n\"number\": 42,\n\"object\": {},\n\"string\": \"Hello world\"\n}");
|
||||
}
|
||||
|
||||
SECTION("indent=4")
|
||||
{
|
||||
CHECK(j.dump(4) ==
|
||||
"{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
|
||||
}
|
||||
|
||||
SECTION("dump and floating-point numbers")
|
||||
{
|
||||
auto s = json(42.23).dump();
|
||||
CHECK(s.find("42.23") != std::string::npos);
|
||||
}
|
||||
|
||||
SECTION("dump and small floating-point numbers")
|
||||
{
|
||||
auto s = json(1.23456e-78).dump();
|
||||
CHECK(s.find("1.23456e-78") != std::string::npos);
|
||||
}
|
||||
|
||||
SECTION("dump and non-ASCII characters")
|
||||
{
|
||||
CHECK(json("ä").dump() == "\"ä\"");
|
||||
CHECK(json("Ö").dump() == "\"Ö\"");
|
||||
CHECK(json("❤️").dump() == "\"❤️\"");
|
||||
}
|
||||
|
||||
SECTION("serialization of discarded element")
|
||||
{
|
||||
json j_discarded(json::value_t::discarded);
|
||||
CHECK(j_discarded.dump() == "<discarded>");
|
||||
}
|
||||
|
||||
SECTION("check that precision is reset after serialization")
|
||||
{
|
||||
// create stringstream and set precision
|
||||
std::stringstream ss;
|
||||
ss.precision(3);
|
||||
ss << 3.141592653589793 << std::fixed;
|
||||
CHECK(ss.str() == "3.14");
|
||||
|
||||
// reset stringstream
|
||||
ss.str(std::string());
|
||||
|
||||
// use stringstream for JSON serialization
|
||||
json j_number = 3.141592653589793;
|
||||
ss << j_number;
|
||||
|
||||
// check that precision has been overridden during serialization
|
||||
CHECK(ss.str() == "3.141592653589793");
|
||||
|
||||
// check that precision has been restored
|
||||
CHECK(ss.precision() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("return the type of the object (explicit)")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
CHECK(j.type() == json::value_t::null);
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j = {{"foo", "bar"}};
|
||||
CHECK(j.type() == json::value_t::object);
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3, 4};
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
CHECK(j.type() == json::value_t::boolean);
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "Hello world";
|
||||
CHECK(j.type() == json::value_t::string);
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
CHECK(j.type() == json::value_t::number_integer);
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
CHECK(j.type() == json::value_t::number_unsigned);
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j = 42.23;
|
||||
CHECK(j.type() == json::value_t::number_float);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("return the type of the object (implicit)")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j = {{"foo", "bar"}};
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3, 4};
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "Hello world";
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
|
||||
SECTION("number (floating-point)")
|
||||
{
|
||||
json j = 42.23;
|
||||
json::value_t t = j;
|
||||
CHECK(t == j.type());
|
||||
}
|
||||
}
|
||||
}
|
||||
729
test/src/unit-iterator_wrapper.cpp
Normal file
@@ -0,0 +1,729 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("iterator_wrapper")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
|
||||
// change the value
|
||||
i.value() = json(11);
|
||||
CHECK(i.value() == json(11));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
|
||||
// change the value
|
||||
i.value() = json(22);
|
||||
CHECK(i.value() == json(22));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
|
||||
// check if values where changed
|
||||
CHECK(j == json({{"A", 11}, {"B", 22}}));
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("const object")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
const json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
const json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
const json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
const json j = {{"A", 1}, {"B", 2}};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "A");
|
||||
CHECK(i.value() == json(1));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "B");
|
||||
CHECK(i.value() == json(2));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
|
||||
// change the value
|
||||
i.value() = "AA";
|
||||
CHECK(i.value() == "AA");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
|
||||
// change the value
|
||||
i.value() = "BB";
|
||||
CHECK(i.value() == "BB");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
|
||||
// check if values where changed
|
||||
CHECK(j == json({"AA", "BB"}));
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("const array")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
const json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
const json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
const json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
const json j = {"A", "B"};
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
switch (counter++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CHECK(i.key() == "0");
|
||||
CHECK(i.value() == "A");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
CHECK(i.key() == "1");
|
||||
CHECK(i.value() == "B");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("primitive")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
|
||||
// change value
|
||||
i.value() = json(2);
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
|
||||
// check if value has changed
|
||||
CHECK(j == json(2));
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("const primitive")
|
||||
{
|
||||
SECTION("value")
|
||||
{
|
||||
const json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
|
||||
SECTION("reference")
|
||||
{
|
||||
const json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
|
||||
SECTION("const value")
|
||||
{
|
||||
const json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (const auto i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
const json j = 1;
|
||||
int counter = 1;
|
||||
|
||||
for (const auto& i : json::iterator_wrapper(j))
|
||||
{
|
||||
++counter;
|
||||
CHECK(i.key() == "");
|
||||
CHECK(i.value() == json(1));
|
||||
}
|
||||
|
||||
CHECK(counter == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
1514
test/src/unit-iterators1.cpp
Normal file
873
test/src/unit-iterators2.cpp
Normal file
@@ -0,0 +1,873 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("iterators 2")
|
||||
{
|
||||
SECTION("iterator comparisons")
|
||||
{
|
||||
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
|
||||
|
||||
for (json& j : j_values)
|
||||
{
|
||||
auto it1 = j.begin();
|
||||
auto it2 = j.begin();
|
||||
auto it3 = j.begin();
|
||||
++it2;
|
||||
++it3;
|
||||
++it3;
|
||||
auto it1_c = j.cbegin();
|
||||
auto it2_c = j.cbegin();
|
||||
auto it3_c = j.cbegin();
|
||||
++it2_c;
|
||||
++it3_c;
|
||||
++it3_c;
|
||||
|
||||
// comparison: equal
|
||||
{
|
||||
CHECK(it1 == it1);
|
||||
CHECK(not (it1 == it2));
|
||||
CHECK(not (it1 == it3));
|
||||
CHECK(not (it2 == it3));
|
||||
CHECK(it1_c == it1_c);
|
||||
CHECK(not (it1_c == it2_c));
|
||||
CHECK(not (it1_c == it3_c));
|
||||
CHECK(not (it2_c == it3_c));
|
||||
}
|
||||
|
||||
// comparison: not equal
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 != it1) == not(it1 == it1) );
|
||||
CHECK( (it1 != it2) == not(it1 == it2) );
|
||||
CHECK( (it1 != it3) == not(it1 == it3) );
|
||||
CHECK( (it2 != it3) == not(it2 == it3) );
|
||||
CHECK( (it1_c != it1_c) == not(it1_c == it1_c) );
|
||||
CHECK( (it1_c != it2_c) == not(it1_c == it2_c) );
|
||||
CHECK( (it1_c != it3_c) == not(it1_c == it3_c) );
|
||||
CHECK( (it2_c != it3_c) == not(it2_c == it3_c) );
|
||||
}
|
||||
|
||||
// comparison: smaller
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 < it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 < it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 < it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 < it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c < it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(not (it1 < it1));
|
||||
CHECK(it1 < it2);
|
||||
CHECK(it1 < it3);
|
||||
CHECK(it2 < it3);
|
||||
CHECK(not (it1_c < it1_c));
|
||||
CHECK(it1_c < it2_c);
|
||||
CHECK(it1_c < it3_c);
|
||||
CHECK(it2_c < it3_c);
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: less than or equal
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 <= it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 <= it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 <= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 <= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 <= it1) == not(it1 < it1) );
|
||||
CHECK( (it1 <= it2) == not(it2 < it1) );
|
||||
CHECK( (it1 <= it3) == not(it3 < it1) );
|
||||
CHECK( (it2 <= it3) == not(it3 < it2) );
|
||||
CHECK( (it1_c <= it1_c) == not(it1_c < it1_c) );
|
||||
CHECK( (it1_c <= it2_c) == not(it2_c < it1_c) );
|
||||
CHECK( (it1_c <= it3_c) == not(it3_c < it1_c) );
|
||||
CHECK( (it2_c <= it3_c) == not(it3_c < it2_c) );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: greater than
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 > it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 > it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 > it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 > it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c > it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 > it1) == (it1 < it1) );
|
||||
CHECK( (it1 > it2) == (it2 < it1) );
|
||||
CHECK( (it1 > it3) == (it3 < it1) );
|
||||
CHECK( (it2 > it3) == (it3 < it2) );
|
||||
CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
|
||||
CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
|
||||
CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
|
||||
CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: greater than or equal
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 >= it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 >= it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 >= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 >= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 >= it1) == not(it1 < it1) );
|
||||
CHECK( (it1 >= it2) == not(it1 < it2) );
|
||||
CHECK( (it1 >= it3) == not(it1 < it3) );
|
||||
CHECK( (it2 >= it3) == not(it2 < it3) );
|
||||
CHECK( (it1_c >= it1_c) == not(it1_c < it1_c) );
|
||||
CHECK( (it1_c >= it2_c) == not(it1_c < it2_c) );
|
||||
CHECK( (it1_c >= it3_c) == not(it1_c < it3_c) );
|
||||
CHECK( (it2_c >= it3_c) == not(it2_c < it3_c) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check exceptions if different objects are compared
|
||||
for (auto j : j_values)
|
||||
{
|
||||
for (auto k : j_values)
|
||||
{
|
||||
if (j != k)
|
||||
{
|
||||
CHECK_THROWS_AS(j.begin() == k.begin(), std::domain_error);
|
||||
CHECK_THROWS_AS(j.cbegin() == k.cbegin(), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.begin() == k.begin(), "cannot compare iterators of different containers");
|
||||
CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "cannot compare iterators of different containers");
|
||||
|
||||
CHECK_THROWS_AS(j.begin() < k.begin(), std::domain_error);
|
||||
CHECK_THROWS_AS(j.cbegin() < k.cbegin(), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.begin() < k.begin(), "cannot compare iterators of different containers");
|
||||
CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "cannot compare iterators of different containers");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("iterator arithmetic")
|
||||
{
|
||||
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
json j_array = {1, 2, 3, 4, 5, 6};
|
||||
json j_null = nullptr;
|
||||
json j_value = 42;
|
||||
|
||||
SECTION("addition and subtraction")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it += 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it += 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it + 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it + 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it -= 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it -= 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it - 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it - 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it - it, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it - it, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
{
|
||||
auto it = j_array.begin();
|
||||
it += 3;
|
||||
CHECK((j_array.begin() + 3) == it);
|
||||
CHECK((it - 3) == j_array.begin());
|
||||
CHECK((it - j_array.begin()) == 3);
|
||||
CHECK(*it == json(4));
|
||||
it -= 2;
|
||||
CHECK(*it == json(2));
|
||||
}
|
||||
{
|
||||
auto it = j_array.cbegin();
|
||||
it += 3;
|
||||
CHECK((j_array.cbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_array.cbegin());
|
||||
CHECK((it - j_array.cbegin()) == 3);
|
||||
CHECK(*it == json(4));
|
||||
it -= 2;
|
||||
CHECK(*it == json(2));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
auto it = j_null.begin();
|
||||
it += 3;
|
||||
CHECK((j_null.begin() + 3) == it);
|
||||
CHECK((it - 3) == j_null.begin());
|
||||
CHECK((it - j_null.begin()) == 3);
|
||||
CHECK(it != j_null.end());
|
||||
it -= 3;
|
||||
CHECK(it == j_null.end());
|
||||
}
|
||||
{
|
||||
auto it = j_null.cbegin();
|
||||
it += 3;
|
||||
CHECK((j_null.cbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_null.cbegin());
|
||||
CHECK((it - j_null.cbegin()) == 3);
|
||||
CHECK(it != j_null.cend());
|
||||
it -= 3;
|
||||
CHECK(it == j_null.cend());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value")
|
||||
{
|
||||
{
|
||||
auto it = j_value.begin();
|
||||
it += 3;
|
||||
CHECK((j_value.begin() + 3) == it);
|
||||
CHECK((it - 3) == j_value.begin());
|
||||
CHECK((it - j_value.begin()) == 3);
|
||||
CHECK(it != j_value.end());
|
||||
it -= 3;
|
||||
CHECK(*it == json(42));
|
||||
}
|
||||
{
|
||||
auto it = j_value.cbegin();
|
||||
it += 3;
|
||||
CHECK((j_value.cbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_value.cbegin());
|
||||
CHECK((it - j_value.cbegin()) == 3);
|
||||
CHECK(it != j_value.cend());
|
||||
it -= 3;
|
||||
CHECK(*it == json(42));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("subscript operator")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
{
|
||||
auto it = j_object.begin();
|
||||
CHECK_THROWS_AS(it[0], std::domain_error);
|
||||
CHECK_THROWS_AS(it[1], std::domain_error);
|
||||
CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators");
|
||||
CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.cbegin();
|
||||
CHECK_THROWS_AS(it[0], std::domain_error);
|
||||
CHECK_THROWS_AS(it[1], std::domain_error);
|
||||
CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators");
|
||||
CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
{
|
||||
auto it = j_array.begin();
|
||||
CHECK(it[0] == json(1));
|
||||
CHECK(it[1] == json(2));
|
||||
CHECK(it[2] == json(3));
|
||||
CHECK(it[3] == json(4));
|
||||
CHECK(it[4] == json(5));
|
||||
CHECK(it[5] == json(6));
|
||||
}
|
||||
{
|
||||
auto it = j_array.cbegin();
|
||||
CHECK(it[0] == json(1));
|
||||
CHECK(it[1] == json(2));
|
||||
CHECK(it[2] == json(3));
|
||||
CHECK(it[3] == json(4));
|
||||
CHECK(it[4] == json(5));
|
||||
CHECK(it[5] == json(6));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
auto it = j_null.begin();
|
||||
CHECK_THROWS_AS(it[0], std::out_of_range);
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[0], "cannot get value");
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
{
|
||||
auto it = j_null.cbegin();
|
||||
CHECK_THROWS_AS(it[0], std::out_of_range);
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[0], "cannot get value");
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value")
|
||||
{
|
||||
{
|
||||
auto it = j_value.begin();
|
||||
CHECK(it[0] == json(42));
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
{
|
||||
auto it = j_value.cbegin();
|
||||
CHECK(it[0] == json(42));
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("reverse iterator comparisons")
|
||||
{
|
||||
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
|
||||
|
||||
for (json& j : j_values)
|
||||
{
|
||||
auto it1 = j.rbegin();
|
||||
auto it2 = j.rbegin();
|
||||
auto it3 = j.rbegin();
|
||||
++it2;
|
||||
++it3;
|
||||
++it3;
|
||||
auto it1_c = j.crbegin();
|
||||
auto it2_c = j.crbegin();
|
||||
auto it3_c = j.crbegin();
|
||||
++it2_c;
|
||||
++it3_c;
|
||||
++it3_c;
|
||||
|
||||
// comparison: equal
|
||||
{
|
||||
CHECK(it1 == it1);
|
||||
CHECK(not (it1 == it2));
|
||||
CHECK(not (it1 == it3));
|
||||
CHECK(not (it2 == it3));
|
||||
CHECK(it1_c == it1_c);
|
||||
CHECK(not (it1_c == it2_c));
|
||||
CHECK(not (it1_c == it3_c));
|
||||
CHECK(not (it2_c == it3_c));
|
||||
}
|
||||
|
||||
// comparison: not equal
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 != it1) == not(it1 == it1) );
|
||||
CHECK( (it1 != it2) == not(it1 == it2) );
|
||||
CHECK( (it1 != it3) == not(it1 == it3) );
|
||||
CHECK( (it2 != it3) == not(it2 == it3) );
|
||||
CHECK( (it1_c != it1_c) == not(it1_c == it1_c) );
|
||||
CHECK( (it1_c != it2_c) == not(it1_c == it2_c) );
|
||||
CHECK( (it1_c != it3_c) == not(it1_c == it3_c) );
|
||||
CHECK( (it2_c != it3_c) == not(it2_c == it3_c) );
|
||||
}
|
||||
|
||||
// comparison: smaller
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 < it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 < it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 < it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 < it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c < it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c < it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(not (it1 < it1));
|
||||
CHECK(it1 < it2);
|
||||
CHECK(it1 < it3);
|
||||
CHECK(it2 < it3);
|
||||
CHECK(not (it1_c < it1_c));
|
||||
CHECK(it1_c < it2_c);
|
||||
CHECK(it1_c < it3_c);
|
||||
CHECK(it2_c < it3_c);
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: less than or equal
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 <= it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 <= it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 <= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 <= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 <= it1) == not(it1 < it1) );
|
||||
CHECK( (it1 <= it2) == not(it2 < it1) );
|
||||
CHECK( (it1 <= it3) == not(it3 < it1) );
|
||||
CHECK( (it2 <= it3) == not(it3 < it2) );
|
||||
CHECK( (it1_c <= it1_c) == not(it1_c < it1_c) );
|
||||
CHECK( (it1_c <= it2_c) == not(it2_c < it1_c) );
|
||||
CHECK( (it1_c <= it3_c) == not(it3_c < it1_c) );
|
||||
CHECK( (it2_c <= it3_c) == not(it3_c < it2_c) );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: greater than
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 > it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 > it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 > it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 > it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c > it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c > it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 > it1) == (it1 < it1) );
|
||||
CHECK( (it1 > it2) == (it2 < it1) );
|
||||
CHECK( (it1 > it3) == (it3 < it1) );
|
||||
CHECK( (it2 > it3) == (it3 < it2) );
|
||||
CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
|
||||
CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
|
||||
CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
|
||||
CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
|
||||
}
|
||||
}
|
||||
|
||||
// comparison: greater than or equal
|
||||
{
|
||||
if (j.type() == json::value_t::object)
|
||||
{
|
||||
CHECK_THROWS_AS(it1 >= it1, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 >= it2, std::domain_error);
|
||||
CHECK_THROWS_AS(it2 >= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1 >= it3, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error);
|
||||
CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error);
|
||||
CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators");
|
||||
CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check definition
|
||||
CHECK( (it1 >= it1) == not(it1 < it1) );
|
||||
CHECK( (it1 >= it2) == not(it1 < it2) );
|
||||
CHECK( (it1 >= it3) == not(it1 < it3) );
|
||||
CHECK( (it2 >= it3) == not(it2 < it3) );
|
||||
CHECK( (it1_c >= it1_c) == not(it1_c < it1_c) );
|
||||
CHECK( (it1_c >= it2_c) == not(it1_c < it2_c) );
|
||||
CHECK( (it1_c >= it3_c) == not(it1_c < it3_c) );
|
||||
CHECK( (it2_c >= it3_c) == not(it2_c < it3_c) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check exceptions if different objects are compared
|
||||
for (auto j : j_values)
|
||||
{
|
||||
for (auto k : j_values)
|
||||
{
|
||||
if (j != k)
|
||||
{
|
||||
CHECK_THROWS_AS(j.rbegin() == k.rbegin(), std::domain_error);
|
||||
CHECK_THROWS_AS(j.crbegin() == k.crbegin(), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "cannot compare iterators of different containers");
|
||||
CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "cannot compare iterators of different containers");
|
||||
|
||||
CHECK_THROWS_AS(j.rbegin() < k.rbegin(), std::domain_error);
|
||||
CHECK_THROWS_AS(j.crbegin() < k.crbegin(), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "cannot compare iterators of different containers");
|
||||
CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "cannot compare iterators of different containers");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("reverse iterator arithmetic")
|
||||
{
|
||||
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
json j_array = {1, 2, 3, 4, 5, 6};
|
||||
json j_null = nullptr;
|
||||
json j_value = 42;
|
||||
|
||||
SECTION("addition and subtraction")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it += 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it += 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it + 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it + 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it -= 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it -= 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it - 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it - 1, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it - it, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it - it, std::domain_error);
|
||||
CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
{
|
||||
auto it = j_array.rbegin();
|
||||
it += 3;
|
||||
CHECK((j_array.rbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_array.rbegin());
|
||||
CHECK((j_array.rbegin() - it) == 3);
|
||||
CHECK(*it == json(3));
|
||||
it -= 2;
|
||||
CHECK(*it == json(5));
|
||||
}
|
||||
{
|
||||
auto it = j_array.crbegin();
|
||||
it += 3;
|
||||
CHECK((j_array.crbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_array.crbegin());
|
||||
CHECK((j_array.crbegin() - it) == 3);
|
||||
CHECK(*it == json(3));
|
||||
it -= 2;
|
||||
CHECK(*it == json(5));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
auto it = j_null.rbegin();
|
||||
it += 3;
|
||||
CHECK((j_null.rbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_null.rbegin());
|
||||
CHECK((j_null.rbegin() - it) == 3);
|
||||
CHECK(it != j_null.rend());
|
||||
it -= 3;
|
||||
CHECK(it == j_null.rend());
|
||||
}
|
||||
{
|
||||
auto it = j_null.crbegin();
|
||||
it += 3;
|
||||
CHECK((j_null.crbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_null.crbegin());
|
||||
CHECK((j_null.crbegin() - it) == 3);
|
||||
CHECK(it != j_null.crend());
|
||||
it -= 3;
|
||||
CHECK(it == j_null.crend());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value")
|
||||
{
|
||||
{
|
||||
auto it = j_value.rbegin();
|
||||
it += 3;
|
||||
CHECK((j_value.rbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_value.rbegin());
|
||||
CHECK((j_value.rbegin() - it) == 3);
|
||||
CHECK(it != j_value.rend());
|
||||
it -= 3;
|
||||
CHECK(*it == json(42));
|
||||
}
|
||||
{
|
||||
auto it = j_value.crbegin();
|
||||
it += 3;
|
||||
CHECK((j_value.crbegin() + 3) == it);
|
||||
CHECK((it - 3) == j_value.crbegin());
|
||||
CHECK((j_value.crbegin() - it) == 3);
|
||||
CHECK(it != j_value.crend());
|
||||
it -= 3;
|
||||
CHECK(*it == json(42));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("subscript operator")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
{
|
||||
auto it = j_object.rbegin();
|
||||
CHECK_THROWS_AS(it[0], std::domain_error);
|
||||
CHECK_THROWS_AS(it[1], std::domain_error);
|
||||
CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators");
|
||||
CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators");
|
||||
}
|
||||
{
|
||||
auto it = j_object.crbegin();
|
||||
CHECK_THROWS_AS(it[0], std::domain_error);
|
||||
CHECK_THROWS_AS(it[1], std::domain_error);
|
||||
CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators");
|
||||
CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
{
|
||||
auto it = j_array.rbegin();
|
||||
CHECK(it[0] == json(6));
|
||||
CHECK(it[1] == json(5));
|
||||
CHECK(it[2] == json(4));
|
||||
CHECK(it[3] == json(3));
|
||||
CHECK(it[4] == json(2));
|
||||
CHECK(it[5] == json(1));
|
||||
}
|
||||
{
|
||||
auto it = j_array.crbegin();
|
||||
CHECK(it[0] == json(6));
|
||||
CHECK(it[1] == json(5));
|
||||
CHECK(it[2] == json(4));
|
||||
CHECK(it[3] == json(3));
|
||||
CHECK(it[4] == json(2));
|
||||
CHECK(it[5] == json(1));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
{
|
||||
auto it = j_null.rbegin();
|
||||
CHECK_THROWS_AS(it[0], std::out_of_range);
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[0], "cannot get value");
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
{
|
||||
auto it = j_null.crbegin();
|
||||
CHECK_THROWS_AS(it[0], std::out_of_range);
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[0], "cannot get value");
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("value")
|
||||
{
|
||||
{
|
||||
auto it = j_value.rbegin();
|
||||
CHECK(it[0] == json(42));
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
{
|
||||
auto it = j_value.crbegin();
|
||||
CHECK(it[0] == json(42));
|
||||
CHECK_THROWS_AS(it[1], std::out_of_range);
|
||||
CHECK_THROWS_WITH(it[1], "cannot get value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1217
test/src/unit-json_patch.cpp
Normal file
393
test/src/unit-json_pointer.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("JSON pointers")
|
||||
{
|
||||
SECTION("errors")
|
||||
{
|
||||
CHECK_THROWS_AS(json::json_pointer("foo"), std::domain_error);
|
||||
CHECK_THROWS_WITH(json::json_pointer("foo"), "JSON pointer must be empty or begin with '/'");
|
||||
|
||||
CHECK_THROWS_AS(json::json_pointer("/~~"), std::domain_error);
|
||||
CHECK_THROWS_WITH(json::json_pointer("/~~"), "escape error: '~' must be followed with '0' or '1'");
|
||||
|
||||
CHECK_THROWS_AS(json::json_pointer("/~"), std::domain_error);
|
||||
CHECK_THROWS_WITH(json::json_pointer("/~"), "escape error: '~' must be followed with '0' or '1'");
|
||||
|
||||
json::json_pointer p;
|
||||
CHECK_THROWS_AS(p.top(), std::domain_error);
|
||||
CHECK_THROWS_WITH(p.top(), "JSON pointer has no parent");
|
||||
CHECK_THROWS_AS(p.pop_back(), std::domain_error);
|
||||
CHECK_THROWS_WITH(p.pop_back(), "JSON pointer has no parent");
|
||||
}
|
||||
|
||||
SECTION("examples from RFC 6901")
|
||||
{
|
||||
SECTION("nonconst access")
|
||||
{
|
||||
json j = R"(
|
||||
{
|
||||
"foo": ["bar", "baz"],
|
||||
"": 0,
|
||||
"a/b": 1,
|
||||
"c%d": 2,
|
||||
"e^f": 3,
|
||||
"g|h": 4,
|
||||
"i\\j": 5,
|
||||
"k\"l": 6,
|
||||
" ": 7,
|
||||
"m~n": 8
|
||||
}
|
||||
)"_json;
|
||||
|
||||
// the whole document
|
||||
CHECK(j[json::json_pointer()] == j);
|
||||
CHECK(j[json::json_pointer("")] == j);
|
||||
|
||||
// array access
|
||||
CHECK(j[json::json_pointer("/foo")] == j["foo"]);
|
||||
CHECK(j[json::json_pointer("/foo/0")] == j["foo"][0]);
|
||||
CHECK(j[json::json_pointer("/foo/1")] == j["foo"][1]);
|
||||
CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
|
||||
|
||||
// checked array access
|
||||
CHECK(j.at(json::json_pointer("/foo/0")) == j["foo"][0]);
|
||||
CHECK(j.at(json::json_pointer("/foo/1")) == j["foo"][1]);
|
||||
|
||||
// empty string access
|
||||
CHECK(j[json::json_pointer("/")] == j[""]);
|
||||
|
||||
// other cases
|
||||
CHECK(j[json::json_pointer("/ ")] == j[" "]);
|
||||
CHECK(j[json::json_pointer("/c%d")] == j["c%d"]);
|
||||
CHECK(j[json::json_pointer("/e^f")] == j["e^f"]);
|
||||
CHECK(j[json::json_pointer("/g|h")] == j["g|h"]);
|
||||
CHECK(j[json::json_pointer("/i\\j")] == j["i\\j"]);
|
||||
CHECK(j[json::json_pointer("/k\"l")] == j["k\"l"]);
|
||||
|
||||
// checked access
|
||||
CHECK(j.at(json::json_pointer("/ ")) == j[" "]);
|
||||
CHECK(j.at(json::json_pointer("/c%d")) == j["c%d"]);
|
||||
CHECK(j.at(json::json_pointer("/e^f")) == j["e^f"]);
|
||||
CHECK(j.at(json::json_pointer("/g|h")) == j["g|h"]);
|
||||
CHECK(j.at(json::json_pointer("/i\\j")) == j["i\\j"]);
|
||||
CHECK(j.at(json::json_pointer("/k\"l")) == j["k\"l"]);
|
||||
|
||||
// escaped access
|
||||
CHECK(j[json::json_pointer("/a~1b")] == j["a/b"]);
|
||||
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
||||
|
||||
// unescaped access
|
||||
// access to nonexisting values yield object creation
|
||||
CHECK_NOTHROW(j[json::json_pointer("/a/b")] = 42);
|
||||
CHECK(j["a"]["b"] == json(42));
|
||||
CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
|
||||
CHECK(j["a"]["c"] == json({nullptr, 42}));
|
||||
CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
|
||||
CHECK(j["a"]["d"] == json::array({42}));
|
||||
// "/a/b" works for JSON {"a": {"b": 42}}
|
||||
CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
|
||||
|
||||
// unresolved access
|
||||
json j_primitive = 1;
|
||||
CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'");
|
||||
CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'");
|
||||
}
|
||||
|
||||
SECTION("const access")
|
||||
{
|
||||
const json j = R"(
|
||||
{
|
||||
"foo": ["bar", "baz"],
|
||||
"": 0,
|
||||
"a/b": 1,
|
||||
"c%d": 2,
|
||||
"e^f": 3,
|
||||
"g|h": 4,
|
||||
"i\\j": 5,
|
||||
"k\"l": 6,
|
||||
" ": 7,
|
||||
"m~n": 8
|
||||
}
|
||||
)"_json;
|
||||
|
||||
// the whole document
|
||||
CHECK(j[json::json_pointer()] == j);
|
||||
CHECK(j[json::json_pointer("")] == j);
|
||||
|
||||
// array access
|
||||
CHECK(j[json::json_pointer("/foo")] == j["foo"]);
|
||||
CHECK(j[json::json_pointer("/foo/0")] == j["foo"][0]);
|
||||
CHECK(j[json::json_pointer("/foo/1")] == j["foo"][1]);
|
||||
CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
|
||||
|
||||
// checked array access
|
||||
CHECK(j.at(json::json_pointer("/foo/0")) == j["foo"][0]);
|
||||
CHECK(j.at(json::json_pointer("/foo/1")) == j["foo"][1]);
|
||||
|
||||
// empty string access
|
||||
CHECK(j[json::json_pointer("/")] == j[""]);
|
||||
|
||||
// other cases
|
||||
CHECK(j[json::json_pointer("/ ")] == j[" "]);
|
||||
CHECK(j[json::json_pointer("/c%d")] == j["c%d"]);
|
||||
CHECK(j[json::json_pointer("/e^f")] == j["e^f"]);
|
||||
CHECK(j[json::json_pointer("/g|h")] == j["g|h"]);
|
||||
CHECK(j[json::json_pointer("/i\\j")] == j["i\\j"]);
|
||||
CHECK(j[json::json_pointer("/k\"l")] == j["k\"l"]);
|
||||
|
||||
// checked access
|
||||
CHECK(j.at(json::json_pointer("/ ")) == j[" "]);
|
||||
CHECK(j.at(json::json_pointer("/c%d")) == j["c%d"]);
|
||||
CHECK(j.at(json::json_pointer("/e^f")) == j["e^f"]);
|
||||
CHECK(j.at(json::json_pointer("/g|h")) == j["g|h"]);
|
||||
CHECK(j.at(json::json_pointer("/i\\j")) == j["i\\j"]);
|
||||
CHECK(j.at(json::json_pointer("/k\"l")) == j["k\"l"]);
|
||||
|
||||
// escaped access
|
||||
CHECK(j[json::json_pointer("/a~1b")] == j["a/b"]);
|
||||
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
||||
|
||||
// unescaped access
|
||||
CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at(json::json_pointer("/a/b")), "key 'a' not found");
|
||||
|
||||
// unresolved access
|
||||
const json j_primitive = 1;
|
||||
CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'");
|
||||
CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'");
|
||||
}
|
||||
|
||||
SECTION("user-defined string literal")
|
||||
{
|
||||
json j = R"(
|
||||
{
|
||||
"foo": ["bar", "baz"],
|
||||
"": 0,
|
||||
"a/b": 1,
|
||||
"c%d": 2,
|
||||
"e^f": 3,
|
||||
"g|h": 4,
|
||||
"i\\j": 5,
|
||||
"k\"l": 6,
|
||||
" ": 7,
|
||||
"m~n": 8
|
||||
}
|
||||
)"_json;
|
||||
|
||||
// the whole document
|
||||
CHECK(j[""_json_pointer] == j);
|
||||
|
||||
// array access
|
||||
CHECK(j["/foo"_json_pointer] == j["foo"]);
|
||||
CHECK(j["/foo/0"_json_pointer] == j["foo"][0]);
|
||||
CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array access")
|
||||
{
|
||||
SECTION("nonconst access")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
const json j_const = j;
|
||||
|
||||
// check reading access
|
||||
CHECK(j["/0"_json_pointer] == j[0]);
|
||||
CHECK(j["/1"_json_pointer] == j[1]);
|
||||
CHECK(j["/2"_json_pointer] == j[2]);
|
||||
|
||||
// assign to existing index
|
||||
j["/1"_json_pointer] = 13;
|
||||
CHECK(j[1] == json(13));
|
||||
|
||||
// assign to nonexisting index
|
||||
j["/3"_json_pointer] = 33;
|
||||
CHECK(j[3] == json(33));
|
||||
|
||||
// assign to nonexisting index (with gap)
|
||||
j["/5"_json_pointer] = 55;
|
||||
CHECK(j == json({1, 13, 3, 33, nullptr, 55}));
|
||||
|
||||
// error with leading 0
|
||||
CHECK_THROWS_AS(j["/01"_json_pointer], std::domain_error);
|
||||
CHECK_THROWS_WITH(j["/01"_json_pointer], "array index must not begin with '0'");
|
||||
CHECK_THROWS_AS(j_const["/01"_json_pointer], std::domain_error);
|
||||
CHECK_THROWS_WITH(j_const["/01"_json_pointer], "array index must not begin with '0'");
|
||||
CHECK_THROWS_AS(j.at("/01"_json_pointer), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.at("/01"_json_pointer), "array index must not begin with '0'");
|
||||
CHECK_THROWS_AS(j_const.at("/01"_json_pointer), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "array index must not begin with '0'");
|
||||
|
||||
// error with incorrect numbers
|
||||
CHECK_THROWS_AS(j["/one"_json_pointer] = 1, std::invalid_argument);
|
||||
|
||||
// assign to "-"
|
||||
j["/-"_json_pointer] = 99;
|
||||
CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99}));
|
||||
|
||||
// error when using "-" in const object
|
||||
CHECK_THROWS_AS(j_const["/-"_json_pointer], std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_const["/-"_json_pointer], "array index '-' (3) is out of range");
|
||||
|
||||
// error when using "-" with at
|
||||
CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (7) is out of range");
|
||||
CHECK_THROWS_AS(j_const.at("/-"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "array index '-' (3) is out of range");
|
||||
}
|
||||
|
||||
SECTION("const access")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
|
||||
// check reading access
|
||||
CHECK(j["/0"_json_pointer] == j[0]);
|
||||
CHECK(j["/1"_json_pointer] == j[1]);
|
||||
CHECK(j["/2"_json_pointer] == j[2]);
|
||||
|
||||
// assign to nonexisting index
|
||||
CHECK_THROWS_AS(j.at("/3"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at("/3"_json_pointer), "array index 3 is out of range");
|
||||
|
||||
// assign to nonexisting index (with gap)
|
||||
CHECK_THROWS_AS(j.at("/5"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at("/5"_json_pointer), "array index 5 is out of range");
|
||||
|
||||
// assign to "-"
|
||||
CHECK_THROWS_AS(j["/-"_json_pointer], std::out_of_range);
|
||||
CHECK_THROWS_WITH(j["/-"_json_pointer], "array index '-' (3) is out of range");
|
||||
CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
|
||||
CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (3) is out of range");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SECTION("flatten")
|
||||
{
|
||||
json j =
|
||||
{
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{
|
||||
"answer", {
|
||||
{"everything", 42}
|
||||
}
|
||||
},
|
||||
{"list", {1, 0, 2}},
|
||||
{
|
||||
"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99},
|
||||
{"", "empty string"},
|
||||
{"/", "slash"},
|
||||
{"~", "tilde"},
|
||||
{"~1", "tilde1"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
json j_flatten =
|
||||
{
|
||||
{"/pi", 3.141},
|
||||
{"/happy", true},
|
||||
{"/name", "Niels"},
|
||||
{"/nothing", nullptr},
|
||||
{"/answer/everything", 42},
|
||||
{"/list/0", 1},
|
||||
{"/list/1", 0},
|
||||
{"/list/2", 2},
|
||||
{"/object/currency", "USD"},
|
||||
{"/object/value", 42.99},
|
||||
{"/object/", "empty string"},
|
||||
{"/object/~1", "slash"},
|
||||
{"/object/~0", "tilde"},
|
||||
{"/object/~01", "tilde1"}
|
||||
};
|
||||
|
||||
// check if flattened result is as expected
|
||||
CHECK(j.flatten() == j_flatten);
|
||||
|
||||
// check if unflattened result is as expected
|
||||
CHECK(j_flatten.unflatten() == j);
|
||||
|
||||
// error for nonobjects
|
||||
CHECK_THROWS_AS(json(1).unflatten(), std::domain_error);
|
||||
CHECK_THROWS_WITH(json(1).unflatten(), "only objects can be unflattened");
|
||||
|
||||
// error for nonprimitve values
|
||||
CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), std::domain_error);
|
||||
CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "values in object must be primitive");
|
||||
|
||||
// error for conflicting values
|
||||
json j_error = {{"", 42}, {"/foo", 17}};
|
||||
CHECK_THROWS_AS(j_error.unflatten(), std::domain_error);
|
||||
CHECK_THROWS_WITH(j_error.unflatten(), "invalid value to unflatten");
|
||||
|
||||
// explicit roundtrip check
|
||||
CHECK(j.flatten().unflatten() == j);
|
||||
|
||||
// roundtrip for primitive values
|
||||
json j_null;
|
||||
CHECK(j_null.flatten().unflatten() == j_null);
|
||||
json j_number = 42;
|
||||
CHECK(j_number.flatten().unflatten() == j_number);
|
||||
json j_boolean = false;
|
||||
CHECK(j_boolean.flatten().unflatten() == j_boolean);
|
||||
json j_string = "foo";
|
||||
CHECK(j_string.flatten().unflatten() == j_string);
|
||||
|
||||
// roundtrip for empty structured values (will be unflattened to null)
|
||||
json j_array(json::value_t::array);
|
||||
CHECK(j_array.flatten().unflatten() == json());
|
||||
json j_object(json::value_t::object);
|
||||
CHECK(j_object.flatten().unflatten() == json());
|
||||
}
|
||||
|
||||
SECTION("string representation")
|
||||
{
|
||||
for (auto ptr :
|
||||
{"", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n"
|
||||
})
|
||||
{
|
||||
CHECK(json::json_pointer(ptr).to_string() == ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
713
test/src/unit-modifiers.cpp
Normal file
@@ -0,0 +1,713 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("modifiers")
|
||||
{
|
||||
SECTION("clear()")
|
||||
{
|
||||
SECTION("boolean")
|
||||
{
|
||||
json j = true;
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::boolean));
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
json j = "hello world";
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::string));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
SECTION("empty array")
|
||||
{
|
||||
json j = json::array();
|
||||
|
||||
j.clear();
|
||||
CHECK(j.empty());
|
||||
CHECK(j == json(json::value_t::array));
|
||||
}
|
||||
|
||||
SECTION("filled array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
|
||||
j.clear();
|
||||
CHECK(j.empty());
|
||||
CHECK(j == json(json::value_t::array));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("empty object")
|
||||
{
|
||||
json j = json::object();
|
||||
|
||||
j.clear();
|
||||
CHECK(j.empty());
|
||||
CHECK(j == json(json::value_t::object));
|
||||
}
|
||||
|
||||
SECTION("filled object")
|
||||
{
|
||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}};
|
||||
|
||||
j.clear();
|
||||
CHECK(j.empty());
|
||||
CHECK(j == json(json::value_t::object));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("number (integer)")
|
||||
{
|
||||
json j = 23;
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::number_integer));
|
||||
}
|
||||
|
||||
SECTION("number (unsigned)")
|
||||
{
|
||||
json j = 23u;
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::number_integer));
|
||||
}
|
||||
|
||||
SECTION("number (float)")
|
||||
{
|
||||
json j = 23.42;
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::number_float));
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
json j = nullptr;
|
||||
|
||||
j.clear();
|
||||
CHECK(j == json(json::value_t::null));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("push_back()")
|
||||
{
|
||||
SECTION("to array")
|
||||
{
|
||||
SECTION("json&&")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j.push_back(1);
|
||||
j.push_back(2);
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
j.push_back("Hello");
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2, 3, "Hello"}));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
CHECK_THROWS_AS(j.push_back("Hello"), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.push_back("Hello"), "cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("const json&")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
json k(1);
|
||||
j.push_back(k);
|
||||
j.push_back(k);
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 1}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
json k("Hello");
|
||||
j.push_back(k);
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2, 3, "Hello"}));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
json k("Hello");
|
||||
CHECK_THROWS_AS(j.push_back(k), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.push_back(k), "cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("to object")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j.push_back(json::object_t::value_type({"one", 1}));
|
||||
j.push_back(json::object_t::value_type({"two", 2}));
|
||||
CHECK(j.type() == json::value_t::object);
|
||||
CHECK(j.size() == 2);
|
||||
CHECK(j["one"] == json(1));
|
||||
CHECK(j["two"] == json(2));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
j.push_back(json::object_t::value_type({"one", 1}));
|
||||
j.push_back(json::object_t::value_type({"two", 2}));
|
||||
CHECK(j.size() == 2);
|
||||
CHECK(j["one"] == json(1));
|
||||
CHECK(j["two"] == json(2));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
json k("Hello");
|
||||
CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.push_back(json::object_t::value_type({"one", 1})),
|
||||
"cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("with initializer_list")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j.push_back({"foo", "bar"});
|
||||
CHECK(j == json::array({{"foo", "bar"}}));
|
||||
|
||||
json k;
|
||||
k.push_back({1, 2, 3});
|
||||
CHECK(k == json::array({{1, 2, 3}}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
j.push_back({"foo", "bar"});
|
||||
CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
|
||||
|
||||
json k = {1, 2, 3};
|
||||
k.push_back({1, 2, 3});
|
||||
CHECK(k == json({1, 2, 3, {1, 2, 3}}));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j = {{"key1", 1}};
|
||||
j.push_back({"key2", "bar"});
|
||||
CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
|
||||
|
||||
json k = {{"key1", 1}};
|
||||
CHECK_THROWS_AS(k.push_back({1, 2, 3, 4}), std::domain_error);
|
||||
CHECK_THROWS_WITH(k.push_back({1, 2, 3, 4}), "cannot use push_back() with object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("operator+=")
|
||||
{
|
||||
SECTION("to array")
|
||||
{
|
||||
SECTION("json&&")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j += 1;
|
||||
j += 2;
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
j += "Hello";
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2, 3, "Hello"}));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
CHECK_THROWS_AS(j += "Hello", std::domain_error);
|
||||
CHECK_THROWS_WITH(j += "Hello", "cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("const json&")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
json k(1);
|
||||
j += k;
|
||||
j += k;
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 1}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
json k("Hello");
|
||||
j += k;
|
||||
CHECK(j.type() == json::value_t::array);
|
||||
CHECK(j == json({1, 2, 3, "Hello"}));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
json k("Hello");
|
||||
CHECK_THROWS_AS(j += k, std::domain_error);
|
||||
CHECK_THROWS_WITH(j += k, "cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("to object")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j += json::object_t::value_type({"one", 1});
|
||||
j += json::object_t::value_type({"two", 2});
|
||||
CHECK(j.type() == json::value_t::object);
|
||||
CHECK(j.size() == 2);
|
||||
CHECK(j["one"] == json(1));
|
||||
CHECK(j["two"] == json(2));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j(json::value_t::object);
|
||||
j += json::object_t::value_type({"one", 1});
|
||||
j += json::object_t::value_type({"two", 2});
|
||||
CHECK(j.size() == 2);
|
||||
CHECK(j["one"] == json(1));
|
||||
CHECK(j["two"] == json(2));
|
||||
}
|
||||
|
||||
SECTION("other type")
|
||||
{
|
||||
json j = 1;
|
||||
json k("Hello");
|
||||
CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), std::domain_error);
|
||||
CHECK_THROWS_WITH(j += json::object_t::value_type({"one", 1}),
|
||||
"cannot use push_back() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("with initializer_list")
|
||||
{
|
||||
SECTION("null")
|
||||
{
|
||||
json j;
|
||||
j += {"foo", "bar"};
|
||||
CHECK(j == json::array({{"foo", "bar"}}));
|
||||
|
||||
json k;
|
||||
k += {1, 2, 3};
|
||||
CHECK(k == json::array({{1, 2, 3}}));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
j += {"foo", "bar"};
|
||||
CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
|
||||
|
||||
json k = {1, 2, 3};
|
||||
k += {1, 2, 3};
|
||||
CHECK(k == json({1, 2, 3, {1, 2, 3}}));
|
||||
}
|
||||
|
||||
SECTION("object")
|
||||
{
|
||||
json j = {{"key1", 1}};
|
||||
j += {"key2", "bar"};
|
||||
CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
|
||||
|
||||
json k = {{"key1", 1}};
|
||||
CHECK_THROWS_AS((k += {1, 2, 3, 4}), std::domain_error);
|
||||
CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "cannot use push_back() with object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("insert")
|
||||
{
|
||||
json j_array = {1, 2, 3, 4};
|
||||
json j_value = 5;
|
||||
|
||||
SECTION("value at position")
|
||||
{
|
||||
SECTION("insert before begin()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin(), j_value);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK(j_array.begin() == it);
|
||||
CHECK(j_array == json({5, 1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert in the middle")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin() + 2, j_value);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((it - j_array.begin()) == 2);
|
||||
CHECK(j_array == json({1, 2, 5, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert before end()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), j_value);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((j_array.end() - it) == 1);
|
||||
CHECK(j_array == json({1, 2, 3, 4, 5}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("rvalue at position")
|
||||
{
|
||||
SECTION("insert before begin()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin(), 5);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK(j_array.begin() == it);
|
||||
CHECK(j_array == json({5, 1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert in the middle")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin() + 2, 5);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((it - j_array.begin()) == 2);
|
||||
CHECK(j_array == json({1, 2, 5, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert before end()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), 5);
|
||||
CHECK(j_array.size() == 5);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((j_array.end() - it) == 1);
|
||||
CHECK(j_array == json({1, 2, 3, 4, 5}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("copies at position")
|
||||
{
|
||||
SECTION("insert before begin()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin(), 3, 5);
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == j_value);
|
||||
CHECK(j_array.begin() == it);
|
||||
CHECK(j_array == json({5, 5, 5, 1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert in the middle")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin() + 2, 3, 5);
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((it - j_array.begin()) == 2);
|
||||
CHECK(j_array == json({1, 2, 5, 5, 5, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert before end()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), 3, 5);
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == j_value);
|
||||
CHECK((j_array.end() - it) == 3);
|
||||
CHECK(j_array == json({1, 2, 3, 4, 5, 5, 5}));
|
||||
}
|
||||
|
||||
SECTION("insert nothing (count = 0)")
|
||||
{
|
||||
auto pos = j_array.end();
|
||||
auto it = j_array.insert(j_array.end(), 0, 5);
|
||||
CHECK(j_array.size() == 4);
|
||||
CHECK(it == pos);
|
||||
CHECK(j_array == json({1, 2, 3, 4}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("range")
|
||||
{
|
||||
json j_other_array = {"first", "second"};
|
||||
|
||||
SECTION("proper usage")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.end());
|
||||
CHECK(j_array.size() == 6);
|
||||
CHECK(*it == *j_other_array.begin());
|
||||
CHECK((j_array.end() - it) == 2);
|
||||
CHECK(j_array == json({1, 2, 3, 4, "first", "second"}));
|
||||
}
|
||||
|
||||
SECTION("empty range")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.begin());
|
||||
CHECK(j_array.size() == 4);
|
||||
CHECK(it == j_array.end());
|
||||
CHECK(j_array == json({1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("invalid iterators")
|
||||
{
|
||||
json j_other_array2 = {"first", "second"};
|
||||
|
||||
CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()),
|
||||
std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_array.begin(), j_array.end()),
|
||||
"passed iterators may not belong to container");
|
||||
CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()),
|
||||
"iterators do not fit");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("initializer list at position")
|
||||
{
|
||||
SECTION("insert before begin()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin(), {7, 8, 9});
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == json(7));
|
||||
CHECK(j_array.begin() == it);
|
||||
CHECK(j_array == json({7, 8, 9, 1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert in the middle")
|
||||
{
|
||||
auto it = j_array.insert(j_array.begin() + 2, {7, 8, 9});
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == json(7));
|
||||
CHECK((it - j_array.begin()) == 2);
|
||||
CHECK(j_array == json({1, 2, 7, 8, 9, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("insert before end()")
|
||||
{
|
||||
auto it = j_array.insert(j_array.end(), {7, 8, 9});
|
||||
CHECK(j_array.size() == 7);
|
||||
CHECK(*it == json(7));
|
||||
CHECK((j_array.end() - it) == 3);
|
||||
CHECK(j_array == json({1, 2, 3, 4, 7, 8, 9}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("invalid iterator")
|
||||
{
|
||||
// pass iterator to a different array
|
||||
json j_another_array = {1, 2};
|
||||
json j_yet_another_array = {"first", "second"};
|
||||
CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), std::domain_error);
|
||||
CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), std::domain_error);
|
||||
CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), std::domain_error);
|
||||
CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(),
|
||||
j_yet_another_array.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_value),
|
||||
"iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10, 11),
|
||||
"iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_yet_another_array.begin(),
|
||||
j_yet_another_array.end()), "iterator does not fit current value");
|
||||
CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), {1, 2, 3, 4}),
|
||||
"iterator does not fit current value");
|
||||
}
|
||||
|
||||
SECTION("non-array type")
|
||||
{
|
||||
// call insert on a non-array type
|
||||
json j_nonarray = 3;
|
||||
json j_yet_another_array = {"first", "second"};
|
||||
CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(),
|
||||
j_yet_another_array.end()), std::domain_error);
|
||||
CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), std::domain_error);
|
||||
|
||||
CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), "cannot use insert() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), "cannot use insert() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10, 11), "cannot use insert() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(),
|
||||
j_yet_another_array.end()), "cannot use insert() with number");
|
||||
CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}),
|
||||
"cannot use insert() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("swap()")
|
||||
{
|
||||
SECTION("json")
|
||||
{
|
||||
SECTION("member swap")
|
||||
{
|
||||
json j("hello world");
|
||||
json k(42.23);
|
||||
|
||||
j.swap(k);
|
||||
|
||||
CHECK(j == json(42.23));
|
||||
CHECK(k == json("hello world"));
|
||||
}
|
||||
|
||||
SECTION("nonmember swap")
|
||||
{
|
||||
json j("hello world");
|
||||
json k(42.23);
|
||||
|
||||
std::swap(j, k);
|
||||
|
||||
CHECK(j == json(42.23));
|
||||
CHECK(k == json("hello world"));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("array_t")
|
||||
{
|
||||
SECTION("array_t type")
|
||||
{
|
||||
json j = {1, 2, 3, 4};
|
||||
json::array_t a = {"foo", "bar", "baz"};
|
||||
|
||||
j.swap(a);
|
||||
|
||||
CHECK(j == json({"foo", "bar", "baz"}));
|
||||
|
||||
j.swap(a);
|
||||
|
||||
CHECK(j == json({1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
SECTION("non-array_t type")
|
||||
{
|
||||
json j = 17;
|
||||
json::array_t a = {"foo", "bar", "baz"};
|
||||
|
||||
CHECK_THROWS_AS(j.swap(a), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.swap(a), "cannot use swap() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("object_t")
|
||||
{
|
||||
SECTION("object_t type")
|
||||
{
|
||||
json j = {{"one", 1}, {"two", 2}};
|
||||
json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
|
||||
|
||||
j.swap(o);
|
||||
|
||||
CHECK(j == json({{"cow", "Kuh"}, {"chicken", "Huhn"}}));
|
||||
|
||||
j.swap(o);
|
||||
|
||||
CHECK(j == json({{"one", 1}, {"two", 2}}));
|
||||
}
|
||||
|
||||
SECTION("non-object_t type")
|
||||
{
|
||||
json j = 17;
|
||||
json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
|
||||
|
||||
CHECK_THROWS_AS(j.swap(o), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.swap(o), "cannot use swap() with number");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("string_t")
|
||||
{
|
||||
SECTION("string_t type")
|
||||
{
|
||||
json j = "Hello world";
|
||||
json::string_t s = "Hallo Welt";
|
||||
|
||||
j.swap(s);
|
||||
|
||||
CHECK(j == json("Hallo Welt"));
|
||||
|
||||
j.swap(s);
|
||||
|
||||
CHECK(j == json("Hello world"));
|
||||
}
|
||||
|
||||
SECTION("non-string_t type")
|
||||
{
|
||||
json j = 17;
|
||||
json::string_t s = "Hallo Welt";
|
||||
|
||||
CHECK_THROWS_AS(j.swap(s), std::domain_error);
|
||||
CHECK_THROWS_WITH(j.swap(s), "cannot use swap() with number");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
443
test/src/unit-pointer_access.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("pointer access")
|
||||
{
|
||||
// create a JSON value with different types
|
||||
json json_types =
|
||||
{
|
||||
{"boolean", true},
|
||||
{
|
||||
"number", {
|
||||
{"integer", 42},
|
||||
{"unsigned", 42u},
|
||||
{"floating-point", 17.23}
|
||||
}
|
||||
},
|
||||
{"string", "Hello, world!"},
|
||||
{"array", {1, 2, 3, 4, 5}},
|
||||
{"null", nullptr}
|
||||
};
|
||||
|
||||
SECTION("pointer access to object_t")
|
||||
{
|
||||
using test_type = json::object_t;
|
||||
json value = {{"one", 1}, {"two", 2}};
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const object_t")
|
||||
{
|
||||
using test_type = const json::object_t;
|
||||
const json value = {{"one", 1}, {"two", 2}};
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to array_t")
|
||||
{
|
||||
using test_type = json::array_t;
|
||||
json value = {1, 2, 3, 4};
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const array_t")
|
||||
{
|
||||
using test_type = const json::array_t;
|
||||
const json value = {1, 2, 3, 4};
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to string_t")
|
||||
{
|
||||
using test_type = json::string_t;
|
||||
json value = "hello";
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const string_t")
|
||||
{
|
||||
using test_type = const json::string_t;
|
||||
const json value = "hello";
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to boolean_t")
|
||||
{
|
||||
using test_type = json::boolean_t;
|
||||
json value = false;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const boolean_t")
|
||||
{
|
||||
using test_type = const json::boolean_t;
|
||||
const json value = false;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
//CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
//CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
//CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to number_integer_t")
|
||||
{
|
||||
using test_type = json::number_integer_t;
|
||||
json value = 23;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const number_integer_t")
|
||||
{
|
||||
using test_type = const json::number_integer_t;
|
||||
const json value = 23;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to number_unsigned_t")
|
||||
{
|
||||
using test_type = json::number_unsigned_t;
|
||||
json value = 23u;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const number_unsigned_t")
|
||||
{
|
||||
using test_type = const json::number_unsigned_t;
|
||||
const json value = 23u;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == value.get<test_type>());
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == value.get<test_type>());
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == value.get<test_type>());
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() != nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to number_float_t")
|
||||
{
|
||||
using test_type = json::number_float_t;
|
||||
json value = 42.23;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == Approx(value.get<test_type>()));
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == Approx(value.get<test_type>()));
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == Approx(value.get<test_type>()));
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<json::number_float_t*>() != nullptr);
|
||||
}
|
||||
|
||||
SECTION("pointer access to const number_float_t")
|
||||
{
|
||||
using test_type = const json::number_float_t;
|
||||
const json value = 42.23;
|
||||
|
||||
// check if pointers are returned correctly
|
||||
test_type* p1 = value.get_ptr<test_type*>();
|
||||
CHECK(p1 == value.get_ptr<test_type*>());
|
||||
CHECK(*p1 == Approx(value.get<test_type>()));
|
||||
|
||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||
CHECK(*p2 == Approx(value.get<test_type>()));
|
||||
|
||||
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||
CHECK(*p3 == Approx(value.get<test_type>()));
|
||||
|
||||
// check if null pointers are returned correctly
|
||||
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||
CHECK(value.get_ptr<const json::number_float_t*>() != nullptr);
|
||||
}
|
||||
}
|
||||
299
test/src/unit-readme.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
TEST_CASE("README", "[hide]")
|
||||
{
|
||||
{
|
||||
// redirect std::cout for the README file
|
||||
auto old_cout_buffer = std::cout.rdbuf();
|
||||
std::ostringstream new_stream;
|
||||
std::cout.rdbuf(new_stream.rdbuf());
|
||||
{
|
||||
// create an empty structure (null)
|
||||
json j;
|
||||
|
||||
// add a number that is stored as double (note the implicit conversion of j to an object)
|
||||
j["pi"] = 3.141;
|
||||
|
||||
// add a Boolean that is stored as bool
|
||||
j["happy"] = true;
|
||||
|
||||
// add a string that is stored as std::string
|
||||
j["name"] = "Niels";
|
||||
|
||||
// add another null object by passing nullptr
|
||||
j["nothing"] = nullptr;
|
||||
|
||||
// add an object inside the object
|
||||
j["answer"]["everything"] = 42;
|
||||
|
||||
// add an array that is stored as std::vector (using an initializer list)
|
||||
j["list"] = { 1, 0, 2 };
|
||||
|
||||
// add another object (using an initializer list of pairs)
|
||||
j["object"] = { {"currency", "USD"}, {"value", 42.99} };
|
||||
|
||||
// instead, you could also write (which looks very similar to the JSON above)
|
||||
json j2 =
|
||||
{
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{
|
||||
"answer", {
|
||||
{"everything", 42}
|
||||
}
|
||||
},
|
||||
{"list", {1, 0, 2}},
|
||||
{
|
||||
"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
// ways to express the empty array []
|
||||
json empty_array_implicit = {{}};
|
||||
json empty_array_explicit = json::array();
|
||||
|
||||
// a way to express the empty object {}
|
||||
json empty_object_explicit = json::object();
|
||||
|
||||
// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
|
||||
json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
|
||||
}
|
||||
|
||||
{
|
||||
// create object from string literal
|
||||
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
|
||||
|
||||
// or even nicer with a raw string literal
|
||||
auto j2 = R"(
|
||||
{
|
||||
"happy": true,
|
||||
"pi": 3.141
|
||||
}
|
||||
)"_json;
|
||||
|
||||
// or explicitly
|
||||
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
|
||||
|
||||
// explicit conversion to string
|
||||
std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141}
|
||||
|
||||
// serialization with pretty printing
|
||||
// pass in the amount of spaces to indent
|
||||
std::cout << j.dump(4) << std::endl;
|
||||
// {
|
||||
// "happy": true,
|
||||
// "pi": 3.141
|
||||
// }
|
||||
|
||||
std::cout << std::setw(2) << j << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
// create an array using push_back
|
||||
json j;
|
||||
j.push_back("foo");
|
||||
j.push_back(1);
|
||||
j.push_back(true);
|
||||
|
||||
// iterate the array
|
||||
for (json::iterator it = j.begin(); it != j.end(); ++it)
|
||||
{
|
||||
std::cout << *it << '\n';
|
||||
}
|
||||
|
||||
// range-based for
|
||||
for (auto element : j)
|
||||
{
|
||||
std::cout << element << '\n';
|
||||
}
|
||||
|
||||
// getter/setter
|
||||
const std::string tmp = j[0];
|
||||
j[1] = 42;
|
||||
bool foo = j.at(2);
|
||||
|
||||
// other stuff
|
||||
j.size(); // 3 entries
|
||||
j.empty(); // false
|
||||
j.type(); // json::value_t::array
|
||||
j.clear(); // the array is empty again
|
||||
|
||||
// comparison
|
||||
j == "[\"foo\", 1, true]"_json; // true
|
||||
|
||||
// create an object
|
||||
json o;
|
||||
o["foo"] = 23;
|
||||
o["bar"] = false;
|
||||
o["baz"] = 3.141;
|
||||
|
||||
// find an entry
|
||||
if (o.find("foo") != o.end())
|
||||
{
|
||||
// there is an entry with key "foo"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> c_vector {1, 2, 3, 4};
|
||||
json j_vec(c_vector);
|
||||
// [1, 2, 3, 4]
|
||||
|
||||
std::deque<float> c_deque {1.2f, 2.3f, 3.4f, 5.6f};
|
||||
json j_deque(c_deque);
|
||||
// [1.2, 2.3, 3.4, 5.6]
|
||||
|
||||
std::list<bool> c_list {true, true, false, true};
|
||||
json j_list(c_list);
|
||||
// [true, true, false, true]
|
||||
|
||||
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
|
||||
json j_flist(c_flist);
|
||||
// [12345678909876, 23456789098765, 34567890987654, 45678909876543]
|
||||
|
||||
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
|
||||
json j_array(c_array);
|
||||
// [1, 2, 3, 4]
|
||||
|
||||
std::set<std::string> c_set {"one", "two", "three", "four", "one"};
|
||||
json j_set(c_set); // only one entry for "one" is used
|
||||
// ["four", "one", "three", "two"]
|
||||
|
||||
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
|
||||
json j_uset(c_uset); // only one entry for "one" is used
|
||||
// maybe ["two", "three", "four", "one"]
|
||||
|
||||
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
|
||||
json j_mset(c_mset); // both entries for "one" are used
|
||||
// maybe ["one", "two", "one", "four"]
|
||||
|
||||
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
|
||||
json j_umset(c_umset); // both entries for "one" are used
|
||||
// maybe ["one", "two", "one", "four"]
|
||||
}
|
||||
|
||||
{
|
||||
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
|
||||
json j_map(c_map);
|
||||
// {"one": 1, "two": 2, "three": 3}
|
||||
|
||||
std::unordered_map<const char*, float> c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} };
|
||||
json j_umap(c_umap);
|
||||
// {"one": 1.2, "two": 2.3, "three": 3.4}
|
||||
|
||||
std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
||||
json j_mmap(c_mmap); // only one entry for key "three" is used
|
||||
// maybe {"one": true, "two": true, "three": true}
|
||||
|
||||
std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
||||
json j_ummap(c_ummap); // only one entry for key "three" is used
|
||||
// maybe {"one": true, "two": true, "three": true}
|
||||
}
|
||||
|
||||
{
|
||||
// strings
|
||||
std::string s1 = "Hello, world!";
|
||||
json js = s1;
|
||||
std::string s2 = js;
|
||||
|
||||
// Booleans
|
||||
bool b1 = true;
|
||||
json jb = b1;
|
||||
bool b2 = jb;
|
||||
|
||||
// numbers
|
||||
int i = 42;
|
||||
json jn = i;
|
||||
double f = jn;
|
||||
|
||||
// etc.
|
||||
|
||||
std::string vs = js.get<std::string>();
|
||||
bool vb = jb.get<bool>();
|
||||
int vi = jn.get<int>();
|
||||
|
||||
// etc.
|
||||
}
|
||||
|
||||
{
|
||||
// a JSON value
|
||||
json j_original = R"({
|
||||
"baz": ["one", "two", "three"],
|
||||
"foo": "bar"
|
||||
})"_json;
|
||||
|
||||
// access members with a JSON pointer (RFC 6901)
|
||||
j_original["/baz/1"_json_pointer];
|
||||
// "two"
|
||||
|
||||
// a JSON patch (RFC 6902)
|
||||
json j_patch = R"([
|
||||
{ "op": "replace", "path": "/baz", "value": "boo" },
|
||||
{ "op": "add", "path": "/hello", "value": ["world"] },
|
||||
{ "op": "remove", "path": "/foo"}
|
||||
])"_json;
|
||||
|
||||
// apply the patch
|
||||
json j_result = j_original.patch(j_patch);
|
||||
// {
|
||||
// "baz": "boo",
|
||||
// "hello": ["world"]
|
||||
// }
|
||||
|
||||
// calculate a JSON patch from two JSON values
|
||||
json::diff(j_result, j_original);
|
||||
// [
|
||||
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
|
||||
// { "op":"remove","path":"/hello" },
|
||||
// { "op":"add","path":"/foo","value":"bar" }
|
||||
// ]
|
||||
}
|
||||
|
||||
// restore old std::cout
|
||||
std::cout.rdbuf(old_cout_buffer);
|
||||
}
|
||||
}
|
||||
202
test/src/unit-reference_access.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("reference access")
|
||||
{
|
||||
// create a JSON value with different types
|
||||
json json_types =
|
||||
{
|
||||
{"boolean", true},
|
||||
{
|
||||
"number", {
|
||||
{"integer", 42},
|
||||
{"floating-point", 17.23}
|
||||
}
|
||||
},
|
||||
{"string", "Hello, world!"},
|
||||
{"array", {1, 2, 3, 4, 5}},
|
||||
{"null", nullptr}
|
||||
};
|
||||
|
||||
SECTION("reference access to object_t")
|
||||
{
|
||||
using test_type = json::object_t;
|
||||
json value = {{"one", 1}, {"two", 2}};
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_NOTHROW(value.get_ref<json::object_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
|
||||
SECTION("const reference access to const object_t")
|
||||
{
|
||||
using test_type = json::object_t;
|
||||
const json value = {{"one", 1}, {"two", 2}};
|
||||
|
||||
// this should not compile
|
||||
// test_type& p1 = value.get_ref<test_type&>();
|
||||
|
||||
// check if references are returned correctly
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
}
|
||||
|
||||
SECTION("reference access to array_t")
|
||||
{
|
||||
using test_type = json::array_t;
|
||||
json value = {1, 2, 3, 4};
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_THROWS(value.get_ref<json::object_t&>());
|
||||
CHECK_NOTHROW(value.get_ref<json::array_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
|
||||
SECTION("reference access to string_t")
|
||||
{
|
||||
using test_type = json::string_t;
|
||||
json value = "hello";
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_THROWS(value.get_ref<json::object_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||
CHECK_NOTHROW(value.get_ref<json::string_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
|
||||
SECTION("reference access to boolean_t")
|
||||
{
|
||||
using test_type = json::boolean_t;
|
||||
json value = false;
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_THROWS(value.get_ref<json::object_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||
CHECK_NOTHROW(value.get_ref<json::boolean_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
|
||||
SECTION("reference access to number_integer_t")
|
||||
{
|
||||
using test_type = json::number_integer_t;
|
||||
json value = 23;
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_THROWS(value.get_ref<json::object_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||
CHECK_NOTHROW(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
|
||||
SECTION("reference access to number_float_t")
|
||||
{
|
||||
using test_type = json::number_float_t;
|
||||
json value = 42.23;
|
||||
|
||||
// check if references are returned correctly
|
||||
test_type& p1 = value.get_ref<test_type&>();
|
||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||
CHECK(p1 == value.get<test_type>());
|
||||
|
||||
const test_type& p2 = value.get_ref<const test_type&>();
|
||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||
CHECK(p2 == value.get<test_type>());
|
||||
|
||||
// check if mismatching references throw correctly
|
||||
CHECK_THROWS(value.get_ref<json::object_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||
CHECK_THROWS(value.get_ref<json::number_integer_t&>());
|
||||
CHECK_NOTHROW(value.get_ref<json::number_float_t&>());
|
||||
}
|
||||
}
|
||||
492
test/src/unit-regression.cpp
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <fstream>
|
||||
|
||||
TEST_CASE("regression tests")
|
||||
{
|
||||
SECTION("issue #60 - Double quotation mark is not parsed correctly")
|
||||
{
|
||||
SECTION("escape_dobulequote")
|
||||
{
|
||||
auto s = "[\"\\\"foo\\\"\"]";
|
||||
json j = json::parse(s);
|
||||
auto expected = R"(["\"foo\""])"_json;
|
||||
CHECK(j == expected);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("issue #70 - Handle infinity and NaN cases")
|
||||
{
|
||||
SECTION("NAN value")
|
||||
{
|
||||
CHECK(json(NAN) == json());
|
||||
CHECK(json(json::number_float_t(NAN)) == json());
|
||||
}
|
||||
|
||||
SECTION("infinity")
|
||||
{
|
||||
CHECK(json(INFINITY) == json());
|
||||
CHECK(json(json::number_float_t(INFINITY)) == json());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("pull request #71 - handle enum type")
|
||||
{
|
||||
enum { t = 0 };
|
||||
json j = json::array();
|
||||
j.push_back(t);
|
||||
|
||||
j.push_back(json::object(
|
||||
{
|
||||
{"game_type", t}
|
||||
}));
|
||||
}
|
||||
|
||||
SECTION("issue #76 - dump() / parse() not idempotent")
|
||||
{
|
||||
// create JSON object
|
||||
json fields;
|
||||
fields["one"] = std::string("one");
|
||||
fields["two"] = std::string("two three");
|
||||
fields["three"] = std::string("three \"four\"");
|
||||
|
||||
// create another JSON object by deserializing the serialization
|
||||
std::string payload = fields.dump();
|
||||
json parsed_fields = json::parse(payload);
|
||||
|
||||
// check individual fields to match both objects
|
||||
CHECK(parsed_fields["one"] == fields["one"]);
|
||||
CHECK(parsed_fields["two"] == fields["two"]);
|
||||
CHECK(parsed_fields["three"] == fields["three"]);
|
||||
|
||||
// check individual fields to match original input
|
||||
CHECK(parsed_fields["one"] == std::string("one"));
|
||||
CHECK(parsed_fields["two"] == std::string("two three"));
|
||||
CHECK(parsed_fields["three"] == std::string("three \"four\""));
|
||||
|
||||
// check equality of the objects
|
||||
CHECK(parsed_fields == fields);
|
||||
|
||||
// check equality of the serialized objects
|
||||
CHECK(fields.dump() == parsed_fields.dump());
|
||||
|
||||
// check everything in one line
|
||||
CHECK(fields == json::parse(fields.dump()));
|
||||
}
|
||||
|
||||
SECTION("issue #82 - lexer::get_number return NAN")
|
||||
{
|
||||
const auto content = R"(
|
||||
{
|
||||
"Test":"Test1",
|
||||
"Number":100,
|
||||
"Foo":42.42
|
||||
})";
|
||||
|
||||
std::stringstream ss;
|
||||
ss << content;
|
||||
json j;
|
||||
ss >> j;
|
||||
|
||||
std::string test = j["Test"];
|
||||
CHECK(test == "Test1");
|
||||
int number = j["Number"];
|
||||
CHECK(number == 100);
|
||||
float foo = j["Foo"];
|
||||
CHECK(foo == Approx(42.42));
|
||||
}
|
||||
|
||||
SECTION("issue #89 - nonstandard integer type")
|
||||
{
|
||||
// create JSON class with nonstandard integer number type
|
||||
using custom_json =
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
|
||||
custom_json j;
|
||||
j["int_1"] = 1;
|
||||
// we need to cast to int to compile with Catch - the value is int32_t
|
||||
CHECK(static_cast<int>(j["int_1"]) == 1);
|
||||
|
||||
// tests for correct handling of non-standard integers that overflow the type selected by the user
|
||||
|
||||
// unsigned integer object creation - expected to wrap and still be stored as an integer
|
||||
j = 4294967296U; // 2^32
|
||||
CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
|
||||
CHECK(j.get<uint32_t>() == 0); // Wrap
|
||||
|
||||
// unsigned integer parsing - expected to overflow and be stored as a float
|
||||
j = custom_json::parse("4294967296"); // 2^32
|
||||
CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
|
||||
CHECK(j.get<float>() == 4294967296.0f);
|
||||
|
||||
// integer object creation - expected to wrap and still be stored as an integer
|
||||
j = -2147483649LL; // -2^31-1
|
||||
CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
|
||||
CHECK(j.get<int32_t>() == 2147483647); // Wrap
|
||||
|
||||
// integer parsing - expected to overflow and be stored as a float with rounding
|
||||
j = custom_json::parse("-2147483649"); // -2^31
|
||||
CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
|
||||
CHECK(j.get<float>() == -2147483650.0f);
|
||||
}
|
||||
|
||||
SECTION("issue #93 reverse_iterator operator inheritance problem")
|
||||
{
|
||||
{
|
||||
json a = {1, 2, 3};
|
||||
json::reverse_iterator rit = a.rbegin();
|
||||
++rit;
|
||||
CHECK(*rit == json(2));
|
||||
CHECK(rit.value() == json(2));
|
||||
}
|
||||
{
|
||||
json a = {1, 2, 3};
|
||||
json::reverse_iterator rit = ++a.rbegin();
|
||||
}
|
||||
{
|
||||
json a = {1, 2, 3};
|
||||
json::reverse_iterator rit = a.rbegin();
|
||||
++rit;
|
||||
json b = {0, 0, 0};
|
||||
std::transform(rit, a.rend(), b.rbegin(), [](json el)
|
||||
{
|
||||
return el;
|
||||
});
|
||||
CHECK(b == json({0, 1, 2}));
|
||||
}
|
||||
{
|
||||
json a = {1, 2, 3};
|
||||
json b = {0, 0, 0};
|
||||
std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el)
|
||||
{
|
||||
return el;
|
||||
});
|
||||
CHECK(b == json({0, 1, 2}));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("issue #100 - failed to iterator json object with reverse_iterator")
|
||||
{
|
||||
json config =
|
||||
{
|
||||
{ "111", 111 },
|
||||
{ "112", 112 },
|
||||
{ "113", 113 }
|
||||
};
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
for (auto it = config.begin(); it != config.end(); ++it)
|
||||
{
|
||||
ss << it.key() << ": " << it.value() << '\n';
|
||||
}
|
||||
|
||||
for (auto it = config.rbegin(); it != config.rend(); ++it)
|
||||
{
|
||||
ss << it.key() << ": " << it.value() << '\n';
|
||||
}
|
||||
|
||||
CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n");
|
||||
}
|
||||
|
||||
SECTION("issue #101 - binary string causes numbers to be dumped as hex")
|
||||
{
|
||||
int64_t number = 10;
|
||||
std::string bytes{"\x00" "asdf\n", 6};
|
||||
json j;
|
||||
j["int64"] = number;
|
||||
j["binary string"] = bytes;
|
||||
// make sure the number is really printed as decimal "10" and not as
|
||||
// hexadecimal "a"
|
||||
CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}");
|
||||
}
|
||||
|
||||
SECTION("issue #111 - subsequent unicode chars")
|
||||
{
|
||||
std::string bytes{0x7, 0x7};
|
||||
json j;
|
||||
j["string"] = bytes;
|
||||
CHECK(j["string"] == "\u0007\u0007");
|
||||
}
|
||||
|
||||
SECTION("issue #144 - implicit assignment to std::string fails")
|
||||
{
|
||||
json o = {{"name", "value"}};
|
||||
|
||||
std::string s1 = o["name"];
|
||||
CHECK(s1 == "value");
|
||||
|
||||
std::string s2;
|
||||
s2 = o["name"];
|
||||
|
||||
CHECK(s2 == "value");
|
||||
}
|
||||
|
||||
SECTION("issue #146 - character following a surrogate pair is skipped")
|
||||
{
|
||||
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
|
||||
}
|
||||
|
||||
SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
|
||||
{
|
||||
json j;
|
||||
|
||||
// Non-const access with key as "char []"
|
||||
char array_key[] = "Key1";
|
||||
CHECK_NOTHROW(j[array_key] = 1);
|
||||
CHECK(j[array_key] == json(1));
|
||||
|
||||
// Non-const access with key as "const char[]"
|
||||
const char const_array_key[] = "Key2";
|
||||
CHECK_NOTHROW(j[const_array_key] = 2);
|
||||
CHECK(j[const_array_key] == json(2));
|
||||
|
||||
// Non-const access with key as "char *"
|
||||
char _ptr_key[] = "Key3";
|
||||
char* ptr_key = &_ptr_key[0];
|
||||
CHECK_NOTHROW(j[ptr_key] = 3);
|
||||
CHECK(j[ptr_key] == json(3));
|
||||
|
||||
// Non-const access with key as "const char *"
|
||||
const char* const_ptr_key = "Key4";
|
||||
CHECK_NOTHROW(j[const_ptr_key] = 4);
|
||||
CHECK(j[const_ptr_key] == json(4));
|
||||
|
||||
// Non-const access with key as "static constexpr const char *"
|
||||
static constexpr const char* constexpr_ptr_key = "Key5";
|
||||
CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
|
||||
CHECK(j[constexpr_ptr_key] == json(5));
|
||||
|
||||
const json j_const = j;
|
||||
|
||||
// Const access with key as "char []"
|
||||
CHECK(j_const[array_key] == json(1));
|
||||
|
||||
// Const access with key as "const char[]"
|
||||
CHECK(j_const[const_array_key] == json(2));
|
||||
|
||||
// Const access with key as "char *"
|
||||
CHECK(j_const[ptr_key] == json(3));
|
||||
|
||||
// Const access with key as "const char *"
|
||||
CHECK(j_const[const_ptr_key] == json(4));
|
||||
|
||||
// Const access with key as "static constexpr const char *"
|
||||
CHECK(j_const[constexpr_ptr_key] == json(5));
|
||||
}
|
||||
|
||||
SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
|
||||
{
|
||||
json j;
|
||||
|
||||
j = json::parse("-0.0");
|
||||
CHECK(j.get<double>() == -0.0);
|
||||
|
||||
j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
|
||||
CHECK(j.get<double>() == 2.2250738585072009e-308);
|
||||
|
||||
j = json::parse("0.999999999999999944488848768742172978818416595458984374");
|
||||
CHECK(j.get<double>() == 0.99999999999999989);
|
||||
|
||||
j = json::parse("1.00000000000000011102230246251565404236316680908203126");
|
||||
CHECK(j.get<double>() == 1.00000000000000022);
|
||||
|
||||
j = json::parse("7205759403792793199999e-5");
|
||||
CHECK(j.get<double>() == 72057594037927928.0);
|
||||
|
||||
j = json::parse("922337203685477529599999e-5");
|
||||
CHECK(j.get<double>() == 9223372036854774784.0);
|
||||
|
||||
j = json::parse("1014120480182583464902367222169599999e-5");
|
||||
CHECK(j.get<double>() == 10141204801825834086073718800384.0);
|
||||
|
||||
j = json::parse("5708990770823839207320493820740630171355185151999e-3");
|
||||
CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);
|
||||
|
||||
// create JSON class with nonstandard float number type
|
||||
|
||||
// float
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float =
|
||||
1.23e25f;
|
||||
CHECK(j_float.get<float>() == 1.23e25f);
|
||||
|
||||
// double
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double =
|
||||
1.23e35f;
|
||||
CHECK(j_double.get<double>() == 1.23e35f);
|
||||
|
||||
// long double
|
||||
nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
|
||||
j_long_double = 1.23e45L;
|
||||
CHECK(j_long_double.get<long double>() == 1.23e45L);
|
||||
}
|
||||
|
||||
SECTION("issue #228 - double values are serialized with commas as decimal points")
|
||||
{
|
||||
json j1a = 23.42;
|
||||
json j1b = json::parse("23.42");
|
||||
|
||||
json j2a = 2342e-2;
|
||||
//issue #230
|
||||
//json j2b = json::parse("2342e-2");
|
||||
|
||||
json j3a = 10E3;
|
||||
json j3b = json::parse("10E3");
|
||||
json j3c = json::parse("10e3");
|
||||
|
||||
// class to create a locale that would use a comma for decimals
|
||||
class CommaDecimalSeparator : public std::numpunct<char>
|
||||
{
|
||||
protected:
|
||||
char do_decimal_point() const
|
||||
{
|
||||
return ',';
|
||||
}
|
||||
};
|
||||
|
||||
// change locale to mess with decimal points
|
||||
std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator));
|
||||
|
||||
CHECK(j1a.dump() == "23.42");
|
||||
CHECK(j1b.dump() == "23.42");
|
||||
|
||||
// check if locale is properly reset
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator));
|
||||
ss << 47.11;
|
||||
CHECK(ss.str() == "47,11");
|
||||
ss << j1a;
|
||||
CHECK(ss.str() == "47,1123.42");
|
||||
ss << 47.11;
|
||||
CHECK(ss.str() == "47,1123.4247,11");
|
||||
|
||||
CHECK(j2a.dump() == "23.42");
|
||||
//issue #230
|
||||
//CHECK(j2b.dump() == "23.42");
|
||||
|
||||
CHECK(j3a.dump() == "10000");
|
||||
CHECK(j3b.dump() == "10000");
|
||||
CHECK(j3c.dump() == "10000");
|
||||
//CHECK(j3b.dump() == "1E04"); // roundtrip error
|
||||
//CHECK(j3c.dump() == "1e04"); // roundtrip error
|
||||
}
|
||||
|
||||
SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
|
||||
{
|
||||
json source = {"a", "b", "c"};
|
||||
json expected = {"a", "b"};
|
||||
json dest;
|
||||
|
||||
std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest));
|
||||
|
||||
CHECK(dest == expected);
|
||||
}
|
||||
|
||||
SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
|
||||
{
|
||||
json data = {{"key", "value"}};
|
||||
data.push_back({"key2", "value2"});
|
||||
data += {"key3", "value3"};
|
||||
|
||||
CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
|
||||
}
|
||||
|
||||
SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
|
||||
{
|
||||
json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
|
||||
json expected = R"( { "arr1": [1, 2] } )"_json;
|
||||
|
||||
// check roundtrip
|
||||
CHECK(doc.patch(json::diff(doc, expected)) == expected);
|
||||
}
|
||||
|
||||
SECTION("issue #283 - value() does not work with _json_pointer types")
|
||||
{
|
||||
json j =
|
||||
{
|
||||
{"object", {{"key1", 1}, {"key2", 2}}},
|
||||
};
|
||||
|
||||
int at_integer = j.at("/object/key2"_json_pointer);
|
||||
int val_integer = j.value("/object/key2"_json_pointer, 0);
|
||||
|
||||
CHECK(at_integer == val_integer);
|
||||
}
|
||||
|
||||
SECTION("issue #304 - Unused variable warning")
|
||||
{
|
||||
// code triggered a "warning: unused variable" warning and is left
|
||||
// here to avoid the warning in the future
|
||||
json object;
|
||||
json patch = json::array();
|
||||
object = object.patch(patch);
|
||||
}
|
||||
|
||||
SECTION("issue #306 - Parsing fails without space at end of file")
|
||||
{
|
||||
for (auto filename :
|
||||
{
|
||||
"test/data/regression/broken_file.json",
|
||||
"test/data/regression/working_file.json"
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
json j;
|
||||
std::ifstream f(filename);
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("issue #310 - make json_benchmarks no longer working in 2.0.4")
|
||||
{
|
||||
for (auto filename :
|
||||
{
|
||||
"test/data/regression/floats.json",
|
||||
"test/data/regression/signed_ints.json",
|
||||
"test/data/regression/unsigned_ints.json"
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
json j;
|
||||
std::ifstream f(filename);
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("issue #323 - add nested object capabilities to pointers")
|
||||
{
|
||||
json j;
|
||||
j["/this/that/2"_json_pointer] = 27;
|
||||
CHECK(j == json({{"this", {{"that", {nullptr, nullptr, 27}}}}}));
|
||||
}
|
||||
}
|
||||
76
test/src/unit-serialization.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
TEST_CASE("serialization")
|
||||
{
|
||||
SECTION("operator<<")
|
||||
{
|
||||
SECTION("no given width")
|
||||
{
|
||||
std::stringstream ss;
|
||||
json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
|
||||
ss << j;
|
||||
CHECK(ss.str() == "[\"foo\",1,2,3,false,{\"one\":1}]");
|
||||
}
|
||||
|
||||
SECTION("given width")
|
||||
{
|
||||
std::stringstream ss;
|
||||
json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
|
||||
ss << std::setw(4) << j;
|
||||
CHECK(ss.str() ==
|
||||
"[\n \"foo\",\n 1,\n 2,\n 3,\n false,\n {\n \"one\": 1\n }\n]");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("operator>>")
|
||||
{
|
||||
SECTION("no given width")
|
||||
{
|
||||
std::stringstream ss;
|
||||
json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
|
||||
j >> ss;
|
||||
CHECK(ss.str() == "[\"foo\",1,2,3,false,{\"one\":1}]");
|
||||
}
|
||||
|
||||
SECTION("given width")
|
||||
{
|
||||
std::stringstream ss;
|
||||
json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
|
||||
ss.width(4);
|
||||
j >> ss;
|
||||
CHECK(ss.str() ==
|
||||
"[\n \"foo\",\n 1,\n 2,\n 3,\n false,\n {\n \"one\": 1\n }\n]");
|
||||
}
|
||||
}
|
||||
}
|
||||
436
test/src/unit-testsuites.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <fstream>
|
||||
|
||||
TEST_CASE("compliance tests from json.org")
|
||||
{
|
||||
// test cases are from http://json.org/JSON_checker/
|
||||
|
||||
SECTION("expected failures")
|
||||
{
|
||||
for (auto filename :
|
||||
{
|
||||
//"test/data/json_tests/fail1.json",
|
||||
"test/data/json_tests/fail2.json",
|
||||
"test/data/json_tests/fail3.json",
|
||||
"test/data/json_tests/fail4.json",
|
||||
"test/data/json_tests/fail5.json",
|
||||
"test/data/json_tests/fail6.json",
|
||||
"test/data/json_tests/fail7.json",
|
||||
"test/data/json_tests/fail8.json",
|
||||
"test/data/json_tests/fail9.json",
|
||||
"test/data/json_tests/fail10.json",
|
||||
"test/data/json_tests/fail11.json",
|
||||
"test/data/json_tests/fail12.json",
|
||||
"test/data/json_tests/fail13.json",
|
||||
"test/data/json_tests/fail14.json",
|
||||
"test/data/json_tests/fail15.json",
|
||||
"test/data/json_tests/fail16.json",
|
||||
"test/data/json_tests/fail17.json",
|
||||
//"test/data/json_tests/fail18.json",
|
||||
"test/data/json_tests/fail19.json",
|
||||
"test/data/json_tests/fail20.json",
|
||||
"test/data/json_tests/fail21.json",
|
||||
"test/data/json_tests/fail22.json",
|
||||
"test/data/json_tests/fail23.json",
|
||||
"test/data/json_tests/fail24.json",
|
||||
"test/data/json_tests/fail25.json",
|
||||
"test/data/json_tests/fail26.json",
|
||||
"test/data/json_tests/fail27.json",
|
||||
"test/data/json_tests/fail28.json",
|
||||
"test/data/json_tests/fail29.json",
|
||||
"test/data/json_tests/fail30.json",
|
||||
"test/data/json_tests/fail31.json",
|
||||
"test/data/json_tests/fail32.json",
|
||||
"test/data/json_tests/fail33.json"
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
json j;
|
||||
std::ifstream f(filename);
|
||||
CHECK_THROWS_AS(j << f, std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("expected passes")
|
||||
{
|
||||
for (auto filename :
|
||||
{
|
||||
"test/data/json_tests/pass1.json",
|
||||
"test/data/json_tests/pass2.json",
|
||||
"test/data/json_tests/pass3.json"
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
json j;
|
||||
std::ifstream f(filename);
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("compliance tests from nativejson-benchmark")
|
||||
{
|
||||
// test cases from https://github.com/miloyip/nativejson-benchmark/blob/master/src/main.cpp
|
||||
|
||||
SECTION("doubles")
|
||||
{
|
||||
auto TEST_DOUBLE = [](const std::string & json_string, const double expected)
|
||||
{
|
||||
CAPTURE(json_string);
|
||||
CAPTURE(expected);
|
||||
CHECK(json::parse(json_string)[0].get<double>() == Approx(expected));
|
||||
};
|
||||
|
||||
TEST_DOUBLE("[0.0]", 0.0);
|
||||
TEST_DOUBLE("[-0.0]", -0.0);
|
||||
TEST_DOUBLE("[1.0]", 1.0);
|
||||
TEST_DOUBLE("[-1.0]", -1.0);
|
||||
TEST_DOUBLE("[1.5]", 1.5);
|
||||
TEST_DOUBLE("[-1.5]", -1.5);
|
||||
TEST_DOUBLE("[3.1416]", 3.1416);
|
||||
TEST_DOUBLE("[1E10]", 1E10);
|
||||
TEST_DOUBLE("[1e10]", 1e10);
|
||||
TEST_DOUBLE("[1E+10]", 1E+10);
|
||||
TEST_DOUBLE("[1E-10]", 1E-10);
|
||||
TEST_DOUBLE("[-1E10]", -1E10);
|
||||
TEST_DOUBLE("[-1e10]", -1e10);
|
||||
TEST_DOUBLE("[-1E+10]", -1E+10);
|
||||
TEST_DOUBLE("[-1E-10]", -1E-10);
|
||||
TEST_DOUBLE("[1.234E+10]", 1.234E+10);
|
||||
TEST_DOUBLE("[1.234E-10]", 1.234E-10);
|
||||
TEST_DOUBLE("[1.79769e+308]", 1.79769e+308);
|
||||
TEST_DOUBLE("[2.22507e-308]", 2.22507e-308);
|
||||
TEST_DOUBLE("[-1.79769e+308]", -1.79769e+308);
|
||||
TEST_DOUBLE("[-2.22507e-308]", -2.22507e-308);
|
||||
TEST_DOUBLE("[4.9406564584124654e-324]", 4.9406564584124654e-324); // minimum denormal
|
||||
TEST_DOUBLE("[2.2250738585072009e-308]", 2.2250738585072009e-308); // Max subnormal double
|
||||
TEST_DOUBLE("[2.2250738585072014e-308]", 2.2250738585072014e-308); // Min normal positive double
|
||||
TEST_DOUBLE("[1.7976931348623157e+308]", 1.7976931348623157e+308); // Max double
|
||||
TEST_DOUBLE("[1e-10000]", 0.0); // must underflow
|
||||
TEST_DOUBLE("[18446744073709551616]",
|
||||
18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double)
|
||||
TEST_DOUBLE("[-9223372036854775809]",
|
||||
-9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double)
|
||||
TEST_DOUBLE("[0.9868011474609375]",
|
||||
0.9868011474609375); // https://github.com/miloyip/rapidjson/issues/120
|
||||
TEST_DOUBLE("[123e34]", 123e34); // Fast Path Cases In Disguise
|
||||
TEST_DOUBLE("[45913141877270640000.0]", 45913141877270640000.0);
|
||||
TEST_DOUBLE("[2.2250738585072011e-308]",
|
||||
2.2250738585072011e-308);
|
||||
//TEST_DOUBLE("[1e-00011111111111]", 0.0);
|
||||
//TEST_DOUBLE("[-1e-00011111111111]", -0.0);
|
||||
TEST_DOUBLE("[1e-214748363]", 0.0);
|
||||
TEST_DOUBLE("[1e-214748364]", 0.0);
|
||||
//TEST_DOUBLE("[1e-21474836311]", 0.0);
|
||||
TEST_DOUBLE("[0.017976931348623157e+310]", 1.7976931348623157e+308); // Max double in another form
|
||||
|
||||
// Since
|
||||
// abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
|
||||
// abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... ¡Á 10 ^ -324
|
||||
// So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308
|
||||
TEST_DOUBLE("[2.2250738585072012e-308]",
|
||||
2.2250738585072014e-308);
|
||||
|
||||
// More closer to normal/subnormal boundary
|
||||
// boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308
|
||||
TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164564e-308]",
|
||||
2.2250738585072009e-308);
|
||||
TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164565e-308]",
|
||||
2.2250738585072014e-308);
|
||||
|
||||
// 1.0 is in (1.0 - 2^-54, 1.0 + 2^-53)
|
||||
// 1.0 - 2^-54 = 0.999999999999999944488848768742172978818416595458984375
|
||||
TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984375]", 1.0); // round to even
|
||||
TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984374]",
|
||||
0.99999999999999989); // previous double
|
||||
TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984376]", 1.0); // next double
|
||||
// 1.0 + 2^-53 = 1.00000000000000011102230246251565404236316680908203125
|
||||
TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203125]", 1.0); // round to even
|
||||
TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203124]", 1.0); // previous double
|
||||
TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203126]",
|
||||
1.00000000000000022); // next double
|
||||
|
||||
// Numbers from https://github.com/floitsch/double-conversion/blob/master/test/cctest/test-strtod.cc
|
||||
|
||||
TEST_DOUBLE("[72057594037927928.0]", 72057594037927928.0);
|
||||
TEST_DOUBLE("[72057594037927936.0]", 72057594037927936.0);
|
||||
TEST_DOUBLE("[72057594037927932.0]", 72057594037927936.0);
|
||||
TEST_DOUBLE("[7205759403792793199999e-5]", 72057594037927928.0);
|
||||
TEST_DOUBLE("[7205759403792793200001e-5]", 72057594037927936.0);
|
||||
|
||||
TEST_DOUBLE("[9223372036854774784.0]", 9223372036854774784.0);
|
||||
TEST_DOUBLE("[9223372036854775808.0]", 9223372036854775808.0);
|
||||
TEST_DOUBLE("[9223372036854775296.0]", 9223372036854775808.0);
|
||||
TEST_DOUBLE("[922337203685477529599999e-5]", 9223372036854774784.0);
|
||||
TEST_DOUBLE("[922337203685477529600001e-5]", 9223372036854775808.0);
|
||||
|
||||
TEST_DOUBLE("[10141204801825834086073718800384]", 10141204801825834086073718800384.0);
|
||||
TEST_DOUBLE("[10141204801825835211973625643008]", 10141204801825835211973625643008.0);
|
||||
TEST_DOUBLE("[10141204801825834649023672221696]", 10141204801825835211973625643008.0);
|
||||
TEST_DOUBLE("[1014120480182583464902367222169599999e-5]", 10141204801825834086073718800384.0);
|
||||
TEST_DOUBLE("[1014120480182583464902367222169600001e-5]", 10141204801825835211973625643008.0);
|
||||
|
||||
TEST_DOUBLE("[5708990770823838890407843763683279797179383808]",
|
||||
5708990770823838890407843763683279797179383808.0);
|
||||
TEST_DOUBLE("[5708990770823839524233143877797980545530986496]",
|
||||
5708990770823839524233143877797980545530986496.0);
|
||||
TEST_DOUBLE("[5708990770823839207320493820740630171355185152]",
|
||||
5708990770823839524233143877797980545530986496.0);
|
||||
TEST_DOUBLE("[5708990770823839207320493820740630171355185151999e-3]",
|
||||
5708990770823838890407843763683279797179383808.0);
|
||||
TEST_DOUBLE("[5708990770823839207320493820740630171355185152001e-3]",
|
||||
5708990770823839524233143877797980545530986496.0);
|
||||
|
||||
{
|
||||
char n1e308[312]; // '1' followed by 308 '0'
|
||||
n1e308[0] = '[';
|
||||
n1e308[1] = '1';
|
||||
for (int j = 2; j < 310; j++)
|
||||
{
|
||||
n1e308[j] = '0';
|
||||
}
|
||||
n1e308[310] = ']';
|
||||
n1e308[311] = '\0';
|
||||
TEST_DOUBLE(n1e308, 1E308);
|
||||
}
|
||||
|
||||
// Cover trimming
|
||||
TEST_DOUBLE(
|
||||
"[2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
|
||||
"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
|
||||
"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
|
||||
"6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505"
|
||||
"1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621"
|
||||
"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
|
||||
"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
|
||||
"7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
|
||||
"e-308]",
|
||||
2.2250738585072014e-308);
|
||||
}
|
||||
|
||||
SECTION("strings")
|
||||
{
|
||||
auto TEST_STRING = [](const std::string & json_string, const std::string & expected)
|
||||
{
|
||||
CAPTURE(json_string);
|
||||
CAPTURE(expected);
|
||||
CHECK(json::parse(json_string)[0].get<std::string>() == expected);
|
||||
};
|
||||
|
||||
TEST_STRING("[\"\"]", "");
|
||||
TEST_STRING("[\"Hello\"]", "Hello");
|
||||
TEST_STRING("[\"Hello\\nWorld\"]", "Hello\nWorld");
|
||||
//TEST_STRING("[\"Hello\\u0000World\"]", "Hello\0World");
|
||||
TEST_STRING("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]", "\"\\/\b\f\n\r\t");
|
||||
TEST_STRING("[\"\\u0024\"]", "\x24"); // Dollar sign U+0024
|
||||
TEST_STRING("[\"\\u00A2\"]", "\xC2\xA2"); // Cents sign U+00A2
|
||||
TEST_STRING("[\"\\u20AC\"]", "\xE2\x82\xAC"); // Euro sign U+20AC
|
||||
TEST_STRING("[\"\\uD834\\uDD1E\"]", "\xF0\x9D\x84\x9E"); // G clef sign U+1D11E
|
||||
}
|
||||
|
||||
SECTION("roundtrip")
|
||||
{
|
||||
// test cases are from https://github.com/miloyip/nativejson-benchmark/tree/master/test/data/roundtrip
|
||||
|
||||
for (auto filename :
|
||||
{
|
||||
"test/data/json_roundtrip/roundtrip01.json",
|
||||
"test/data/json_roundtrip/roundtrip02.json",
|
||||
"test/data/json_roundtrip/roundtrip03.json",
|
||||
"test/data/json_roundtrip/roundtrip04.json",
|
||||
"test/data/json_roundtrip/roundtrip05.json",
|
||||
"test/data/json_roundtrip/roundtrip06.json",
|
||||
"test/data/json_roundtrip/roundtrip07.json",
|
||||
"test/data/json_roundtrip/roundtrip08.json",
|
||||
"test/data/json_roundtrip/roundtrip09.json",
|
||||
"test/data/json_roundtrip/roundtrip10.json",
|
||||
"test/data/json_roundtrip/roundtrip11.json",
|
||||
"test/data/json_roundtrip/roundtrip12.json",
|
||||
"test/data/json_roundtrip/roundtrip13.json",
|
||||
"test/data/json_roundtrip/roundtrip14.json",
|
||||
"test/data/json_roundtrip/roundtrip15.json",
|
||||
"test/data/json_roundtrip/roundtrip16.json",
|
||||
"test/data/json_roundtrip/roundtrip17.json",
|
||||
"test/data/json_roundtrip/roundtrip18.json",
|
||||
"test/data/json_roundtrip/roundtrip19.json",
|
||||
"test/data/json_roundtrip/roundtrip20.json",
|
||||
"test/data/json_roundtrip/roundtrip21.json",
|
||||
"test/data/json_roundtrip/roundtrip22.json",
|
||||
"test/data/json_roundtrip/roundtrip23.json",
|
||||
//"test/data/json_roundtrip/roundtrip24.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip25.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip26.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip27.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip28.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip29.json",
|
||||
//"test/data/json_roundtrip/roundtrip30.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip31.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip32.json"
|
||||
})
|
||||
{
|
||||
CAPTURE(filename);
|
||||
std::ifstream f(filename);
|
||||
std::string json_string( (std::istreambuf_iterator<char>(f) ),
|
||||
(std::istreambuf_iterator<char>()) );
|
||||
|
||||
json j = json::parse(json_string);
|
||||
CHECK(j.dump() == json_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("test suite from json-test-suite")
|
||||
{
|
||||
SECTION("read all sample.json")
|
||||
{
|
||||
// read a file with all unicode characters stored as single-character
|
||||
// strings in a JSON array
|
||||
std::ifstream f("test/data/json_testsuite/sample.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
|
||||
// the array has 3 elements
|
||||
CHECK(j.size() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("json.org examples")
|
||||
{
|
||||
// here, we list all JSON values from http://json.org/example
|
||||
|
||||
SECTION("1.json")
|
||||
{
|
||||
std::ifstream f("test/data/json.org/1.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
|
||||
SECTION("2.json")
|
||||
{
|
||||
std::ifstream f("test/data/json.org/2.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
|
||||
SECTION("3.json")
|
||||
{
|
||||
std::ifstream f("test/data/json.org/3.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
|
||||
SECTION("4.json")
|
||||
{
|
||||
std::ifstream f("test/data/json.org/4.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
|
||||
SECTION("5.json")
|
||||
{
|
||||
std::ifstream f("test/data/json.org/5.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("RFC 7159 examples")
|
||||
{
|
||||
// here, we list all JSON values from the RFC 7159 document
|
||||
|
||||
SECTION("7. Strings")
|
||||
{
|
||||
CHECK(json::parse("\"\\u005C\"") == json("\\"));
|
||||
CHECK(json::parse("\"\\uD834\\uDD1E\"") == json("𝄞"));
|
||||
CHECK(json::parse("\"𝄞\"") == json("𝄞"));
|
||||
}
|
||||
|
||||
SECTION("8.3 String Comparison")
|
||||
{
|
||||
CHECK(json::parse("\"a\\b\"") == json::parse("\"a\u005Cb\""));
|
||||
}
|
||||
|
||||
SECTION("13 Examples")
|
||||
{
|
||||
{
|
||||
CHECK_NOTHROW(json(R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": 100
|
||||
},
|
||||
"Animated" : false,
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
}
|
||||
}
|
||||
)"));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_NOTHROW(json(R"(
|
||||
[
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.7668,
|
||||
"Longitude": -122.3959,
|
||||
"Address": "",
|
||||
"City": "SAN FRANCISCO",
|
||||
"State": "CA",
|
||||
"Zip": "94107",
|
||||
"Country": "US"
|
||||
},
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.371991,
|
||||
"Longitude": -122.026020,
|
||||
"Address": "",
|
||||
"City": "SUNNYVALE",
|
||||
"State": "CA",
|
||||
"Zip": "94085",
|
||||
"Country": "US"
|
||||
}
|
||||
])"));
|
||||
}
|
||||
|
||||
CHECK(json::parse("\"Hello world!\"") == json("Hello world!"));
|
||||
CHECK(json::parse("42") == json(42));
|
||||
CHECK(json::parse("true") == json(true));
|
||||
}
|
||||
}
|
||||
176
test/src/unit-unicode.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 2.0.6
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#define private public
|
||||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
#include <fstream>
|
||||
|
||||
TEST_CASE("Unicode", "[hide]")
|
||||
{
|
||||
SECTION("full enumeration of Unicode code points")
|
||||
{
|
||||
// create an escaped string from a code point
|
||||
const auto codepoint_to_unicode = [](std::size_t cp)
|
||||
{
|
||||
// copd points are represented as a six-character sequence: a
|
||||
// reverse solidus, followed by the lowercase letter u, followed
|
||||
// by four hexadecimal digits that encode the character's code
|
||||
// point
|
||||
std::stringstream ss;
|
||||
ss << "\\u" << std::setw(4) << std::setfill('0') << std::hex << cp;
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
// generate all UTF-8 code points; in total, 1112064 code points are
|
||||
// generated: 0x1FFFFF code points - 2048 invalid values between
|
||||
// 0xD800 and 0xDFFF.
|
||||
for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
|
||||
{
|
||||
// The Unicode standard permanently reserves these code point
|
||||
// values for UTF-16 encoding of the high and low surrogates, and
|
||||
// they will never be assigned a character, so there should be no
|
||||
// reason to encode them. The official Unicode standard says that
|
||||
// no UTF forms, including UTF-16, can encode these code points.
|
||||
if (cp >= 0xD800u and cp <= 0xDFFFu)
|
||||
{
|
||||
// if we would not skip these code points, we would get a
|
||||
// "missing low surrogate" exception
|
||||
continue;
|
||||
}
|
||||
|
||||
// string to store the code point as in \uxxxx format
|
||||
std::string escaped_string;
|
||||
// string to store the code point as unescaped character sequence
|
||||
std::string unescaped_string;
|
||||
|
||||
if (cp < 0x10000u)
|
||||
{
|
||||
// code points in the Basic Multilingual Plane can be
|
||||
// represented with one \\uxxxx sequence
|
||||
escaped_string = codepoint_to_unicode(cp);
|
||||
|
||||
// All Unicode characters may be placed within the quotation
|
||||
// marks, except for the characters that must be escaped:
|
||||
// quotation mark, reverse solidus, and the control characters
|
||||
// (U+0000 through U+001F); we ignore these code points as
|
||||
// they are checked with codepoint_to_unicode.
|
||||
if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
|
||||
{
|
||||
unescaped_string = json::lexer::to_unicode(cp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// To escape an extended character that is not in the Basic
|
||||
// Multilingual Plane, the character is represented as a
|
||||
// 12-character sequence, encoding the UTF-16 surrogate pair
|
||||
const auto codepoint1 = 0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu);
|
||||
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
|
||||
escaped_string = codepoint_to_unicode(codepoint1);
|
||||
escaped_string += codepoint_to_unicode(codepoint2);
|
||||
unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2);
|
||||
}
|
||||
|
||||
// all other code points are valid and must not yield parse errors
|
||||
CAPTURE(cp);
|
||||
CAPTURE(escaped_string);
|
||||
CAPTURE(unescaped_string);
|
||||
|
||||
json j1, j2, j3, j4;
|
||||
CHECK_NOTHROW(j1 = json::parse("\"" + escaped_string + "\""));
|
||||
CHECK_NOTHROW(j2 = json::parse(j1.dump()));
|
||||
CHECK(j1 == j2);
|
||||
|
||||
CHECK_NOTHROW(j3 = json::parse("\"" + unescaped_string + "\""));
|
||||
CHECK_NOTHROW(j4 = json::parse(j3.dump()));
|
||||
CHECK(j3 == j4);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("read all unicode characters")
|
||||
{
|
||||
// read a file with all unicode characters stored as single-character
|
||||
// strings in a JSON array
|
||||
std::ifstream f("test/data/json_nlohmann_tests/all_unicode.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
|
||||
// the array has 1112064 + 1 elemnts (a terminating "null" value)
|
||||
// Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between
|
||||
// 0xD800 and 0xDFFF.
|
||||
CHECK(j.size() == 1112065);
|
||||
|
||||
SECTION("check JSON Pointers")
|
||||
{
|
||||
for (auto s : j)
|
||||
{
|
||||
// skip non-string JSON values
|
||||
if (not s.is_string())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string ptr = s;
|
||||
|
||||
// tilde must be followed by 0 or 1
|
||||
if (ptr == "~")
|
||||
{
|
||||
ptr += "0";
|
||||
}
|
||||
|
||||
// JSON Pointers must begin with "/"
|
||||
ptr = "/" + ptr;
|
||||
|
||||
CHECK_NOTHROW(json::json_pointer("/" + ptr));
|
||||
|
||||
// check escape/unescape roundtrip
|
||||
auto escaped = json::json_pointer::escape(ptr);
|
||||
json::json_pointer::unescape(escaped);
|
||||
CHECK(escaped == ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("ignore byte-order-mark")
|
||||
{
|
||||
// read a file with a UTF-8 BOM
|
||||
std::ifstream f("test/data/json_nlohmann_tests/bom.json");
|
||||
json j;
|
||||
CHECK_NOTHROW(j << f);
|
||||
}
|
||||
|
||||
SECTION("error for incomplete/wrong BOM")
|
||||
{
|
||||
CHECK_THROWS_AS(json::parse("\xef\xbb"), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), std::invalid_argument);
|
||||
}
|
||||
}
|
||||