2020-07-30 13:13:05 +03:00
/*
__ _____ _____ _____
__ | | __ | | | | JSON for Modern C + + ( test suite )
2021-08-17 16:23:23 +03:00
| | | __ | | | | | | version 3.10 .0
2020-07-30 13:13:05 +03:00
| _____ | _____ | _____ | _ | ___ | https : //github.com/nlohmann/json
Licensed under the MIT License < http : //opensource.org/licenses/MIT>.
SPDX - License - Identifier : MIT
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
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
*/
# include "doctest_compatibility.h"
// for some reason including this after the json header leads to linker errors with VS 2017...
# include <locale>
2020-08-12 14:30:06 +03:00
# define JSON_TESTS_PRIVATE
2020-07-30 13:13:05 +03:00
# include <nlohmann/json.hpp>
2021-08-20 15:49:58 +03:00
using json = nlohmann : : json ;
using ordered_json = nlohmann : : ordered_json ;
2020-07-30 13:13:05 +03:00
# include <list>
# include <cstdio>
2021-06-17 20:17:43 +03:00
# include <type_traits>
2021-03-24 09:15:18 +03:00
# include <utility>
2020-07-30 13:13:05 +03:00
# if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
# define JSON_HAS_CPP_17
# endif
# ifdef JSON_HAS_CPP_17
# include <variant>
# endif
2020-12-29 16:48:18 +03:00
# ifdef JSON_HAS_CPP_20
# include <span>
# endif
2021-08-17 15:43:43 +03:00
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING ( " -Wexit-time-destructors " )
2020-07-30 13:13:05 +03:00
/////////////////////////////////////////////////////////////////////
// for #1021
/////////////////////////////////////////////////////////////////////
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 { } ;
2021-03-24 09:15:18 +03:00
inline bool operator = = ( NonDefaultFromJsonStruct const & /*unused*/ , NonDefaultFromJsonStruct const & /*unused*/ )
2020-07-30 13:13:05 +03:00
{
return true ;
}
enum class for_1647 { one , two } ;
2021-03-24 09:15:18 +03:00
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive
2020-07-30 13:13:05 +03:00
NLOHMANN_JSON_SERIALIZE_ENUM ( for_1647 ,
{
{ for_1647 : : one , " one " } ,
{ for_1647 : : two , " two " } ,
} )
2021-03-24 09:15:18 +03:00
} // namespace
2020-07-30 13:13:05 +03:00
/////////////////////////////////////////////////////////////////////
// for #1299
/////////////////////////////////////////////////////////////////////
struct Data
{
Data ( ) = default ;
2021-03-24 09:15:18 +03:00
Data ( std : : string a_ , std : : string b_ ) : a ( std : : move ( a_ ) ) , b ( std : : move ( b_ ) ) { }
2020-07-30 13:13:05 +03:00
std : : string a { } ;
std : : string b { } ;
} ;
2021-03-24 09:15:18 +03:00
void from_json ( const json & j , Data & data ) ;
2020-07-30 13:13:05 +03:00
void from_json ( const json & j , Data & data )
{
j [ " a " ] . get_to ( data . a ) ;
j [ " b " ] . get_to ( data . b ) ;
}
2021-03-24 09:15:18 +03:00
bool operator = = ( Data const & lhs , Data const & rhs ) ;
2020-07-30 13:13:05 +03:00
bool operator = = ( Data const & lhs , Data const & rhs )
{
return lhs . a = = rhs . a & & lhs . b = = rhs . b ;
}
//bool operator!=(Data const& lhs, Data const& rhs)
//{
// return !(lhs == rhs);
//}
namespace nlohmann
{
template < >
struct adl_serializer < NonDefaultFromJsonStruct >
{
2021-03-24 09:15:18 +03:00
static NonDefaultFromJsonStruct from_json ( json const & /*unused*/ ) noexcept
2020-07-30 13:13:05 +03:00
{
return { } ;
}
} ;
2021-03-24 09:15:18 +03:00
} // namespace nlohmann
2020-07-30 13:13:05 +03:00
/////////////////////////////////////////////////////////////////////
// for #1805
/////////////////////////////////////////////////////////////////////
struct NotSerializableData
{
int mydata ;
float myfloat ;
} ;
2021-01-09 02:08:27 +03:00
/////////////////////////////////////////////////////////////////////
// for #2574
/////////////////////////////////////////////////////////////////////
2021-01-23 20:24:47 +03:00
2021-01-09 02:08:27 +03:00
struct NonDefaultConstructible
{
2021-03-24 15:27:59 +03:00
explicit NonDefaultConstructible ( int a ) : x ( a ) { }
2021-01-09 02:08:27 +03:00
int x ;
} ;
namespace nlohmann
{
template < >
struct adl_serializer < NonDefaultConstructible >
{
2021-03-25 01:33:21 +03:00
static NonDefaultConstructible from_json ( json const & j )
2021-01-09 02:08:27 +03:00
{
return NonDefaultConstructible ( j . get < int > ( ) ) ;
}
} ;
2021-03-24 15:27:59 +03:00
} // namespace nlohmann
2021-01-09 02:08:27 +03:00
2021-07-29 16:23:21 +03:00
/////////////////////////////////////////////////////////////////////
// for #2824
/////////////////////////////////////////////////////////////////////
class sax_no_exception : public nlohmann : : detail : : json_sax_dom_parser < json >
{
public :
explicit sax_no_exception ( json & j ) : nlohmann : : detail : : json_sax_dom_parser < json > ( j , false ) { }
2021-07-30 15:41:06 +03:00
static bool parse_error ( std : : size_t /*position*/ , const std : : string & /*last_token*/ , const json : : exception & ex )
2021-07-29 16:23:21 +03:00
{
2021-07-30 16:00:54 +03:00
error_string = new std : : string ( ex . what ( ) ) ; // NOLINT(cppcoreguidelines-owning-memory)
2021-07-29 16:23:21 +03:00
return false ;
}
2021-07-30 15:41:06 +03:00
static std : : string * error_string ;
2021-07-29 16:23:21 +03:00
} ;
2021-07-30 15:41:06 +03:00
std : : string * sax_no_exception : : error_string = nullptr ;
2021-07-29 16:23:21 +03:00
2021-01-09 02:08:27 +03:00
2020-07-30 13:13:05 +03:00
TEST_CASE ( " regression tests 2 " )
{
SECTION ( " issue #1001 - Fix memory leak during parser callback " )
{
2021-03-24 09:15:18 +03:00
const auto * geojsonExample = R " (
2020-07-30 13:13:05 +03:00
{ " type " : " FeatureCollection " ,
" features " : [
{ " type " : " Feature " ,
" geometry " : { " type " : " Point " , " coordinates " : [ 102.0 , 0.5 ] } ,
" properties " : { " prop0 " : " value0 " }
} ,
{ " type " : " Feature " ,
" geometry " : {
" type " : " LineString " ,
" coordinates " : [
[ 102.0 , 0.0 ] , [ 103.0 , 1.0 ] , [ 104.0 , 0.0 ] , [ 105.0 , 1.0 ]
]
} ,
" properties " : {
" prop0 " : " value0 " ,
" prop1 " : 0.0
}
} ,
{ " type " : " Feature " ,
" geometry " : {
" type " : " Polygon " ,
" coordinates " : [
[ [ 100.0 , 0.0 ] , [ 101.0 , 0.0 ] , [ 101.0 , 1.0 ] ,
[ 100.0 , 1.0 ] , [ 100.0 , 0.0 ] ]
]
} ,
" properties " : {
" prop0 " : " value0 " ,
" prop1 " : { " this " : " that " }
}
}
]
} ) " ;
2021-03-24 09:15:18 +03:00
json : : parser_callback_t cb = [ & ] ( int /*level*/ , json : : parse_event_t event , json & parsed )
2020-07-30 13:13:05 +03:00
{
// skip uninteresting events
if ( event = = json : : parse_event_t : : value & & ! parsed . is_primitive ( ) )
{
return false ;
}
switch ( event )
{
case json : : parse_event_t : : key :
{
return true ;
}
case json : : parse_event_t : : value :
{
return false ;
}
case json : : parse_event_t : : object_start :
{
return true ;
}
case json : : parse_event_t : : object_end :
{
return false ;
}
case json : : parse_event_t : : array_start :
{
return true ;
}
case json : : parse_event_t : : array_end :
{
return false ;
}
default :
{
return true ;
}
}
} ;
auto j = json : : parse ( geojsonExample , cb , true ) ;
CHECK ( j = = json ( ) ) ;
}
SECTION ( " issue #1021 - to/from_msgpack only works with standard typization " )
{
float_json j = 1000.0 ;
CHECK ( float_json : : from_cbor ( float_json : : to_cbor ( j ) ) = = j ) ;
CHECK ( float_json : : from_msgpack ( float_json : : to_msgpack ( j ) ) = = j ) ;
CHECK ( float_json : : from_ubjson ( float_json : : to_ubjson ( j ) ) = = j ) ;
float_json j2 = { 1000.0 , 2000.0 , 3000.0 } ;
CHECK ( float_json : : from_ubjson ( float_json : : to_ubjson ( j2 , true , true ) ) = = j2 ) ;
}
SECTION ( " issue #1045 - Using STL algorithms with JSON containers with expected results? " )
{
json diffs = nlohmann : : json : : array ( ) ;
json m1 { { " key1 " , 42 } } ;
json m2 { { " key2 " , 42 } } ;
auto p1 = m1 . items ( ) ;
auto p2 = m2 . items ( ) ;
using it_type = decltype ( p1 . begin ( ) ) ;
std : : set_difference (
p1 . begin ( ) , p1 . end ( ) ,
p2 . begin ( ) , p2 . end ( ) ,
std : : inserter ( diffs , diffs . end ( ) ) , [ & ] ( const it_type & e1 , const it_type & e2 ) - > bool
{
using comper_pair = std : : pair < std : : string , decltype ( e1 . value ( ) ) > ; // Trying to avoid unneeded copy
return comper_pair ( e1 . key ( ) , e1 . value ( ) ) < comper_pair ( e2 . key ( ) , e2 . value ( ) ) ; // Using pair comper
} ) ;
CHECK ( diffs . size ( ) = = 1 ) ; // Note the change here, was 2
}
# ifdef JSON_HAS_CPP_17
SECTION ( " issue #1292 - Serializing std::variant causes stack overflow " )
{
static_assert (
! std : : is_constructible < json , std : : variant < int , float > > : : value , " " ) ;
}
# endif
SECTION ( " issue #1299 - compile error in from_json converting to container "
" with std::pair " )
{
json j =
{
{ " 1 " , { { " a " , " testa_1 " } , { " b " , " testb_1 " } } } ,
{ " 2 " , { { " a " , " testa_2 " } , { " b " , " testb_2 " } } } ,
{ " 3 " , { { " a " , " testa_3 " } , { " b " , " testb_3 " } } } ,
} ;
std : : map < std : : string , Data > expected
{
{ " 1 " , { " testa_1 " , " testb_1 " } } ,
{ " 2 " , { " testa_2 " , " testb_2 " } } ,
{ " 3 " , { " testa_3 " , " testb_3 " } } ,
} ;
const auto data = j . get < decltype ( expected ) > ( ) ;
CHECK ( expected = = data ) ;
}
SECTION ( " issue #1445 - buffer overflow in dumping invalid utf-8 strings " )
{
SECTION ( " a bunch of -1, ensure_ascii=true " )
{
const auto length = 300 ;
json dump_test ;
dump_test [ " 1 " ] = std : : string ( length , - 1 ) ;
2021-03-24 09:15:18 +03:00
std : : string expected = R " ({ " 1 " : " ) " ;
2020-07-30 13:13:05 +03:00
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 ;
dump_test [ " 1 " ] = std : : string ( length , - 2 ) ;
2021-03-24 09:15:18 +03:00
std : : string expected = R " ({ " 1 " : " ) " ;
2020-07-30 13:13:05 +03:00
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 " )
{
nlohmann : : json dump_test ;
2021-03-24 09:15:18 +03:00
const std : : array < int , 108 > data =
2020-07-30 13:13:05 +03:00
{
2021-03-24 09:15:18 +03:00
{
109 , 108 , 103 , 125 , - 122 , - 53 , 115 ,
18 , 3 , 0 , 102 , 19 , 1 , 15 ,
- 110 , 13 , - 3 , - 1 , - 81 , 32 , 2 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
8 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , - 80 , 2 ,
0 , 0 , 96 , - 118 , 46 , - 116 , 46 ,
109 , - 84 , - 87 , 108 , 14 , 109 , - 24 ,
- 83 , 13 , - 18 , - 51 , - 83 , - 52 , - 115 ,
14 , 6 , 32 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
64 , 3 , 0 , 0 , 0 , 35 , - 74 ,
- 73 , 55 , 57 , - 128 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 33 , 0 , 0 , 0 , - 96 ,
- 54 , - 28 , - 26
}
2020-07-30 13:13:05 +03:00
} ;
std : : string s ;
2021-03-24 09:15:18 +03:00
for ( int i : data )
2020-07-30 13:13:05 +03:00
{
2021-03-24 09:15:18 +03:00
s + = static_cast < char > ( i ) ;
2020-07-30 13:13:05 +03:00
}
dump_test [ " 1 " ] = s ;
dump_test . dump ( - 1 , ' ' , true , nlohmann : : json : : error_handler_t : : replace ) ;
}
}
SECTION ( " issue #1447 - Integer Overflow (OSS-Fuzz 12506) " )
{
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 #1715 - json::from_cbor does not respect allow_exceptions = false when input is string literal " )
{
SECTION ( " string literal " )
{
json cbor = json : : from_cbor ( " B " , true , false ) ;
CHECK ( cbor . is_discarded ( ) ) ;
}
SECTION ( " string array " )
{
2021-03-24 09:15:18 +03:00
const std : : array < char , 2 > input = { { ' B ' , 0x00 } } ;
2020-07-30 13:13:05 +03:00
json cbor = json : : from_cbor ( input , true , false ) ;
CHECK ( cbor . is_discarded ( ) ) ;
}
SECTION ( " std::string " )
{
json cbor = json : : from_cbor ( std : : string ( " B " ) , true , false ) ;
CHECK ( cbor . is_discarded ( ) ) ;
}
}
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 , " " ) ;
}
SECTION ( " issue #1983 - JSON patch diff for op=add formation is not as per standard (RFC 6902) " )
{
const auto source = R " ({ " foo " : [ " 1 " , " 2 " ] }) " _json ;
const auto target = R " ({ " foo " : [ " 1 " , " 2 " , " 3 " ]}) " _json ;
const auto result = json : : diff ( source , target ) ;
CHECK ( result . dump ( ) = = R " ([{ " op " : " add " , " path " : " / foo / - " , " value " : " 3 " }]) " ) ;
}
SECTION ( " issue #2067 - cannot serialize binary data to text JSON " )
{
2021-03-24 09:15:18 +03:00
const std : : array < unsigned char , 23 > data = { { 0x81 , 0xA4 , 0x64 , 0x61 , 0x74 , 0x61 , 0xC4 , 0x0F , 0x33 , 0x30 , 0x30 , 0x32 , 0x33 , 0x34 , 0x30 , 0x31 , 0x30 , 0x37 , 0x30 , 0x35 , 0x30 , 0x31 , 0x30 } } ;
json j = json : : from_msgpack ( data . data ( ) , data . size ( ) ) ;
2020-07-30 13:13:05 +03:00
CHECK_NOTHROW (
j . dump ( 4 , // Indent
' ' , // Indent char
false , // Ensure ascii
json : : error_handler_t : : strict // Error
)
) ;
}
SECTION ( " PR #2181 - regression bug with lvalue " )
{
// see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060
json j { { " x " , " test " } } ;
std : : string defval = " default value " ;
auto val = j . value ( " x " , defval ) ;
auto val2 = j . value ( " y " , defval ) ;
}
SECTION ( " issue #2293 - eof doesnt cause parsing to stop " )
{
std : : vector < uint8_t > data =
{
0x7B , 0x6F , 0x62 , 0x6A , 0x65 , 0x63 , 0x74 , 0x20 , 0x4F , 0x42
} ;
json result = json : : from_cbor ( data , true , false ) ;
CHECK ( result . is_discarded ( ) ) ;
}
SECTION ( " issue #2315 - json.update and vector<pair>does not work with ordered_json " )
{
nlohmann : : ordered_json jsonAnimals = { { " animal " , " dog " } } ;
nlohmann : : ordered_json jsonCat = { { " animal " , " cat " } } ;
jsonAnimals . update ( jsonCat ) ;
CHECK ( jsonAnimals [ " animal " ] = = " cat " ) ;
auto jsonAnimals_parsed = nlohmann : : ordered_json : : parse ( jsonAnimals . dump ( ) ) ;
CHECK ( jsonAnimals = = jsonAnimals_parsed ) ;
std : : vector < std : : pair < std : : string , int64_t > > intData = { std : : make_pair ( " aaaa " , 11 ) ,
std : : make_pair ( " bbb " , 222 )
} ;
nlohmann : : ordered_json jsonObj ;
for ( const auto & data : intData )
{
jsonObj [ data . first ] = data . second ;
}
CHECK ( jsonObj [ " aaaa " ] = = 11 ) ;
CHECK ( jsonObj [ " bbb " ] = = 222 ) ;
}
2020-07-31 19:59:22 +03:00
SECTION ( " issue #2330 - ignore_comment=true fails on multiple consecutive lines starting with comments " )
{
std : : string ss = " // \n // \n { \n } \n " ;
json j = json : : parse ( ss , nullptr , true , true ) ;
CHECK ( j . dump ( ) = = " {} " ) ;
}
2020-12-29 16:48:18 +03:00
# ifdef JSON_HAS_CPP_20
SECTION ( " issue #2546 - parsing containers of std::byte " )
{
const char DATA [ ] = R " ( " Hello , world ! " ) " ;
const auto s = std : : as_bytes ( std : : span ( DATA ) ) ;
json j = json : : parse ( s ) ;
2020-12-29 22:52:57 +03:00
CHECK ( j . dump ( ) = = " \" Hello, world! \" " ) ;
2020-12-29 16:48:18 +03:00
}
# endif
2021-01-09 02:08:27 +03:00
SECTION ( " issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails " )
{
SECTION ( " std::array " )
{
2021-01-09 19:54:56 +03:00
{
json j = { 7 , 4 } ;
auto arr = j . get < std : : array < NonDefaultConstructible , 2 > > ( ) ;
CHECK ( arr [ 0 ] . x = = 7 ) ;
CHECK ( arr [ 1 ] . x = = 4 ) ;
}
{
json j = 7 ;
CHECK_THROWS_AS ( ( j . get < std : : array < NonDefaultConstructible , 1 > > ( ) ) , json : : type_error ) ;
}
2021-01-09 02:08:27 +03:00
}
SECTION ( " std::pair " )
{
{
json j = { 3 , 8 } ;
auto p = j . get < std : : pair < NonDefaultConstructible , NonDefaultConstructible > > ( ) ;
CHECK ( p . first . x = = 3 ) ;
CHECK ( p . second . x = = 8 ) ;
}
{
json j = { 4 , 1 } ;
auto p = j . get < std : : pair < int , NonDefaultConstructible > > ( ) ;
CHECK ( p . first = = 4 ) ;
CHECK ( p . second . x = = 1 ) ;
}
{
json j = { 6 , 7 } ;
auto p = j . get < std : : pair < NonDefaultConstructible , int > > ( ) ;
CHECK ( p . first . x = = 6 ) ;
CHECK ( p . second = = 7 ) ;
}
2021-01-09 19:54:56 +03:00
{
json j = 7 ;
CHECK_THROWS_AS ( ( j . get < std : : pair < NonDefaultConstructible , int > > ( ) ) , json : : type_error ) ;
}
2021-01-09 02:08:27 +03:00
}
SECTION ( " std::tuple " )
{
{
json j = { 9 } ;
auto t = j . get < std : : tuple < NonDefaultConstructible > > ( ) ;
CHECK ( std : : get < 0 > ( t ) . x = = 9 ) ;
}
{
json j = { 9 , 8 , 7 } ;
auto t = j . get < std : : tuple < NonDefaultConstructible , int , NonDefaultConstructible > > ( ) ;
CHECK ( std : : get < 0 > ( t ) . x = = 9 ) ;
CHECK ( std : : get < 1 > ( t ) = = 8 ) ;
CHECK ( std : : get < 2 > ( t ) . x = = 7 ) ;
}
2021-01-09 19:54:56 +03:00
{
json j = 7 ;
CHECK_THROWS_AS ( ( j . get < std : : tuple < NonDefaultConstructible > > ( ) ) , json : : type_error ) ;
}
2021-01-09 02:08:27 +03:00
}
}
2021-07-15 10:02:24 +03:00
SECTION ( " issue #2865 - ASAN detects memory leaks " )
{
// the code below is expected to not leak memory
{
nlohmann : : json o ;
std : : string s = " bar " ;
nlohmann : : to_json ( o [ " foo " ] , s ) ;
nlohmann : : json p = o ;
// call to_json with a non-null JSON value
nlohmann : : to_json ( p [ " foo " ] , s ) ;
}
{
nlohmann : : json o ;
std : : string s = " bar " ;
nlohmann : : to_json ( o [ " foo " ] , s ) ;
// call to_json with a non-null JSON value
nlohmann : : to_json ( o [ " foo " ] , s ) ;
}
}
2021-06-17 20:17:43 +03:00
2021-07-29 16:23:21 +03:00
SECTION ( " issue #2824 - encoding of json::exception::what() " )
{
json j ;
sax_no_exception sax ( j ) ;
CHECK ( ! json : : sax_parse ( " xyz " , & sax ) ) ;
2021-07-30 15:41:06 +03:00
CHECK ( * sax_no_exception : : error_string = = " [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x' " ) ;
2021-07-30 22:18:25 +03:00
delete sax_no_exception : : error_string ; // NOLINT(cppcoreguidelines-owning-memory)
2021-07-29 16:23:21 +03:00
}
2021-06-17 20:17:43 +03:00
SECTION ( " issue #2825 - Properly constrain the basic_json conversion operator " )
{
static_assert ( std : : is_copy_assignable < nlohmann : : ordered_json > : : value , " " ) ;
}
2021-08-20 15:49:58 +03:00
SECTION ( " issue #2958 - Inserting in unordered json using a pointer retains the leading slash " )
{
std : : string p = " /root " ;
// matching types
json test1 ;
test1 [ json : : json_pointer ( p ) ] = json : : object ( ) ;
CHECK ( test1 . dump ( ) = = " { \" root \" :{}} " ) ;
ordered_json test2 ;
test2 [ ordered_json : : json_pointer ( p ) ] = json : : object ( ) ;
CHECK ( test2 . dump ( ) = = " { \" root \" :{}} " ) ;
// mixed type - the JSON Pointer is implicitly converted into a string "/root"
ordered_json test3 ;
test3 [ json : : json_pointer ( p ) ] = json : : object ( ) ;
CHECK ( test3 . dump ( ) = = " { \" /root \" :{}} " ) ;
}
2020-07-30 13:13:05 +03:00
}
2021-08-17 15:43:43 +03:00
DOCTEST_CLANG_SUPPRESS_WARNING_POP