2016-08-04 19:55:47 +00:00
/*
__ _____ _____ _____
__ | | __ | | | | JSON for Modern C + + ( test suite )
2018-02-12 21:59:36 +00:00
| | | __ | | | | | | version 3.1 .1
2016-08-04 19:55:47 +00:00
| _____ | _____ | _____ | _ | ___ | https : //github.com/nlohmann/json
Licensed under the MIT License < http : //opensource.org/licenses/MIT>.
2018-02-01 21:20:26 +00:00
Copyright ( c ) 2013 - 2018 Niels Lohmann < http : //nlohmann.me>.
2016-08-04 19:55:47 +00: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"
# define private public
2018-01-29 10:21:11 +00:00
# include <nlohmann/json.hpp>
2016-08-04 19:55:47 +00:00
using nlohmann : : json ;
2016-08-14 12:18:25 +00:00
# include <valarray>
2018-02-26 22:39:23 +00:00
class SaxEventLogger : public nlohmann : : json : : json_sax_t
2018-02-25 13:21:30 +00:00
{
public :
bool null ( ) override
{
events . push_back ( " null() " ) ;
return true ;
}
bool boolean ( bool val ) override
{
events . push_back ( val ? " boolean(true) " : " boolean(false) " ) ;
return true ;
}
bool number_integer ( json : : number_integer_t val ) override
{
events . push_back ( " number_integer( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
bool number_unsigned ( json : : number_unsigned_t val ) override
{
events . push_back ( " number_unsigned( " + std : : to_string ( val ) + " ) " ) ;
return true ;
}
2018-02-25 17:35:16 +00:00
bool number_float ( json : : number_float_t , const std : : string & s ) override
2018-02-25 13:21:30 +00:00
{
events . push_back ( " number_float( " + s + " ) " ) ;
return true ;
}
2018-02-26 22:39:23 +00:00
bool string ( std : : string & & val ) override
2018-02-25 13:21:30 +00:00
{
events . push_back ( " string( " + val + " ) " ) ;
return true ;
}
bool start_object ( std : : size_t elements ) override
{
2018-02-26 22:39:23 +00:00
if ( elements = = no_limit )
2018-02-25 13:21:30 +00:00
{
events . push_back ( " start_object() " ) ;
}
else
{
events . push_back ( " start_object( " + std : : to_string ( elements ) + " ) " ) ;
}
return true ;
}
2018-02-26 22:39:23 +00:00
bool key ( std : : string & & val ) override
2018-02-25 13:21:30 +00:00
{
events . push_back ( " key( " + val + " ) " ) ;
return true ;
}
2018-02-26 22:39:23 +00:00
bool end_object ( ) override
2018-02-25 13:21:30 +00:00
{
events . push_back ( " end_object() " ) ;
return true ;
}
bool start_array ( std : : size_t elements ) override
{
2018-02-26 22:39:23 +00:00
if ( elements = = no_limit )
2018-02-25 13:21:30 +00:00
{
events . push_back ( " start_array() " ) ;
}
else
{
events . push_back ( " start_array( " + std : : to_string ( elements ) + " ) " ) ;
}
return true ;
}
bool end_array ( ) override
{
events . push_back ( " end_array() " ) ;
return true ;
}
2018-02-25 17:35:16 +00:00
bool binary ( const std : : vector < uint8_t > & ) override
2018-02-25 13:21:30 +00:00
{
events . push_back ( " binary() " ) ;
return true ;
}
2018-02-25 17:35:16 +00:00
bool parse_error ( std : : size_t position , const std : : string & ) override
2018-02-25 13:21:30 +00:00
{
errored = true ;
events . push_back ( " parse_error( " + std : : to_string ( position ) + " ) " ) ;
return false ;
}
std : : vector < std : : string > events ;
bool errored = false ;
} ;
2018-02-26 22:39:23 +00:00
class SaxDomParser : public nlohmann : : json : : json_sax_t
{
public :
bool null ( ) override
{
handle_value ( nullptr ) ;
return true ;
}
bool boolean ( bool val ) override
{
handle_value ( val ) ;
return true ;
}
bool number_integer ( json : : number_integer_t val ) override
{
handle_value ( val ) ;
return true ;
}
bool number_unsigned ( json : : number_unsigned_t val ) override
{
handle_value ( val ) ;
return true ;
}
bool number_float ( json : : number_float_t val , const std : : string & ) override
{
handle_value ( val ) ;
return true ;
}
bool string ( std : : string & & val ) override
{
handle_value ( val ) ;
return true ;
}
bool start_object ( std : : size_t ) override
{
ref_stack . push_back ( handle_value ( json : : value_t : : object ) ) ;
return true ;
}
bool key ( std : : string & & val ) override
{
last_key = val ;
return true ;
}
bool end_object ( ) override
{
ref_stack . pop_back ( ) ;
return true ;
}
bool start_array ( std : : size_t ) override
{
ref_stack . push_back ( handle_value ( json : : value_t : : array ) ) ;
return true ;
}
bool end_array ( ) override
{
ref_stack . pop_back ( ) ;
return true ;
}
bool binary ( const std : : vector < uint8_t > & ) override
{
return true ;
}
bool parse_error ( std : : size_t position , const std : : string & ) override
{
return false ;
}
json & get_value ( )
{
return root ;
}
private :
/// the parsed JSON value
json root ;
/// stack to model hierarchy of values
std : : vector < json * > ref_stack ;
/// helper variable for object keys
std : : string last_key ;
/*!
@ invariant If the ref stack is empty , then the passed value will be the new
root .
@ invariant If the ref stack contains a value , then it is an array or an
object to which we can add elements
*/
json * handle_value ( json & & j )
{
if ( ref_stack . empty ( ) )
{
assert ( root . is_null ( ) ) ;
root = j ;
return & root ;
}
else
{
assert ( ref_stack . back ( ) - > is_array ( ) or ref_stack . back ( ) - > is_object ( ) ) ;
if ( ref_stack . back ( ) - > is_array ( ) )
{
ref_stack . back ( ) - > push_back ( j ) ;
return & ( ref_stack . back ( ) - > back ( ) ) ;
}
else
{
json & r = ref_stack . back ( ) - > operator [ ] ( last_key ) = j ;
return & r ;
}
}
}
} ;
2017-07-22 13:18:38 +00:00
json parser_helper ( const std : : string & s ) ;
bool accept_helper ( const std : : string & s ) ;
json parser_helper ( const std : : string & s )
{
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( s ) ) . parse ( true , j ) ;
2017-07-27 18:33:11 +00:00
// if this line was reached, no exception ocurred
// -> 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 ) ) ;
CHECK ( j_nothrow = = j ) ;
2018-02-26 22:39:23 +00:00
SaxDomParser sdp ;
json : : sax_parse ( s , & sdp ) ;
CHECK ( sdp . get_value ( ) = = j ) ;
2017-07-22 13:18:38 +00:00
return j ;
}
bool accept_helper ( const std : : string & s )
{
2018-02-25 13:21:30 +00:00
CAPTURE ( s ) ;
2017-07-27 18:33:11 +00:00
// 1. parse s without exceptions
json j ;
CHECK_NOTHROW ( json : : parser ( nlohmann : : detail : : input_adapter ( s ) , nullptr , false ) . parse ( true , j ) ) ;
const bool ok_noexcept = not j . is_discarded ( ) ;
// 2. accept s
const bool ok_accept = json : : parser ( nlohmann : : detail : : input_adapter ( s ) ) . accept ( true ) ;
// 3. check if both approaches come to the same result
CHECK ( ok_noexcept = = ok_accept ) ;
2018-02-25 13:21:30 +00:00
// 4. parse with SAX (compare with relaxed accept result)
SaxEventLogger el ;
CHECK_NOTHROW ( json : : sax_parse ( s , & el ) ) ;
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( s ) ) . accept ( false ) = = not el . errored ) ;
// 5. return result
2017-07-27 18:33:11 +00:00
return ok_accept ;
2017-07-22 13:18:38 +00:00
}
2016-08-04 19:55:47 +00:00
TEST_CASE ( " parser class " )
{
SECTION ( " parse " )
{
SECTION ( " null " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " null " ) = = json ( nullptr ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " true " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " true " ) = = json ( true ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " false " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " false " ) = = json ( false ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " array " )
{
SECTION ( " empty array " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " [] " ) = = json ( json : : value_t : : array ) ) ;
CHECK ( parser_helper ( " [ ] " ) = = json ( json : : value_t : : array ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " nonempty array " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " [true, false, null] " ) = = json ( { true , false , nullptr } ) ) ;
2016-08-04 19:55:47 +00:00
}
}
SECTION ( " object " )
{
SECTION ( " empty object " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " {} " ) = = json ( json : : value_t : : object ) ) ;
CHECK ( parser_helper ( " { } " ) = = json ( json : : value_t : : object ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " nonempty object " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " { \" \" : true, \" one \" : 1, \" two \" : null} " ) = = json ( { { " " , true } , { " one " , 1 } , { " two " , nullptr } } ) ) ;
2016-08-04 19:55:47 +00:00
}
}
SECTION ( " string " )
{
// empty string
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \" " ) = = json ( json : : value_t : : string ) ) ;
2016-08-04 19:55:47 +00:00
SECTION ( " errors " )
{
// error: tab in string
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \" \t \" " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \t \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0009>' " ) ;
2016-08-04 19:55:47 +00:00
// error: newline in string
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \" \n \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \r \" " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \n \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000A>' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \r \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000D>' " ) ;
2016-08-04 19:55:47 +00:00
// error: backspace in string
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \" \b \" " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \b \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0008>' " ) ;
2016-08-04 19:55:47 +00:00
// improve code coverage
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \uFF01 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " [-4:1,] " ) , json : : parse_error & ) ;
2016-08-04 19:55:47 +00:00
// unescaped control characters
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \" \x00 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x01 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x02 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x03 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x04 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x05 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x06 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x07 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x08 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x09 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0a \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0b \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0c \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0d \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0e \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x0f \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x10 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x11 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x12 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x13 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x14 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x15 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x16 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x17 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x18 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x19 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1a \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1b \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1c \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1d \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1e \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \x1f \" " ) , json : : parse_error & ) ;
2017-09-09 09:04:58 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \x00 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: ' \" ' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x01 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0001>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x02 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0002>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x03 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0003>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x04 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0004>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x05 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0005>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x06 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0006>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x07 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0007>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x08 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0008>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x09 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0009>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0a \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000A>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0b \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000B>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0c \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000C>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0d \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000D>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0e \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000E>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x0f \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+000F>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x10 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0010>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x11 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0011>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x12 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0012>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x13 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0013>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x14 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0014>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x15 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0015>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x16 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0016>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x17 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0017>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x18 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0018>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x19 \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0019>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1a \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001A>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1b \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001B>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1c \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001C>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1d \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001D>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1e \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001E>' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" \x1f \" " ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+001F>' " ) ;
2017-09-13 16:56:54 +00:00
SECTION ( " additional test for null byte " )
{
// The test above for the null byte is wrong, because passing
// a string to the parser only reads int until it encounters
// a null byte. This test inserts the null byte later on and
// uses an iterator range.
std : : string s = " \" 1 \" " ;
s [ 1 ] = ' \0 ' ;
CHECK_THROWS_AS ( json : : parse ( s . begin ( ) , s . end ( ) ) , json : : parse_error & ) ;
2017-10-04 18:31:10 +00:00
CHECK_THROWS_WITH ( json : : parse ( s . begin ( ) , s . end ( ) ) , " [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: ' \" <U+0000>' " ) ;
2017-09-13 16:56:54 +00:00
}
2016-08-04 19:55:47 +00:00
}
SECTION ( " escaped " )
{
// quotation mark "\""
auto r1 = R " ( " \ " " ) " _json;
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ \" \" " ) = = r1 ) ;
2016-08-04 19:55:47 +00:00
// reverse solidus "\\"
auto r2 = R " ( " \ \ " ) " _json ;
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ \\ \" " ) = = r2 ) ;
2016-08-04 19:55:47 +00:00
// solidus
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ / \" " ) = = R " ( " / " ) " _json ) ;
2016-08-04 19:55:47 +00:00
// backspace
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ b \" " ) = = json ( " \b " ) ) ;
2016-08-04 19:55:47 +00:00
// formfeed
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ f \" " ) = = json ( " \f " ) ) ;
2016-08-04 19:55:47 +00:00
// newline
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ n \" " ) = = json ( " \n " ) ) ;
2016-08-04 19:55:47 +00:00
// carriage return
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ r \" " ) = = json ( " \r " ) ) ;
2016-08-04 19:55:47 +00:00
// horizontal tab
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " \" \\ t \" " ) = = json ( " \t " ) ) ;
CHECK ( parser_helper ( " \" \\ u0001 \" " ) . get < json : : string_t > ( ) = = " \x01 " ) ;
CHECK ( parser_helper ( " \" \\ u000a \" " ) . get < json : : string_t > ( ) = = " \n " ) ;
CHECK ( parser_helper ( " \" \\ u00b0 \" " ) . get < json : : string_t > ( ) = = " ° " ) ;
CHECK ( parser_helper ( " \" \\ u0c00 \" " ) . get < json : : string_t > ( ) = = " ఀ " ) ;
CHECK ( parser_helper ( " \" \\ ud000 \" " ) . get < json : : string_t > ( ) = = " 퀀 " ) ;
CHECK ( parser_helper ( " \" \\ u000E \" " ) . get < json : : string_t > ( ) = = " \x0E " ) ;
CHECK ( parser_helper ( " \" \\ u00F0 \" " ) . get < json : : string_t > ( ) = = " ð " ) ;
CHECK ( parser_helper ( " \" \\ u0100 \" " ) . get < json : : string_t > ( ) = = " Ā " ) ;
CHECK ( parser_helper ( " \" \\ u2000 \" " ) . get < json : : string_t > ( ) = = " " ) ;
CHECK ( parser_helper ( " \" \\ uFFFF \" " ) . get < json : : string_t > ( ) = = " " ) ;
CHECK ( parser_helper ( " \" \\ u20AC \" " ) . get < json : : string_t > ( ) = = " € " ) ;
CHECK ( parser_helper ( " \" € \" " ) . get < json : : string_t > ( ) = = " € " ) ;
CHECK ( parser_helper ( " \" 🎈 \" " ) . get < json : : string_t > ( ) = = " 🎈 " ) ;
CHECK ( parser_helper ( " \" \\ ud80c \\ udc60 \" " ) . get < json : : string_t > ( ) = = u8 " \U00013060 " ) ;
CHECK ( parser_helper ( " \" \\ ud83c \\ udf1e \" " ) . get < json : : string_t > ( ) = = " 🌞 " ) ;
2016-08-04 19:55:47 +00:00
}
}
SECTION ( " number " )
{
SECTION ( " integers " )
{
SECTION ( " without exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " -128 " ) = = json ( - 128 ) ) ;
CHECK ( parser_helper ( " -0 " ) = = json ( - 0 ) ) ;
CHECK ( parser_helper ( " 0 " ) = = json ( 0 ) ) ;
CHECK ( parser_helper ( " 128 " ) = = json ( 128 ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " with exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " 0e1 " ) = = json ( 0e1 ) ) ;
CHECK ( parser_helper ( " 0E1 " ) = = json ( 0e1 ) ) ;
CHECK ( parser_helper ( " 10000E-4 " ) = = json ( 10000e-4 ) ) ;
CHECK ( parser_helper ( " 10000E-3 " ) = = json ( 10000e-3 ) ) ;
CHECK ( parser_helper ( " 10000E-2 " ) = = json ( 10000e-2 ) ) ;
CHECK ( parser_helper ( " 10000E-1 " ) = = json ( 10000e-1 ) ) ;
CHECK ( parser_helper ( " 10000E0 " ) = = json ( 10000e0 ) ) ;
CHECK ( parser_helper ( " 10000E1 " ) = = json ( 10000e1 ) ) ;
CHECK ( parser_helper ( " 10000E2 " ) = = json ( 10000e2 ) ) ;
CHECK ( parser_helper ( " 10000E3 " ) = = json ( 10000e3 ) ) ;
CHECK ( parser_helper ( " 10000E4 " ) = = json ( 10000e4 ) ) ;
CHECK ( parser_helper ( " 10000e-4 " ) = = json ( 10000e-4 ) ) ;
CHECK ( parser_helper ( " 10000e-3 " ) = = json ( 10000e-3 ) ) ;
CHECK ( parser_helper ( " 10000e-2 " ) = = json ( 10000e-2 ) ) ;
CHECK ( parser_helper ( " 10000e-1 " ) = = json ( 10000e-1 ) ) ;
CHECK ( parser_helper ( " 10000e0 " ) = = json ( 10000e0 ) ) ;
CHECK ( parser_helper ( " 10000e1 " ) = = json ( 10000e1 ) ) ;
CHECK ( parser_helper ( " 10000e2 " ) = = json ( 10000e2 ) ) ;
CHECK ( parser_helper ( " 10000e3 " ) = = json ( 10000e3 ) ) ;
CHECK ( parser_helper ( " 10000e4 " ) = = json ( 10000e4 ) ) ;
CHECK ( parser_helper ( " -0e1 " ) = = json ( - 0e1 ) ) ;
CHECK ( parser_helper ( " -0E1 " ) = = json ( - 0e1 ) ) ;
CHECK ( parser_helper ( " -0E123 " ) = = json ( - 0e123 ) ) ;
2017-09-09 14:53:27 +00:00
// numbers after exponent
CHECK ( parser_helper ( " 10E0 " ) = = json ( 10e0 ) ) ;
CHECK ( parser_helper ( " 10E1 " ) = = json ( 10e1 ) ) ;
CHECK ( parser_helper ( " 10E2 " ) = = json ( 10e2 ) ) ;
CHECK ( parser_helper ( " 10E3 " ) = = json ( 10e3 ) ) ;
CHECK ( parser_helper ( " 10E4 " ) = = json ( 10e4 ) ) ;
CHECK ( parser_helper ( " 10E5 " ) = = json ( 10e5 ) ) ;
CHECK ( parser_helper ( " 10E6 " ) = = json ( 10e6 ) ) ;
CHECK ( parser_helper ( " 10E7 " ) = = json ( 10e7 ) ) ;
CHECK ( parser_helper ( " 10E8 " ) = = json ( 10e8 ) ) ;
CHECK ( parser_helper ( " 10E9 " ) = = json ( 10e9 ) ) ;
CHECK ( parser_helper ( " 10E+0 " ) = = json ( 10e0 ) ) ;
CHECK ( parser_helper ( " 10E+1 " ) = = json ( 10e1 ) ) ;
CHECK ( parser_helper ( " 10E+2 " ) = = json ( 10e2 ) ) ;
CHECK ( parser_helper ( " 10E+3 " ) = = json ( 10e3 ) ) ;
CHECK ( parser_helper ( " 10E+4 " ) = = json ( 10e4 ) ) ;
CHECK ( parser_helper ( " 10E+5 " ) = = json ( 10e5 ) ) ;
CHECK ( parser_helper ( " 10E+6 " ) = = json ( 10e6 ) ) ;
CHECK ( parser_helper ( " 10E+7 " ) = = json ( 10e7 ) ) ;
CHECK ( parser_helper ( " 10E+8 " ) = = json ( 10e8 ) ) ;
CHECK ( parser_helper ( " 10E+9 " ) = = json ( 10e9 ) ) ;
CHECK ( parser_helper ( " 10E-1 " ) = = json ( 10e-1 ) ) ;
CHECK ( parser_helper ( " 10E-2 " ) = = json ( 10e-2 ) ) ;
CHECK ( parser_helper ( " 10E-3 " ) = = json ( 10e-3 ) ) ;
CHECK ( parser_helper ( " 10E-4 " ) = = json ( 10e-4 ) ) ;
CHECK ( parser_helper ( " 10E-5 " ) = = json ( 10e-5 ) ) ;
CHECK ( parser_helper ( " 10E-6 " ) = = json ( 10e-6 ) ) ;
CHECK ( parser_helper ( " 10E-7 " ) = = json ( 10e-7 ) ) ;
CHECK ( parser_helper ( " 10E-8 " ) = = json ( 10e-8 ) ) ;
CHECK ( parser_helper ( " 10E-9 " ) = = json ( 10e-9 ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " edge cases " )
{
// From RFC7159, Section 6:
// Note that when such software is used, numbers that are
// integers and are in the range [-(2**53)+1, (2**53)-1]
// are interoperable in the sense that implementations will
// agree exactly on their numeric values.
// -(2**53)+1
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " -9007199254740991 " ) . get < int64_t > ( ) = = - 9007199254740991 ) ;
2016-08-04 19:55:47 +00:00
// (2**53)-1
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " 9007199254740991 " ) . get < int64_t > ( ) = = 9007199254740991 ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " over the edge cases " ) // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
{
// While RFC7159, Section 6 specifies a preference for support
// for ranges in range of IEEE 754-2008 binary64 (double precision)
// this does not accommodate 64 bit integers without loss of accuracy.
// As 64 bit integers are now widely used in software, it is desirable
// to expand support to to the full 64 bit (signed and unsigned) range
// i.e. -(2**63) -> (2**64)-1.
// -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " -9223372036854775808 " ) . get < int64_t > ( ) = = - 9223372036854775807 - 1 ) ;
2016-08-04 19:55:47 +00:00
// (2**63)-1
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " 9223372036854775807 " ) . get < int64_t > ( ) = = 9223372036854775807 ) ;
2016-08-04 19:55:47 +00:00
// (2**64)-1
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " 18446744073709551615 " ) . get < uint64_t > ( ) = = 18446744073709551615u ) ;
2016-08-04 19:55:47 +00:00
}
}
SECTION ( " floating-point " )
{
SECTION ( " without exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " -128.5 " ) = = json ( - 128.5 ) ) ;
CHECK ( parser_helper ( " 0.999 " ) = = json ( 0.999 ) ) ;
CHECK ( parser_helper ( " 128.5 " ) = = json ( 128.5 ) ) ;
CHECK ( parser_helper ( " -0.0 " ) = = json ( - 0.0 ) ) ;
2016-08-04 19:55:47 +00:00
}
SECTION ( " with exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " -128.5E3 " ) = = json ( - 128.5E3 ) ) ;
CHECK ( parser_helper ( " -128.5E-3 " ) = = json ( - 128.5E-3 ) ) ;
CHECK ( parser_helper ( " -0.0e1 " ) = = json ( - 0.0e1 ) ) ;
CHECK ( parser_helper ( " -0.0E1 " ) = = json ( - 0.0e1 ) ) ;
2016-08-04 19:55:47 +00:00
}
}
2017-02-13 17:51:23 +00:00
SECTION ( " overflow " )
{
2017-03-12 17:38:05 +00:00
// overflows during parsing yield an exception
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " 1.18973e+4932 " ) = = json ( ) , json : : out_of_range & ) ;
CHECK_THROWS_WITH ( parser_helper ( " 1.18973e+4932 " ) = = json ( ) ,
2017-03-14 15:07:28 +00:00
" [json.exception.out_of_range.406] number overflow parsing '1.18973e+4932' " ) ;
2017-02-13 17:51:23 +00:00
}
2016-08-04 19:55:47 +00:00
SECTION ( " invalid numbers " )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " 01 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " --1 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1E " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1E- " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1.E1 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -1E " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0E# " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0E-# " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0# " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0.0: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0.0Z " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0E123: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0e0-: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0e-: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0f " ) , json : : parse_error & ) ;
2016-08-04 19:55:47 +00:00
// numbers must not begin with "+"
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " +1 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " +0 " ) , json : : parse_error & ) ;
2016-08-04 19:55:47 +00:00
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 01 " ) ,
2017-03-28 15:00:03 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - unexpected number literal; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -01 " ) ,
2017-03-28 15:00:03 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - unexpected number literal; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " --1 " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '--' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '1.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1E " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1E- " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after exponent sign; last read: '1E-' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1.E1 " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '1.E' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -1E " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '-1E' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0E# " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0E-# " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0E-#' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0# " ) ,
2017-03-28 15:00:03 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: '-0#'; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0.0: " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - unexpected ':'; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0.0Z " ) ,
2017-03-28 15:00:03 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: '-0.0Z'; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0E123: " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 7: syntax error - unexpected ':'; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0e0-: " ) ,
2017-03-28 15:00:03 +00:00
" [json.exception.parse_error.101] parse error at 6: syntax error - invalid number; expected digit after '-'; last read: '-:'; expected end of input " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0e-: " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0e-:' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0f " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: '-0f'; expected end of input " ) ;
2016-08-04 19:55:47 +00:00
}
}
}
2017-04-24 15:46:21 +00:00
SECTION ( " accept " )
{
SECTION ( " null " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " null " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " true " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " true " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " false " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " false " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " array " )
{
SECTION ( " empty array " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " [] " ) ) ;
CHECK ( accept_helper ( " [ ] " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " nonempty array " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " [true, false, null] " ) ) ;
2017-04-24 15:46:21 +00:00
}
}
SECTION ( " object " )
{
SECTION ( " empty object " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " {} " ) ) ;
CHECK ( accept_helper ( " { } " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " nonempty object " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " { \" \" : true, \" one \" : 1, \" two \" : null} " ) ) ;
2017-04-24 15:46:21 +00:00
}
}
SECTION ( " string " )
{
// empty string
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \" " ) ) ;
2017-04-24 15:46:21 +00:00
SECTION ( " errors " )
{
// error: tab in string
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \t \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// error: newline in string
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \n \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \r \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// error: backspace in string
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \b \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// improve code coverage
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \uFF01 " ) = = false ) ;
CHECK ( accept_helper ( " [-4:1,] " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// unescaped control characters
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \x00 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x01 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x02 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x03 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x04 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x05 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x06 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x07 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x08 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x09 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0a \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0b \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0c \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0d \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0e \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x0f \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x10 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x11 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x12 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x13 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x14 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x15 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x16 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x17 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x18 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x19 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1a \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1b \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1c \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1d \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1e \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \x1f \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " escaped " )
{
// quotation mark "\""
auto r1 = R " ( " \ " " ) " _json;
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ \" \" " ) ) ;
2017-04-24 15:46:21 +00:00
// reverse solidus "\\"
auto r2 = R " ( " \ \ " ) " _json ;
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ \\ \" " ) ) ;
2017-04-24 15:46:21 +00:00
// solidus
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ / \" " ) ) ;
2017-04-24 15:46:21 +00:00
// backspace
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ b \" " ) ) ;
2017-04-24 15:46:21 +00:00
// formfeed
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ f \" " ) ) ;
2017-04-24 15:46:21 +00:00
// newline
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ n \" " ) ) ;
2017-04-24 15:46:21 +00:00
// carriage return
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ r \" " ) ) ;
2017-04-24 15:46:21 +00:00
// horizontal tab
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ t \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u0001 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u000a \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u00b0 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u0c00 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ ud000 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u000E \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u00F0 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u0100 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u2000 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ uFFFF \" " ) ) ;
CHECK ( accept_helper ( " \" \\ u20AC \" " ) ) ;
CHECK ( accept_helper ( " \" € \" " ) ) ;
CHECK ( accept_helper ( " \" 🎈 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ ud80c \\ udc60 \" " ) ) ;
CHECK ( accept_helper ( " \" \\ ud83c \\ udf1e \" " ) ) ;
2017-04-24 15:46:21 +00:00
}
}
SECTION ( " number " )
{
SECTION ( " integers " )
{
SECTION ( " without exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " -128 " ) ) ;
CHECK ( accept_helper ( " -0 " ) ) ;
CHECK ( accept_helper ( " 0 " ) ) ;
CHECK ( accept_helper ( " 128 " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " with exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 0e1 " ) ) ;
CHECK ( accept_helper ( " 0E1 " ) ) ;
CHECK ( accept_helper ( " 10000E-4 " ) ) ;
CHECK ( accept_helper ( " 10000E-3 " ) ) ;
CHECK ( accept_helper ( " 10000E-2 " ) ) ;
CHECK ( accept_helper ( " 10000E-1 " ) ) ;
CHECK ( accept_helper ( " 10000E0 " ) ) ;
CHECK ( accept_helper ( " 10000E1 " ) ) ;
CHECK ( accept_helper ( " 10000E2 " ) ) ;
CHECK ( accept_helper ( " 10000E3 " ) ) ;
CHECK ( accept_helper ( " 10000E4 " ) ) ;
CHECK ( accept_helper ( " 10000e-4 " ) ) ;
CHECK ( accept_helper ( " 10000e-3 " ) ) ;
CHECK ( accept_helper ( " 10000e-2 " ) ) ;
CHECK ( accept_helper ( " 10000e-1 " ) ) ;
CHECK ( accept_helper ( " 10000e0 " ) ) ;
CHECK ( accept_helper ( " 10000e1 " ) ) ;
CHECK ( accept_helper ( " 10000e2 " ) ) ;
CHECK ( accept_helper ( " 10000e3 " ) ) ;
CHECK ( accept_helper ( " 10000e4 " ) ) ;
CHECK ( accept_helper ( " -0e1 " ) ) ;
CHECK ( accept_helper ( " -0E1 " ) ) ;
CHECK ( accept_helper ( " -0E123 " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " edge cases " )
{
// From RFC7159, Section 6:
// Note that when such software is used, numbers that are
// integers and are in the range [-(2**53)+1, (2**53)-1]
// are interoperable in the sense that implementations will
// agree exactly on their numeric values.
// -(2**53)+1
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " -9007199254740991 " ) ) ;
2017-04-24 15:46:21 +00:00
// (2**53)-1
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 9007199254740991 " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " over the edge cases " ) // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
{
// While RFC7159, Section 6 specifies a preference for support
// for ranges in range of IEEE 754-2008 binary64 (double precision)
// this does not accommodate 64 bit integers without loss of accuracy.
// As 64 bit integers are now widely used in software, it is desirable
// to expand support to to the full 64 bit (signed and unsigned) range
// i.e. -(2**63) -> (2**64)-1.
// -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " -9223372036854775808 " ) ) ;
2017-04-24 15:46:21 +00:00
// (2**63)-1
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 9223372036854775807 " ) ) ;
2017-04-24 15:46:21 +00:00
// (2**64)-1
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 18446744073709551615 " ) ) ;
2017-04-24 15:46:21 +00:00
}
}
SECTION ( " floating-point " )
{
SECTION ( " without exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " -128.5 " ) ) ;
CHECK ( accept_helper ( " 0.999 " ) ) ;
CHECK ( accept_helper ( " 128.5 " ) ) ;
CHECK ( accept_helper ( " -0.0 " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " with exponent " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " -128.5E3 " ) ) ;
CHECK ( accept_helper ( " -128.5E-3 " ) ) ;
CHECK ( accept_helper ( " -0.0e1 " ) ) ;
CHECK ( accept_helper ( " -0.0E1 " ) ) ;
2017-04-24 15:46:21 +00:00
}
}
SECTION ( " overflow " )
{
2017-07-27 18:33:11 +00:00
// overflows during parsing
CHECK ( not accept_helper ( " 1.18973e+4932 " ) ) ;
2017-04-24 15:46:21 +00:00
}
SECTION ( " invalid numbers " )
{
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 01 " ) = = false ) ;
CHECK ( accept_helper ( " --1 " ) = = false ) ;
CHECK ( accept_helper ( " 1. " ) = = false ) ;
CHECK ( accept_helper ( " 1E " ) = = false ) ;
CHECK ( accept_helper ( " 1E- " ) = = false ) ;
CHECK ( accept_helper ( " 1.E1 " ) = = false ) ;
CHECK ( accept_helper ( " -1E " ) = = false ) ;
CHECK ( accept_helper ( " -0E# " ) = = false ) ;
CHECK ( accept_helper ( " -0E-# " ) = = false ) ;
CHECK ( accept_helper ( " -0# " ) = = false ) ;
CHECK ( accept_helper ( " -0.0: " ) = = false ) ;
CHECK ( accept_helper ( " -0.0Z " ) = = false ) ;
CHECK ( accept_helper ( " -0E123: " ) = = false ) ;
CHECK ( accept_helper ( " -0e0-: " ) = = false ) ;
CHECK ( accept_helper ( " -0e-: " ) = = false ) ;
CHECK ( accept_helper ( " -0f " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// numbers must not begin with "+"
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " +1 " ) = = false ) ;
CHECK ( accept_helper ( " +0 " ) = = false ) ;
2017-04-24 15:46:21 +00:00
}
}
}
2016-08-04 19:55:47 +00:00
SECTION ( " parse errors " )
{
// unexpected end of number
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " 0. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " - " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -- " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -0. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " -: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 0.: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " e. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1e. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1e/ " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1e: " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1E. " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1E/ " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " 1E: " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " 0. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " - " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -- " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '--' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -0. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after '.'; last read: '-0.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " -: " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-:' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 0.: " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.:' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " e. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 1: syntax error - invalid literal; last read: 'e' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1e. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1e/ " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e/' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1e: " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e:' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1E. " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E.' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1E/ " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E/' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " 1E: " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E:' " ) ;
2016-08-04 19:55:47 +00:00
// unexpected end of null
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " n " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " nu " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " nul " ) , json : : parse_error & ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_AS ( parser_helper ( " nulk " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " nulm " ) , json : : parse_error & ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " n " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'n' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " nu " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'nu' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " nul " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nul' " ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_WITH ( parser_helper ( " nulk " ) ,
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulk' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " nulm " ) ,
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulm' " ) ;
2016-08-04 19:55:47 +00:00
// unexpected end of true
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " t " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " tr " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " tru " ) , json : : parse_error & ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_AS ( parser_helper ( " trud " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " truf " ) , json : : parse_error & ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " t " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 't' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " tr " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'tr' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " tru " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'tru' " ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_WITH ( parser_helper ( " trud " ) ,
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'trud' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " truf " ) ,
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'truf' " ) ;
2016-08-04 19:55:47 +00:00
// unexpected end of false
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " f " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " fa " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " fal " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " fals " ) , json : : parse_error & ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_AS ( parser_helper ( " falsd " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " falsf " ) , json : : parse_error & ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " f " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'f' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " fa " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'fa' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " fal " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'fal' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " fals " ) ,
2017-06-22 14:40:15 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'fals' " ) ;
2017-09-09 11:07:10 +00:00
CHECK_THROWS_WITH ( parser_helper ( " falsd " ) ,
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsd' " ) ;
CHECK_THROWS_WITH ( parser_helper ( " falsf " ) ,
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsf' " ) ;
2016-08-04 19:55:47 +00:00
// missing/unexpected end of array
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " [ " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " [1 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " [1, " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " [1,] " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " ] " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " [ " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected '[', '{', or a literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " [1 " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - unexpected end of input; expected ']' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " [1, " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " [1,] " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - unexpected ']'; expected '[', '{', or a literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " ] " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 1: syntax error - unexpected ']'; expected '[', '{', or a literal " ) ;
2016-08-04 19:55:47 +00:00
// missing/unexpected end of object
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " { " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " { \" foo \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " { \" foo \" : " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " { \" foo \" :} " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " { \" foo \" :1,} " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " } " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " { " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected string literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " { \" foo \" " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 7: syntax error - unexpected end of input; expected ':' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " { \" foo \" : " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 8: syntax error - unexpected end of input; expected '[', '{', or a literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " { \" foo \" :} " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 8: syntax error - unexpected '}'; expected '[', '{', or a literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " { \" foo \" :1,} " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 10: syntax error - unexpected '}'; expected string literal " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " } " ) ,
2017-06-21 05:26:50 +00:00
" [json.exception.parse_error.101] parse error at 1: syntax error - unexpected '}'; expected '[', '{', or a literal " ) ;
2016-08-04 19:55:47 +00:00
// missing/unexpected end of string
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u0 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u01 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u012 \" " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u0 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u01 " ) , json : : parse_error & ) ;
CHECK_THROWS_AS ( parser_helper ( " \" \\ u012 " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: ' \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid string: missing closing quote; last read: ' \" \\ \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u0 \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u0 \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u01 \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 6: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u01 \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u012 \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 7: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u012 \" ' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u0 " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u0' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u01 " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 6: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u01' " ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( " \" \\ u012 " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 7: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' \" \\ u012' " ) ;
2016-08-04 19:55:47 +00:00
// invalid escapes
for ( int c = 1 ; c < 128 ; + + c )
{
2017-03-16 17:39:33 +00:00
auto s = std : : string ( " \" \\ " ) + std : : string ( 1 , static_cast < char > ( c ) ) + " \" " ;
2016-08-04 19:55:47 +00:00
switch ( c )
{
// valid escapes
case ( ' " ' ) :
case ( ' \\ ' ) :
case ( ' / ' ) :
case ( ' b ' ) :
case ( ' f ' ) :
case ( ' n ' ) :
case ( ' r ' ) :
case ( ' t ' ) :
{
2017-07-22 13:18:38 +00:00
CHECK_NOTHROW ( parser_helper ( s . c_str ( ) ) ) ;
2016-08-04 19:55:47 +00:00
break ;
}
// \u must be followed with four numbers, so we skip it here
case ( ' u ' ) :
{
break ;
}
// any other combination of backslash and character is invalid
default :
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( s . c_str ( ) ) , json : : parse_error & ) ;
2017-03-26 13:29:08 +00:00
// only check error message if c is not a control character
if ( c > 0x1f )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( s . c_str ( ) ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 3: syntax error - invalid string: forbidden character after backslash; last read: ' \" \\ " + std : : string ( 1 , static_cast < char > ( c ) ) + " ' " ) ;
2017-03-26 13:29:08 +00:00
}
2016-08-04 19:55:47 +00:00
break ;
}
}
}
// invalid \uxxxx escapes
{
// check whether character is a valid hex character
const auto valid = [ ] ( int c )
{
switch ( c )
{
case ( ' 0 ' ) :
case ( ' 1 ' ) :
case ( ' 2 ' ) :
case ( ' 3 ' ) :
case ( ' 4 ' ) :
case ( ' 5 ' ) :
case ( ' 6 ' ) :
case ( ' 7 ' ) :
case ( ' 8 ' ) :
case ( ' 9 ' ) :
case ( ' a ' ) :
case ( ' b ' ) :
case ( ' c ' ) :
case ( ' d ' ) :
case ( ' e ' ) :
case ( ' f ' ) :
case ( ' A ' ) :
case ( ' B ' ) :
case ( ' C ' ) :
case ( ' D ' ) :
case ( ' E ' ) :
case ( ' F ' ) :
{
return true ;
}
default :
{
return false ;
}
}
} ;
for ( int c = 1 ; c < 128 ; + + c )
{
std : : string s = " \" \\ u " ;
// create a string with the iterated character at each position
2017-03-16 17:39:33 +00:00
auto s1 = s + " 000 " + std : : string ( 1 , static_cast < char > ( c ) ) + " \" " ;
auto s2 = s + " 00 " + std : : string ( 1 , static_cast < char > ( c ) ) + " 0 \" " ;
auto s3 = s + " 0 " + std : : string ( 1 , static_cast < char > ( c ) ) + " 00 \" " ;
auto s4 = s + std : : string ( 1 , static_cast < char > ( c ) ) + " 000 \" " ;
2016-08-04 19:55:47 +00:00
if ( valid ( c ) )
{
2017-03-26 13:29:08 +00:00
CAPTURE ( s1 ) ;
2017-07-22 13:18:38 +00:00
CHECK_NOTHROW ( parser_helper ( s1 . c_str ( ) ) ) ;
2017-03-26 13:29:08 +00:00
CAPTURE ( s2 ) ;
2017-07-22 13:18:38 +00:00
CHECK_NOTHROW ( parser_helper ( s2 . c_str ( ) ) ) ;
2017-03-26 13:29:08 +00:00
CAPTURE ( s3 ) ;
2017-07-22 13:18:38 +00:00
CHECK_NOTHROW ( parser_helper ( s3 . c_str ( ) ) ) ;
2017-03-26 13:29:08 +00:00
CAPTURE ( s4 ) ;
2017-07-22 13:18:38 +00:00
CHECK_NOTHROW ( parser_helper ( s4 . c_str ( ) ) ) ;
2016-08-04 19:55:47 +00:00
}
else
{
2017-03-26 13:29:08 +00:00
CAPTURE ( s1 ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( s1 . c_str ( ) ) , json : : parse_error & ) ;
2017-03-26 13:29:08 +00:00
// only check error message if c is not a control character
if ( c > 0x1f )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( s1 . c_str ( ) ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 7: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' " + s1 . substr ( 0 , 7 ) + " ' " ) ;
2017-03-26 13:29:08 +00:00
}
CAPTURE ( s2 ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( s2 . c_str ( ) ) , json : : parse_error & ) ;
2017-03-26 13:29:08 +00:00
// only check error message if c is not a control character
if ( c > 0x1f )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( s2 . c_str ( ) ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 6: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' " + s2 . substr ( 0 , 6 ) + " ' " ) ;
2017-03-26 13:29:08 +00:00
}
CAPTURE ( s3 ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( s3 . c_str ( ) ) , json : : parse_error & ) ;
2017-03-26 13:29:08 +00:00
// only check error message if c is not a control character
if ( c > 0x1f )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( s3 . c_str ( ) ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 5: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' " + s3 . substr ( 0 , 5 ) + " ' " ) ;
2017-03-26 13:29:08 +00:00
}
2017-03-01 20:28:44 +00:00
2017-03-26 13:29:08 +00:00
CAPTURE ( s4 ) ;
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( s4 . c_str ( ) ) , json : : parse_error & ) ;
2017-03-26 13:29:08 +00:00
// only check error message if c is not a control character
if ( c > 0x1f )
{
2017-07-22 13:18:38 +00:00
CHECK_THROWS_WITH ( parser_helper ( s4 . c_str ( ) ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ' \\ u' must be followed by 4 hex digits; last read: ' " + s4 . substr ( 0 , 4 ) + " ' " ) ;
2017-03-26 13:29:08 +00:00
}
2016-08-04 19:55:47 +00:00
}
}
}
// missing part of a surrogate pair
2017-07-07 20:41:22 +00:00
CHECK_THROWS_AS ( json : : parse ( " \" \\ uD80C \" " ) , json : : parse_error & ) ;
2017-03-01 20:28:44 +00:00
CHECK_THROWS_WITH ( json : : parse ( " \" \\ uD80C \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: ' \" \\ uD80C \" ' " ) ;
2016-08-04 19:55:47 +00:00
// invalid surrogate pair
2017-07-07 20:41:22 +00:00
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 & ) ;
2016-08-04 19:55:47 +00:00
CHECK_THROWS_WITH ( json : : parse ( " \" \\ uD80C \\ uD80C \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: ' \" \\ uD80C \\ uD80C' " ) ;
2016-08-04 19:55:47 +00:00
CHECK_THROWS_WITH ( json : : parse ( " \" \\ uD80C \\ u0000 \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: ' \" \\ uD80C \\ u0000' " ) ;
2016-08-04 19:55:47 +00:00
CHECK_THROWS_WITH ( json : : parse ( " \" \\ uD80C \\ uFFFF \" " ) ,
2017-06-20 18:14:18 +00:00
" [json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: ' \" \\ uD80C \\ uFFFF' " ) ;
2016-08-04 19:55:47 +00:00
}
2017-04-24 15:46:21 +00:00
SECTION ( " parse errors (accept) " )
{
// unexpected end of number
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " 0. " ) = = false ) ;
CHECK ( accept_helper ( " - " ) = = false ) ;
CHECK ( accept_helper ( " -- " ) = = false ) ;
CHECK ( accept_helper ( " -0. " ) = = false ) ;
CHECK ( accept_helper ( " -. " ) = = false ) ;
CHECK ( accept_helper ( " -: " ) = = false ) ;
CHECK ( accept_helper ( " 0.: " ) = = false ) ;
CHECK ( accept_helper ( " e. " ) = = false ) ;
CHECK ( accept_helper ( " 1e. " ) = = false ) ;
CHECK ( accept_helper ( " 1e/ " ) = = false ) ;
CHECK ( accept_helper ( " 1e: " ) = = false ) ;
CHECK ( accept_helper ( " 1E. " ) = = false ) ;
CHECK ( accept_helper ( " 1E/ " ) = = false ) ;
CHECK ( accept_helper ( " 1E: " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// unexpected end of null
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " n " ) = = false ) ;
CHECK ( accept_helper ( " nu " ) = = false ) ;
CHECK ( accept_helper ( " nul " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// unexpected end of true
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " t " ) = = false ) ;
CHECK ( accept_helper ( " tr " ) = = false ) ;
CHECK ( accept_helper ( " tru " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// unexpected end of false
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " f " ) = = false ) ;
CHECK ( accept_helper ( " fa " ) = = false ) ;
CHECK ( accept_helper ( " fal " ) = = false ) ;
CHECK ( accept_helper ( " fals " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// missing/unexpected end of array
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " [ " ) = = false ) ;
CHECK ( accept_helper ( " [1 " ) = = false ) ;
CHECK ( accept_helper ( " [1, " ) = = false ) ;
CHECK ( accept_helper ( " [1,] " ) = = false ) ;
CHECK ( accept_helper ( " ] " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// missing/unexpected end of object
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " { " ) = = false ) ;
CHECK ( accept_helper ( " { \" foo \" " ) = = false ) ;
CHECK ( accept_helper ( " { \" foo \" : " ) = = false ) ;
CHECK ( accept_helper ( " { \" foo \" :} " ) = = false ) ;
CHECK ( accept_helper ( " { \" foo \" :1,} " ) = = false ) ;
CHECK ( accept_helper ( " } " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// missing/unexpected end of string
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u0 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u01 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u012 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u0 " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u01 " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ u012 " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// invalid escapes
for ( int c = 1 ; c < 128 ; + + c )
{
auto s = std : : string ( " \" \\ " ) + std : : string ( 1 , static_cast < char > ( c ) ) + " \" " ;
switch ( c )
{
// valid escapes
case ( ' " ' ) :
case ( ' \\ ' ) :
case ( ' / ' ) :
case ( ' b ' ) :
case ( ' f ' ) :
case ( ' n ' ) :
case ( ' r ' ) :
case ( ' t ' ) :
{
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s . c_str ( ) ) ) ) . accept ( ) ) ;
2017-04-24 15:46:21 +00:00
break ;
}
// \u must be followed with four numbers, so we skip it here
case ( ' u ' ) :
{
break ;
}
// any other combination of backslash and character is invalid
default :
{
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s . c_str ( ) ) ) ) . accept ( ) = = false ) ;
2017-04-24 15:46:21 +00:00
break ;
}
}
}
// invalid \uxxxx escapes
{
// check whether character is a valid hex character
const auto valid = [ ] ( int c )
{
switch ( c )
{
case ( ' 0 ' ) :
case ( ' 1 ' ) :
case ( ' 2 ' ) :
case ( ' 3 ' ) :
case ( ' 4 ' ) :
case ( ' 5 ' ) :
case ( ' 6 ' ) :
case ( ' 7 ' ) :
case ( ' 8 ' ) :
case ( ' 9 ' ) :
case ( ' a ' ) :
case ( ' b ' ) :
case ( ' c ' ) :
case ( ' d ' ) :
case ( ' e ' ) :
case ( ' f ' ) :
case ( ' A ' ) :
case ( ' B ' ) :
case ( ' C ' ) :
case ( ' D ' ) :
case ( ' E ' ) :
case ( ' F ' ) :
{
return true ;
}
default :
{
return false ;
}
}
} ;
for ( int c = 1 ; c < 128 ; + + c )
{
std : : string s = " \" \\ u " ;
// create a string with the iterated character at each position
auto s1 = s + " 000 " + std : : string ( 1 , static_cast < char > ( c ) ) + " \" " ;
auto s2 = s + " 00 " + std : : string ( 1 , static_cast < char > ( c ) ) + " 0 \" " ;
auto s3 = s + " 0 " + std : : string ( 1 , static_cast < char > ( c ) ) + " 00 \" " ;
auto s4 = s + std : : string ( 1 , static_cast < char > ( c ) ) + " 000 \" " ;
if ( valid ( c ) )
{
CAPTURE ( s1 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s1 . c_str ( ) ) ) ) . accept ( ) ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s2 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s2 . c_str ( ) ) ) ) . accept ( ) ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s3 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s3 . c_str ( ) ) ) ) . accept ( ) ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s4 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s4 . c_str ( ) ) ) ) . accept ( ) ) ;
2017-04-24 15:46:21 +00:00
}
else
{
CAPTURE ( s1 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s1 . c_str ( ) ) ) ) . accept ( ) = = false ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s2 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s2 . c_str ( ) ) ) ) . accept ( ) = = false ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s3 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s3 . c_str ( ) ) ) ) . accept ( ) = = false ) ;
2017-04-24 15:46:21 +00:00
CAPTURE ( s4 ) ;
2017-07-23 16:11:34 +00:00
CHECK ( json : : parser ( nlohmann : : detail : : input_adapter ( std : : string ( s4 . c_str ( ) ) ) ) . accept ( ) = = false ) ;
2017-04-24 15:46:21 +00:00
}
}
}
// missing part of a surrogate pair
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ uD80C \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
// invalid surrogate pair
2017-07-22 13:18:38 +00:00
CHECK ( accept_helper ( " \" \\ uD80C \\ uD80C \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ uD80C \\ u0000 \" " ) = = false ) ;
CHECK ( accept_helper ( " \" \\ uD80C \\ uFFFF \" " ) = = false ) ;
2017-04-24 15:46:21 +00:00
}
2017-01-29 16:18:56 +00:00
SECTION ( " tests found by mutate++ " )
{
// test case to make sure no comma preceeds the first key
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " {, \" key \" : false} " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " {, \" key \" : false} " ) ,
2017-03-31 21:24:33 +00:00
" [json.exception.parse_error.101] parse error at 2: syntax error - unexpected ','; expected string literal " ) ;
2017-01-29 16:18:56 +00:00
// test case to make sure an object is properly closed
2017-07-22 13:18:38 +00:00
CHECK_THROWS_AS ( parser_helper ( " [{ \" key \" : false true] " ) , json : : parse_error & ) ;
CHECK_THROWS_WITH ( parser_helper ( " [{ \" key \" : false true] " ) ,
2017-03-24 18:49:02 +00:00
" [json.exception.parse_error.101] parse error at 19: syntax error - unexpected true literal; expected '}' " ) ;
2017-01-29 16:18:56 +00:00
// test case to make sure the callback is properly evaluated after reading a key
{
2017-02-18 10:00:18 +00:00
json : : parser_callback_t cb = [ ] ( int , json : : parse_event_t event , json & )
2017-01-29 16:18:56 +00:00
{
if ( event = = json : : parse_event_t : : key )
{
return false ;
}
else
{
return true ;
}
} ;
json x = json : : parse ( " { \" key \" : false} " , cb ) ;
CHECK ( x = = json : : object ( ) ) ;
}
}
2016-08-04 19:55:47 +00:00
SECTION ( " callback function " )
{
auto s_object = R " (
{
" foo " : 2 ,
" bar " : {
" baz " : 1
}
}
) " ;
auto s_array = R " (
[ 1 , 2 , [ 3 , 4 , 5 ] , 4 , 5 ]
) " ;
SECTION ( " filter nothing " )
{
json j_object = json : : parse ( s_object , [ ] ( int , json : : parse_event_t , const json & )
{
return true ;
} ) ;
CHECK ( j_object = = json ( { { " foo " , 2 } , { " bar " , { { " baz " , 1 } } } } ) ) ;
json j_array = json : : parse ( s_array , [ ] ( int , json : : parse_event_t , const json & )
{
return true ;
} ) ;
CHECK ( j_array = = json ( { 1 , 2 , { 3 , 4 , 5 } , 4 , 5 } ) ) ;
}
SECTION ( " filter everything " )
{
json j_object = json : : parse ( s_object , [ ] ( int , json : : parse_event_t , const json & )
{
return false ;
} ) ;
// the top-level object will be discarded, leaving a null
CHECK ( j_object . is_null ( ) ) ;
json j_array = json : : parse ( s_array , [ ] ( int , json : : parse_event_t , const json & )
{
return false ;
} ) ;
// the top-level array will be discarded, leaving a null
CHECK ( j_array . is_null ( ) ) ;
}
SECTION ( " filter specific element " )
{
json j_object = json : : parse ( s_object , [ ] ( int , json : : parse_event_t , const json & j )
{
// filter all number(2) elements
if ( j = = json ( 2 ) )
{
return false ;
}
else
{
return true ;
}
} ) ;
CHECK ( j_object = = json ( { { " bar " , { { " baz " , 1 } } } } ) ) ;
json j_array = json : : parse ( s_array , [ ] ( int , json : : parse_event_t , const json & j )
{
if ( j = = json ( 2 ) )
{
return false ;
}
else
{
return true ;
}
} ) ;
CHECK ( j_array = = json ( { 1 , { 3 , 4 , 5 } , 4 , 5 } ) ) ;
}
SECTION ( " filter specific events " )
{
SECTION ( " first closing event " )
{
{
json j_object = json : : parse ( s_object , [ ] ( int , json : : parse_event_t e , const json & )
{
static bool first = true ;
if ( e = = json : : parse_event_t : : object_end and first )
{
first = false ;
return false ;
}
else
{
return true ;
}
} ) ;
// the first completed object will be discarded
CHECK ( j_object = = json ( { { " foo " , 2 } } ) ) ;
}
{
json j_array = json : : parse ( s_array , [ ] ( int , json : : parse_event_t e , const json & )
{
static bool first = true ;
if ( e = = json : : parse_event_t : : array_end and first )
{
first = false ;
return false ;
}
else
{
return true ;
}
} ) ;
// the first completed array will be discarded
CHECK ( j_array = = json ( { 1 , 2 , 4 , 5 } ) ) ;
}
}
}
SECTION ( " special cases " )
{
// the following test cases cover the situation in which an empty
// object and array is discarded only after the closing character
// has been read
json j_empty_object = json : : parse ( " {} " , [ ] ( int , json : : parse_event_t e , const json & )
{
if ( e = = json : : parse_event_t : : object_end )
{
return false ;
}
else
{
return true ;
}
} ) ;
CHECK ( j_empty_object = = json ( ) ) ;
json j_empty_array = json : : parse ( " [] " , [ ] ( int , json : : parse_event_t e , const json & )
{
if ( e = = json : : parse_event_t : : array_end )
{
return false ;
}
else
{
return true ;
}
} ) ;
CHECK ( j_empty_array = = json ( ) ) ;
}
}
2016-08-14 15:52:21 +00:00
SECTION ( " constructing from contiguous containers " )
2016-08-04 19:55:47 +00:00
{
2016-08-14 12:18:25 +00:00
SECTION ( " from std::vector " )
{
2016-08-23 20:38:05 +00:00
std : : vector < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from std::array " )
{
2016-08-23 20:38:05 +00:00
std : : array < uint8_t , 5 > v { { ' t ' , ' r ' , ' u ' , ' e ' } } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from array " )
{
2016-08-23 20:38:05 +00:00
uint8_t v [ ] = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from char literal " )
{
2017-07-22 13:18:38 +00:00
CHECK ( parser_helper ( " true " ) = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from std::string " )
{
std : : string v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from std::initializer_list " )
{
2016-08-23 20:38:05 +00:00
std : : initializer_list < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
SECTION ( " from std::valarray " )
{
2016-08-23 20:38:05 +00:00
std : : valarray < uint8_t > v = { ' t ' , ' r ' , ' u ' , ' e ' } ;
2017-07-22 13:18:38 +00:00
json j ;
2017-07-23 16:11:34 +00:00
json : : parser ( nlohmann : : detail : : input_adapter ( std : : begin ( v ) , std : : end ( v ) ) ) . parse ( true , j ) ;
2017-07-22 13:18:38 +00:00
CHECK ( j = = json ( true ) ) ;
2016-08-14 12:18:25 +00:00
}
2016-08-04 19:55:47 +00:00
}
}