mirror of
https://github.com/boostorg/json.git
synced 2025-05-12 14:11:40 +00:00
871 lines
22 KiB
C++
871 lines
22 KiB
C++
//
|
|
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Official repository: https://github.com/boostorg/json
|
|
//
|
|
|
|
// Test that header file is self-contained.
|
|
#include <boost/json/serializer.hpp>
|
|
|
|
#include <boost/describe/class.hpp>
|
|
#include <boost/describe/enum.hpp>
|
|
#include <boost/json/detail/stack.hpp>
|
|
#include <boost/json/serialize.hpp>
|
|
#include <boost/json/null_resource.hpp>
|
|
#include <boost/json/parse.hpp>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <limits.h>
|
|
|
|
#include "parse-vectors.hpp"
|
|
#include "test.hpp"
|
|
#include "test_suite.hpp"
|
|
|
|
namespace boost {
|
|
namespace json {
|
|
namespace serializer_test_ns {
|
|
|
|
struct my_struct
|
|
{
|
|
std::string s;
|
|
int n;
|
|
double d;
|
|
};
|
|
BOOST_DESCRIBE_STRUCT(my_struct, (), (s, n, d));
|
|
|
|
enum class my_enum
|
|
{
|
|
option_one,
|
|
option_two,
|
|
option_three,
|
|
option_four,
|
|
};
|
|
BOOST_DESCRIBE_ENUM(my_enum, option_one, option_two, option_three);
|
|
|
|
} // namespace serializer_test_ns
|
|
|
|
BOOST_STATIC_ASSERT( std::is_nothrow_destructible<serializer>::value );
|
|
|
|
class serializer_test
|
|
{
|
|
public:
|
|
//------------------------------------------------------
|
|
|
|
// From the javadoc
|
|
|
|
void print( std::ostream& os, value const& jv)
|
|
{
|
|
serializer sr;
|
|
sr.reset( &jv );
|
|
while( ! sr.done() )
|
|
{
|
|
char buf[ 4000 ];
|
|
os << sr.read( buf );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
|
|
::test_suite::log_type log;
|
|
|
|
void
|
|
grind_one(
|
|
string_view s,
|
|
value const& jv,
|
|
string_view name = {})
|
|
{
|
|
{
|
|
system::error_code ec;
|
|
auto const s1 = serialize(jv);
|
|
auto const jv2 = parse(s1, ec);
|
|
if(! BOOST_TEST(equal(jv, jv2)))
|
|
{
|
|
if(name.empty())
|
|
log <<
|
|
" " << s << "\n"
|
|
" " << s1 <<
|
|
std::endl;
|
|
else
|
|
log << name << ":\n"
|
|
" " << s << "\n"
|
|
" " << s1 <<
|
|
std::endl;
|
|
}
|
|
}
|
|
|
|
// large buffer
|
|
{
|
|
system::error_code ec;
|
|
serializer sr;
|
|
sr.reset(&jv);
|
|
string js;
|
|
js.reserve(4096);
|
|
js.grow(sr.read(
|
|
js.data(), js.capacity()).size());
|
|
|
|
auto const s1 = serialize(jv);
|
|
auto const jv2 = parse(s1, ec);
|
|
BOOST_TEST(equal(jv, jv2));
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void
|
|
grind_one(string_view s, T const& t, string_view name = {})
|
|
{
|
|
{
|
|
auto const s1 = serialize(t);
|
|
if( !BOOST_TEST(s == s1) )
|
|
{
|
|
if(name.empty())
|
|
log <<
|
|
" " << s << "\n"
|
|
" " << s1 <<
|
|
std::endl;
|
|
else
|
|
log << name << ":\n"
|
|
" " << s << "\n"
|
|
" " << s1 <<
|
|
std::endl;
|
|
}
|
|
}
|
|
|
|
// large buffer
|
|
{
|
|
serializer sr;
|
|
sr.reset(&t);
|
|
string js;
|
|
js.reserve(4096);
|
|
js.grow(sr.read(
|
|
js.data(), js.capacity()).size());
|
|
|
|
auto const s1 = serialize(t);
|
|
BOOST_TEST( s == s1 );
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void
|
|
grind(
|
|
string_view s0,
|
|
T const& t,
|
|
string_view name = {})
|
|
{
|
|
grind_one(s0, t, name);
|
|
|
|
auto const s1 = serialize(t);
|
|
for(std::size_t i = 1;
|
|
i < s1.size(); ++i)
|
|
{
|
|
serializer sr;
|
|
sr.reset(&t);
|
|
string s2;
|
|
s2.reserve(s1.size());
|
|
s2.grow(sr.read(
|
|
s2.data(), i).size());
|
|
auto const dump =
|
|
[&]
|
|
{
|
|
if(name.empty())
|
|
log <<
|
|
" " << s0 << "\n"
|
|
" " << s1 << "\n"
|
|
" " << s2 << std::endl;
|
|
else
|
|
log << name << ":\n"
|
|
" " << s0 << "\n"
|
|
" " << s1 << "\n"
|
|
" " << s2 << std::endl;
|
|
};
|
|
if(! BOOST_TEST(
|
|
s2.size() == i))
|
|
{
|
|
dump();
|
|
break;
|
|
}
|
|
s2.grow(sr.read(
|
|
s2.data() + i,
|
|
s1.size() - i).size());
|
|
if(! BOOST_TEST(
|
|
s2.size() == s1.size()))
|
|
{
|
|
dump();
|
|
break;
|
|
}
|
|
if(! BOOST_TEST(s2 == s1))
|
|
{
|
|
dump();
|
|
break;
|
|
}
|
|
}
|
|
{
|
|
string s2;
|
|
s2.reserve( s1.size() );
|
|
serializer sr;
|
|
sr.reset(&t);
|
|
for(std::size_t i = 0; i < s1.size(); ++i)
|
|
{
|
|
BOOST_TEST( sr.read(s2.data() + i, 1).size() == 1 );
|
|
s2.grow(1);
|
|
}
|
|
BOOST_TEST(s2 == s1);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
|
|
void
|
|
testNull()
|
|
{
|
|
check("null");
|
|
}
|
|
|
|
void
|
|
testBoolean()
|
|
{
|
|
check("true");
|
|
check("false");
|
|
}
|
|
|
|
void
|
|
testString()
|
|
{
|
|
check("\"\"");
|
|
check("\"x\"");
|
|
check("\"xyz\"");
|
|
check("\"x z\"");
|
|
|
|
// escapes
|
|
check("\"\\\"\""); // double quote
|
|
check("\"\\\\\""); // backslash
|
|
check("\"\\b\""); // backspace
|
|
check("\"\\f\""); // formfeed
|
|
check("\"\\n\""); // newline
|
|
check("\"\\r\""); // carriage return
|
|
check("\"\\t\""); // horizontal tab
|
|
|
|
// control characters
|
|
check("\"\\u0000\"");
|
|
check("\"\\u0001\"");
|
|
check("\"\\u0002\"");
|
|
check("\"\\u0003\"");
|
|
check("\"\\u0004\"");
|
|
check("\"\\u0005\"");
|
|
check("\"\\u0006\"");
|
|
check("\"\\u0007\"");
|
|
check("\"\\u0008\"");
|
|
check("\"\\u0009\"");
|
|
check("\"\\u000a\"");
|
|
check("\"\\u000b\"");
|
|
check("\"\\u000c\"");
|
|
check("\"\\u000d\"");
|
|
check("\"\\u000e\"");
|
|
check("\"\\u000f\"");
|
|
check("\"\\u0010\"");
|
|
check("\"\\u0011\"");
|
|
check("\"\\u0012\"");
|
|
check("\"\\u0013\"");
|
|
check("\"\\u0014\"");
|
|
check("\"\\u0015\"");
|
|
check("\"\\u0016\"");
|
|
check("\"\\u0017\"");
|
|
check("\"\\u0018\"");
|
|
check("\"\\u0019\"");
|
|
check("\"\\u0020\"");
|
|
check("\"\\u0021\"");
|
|
}
|
|
|
|
void
|
|
testNumber()
|
|
{
|
|
// VFALCO These don't perfectly round-trip,
|
|
// because the representations are not exact.
|
|
// The test needs to do a better job of comparison.
|
|
|
|
check("-999999999999999999999");
|
|
check("-100000000000000000009");
|
|
check("-10000000000000000000");
|
|
//check("-9223372036854775809");
|
|
check("-9223372036854775808");
|
|
check("-9223372036854775807");
|
|
check("-999999999999999999");
|
|
check("-99999999999999999");
|
|
check("-9999999999999999");
|
|
check("-999999999999999");
|
|
check("-99999999999999");
|
|
check("-9999999999999");
|
|
check("-999999999999");
|
|
check("-99999999999");
|
|
check("-9999999999");
|
|
check("-999999999");
|
|
check("-99999999");
|
|
check("-9999999");
|
|
check("-999999");
|
|
check("-99999");
|
|
check("-9999");
|
|
check("-999");
|
|
check("-99");
|
|
check("-9");
|
|
check("-0");
|
|
check("-0.0");
|
|
check( "0");
|
|
check( "9");
|
|
check( "99");
|
|
check( "999");
|
|
check( "9999");
|
|
check( "99999");
|
|
check( "999999");
|
|
check( "9999999");
|
|
check( "99999999");
|
|
check( "999999999");
|
|
check( "9999999999");
|
|
check( "99999999999");
|
|
check( "999999999999");
|
|
check( "9999999999999");
|
|
check( "99999999999999");
|
|
check( "999999999999999");
|
|
check( "9999999999999999");
|
|
check( "99999999999999999");
|
|
check( "999999999999999999");
|
|
check( "9223372036854775807");
|
|
check( "9223372036854775808");
|
|
check( "9999999999999999999");
|
|
check( "18446744073709551615");
|
|
//check( "18446744073709551616");
|
|
check( "99999999999999999999");
|
|
check( "999999999999999999999");
|
|
check( "1000000000000000000000");
|
|
check( "9999999999999999999999");
|
|
check( "99999999999999999999999");
|
|
|
|
//check("-0.9999999999999999999999");
|
|
check("-0.9999999999999999");
|
|
//check("-0.9007199254740991");
|
|
//check("-0.999999999999999");
|
|
//check("-0.99999999999999");
|
|
//check("-0.9999999999999");
|
|
//check("-0.999999999999");
|
|
//check("-0.99999999999");
|
|
//check("-0.9999999999");
|
|
//check("-0.999999999");
|
|
//check("-0.99999999");
|
|
//check("-0.9999999");
|
|
//check("-0.999999");
|
|
//check("-0.99999");
|
|
//check("-0.9999");
|
|
//check("-0.8125");
|
|
//check("-0.999");
|
|
//check("-0.99");
|
|
check("-1.0");
|
|
check("-0.9");
|
|
check("-0.0");
|
|
check( "0.0");
|
|
check( "0.9");
|
|
//check( "0.99");
|
|
//check( "0.999");
|
|
//check( "0.8125");
|
|
//check( "0.9999");
|
|
//check( "0.99999");
|
|
//check( "0.999999");
|
|
//check( "0.9999999");
|
|
//check( "0.99999999");
|
|
//check( "0.999999999");
|
|
//check( "0.9999999999");
|
|
//check( "0.99999999999");
|
|
//check( "0.999999999999");
|
|
//check( "0.9999999999999");
|
|
//check( "0.99999999999999");
|
|
//check( "0.999999999999999");
|
|
//check( "0.9007199254740991");
|
|
check( "0.9999999999999999");
|
|
//check( "0.9999999999999999999999");
|
|
//check( "0.999999999999999999999999999");
|
|
|
|
check("-1e308");
|
|
check("-1e-308");
|
|
//check("-9999e300");
|
|
//check("-999e100");
|
|
//check("-99e10");
|
|
check("-9e1");
|
|
check( "9e1");
|
|
//check( "99e10");
|
|
//check( "999e100");
|
|
//check( "9999e300");
|
|
check( "999999999999999999.0");
|
|
check( "999999999999999999999.0");
|
|
check( "999999999999999999999e5");
|
|
check( "999999999999999999999.0e5");
|
|
|
|
check("-1e-1");
|
|
check("-1e0");
|
|
check("-1e1");
|
|
check( "0e0");
|
|
check( "1e0");
|
|
check( "1e10");
|
|
}
|
|
|
|
void
|
|
testArray()
|
|
{
|
|
check("[]");
|
|
check("[[]]");
|
|
check("[[],[],[]]");
|
|
check("[[[[[[[[[[]]]]]]]]]]");
|
|
check("[{}]");
|
|
check("[{},{}]");
|
|
check("[1,2,3,4,5]");
|
|
check("[true,false,null]");
|
|
}
|
|
|
|
void
|
|
testObject()
|
|
{
|
|
check("{}");
|
|
check("{\"x\":1}");
|
|
check("{\"x\":[]}");
|
|
check("{\"x\":1,\"y\":null}");
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
|
|
void
|
|
testMembers()
|
|
{
|
|
// serializer()
|
|
{
|
|
serializer sr;
|
|
|
|
char buf[32];
|
|
BOOST_TEST(sr.read(buf) == "null");
|
|
}
|
|
|
|
// serializer(storage_ptr)
|
|
{
|
|
{
|
|
serializer sr((storage_ptr()));
|
|
char buf[32];
|
|
BOOST_TEST(sr.read(buf) == "null");
|
|
}
|
|
{
|
|
serializer sr(get_null_resource());
|
|
char buf[1];
|
|
BOOST_TEST_THROWS(
|
|
sr.read(buf),
|
|
std::bad_alloc);
|
|
}
|
|
}
|
|
|
|
// serializer(storage_ptr, unsigned char*, size_t)
|
|
{
|
|
{
|
|
unsigned char temp[256];
|
|
serializer sr(
|
|
get_null_resource(),
|
|
temp,
|
|
sizeof(temp));
|
|
char buf[32];
|
|
BOOST_TEST(sr.read(&buf[0], 1) == "n");
|
|
BOOST_TEST(sr.read(&buf[1], 2) == "ul");
|
|
BOOST_TEST(sr.read(&buf[3], 1) == "l");
|
|
BOOST_TEST(
|
|
std::memcmp(buf, "null", 4) == 0);
|
|
}
|
|
{
|
|
unsigned char temp[1];
|
|
serializer sr(
|
|
get_null_resource(),
|
|
temp,
|
|
sizeof(temp));
|
|
array ar({1, 2, 3});
|
|
sr.reset(&ar);
|
|
char buf[32];
|
|
BOOST_TEST_THROWS(
|
|
sr.read(&buf[0], 1),
|
|
std::bad_alloc);
|
|
}
|
|
}
|
|
|
|
// done()
|
|
{
|
|
value jv = 1;
|
|
serializer sr;
|
|
sr.reset(&jv);
|
|
BOOST_TEST(! sr.done());
|
|
char buf[32];
|
|
BOOST_TEST(sr.read(buf) == "1");
|
|
BOOST_TEST(sr.done());
|
|
}
|
|
|
|
// read()
|
|
{
|
|
value jv = 1;
|
|
serializer sr;
|
|
sr.reset(&jv);
|
|
char buf[1024];
|
|
auto const s = sr.read(buf);
|
|
BOOST_TEST(sr.done());
|
|
BOOST_TEST(s == "1");
|
|
}
|
|
|
|
// checked read()
|
|
{
|
|
serializer sr;
|
|
char buf[100];
|
|
BOOST_TEST(sr.read(buf, 50) == "null");
|
|
}
|
|
|
|
// reset(value)
|
|
{
|
|
char buf[100];
|
|
serializer sr;
|
|
value jv = { 1, 2, 3 };
|
|
sr.reset(&jv);
|
|
BOOST_TEST(sr.read(buf) == "[1,2,3]");
|
|
}
|
|
|
|
// reset(array)
|
|
{
|
|
char buf[100];
|
|
serializer sr;
|
|
array arr = { 1, 2, 3 };
|
|
sr.reset(&arr);
|
|
BOOST_TEST(sr.read(buf) == "[1,2,3]");
|
|
}
|
|
|
|
// reset(object)
|
|
{
|
|
char buf[100];
|
|
serializer sr;
|
|
object obj = { {"k1",1}, {"k2",2} };
|
|
sr.reset(&obj);
|
|
BOOST_TEST(sr.read(buf) == "{\"k1\":1,\"k2\":2}");
|
|
}
|
|
|
|
// reset(string)
|
|
{
|
|
char buf[100];
|
|
serializer sr;
|
|
string str = "123";
|
|
sr.reset(&str);
|
|
BOOST_TEST(sr.read(buf) == "\"123\"");
|
|
}
|
|
}
|
|
|
|
void
|
|
check(
|
|
string_view s,
|
|
string_view name = {})
|
|
{
|
|
try
|
|
{
|
|
auto const jv = parse(s);
|
|
grind(s, jv, name);
|
|
}
|
|
catch(std::exception const&)
|
|
{
|
|
BOOST_TEST_FAIL();
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void
|
|
check_udt(
|
|
T const& t,
|
|
string_view s,
|
|
string_view name = {})
|
|
{
|
|
try
|
|
{
|
|
grind(s, t, name);
|
|
}
|
|
catch(std::exception const&)
|
|
{
|
|
BOOST_TEST_FAIL();
|
|
}
|
|
}
|
|
|
|
void
|
|
testVectors()
|
|
{
|
|
#if 0
|
|
check(
|
|
R"xx({
|
|
"glossary": {
|
|
"title": "example glossary",
|
|
"GlossDiv": {
|
|
"title": "S",
|
|
"GlossList": {
|
|
"GlossEntry": {
|
|
"ID": "SGML",
|
|
"SortAs": "SGML",
|
|
"GlossTerm": "Standard Generalized Markup Language",
|
|
"Acronym": "SGML",
|
|
"Abbrev": "ISO 8879:1986",
|
|
"GlossDef": {
|
|
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
|
"GlossSeeAlso": ["GML", "XML"]
|
|
},
|
|
"GlossSee": "markup"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})xx");
|
|
#endif
|
|
|
|
parse_vectors const pv;
|
|
for(auto const e : pv)
|
|
{
|
|
if(e.result != 'y')
|
|
continue;
|
|
// skip these failures for now
|
|
if(
|
|
e.name == "number" ||
|
|
e.name == "number_real_exponent" ||
|
|
e.name == "number_real_fraction_exponent" ||
|
|
e.name == "number_simple_real" ||
|
|
e.name == "object_extreme_numbers" ||
|
|
e.name == "pass01"
|
|
)
|
|
continue;
|
|
check(e.text, e.name);
|
|
}
|
|
}
|
|
|
|
std::string
|
|
to_ostream(value const& jv)
|
|
{
|
|
std::stringstream ss;
|
|
ss << jv;
|
|
return ss.str();
|
|
}
|
|
|
|
void
|
|
testOstream()
|
|
{
|
|
for(string_view js : {
|
|
"{\"1\":{},\"2\":[],\"3\":\"x\",\"4\":1,"
|
|
"\"5\":-1,\"6\":144.0,\"7\":false,\"8\":null}",
|
|
"[1,2,3,4,5]"
|
|
})
|
|
{
|
|
system::error_code ec;
|
|
auto const jv1 = parse(js, ec);
|
|
if(! BOOST_TEST(! ec))
|
|
return;
|
|
auto const jv2 =
|
|
parse(to_ostream(jv1), ec);
|
|
if(! BOOST_TEST(! ec))
|
|
return;
|
|
if(! BOOST_TEST(equal(jv1, jv2)))
|
|
log <<
|
|
" " << js << "\n"
|
|
" " << jv1 << "\n"
|
|
" " << jv2 <<
|
|
std::endl;
|
|
}
|
|
}
|
|
|
|
void
|
|
testNumberRoundTrips()
|
|
{
|
|
// no decimal or exponent parsed as integer
|
|
BOOST_TEST(parse("-0").as_int64() == 0);
|
|
BOOST_TEST(serialize(parse("-0")) == "0");
|
|
BOOST_TEST(parse("-0.0").as_double() == -0);
|
|
BOOST_TEST(serialize(parse("0.0")) == "0E0");
|
|
BOOST_TEST(parse("0.0").as_double() == 0);
|
|
BOOST_TEST(serialize(parse("-0.0")) == "-0E0");
|
|
}
|
|
|
|
void
|
|
testStack()
|
|
{
|
|
char const* sample = "sample string";
|
|
|
|
detail::stack st;
|
|
BOOST_TEST( st.empty() );
|
|
|
|
st.clear();
|
|
BOOST_TEST( st.empty() );
|
|
|
|
st.push(1);
|
|
BOOST_TEST( !st.empty() );
|
|
|
|
st.push(sample);
|
|
st.push(3.4);
|
|
|
|
std::vector<int> v{1, 2, 3, 4, 5};
|
|
st.push(v);
|
|
|
|
v.pop_back();
|
|
st.push(v);
|
|
|
|
v.pop_back();
|
|
st.push(v);
|
|
|
|
{
|
|
std::vector<int> v1;
|
|
st.pop( v1 );
|
|
|
|
BOOST_TEST( v == v1 );
|
|
}
|
|
v.push_back(4);
|
|
{
|
|
std::vector<int> v1;
|
|
st.pop( v1 );
|
|
|
|
BOOST_TEST( v == v1 );
|
|
}
|
|
v.push_back(5);
|
|
{
|
|
std::vector<int> v1;
|
|
st.pop( v1 );
|
|
|
|
BOOST_TEST( v == v1 );
|
|
}
|
|
{
|
|
double d1;
|
|
st.peek( d1 );
|
|
BOOST_TEST( d1 == 3.4 );
|
|
|
|
double d2;
|
|
st.pop( d2 );
|
|
BOOST_TEST( d2 == d1 );
|
|
BOOST_TEST( !st.empty() );
|
|
}
|
|
{
|
|
char const* s1;
|
|
st.peek( s1 );
|
|
BOOST_TEST( s1 == sample );
|
|
|
|
char const* s2;
|
|
st.pop( s2 );
|
|
BOOST_TEST( s2 == s1 );
|
|
BOOST_TEST( !st.empty() );
|
|
}
|
|
{
|
|
int n1;
|
|
st.peek( n1 );
|
|
BOOST_TEST( n1 == 1 );
|
|
|
|
int n2;
|
|
st.pop( n2 );
|
|
BOOST_TEST( n2 == n1 );
|
|
BOOST_TEST( st.empty() );
|
|
}
|
|
BOOST_TEST( st.empty() );
|
|
|
|
st.push(1);
|
|
st.push(v);
|
|
st.clear();
|
|
BOOST_TEST( st.empty() );
|
|
}
|
|
|
|
void
|
|
testUDT()
|
|
{
|
|
{
|
|
check_udt(nullptr, "null");
|
|
|
|
auto np = nullptr;
|
|
check_udt(np, "null");
|
|
}
|
|
{
|
|
bool b = true;
|
|
check_udt(b, "true");
|
|
|
|
b = false;
|
|
check_udt(b, "false");
|
|
}
|
|
{
|
|
std::uint64_t u = 1;
|
|
check_udt(u, "1");
|
|
|
|
u = (std::numeric_limits<std::int64_t>::max)();
|
|
u += 1;
|
|
check_udt(u, "9223372036854775808");
|
|
|
|
std::int64_t i = -1;
|
|
check_udt(i, "-1");
|
|
|
|
double d = 3.12;
|
|
check_udt(d, "3.12E0");
|
|
|
|
#if defined(BOOST_HAS_INT128) && defined(__GLIBCXX_TYPE_INT_N_0)
|
|
boost::int128_type ii =
|
|
(std::numeric_limits<std::uint64_t>::max)();
|
|
ii += 1;
|
|
d = ii;
|
|
check_udt( ii, serialize(value(d)) );
|
|
|
|
ii = (std::numeric_limits<std::int64_t>::min)();
|
|
ii -= 1;
|
|
d = ii;
|
|
check_udt( ii, serialize(value(d)) );
|
|
#endif
|
|
}
|
|
{
|
|
std::string s = "fairly long string which avoids SBO";
|
|
check_udt(s, "\"fairly long string which avoids SBO\"");
|
|
}
|
|
{
|
|
std::vector<int> v = {1,2,3,4,5};
|
|
check_udt(v, "[1,2,3,4,5]");
|
|
}
|
|
{
|
|
std::map<std::string, int> v = {
|
|
{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}};
|
|
check_udt(v, R"({"a":1,"b":2,"c":3,"d":4,"e":5})");
|
|
}
|
|
{
|
|
check_udt(
|
|
std::tuple<std::string, int, bool>("a string", 12, true),
|
|
R"(["a string",12,true])");
|
|
check_udt(
|
|
std::tuple<std::string, std::pair<int, bool>>(
|
|
"a string", {12, true}),
|
|
R"(["a string",[12,true]])");
|
|
}
|
|
#ifdef BOOST_DESCRIBE_CXX14
|
|
{
|
|
serializer_test_ns::my_struct s{"some string", 1424, 12.4};
|
|
check_udt(s, R"({"s":"some string","n":1424,"d":1.24E1})");
|
|
}
|
|
{
|
|
check_udt(
|
|
serializer_test_ns::my_enum::option_three,
|
|
R"("option_three")");
|
|
check_udt( serializer_test_ns::my_enum(100), "100" );
|
|
}
|
|
#endif // BOOST_DESCRIBE_CXX14
|
|
}
|
|
|
|
void
|
|
run()
|
|
{
|
|
testNull();
|
|
testBoolean();
|
|
testString();
|
|
testNumber();
|
|
testArray();
|
|
testObject();
|
|
|
|
testMembers();
|
|
testVectors();
|
|
testOstream();
|
|
testNumberRoundTrips();
|
|
testStack();
|
|
testUDT();
|
|
}
|
|
};
|
|
|
|
TEST_SUITE(serializer_test, "boost.json.serializer");
|
|
|
|
} // namespace json
|
|
} // namespace boost
|