Unverified Commit 43b82852 by Niels Lohmann

🔀 merge branch 'feature/exceptions_3.0.0' into develop

parents 8feaf8dc 855cdcf0
...@@ -49,6 +49,7 @@ doctest: ...@@ -49,6 +49,7 @@ doctest:
# -Wno-documentation-unknown-command: code uses user-defined commands like @complexity # -Wno-documentation-unknown-command: code uses user-defined commands like @complexity
# -Wno-exit-time-destructors: warning in Catch code # -Wno-exit-time-destructors: warning in Catch code
# -Wno-keyword-macro: unit-tests use "#define private public" # -Wno-keyword-macro: unit-tests use "#define private public"
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
# -Wno-range-loop-analysis: iterator_wrapper tests tests "for(const auto i...)" # -Wno-range-loop-analysis: iterator_wrapper tests tests "for(const auto i...)"
pedantic: pedantic:
$(MAKE) json_unit CXXFLAGS="\ $(MAKE) json_unit CXXFLAGS="\
...@@ -58,6 +59,7 @@ pedantic: ...@@ -58,6 +59,7 @@ pedantic:
-Wno-documentation-unknown-command \ -Wno-documentation-unknown-command \
-Wno-exit-time-destructors \ -Wno-exit-time-destructors \
-Wno-keyword-macro \ -Wno-keyword-macro \
-Wno-weak-vtables \
-Wno-range-loop-analysis" -Wno-range-loop-analysis"
......
...@@ -58,6 +58,9 @@ doxygen: create_output create_links ...@@ -58,6 +58,9 @@ doxygen: create_output create_links
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType&#160;JSONSerializer&#160;&gt;@@g' html/*.html $(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType&#160;JSONSerializer&#160;&gt;@@g' html/*.html
$(SED) -i 's@template&lt;template&lt; typename U, typename V, typename... Args &gt; class ObjectType = std::map, template&lt; typename U, typename... Args &gt; class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, template&lt; typename U &gt; class AllocatorType = std::allocator, template&lt; typename T, typename SFINAE=void &gt; class JSONSerializer = adl_serializer&gt;@@g' html/*.html
$(SED) -i 's@&lt; ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer &gt;@@g' html/*.html
$(SED) -i 's@&lt;&#160;ObjectType,&#160;ArrayType,&#160;StringType,&#160;BooleanType,&#160;NumberIntegerType,&#160;NumberUnsignedType,&#160;NumberFloatType,&#160;AllocatorType,&#160;JSONSerializer&#160;&gt;@@g' html/*.html
upload: clean doxygen check_output upload: clean doxygen check_output
cd html ; ../scripts/git-update-ghpages nlohmann/json cd html ; ../scripts/git-update-ghpages nlohmann/json
......
...@@ -21,13 +21,27 @@ int main() ...@@ -21,13 +21,27 @@ int main()
// output changed array // output changed array
std::cout << object << '\n'; std::cout << object << '\n';
// try to write at a nonexisting key
// exception type_error.304
try try
{ {
// use at() on a non-object type
json str = "I am a string";
str.at("the good") = "Another string";
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to write at a nonexisting key
object.at("the fast") = "il rapido"; object.at("the fast") = "il rapido";
} }
catch (std::out_of_range& e) catch (json::out_of_range& e)
{ {
std::cout << "out of range: " << e.what() << '\n'; std::cout << e.what() << '\n';
} }
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/tb5CaFfsMWpAvi7m"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/8ldtT0NOhidn0fOA"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
"il brutto" "il brutto"
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"} {"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
out of range: key 'the fast' not found [json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.403] key 'the fast' not found
"il brutto"
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
[json.exception.out_of_range.403] key 'the fast' not found
...@@ -15,12 +15,26 @@ int main() ...@@ -15,12 +15,26 @@ int main()
// output element with key "the ugly" // output element with key "the ugly"
std::cout << object.at("the ugly") << '\n'; std::cout << object.at("the ugly") << '\n';
// try to read from a nonexisting key
// exception type_error.304
try try
{ {
// use at() on a non-object type
const json str = "I am a string";
std::cout << str.at("the good") << '\n';
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to read from a nonexisting key
std::cout << object.at("the fast") << '\n'; std::cout << object.at("the fast") << '\n';
} }
catch (std::out_of_range) catch (json::out_of_range)
{ {
std::cout << "out of range" << '\n'; std::cout << "out of range" << '\n';
} }
......
<a target="_blank" href="http://melpon.org/wandbox/permlink/NFG86H5khRUePc1s"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/nfmFWMaJJHFJ7eVK"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
"il brutto" "il brutto"
[json.exception.type_error.304] cannot use at() with string
out of range out of range
...@@ -16,13 +16,27 @@ int main() ...@@ -16,13 +16,27 @@ int main()
// output changed array // output changed array
std::cout << array << '\n'; std::cout << array << '\n';
// try to write beyond the array limit
// exception type_error.304
try try
{ {
// use at() on a non-array type
json str = "I am a string";
str.at(0) = "Another string";
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to write beyond the array limit
array.at(5) = "sixth"; array.at(5) = "sixth";
} }
catch (std::out_of_range& e) catch (json::out_of_range& e)
{ {
std::cout << "out of range: " << e.what() << '\n'; std::cout << e.what() << '\n';
} }
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/R7z2SB2rMdFQ9XtR"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/8UnQY256zGX2Lx6d"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
"third" "third"
["first","second","third","fourth"] ["first","second","third","fourth"]
out of range: array index 5 is out of range [json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.401] array index 5 is out of range
...@@ -5,18 +5,32 @@ using json = nlohmann::json; ...@@ -5,18 +5,32 @@ using json = nlohmann::json;
int main() int main()
{ {
// create JSON array // create JSON array
json array = {"first", "2nd", "third", "fourth"}; const json array = {"first", "2nd", "third", "fourth"};
// output element at index 2 (third element) // output element at index 2 (third element)
std::cout << array.at(2) << '\n'; std::cout << array.at(2) << '\n';
// try to read beyond the array limit
// exception type_error.304
try try
{ {
// use at() on a non-array type
const json str = "I am a string";
std::cout << str.at(0) << '\n';
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
// exception out_of_range.401
try
{
// try to read beyond the array limit
std::cout << array.at(5) << '\n'; std::cout << array.at(5) << '\n';
} }
catch (std::out_of_range) catch (json::out_of_range& e)
{ {
std::cout << "out of range" << '\n'; std::cout << e.what() << '\n';
} }
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/L1bMeiN6nYm7JrvA"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/U1fv6LY7xZOAuSBs"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
"third" "third"
out of range [json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.401] array index 5 is out of range
...@@ -32,4 +32,60 @@ int main() ...@@ -32,4 +32,60 @@ int main()
j.at("/array/1"_json_pointer) = 21; j.at("/array/1"_json_pointer) = 21;
// output the changed array // output the changed array
std::cout << j["array"] << '\n'; std::cout << j["array"] << '\n';
// out_of_range.106
try
{
// try to use an array index with leading '0'
json::reference ref = j.at("/array/01"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.109
try
{
// try to use an array index that is not a number
json::reference ref = j.at("/array/one"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.401
try
{
// try to use a an invalid array index
json::reference ref = j.at("/array/4"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.402
try
{
// try to use the array index '-'
json::reference ref = j.at("/array/-"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.404
try
{
// try to use a JSON pointer that cannot be resolved
json::reference ref = j.at("/number/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/NDSjglHZIjIZ0Uxg"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/Fy2xBfZMols2DUQC"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -4,3 +4,8 @@ ...@@ -4,3 +4,8 @@
2 2
"bar" "bar"
[1,21] [1,21]
[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'
[json.exception.parse_error.109] parse error: array index 'one' is not a number
[json.exception.out_of_range.401] array index 4 is out of range
[json.exception.out_of_range.402] array index '-' (2) is out of range
[json.exception.out_of_range.404] unresolved reference token 'foo'
...@@ -5,7 +5,7 @@ using json = nlohmann::json; ...@@ -5,7 +5,7 @@ using json = nlohmann::json;
int main() int main()
{ {
// create a JSON value // create a JSON value
json j = const json j =
{ {
{"number", 1}, {"string", "foo"}, {"array", {1, 2}} {"number", 1}, {"string", "foo"}, {"array", {1, 2}}
}; };
...@@ -20,4 +20,48 @@ int main() ...@@ -20,4 +20,48 @@ int main()
std::cout << j.at("/array"_json_pointer) << '\n'; std::cout << j.at("/array"_json_pointer) << '\n';
// output element with JSON pointer "/array/1" // output element with JSON pointer "/array/1"
std::cout << j.at("/array/1"_json_pointer) << '\n'; std::cout << j.at("/array/1"_json_pointer) << '\n';
// out_of_range.109
try
{
// try to use an array index that is not a number
json::const_reference ref = j.at("/array/one"_json_pointer);
}
catch (json::parse_error& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.401
try
{
// try to use a an invalid array index
json::const_reference ref = j.at("/array/4"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.402
try
{
// try to use the array index '-'
json::const_reference ref = j.at("/array/-"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
// out_of_range.404
try
{
// try to use a JSON pointer that cannot be resolved
json::const_reference ref = j.at("/number/foo"_json_pointer);
}
catch (json::out_of_range& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/OuLYiMJ3pgyOHupb"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/WxhV3mL9YX8FJonk"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -2,3 +2,7 @@ ...@@ -2,3 +2,7 @@
"foo" "foo"
[1,2] [1,2]
2 2
[json.exception.parse_error.109] parse error: array index 'one' is not a number
[json.exception.out_of_range.401] array index 4 is out of range
[json.exception.out_of_range.402] array index '-' (2) is out of range
[json.exception.out_of_range.404] unresolved reference token 'foo'
...@@ -5,7 +5,6 @@ using json = nlohmann::json; ...@@ -5,7 +5,6 @@ using json = nlohmann::json;
int main() int main()
{ {
// create JSON values // create JSON values
json j_null;
json j_boolean = true; json j_boolean = true;
json j_number_integer = 17; json j_number_integer = 17;
json j_number_float = 23.42; json j_number_float = 23.42;
...@@ -16,7 +15,6 @@ int main() ...@@ -16,7 +15,6 @@ int main()
json j_string = "Hello, world"; json j_string = "Hello, world";
// call back() // call back()
//std::cout << j_null.back() << '\n'; // would throw
std::cout << j_boolean.back() << '\n'; std::cout << j_boolean.back() << '\n';
std::cout << j_number_integer.back() << '\n'; std::cout << j_number_integer.back() << '\n';
std::cout << j_number_float.back() << '\n'; std::cout << j_number_float.back() << '\n';
...@@ -25,4 +23,15 @@ int main() ...@@ -25,4 +23,15 @@ int main()
std::cout << j_array.back() << '\n'; std::cout << j_array.back() << '\n';
//std::cout << j_array_empty.back() << '\n'; // undefined behavior //std::cout << j_array_empty.back() << '\n'; // undefined behavior
std::cout << j_string.back() << '\n'; std::cout << j_string.back() << '\n';
// back() called on a null value
try
{
json j_null;
j_null.back();
}
catch (json::invalid_iterator& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/nPVnBcHf8nrNpGOJ"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/CAv4NNr4D1FJhhUv"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -4,3 +4,4 @@ true ...@@ -4,3 +4,4 @@ true
2 2
16 16
"Hello, world" "Hello, world"
[json.exception.invalid_iterator.214] cannot get value
...@@ -18,4 +18,14 @@ int main() ...@@ -18,4 +18,14 @@ int main()
std::cout << j_array_range << '\n'; std::cout << j_array_range << '\n';
std::cout << j_number_range << '\n'; std::cout << j_number_range << '\n';
std::cout << j_object_range << '\n'; std::cout << j_object_range << '\n';
// example for an exception
try
{
json j_invalid(j_number.begin() + 1, j_number.end());
}
catch (json::invalid_iterator& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/nKF1QcieoCHm6Lez"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/oUU2X0pbZq7gawRB"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
["bravo","charly"] ["bravo","charly"]
42 42
{"one":"eins"} {"one":"eins"}
[json.exception.invalid_iterator.204] iterators out of range
...@@ -19,7 +19,7 @@ int main() ...@@ -19,7 +19,7 @@ int main()
{ {
auto r3 = value.get_ref<json::number_float_t&>(); auto r3 = value.get_ref<json::number_float_t&>();
} }
catch (std::domain_error& ex) catch (json::type_error& ex)
{ {
std::cout << ex.what() << '\n'; std::cout << ex.what() << '\n';
} }
......
<a target="_blank" href="http://melpon.org/wandbox/permlink/WiO1oBWDvIs82OX1"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/lsl8Ex3d3SOYnKHu"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
17 17 17 17
incompatible ReferenceType for get_ref, actual type is number [json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number
17 17
[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number
...@@ -19,9 +19,9 @@ int main() ...@@ -19,9 +19,9 @@ int main()
{ {
json::json_pointer p9("foo"); json::json_pointer p9("foo");
} }
catch (std::domain_error& e) catch (json::parse_error& e)
{ {
std::cout << "domain_error: " << e.what() << '\n'; std::cout << e.what() << '\n';
} }
// error: JSON pointer uses escape symbol ~ not followed by 0 or 1 // error: JSON pointer uses escape symbol ~ not followed by 0 or 1
...@@ -29,9 +29,9 @@ int main() ...@@ -29,9 +29,9 @@ int main()
{ {
json::json_pointer p10("/foo/~"); json::json_pointer p10("/foo/~");
} }
catch (std::domain_error& e) catch (json::parse_error& e)
{ {
std::cout << "domain_error: " << e.what() << '\n'; std::cout << e.what() << '\n';
} }
// error: JSON pointer uses escape symbol ~ not followed by 0 or 1 // error: JSON pointer uses escape symbol ~ not followed by 0 or 1
...@@ -39,8 +39,8 @@ int main() ...@@ -39,8 +39,8 @@ int main()
{ {
json::json_pointer p11("/foo/~3"); json::json_pointer p11("/foo/~3");
} }
catch (std::domain_error& e) catch (json::parse_error& e)
{ {
std::cout << "domain_error: " << e.what() << '\n'; std::cout << e.what() << '\n';
} }
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/WM2WWKnXdmdw17Wu"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/Wlvqfd3JpEXTv2iH"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
domain_error: JSON pointer must be empty or begin with '/' [json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'
domain_error: escape error: '~' must be followed with '0' or '1' [json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'
domain_error: escape error: '~' must be followed with '0' or '1' [json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'
[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'
[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'
[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'
...@@ -8,10 +8,20 @@ int main() ...@@ -8,10 +8,20 @@ int main()
json j_no_init_list = json::object(); json j_no_init_list = json::object();
json j_empty_init_list = json::object({}); json j_empty_init_list = json::object({});
json j_list_of_pairs = json::object({ {"one", 1}, {"two", 2} }); json j_list_of_pairs = json::object({ {"one", 1}, {"two", 2} });
//json j_invalid_list = json::object({ "one", 1 }); // would throw
// serialize the JSON objects // serialize the JSON objects
std::cout << j_no_init_list << '\n'; std::cout << j_no_init_list << '\n';
std::cout << j_empty_init_list << '\n'; std::cout << j_empty_init_list << '\n';
std::cout << j_list_of_pairs << '\n'; std::cout << j_list_of_pairs << '\n';
// example for an exception
try
{
// can only create an object from a list of pairs
json j_invalid_object = json::object({{ "one", 1, 2 }});
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/hhxRaUctq3FA54SW"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/Ub9U5AMbng3oZiao"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
{} {}
{} {}
{"one":1,"two":2} {"one":1,"two":2}
[json.exception.type_error.301] cannot create object from initializer list
...@@ -46,4 +46,14 @@ int main() ...@@ -46,4 +46,14 @@ int main()
{ {
std::cout << i.first << ": " << i.second << '\n'; std::cout << i.first << ": " << i.second << '\n';
} }
// example for an exception
try
{
bool v1 = json_types["string"];
}
catch (json::type_error& e)
{
std::cout << e.what() << '\n';
}
} }
<a target="_blank" href="http://melpon.org/wandbox/permlink/rUGX6AaVuZfwiiYI"><b>online</b></a> <a target="_blank" href="http://melpon.org/wandbox/permlink/drFSKFXJd8IMzMK3"><b>online</b></a>
\ No newline at end of file \ No newline at end of file
...@@ -9,3 +9,4 @@ number: {"floating-point":17.23,"integer":42} ...@@ -9,3 +9,4 @@ number: {"floating-point":17.23,"integer":42}
null: null null: null
boolean: true boolean: true
array: [1,2,3,4,5] array: [1,2,3,4,5]
[json.exception.type_error.302] type must be boolean, but is string
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -44,23 +44,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) ...@@ -44,23 +44,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
// deserializations must match // deserializations must match
assert(j1 == j2); assert(j1 == j2);
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parsing a CBOR serialization must not fail // parsing a CBOR serialization must not fail
assert(false); assert(false);
} }
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parse errors are ok, because input may be random bytes // parse errors are ok, because input may be random bytes
} }
catch (const std::out_of_range&) catch (const json::type_error&)
{ {
// parse errors are ok, because input may be random bytes // type errors can occur during parsing, too
}
catch (const std::domain_error&)
{
// parse errors are ok, because input may be random bytes
} }
// return 0 - non-zero return values are reserved for future use // return 0 - non-zero return values are reserved for future use
......
...@@ -49,13 +49,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) ...@@ -49,13 +49,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
// serializations must match // serializations must match
assert(s1 == s2); assert(s1 == s2);
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parsing a JSON serialization must not fail // parsing a JSON serialization must not fail
assert(false); assert(false);
} }
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parse errors are ok, because input may be random bytes // parse errors are ok, because input may be random bytes
} }
......
...@@ -44,23 +44,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) ...@@ -44,23 +44,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
// deserializations must match // deserializations must match
assert(j1 == j2); assert(j1 == j2);
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parsing a MessagePack serialization must not fail // parsing a MessagePack serialization must not fail
assert(false); assert(false);
} }
} }
catch (const std::invalid_argument&) catch (const json::parse_error&)
{ {
// parse errors are ok, because input may be random bytes // parse errors are ok, because input may be random bytes
} }
catch (const std::out_of_range&) catch (const json::type_error&)
{ {
// parse errors are ok, because input may be random bytes // type errors can occur during parsing, too
}
catch (const std::domain_error&)
{
// parse errors are ok, because input may be random bytes
} }
// return 0 - non-zero return values are reserved for future use // return 0 - non-zero return values are reserved for future use
......
...@@ -240,8 +240,9 @@ TEST_CASE("algorithms") ...@@ -240,8 +240,9 @@ TEST_CASE("algorithms")
SECTION("sorting an object") SECTION("sorting an object")
{ {
json j({{"one", 1}, {"two", 2}}); json j({{"one", 1}, {"two", 2}});
CHECK_THROWS_AS(std::sort(j.begin(), j.end()), std::domain_error); CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator);
CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "cannot use offsets with object iterators"); CHECK_THROWS_WITH(std::sort(j.begin(), j.end()),
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
} }
} }
......
...@@ -147,8 +147,8 @@ TEST_CASE("const_iterator class") ...@@ -147,8 +147,8 @@ TEST_CASE("const_iterator class")
{ {
json j(json::value_t::null); json j(json::value_t::null);
json::const_iterator it = j.cbegin(); json::const_iterator it = j.cbegin();
CHECK_THROWS_AS(*it, std::out_of_range); CHECK_THROWS_AS(*it, json::invalid_iterator);
CHECK_THROWS_WITH(*it, "cannot get value"); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("number") SECTION("number")
...@@ -157,8 +157,8 @@ TEST_CASE("const_iterator class") ...@@ -157,8 +157,8 @@ TEST_CASE("const_iterator class")
json::const_iterator it = j.cbegin(); json::const_iterator it = j.cbegin();
CHECK(*it == json(17)); CHECK(*it == json(17));
it = j.cend(); it = j.cend();
CHECK_THROWS_AS(*it, std::out_of_range); CHECK_THROWS_AS(*it, json::invalid_iterator);
CHECK_THROWS_WITH(*it, "cannot get value"); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("object") SECTION("object")
...@@ -182,8 +182,8 @@ TEST_CASE("const_iterator class") ...@@ -182,8 +182,8 @@ TEST_CASE("const_iterator class")
{ {
json j(json::value_t::null); json j(json::value_t::null);
json::const_iterator it = j.cbegin(); json::const_iterator it = j.cbegin();
CHECK_THROWS_AS(it->type_name(), std::out_of_range); CHECK_THROWS_AS(it->type_name(), json::invalid_iterator);
CHECK_THROWS_WITH(it->type_name(), "cannot get value"); CHECK_THROWS_WITH(it->type_name(), "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("number") SECTION("number")
...@@ -192,8 +192,8 @@ TEST_CASE("const_iterator class") ...@@ -192,8 +192,8 @@ TEST_CASE("const_iterator class")
json::const_iterator it = j.cbegin(); json::const_iterator it = j.cbegin();
CHECK(it->type_name() == "number"); CHECK(it->type_name() == "number");
it = j.cend(); it = j.cend();
CHECK_THROWS_AS(it->type_name(), std::out_of_range); CHECK_THROWS_AS(it->type_name(), json::invalid_iterator);
CHECK_THROWS_WITH(it->type_name(), "cannot get value"); CHECK_THROWS_WITH(it->type_name(), "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("object") SECTION("object")
......
...@@ -131,8 +131,8 @@ TEST_CASE("iterator class") ...@@ -131,8 +131,8 @@ TEST_CASE("iterator class")
{ {
json j(json::value_t::null); json j(json::value_t::null);
json::iterator it = j.begin(); json::iterator it = j.begin();
CHECK_THROWS_AS(*it, std::out_of_range); CHECK_THROWS_AS(*it, json::invalid_iterator);
CHECK_THROWS_WITH(*it, "cannot get value"); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("number") SECTION("number")
...@@ -141,8 +141,8 @@ TEST_CASE("iterator class") ...@@ -141,8 +141,8 @@ TEST_CASE("iterator class")
json::iterator it = j.begin(); json::iterator it = j.begin();
CHECK(*it == json(17)); CHECK(*it == json(17));
it = j.end(); it = j.end();
CHECK_THROWS_AS(*it, std::out_of_range); CHECK_THROWS_AS(*it, json::invalid_iterator);
CHECK_THROWS_WITH(*it, "cannot get value"); CHECK_THROWS_WITH(*it, "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("object") SECTION("object")
...@@ -166,8 +166,8 @@ TEST_CASE("iterator class") ...@@ -166,8 +166,8 @@ TEST_CASE("iterator class")
{ {
json j(json::value_t::null); json j(json::value_t::null);
json::iterator it = j.begin(); json::iterator it = j.begin();
CHECK_THROWS_AS(it->type_name(), std::out_of_range); CHECK_THROWS_AS(it->type_name(), json::invalid_iterator);
CHECK_THROWS_WITH(it->type_name(), "cannot get value"); CHECK_THROWS_WITH(it->type_name(), "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("number") SECTION("number")
...@@ -176,8 +176,8 @@ TEST_CASE("iterator class") ...@@ -176,8 +176,8 @@ TEST_CASE("iterator class")
json::iterator it = j.begin(); json::iterator it = j.begin();
CHECK(it->type_name() == "number"); CHECK(it->type_name() == "number");
it = j.end(); it = j.end();
CHECK_THROWS_AS(it->type_name(), std::out_of_range); CHECK_THROWS_AS(it->type_name(), json::invalid_iterator);
CHECK_THROWS_WITH(it->type_name(), "cannot get value"); CHECK_THROWS_WITH(it->type_name(), "[json.exception.invalid_iterator.214] cannot get value");
} }
SECTION("object") SECTION("object")
......
...@@ -190,8 +190,10 @@ TEST_CASE("lexer class") ...@@ -190,8 +190,10 @@ TEST_CASE("lexer class")
SECTION("to_unicode") SECTION("to_unicode")
{ {
CHECK(json::lexer::to_unicode(0x1F4A9) == "💩"); // lexer to call to_unicode on
CHECK_THROWS_AS(json::lexer::to_unicode(0x200000), std::out_of_range); json::lexer dummy_lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(""), 0);
CHECK_THROWS_WITH(json::lexer::to_unicode(0x200000), "code points above 0x10FFFF are invalid"); CHECK(dummy_lexer.to_unicode(0x1F4A9) == "💩");
CHECK_THROWS_AS(dummy_lexer.to_unicode(0x200000), json::parse_error);
CHECK_THROWS_WITH(dummy_lexer.to_unicode(0x200000), "[json.exception.parse_error.103] parse error: code points above 0x10FFFF are invalid");
} }
} }
...@@ -90,15 +90,17 @@ TEST_CASE("deserialization") ...@@ -90,15 +90,17 @@ TEST_CASE("deserialization")
std::stringstream ss1, ss2; std::stringstream ss1, ss2;
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(ss1), std::invalid_argument); CHECK_THROWS_AS(json::parse(ss1), json::parse_error);
CHECK_THROWS_WITH(json::parse(ss2), "parse error - unexpected end of input; expected ']'"); CHECK_THROWS_WITH(json::parse(ss2),
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
} }
SECTION("string") SECTION("string")
{ {
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}"; json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(s), std::invalid_argument); CHECK_THROWS_AS(json::parse(s), json::parse_error);
CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'"); CHECK_THROWS_WITH(json::parse(s),
"[json.exception.parse_error.101] parse error at 29: parse error - unexpected end of input; expected ']'");
} }
SECTION("operator<<") SECTION("operator<<")
...@@ -107,8 +109,9 @@ TEST_CASE("deserialization") ...@@ -107,8 +109,9 @@ TEST_CASE("deserialization")
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
json j; json j;
CHECK_THROWS_AS(j << ss1, std::invalid_argument); CHECK_THROWS_AS(j << ss1, json::parse_error);
CHECK_THROWS_WITH(j << ss2, "parse error - unexpected end of input; expected ']'"); CHECK_THROWS_WITH(j << ss2,
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
} }
SECTION("operator>>") SECTION("operator>>")
...@@ -117,15 +120,16 @@ TEST_CASE("deserialization") ...@@ -117,15 +120,16 @@ TEST_CASE("deserialization")
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}"; ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
json j; json j;
CHECK_THROWS_AS(ss1 >> j, std::invalid_argument); CHECK_THROWS_AS(ss1 >> j, json::parse_error);
CHECK_THROWS_WITH(ss2 >> j, "parse error - unexpected end of input; expected ']'"); CHECK_THROWS_WITH(ss2 >> j,
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
} }
SECTION("user-defined string literal") SECTION("user-defined string literal")
{ {
CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument); CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error);
CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json, CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
"parse error - unexpected end of input; expected ']'"); "[json.exception.parse_error.101] parse error at 29: parse error - unexpected end of input; expected ']'");
} }
} }
...@@ -178,7 +182,7 @@ TEST_CASE("deserialization") ...@@ -178,7 +182,7 @@ TEST_CASE("deserialization")
SECTION("empty container") SECTION("empty container")
{ {
std::vector<uint8_t> v; std::vector<uint8_t> v;
CHECK_THROWS_AS(json::parse(v), std::invalid_argument); CHECK_THROWS_AS(json::parse(v), json::parse_error);
} }
} }
...@@ -223,7 +227,7 @@ TEST_CASE("deserialization") ...@@ -223,7 +227,7 @@ TEST_CASE("deserialization")
SECTION("with empty range") SECTION("with empty range")
{ {
std::vector<uint8_t> v; std::vector<uint8_t> v;
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
} }
...@@ -233,91 +237,91 @@ TEST_CASE("deserialization") ...@@ -233,91 +237,91 @@ TEST_CASE("deserialization")
SECTION("case 1") SECTION("case 1")
{ {
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}; uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 2") SECTION("case 2")
{ {
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}; uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 3") SECTION("case 3")
{ {
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}; uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 4") SECTION("case 4")
{ {
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}; uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 5") SECTION("case 5")
{ {
uint8_t v[] = {'\"', 0x7F, 0xC1}; uint8_t v[] = {'\"', 0x7F, 0xC1};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 6") SECTION("case 6")
{ {
uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F}; uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 7") SECTION("case 7")
{ {
uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0}; uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 8") SECTION("case 8")
{ {
uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F}; uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 9") SECTION("case 9")
{ {
uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0}; uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 10") SECTION("case 10")
{ {
uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F}; uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 11") SECTION("case 11")
{ {
uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F}; uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 12") SECTION("case 12")
{ {
uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0}; uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 13") SECTION("case 13")
{ {
uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F}; uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 14") SECTION("case 14")
{ {
uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0}; uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
SECTION("case 15") SECTION("case 15")
{ {
uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F}; uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument); CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
} }
} }
} }
......
...@@ -1016,6 +1016,90 @@ TEST_CASE("MessagePack") ...@@ -1016,6 +1016,90 @@ TEST_CASE("MessagePack")
json j = json::from_msgpack(given); json j = json::from_msgpack(given);
CHECK(j.get<double>() == Approx(25.0000019073486)); CHECK(j.get<double>() == Approx(25.0000019073486));
} }
SECTION("errors")
{
SECTION("too short byte vector")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcc})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcc})),
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd})),
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce})),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
}
SECTION("unsupported bytes")
{
SECTION("concrete examples")
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc1})), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc1})),
"[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xc1");
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc6})), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc6})),
"[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xc6");
}
SECTION("all unsupported bytes")
{
for (auto byte :
{
// never used
0xc1,
// bin
0xc4, 0xc5, 0xc6,
// ext
0xc7, 0xc8, 0xc9,
// fixext
0xd4, 0xd5, 0xd6, 0xd7, 0xd8
})
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error);
}
}
}
}
} }
......
...@@ -79,7 +79,7 @@ TEST_CASE("compliance tests from json.org") ...@@ -79,7 +79,7 @@ TEST_CASE("compliance tests from json.org")
CAPTURE(filename); CAPTURE(filename);
json j; json j;
std::ifstream f(filename); std::ifstream f(filename);
CHECK_THROWS_AS(j << f, std::invalid_argument); CHECK_THROWS_AS(j << f, json::parse_error);
} }
} }
...@@ -754,7 +754,7 @@ TEST_CASE("nst's JSONTestSuite") ...@@ -754,7 +754,7 @@ TEST_CASE("nst's JSONTestSuite")
CAPTURE(filename); CAPTURE(filename);
std::ifstream f(filename); std::ifstream f(filename);
json j; json j;
CHECK_THROWS_AS(j << f, std::invalid_argument); CHECK_THROWS_AS(j << f, json::parse_error);
} }
} }
...@@ -824,7 +824,7 @@ TEST_CASE("nst's JSONTestSuite") ...@@ -824,7 +824,7 @@ TEST_CASE("nst's JSONTestSuite")
CAPTURE(filename); CAPTURE(filename);
std::ifstream f(filename); std::ifstream f(filename);
json j; json j;
CHECK_THROWS_AS(j << f, std::invalid_argument); CHECK_THROWS_AS(j << f, json::parse_error);
} }
} }
} }
......
...@@ -38,6 +38,9 @@ TEST_CASE("Unicode", "[hide]") ...@@ -38,6 +38,9 @@ TEST_CASE("Unicode", "[hide]")
{ {
SECTION("full enumeration of Unicode code points") SECTION("full enumeration of Unicode code points")
{ {
// lexer to call to_unicode on
json::lexer dummy_lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(""), 0);
// create an escaped string from a code point // create an escaped string from a code point
const auto codepoint_to_unicode = [](std::size_t cp) const auto codepoint_to_unicode = [](std::size_t cp)
{ {
...@@ -85,7 +88,7 @@ TEST_CASE("Unicode", "[hide]") ...@@ -85,7 +88,7 @@ TEST_CASE("Unicode", "[hide]")
// they are checked with codepoint_to_unicode. // they are checked with codepoint_to_unicode.
if (cp > 0x1f and cp != 0x22 and cp != 0x5c) if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
{ {
unescaped_string = json::lexer::to_unicode(cp); unescaped_string = dummy_lexer.to_unicode(cp);
} }
} }
else else
...@@ -97,7 +100,7 @@ TEST_CASE("Unicode", "[hide]") ...@@ -97,7 +100,7 @@ TEST_CASE("Unicode", "[hide]")
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu); const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
escaped_string = codepoint_to_unicode(codepoint1); escaped_string = codepoint_to_unicode(codepoint1);
escaped_string += codepoint_to_unicode(codepoint2); escaped_string += codepoint_to_unicode(codepoint2);
unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2); unescaped_string += dummy_lexer.to_unicode(codepoint1, codepoint2);
} }
// all other code points are valid and must not yield parse errors // all other code points are valid and must not yield parse errors
...@@ -170,7 +173,7 @@ TEST_CASE("Unicode", "[hide]") ...@@ -170,7 +173,7 @@ TEST_CASE("Unicode", "[hide]")
SECTION("error for incomplete/wrong BOM") SECTION("error for incomplete/wrong BOM")
{ {
CHECK_THROWS_AS(json::parse("\xef\xbb"), std::invalid_argument); CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error);
CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), std::invalid_argument); CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment