2016-08-04 07:24:46 +02:00
/*
__ _____ _____ _____
__ | | __ | | | | JSON for Modern C + + ( test suite )
2018-12-21 23:52:29 +01:00
| | | __ | | | | | | version 3.5 .0
2016-08-04 07:24:46 +02:00
| _____ | _____ | _____ | _ | ___ | https : //github.com/nlohmann/json
Licensed under the MIT License < http : //opensource.org/licenses/MIT>.
2018-05-03 17:41:45 +02:00
SPDX - License - Identifier : MIT
2018-02-01 22:20:26 +01:00
Copyright ( c ) 2013 - 2018 Niels Lohmann < http : //nlohmann.me>.
2016-08-04 07:24:46 +02:00
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
*/
# include "catch.hpp"
2016-08-04 21:55:47 +02:00
2018-01-29 11:21:11 +01:00
# include <nlohmann/json.hpp>
2016-08-04 21:55:47 +02:00
using nlohmann : : json ;
2017-09-10 22:38:04 +02:00
# include <iostream>
2016-08-15 22:44:14 +02:00
# include <valarray>
2018-08-16 18:20:30 +02:00
struct SaxEventLogger : public nlohmann : : json_sax < json >
2018-02-24 18:04:07 +01:00
{
2018-08-16 18:20:30 +02:00
bool null ( ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " null() " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool boolean ( bool val ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( val ? " boolean(true) " : " boolean(false) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool number_integer ( json : : number_integer_t val ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " number_integer( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool number_unsigned ( json : : number_unsigned_t val ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " number_unsigned( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool number_float ( json : : number_float_t , const std : : string & s ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " number_float( " + s + " ) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool string ( std : : string & val ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " string( " + val + " ) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool start_object ( std : : size_t elements ) override
2018-02-24 18:04:07 +01:00
{
2018-02-25 18:35:16 +01:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 10:44:47 +01:00
{
events . push_back ( " start_object() " ) ;
}
else
{
events . push_back ( " start_object( " + std : : to_string ( elements ) + " ) " ) ;
}
2018-02-24 18:04:07 +01:00
return true ;
}
2018-08-16 18:20:30 +02:00
bool key ( std : : string & val ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " key( " + val + " ) " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool end_object ( ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " end_object() " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool start_array ( std : : size_t elements ) override
2018-02-24 18:04:07 +01:00
{
2018-02-25 18:35:16 +01:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 10:44:47 +01:00
{
events . push_back ( " start_array() " ) ;
}
else
{
events . push_back ( " start_array( " + std : : to_string ( elements ) + " ) " ) ;
}
2018-02-24 18:04:07 +01:00
return true ;
}
2018-08-16 18:20:30 +02:00
bool end_array ( ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " end_array() " ) ;
return true ;
}
2018-08-16 18:20:30 +02:00
bool parse_error ( std : : size_t position , const std : : string & , const json : : exception & ) override
2018-02-24 18:04:07 +01:00
{
events . push_back ( " parse_error( " + std : : to_string ( position ) + " ) " ) ;
return false ;
}
2019-03-17 12:01:49 +01:00
std : : vector < std : : string > events { } ;
2018-02-24 18:04:07 +01:00
} ;
2018-02-25 17:10:30 +01:00
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
{
2018-08-16 18:20:30 +02:00
bool start_object ( std : : size_t elements ) override
2018-02-25 17:10:30 +01:00
{
2018-08-16 18:20:30 +02:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 17:10:30 +01:00
{
events . push_back ( " start_object() " ) ;
}
else
{
events . push_back ( " start_object( " + std : : to_string ( elements ) + " ) " ) ;
}
return false ;
}
} ;
struct SaxEventLoggerExitAfterKey : public SaxEventLogger
{
2018-08-16 18:20:30 +02:00
bool key ( std : : string & val ) override
2018-02-25 17:10:30 +01:00
{
events . push_back ( " key( " + val + " ) " ) ;
return false ;
}
} ;
struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
{
2018-08-16 18:20:30 +02:00
bool start_array ( std : : size_t elements ) override
2018-02-25 17:10:30 +01:00
{
2018-08-16 18:20:30 +02:00
if ( elements = = std : : size_t ( - 1 ) )
2018-02-25 17:10:30 +01:00
{
events . push_back ( " start_array() " ) ;
}
else
{
events . push_back ( " start_array( " + std : : to_string ( elements ) + " ) " ) ;
}
return false ;
}
} ;
2016-08-04 21:55:47 +02:00
TEST_CASE ( " deserialization " )
{
2016-08-30 23:44:15 +02:00
SECTION ( " successful deserialization " )
2016-08-04 21:55:47 +02:00
{
2016-08-30 23:44:15 +02:00
SECTION ( " stream " )
{
2018-02-24 18:04:07 +01:00
std : : stringstream ss1 , ss2 , ss3 ;
2017-06-16 19:23:55 +02:00
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
2018-02-24 18:04:07 +01:00
ss3 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
2017-06-16 19:23:55 +02:00
json j = json : : parse ( ss1 ) ;
CHECK ( json : : accept ( ss2 ) ) ;
2016-08-30 23:44:15 +02:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( ss3 , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 18:04:07 +01:00
} ) ) ;
2016-08-30 23:44:15 +02:00
}
2016-08-04 21:55:47 +02:00
2016-08-31 18:07:18 +02:00
SECTION ( " string literal " )
{
auto s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j = json : : parse ( s ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( s ) ) ;
2016-08-31 18:07:18 +02:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 18:04:07 +01:00
} ) ) ;
2016-08-31 18:07:18 +02:00
}
2016-08-04 21:55:47 +02:00
2016-08-31 18:07:18 +02:00
SECTION ( " string_t " )
2016-08-30 23:44:15 +02:00
{
json : : string_t s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j = json : : parse ( s ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( s ) ) ;
2016-08-30 23:44:15 +02:00
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " end_array() "
2018-02-24 18:04:07 +01:00
} ) ) ;
2016-08-30 23:44:15 +02:00
}
2016-08-15 22:44:14 +02:00
2016-08-30 23:44:15 +02:00
SECTION ( " operator<< " )
{
std : : stringstream ss ;
ss < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j ;
j < < ss ;
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
2016-08-04 21:55:47 +02:00
2016-08-30 23:44:15 +02:00
SECTION ( " operator>> " )
{
std : : stringstream ss ;
ss < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " ;
json j ;
ss > > j ;
CHECK ( j = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
SECTION ( " user-defined string literal " )
{
CHECK ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1}] " _json = = json ( { " foo " , 1 , 2 , 3 , false , { { " one " , 1 } } } ) ) ;
}
2016-08-04 21:55:47 +02:00
}
2016-08-31 18:07:18 +02:00
SECTION ( " unsuccessful deserialization " )
2016-08-04 21:55:47 +02:00
{
2016-08-30 23:44:15 +02:00
SECTION ( " stream " )
{
2018-02-24 18:04:07 +01:00
std : : stringstream ss1 , ss2 , ss3 , ss4 , ss5 ;
2016-11-02 15:44:46 +01:00
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-06-16 19:23:55 +02:00
ss3 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-07-27 20:33:11 +02:00
ss4 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2018-02-24 18:04:07 +01:00
ss5 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( ss1 ) , json : : parse_error & ) ;
2017-03-01 21:28:44 +01:00
CHECK_THROWS_WITH ( json : : parse ( ss2 ) ,
2018-10-07 22:39:17 +02:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( ss3 ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
2018-02-24 18:04:07 +01:00
CHECK_NOTHROW ( j_error = json : : parse ( ss4 , nullptr , false ) ) ;
2017-07-27 20:33:11 +02:00
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( ss5 , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " parse_error(29) "
2018-02-24 18:04:07 +01:00
} ) ) ;
2016-08-30 23:44:15 +02:00
}
2016-08-04 21:55:47 +02:00
2016-08-30 23:44:15 +02:00
SECTION ( " string " )
{
json : : string_t s = " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( s ) , json : : parse_error & ) ;
2017-03-01 21:28:44 +01:00
CHECK_THROWS_WITH ( json : : parse ( s ) ,
2018-10-07 22:39:17 +02:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( s ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( s , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( s , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 11 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_array() " , " string(foo) " , " number_unsigned(1) " ,
" number_unsigned(2) " , " number_unsigned(3) " , " boolean(false) " ,
" start_object() " , " key(one) " , " number_unsigned(1) " ,
" end_object() " , " parse_error(29) "
2018-02-24 18:04:07 +01:00
} ) ) ;
2016-08-30 23:44:15 +02:00
}
SECTION ( " operator<< " )
{
2016-11-02 15:44:46 +01:00
std : : stringstream ss1 , ss2 ;
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2016-08-30 23:44:15 +02:00
json j ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( j < < ss1 , json : : parse_error & ) ;
2017-03-01 21:28:44 +01:00
CHECK_THROWS_WITH ( j < < ss2 ,
2018-10-07 22:39:17 +02:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 23:44:15 +02:00
}
SECTION ( " operator>> " )
{
2016-11-02 15:44:46 +01:00
std : : stringstream ss1 , ss2 ;
ss1 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
ss2 < < " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " ;
2016-08-30 23:44:15 +02:00
json j ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( ss1 > > j , json : : parse_error & ) ;
2017-03-01 21:28:44 +01:00
CHECK_THROWS_WITH ( ss2 > > j ,
2018-10-07 22:39:17 +02:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 23:44:15 +02:00
}
SECTION ( " user-defined string literal " )
{
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " _json , json : : parse_error & ) ;
2016-08-30 23:44:15 +02:00
CHECK_THROWS_WITH ( " [ \" foo \" ,1,2,3,false,{ \" one \" :1} " _json ,
2018-10-07 22:39:17 +02:00
" [json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']' " ) ;
2016-08-30 23:44:15 +02:00
}
2016-08-04 21:55:47 +02:00
}
2016-08-15 22:44:14 +02:00
SECTION ( " contiguous containers " )
{
2016-08-20 20:29:33 +02:00
SECTION ( " directly " )
2016-08-15 22:44:14 +02:00
{
2016-08-20 20:29:33 +02:00
SECTION ( " from std::vector " )
{
2016-08-23 22:38:05 +02:00
std : : vector < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::array " )
{
2016-08-23 22:38:05 +02:00
std : : array < uint8_t , 5 > v { { ' t ' , ' r ' , ' u ' , ' e ' } } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from array " )
{
2016-08-23 22:38:05 +02:00
uint8_t v [ ] = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
2016-08-31 18:23:46 +02:00
SECTION ( " from chars " )
{
2016-08-31 21:27:23 +02:00
uint8_t * v = new uint8_t [ 5 ] ;
2016-08-31 18:23:46 +02:00
v [ 0 ] = ' t ' ;
v [ 1 ] = ' r ' ;
v [ 2 ] = ' u ' ;
v [ 3 ] = ' e ' ;
v [ 4 ] = ' \0 ' ;
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-31 18:23:46 +02:00
delete [ ] v ;
}
2016-08-20 20:29:33 +02:00
SECTION ( " from std::string " )
{
std : : string v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::initializer_list " )
{
2016-08-23 22:38:05 +02:00
std : : initializer_list < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( v ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
2016-08-21 12:35:40 +02:00
SECTION ( " empty container " )
{
std : : vector < uint8_t > v ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( v ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( v ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( v , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(1) " } ) ) ;
2016-08-21 12:35:40 +02:00
}
2016-08-15 22:44:14 +02:00
}
2016-08-20 20:29:33 +02:00
SECTION ( " via iterator range " )
2016-08-15 22:44:14 +02:00
{
2016-08-20 20:29:33 +02:00
SECTION ( " from std::vector " )
{
2016-08-23 22:38:05 +02:00
std : : vector < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::array " )
{
2016-08-23 22:38:05 +02:00
std : : array < uint8_t , 5 > v { { ' t ' , ' r ' , ' u ' , ' e ' } } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from array " )
{
2016-08-23 22:38:05 +02:00
uint8_t v [ ] = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::string " )
{
std : : string v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::initializer_list " )
{
2016-08-23 22:38:05 +02:00
std : : initializer_list < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " from std::valarray " )
{
2016-08-23 22:38:05 +02:00
std : : valarray < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2016-08-20 20:29:33 +02:00
CHECK ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) = = json ( true ) ) ;
2017-06-16 19:23:55 +02:00
CHECK ( json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " boolean(true) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
SECTION ( " with empty range " )
{
std : : vector < uint8_t > v ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(1) " } ) ) ;
2016-08-20 20:29:33 +02:00
}
2016-08-15 22:44:14 +02:00
}
2016-09-01 00:29:42 +02:00
// these cases are required for 100% line coverage
SECTION ( " error cases " )
{
SECTION ( " case 1 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(10) " } ) ) ;
2016-09-01 00:29:42 +02:00
}
SECTION ( " case 2 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' , ' 1 ' } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(11) " } ) ) ;
2016-09-01 00:29:42 +02:00
}
2016-10-10 21:58:31 +02:00
SECTION ( " case 3 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' \\ ' , ' u ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(18) " } ) ) ;
2016-10-10 21:58:31 +02:00
}
SECTION ( " case 4 " )
{
uint8_t v [ ] = { ' \" ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' a ' , ' u ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' 1 ' , ' \\ ' } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(18) " } ) ) ;
2016-10-10 21:58:31 +02:00
}
2016-10-30 17:10:11 +01:00
SECTION ( " case 5 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xC1 } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(3) " } ) ) ;
2016-10-30 17:10:11 +01:00
}
SECTION ( " case 6 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xDF , 0x7F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-09-09 11:04:58 +02:00
CHECK_THROWS_WITH ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) ,
2018-10-07 22:39:17 +02:00
" [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 ' " ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:10:11 +01:00
}
SECTION ( " case 7 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xDF , 0xC0 } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:10:11 +01:00
}
SECTION ( " case 8 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xE0 , 0x9F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:10:11 +01:00
}
SECTION ( " case 9 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xEF , 0xC0 } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:10:11 +01:00
}
2016-10-30 17:46:00 +01:00
SECTION ( " case 10 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xED , 0x7F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
SECTION ( " case 11 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF0 , 0x8F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
SECTION ( " case 12 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF0 , 0xC0 } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
SECTION ( " case 13 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF3 , 0x7F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
SECTION ( " case 14 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF3 , 0xC0 } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
SECTION ( " case 15 " )
{
uint8_t v [ ] = { ' \" ' , 0x7F , 0xF4 , 0x7F } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-16 19:23:55 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > ( { " parse_error(4) " } ) ) ;
2016-10-30 17:46:00 +01:00
}
2017-06-20 21:09:26 +02:00
SECTION ( " case 16 " )
{
2017-06-20 22:35:31 +02:00
uint8_t v [ ] = { ' { ' , ' \" ' , ' \" ' , ' : ' , ' 1 ' , ' 1 ' } ;
2017-07-07 22:41:22 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : begin ( v ) , std : : end ( v ) ) , json : : parse_error & ) ;
2017-06-20 21:09:26 +02:00
CHECK ( not json : : accept ( std : : begin ( v ) , std : : end ( v ) ) ) ;
2017-07-27 20:33:11 +02:00
json j_error ;
CHECK_NOTHROW ( j_error = json : : parse ( std : : begin ( v ) , std : : end ( v ) , nullptr , false ) ) ;
CHECK ( j_error . is_discarded ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( std : : begin ( v ) , std : : end ( v ) , & l ) ) ;
2018-02-25 17:10:30 +01:00
CHECK ( l . events . size ( ) = = 4 ) ;
2018-02-24 18:04:07 +01:00
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-02-25 17:10:30 +01:00
" start_object() " , " key() " , " number_unsigned(11) " ,
2018-02-24 18:04:07 +01:00
" parse_error(7) "
} ) ) ;
2017-06-20 21:09:26 +02:00
}
2016-09-01 00:29:42 +02:00
}
2016-08-15 22:44:14 +02:00
}
2017-09-10 22:38:04 +02:00
SECTION ( " ignoring byte-order marks " )
{
std : : string bom = " \xEF \xBB \xBF " ;
SECTION ( " BOM only " )
{
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( bom ) , json : : parse_error & ) ;
2017-09-10 22:38:04 +02:00
CHECK_THROWS_WITH ( json : : parse ( bom ) ,
2018-10-07 22:39:17 +02:00
" [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 " ) ;
2017-09-10 22:38:04 +02:00
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : istringstream ( bom ) ) , json : : parse_error & ) ;
2017-09-10 22:38:04 +02:00
CHECK_THROWS_WITH ( json : : parse ( std : : istringstream ( bom ) ) ,
2018-10-07 22:39:17 +02:00
" [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 " ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( bom , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > (
{
2018-04-02 21:10:48 +02:00
" parse_error(4) "
2018-02-24 18:04:07 +01:00
} ) ) ;
2017-09-10 22:38:04 +02:00
}
SECTION ( " BOM and content " )
{
CHECK ( json : : parse ( bom + " 1 " ) = = 1 ) ;
CHECK ( json : : parse ( std : : istringstream ( bom + " 1 " ) ) = = 1 ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l1 , l2 ;
CHECK ( json : : sax_parse ( std : : istringstream ( bom + " 1 " ) , & l1 ) ) ;
CHECK ( json : : sax_parse ( bom + " 1 " , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
" number_unsigned(1) "
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
" number_unsigned(1) "
} ) ) ;
2017-09-10 22:38:04 +02:00
}
SECTION ( " 2 byte of BOM " )
{
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( bom . substr ( 0 , 2 ) ) , json : : parse_error & ) ;
2018-04-02 21:10:48 +02:00
CHECK_THROWS_WITH ( json : : parse ( bom . substr ( 0 , 2 ) ) ,
2018-10-07 22:39:17 +02:00
" [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 ' " ) ;
2017-09-10 22:38:04 +02:00
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) ) , json : : parse_error & ) ;
2018-04-02 21:10:48 +02:00
CHECK_THROWS_WITH ( json : : parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) ) ,
2018-10-07 22:39:17 +02:00
" [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 ' " ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l1 , l2 ;
CHECK ( not json : : sax_parse ( std : : istringstream ( bom . substr ( 0 , 2 ) ) , & l1 ) ) ;
CHECK ( not json : : sax_parse ( bom . substr ( 0 , 2 ) , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
2018-04-02 21:10:48 +02:00
" parse_error(3) "
2018-02-24 18:04:07 +01:00
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
2018-04-02 21:10:48 +02:00
" parse_error(3) "
2018-02-24 18:04:07 +01:00
} ) ) ;
2017-09-10 22:38:04 +02:00
}
SECTION ( " 1 byte of BOM " )
{
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( bom . substr ( 0 , 1 ) ) , json : : parse_error & ) ;
2018-04-02 21:10:48 +02:00
CHECK_THROWS_WITH ( json : : parse ( bom . substr ( 0 , 1 ) ) ,
2018-10-07 22:39:17 +02:00
" [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 ' " ) ;
2017-09-10 22:38:04 +02:00
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) ) , json : : parse_error & ) ;
2018-04-02 21:10:48 +02:00
CHECK_THROWS_WITH ( json : : parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) ) ,
2018-10-07 22:39:17 +02:00
" [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 ' " ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l1 , l2 ;
CHECK ( not json : : sax_parse ( std : : istringstream ( bom . substr ( 0 , 1 ) ) , & l1 ) ) ;
CHECK ( not json : : sax_parse ( bom . substr ( 0 , 1 ) , & l2 ) ) ;
CHECK ( l1 . events . size ( ) = = 1 ) ;
CHECK ( l1 . events = = std : : vector < std : : string > (
{
2018-04-02 21:10:48 +02:00
" parse_error(2) "
2018-02-24 18:04:07 +01:00
} ) ) ;
CHECK ( l2 . events . size ( ) = = 1 ) ;
CHECK ( l2 . events = = std : : vector < std : : string > (
{
2018-04-02 21:10:48 +02:00
" parse_error(2) "
2018-02-24 18:04:07 +01:00
} ) ) ;
2017-09-10 22:38:04 +02:00
}
SECTION ( " variations " )
{
// calculate variations of each byte of the BOM to make sure
// that the BOM and only the BOM is skipped
for ( int i0 = - 1 ; i0 < 2 ; + + i0 )
{
for ( int i1 = - 1 ; i1 < 2 ; + + i1 )
{
for ( int i2 = - 1 ; i2 < 2 ; + + i2 )
{
// debug output for the variations
2018-12-23 13:56:18 +01:00
CAPTURE ( i0 )
CAPTURE ( i1 )
CAPTURE ( i2 )
2017-09-10 22:38:04 +02:00
std : : string s = " " ;
2017-09-30 11:00:26 +02:00
s . push_back ( static_cast < char > ( bom [ 0 ] + i0 ) ) ;
s . push_back ( static_cast < char > ( bom [ 1 ] + i1 ) ) ;
s . push_back ( static_cast < char > ( bom [ 2 ] + i2 ) ) ;
2017-09-10 22:38:04 +02:00
if ( i0 = = 0 and i1 = = 0 and i2 = = 0 )
{
// without any variation, we skip the BOM
CHECK ( json : : parse ( s + " null " ) = = json ( ) ) ;
CHECK ( json : : parse ( std : : istringstream ( s + " null " ) ) = = json ( ) ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( json : : sax_parse ( s + " null " , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
CHECK ( l . events = = std : : vector < std : : string > (
{
" null() "
} ) ) ;
2017-09-10 22:38:04 +02:00
}
else
{
// any variation is an error
2017-09-30 11:00:26 +02:00
CHECK_THROWS_AS ( json : : parse ( s + " null " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( json : : parse ( std : : istringstream ( s + " null " ) ) , json : : parse_error & ) ;
2018-02-24 18:04:07 +01:00
SaxEventLogger l ;
CHECK ( not json : : sax_parse ( s + " null " , & l ) ) ;
CHECK ( l . events . size ( ) = = 1 ) ;
2018-04-02 21:10:48 +02:00
if ( i0 ! = 0 )
2018-02-24 18:04:07 +01:00
{
2018-04-02 21:10:48 +02:00
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(1) "
} ) ) ;
}
else if ( i1 ! = 0 )
{
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(2) "
} ) ) ;
}
else
{
CHECK ( l . events = = std : : vector < std : : string > (
{
" parse_error(3) "
} ) ) ;
}
2017-09-10 22:38:04 +02:00
}
}
}
}
}
SECTION ( " preserve state after parsing " )
{
std : : istringstream s ( bom + " 123 456 " ) ;
json j ;
j < < s ;
CHECK ( j = = 123 ) ;
j < < s ;
CHECK ( j = = 456 ) ;
}
}
2018-02-25 17:10:30 +01:00
SECTION ( " SAX and early abort " )
{
std : : string s = " [1, [ \" string \" , 43.12], null, { \" key1 \" : true, \" key2 \" : false}] " ;
SaxEventLogger default_logger ;
SaxEventLoggerExitAfterStartObject exit_after_start_object ;
SaxEventLoggerExitAfterKey exit_after_key ;
SaxEventLoggerExitAfterStartArray exit_after_start_array ;
json : : sax_parse ( s , & default_logger ) ;
CHECK ( default_logger . events . size ( ) = = 14 ) ;
CHECK ( default_logger . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() " , " key(key1) " , " boolean(true) " , " key(key2) " ,
" boolean(false) " , " end_object() " , " end_array() "
} ) ) ;
json : : sax_parse ( s , & exit_after_start_object ) ;
CHECK ( exit_after_start_object . events . size ( ) = = 8 ) ;
CHECK ( exit_after_start_object . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() "
} ) ) ;
json : : sax_parse ( s , & exit_after_key ) ;
CHECK ( exit_after_key . events . size ( ) = = 9 ) ;
CHECK ( exit_after_key . events = = std : : vector < std : : string > (
{
" start_array() " , " number_unsigned(1) " , " start_array() " ,
" string(string) " , " number_float(43.12) " , " end_array() " , " null() " ,
" start_object() " , " key(key1) "
} ) ) ;
json : : sax_parse ( s , & exit_after_start_array ) ;
CHECK ( exit_after_start_array . events . size ( ) = = 1 ) ;
CHECK ( exit_after_start_array . events = = std : : vector < std : : string > (
{
" start_array() "
} ) ) ;
}
2016-08-04 21:55:47 +02:00
}