2022-07-20 13:38:07 +03:00
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.10.5
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
2016-08-04 22:55:47 +03:00
2019-01-13 19:41:21 +03:00
# include "doctest_compatibility.h"
2016-08-04 22:55:47 +03:00
2018-01-29 13:21:11 +03:00
# include <nlohmann/json.hpp>
2016-08-04 22:55:47 +03:00
using nlohmann : : json ;
TEST_CASE ( " algorithms " )
{
json j_array = { 13 , 29 , 3 , { { " one " , 1 } , { " two " , 2 } } , true , false , { 1 , 2 , 3 } , " foo " , " baz " } ;
json j_object = { { " one " , 1 } , { " two " , 2 } } ;
SECTION ( " non-modifying sequence operations " )
{
SECTION ( " std::all_of " )
{
CHECK ( std : : all_of ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & value )
{
2021-03-24 09:15:18 +03:00
return ! value . empty ( ) ;
2016-08-04 22:55:47 +03:00
} ) ) ;
CHECK ( std : : all_of ( j_object . begin ( ) , j_object . end ( ) , [ ] ( const json & value )
{
return value . type ( ) = = json : : value_t : : number_integer ;
} ) ) ;
}
SECTION ( " std::any_of " )
{
CHECK ( std : : any_of ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & value )
{
2020-06-03 22:22:07 +03:00
return value . is_string ( ) & & value . get < std : : string > ( ) = = " foo " ;
2016-08-04 22:55:47 +03:00
} ) ) ;
CHECK ( std : : any_of ( j_object . begin ( ) , j_object . end ( ) , [ ] ( const json & value )
{
return value . get < int > ( ) > 1 ;
} ) ) ;
}
SECTION ( " std::none_of " )
{
CHECK ( std : : none_of ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & value )
{
2021-03-24 09:15:18 +03:00
return value . empty ( ) ;
2016-08-04 22:55:47 +03:00
} ) ) ;
CHECK ( std : : none_of ( j_object . begin ( ) , j_object . end ( ) , [ ] ( const json & value )
{
return value . get < int > ( ) < = 0 ;
} ) ) ;
}
SECTION ( " std::for_each " )
{
SECTION ( " reading " )
{
int sum = 0 ;
std : : for_each ( j_array . cbegin ( ) , j_array . cend ( ) , [ & sum ] ( const json & value )
{
if ( value . is_number ( ) )
{
sum + = static_cast < int > ( value ) ;
}
} ) ;
CHECK ( sum = = 45 ) ;
}
SECTION ( " writing " )
{
auto add17 = [ ] ( json & value )
{
if ( value . is_array ( ) )
{
value . push_back ( 17 ) ;
}
} ;
std : : for_each ( j_array . begin ( ) , j_array . end ( ) , add17 ) ;
CHECK ( j_array [ 6 ] = = json ( { 1 , 2 , 3 , 17 } ) ) ;
}
}
SECTION ( " std::count " )
{
CHECK ( std : : count ( j_array . begin ( ) , j_array . end ( ) , json ( true ) ) = = 1 ) ;
}
SECTION ( " std::count_if " )
{
CHECK ( std : : count_if ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & value )
{
return ( value . is_number ( ) ) ;
} ) = = 3 ) ;
CHECK ( std : : count_if ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & )
{
return true ;
} ) = = 9 ) ;
}
SECTION ( " std::mismatch " )
{
json j_array2 = { 13 , 29 , 3 , { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } } , true , false , { 1 , 2 , 3 } , " foo " , " baz " } ;
auto res = std : : mismatch ( j_array . begin ( ) , j_array . end ( ) , j_array2 . begin ( ) ) ;
CHECK ( * res . first = = json ( { { " one " , 1 } , { " two " , 2 } } ) ) ;
CHECK ( * res . second = = json ( { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } } ) ) ;
}
SECTION ( " std::equal " )
{
SECTION ( " using operator== " )
{
CHECK ( std : : equal ( j_array . begin ( ) , j_array . end ( ) , j_array . begin ( ) ) ) ;
CHECK ( std : : equal ( j_object . begin ( ) , j_object . end ( ) , j_object . begin ( ) ) ) ;
2020-06-03 22:22:07 +03:00
CHECK ( ! std : : equal ( j_array . begin ( ) , j_array . end ( ) , j_object . begin ( ) ) ) ;
2016-08-04 22:55:47 +03:00
}
SECTION ( " using user-defined comparison " )
{
// compare objects only by size of its elements
json j_array2 = { 13 , 29 , 3 , { " Hello " , " World " } , true , false , { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } } , " foo " , " baz " } ;
2020-06-03 22:22:07 +03:00
CHECK ( ! std : : equal ( j_array . begin ( ) , j_array . end ( ) , j_array2 . begin ( ) ) ) ;
2016-08-04 22:55:47 +03:00
CHECK ( std : : equal ( j_array . begin ( ) , j_array . end ( ) , j_array2 . begin ( ) ,
[ ] ( const json & a , const json & b )
{
return ( a . size ( ) = = b . size ( ) ) ;
} ) ) ;
}
}
SECTION ( " std::find " )
{
auto it = std : : find ( j_array . begin ( ) , j_array . end ( ) , json ( false ) ) ;
CHECK ( std : : distance ( j_array . begin ( ) , it ) = = 5 ) ;
}
SECTION ( " std::find_if " )
{
auto it = std : : find_if ( j_array . begin ( ) , j_array . end ( ) ,
[ ] ( const json & value )
{
return value . is_boolean ( ) ;
} ) ;
CHECK ( std : : distance ( j_array . begin ( ) , it ) = = 4 ) ;
}
SECTION ( " std::find_if_not " )
{
auto it = std : : find_if_not ( j_array . begin ( ) , j_array . end ( ) ,
[ ] ( const json & value )
{
return value . is_number ( ) ;
} ) ;
CHECK ( std : : distance ( j_array . begin ( ) , it ) = = 3 ) ;
}
SECTION ( " std::adjacent_find " )
{
CHECK ( std : : adjacent_find ( j_array . begin ( ) , j_array . end ( ) ) = = j_array . end ( ) ) ;
CHECK ( std : : adjacent_find ( j_array . begin ( ) , j_array . end ( ) ,
[ ] ( const json & v1 , const json & v2 )
{
return v1 . type ( ) = = v2 . type ( ) ;
} ) = = j_array . begin ( ) ) ;
}
}
SECTION ( " modifying sequence operations " )
{
SECTION ( " std::reverse " )
{
std : : reverse ( j_array . begin ( ) , j_array . end ( ) ) ;
CHECK ( j_array = = json ( { " baz " , " foo " , { 1 , 2 , 3 } , false , true , { { " one " , 1 } , { " two " , 2 } } , 3 , 29 , 13 } ) ) ;
}
SECTION ( " std::rotate " )
{
std : : rotate ( j_array . begin ( ) , j_array . begin ( ) + 1 , j_array . end ( ) ) ;
CHECK ( j_array = = json ( { 29 , 3 , { { " one " , 1 } , { " two " , 2 } } , true , false , { 1 , 2 , 3 } , " foo " , " baz " , 13 } ) ) ;
}
SECTION ( " std::partition " )
{
auto it = std : : partition ( j_array . begin ( ) , j_array . end ( ) , [ ] ( const json & v )
{
return v . is_string ( ) ;
} ) ;
CHECK ( std : : distance ( j_array . begin ( ) , it ) = = 2 ) ;
2020-06-03 22:22:07 +03:00
CHECK ( ! it [ 2 ] . is_string ( ) ) ;
2016-08-04 22:55:47 +03:00
}
}
SECTION ( " sorting operations " )
{
SECTION ( " std::sort " )
{
SECTION ( " with standard comparison " )
{
json j = { 13 , 29 , 3 , { { " one " , 1 } , { " two " , 2 } } , true , false , { 1 , 2 , 3 } , " foo " , " baz " , nullptr } ;
std : : sort ( j . begin ( ) , j . end ( ) ) ;
CHECK ( j = = json ( { nullptr , false , true , 3 , 13 , 29 , { { " one " , 1 } , { " two " , 2 } } , { 1 , 2 , 3 } , " baz " , " foo " } ) ) ;
}
SECTION ( " with user-defined comparison " )
{
json j = { 3 , { { " one " , 1 } , { " two " , 2 } } , { 1 , 2 , 3 } , nullptr } ;
std : : sort ( j . begin ( ) , j . end ( ) , [ ] ( const json & a , const json & b )
{
return a . size ( ) < b . size ( ) ;
} ) ;
CHECK ( j = = json ( { nullptr , 3 , { { " one " , 1 } , { " two " , 2 } } , { 1 , 2 , 3 } } ) ) ;
}
SECTION ( " sorting an object " )
{
json j ( { { " one " , 1 } , { " two " , 2 } } ) ;
2022-03-24 17:55:35 +03:00
CHECK_THROWS_WITH_AS ( std : : sort ( j . begin ( ) , j . end ( ) ) , " [json.exception.invalid_iterator.209] cannot use offsets with object iterators " , json : : invalid_iterator & ) ;
2016-08-04 22:55:47 +03:00
}
}
SECTION ( " std::partial_sort " )
{
json j = { 13 , 29 , 3 , { { " one " , 1 } , { " two " , 2 } } , true , false , { 1 , 2 , 3 } , " foo " , " baz " , nullptr } ;
std : : partial_sort ( j . begin ( ) , j . begin ( ) + 4 , j . end ( ) ) ;
CHECK ( j = = json ( { nullptr , false , true , 3 , { { " one " , 1 } , { " two " , 2 } } , 29 , { 1 , 2 , 3 } , " foo " , " baz " , 13 } ) ) ;
}
}
SECTION ( " set operations " )
{
SECTION ( " std::merge " )
{
{
json j1 = { 2 , 4 , 6 , 8 } ;
json j2 = { 1 , 2 , 3 , 5 , 7 } ;
json j3 ;
std : : merge ( j1 . begin ( ) , j1 . end ( ) , j2 . begin ( ) , j2 . end ( ) , std : : back_inserter ( j3 ) ) ;
CHECK ( j3 = = json ( { 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } ) ) ;
}
}
SECTION ( " std::set_difference " )
{
json j1 = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } ;
json j2 = { 1 , 2 , 3 , 5 , 7 } ;
json j3 ;
std : : set_difference ( j1 . begin ( ) , j1 . end ( ) , j2 . begin ( ) , j2 . end ( ) , std : : back_inserter ( j3 ) ) ;
CHECK ( j3 = = json ( { 4 , 6 , 8 } ) ) ;
}
SECTION ( " std::set_intersection " )
{
json j1 = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } ;
json j2 = { 1 , 2 , 3 , 5 , 7 } ;
json j3 ;
std : : set_intersection ( j1 . begin ( ) , j1 . end ( ) , j2 . begin ( ) , j2 . end ( ) , std : : back_inserter ( j3 ) ) ;
CHECK ( j3 = = json ( { 1 , 2 , 3 , 5 , 7 } ) ) ;
}
SECTION ( " std::set_union " )
{
json j1 = { 2 , 4 , 6 , 8 } ;
json j2 = { 1 , 2 , 3 , 5 , 7 } ;
json j3 ;
std : : set_union ( j1 . begin ( ) , j1 . end ( ) , j2 . begin ( ) , j2 . end ( ) , std : : back_inserter ( j3 ) ) ;
CHECK ( j3 = = json ( { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } ) ) ;
}
SECTION ( " std::set_symmetric_difference " )
{
json j1 = { 2 , 4 , 6 , 8 } ;
json j2 = { 1 , 2 , 3 , 5 , 7 } ;
json j3 ;
std : : set_symmetric_difference ( j1 . begin ( ) , j1 . end ( ) , j2 . begin ( ) , j2 . end ( ) , std : : back_inserter ( j3 ) ) ;
CHECK ( j3 = = json ( { 1 , 3 , 4 , 5 , 6 , 7 , 8 } ) ) ;
}
}
SECTION ( " heap operations " )
{
std : : make_heap ( j_array . begin ( ) , j_array . end ( ) ) ;
CHECK ( std : : is_heap ( j_array . begin ( ) , j_array . end ( ) ) ) ;
std : : sort_heap ( j_array . begin ( ) , j_array . end ( ) ) ;
CHECK ( j_array = = json ( { false , true , 3 , 13 , 29 , { { " one " , 1 } , { " two " , 2 } } , { 1 , 2 , 3 } , " baz " , " foo " } ) ) ;
}
}