Merge remote-tracking branch 'nlohmann/develop' into iterate-on-destruction

This commit is contained in:
Isaac Nickaein 2019-11-09 14:50:48 +03:30
commit eec1974218
148 changed files with 27046 additions and 18980 deletions

View file

@ -6,7 +6,7 @@ option(JSON_Coverage "Build test suite with coverage information" OFF)
if(JSON_Sanitizer)
message(STATUS "Building test suite with Clang sanitizer")
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "-g -O0 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fsanitize-recover=unsigned-integer-overflow")
endif()
endif()
@ -22,7 +22,7 @@ if(JSON_NoExceptions)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJSON_NOEXCEPTION")
endif()
set(CATCH_TEST_FILTER -e)
set(DOCTEST_TEST_FILTER --no-throw)
endif()
if(JSON_Coverage)
@ -45,27 +45,38 @@ if(JSON_Coverage)
# add target to collect coverage information and generate HTML file
# (filter script from https://stackoverflow.com/a/43726240/266378)
add_custom_target(lcov_html
COMMAND lcov --directory . --capture --output-file json.info --gcov-tool ${GCOV_BIN} --rc lcov_branch_coverage=1
COMMAND lcov -e json.info ${SOURCE_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1
COMMAND lcov --directory . --capture --output-file json.info --rc lcov_branch_coverage=1
COMMAND lcov -e json.info ${SOURCE_FILES} --output-file json.info.filtered --gcov-tool ${GCOV_BIN} --rc lcov_branch_coverage=1
COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept
COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept
COMMENT "Generating HTML report test/html/index.html"
)
add_custom_target(fastcov_html
COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/fastcov/fastcov.py --branch-coverage --lcov -o json.info --gcov ${GCOV_BIN} --compiler-directory ${CMAKE_BINARY_DIR} --source-files ${SOURCE_FILES}
COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info > json.info.noexcept
COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.noexcept
COMMENT "Generating HTML report test/html/index.html"
)
endif()
#############################################################################
# Catch library with the main function to speed up build
# doctest library with the main function to speed up build
#############################################################################
add_library(catch_main OBJECT
add_library(doctest_main OBJECT
"src/unit.cpp"
)
set_target_properties(catch_main PROPERTIES
set_target_properties(doctest_main PROPERTIES
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
target_compile_features(catch_main PUBLIC cxx_std_11)
target_include_directories(catch_main PRIVATE "thirdparty/catch")
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
target_compile_features(doctest_main PUBLIC cxx_range_for)
else()
target_compile_features(doctest_main PUBLIC cxx_std_11)
endif()
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
if(MSVC)
@ -81,7 +92,7 @@ if(MSVC)
# Disable warning C4566: character represented by universal-character-name '\uFF01' cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator <<': was declared deprecated
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4389 /wd4309 /wd4566 /wd4996")
# https://github.com/nlohmann/json/issues/1114
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
endif()
@ -90,15 +101,56 @@ endif()
# one executable for each unit test file
#############################################################################
file(GLOB files "src/unit-*.cpp")
set(files
src/unit-algorithms.cpp
src/unit-allocator.cpp
src/unit-alt-string.cpp
src/unit-bson.cpp
src/unit-capacity.cpp
src/unit-cbor.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-items.cpp
src/unit-iterators1.cpp
src/unit-iterators2.cpp
src/unit-json_patch.cpp
src/unit-json_pointer.cpp
src/unit-merge_patch.cpp
src/unit-meta.cpp
src/unit-modifiers.cpp
src/unit-msgpack.cpp
src/unit-noexcept.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-to_chars.cpp
src/unit-ubjson.cpp
src/unit-udt.cpp
src/unit-unicode.cpp
src/unit-wstring.cpp)
foreach(file ${files})
get_filename_component(file_basename ${file} NAME_WE)
string(REGEX REPLACE "unit-([^$]+)" "test-\\1" testcase ${file_basename})
add_executable(${testcase} $<TARGET_OBJECTS:catch_main> ${file})
add_executable(${testcase} $<TARGET_OBJECTS:doctest_main> ${file})
target_compile_definitions(${testcase} PRIVATE
CATCH_CONFIG_FAST_COMPILE
$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>
DOCTEST_CONFIG_SUPER_FAST_ASSERTS
)
target_compile_options(${testcase} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
@ -106,26 +158,26 @@ foreach(file ${files})
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
)
target_include_directories(${testcase} PRIVATE
thirdparty/catch
thirdparty/doctest
thirdparty/fifo_map
)
target_link_libraries(${testcase} ${NLOHMANN_JSON_TARGET_NAME})
add_test(NAME "${testcase}_default"
COMMAND ${testcase} ${CATCH_TEST_FILTER}
COMMAND ${testcase} ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
set_tests_properties("${testcase}_default" PROPERTIES LABELS "default")
add_test(NAME "${testcase}_all"
COMMAND ${testcase} ${CATCH_TEST_FILTER} "*"
COMMAND ${testcase} ${DOCTEST_TEST_FILTER} --no-skip
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
set_tests_properties("${testcase}_all" PROPERTIES LABELS "all")
if(JSON_Valgrind)
add_test(NAME "${testcase}_valgrind"
COMMAND ${memcheck_command} ${CMAKE_CURRENT_BINARY_DIR}/${testcase} ${CATCH_TEST_FILTER}
COMMAND ${memcheck_command} ${CMAKE_CURRENT_BINARY_DIR}/${testcase} ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
set_tests_properties("${testcase}_valgrind" PROPERTIES LABELS "valgrind")

View file

@ -4,7 +4,7 @@
# additional flags
CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic -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 ../single_include -I . -I thirdparty/catch -I thirdparty/fifo_map -DCATCH_CONFIG_FAST_COMPILE
CPPFLAGS += -I ../single_include -I . -I thirdparty/doctest -I thirdparty/fifo_map -DDOCTEST_CONFIG_SUPER_FAST_ASSERTS
SOURCES = src/unit.cpp \
src/unit-algorithms.cpp \
@ -63,11 +63,11 @@ clean:
# single test file
##############################################################################
json_unit: $(OBJECTS) ../single_include/nlohmann/json.hpp thirdparty/catch/catch.hpp
json_unit: $(OBJECTS) ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h
@echo "[CXXLD] $@"
@$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) -o $@
%.o: %.cpp ../single_include/nlohmann/json.hpp thirdparty/catch/catch.hpp
%.o: %.cpp ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h
@echo "[CXX] $@"
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
@ -76,7 +76,7 @@ json_unit: $(OBJECTS) ../single_include/nlohmann/json.hpp thirdparty/catch/catch
# individual test cases
##############################################################################
test-%: src/unit-%.o src/unit.o ../single_include/nlohmann/json.hpp thirdparty/catch/catch.hpp
test-%: src/unit-%.o src/unit.o ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h
@echo "[CXXLD] $@"
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $< src/unit.o -o $@

View file

@ -1,6 +1,7 @@
add_test(NAME cmake_import_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-Dnlohmann_json_DIR=${PROJECT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)

View file

@ -1,6 +1,7 @@
add_test(NAME cmake_import_minver_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-Dnlohmann_json_DIR=${PROJECT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)

1
test/src/UBSAN.supp Normal file
View file

@ -0,0 +1 @@
unsigned-integer-overflow:stl_bvector.h

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,14 +27,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
namespace
{
// special test case to check if memory is leaked if constructor throws
template<class T>
struct bad_allocator : std::allocator<T>
{
@ -44,6 +46,7 @@ struct bad_allocator : std::allocator<T>
throw std::bad_alloc();
}
};
}
TEST_CASE("bad_alloc")
{
@ -64,13 +67,17 @@ TEST_CASE("bad_alloc")
}
}
static bool next_construct_fails = false;
static bool next_destroy_fails = false;
static bool next_deallocate_fails = false;
namespace
{
bool next_construct_fails = false;
bool next_destroy_fails = false;
bool next_deallocate_fails = false;
template<class T>
struct my_allocator : std::allocator<T>
{
using std::allocator<T>::allocator;
template<class... Args>
void construct(T* p, Args&& ... args)
{
@ -110,6 +117,12 @@ struct my_allocator : std::allocator<T>
p->~T();
}
}
template <class U>
struct rebind
{
using other = my_allocator<U>;
};
};
// allows deletion of raw pointer, usually hold by json_value
@ -121,6 +134,7 @@ void my_allocator_clean_up(T* p)
alloc.destroy(p);
alloc.deallocate(p, 1);
}
}
TEST_CASE("controlled bad_alloc")
{

View file

@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@ -27,9 +27,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
#include <string>
#include <utility>
@ -37,7 +38,7 @@ SOFTWARE.
/* forward declarations */
class alt_string;
bool operator<(const char* op1, const alt_string& op2);
void int_to_string(alt_string& target, std::size_t value);
/*
* This is virtually a string class.
@ -149,11 +150,15 @@ class alt_string
}
private:
std::string str_impl;
std::string str_impl {};
friend bool ::operator<(const char*, const alt_string&);
};
void int_to_string(alt_string& target, std::size_t value)
{
target = std::to_string(value).c_str();
}
using alt_json = nlohmann::basic_json <
std::map,
@ -172,8 +177,6 @@ bool operator<(const char* op1, const alt_string& op2)
return op1 < op2.str_impl;
}
TEST_CASE("alternative string type")
{
SECTION("dump")
@ -235,6 +238,35 @@ TEST_CASE("alternative string type")
CHECK(dump == R"({"foo":"bar"})");
}
SECTION("items")
{
auto doc = alt_json::parse("{\"foo\": \"bar\"}");
for ( auto item : doc.items() )
{
CHECK( item.key() == "foo" );
CHECK( item.value() == "bar" );
}
auto doc_array = alt_json::parse("[\"foo\", \"bar\"]");
for ( auto item : doc_array.items() )
{
if (item.key() == "0" )
{
CHECK( item.value() == "foo" );
}
else if (item.key() == "1" )
{
CHECK( item.value() == "bar" );
}
else
{
CHECK( false );
}
}
}
SECTION("equality")
{
alt_json doc;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <sstream>
TEST_CASE("BSON")
{
@ -110,8 +112,9 @@ TEST_CASE("BSON")
0x00,
0x00, 0x00, 0x00, 0x80
};
CHECK_THROWS_AS(json::from_bson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(v), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BSON string: string length must be at least 1, is -2147483648");
json _;
CHECK_THROWS_AS(_ = json::from_bson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(v), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BSON string: string length must be at least 1, is -2147483648");
}
SECTION("objects")
@ -581,10 +584,9 @@ TEST_CASE("BSON input/output_adapters")
{
SECTION("std::ostringstream")
{
std::ostringstream ss;
std::basic_ostringstream<std::uint8_t> ss;
json::to_bson(json_representation, ss);
std::istringstream iss(ss.str());
json j3 = json::from_bson(iss);
json j3 = json::from_bson(ss.str());
CHECK(json_representation == j3);
}
@ -606,6 +608,8 @@ TEST_CASE("BSON input/output_adapters")
}
}
namespace
{
class SaxCountdown
{
public:
@ -675,6 +679,7 @@ class SaxCountdown
private:
int events_left = 0;
};
}
TEST_CASE("Incomplete BSON Input")
{
@ -687,8 +692,9 @@ TEST_CASE("Incomplete BSON Input")
'e', 'n', 't' // unexpected EOF
};
CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
json _;
CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BSON cstring: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
@ -705,8 +711,9 @@ TEST_CASE("Incomplete BSON Input")
0x08, // entry: boolean, unexpected EOF
};
CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
json _;
CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BSON cstring: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
@ -728,8 +735,9 @@ TEST_CASE("Incomplete BSON Input")
// missing input data...
};
CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
json _;
CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 28: syntax error while parsing BSON element list: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
@ -744,8 +752,9 @@ TEST_CASE("Incomplete BSON Input")
0x0D, 0x00, // size (incomplete), unexpected EOF
};
CHECK_THROWS_AS(json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(incomplete_bson),
json _;
CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BSON number: unexpected end of input");
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
@ -786,8 +795,9 @@ TEST_CASE("Unsupported BSON input")
0x00 // end marker
};
CHECK_THROWS_AS(json::from_bson(bson), json::parse_error&);
CHECK_THROWS_WITH(json::from_bson(bson),
json _;
CHECK_THROWS_AS(_ = json::from_bson(bson), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_bson(bson),
"[json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF");
CHECK(json::from_bson(bson, true, false).is_discarded());
@ -1138,7 +1148,7 @@ TEST_CASE("BSON numerical data")
};
CHECK_THROWS_AS(json::to_bson(j), json::out_of_range&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.407] integer number " + std::to_string(i) + " cannot be represented by BSON as it does not fit int64");
CHECK_THROWS_WITH_STD_STR(json::to_bson(j), "[json.exception.out_of_range.407] integer number " + std::to_string(i) + " cannot be represented by BSON as it does not fit int64");
}
}
@ -1146,7 +1156,7 @@ TEST_CASE("BSON numerical data")
}
}
TEST_CASE("BSON roundtrips", "[hide]")
TEST_CASE("BSON roundtrips" * doctest::skip())
{
SECTION("reference files")
{
@ -1161,8 +1171,8 @@ TEST_CASE("BSON roundtrips", "[hide]")
{
CAPTURE(filename)
SECTION(filename + ": std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1179,8 +1189,8 @@ TEST_CASE("BSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": std::ifstream")
{
INFO_WITH_TEMP(filename + ": std::ifstream");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1194,8 +1204,8 @@ TEST_CASE("BSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": uint8_t* and size")
{
INFO_WITH_TEMP(filename + ": uint8_t* and size");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1212,8 +1222,8 @@ TEST_CASE("BSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": output to output adapters")
{
INFO_WITH_TEMP(filename + ": output to output adapters");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1224,8 +1234,8 @@ TEST_CASE("BSON roundtrips", "[hide]")
(std::istreambuf_iterator<char>(f_bson)),
std::istreambuf_iterator<char>());
SECTION(filename + ": output adapters: std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
std::vector<uint8_t> vec;
json::to_bson(j1, vec);

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,13 +27,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <sstream>
#include <iomanip>
#include <set>
namespace
{
class SaxCountdown
{
public:
@ -103,6 +109,7 @@ class SaxCountdown
private:
int events_left = 0;
};
}
TEST_CASE("CBOR")
{
@ -829,15 +836,17 @@ TEST_CASE("CBOR")
{
SECTION("no byte follows")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf9})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf9})),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf9})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xf9})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input");
CHECK(json::from_cbor(std::vector<uint8_t>({0xf9}), true, false).is_discarded());
}
SECTION("only one byte follows")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
CHECK(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c}), true, false).is_discarded());
}
@ -1278,7 +1287,7 @@ TEST_CASE("CBOR")
}
}
SECTION("additonal deserialization")
SECTION("additional deserialization")
{
SECTION("0x7b (string)")
{
@ -1312,86 +1321,88 @@ TEST_CASE("CBOR")
{
SECTION("empty byte vector")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>()),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>()),
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input");
CHECK(json::from_cbor(std::vector<uint8_t>(), true, false).is_discarded());
}
SECTION("too short byte vector")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x18})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x62})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x62, 0x60})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x7F})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x82, 0x01})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0X61})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0X61})), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x18})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x19})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x19, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x62})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x62, 0x60})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x82, 0x01})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0X61})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0X61})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x18})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x18})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x19})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x19})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x19, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x19, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1a})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing CBOR number: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x62})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x62})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x62, 0x60})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x62, 0x60})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR string: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x7F})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x7F})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR string: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x82, 0x01})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x82, 0x01})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0x61})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0x61})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR value: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61})),
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR value: unexpected end of input");
CHECK(json::from_cbor(std::vector<uint8_t>({0x18}), true, false).is_discarded());
@ -1424,13 +1435,14 @@ TEST_CASE("CBOR")
{
SECTION("concrete examples")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1c})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1c})),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0x1c})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0x1c})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0x1C");
CHECK(json::from_cbor(std::vector<uint8_t>({0x1c}), true, false).is_discarded());
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf8})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf8})),
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xf8})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xf8})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0xF8");
CHECK(json::from_cbor(std::vector<uint8_t>({0xf8}), true, false).is_discarded());
}
@ -1481,7 +1493,8 @@ TEST_CASE("CBOR")
0xf8
})
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
CHECK(json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)}), true, false).is_discarded());
}
}
@ -1489,8 +1502,9 @@ TEST_CASE("CBOR")
SECTION("invalid string in map")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})),
"[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF");
CHECK(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01}), true, false).is_discarded());
}
@ -1507,8 +1521,9 @@ TEST_CASE("CBOR")
SECTION("strict mode")
{
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: expected end of input; last byte: 0xF6");
CHECK(json::from_cbor(vec, true, false).is_discarded());
}
@ -1565,7 +1580,7 @@ TEST_CASE("single CBOR roundtrip")
{
SECTION("std::ostringstream")
{
std::ostringstream ss;
std::basic_ostringstream<std::uint8_t> ss;
json::to_cbor(j1, ss);
json j3 = json::from_cbor(ss.str());
CHECK(j1 == j3);
@ -1586,7 +1601,8 @@ TEST_CASE("single CBOR roundtrip")
}
}
TEST_CASE("CBOR regressions", "[!throws]")
#if not defined(JSON_NOEXCEPTION)
TEST_CASE("CBOR regressions")
{
SECTION("fuzz test results")
{
@ -1655,12 +1671,13 @@ TEST_CASE("CBOR regressions", "[!throws]")
}
}
}
#endif
TEST_CASE("CBOR roundtrips", "[hide]")
TEST_CASE("CBOR roundtrips" * doctest::skip())
{
SECTION("input from flynn")
{
// most of these are exluded due to differences in key order (not a real problem)
// most of these are excluded due to differences in key order (not a real problem)
auto exclude_packed = std::set<std::string>
{
"test/data/json.org/1.json",
@ -1827,8 +1844,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
{
CAPTURE(filename)
SECTION(filename + ": std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1845,8 +1862,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": std::ifstream")
{
INFO_WITH_TEMP(filename + ": std::ifstream");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1860,8 +1877,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": uint8_t* and size")
{
INFO_WITH_TEMP(filename + ": uint8_t* and size");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1878,8 +1895,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": output to output adapters")
{
INFO_WITH_TEMP(filename + ": output to output adapters");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1892,8 +1909,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
if (!exclude_packed.count(filename))
{
SECTION(filename + ": output adapters: std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
std::vector<uint8_t> vec;
json::to_cbor(j1, vec);
CHECK(vec == packed);
@ -1904,7 +1921,8 @@ TEST_CASE("CBOR roundtrips", "[hide]")
}
}
TEST_CASE("all CBOR first bytes", "[!throws]")
#if not defined(JSON_NOEXCEPTION)
TEST_CASE("all CBOR first bytes")
{
// these bytes will fail immediately with exception parse_error.112
std::set<uint8_t> unsupported =
@ -1968,7 +1986,7 @@ TEST_CASE("all CBOR first bytes", "[!throws]")
{
// check that parse_error.112 is only thrown if the
// first byte is in the unsupported set
CAPTURE(e.what())
INFO_WITH_TEMP(e.what());
if (std::find(unsupported.begin(), unsupported.end(), byte) != unsupported.end())
{
CHECK(e.id == 112);
@ -1980,6 +1998,7 @@ TEST_CASE("all CBOR first bytes", "[!throws]")
}
}
}
#endif
TEST_CASE("examples from RFC 7049 Appendix A")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
TEST_CASE("const_iterator class")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
TEST_CASE("iterator class")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,18 +27,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
namespace
{
// shortcut to scan a string literal
json::lexer::token_type scan_string(const char* s);
json::lexer::token_type scan_string(const char* s)
{
return json::lexer(nlohmann::detail::input_adapter(s)).scan();
}
}
TEST_CASE("lexer class")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,14 +27,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <valarray>
namespace
{
class SaxEventLogger
{
public:
@ -125,7 +128,7 @@ class SaxEventLogger
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
bool errored = false;
};
@ -207,7 +210,7 @@ json parser_helper(const std::string& s)
json j;
json::parser(nlohmann::detail::input_adapter(s)).parse(true, j);
// if this line was reached, no exception ocurred
// if this line was reached, no exception occurred
// -> check if result is the same without exceptions
json j_nothrow;
CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow));
@ -255,6 +258,7 @@ bool accept_helper(const std::string& s)
// 7. return result
return ok_accept;
}
}
TEST_CASE("parser class")
{
@ -402,8 +406,9 @@ TEST_CASE("parser class")
// uses an iterator range.
std::string s = "\"1\"";
s[1] = '\0';
CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error&);
CHECK_THROWS_WITH(json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"<U+0000>'");
json _;
CHECK_THROWS_AS(_ = json::parse(s.begin(), s.end()), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"<U+0000>'");
}
}
@ -1105,8 +1110,8 @@ TEST_CASE("parser class")
// only check error message if c is not a control character
if (c > 0x1f)
{
CHECK_THROWS_WITH(parser_helper(s.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast<char>(c)) + "'");
CHECK_THROWS_WITH_STD_STR(parser_helper(s.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast<char>(c)) + "'");
}
break;
}
@ -1181,8 +1186,8 @@ TEST_CASE("parser class")
// only check error message if c is not a control character
if (c > 0x1f)
{
CHECK_THROWS_WITH(parser_helper(s1.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'");
CHECK_THROWS_WITH_STD_STR(parser_helper(s1.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'");
}
CAPTURE(s2)
@ -1190,8 +1195,8 @@ TEST_CASE("parser class")
// only check error message if c is not a control character
if (c > 0x1f)
{
CHECK_THROWS_WITH(parser_helper(s2.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'");
CHECK_THROWS_WITH_STD_STR(parser_helper(s2.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'");
}
CAPTURE(s3)
@ -1199,8 +1204,8 @@ TEST_CASE("parser class")
// only check error message if c is not a control character
if (c > 0x1f)
{
CHECK_THROWS_WITH(parser_helper(s3.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'");
CHECK_THROWS_WITH_STD_STR(parser_helper(s3.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'");
}
CAPTURE(s4)
@ -1208,26 +1213,28 @@ TEST_CASE("parser class")
// only check error message if c is not a control character
if (c > 0x1f)
{
CHECK_THROWS_WITH(parser_helper(s4.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'");
CHECK_THROWS_WITH_STD_STR(parser_helper(s4.c_str()),
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'");
}
}
}
}
json _;
// missing part of a surrogate pair
CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD80C\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\""),
"[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'");
// invalid surrogate pair
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error&);
CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error&);
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\uD80C\""), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\u0000\""), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\uD80C\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'");
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""),
CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\u0000\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'");
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""),
CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\uFFFF\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'");
}
@ -1675,12 +1682,13 @@ TEST_CASE("parser class")
CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded());
CHECK_THROWS_AS(json::parse("{\"foo\": true:", cb), json::parse_error&);
CHECK_THROWS_WITH(json::parse("{\"foo\": true:", cb),
json _;
CHECK_THROWS_AS(_ = json::parse("{\"foo\": true:", cb), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("{\"foo\": true:", cb),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing object - unexpected ':'; expected '}'");
CHECK_THROWS_AS(json::parse("1.18973e+4932", cb), json::out_of_range&);
CHECK_THROWS_WITH(json::parse("1.18973e+4932", cb),
CHECK_THROWS_AS(_ = json::parse("1.18973e+4932", cb), json::out_of_range&);
CHECK_THROWS_WITH(_ = json::parse("1.18973e+4932", cb),
"[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'");
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace
{
// helper function to check std::less<json::value_t>
// see https://en.cppreference.com/w/cpp/utility/functional/less
template <typename A, typename B, typename U = std::less<json::value_t>>
@ -39,6 +41,7 @@ bool f(A a, B b, U u = U())
{
return u(a, b);
}
}
TEST_CASE("lexicographical comparison operators")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -73,8 +73,8 @@ TEST_CASE("concepts")
// 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(static_cast<json::size_type>(std::numeric_limits<json::difference_type>::max()) <=
std::numeric_limits<json::size_type>::max());
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
(std::numeric_limits<json::size_type>::max)());
// the expression "X u" has the post-condition "u.empty()"
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,16 +27,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <deque>
#include <forward_list>
#include <fstream>
#include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
@ -1049,9 +1052,10 @@ TEST_CASE("constructors")
SECTION("object with error")
{
CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
json _;
CHECK_THROWS_AS(_ = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
json::type_error&);
CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
CHECK_THROWS_WITH(_ = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
"[json.exception.type_error.301] cannot create object from initializer list");
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,12 +27,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <sstream>
namespace
{
void check_escaped(const char* original, const char* escaped = "", const bool ensure_ascii = false);
void check_escaped(const char* original, const char* escaped, const bool ensure_ascii)
{
@ -41,6 +46,7 @@ void check_escaped(const char* original, const char* escaped, const bool ensure_
s.dump_escaped(original, ensure_ascii);
CHECK(ss.str() == escaped);
}
}
TEST_CASE("convenience functions")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,15 +27,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <deque>
#include <forward_list>
#include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
@ -140,6 +142,54 @@ TEST_CASE("value conversion")
}
}
SECTION("get an object (explicit, get_to)")
{
json::object_t o_reference = {{"object", json::object()},
{"array", {1, 2, 3, 4}},
{"number", 42},
{"boolean", false},
{"null", nullptr},
{"string", "Hello world"}
};
json j(o_reference);
SECTION("json::object_t")
{
json::object_t o = {{"previous", "value"}};
j.get_to(o);
CHECK(json(o) == j);
}
SECTION("std::map<json::string_t, json>")
{
std::map<json::string_t, json> o{{"previous", "value"}};
j.get_to(o);
CHECK(json(o) == j);
}
SECTION("std::multimap<json::string_t, json>")
{
std::multimap<json::string_t, json> o{{"previous", "value"}};
j.get_to(o);
CHECK(json(o) == j);
}
SECTION("std::unordered_map<json::string_t, json>")
{
std::unordered_map<json::string_t, json> o{{"previous", "value"}};
j.get_to(o);
CHECK(json(o) == j);
}
SECTION("std::unordered_multimap<json::string_t, json>")
{
std::unordered_multimap<json::string_t, json> o{{"previous", "value"}};
j.get_to(o);
CHECK(json(o) == j);
}
}
SECTION("get an object (implicit)")
{
json::object_t o_reference = {{"object", json::object()},
@ -226,11 +276,6 @@ TEST_CASE("value conversion")
#if not defined(JSON_NOEXCEPTION)
SECTION("reserve is called on containers that supports it")
{
// making the call to from_json throw in order to check capacity
std::vector<float> v;
CHECK_THROWS_AS(nlohmann::from_json(j, v), json::type_error&);
CHECK(v.capacity() == j.size());
// make sure all values are properly copied
std::vector<int> v2 = json({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
CHECK(v2.size() == 10);
@ -302,6 +347,65 @@ TEST_CASE("value conversion")
}
}
SECTION("get an array (explicit, get_to)")
{
json::array_t a_reference{json(1), json(1u), json(2.2),
json(false), json("string"), json()};
json j(a_reference);
SECTION("json::array_t")
{
json::array_t a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
SECTION("std::valarray<json>")
{
std::valarray<json> a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
SECTION("std::list<json>")
{
std::list<json> a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
SECTION("std::forward_list<json>")
{
std::forward_list<json> a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
SECTION("std::vector<json>")
{
std::vector<json> a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
SECTION("built-in arrays")
{
const int nbs[] = {0, 1, 2};
int nbs2[] = {0, 0, 0};
json j2 = nbs;
j2.get_to(nbs2);
CHECK(std::equal(std::begin(nbs), std::end(nbs), std::begin(nbs2)));
}
SECTION("std::deque<json>")
{
std::deque<json> a{"previous", "value"};
j.get_to(a);
CHECK(json(a) == j);
}
}
SECTION("get an array (implicit)")
{
json::array_t a_reference{json(1), json(1u), json(2.2),
@ -433,6 +537,35 @@ TEST_CASE("value conversion")
#endif
}
SECTION("get a string (explicit, get_to)")
{
json::string_t s_reference{"Hello world"};
json j(s_reference);
SECTION("string_t")
{
json::string_t s = "previous value";
j.get_to(s);
CHECK(json(s) == j);
}
SECTION("std::string")
{
std::string s = "previous value";
j.get_to(s);
CHECK(json(s) == j);
}
#if defined(JSON_HAS_CPP_17)
SECTION("std::string_view")
{
std::string s = "previous value";
std::string_view sv = s;
j.get_to(sv);
CHECK(json(sv) == j);
}
#endif
}
SECTION("get null (explicit)")
{
std::nullptr_t n = nullptr;
@ -480,7 +613,7 @@ TEST_CASE("value conversion")
#if defined(JSON_HAS_CPP_17)
SECTION("std::string_view")
{
std::string_view s = j;
std::string_view s = j.get<std::string_view>();
CHECK(json(s) == j);
}
#endif
@ -503,13 +636,19 @@ TEST_CASE("value conversion")
CHECK(json(b) == j);
}
SECTION("uint8_t")
{
auto n = j.get<uint8_t>();
CHECK(n == 1);
}
SECTION("bool")
{
bool b = j.get<bool>();
CHECK(json(b) == j);
}
SECTION("exception in case of a non-string type")
SECTION("exception in case of a non-number type")
{
CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(),
json::type_error&);
@ -519,6 +658,8 @@ TEST_CASE("value conversion")
json::type_error&);
CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(),
json::type_error&);
CHECK_THROWS_AS(json(json::value_t::string).get<uint8_t>(),
json::type_error&);
CHECK_THROWS_AS(
json(json::value_t::number_integer).get<json::boolean_t>(),
json::type_error&);

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,14 +27,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <iostream>
#include <sstream>
#include <valarray>
namespace
{
struct SaxEventLogger : public nlohmann::json_sax<json>
{
bool null() override
@ -123,7 +126,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
};
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
@ -166,6 +169,7 @@ struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
return false;
}
};
}
TEST_CASE("deserialization")
{
@ -265,8 +269,10 @@ TEST_CASE("deserialization")
ss3 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss4 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss5 << "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(ss1), json::parse_error&);
CHECK_THROWS_WITH(json::parse(ss2),
json _;
CHECK_THROWS_AS(_ = json::parse(ss1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(ss2),
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
CHECK(not json::accept(ss3));
@ -289,8 +295,9 @@ TEST_CASE("deserialization")
SECTION("string")
{
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(s), json::parse_error&);
CHECK_THROWS_WITH(json::parse(s),
json _;
CHECK_THROWS_AS(_ = json::parse(s), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(s),
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'");
CHECK(not json::accept(s));
@ -426,7 +433,8 @@ TEST_CASE("deserialization")
SECTION("empty container")
{
std::vector<uint8_t> v;
CHECK_THROWS_AS(json::parse(v), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(v), json::parse_error&);
CHECK(not json::accept(v));
SaxEventLogger l;
@ -610,8 +618,9 @@ TEST_CASE("deserialization")
SECTION("case 6")
{
uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
CHECK_THROWS_WITH(json::parse(std::begin(v), std::end(v)),
json _;
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(std::begin(v), std::end(v)),
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'");
CHECK(not json::accept(std::begin(v), std::end(v)));
@ -797,12 +806,13 @@ TEST_CASE("deserialization")
SECTION("BOM only")
{
CHECK_THROWS_AS(json::parse(bom), json::parse_error&);
CHECK_THROWS_WITH(json::parse(bom),
json _;
CHECK_THROWS_AS(_ = json::parse(bom), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(bom),
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error&);
CHECK_THROWS_WITH(json::parse(std::istringstream(bom)),
CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom)), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom)),
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
SaxEventLogger l;
@ -836,12 +846,13 @@ TEST_CASE("deserialization")
SECTION("2 byte of BOM")
{
CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error&);
CHECK_THROWS_WITH(json::parse(bom.substr(0, 2)),
json _;
CHECK_THROWS_AS(_ = json::parse(bom.substr(0, 2)), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(bom.substr(0, 2)),
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&);
CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 2))),
CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom.substr(0, 2))),
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
SaxEventLogger l1, l2;
@ -861,12 +872,13 @@ TEST_CASE("deserialization")
SECTION("1 byte of BOM")
{
CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error&);
CHECK_THROWS_WITH(json::parse(bom.substr(0, 1)),
json _;
CHECK_THROWS_AS(_ = json::parse(bom.substr(0, 1)), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(bom.substr(0, 1)),
"[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&);
CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 1))),
CHECK_THROWS_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(std::istringstream(bom.substr(0, 1))),
"[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
SaxEventLogger l1, l2;
@ -921,8 +933,9 @@ TEST_CASE("deserialization")
else
{
// any variation is an error
CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error&);
CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&);
SaxEventLogger l;
CHECK(not json::sax_parse(s + "null", &l));

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -982,10 +982,98 @@ TEST_CASE("element access 2")
}
}
}
SECTION("check existence of key in an object")
{
SECTION("existing element")
{
for (auto key :
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
})
{
CHECK(j.contains(key) == true);
CHECK(j_const.contains(key) == true);
}
}
SECTION("nonexisting element")
{
CHECK(j.contains("foo") == false);
CHECK(j_const.contains("foo") == false);
}
SECTION("all types")
{
SECTION("null")
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("string")
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("object")
{
json j_nonobject(json::value_t::object);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("array")
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("boolean")
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (integer)")
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (unsigned)")
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (floating-point)")
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
}
}
}
}
TEST_CASE("element access 2 (throwing tests)", "[!throws]")
#if not defined(JSON_NOEXCEPTION)
TEST_CASE("element access 2 (throwing tests)")
{
SECTION("object")
{
@ -1018,3 +1106,4 @@ TEST_CASE("element access 2 (throwing tests)", "[!throws]")
}
}
}
#endif

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,12 +27,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <fstream>
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <sstream>
TEST_CASE("object inspection")
{
SECTION("convenience type checker")

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
TEST_CASE("iterators 1")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -342,7 +342,7 @@ TEST_CASE("JSON patch")
// check that evaluation throws
CHECK_THROWS_AS(doc.patch(patch), json::other_error&);
CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
CHECK_THROWS_WITH_STD_STR(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
}
SECTION("A.10. Adding a Nested Member Object")
@ -483,7 +483,7 @@ TEST_CASE("JSON patch")
// check that evaluation throws
CHECK_THROWS_AS(doc.patch(patch), json::other_error&);
CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
CHECK_THROWS_WITH_STD_STR(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
}
SECTION("A.16. Adding an Array Value")
@ -1182,7 +1182,7 @@ TEST_CASE("JSON patch")
// the test will fail
CHECK_THROWS_AS(doc.patch(patch), json::other_error&);
CHECK_THROWS_WITH(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
CHECK_THROWS_WITH_STD_STR(doc.patch(patch), "[json.exception.other_error.501] unsuccessful: " + patch[0].dump());
}
}
}
@ -1268,7 +1268,7 @@ TEST_CASE("JSON patch")
for (const auto& test : suite)
{
CAPTURE(test.value("comment", ""))
INFO_WITH_TEMP(test.value("comment", ""));
// skip tests marked as disabled
if (test.value("disabled", false))

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
TEST_CASE("JSON pointers")
{
@ -89,12 +90,18 @@ TEST_CASE("JSON pointers")
// the whole document
CHECK(j[json::json_pointer()] == j);
CHECK(j[json::json_pointer("")] == j);
CHECK(j.contains(json::json_pointer()));
CHECK(j.contains(json::json_pointer("")));
// array access
CHECK(j[json::json_pointer("/foo")] == j["foo"]);
CHECK(j.contains(json::json_pointer("/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]);
CHECK(j.contains(json::json_pointer("/foo/0")));
CHECK(j.contains(json::json_pointer("/foo/1")));
CHECK(not j.contains(json::json_pointer("/foo/-")));
// checked array access
CHECK(j.at(json::json_pointer("/foo/0")) == j["foo"][0]);
@ -102,6 +109,8 @@ TEST_CASE("JSON pointers")
// empty string access
CHECK(j[json::json_pointer("/")] == j[""]);
CHECK(j.contains(json::json_pointer("")));
CHECK(j.contains(json::json_pointer("/")));
// other cases
CHECK(j[json::json_pointer("/ ")] == j[" "]);
@ -111,6 +120,14 @@ TEST_CASE("JSON pointers")
CHECK(j[json::json_pointer("/i\\j")] == j["i\\j"]);
CHECK(j[json::json_pointer("/k\"l")] == j["k\"l"]);
// contains
CHECK(j.contains(json::json_pointer("/ ")));
CHECK(j.contains(json::json_pointer("/c%d")));
CHECK(j.contains(json::json_pointer("/e^f")));
CHECK(j.contains(json::json_pointer("/g|h")));
CHECK(j.contains(json::json_pointer("/i\\j")));
CHECK(j.contains(json::json_pointer("/k\"l")));
// checked access
CHECK(j.at(json::json_pointer("/ ")) == j[" "]);
CHECK(j.at(json::json_pointer("/c%d")) == j["c%d"]);
@ -122,14 +139,24 @@ TEST_CASE("JSON pointers")
// escaped access
CHECK(j[json::json_pointer("/a~1b")] == j["a/b"]);
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
CHECK(j.contains(json::json_pointer("/a~1b")));
CHECK(j.contains(json::json_pointer("/m~0n")));
// unescaped access
// access to nonexisting values yield object creation
CHECK(not j.contains(json::json_pointer("/a/b")));
CHECK_NOTHROW(j[json::json_pointer("/a/b")] = 42);
CHECK(j.contains(json::json_pointer("/a/b")));
CHECK(j["a"]["b"] == json(42));
CHECK(not j.contains(json::json_pointer("/a/c/1")));
CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
CHECK(j["a"]["c"] == json({nullptr, 42}));
CHECK(j.contains(json::json_pointer("/a/c/1")));
CHECK(not j.contains(json::json_pointer("/a/d/-")));
CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
CHECK(not j.contains(json::json_pointer("/a/d/-")));
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));
@ -142,6 +169,7 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::out_of_range&);
CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer),
"[json.exception.out_of_range.404] unresolved reference token 'foo'");
CHECK(not j_primitive.contains(json::json_pointer("/foo")));
}
SECTION("const access")
@ -232,11 +260,16 @@ TEST_CASE("JSON pointers")
// the whole document
CHECK(j[""_json_pointer] == j);
CHECK(j.contains(""_json_pointer));
// 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]);
CHECK(j.contains("/foo"_json_pointer));
CHECK(j.contains("/foo/0"_json_pointer));
CHECK(j.contains("/foo/1"_json_pointer));
CHECK(not j.contains("/foo/-"_json_pointer));
}
}
@ -277,6 +310,12 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j_const.at("/01"_json_pointer),
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
CHECK_THROWS_AS(j.contains("/01"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j.contains("/01"_json_pointer),
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
CHECK_THROWS_AS(j_const.contains("/01"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j_const.contains("/01"_json_pointer),
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'");
// error with incorrect numbers
CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::parse_error&);
@ -293,6 +332,13 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_WITH(j_const.at("/one"_json_pointer) == 1,
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(j.contains("/one"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j.contains("/one"_json_pointer),
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(j_const.contains("/one"_json_pointer), json::parse_error&);
CHECK_THROWS_WITH(j_const.contains("/one"_json_pointer),
"[json.exception.parse_error.109] parse error: array index 'one' is not a number");
CHECK_THROWS_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(), json::parse_error&);
CHECK_THROWS_WITH(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(),
"[json.exception.parse_error.109] parse error: array index 'three' is not a number");
@ -305,6 +351,7 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range&);
CHECK_THROWS_WITH(j_const["/-"_json_pointer],
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
CHECK(not j_const.contains("/-"_json_pointer));
// error when using "-" with at
CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&);
@ -313,6 +360,7 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range&);
CHECK_THROWS_WITH(j_const.at("/-"_json_pointer),
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
CHECK(not j_const.contains("/-"_json_pointer));
}
SECTION("const access")
@ -328,11 +376,13 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range&);
CHECK_THROWS_WITH(j.at("/3"_json_pointer),
"[json.exception.out_of_range.401] array index 3 is out of range");
CHECK(not j.contains("/3"_json_pointer));
// assign to nonexisting index (with gap)
CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range&);
CHECK_THROWS_WITH(j.at("/5"_json_pointer),
"[json.exception.out_of_range.401] array index 5 is out of range");
CHECK(not j.contains("/5"_json_pointer));
// assign to "-"
CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range&);
@ -341,8 +391,8 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range&);
CHECK_THROWS_WITH(j.at("/-"_json_pointer),
"[json.exception.out_of_range.402] array index '-' (3) is out of range");
CHECK(not j.contains("/-"_json_pointer));
}
}
SECTION("flatten")
@ -438,6 +488,7 @@ TEST_CASE("JSON pointers")
})
{
CHECK(json::json_pointer(ptr).to_string() == ptr);
CHECK(std::string(json::json_pointer(ptr)) == ptr);
}
}
@ -460,7 +511,83 @@ TEST_CASE("JSON pointers")
}
}
SECTION("push and pop")
SECTION("empty, push, pop and parent")
{
const json j =
{
{"", "Hello"},
{"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"}
}
}
};
// empty json_pointer returns the root JSON-object
auto ptr = ""_json_pointer;
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// simple field access
ptr.push_back("pi");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// object and children access
const std::string answer("answer");
ptr.push_back(answer);
ptr.push_back("everything");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["answer"]["everything"]);
// check access via const pointer
const auto cptr = ptr;
CHECK(cptr.back() == "everything");
ptr.pop_back();
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// push key which has to be encoded
ptr.push_back("object");
ptr.push_back("/");
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
CHECK(j[ptr.parent_pointer()] == j["object"]);
ptr = ptr.parent_pointer().parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// parent-pointer of the empty json_pointer is empty
ptr = ptr.parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
CHECK_THROWS_WITH(ptr.pop_back(),
"[json.exception.out_of_range.405] JSON pointer has no parent");
}
SECTION("operators")
{
const json j =
{
@ -492,24 +619,31 @@ TEST_CASE("JSON pointers")
CHECK(j[ptr] == j);
// simple field access
ptr.push_back("pi");
ptr = ptr / "pi";
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(j[ptr] == j);
// object and children access
ptr.push_back("answer");
ptr.push_back("everything");
const std::string answer("answer");
ptr /= answer;
ptr = ptr / "everything";
CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_back();
ptr.pop_back();
CHECK(j[ptr] == j);
CHECK(ptr / ""_json_pointer == ptr);
CHECK(j["/answer"_json_pointer / "/everything"_json_pointer] == j["answer"]["everything"]);
// list children access
CHECK(j["/list"_json_pointer / 1] == j["list"][1]);
// push key which has to be encoded
ptr.push_back("object");
ptr.push_back("/");
ptr /= "object";
ptr = ptr / "/";
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -43,10 +43,10 @@ TEST_CASE("version information")
CHECK(j["url"] == "https://github.com/nlohmann/json");
CHECK(j["version"] == json(
{
{"string", "3.5.0"},
{"string", "3.7.1"},
{"major", 3},
{"minor", 5},
{"patch", 0}
{"minor", 7},
{"patch", 1}
}));
CHECK(j.find("platform") != j.end());

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -290,8 +290,10 @@ TEST_CASE("modifiers")
SECTION("null")
{
json j;
j.emplace_back(1);
j.emplace_back(2);
auto& x1 = j.emplace_back(1);
CHECK(x1 == 1);
auto& x2 = j.emplace_back(2);
CHECK(x2 == 2);
CHECK(j.type() == json::value_t::array);
CHECK(j == json({1, 2}));
}
@ -299,7 +301,8 @@ TEST_CASE("modifiers")
SECTION("array")
{
json j = {1, 2, 3};
j.emplace_back("Hello");
auto& x = j.emplace_back("Hello");
CHECK(x == "Hello");
CHECK(j.type() == json::value_t::array);
CHECK(j == json({1, 2, 3, "Hello"}));
}
@ -307,7 +310,8 @@ TEST_CASE("modifiers")
SECTION("multiple values")
{
json j;
j.emplace_back(3, "foo");
auto& x = j.emplace_back(3, "foo");
CHECK(x == json({"foo", "foo", "foo"}));
CHECK(j.type() == json::value_t::array);
CHECK(j == json({{"foo", "foo", "foo"}}));
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,13 +27,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <sstream>
#include <iomanip>
#include <set>
namespace
{
class SaxCountdown
{
public:
@ -103,6 +108,7 @@ class SaxCountdown
private:
int events_left = 0;
};
}
TEST_CASE("MessagePack")
{
@ -1122,71 +1128,73 @@ TEST_CASE("MessagePack")
{
SECTION("empty byte vector")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>()),
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>()),
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input");
CHECK(json::from_msgpack(std::vector<uint8_t>(), true, false).is_discarded());
}
SECTION("too short byte vector")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x87})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcc})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x87})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcc})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcd})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xce})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x87})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0x87})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcc})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcc})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcd})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xce})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf})),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing MessagePack number: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack string: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing MessagePack value: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})),
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack value: unexpected end of input");
CHECK(json::from_msgpack(std::vector<uint8_t>({0x87}), true, false).is_discarded());
@ -1214,13 +1222,14 @@ TEST_CASE("MessagePack")
{
SECTION("concrete examples")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc1})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc1})),
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xc1})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xc1})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC1");
CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc6})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc6})),
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xc6})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0xc6})),
"[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC6");
CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
}
@ -1239,7 +1248,8 @@ TEST_CASE("MessagePack")
0xd4, 0xd5, 0xd6, 0xd7, 0xd8
})
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
CHECK(json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)}), true, false).is_discarded());
}
}
@ -1247,8 +1257,9 @@ TEST_CASE("MessagePack")
SECTION("invalid string in map")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})),
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})),
"[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF");
CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
}
@ -1264,8 +1275,9 @@ TEST_CASE("MessagePack")
SECTION("strict mode")
{
CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec),
json _;
CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(vec),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack value: expected end of input; last byte: 0xC0");
CHECK(json::from_msgpack(vec, true, false).is_discarded());
}
@ -1297,7 +1309,6 @@ TEST_CASE("MessagePack")
}
}
// use this testcase outside [hide] to run it with Valgrind
TEST_CASE("single MessagePack roundtrip")
{
@ -1323,7 +1334,7 @@ TEST_CASE("single MessagePack roundtrip")
{
SECTION("std::ostringstream")
{
std::ostringstream ss;
std::basic_ostringstream<std::uint8_t> ss;
json::to_msgpack(j1, ss);
json j3 = json::from_msgpack(ss.str());
CHECK(j1 == j3);
@ -1344,12 +1355,11 @@ TEST_CASE("single MessagePack roundtrip")
}
}
TEST_CASE("MessagePack roundtrips", "[hide]")
TEST_CASE("MessagePack roundtrips" * doctest::skip())
{
SECTION("input from msgpack-python")
{
// most of these are exluded due to differences in key order (not a real problem)
// most of these are excluded due to differences in key order (not a real problem)
auto exclude_packed = std::set<std::string>
{
"test/data/json.org/1.json",
@ -1519,8 +1529,8 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
{
CAPTURE(filename)
SECTION(filename + ": std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1537,8 +1547,8 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": std::ifstream")
{
INFO_WITH_TEMP(filename + ": std::ifstream");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1552,8 +1562,8 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": uint8_t* and size")
{
INFO_WITH_TEMP(filename + ": uint8_t* and size");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1570,8 +1580,8 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": output to output adapters")
{
INFO_WITH_TEMP(filename + ": output to output adapters");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -1584,8 +1594,8 @@ TEST_CASE("MessagePack roundtrips", "[hide]")
if (!exclude_packed.count(filename))
{
SECTION(filename + ": output adapters: std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
std::vector<uint8_t> vec;
json::to_msgpack(j1, vec);
CHECK(vec == packed);

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace
{
enum test
{
};
@ -58,6 +61,7 @@ static_assert(noexcept(json(pod{})), "");
static_assert(noexcept(j.get<pod>()), "");
static_assert(not noexcept(j.get<pod_bis>()), "");
static_assert(noexcept(json(pod{})), "");
}
TEST_CASE("runtime checks")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -35,16 +36,19 @@ using nlohmann::json;
#include <deque>
#include <forward_list>
#include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <iostream>
#include <sstream>
#include <iomanip>
#if defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4189) // local variable is initialized but not referenced
#endif
TEST_CASE("README", "[hide]")
TEST_CASE("README" * doctest::skip())
{
{
// redirect std::cout for the README file

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
#include <nlohmann/json.hpp>
using nlohmann::json;

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
// for some reason including this after the json header leads to linker errors with VS 2017...
#include <locale>
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <fstream>
#include <sstream>
#include <list>
#include <cstdio>
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
@ -43,10 +53,6 @@ using nlohmann::json;
#include "fifo_map.hpp"
#include <fstream>
#include <list>
#include <cstdio>
/////////////////////////////////////////////////////////////////////
// for #972
/////////////////////////////////////////////////////////////////////
@ -124,8 +130,10 @@ struct nocopy
struct Data
{
std::string a;
std::string b;
Data() = default;
Data(const std::string& a_, const std::string b_) : a(a_), b(b_) {}
std::string a {};
std::string b {};
};
void from_json(const json& j, Data& data)
@ -151,12 +159,55 @@ bool operator==(Data const& lhs, Data const& rhs)
using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;
/////////////////////////////////////////////////////////////////////
// for #1647
/////////////////////////////////////////////////////////////////////
namespace
{
struct NonDefaultFromJsonStruct { };
inline bool operator== (NonDefaultFromJsonStruct const&, NonDefaultFromJsonStruct const&)
{
return true;
}
enum class for_1647 { one, two };
NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
{
{for_1647::one, "one"},
{for_1647::two, "two"},
})
}
namespace nlohmann
{
template <>
struct adl_serializer<NonDefaultFromJsonStruct>
{
static NonDefaultFromJsonStruct from_json (json const&) noexcept
{
return {};
}
};
}
/////////////////////////////////////////////////////////////////////
// for #1805
/////////////////////////////////////////////////////////////////////
struct NotSerializableData
{
int mydata;
float myfloat;
};
TEST_CASE("regression tests")
{
SECTION("issue #60 - Double quotation mark is not parsed correctly")
{
SECTION("escape_dobulequote")
SECTION("escape_doublequote")
{
auto s = "[\"\\\"foo\\\"\"]";
json j = json::parse(s);
@ -285,7 +336,7 @@ TEST_CASE("regression tests")
int number = j["Number"];
CHECK(number == 100);
float foo = j["Foo"];
CHECK(foo == Approx(42.42));
CHECK(static_cast<double>(foo) == Approx(42.42));
}
SECTION("issue #89 - nonstandard integer type")
@ -295,8 +346,7 @@ TEST_CASE("regression tests")
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);
CHECK(j["int_1"] == 1);
// tests for correct handling of non-standard integers that overflow the type selected by the user
@ -689,8 +739,9 @@ TEST_CASE("regression tests")
SECTION("issue #329 - serialized value not always can be parsed")
{
CHECK_THROWS_AS(json::parse("22e2222"), json::out_of_range&);
CHECK_THROWS_WITH(json::parse("22e2222"),
json _;
CHECK_THROWS_AS(_ = json::parse("22e2222"), json::out_of_range&);
CHECK_THROWS_WITH(_ = json::parse("22e2222"),
"[json.exception.out_of_range.406] number overflow parsing '22e2222'");
}
@ -712,7 +763,7 @@ TEST_CASE("regression tests")
};
check_roundtrip(100000000000.1236);
check_roundtrip(std::numeric_limits<json::number_float_t>::max());
check_roundtrip((std::numeric_limits<json::number_float_t>::max)());
// Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
check_roundtrip(1.541888611948064e-17);
@ -755,8 +806,9 @@ TEST_CASE("regression tests")
SECTION("issue #366 - json::parse on failed stream gets stuck")
{
std::ifstream f("file_not_found.json");
CHECK_THROWS_AS(json::parse(f), json::parse_error&);
CHECK_THROWS_WITH(json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
json _;
CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
}
SECTION("issue #367 - calling stream at EOF")
@ -951,50 +1003,55 @@ TEST_CASE("regression tests")
{
// original test case
std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21};
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec),
"[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR string: unexpected end of input");
}
SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)")
{
json _;
// original test case: incomplete float64
std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec1),
CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(vec1),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
// related test case: incomplete float32
std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec2),
CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(vec2),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input");
// related test case: incomplete Half-Precision Float (CBOR)
std::vector<uint8_t> vec3 {0xf9, 0x8f};
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec3),
CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input");
// related test case: incomplete Single-Precision Float (CBOR)
std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec4),
CHECK_THROWS_AS(_ = json::from_cbor(vec4), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec4),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
// related test case: incomplete Double-Precision Float (CBOR)
std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec5),
CHECK_THROWS_AS(_ = json::from_cbor(vec5), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec5),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input");
}
SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)")
{
json _;
// original test case
std::vector<uint8_t> vec1 {0x87};
CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec1),
CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(vec1),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input");
// more test cases for MessagePack
@ -1007,7 +1064,7 @@ TEST_CASE("regression tests")
})
{
std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&);
}
// more test cases for CBOR
@ -1022,37 +1079,39 @@ TEST_CASE("regression tests")
})
{
std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
}
// special case: empty input
std::vector<uint8_t> vec2;
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec2),
CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input");
CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec2),
CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_msgpack(vec2),
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input");
}
SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)")
{
json _;
// original test case: empty UTF-8 string (indefinite length)
std::vector<uint8_t> vec1 {0x7f};
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec1),
CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
// related test case: empty array (indefinite length)
std::vector<uint8_t> vec2 {0x9f};
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec2),
CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: unexpected end of input");
// related test case: empty map (indefinite length)
std::vector<uint8_t> vec3 {0xbf};
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec3),
CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input");
}
@ -1079,26 +1138,28 @@ TEST_CASE("regression tests")
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
};
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec),
"[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98");
// related test case: nonempty UTF-8 string (indefinite length)
std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec1),
CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
"[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR string: unexpected end of input");
// related test case: nonempty array (indefinite length)
std::vector<uint8_t> vec2 {0x9f, 0x01};
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec2),
CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input");
// related test case: nonempty map (indefinite length)
std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01};
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec3),
CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input");
}
@ -1132,8 +1193,10 @@ TEST_CASE("regression tests")
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa
};
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec1),
json _;
CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec1),
"[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4");
// related test case: double-precision
@ -1146,15 +1209,16 @@ TEST_CASE("regression tests")
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
};
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec2),
CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_cbor(vec2),
"[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4");
}
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
{
std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'};
CHECK_THROWS_AS(json::parse(vec), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
}
SECTION("issue #454 - doubles are printed as integers")
@ -1302,8 +1366,9 @@ TEST_CASE("regression tests")
SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)")
{
json _;
std::vector<uint8_t> vec = {'"', '\\', '"', 'X', '"', '"'};
CHECK_THROWS_AS(json::parse(vec), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
}
SECTION("issue #600 - how does one convert a map in Json back to std::map?")
@ -1342,7 +1407,8 @@ TEST_CASE("regression tests")
SECTION("issue #602 - BOM not skipped when using json:parse(iterator)")
{
std::string i = "\xef\xbb\xbf{\n \"foo\": true\n}";
CHECK_NOTHROW(json::parse(i.begin(), i.end()));
json _;
CHECK_NOTHROW(_ = json::parse(i.begin(), i.end()));
}
SECTION("issue #702 - conversion from valarray<double> to json fails to build")
@ -1405,7 +1471,8 @@ TEST_CASE("regression tests")
); // handle different exceptions as 'file not found', 'permission denied'
is.open("test/data/regression/working_file.json");
CHECK_NOTHROW(nlohmann::json::parse(is));
json _;
CHECK_NOTHROW(_ = nlohmann::json::parse(is));
}
{
@ -1418,7 +1485,8 @@ TEST_CASE("regression tests")
is.open("test/data/json_nlohmann_tests/all_unicode.json.cbor",
std::ios_base::in | std::ios_base::binary);
CHECK_NOTHROW(nlohmann::json::from_cbor(is));
json _;
CHECK_NOTHROW(_ = nlohmann::json::from_cbor(is));
}
}
@ -1498,13 +1566,14 @@ TEST_CASE("regression tests")
SECTION("issue #962 - Timeout (OSS-Fuzz 6034)")
{
json _;
std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
//CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
// "[json.exception.out_of_range.408] excessive array size: 8658170730974374167");
v_ubjson[0] = '{';
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
//CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
// "[json.exception.out_of_range.408] excessive object size: 8658170730974374167");
}
@ -1701,7 +1770,7 @@ TEST_CASE("regression tests")
std::map<std::string, Data> expected
{
{"1", {"testa_1", "testb_1" }},
{"1", {"testa_1", "testb_1"}},
{"2", {"testa_2", "testb_2"}},
{"3", {"testa_3", "testb_3"}},
};
@ -1723,31 +1792,37 @@ TEST_CASE("regression tests")
{
SECTION("a bunch of -1, ensure_ascii=true")
{
const auto length = 300;
json dump_test;
std::vector<char> data(300, -1);
std::vector<std::string> vec_string(300, "\\ufffd");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
dump_test["1"] = std::string(length, -1);
std::string expected = "{\"1\":\"";
for (int i = 0; i < length; ++i)
{
expected += "\\ufffd";
}
expected += "\"}";
auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
CHECK(s == expected);
}
SECTION("a bunch of -2, ensure_ascii=false")
{
const auto length = 500;
json dump_test;
std::vector<char> data(500, -2);
std::vector<std::string> vec_string(500, "\xEF\xBF\xBD");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
dump_test["1"] = std::string(length, -2);
std::string expected = "{\"1\":\"";
for (int i = 0; i < length; ++i)
{
expected += "\xEF\xBF\xBD";
}
expected += "\"}";
auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
CHECK(s == expected);
}
SECTION("test case in issue #1445")
{
@ -1772,7 +1847,7 @@ TEST_CASE("regression tests")
-54, -28, -26
};
std::string s;
for (int i = 0; i < sizeof(data) / sizeof(int); i++)
for (unsigned i = 0; i < sizeof(data) / sizeof(int); i++)
{
s += static_cast<char>(data[i]);
}
@ -1786,9 +1861,55 @@ TEST_CASE("regression tests")
json j = json::parse("[-9223372036854775808]");
CHECK(j.dump() == "[-9223372036854775808]");
}
SECTION("issue #1708 - minimum value of int64_t can be outputted")
{
constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
json j = smallest;
CHECK(j.dump() == std::to_string(smallest));
}
SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload")
{
json j = {{"root", {{"settings", {{"logging", true}}}}}};
auto jptr1 = "/root/settings/logging"_json_pointer;
auto jptr2 = json::json_pointer{"/root/settings/logging"};
CHECK(j.contains(jptr1));
CHECK(j.contains(jptr2));
}
SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type")
{
{
json j;
NonDefaultFromJsonStruct x = j;
NonDefaultFromJsonStruct y;
CHECK(x == y);
}
auto val = nlohmann::json("one").get<for_1647>();
CHECK(val == for_1647::one);
json j = val;
}
SECTION("issue #1805 - A pair<T1, T2> is json constructible only if T1 and T2 are json constructible")
{
static_assert(!std::is_constructible<json, std::pair<std::string, NotSerializableData>>::value, "");
static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "");
static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "");
}
SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
{
static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "");
static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "");
static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "");
}
}
TEST_CASE("regression tests, exceptions dependent", "[!throws]")
#if not defined(JSON_NOEXCEPTION)
TEST_CASE("regression tests, exceptions dependent")
{
SECTION("issue #1340 - eof not set on exhausted input stream")
{
@ -1800,3 +1921,14 @@ TEST_CASE("regression tests, exceptions dependent", "[!throws]")
CHECK(s.eof());
}
}
#endif
/////////////////////////////////////////////////////////////////////
// for #1642
/////////////////////////////////////////////////////////////////////
template <typename T> class array {};
template <typename T> class object {};
template <typename T> class string {};
template <typename T> class number_integer {};
template <typename T> class number_unsigned {};
template <typename T> class number_float {};

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,11 +27,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <sstream>
#include <iomanip>
TEST_CASE("serialization")
{
SECTION("operator<<")
@ -170,4 +173,36 @@ TEST_CASE("serialization")
test("\xE1\x80\xE2\xF0\x91\x92\xF1\xBF\x41", "\\ufffd" "\\ufffd" "\\ufffd" "\\ufffd" "\x41");
}
}
SECTION("to_string")
{
auto test = [&](std::string const & input, std::string const & expected)
{
using std::to_string;
json j = input;
CHECK(to_string(j) == "\"" + expected + "\"");
};
test("{\"x\":5,\"y\":6}", "{\\\"x\\\":5,\\\"y\\\":6}");
test("{\"x\":[10,null,null,null]}", "{\\\"x\\\":[10,null,null,null]}");
test("test", "test");
test("[3,\"false\",false]", "[3,\\\"false\\\",false]");
}
}
TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t)
{
SECTION("minimum")
{
constexpr auto minimum = (std::numeric_limits<T>::min)();
json j = minimum;
CHECK(j.dump() == std::to_string(minimum));
}
SECTION("maximum")
{
constexpr auto maximum = (std::numeric_limits<T>::max)();
json j = maximum;
CHECK(j.dump() == std::to_string(maximum));
}
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
@ -79,7 +79,8 @@ TEST_CASE("compliance tests from json.org")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_THROWS_AS(json::parse(f), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&);
}
}
@ -387,38 +388,37 @@ TEST_CASE("json.org examples")
SECTION("FILE 1.json")
{
std::unique_ptr<std::FILE, decltype(&std::fclose)> f(std::fopen("test/data/json.org/1.json", "r"), &std::fclose);
json j;
CHECK_NOTHROW(j.parse(f.get()));
json _;
CHECK_NOTHROW(_ = json::parse(f.get()));
}
SECTION("FILE 2.json")
{
std::unique_ptr<std::FILE, decltype(&std::fclose)> f(std::fopen("test/data/json.org/2.json", "r"), &std::fclose);
json j;
CHECK_NOTHROW(j.parse(f.get()));
json _;
CHECK_NOTHROW(_ = json::parse(f.get()));
}
SECTION("FILE 3.json")
{
std::unique_ptr<std::FILE, decltype(&std::fclose)> f(std::fopen("test/data/json.org/3.json", "r"), &std::fclose);
json j;
CHECK_NOTHROW(j.parse(f.get()));
json _;
CHECK_NOTHROW(_ = json::parse(f.get()));
}
SECTION("FILE 4.json")
{
std::unique_ptr<std::FILE, decltype(&std::fclose)> f(std::fopen("test/data/json.org/4.json", "r"), &std::fclose);
json j;
CHECK_NOTHROW(j.parse(f.get()));
json _;
CHECK_NOTHROW(_ = json::parse(f.get()));
}
SECTION("FILE 5.json")
{
std::unique_ptr<std::FILE, decltype(&std::fclose)> f(std::fopen("test/data/json.org/5.json", "r"), &std::fclose);
json j;
CHECK_NOTHROW(j.parse(f.get()));
json _;
CHECK_NOTHROW(_ = json::parse(f.get()));
}
}
TEST_CASE("RFC 7159 examples")
@ -811,7 +811,8 @@ TEST_CASE("nst's JSONTestSuite")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_THROWS_AS(json::parse(f), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&);
}
}
@ -1028,7 +1029,8 @@ TEST_CASE("nst's JSONTestSuite (2)")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_NOTHROW(json::parse(f));
json _;
CHECK_NOTHROW(_ = json::parse(f));
std::ifstream f2(filename);
CHECK(json::accept(f2));
}
@ -1229,7 +1231,8 @@ TEST_CASE("nst's JSONTestSuite (2)")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_THROWS_AS(json::parse(f), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&);
std::ifstream f2(filename);
CHECK(not json::accept(f2));
}
@ -1294,7 +1297,8 @@ TEST_CASE("nst's JSONTestSuite (2)")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_NOTHROW(json::parse(f));
json _;
CHECK_NOTHROW(_ = json::parse(f));
std::ifstream f2(filename);
CHECK(json::accept(f2));
}
@ -1344,7 +1348,8 @@ TEST_CASE("nst's JSONTestSuite (2)")
{
CAPTURE(filename)
std::ifstream f(filename);
CHECK_THROWS_AS(json::parse(f), json::exception&); // could be parse_error or out_of_range
json _;
CHECK_THROWS_AS(_ = json::parse(f), json::exception&); // could be parse_error or out_of_range
std::ifstream f2(filename);
CHECK(not json::accept(f2));
}
@ -1352,6 +1357,8 @@ TEST_CASE("nst's JSONTestSuite (2)")
}
}
namespace
{
std::string trim(const std::string& str);
// from http://stackoverflow.com/a/25829178/266378
@ -1365,6 +1372,7 @@ std::string trim(const std::string& str)
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last - first + 1));
}
}
TEST_CASE("Big List of Naughty Strings")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -31,11 +31,13 @@ SOFTWARE.
// Only compile these tests if 'float' and 'double' are IEEE-754 single- and
// double-precision numbers, resp.
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::detail::dtoa_impl::reinterpret_bits;
namespace
{
static float make_float(uint32_t sign_bit, uint32_t biased_exponent, uint32_t significand)
{
assert(sign_bit == 0 || sign_bit == 1);
@ -139,6 +141,7 @@ static double make_double(uint64_t f, int e)
uint64_t bits = (f & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize);
return reinterpret_bits<double>(bits);
}
}
TEST_CASE("digit gen")
{
@ -356,7 +359,7 @@ TEST_CASE("formatting")
{
auto check_float = [](float number, const std::string & expected)
{
char buf[32];
char buf[33];
char* end = nlohmann::detail::to_chars(buf, buf + 32, number);
std::string actual(buf, end);
@ -416,7 +419,7 @@ TEST_CASE("formatting")
{
auto check_double = [](double number, const std::string & expected)
{
char buf[32];
char buf[33];
char* end = nlohmann::detail::to_chars(buf, buf + 32, number);
std::string actual(buf, end);

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,13 +27,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <fstream>
#include <set>
namespace
{
class SaxCountdown
{
public:
@ -103,6 +106,7 @@ class SaxCountdown
private:
int events_left = 0;
};
}
TEST_CASE("UBJSON")
{
@ -1297,8 +1301,9 @@ TEST_CASE("UBJSON")
SECTION("strict mode")
{
CHECK_THROWS_AS(json::from_ubjson(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vec),
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(vec), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vec),
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: expected end of input; last byte: 0x5A");
}
}
@ -1307,8 +1312,9 @@ TEST_CASE("UBJSON")
{
// larger than max int64
json j = 9223372036854775808llu;
CHECK_THROWS_AS(json::to_ubjson(j), json::out_of_range&);
CHECK_THROWS_WITH(json::to_ubjson(j), "[json.exception.out_of_range.407] integer number 9223372036854775808 cannot be represented by UBJSON as it does not fit int64");
json _;
CHECK_THROWS_AS(_ = json::to_ubjson(j), json::out_of_range&);
CHECK_THROWS_WITH(_ = json::to_ubjson(j), "[json.exception.out_of_range.407] integer number 9223372036854775808 cannot be represented by UBJSON as it does not fit int64");
}
SECTION("excessive size")
@ -1316,27 +1322,29 @@ TEST_CASE("UBJSON")
SECTION("array")
{
std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
json j;
nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int, json::parse_event_t, const json&)
{
return true;
});
CHECK_THROWS_AS(json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
CHECK_THROWS_AS(_ = json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
}
SECTION("object")
{
std::vector<uint8_t> v_ubjson = {'{', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
json j;
nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int, json::parse_event_t, const json&)
{
return true;
});
CHECK_THROWS_AS(json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
CHECK_THROWS_AS(_ = json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
}
}
}
@ -1527,8 +1535,9 @@ TEST_CASE("UBJSON")
{
SECTION("empty byte vector")
{
CHECK_THROWS_AS(json::from_ubjson(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(std::vector<uint8_t>()),
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(std::vector<uint8_t>()),
"[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing UBJSON value: unexpected end of input");
}
@ -1537,15 +1546,17 @@ TEST_CASE("UBJSON")
SECTION("eof after C byte")
{
std::vector<uint8_t> v = {'C'};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input");
}
SECTION("byte out of range")
{
std::vector<uint8_t> v = {'C', 130};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82");
}
}
@ -1554,15 +1565,17 @@ TEST_CASE("UBJSON")
SECTION("eof after S byte")
{
std::vector<uint8_t> v = {'S'};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input");
}
SECTION("invalid byte")
{
std::vector<uint8_t> v = {'S', '1', 'a'};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x31");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x31");
}
}
@ -1571,138 +1584,144 @@ TEST_CASE("UBJSON")
SECTION("optimized array: no size following type")
{
std::vector<uint8_t> v = {'[', '$', 'i', 2};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x02");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x02");
}
}
SECTION("strings")
{
std::vector<uint8_t> vS = {'S'};
CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vS, true, false).is_discarded());
std::vector<uint8_t> v = {'S', 'i', '2', 'a'};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON string: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON string: unexpected end of input");
CHECK(json::from_ubjson(v, true, false).is_discarded());
std::vector<uint8_t> vC = {'C'};
CHECK_THROWS_AS(json::from_ubjson(vC), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vC), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON char: unexpected end of input");
CHECK(json::from_ubjson(vC, true, false).is_discarded());
}
SECTION("sizes")
{
std::vector<uint8_t> vU = {'[', '#', 'U'};
CHECK_THROWS_AS(json::from_ubjson(vU), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(vU), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vU, true, false).is_discarded());
std::vector<uint8_t> vi = {'[', '#', 'i'};
CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vi), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vi, true, false).is_discarded());
std::vector<uint8_t> vI = {'[', '#', 'I'};
CHECK_THROWS_AS(json::from_ubjson(vI), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vI), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vI, true, false).is_discarded());
std::vector<uint8_t> vl = {'[', '#', 'l'};
CHECK_THROWS_AS(json::from_ubjson(vl), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vl), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vl, true, false).is_discarded());
std::vector<uint8_t> vL = {'[', '#', 'L'};
CHECK_THROWS_AS(json::from_ubjson(vL), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vL), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vL, true, false).is_discarded());
std::vector<uint8_t> v0 = {'[', '#', 'T', ']'};
CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x54");
CHECK_THROWS_AS(_ = json::from_ubjson(v0), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x54");
CHECK(json::from_ubjson(v0, true, false).is_discarded());
}
SECTION("types")
{
std::vector<uint8_t> v0 = {'[', '$'};
CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing UBJSON type: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(v0), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing UBJSON type: unexpected end of input");
CHECK(json::from_ubjson(v0, true, false).is_discarded());
std::vector<uint8_t> vi = {'[', '$', '#'};
CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vi), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vi, true, false).is_discarded());
std::vector<uint8_t> vT = {'[', '$', 'T'};
CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vT), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vT, true, false).is_discarded());
}
SECTION("arrays")
{
std::vector<uint8_t> vST = {'[', '$', 'i', '#', 'i', 2, 1};
CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(vST), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vST, true, false).is_discarded());
std::vector<uint8_t> vS = {'[', '#', 'i', 2, 'i', 1};
CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vS, true, false).is_discarded());
std::vector<uint8_t> v = {'[', 'i', 2, 'i', 1};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(v, true, false).is_discarded());
}
SECTION("objects")
{
std::vector<uint8_t> vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1};
CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing UBJSON value: unexpected end of input");
json _;
CHECK_THROWS_AS(_ = json::from_ubjson(vST), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vST, true, false).is_discarded());
std::vector<uint8_t> vT = {'{', '$', 'i', 'i', 1, 'a', 1};
CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x69");
CHECK_THROWS_AS(_ = json::from_ubjson(vT), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x69");
CHECK(json::from_ubjson(vT, true, false).is_discarded());
std::vector<uint8_t> vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1};
CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vS), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vS, true, false).is_discarded());
std::vector<uint8_t> v = {'{', 'i', 1, 'a', 'i', 1};
CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(v), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(v, true, false).is_discarded());
std::vector<uint8_t> v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'};
CHECK_THROWS_AS(json::from_ubjson(v2), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(v2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(v2, true, false).is_discarded());
std::vector<uint8_t> v3 = {'{', 'i', 1, 'a'};
CHECK_THROWS_AS(json::from_ubjson(v3), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(v3), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(v3, true, false).is_discarded());
std::vector<uint8_t> vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'};
CHECK_THROWS_AS(json::from_ubjson(vST1), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON number: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vST1), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing UBJSON number: unexpected end of input");
CHECK(json::from_ubjson(vST1, true, false).is_discarded());
std::vector<uint8_t> vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'};
CHECK_THROWS_AS(json::from_ubjson(vST2), json::parse_error&);
CHECK_THROWS_WITH(json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON value: unexpected end of input");
CHECK_THROWS_AS(_ = json::from_ubjson(vST2), json::parse_error&);
CHECK_THROWS_WITH(_ = json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing UBJSON value: unexpected end of input");
CHECK(json::from_ubjson(vST2, true, false).is_discarded());
}
}
@ -2113,7 +2132,8 @@ TEST_CASE("Universal Binary JSON Specification Examples 1")
}
}
TEST_CASE("all UBJSON first bytes", "[!throws]")
#if not defined(JSON_NOEXCEPTION)
TEST_CASE("all UBJSON first bytes")
{
// these bytes will fail immediately with exception parse_error.112
std::set<uint8_t> supported =
@ -2134,7 +2154,7 @@ TEST_CASE("all UBJSON first bytes", "[!throws]")
{
// check that parse_error.112 is only thrown if the
// first byte is not in the supported set
CAPTURE(e.what())
INFO_WITH_TEMP(e.what());
if (std::find(supported.begin(), supported.end(), byte) == supported.end())
{
CHECK(e.id == 112);
@ -2146,8 +2166,9 @@ TEST_CASE("all UBJSON first bytes", "[!throws]")
}
}
}
#endif
TEST_CASE("UBJSON roundtrips", "[hide]")
TEST_CASE("UBJSON roundtrips" * doctest::skip())
{
SECTION("input from self-generated UBJSON files")
{
@ -2199,8 +2220,8 @@ TEST_CASE("UBJSON roundtrips", "[hide]")
{
CAPTURE(filename)
SECTION(filename + ": std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -2217,8 +2238,8 @@ TEST_CASE("UBJSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": std::ifstream")
{
INFO_WITH_TEMP(filename + ": std::ifstream");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -2232,8 +2253,8 @@ TEST_CASE("UBJSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": uint8_t* and size")
{
INFO_WITH_TEMP(filename + ": uint8_t* and size");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -2250,8 +2271,8 @@ TEST_CASE("UBJSON roundtrips", "[hide]")
CHECK(j1 == j2);
}
SECTION(filename + ": output to output adapters")
{
INFO_WITH_TEMP(filename + ": output to output adapters");
// parse JSON file
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
@ -2262,8 +2283,8 @@ TEST_CASE("UBJSON roundtrips", "[hide]")
(std::istreambuf_iterator<char>(f_ubjson)),
std::istreambuf_iterator<char>());
SECTION(filename + ": output adapters: std::vector<uint8_t>")
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
std::vector<uint8_t> vec;
json::to_ubjson(j1, vec);
CHECK(vec == packed);

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,10 +27,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <array>
@ -236,10 +235,10 @@ void from_json(const nlohmann::json& j, contact_book& cb)
}
}
TEST_CASE("basic usage", "[udt]")
TEST_CASE("basic usage" * doctest::test_suite("udt"))
{
// a bit narcissic maybe :) ?
// a bit narcissistic maybe :) ?
const udt::age a
{
23
@ -392,7 +391,7 @@ struct adl_serializer<udt::legacy_type>
};
}
TEST_CASE("adl_serializer specialization", "[udt]")
TEST_CASE("adl_serializer specialization" * doctest::test_suite("udt"))
{
SECTION("partial specialization")
{
@ -468,7 +467,7 @@ struct adl_serializer<std::vector<float>>
};
}
TEST_CASE("even supported types can be specialized", "[udt]")
TEST_CASE("even supported types can be specialized" * doctest::test_suite("udt"))
{
json j = std::vector<float> {1.0, 2.0, 3.0};
CHECK(j.dump() == R"("hijacked!")");
@ -509,7 +508,7 @@ struct adl_serializer<std::unique_ptr<T>>
};
}
TEST_CASE("Non-copyable types", "[udt]")
TEST_CASE("Non-copyable types" * doctest::test_suite("udt"))
{
SECTION("to_json")
{
@ -599,9 +598,8 @@ struct pod_serializer
static void to_json(BasicJsonType& j, const T& t) noexcept
{
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
std::uint64_t value = bytes[0];
for (auto i = 1; i < 8; ++i)
value |= std::uint64_t{bytes[i]} << 8 * i;
std::uint64_t value;
std::memcpy(&value, bytes, sizeof(value));
nlohmann::to_json(j, value);
}
};
@ -651,7 +649,7 @@ std::ostream& operator<<(std::ostream& os, small_pod l)
}
}
TEST_CASE("custom serializer for pods", "[udt]")
TEST_CASE("custom serializer for pods" * doctest::test_suite("udt"))
{
using custom_json =
nlohmann::basic_json<std::map, std::vector, std::string, bool,
@ -692,7 +690,7 @@ struct another_adl_serializer
}
};
TEST_CASE("custom serializer that does adl by default", "[udt]")
TEST_CASE("custom serializer that does adl by default" * doctest::test_suite("udt"))
{
using json = nlohmann::json;
@ -798,7 +796,7 @@ template <typename T>
struct is_constructible_patched<T, decltype(void(json(std::declval<T>())))> : std::true_type {};
}
TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated context", "[udt]")
TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated context" * doctest::test_suite("udt"))
{
static_assert(not is_constructible_patched<json, incomplete>::value, "");
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,15 +27,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
// for some reason including this after the json header leads to linker errors with VS 2017...
#include <locale>
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip>
namespace
{
extern size_t calls;
size_t calls = 0;
@ -150,17 +158,19 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte
CAPTURE(json_string)
json _;
if (success_expected)
{
CHECK_NOTHROW(json::parse(json_string));
CHECK_NOTHROW(_ = json::parse(json_string));
}
else
{
CHECK_THROWS_AS(json::parse(json_string), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse(json_string), json::parse_error&);
}
}
}
TEST_CASE("Unicode", "[hide]")
TEST_CASE("Unicode" * doctest::skip())
{
SECTION("RFC 3629")
{
@ -1042,7 +1052,8 @@ TEST_CASE("Unicode", "[hide]")
json_text += "\"";
CAPTURE(json_text)
CHECK_NOTHROW(json::parse(json_text));
json _;
CHECK_NOTHROW(_ = json::parse(json_text));
}
}
@ -1050,32 +1061,34 @@ TEST_CASE("Unicode", "[hide]")
{
SECTION("incorrect surrogate values")
{
CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uDC00\\uDC00\""),
json _;
CHECK_THROWS_AS(_ = json::parse("\"\\uDC00\\uDC00\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uDC00\\uDC00\""),
"[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uDC00'");
CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD7FF\\uDC00\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD7FF\\uDC00\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD7FF\\uDC00\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uD7FF\\uDC00'");
CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD800]\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD800]\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD800]\""),
"[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800]'");
CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD800\\v\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD800\\v\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD800\\v\""),
"[json.exception.parse_error.101] parse error at line 1, column 9: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\v'");
CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD800\\u123\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD800\\u123\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD800\\u123\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\uD800\\u123\"'");
CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD800\\uDBFF\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD800\\uDBFF\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD800\\uDBFF\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uDBFF'");
CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error&);
CHECK_THROWS_WITH(json::parse("\"\\uD800\\uE000\""),
CHECK_THROWS_AS(_ = json::parse("\"\\uD800\\uE000\""), json::parse_error&);
CHECK_THROWS_WITH(_ = json::parse("\"\\uD800\\uE000\""),
"[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uE000'");
}
}
@ -1139,7 +1152,7 @@ TEST_CASE("Unicode", "[hide]")
json j;
CHECK_NOTHROW(f >> j);
// the array has 1112064 + 1 elemnts (a terminating "null" value)
// the array has 1112064 + 1 elements (a terminating "null" value)
// Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between
// 0xD800 and 0xDFFF.
CHECK(j.size() == 1112065);
@ -1194,16 +1207,20 @@ TEST_CASE("Unicode", "[hide]")
SECTION("error for incomplete/wrong BOM")
{
CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error&);
CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse("\xef\xbb"), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse("\xef\xbb\xbb"), json::parse_error&);
}
}
namespace
{
void roundtrip(bool success_expected, const std::string& s);
void roundtrip(bool success_expected, const std::string& s)
{
CAPTURE(s)
json _;
// create JSON string value
json j = s;
@ -1219,11 +1236,11 @@ void roundtrip(bool success_expected, const std::string& s)
if (s[0] != '\0')
{
// parsing JSON text succeeds
CHECK_NOTHROW(json::parse(ps));
CHECK_NOTHROW(_ = json::parse(ps));
}
// roundtrip succeeds
CHECK_NOTHROW(json::parse(j.dump()));
CHECK_NOTHROW(_ = json::parse(j.dump()));
// after roundtrip, the same string is stored
json jr = json::parse(j.dump());
@ -1235,9 +1252,10 @@ void roundtrip(bool success_expected, const std::string& s)
CHECK_THROWS_AS(j.dump(), json::type_error&);
// parsing JSON text fails
CHECK_THROWS_AS(json::parse(ps), json::parse_error&);
CHECK_THROWS_AS(_ = json::parse(ps), json::parse_error&);
}
}
}
TEST_CASE("Markus Kuhn's UTF-8 decoder capability and stress test")
{

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,12 +27,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "catch.hpp"
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace
{
bool wstring_is_utf16();
bool wstring_is_utf16()
{
@ -50,6 +51,7 @@ bool u32string_is_utf32()
{
return (std::u32string(U"💩") == std::u32string(U"\U0001F4A9"));
}
}
TEST_CASE("wide strings")
{
@ -68,7 +70,8 @@ TEST_CASE("wide strings")
if (wstring_is_utf16())
{
std::wstring w = L"\"\xDBFF";
CHECK_THROWS_AS(json::parse(w), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(w), json::parse_error&);
}
}
@ -87,7 +90,8 @@ TEST_CASE("wide strings")
if (wstring_is_utf16())
{
std::u16string w = u"\"\xDBFF";
CHECK_THROWS_AS(json::parse(w), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(w), json::parse_error&);
}
}
@ -106,7 +110,8 @@ TEST_CASE("wide strings")
if (u32string_is_utf32())
{
std::u32string w = U"\"\x110000";
CHECK_THROWS_AS(json::parse(w), json::parse_error&);
json _;
CHECK_THROWS_AS(_ = json::parse(w), json::parse_error&);
}
}
}

View file

@ -1,12 +1,12 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.5.0
| | |__ | | | | | | version 3.7.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Copyright (c) 2013-2019 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
@ -27,5 +27,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest_compatibility.h"

View file

@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load diff

21
test/thirdparty/doctest/LICENSE.txt vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016-2018 Viktor Kirilov
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.

5941
test/thirdparty/doctest/doctest.h vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
#ifndef DOCTEST_COMPATIBILITY
#define DOCTEST_COMPATIBILITY
#define DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
#define DOCTEST_THREAD_LOCAL // enable single-threaded builds on XCode 6/7 - https://github.com/onqtam/doctest/issues/172
#include "doctest.h"
// Catch doesn't require a semicolon after CAPTURE but doctest does
#undef CAPTURE
#define CAPTURE(x) DOCTEST_CAPTURE(x);
// Sections from Catch are called Subcases in doctest and don't work with std::string by default
#undef SUBCASE
#define SECTION(x) DOCTEST_SUBCASE(x)
// convenience macro around INFO since it doesn't support temporaries (it is optimized to avoid allocations for runtime speed)
#define INFO_WITH_TEMP_IMPL(x, var_name) const auto var_name = x; INFO(var_name) // lvalue!
#define INFO_WITH_TEMP(x) INFO_WITH_TEMP_IMPL(x, DOCTEST_ANONYMOUS(DOCTEST_STD_STRING_))
// doctest doesn't support THROWS_WITH for std::string out of the box (has to include <string>...)
#define CHECK_THROWS_WITH_STD_STR_IMPL(expr, str, var_name) \
do { \
std::string var_name = str; \
CHECK_THROWS_WITH(expr, var_name.c_str()); \
} while (false)
#define CHECK_THROWS_WITH_STD_STR(expr, str) \
CHECK_THROWS_WITH_STD_STR_IMPL(expr, str, DOCTEST_ANONYMOUS(DOCTEST_STD_STRING_))
// included here because for some tests in the json repository private is defined as
// public and if no STL header is included before that then in the json include when STL
// stuff is included the MSVC STL complains (errors) that C++ keywords are being redefined
#include <iosfwd>
// Catch does this by default
using doctest::Approx;
#endif

21
test/thirdparty/fastcov/LICENSE vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2018-2019 Bryan Gillespie
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.

46
test/thirdparty/fastcov/README.md vendored Normal file
View file

@ -0,0 +1,46 @@
# fastcov
A massively parallel gcov wrapper for generating intermediate coverage formats *fast*
The goal of fastcov is to generate code coverage intermediate formats *as fast as possible* (ideally < 1 second), even for large projects with hundreds of gcda objects. The intermediate formats may then be consumed by a report generator such as lcov's genhtml, or a dedicated front end such as coveralls. fastcov was originally designed to be a drop-in replacement for lcov (application coverage only, not kernel coverage).
Currently the only intermediate formats supported are gcov json format and lcov info format. Adding support for other formats should require just a few lines of python to transform gcov json format to the desired shape.
In order to achieve the massive speed gains, a few constraints apply:
1. GCC version >= 9.0.0
These versions of GCOV have support for JSON intermediate format as well as streaming report data straight to stdout
2. Object files must be either be built:
- Using absolute paths for all `-I` flags passed to the compiler
- Invoking the compiler from the same root directory
If you use CMake, you are almost certainly satisfying the second constraint (unless you care about `ExternalProject` coverage).
## Sample Usage:
```bash
$ cd build_dir
$ fastcov.py --zerocounters
$ <run unit tests>
$ fastcov.py --exclude /usr/include --lcov -o report.info
$ genhtml -o code_coverage report.info
```
## Legacy fastcov
It is possible to reap most of the benefits of fastcov for GCC version < 9.0.0 and >= 7.1.0. However, there will be a *potential* header file loss of correctness.
`fastcov_legacy.py` can be used with pre GCC-9 down to GCC 7.1.0 but with a few penalties due to gcov limitations. This is because running gcov in parallel generates .gcov header reports in parallel which overwrite each other. This isn't a problem unless your header files have actual logic (i.e. header only library) that you want to measure coverage for. Use the `-F` flag to specify which gcda files should not be run in parallel in order to capture accurate header file data just for those. I don't plan on supporting `fastcov_legacy.py` aside from basic bug fixes.
## Benchmarks
Anecdotal testing on my own projects indicate that fastcov is over 100x faster than lcov and over 30x faster than gcovr:
Project Size: ~250 .gcda, ~500 .gcov generated by gcov
Time to process all gcda and parse all gcov:
- fastcov: ~700ms
- lcov: ~90s
- gcovr: ~30s

372
test/thirdparty/fastcov/fastcov.py vendored Executable file
View file

@ -0,0 +1,372 @@
#!/usr/bin/env python3
"""
Author: Bryan Gillespie
A massively parallel gcov wrapper for generating intermediate coverage formats fast
The goal of fastcov is to generate code coverage intermediate formats as fast as possible
(ideally < 1 second), even for large projects with hundreds of gcda objects. The intermediate
formats may then be consumed by a report generator such as lcov's genhtml, or a dedicated front
end such as coveralls.
Sample Usage:
$ cd build_dir
$ ./fastcov.py --zerocounters
$ <run unit tests>
$ ./fastcov.py --exclude /usr/include test/ --lcov -o report.info
$ genhtml -o code_coverage report.info
"""
import re
import os
import sys
import glob
import json
import time
import argparse
import threading
import subprocess
import multiprocessing
MINIMUM_GCOV = (9,0,0)
MINIMUM_CHUNK_SIZE = 5
# Interesting metrics
START_TIME = time.time()
GCOVS_TOTAL = []
GCOVS_SKIPPED = []
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
def stopwatch():
"""Return number of seconds since last time this was called"""
global START_TIME
end_time = time.time()
delta = end_time - START_TIME
START_TIME = end_time
return delta
def parseVersionFromLine(version_str):
"""Given a string containing a dotted integer version, parse out integers and return as tuple"""
version = re.search(r'(\d+\.\d+\.\d+)[^\.]', version_str)
if not version:
return (0,0,0)
return tuple(map(int, version.group(1).split(".")))
def getGcovVersion(gcov):
p = subprocess.Popen([gcov, "-v"], stdout=subprocess.PIPE)
output = p.communicate()[0].decode('UTF-8')
p.wait()
return parseVersionFromLine(output.split("\n")[0])
def removeFiles(files):
for file in files:
os.remove(file)
def getFilteredGcdaFiles(gcda_files, exclude):
def excludeGcda(gcda):
for ex in exclude:
if ex in gcda:
return False
return True
return list(filter(excludeGcda, gcda_files))
def getGcdaFiles(cwd, gcda_files):
if not gcda_files:
gcda_files = glob.glob(os.path.join(os.path.abspath(cwd), "**/*.gcda"), recursive=True)
return gcda_files
def gcovWorker(cwd, gcov, files, chunk, gcov_filter_options, branch_coverage):
gcov_args = "-it"
if branch_coverage:
gcov_args += "b"
p = subprocess.Popen([gcov, gcov_args] + chunk, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
for line in iter(p.stdout.readline, b''):
intermediate_json = json.loads(line.decode(sys.stdout.encoding))
intermediate_json_files = processGcovs(cwd, intermediate_json["files"], gcov_filter_options)
for f in intermediate_json_files:
files.append(f) #thread safe, there might be a better way to do this though
GCOVS_TOTAL.append(len(intermediate_json["files"]))
GCOVS_SKIPPED.append(len(intermediate_json["files"])-len(intermediate_json_files))
p.wait()
def processGcdas(cwd, gcov, jobs, gcda_files, gcov_filter_options, branch_coverage):
chunk_size = max(MINIMUM_CHUNK_SIZE, int(len(gcda_files) / jobs) + 1)
threads = []
intermediate_json_files = []
for chunk in chunks(gcda_files, chunk_size):
t = threading.Thread(target=gcovWorker, args=(cwd, gcov, intermediate_json_files, chunk, gcov_filter_options, branch_coverage))
threads.append(t)
t.start()
log("Spawned %d gcov threads, each processing at most %d gcda files" % (len(threads), chunk_size))
for t in threads:
t.join()
return intermediate_json_files
def processGcov(cwd, gcov, files, gcov_filter_options):
# Add absolute path
gcov["file_abs"] = os.path.abspath(os.path.join(cwd, gcov["file"]))
# If explicit sources were passed, check for match
if gcov_filter_options["sources"]:
if gcov["file_abs"] in gcov_filter_options["sources"]:
files.append(gcov)
return
# Check include filter
if gcov_filter_options["include"]:
for ex in gcov_filter_options["include"]:
if ex in gcov["file"]:
files.append(gcov)
break
return
# Check exclude filter
for ex in gcov_filter_options["exclude"]:
if ex in gcov["file"]:
return
files.append(gcov)
def processGcovs(cwd, gcov_files, gcov_filter_options):
files = []
for gcov in gcov_files:
processGcov(cwd, gcov, files, gcov_filter_options)
return files
def dumpBranchCoverageToLcovInfo(f, branches):
branch_miss = 0
for line_num, branch_counts in branches.items():
for i, count in enumerate(branch_counts):
#Branch (<line number>, <block number>, <branch number>, <taken>)
f.write("BRDA:%s,%d,%d,%d\n" % (line_num, int(i/2), i, count))
branch_miss += int(count == 0)
f.write("BRF:%d\n" % len(branches)) #Branches Found
f.write("BRH:%d\n" % (len(branches) - branch_miss)) #Branches Hit
def dumpToLcovInfo(fastcov_json, output):
with open(output, "w") as f:
for sf, data in fastcov_json["sources"].items():
f.write("SF:%s\n" % sf) #Source File
fn_miss = 0
for function, fdata in data["functions"].items():
f.write("FN:%d,%s\n" % (fdata["start_line"], function)) #Function Start Line
f.write("FNDA:%d,%s\n" % (fdata["execution_count"], function)) #Function Hits
fn_miss += int(fdata["execution_count"] == 0)
f.write("FNF:%d\n" % len(data["functions"])) #Functions Found
f.write("FNH:%d\n" % (len(data["functions"]) - fn_miss)) #Functions Hit
if data["branches"]:
dumpBranchCoverageToLcovInfo(f, data["branches"])
line_miss = 0
for line_num, count in data["lines"].items():
f.write("DA:%s,%d\n" % (line_num, count)) #Line
line_miss += int(count == 0)
f.write("LF:%d\n" % len(data["lines"])) #Lines Found
f.write("LH:%d\n" % (len(data["lines"]) - line_miss)) #Lines Hit
f.write("end_of_record\n")
def exclMarkerWorker(fastcov_sources, chunk):
for source in chunk:
# If there are no covered lines, skip
if not fastcov_sources[source]["lines"]:
continue
start_line = 0
end_line = 0
with open(source) as f:
for i, line in enumerate(f, 1): #Start enumeration at line 1
if not "LCOV_EXCL" in line:
continue
if "LCOV_EXCL_LINE" in line:
if str(i) in fastcov_sources[source]["lines"]:
del fastcov_sources[source]["lines"][str(i)]
if str(i) in fastcov_sources[source]["branches"]:
del fastcov_sources[source]["branches"][str(i)]
elif "LCOV_EXCL_START" in line:
start_line = i
elif "LCOV_EXCL_STOP" in line:
end_line = i
if not start_line:
end_line = 0
continue
for key in ["lines", "branches"]:
for line_num in list(fastcov_sources[source][key].keys()):
if int(line_num) <= end_line and int(line_num) >= start_line:
del fastcov_sources[source][key][line_num]
start_line = end_line = 0
def scanExclusionMarkers(fastcov_json, jobs):
chunk_size = max(MINIMUM_CHUNK_SIZE, int(len(fastcov_json["sources"]) / jobs) + 1)
threads = []
for chunk in chunks(list(fastcov_json["sources"].keys()), chunk_size):
t = threading.Thread(target=exclMarkerWorker, args=(fastcov_json["sources"], chunk))
threads.append(t)
t.start()
log("Spawned %d threads each scanning at most %d source files" % (len(threads), chunk_size))
for t in threads:
t.join()
def distillFunction(function_raw, functions):
function_name = function_raw["name"]
if function_name not in functions:
functions[function_name] = {
"start_line": function_raw["start_line"],
"execution_count": function_raw["execution_count"]
}
else:
functions[function_name]["execution_count"] += function_raw["execution_count"]
def distillLine(line_raw, lines, branches):
line_number = str(line_raw["line_number"])
if line_number not in lines:
lines[line_number] = line_raw["count"]
else:
lines[line_number] += line_raw["count"]
for i, branch in enumerate(line_raw["branches"]):
if line_number not in branches:
branches[line_number] = []
blen = len(branches[line_number])
glen = len(line_raw["branches"])
if blen < glen:
branches[line_number] += [0] * (glen - blen)
branches[line_number][i] += branch["count"]
def distillSource(source_raw, sources):
source_name = source_raw["file_abs"]
if source_name not in sources:
sources[source_name] = {
"functions": {},
"branches": {},
"lines": {},
}
for function in source_raw["functions"]:
distillFunction(function, sources[source_name]["functions"])
for line in source_raw["lines"]:
distillLine(line, sources[source_name]["lines"], sources[source_name]["branches"])
def distillReport(report_raw):
report_json = {
"sources": {}
}
for source in report_raw:
distillSource(source, report_json["sources"])
return report_json
def dumpToJson(intermediate, output):
with open(output, "w") as f:
json.dump(intermediate, f)
def log(line):
if not args.quiet:
print("[{:.3f}s] {}".format(stopwatch(), line))
def getGcovFilterOptions(args):
return {
"sources": set([os.path.abspath(s) for s in args.sources]), #Make paths absolute, use set for fast lookups
"include": args.includepost,
"exclude": args.excludepost,
}
def main(args):
# Need at least gcov 9.0.0 because that's when gcov JSON and stdout streaming was introduced
current_gcov_version = getGcovVersion(args.gcov)
if current_gcov_version < MINIMUM_GCOV:
sys.stderr.write("Minimum gcov version {} required, found {}\n".format(".".join(map(str, MINIMUM_GCOV)), ".".join(map(str, current_gcov_version))))
exit(1)
# Get list of gcda files to process
gcda_files = getGcdaFiles(args.directory, args.gcda_files)
log("Found {} .gcda files ".format(len(gcda_files)))
# If gcda filtering is enabled, filter them out now
if args.excludepre:
gcda_files = getFilteredGcdaFiles(gcda_files, args.excludepre)
log("{} .gcda files after filtering".format(len(gcda_files)))
# We "zero" the "counters" by simply deleting all gcda files
if args.zerocounters:
removeFiles(gcda_files)
log("{} .gcda files removed".format(len(gcda_files)))
return
# Fire up one gcov per cpu and start processing gcdas
gcov_filter_options = getGcovFilterOptions(args)
intermediate_json_files = processGcdas(args.cdirectory, args.gcov, args.jobs, gcda_files, gcov_filter_options, args.branchcoverage)
# Summarize processing results
gcov_total = sum(GCOVS_TOTAL)
gcov_skipped = sum(GCOVS_SKIPPED)
log("Processed {} .gcov files ({} total, {} skipped)".format(gcov_total - gcov_skipped, gcov_total, gcov_skipped))
# Distill all the extraneous info gcov gives us down to the core report
fastcov_json = distillReport(intermediate_json_files)
log("Aggregated raw gcov JSON into fastcov JSON report")
# Dump to desired file format
if args.lcov:
scanExclusionMarkers(fastcov_json, args.jobs)
log("Scanned {} source files for exclusion markers".format(len(fastcov_json["sources"])))
dumpToLcovInfo(fastcov_json, args.output)
log("Created lcov info file '{}'".format(args.output))
elif args.gcov_raw:
dumpToJson(intermediate_json_files, args.output)
log("Created gcov raw json file '{}'".format(args.output))
else:
dumpToJson(fastcov_json, args.output)
log("Created fastcov json file '{}'".format(args.output))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='A parallel gcov wrapper for fast coverage report generation')
parser.add_argument('-z', '--zerocounters', dest='zerocounters', action="store_true", help='Recursively delete all gcda files')
# Enable Branch Coverage
parser.add_argument('-b', '--branch-coverage', dest='branchcoverage', action="store_true", help='Include branch counts in the coverage report')
# Filtering Options
parser.add_argument('-s', '--source-files', dest='sources', nargs="+", metavar='', default=[], help='Filter: Specify exactly which source files should be included in the final report. Paths must be either absolute or relative to current directory.')
parser.add_argument('-e', '--exclude', dest='excludepost', nargs="+", metavar='', default=[], help='Filter: Exclude source files from final report if they contain one of the provided substrings (i.e. /usr/include test/, etc.)')
parser.add_argument('-i', '--include', dest='includepost', nargs="+", metavar='', default=[], help='Filter: Only include source files in final report that contain one of the provided substrings (i.e. src/ etc.)')
parser.add_argument('-f', '--gcda-files', dest='gcda_files', nargs="+", metavar='', default=[], help='Filter: Specify exactly which gcda files should be processed instead of recursively searching the search directory.')
parser.add_argument('-E', '--exclude-gcda', dest='excludepre', nargs="+", metavar='', default=[], help='Filter: Exclude gcda files from being processed via simple find matching (not regex)')
parser.add_argument('-g', '--gcov', dest='gcov', default='gcov', help='Which gcov binary to use')
parser.add_argument('-d', '--search-directory', dest='directory', default=".", help='Base directory to recursively search for gcda files (default: .)')
parser.add_argument('-c', '--compiler-directory', dest='cdirectory', default=".", help='Base directory compiler was invoked from (default: .) \
This needs to be set if invoking fastcov from somewhere other than the base compiler directory.')
parser.add_argument('-j', '--jobs', dest='jobs', type=int, default=multiprocessing.cpu_count(), help='Number of parallel gcov to spawn (default: %d).' % multiprocessing.cpu_count())
parser.add_argument('-m', '--minimum-chunk-size', dest='minimum_chunk', type=int, default=5, help='Minimum number of files a thread should process (default: 5). \
If you have only 4 gcda files but they are monstrously huge, you could change this value to a 1 so that each thread will only process 1 gcda. Otherise fastcov will spawn only 1 thread to process all of them.')
parser.add_argument('-l', '--lcov', dest='lcov', action="store_true", help='Output in lcov info format instead of fastcov json')
parser.add_argument('-r', '--gcov-raw', dest='gcov_raw', action="store_true", help='Output in gcov raw json instead of fastcov json')
parser.add_argument('-o', '--output', dest='output', default="coverage.json", help='Name of output file (default: coverage.json)')
parser.add_argument('-q', '--quiet', dest='quiet', action="store_true", help='Suppress output to stdout')
args = parser.parse_args()
main(args)