From 76e5e29eda2ff9d065e52d5cfe06ced51bd3c253 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 25 Dec 2015 11:46:18 +0100 Subject: [PATCH] overworked exceptions and tests (#160) --- README.md | 4 +- src/json.hpp | 90 ++++--- src/json.hpp.re2c | 90 ++++--- test/unit.cpp | 612 ++++++++++++++++++++++++++++++++++++---------- 4 files changed, 595 insertions(+), 201 deletions(-) diff --git a/README.md b/README.md index 3d5d93bc..42c49dd2 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ to the files you want to use JSON objects. That's it. Do not forget to set the n Though it's 2015 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- GCC 4.9 - 5.2 (and possibly later) -- Clang 3.4 - 3.7 (and possibly later) +- GCC 4.9 - 6.0 (and possibly later) +- Clang 3.4 - 3.8 (and possibly later) - Microsoft Visual C++ 14.0 RC (and possibly later) I would be happy to learn about other compilers/versions. diff --git a/src/json.hpp b/src/json.hpp index b483ca6c..b5db4fe6 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1359,7 +1359,8 @@ class basic_json @throw std::domain_error if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string + whose first element is a string; example: `"cannot create object from + initializer list"` @complexity Linear in the size of the initializer list @a init. @@ -1552,11 +1553,13 @@ class basic_json @param[in] last end of the range to copy from (excluded) @throw std::domain_error if iterators are not compatible; that is, do not - belong to the same JSON value + belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, - boolean, or string) where an out of range error can be detected easily + boolean, or string) where an out of range error can be detected easily; + example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value + @throw std::domain_error if called with a null value; example: `"cannot use + construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @@ -2412,7 +2415,7 @@ class basic_json @return copy of the JSON value, converted to type @a ValueType @throw std::domain_error in case passed type @a ValueType is incompatible - to JSON + to JSON; example: `"type must be object, but is null"` @complexity Linear in the size of the JSON value. @@ -2785,7 +2788,8 @@ class basic_json @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null + @throw std::domain_error if JSON is not an array or null; example: `"cannot + use operator[] with null"` @complexity Constant if @a idx is in the range of the array. Otherwise linear in `idx - size()`. @@ -2830,7 +2834,8 @@ class basic_json @return const reference to the element at index @a idx - @throw std::domain_error if JSON is not an array + @throw std::domain_error if JSON is not an array; example: `"cannot use + operator[] with null"` @complexity Constant. @@ -2865,7 +2870,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null + @throw std::domain_error if JSON is not an object or null; example: + `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -2911,7 +2917,8 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + operator[] with null"` @complexity Logarithmic in the size of the container. @@ -2952,7 +2959,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null + @throw std::domain_error if JSON is not an object or null; example: + `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3001,7 +3009,8 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3061,7 +3070,8 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + value() with null"` @complexity Logarithmic in the size of the container. @@ -3199,11 +3209,13 @@ class basic_json @tparam InteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value + @throw std::domain_error if called on a `null` value; example: `"cannot use + erase() with null"` @throw std::domain_error if called on an iterator which does not belong to - the current JSON value + the current JSON value; example: `"iterator does not fit current value"` @throw std::out_of_range if called on a primitive type with invalid - iterator (i.e., any iterator which is not end()) + iterator (i.e., any iterator which is not end()); example: `"iterator out + of range"` @complexity The complexity depends on the type: - objects: amortized constant @@ -3300,11 +3312,13 @@ class basic_json @tparam InteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value + @throw std::domain_error if called on a `null` value; example: `"cannot use + erase() with null"` @throw std::domain_error if called on iterators which does not belong to - the current JSON value + the current JSON value; example: `"iterators do not fit current value"` @throw std::out_of_range if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`) + iterators (i.e., if `first != begin()` and `last != end()`); example: + `"iterators out of range"` @complexity The complexity depends on the type: - objects: `log(size()) + std::distance(first, last)` @@ -3378,7 +3392,7 @@ class basic_json default: { - throw std::domain_error("cannot use erase with " + type_name()); + throw std::domain_error("cannot use erase() with " + type_name()); } } @@ -3396,7 +3410,8 @@ class basic_json type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). - @throw std::domain_error when called on a type other than JSON object + @throw std::domain_error when called on a type other than JSON object; + example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @@ -3430,8 +3445,10 @@ class basic_json @param[in] idx index of the element to remove - @throw std::domain_error when called on a type other than JSON array - @throw std::out_of_range when `idx >= size()` + @throw std::domain_error when called on a type other than JSON array; + example: `"cannot use erase() with null"` + @throw std::out_of_range when `idx >= size()`; example: `"index out of + range"` @complexity Linear in distance between @a idx and the end of the container. @@ -4065,7 +4082,8 @@ class basic_json @param val the value to add to the JSON array - @throw std::domain_error when called on a type other than JSON array or null + @throw std::domain_error when called on a type other than JSON array or + null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @@ -4149,7 +4167,7 @@ class basic_json @param[in] val the value to add to the JSON object @throw std::domain_error when called on a type other than JSON object or - null + null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -4199,7 +4217,8 @@ class basic_json @return iterator pointing to the inserted @a val. @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @complexity Constant plus linear in the distance between pos and end of the container. @@ -4252,7 +4271,8 @@ class basic_json `cnt==0` @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @@ -4294,11 +4314,14 @@ class basic_json @param[in] last end of the range of elements to insert @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @throw std::domain_error if @a first and @a last do not belong to the same - JSON value + JSON value; example: `"iterators do not fit"` @throw std::domain_error if @a first or @a last are iterators into - container for which insert is called + container for which insert is called; example: `"passed iterators may not + belong to container"` + @return iterator pointing to the first element inserted, or @a pos if `first==last` @@ -4352,7 +4375,8 @@ class basic_json @param[in] ilist initializer list to insert the values from @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @@ -5870,7 +5894,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator< for object iterators"); + throw std::domain_error("cannot compare order of object iterators"); } case basic_json::value_t::array: @@ -5910,7 +5934,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator+= for object iterators"); + throw std::domain_error("cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -5958,7 +5982,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator- for object iterators"); + throw std::domain_error("cannot use offsets with object iterators"); } case basic_json::value_t::array: diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 2feab104..24ab2757 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1359,7 +1359,8 @@ class basic_json @throw std::domain_error if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string + whose first element is a string; example: `"cannot create object from + initializer list"` @complexity Linear in the size of the initializer list @a init. @@ -1552,11 +1553,13 @@ class basic_json @param[in] last end of the range to copy from (excluded) @throw std::domain_error if iterators are not compatible; that is, do not - belong to the same JSON value + belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, - boolean, or string) where an out of range error can be detected easily + boolean, or string) where an out of range error can be detected easily; + example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value + @throw std::domain_error if called with a null value; example: `"cannot use + construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @@ -2412,7 +2415,7 @@ class basic_json @return copy of the JSON value, converted to type @a ValueType @throw std::domain_error in case passed type @a ValueType is incompatible - to JSON + to JSON; example: `"type must be object, but is null"` @complexity Linear in the size of the JSON value. @@ -2785,7 +2788,8 @@ class basic_json @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null + @throw std::domain_error if JSON is not an array or null; example: `"cannot + use operator[] with null"` @complexity Constant if @a idx is in the range of the array. Otherwise linear in `idx - size()`. @@ -2830,7 +2834,8 @@ class basic_json @return const reference to the element at index @a idx - @throw std::domain_error if JSON is not an array + @throw std::domain_error if JSON is not an array; example: `"cannot use + operator[] with null"` @complexity Constant. @@ -2865,7 +2870,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null + @throw std::domain_error if JSON is not an object or null; example: + `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -2911,7 +2917,8 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + operator[] with null"` @complexity Logarithmic in the size of the container. @@ -2952,7 +2959,8 @@ class basic_json @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null + @throw std::domain_error if JSON is not an object or null; example: + `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3001,7 +3009,8 @@ class basic_json @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3061,7 +3070,8 @@ class basic_json @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object + @throw std::domain_error if JSON is not an object; example: `"cannot use + value() with null"` @complexity Logarithmic in the size of the container. @@ -3199,11 +3209,13 @@ class basic_json @tparam InteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value + @throw std::domain_error if called on a `null` value; example: `"cannot use + erase() with null"` @throw std::domain_error if called on an iterator which does not belong to - the current JSON value + the current JSON value; example: `"iterator does not fit current value"` @throw std::out_of_range if called on a primitive type with invalid - iterator (i.e., any iterator which is not end()) + iterator (i.e., any iterator which is not end()); example: `"iterator out + of range"` @complexity The complexity depends on the type: - objects: amortized constant @@ -3300,11 +3312,13 @@ class basic_json @tparam InteratorType an @ref iterator or @ref const_iterator - @throw std::domain_error if called on a `null` value + @throw std::domain_error if called on a `null` value; example: `"cannot use + erase() with null"` @throw std::domain_error if called on iterators which does not belong to - the current JSON value + the current JSON value; example: `"iterators do not fit current value"` @throw std::out_of_range if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`) + iterators (i.e., if `first != begin()` and `last != end()`); example: + `"iterators out of range"` @complexity The complexity depends on the type: - objects: `log(size()) + std::distance(first, last)` @@ -3378,7 +3392,7 @@ class basic_json default: { - throw std::domain_error("cannot use erase with " + type_name()); + throw std::domain_error("cannot use erase() with " + type_name()); } } @@ -3396,7 +3410,8 @@ class basic_json type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). - @throw std::domain_error when called on a type other than JSON object + @throw std::domain_error when called on a type other than JSON object; + example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @@ -3430,8 +3445,10 @@ class basic_json @param[in] idx index of the element to remove - @throw std::domain_error when called on a type other than JSON array - @throw std::out_of_range when `idx >= size()` + @throw std::domain_error when called on a type other than JSON array; + example: `"cannot use erase() with null"` + @throw std::out_of_range when `idx >= size()`; example: `"index out of + range"` @complexity Linear in distance between @a idx and the end of the container. @@ -4065,7 +4082,8 @@ class basic_json @param val the value to add to the JSON array - @throw std::domain_error when called on a type other than JSON array or null + @throw std::domain_error when called on a type other than JSON array or + null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @@ -4149,7 +4167,7 @@ class basic_json @param[in] val the value to add to the JSON object @throw std::domain_error when called on a type other than JSON object or - null + null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -4199,7 +4217,8 @@ class basic_json @return iterator pointing to the inserted @a val. @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @complexity Constant plus linear in the distance between pos and end of the container. @@ -4252,7 +4271,8 @@ class basic_json `cnt==0` @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @@ -4294,11 +4314,14 @@ class basic_json @param[in] last end of the range of elements to insert @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @throw std::domain_error if @a first and @a last do not belong to the same - JSON value + JSON value; example: `"iterators do not fit"` @throw std::domain_error if @a first or @a last are iterators into - container for which insert is called + container for which insert is called; example: `"passed iterators may not + belong to container"` + @return iterator pointing to the first element inserted, or @a pos if `first==last` @@ -4352,7 +4375,8 @@ class basic_json @param[in] ilist initializer list to insert the values from @throw std::domain_error if called on JSON values other than arrays - @throw std::domain_error if @a pos is not an iterator of *this + @throw std::domain_error if @a pos is not an iterator of *this; example: + `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @@ -5870,7 +5894,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator< for object iterators"); + throw std::domain_error("cannot compare order of object iterators"); } case basic_json::value_t::array: @@ -5910,7 +5934,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator+= for object iterators"); + throw std::domain_error("cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -5958,7 +5982,7 @@ class basic_json { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator- for object iterators"); + throw std::domain_error("cannot use offsets with object iterators"); } case basic_json::value_t::array: diff --git a/test/unit.cpp b/test/unit.cpp index 7b4323d3..0f0d745d 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -10,6 +10,9 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" +// macro to check exception names (see https://github.com/philsquared/Catch/issues/563) +#define CHECK_THROWS_NAME(block, exception, name) { try { block; } catch ( exception &e ) { CHECK(e.what() == std::string(name)); } } + #include #include #include @@ -895,6 +898,8 @@ TEST_CASE("constructors") SECTION("object with error") { CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 2.2}, {"three", false}, 13 }), std::logic_error); + CHECK_THROWS_NAME(json::object({ {"one", 1}, {"two", 2.2}, {"three", false}, 13 }), + std::logic_error, "cannot create object from initializer list"); } SECTION("empty array") @@ -968,12 +973,20 @@ TEST_CASE("constructors") json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}}; CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), std::domain_error); CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), std::domain_error); + CHECK_THROWS_NAME(json(jobject.begin(), jobject2.end()), std::domain_error, + "iterators are not compatible"); + CHECK_THROWS_NAME(json(jobject2.begin(), jobject.end()), std::domain_error, + "iterators are not compatible"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}}; CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), std::domain_error); CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), std::domain_error); + CHECK_THROWS_NAME(json(jobject.cbegin(), jobject2.cend()), std::domain_error, + "iterators are not compatible"); + CHECK_THROWS_NAME(json(jobject2.cbegin(), jobject.cend()), std::domain_error, + "iterators are not compatible"); } } } @@ -1029,12 +1042,20 @@ TEST_CASE("constructors") json jarray2 = {2, 3, 4, 5}; CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), std::domain_error); CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), std::domain_error); + CHECK_THROWS_NAME(json(jarray.begin(), jarray2.end()), std::domain_error, + "iterators are not compatible"); + CHECK_THROWS_NAME(json(jarray2.begin(), jarray.end()), std::domain_error, + "iterators are not compatible"); } { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), std::domain_error); CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), std::domain_error); + CHECK_THROWS_NAME(json(jarray.cbegin(), jarray2.cend()), std::domain_error, + "iterators are not compatible"); + CHECK_THROWS_NAME(json(jarray2.cbegin(), jarray.cend()), std::domain_error, + "iterators are not compatible"); } } } @@ -1048,10 +1069,14 @@ TEST_CASE("constructors") { json j; CHECK_THROWS_AS(json(j.begin(), j.end()), std::domain_error); + CHECK_THROWS_NAME(json(j.begin(), j.end()), std::domain_error, + "cannot use construct with iterators from null"); } { json j; CHECK_THROWS_AS(json(j.cbegin(), j.cend()), std::domain_error); + CHECK_THROWS_NAME(json(j.cbegin(), j.cend()), std::domain_error, + "cannot use construct with iterators from null"); } } @@ -1120,11 +1145,15 @@ TEST_CASE("constructors") json j = "foo"; CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = "bar"; CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -1134,11 +1163,15 @@ TEST_CASE("constructors") json j = false; CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = true; CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -1148,11 +1181,15 @@ TEST_CASE("constructors") json j = 17; CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = 17; CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -1162,11 +1199,15 @@ TEST_CASE("constructors") json j = 23.42; CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = 23.42; CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(json(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(json(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } } @@ -1645,6 +1686,19 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::boolean).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_integer).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_float).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be object, but is null"); + CHECK_THROWS_NAME(json(json::value_t::array).get(), std::logic_error, + "type must be object, but is array"); + CHECK_THROWS_NAME(json(json::value_t::string).get(), std::logic_error, + "type must be object, but is string"); + CHECK_THROWS_NAME(json(json::value_t::boolean).get(), std::logic_error, + "type must be object, but is boolean"); + CHECK_THROWS_NAME(json(json::value_t::number_integer).get(), std::logic_error, + "type must be object, but is number"); + CHECK_THROWS_NAME(json(json::value_t::number_float).get(), std::logic_error, + "type must be object, but is number"); } } @@ -1727,6 +1781,19 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::boolean).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_integer).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_float).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be array, but is null"); + CHECK_THROWS_NAME(json(json::value_t::object).get(), std::logic_error, + "type must be array, but is object"); + CHECK_THROWS_NAME(json(json::value_t::string).get(), std::logic_error, + "type must be array, but is string"); + CHECK_THROWS_NAME(json(json::value_t::boolean).get(), std::logic_error, + "type must be array, but is boolean"); + CHECK_THROWS_NAME(json(json::value_t::number_integer).get(), std::logic_error, + "type must be array, but is number"); + CHECK_THROWS_NAME(json(json::value_t::number_float).get(), std::logic_error, + "type must be array, but is number"); } } @@ -1791,6 +1858,19 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::boolean).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_integer).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_float).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be string, but is null"); + CHECK_THROWS_NAME(json(json::value_t::object).get(), std::logic_error, + "type must be string, but is object"); + CHECK_THROWS_NAME(json(json::value_t::array).get(), std::logic_error, + "type must be string, but is array"); + CHECK_THROWS_NAME(json(json::value_t::boolean).get(), std::logic_error, + "type must be string, but is boolean"); + CHECK_THROWS_NAME(json(json::value_t::number_integer).get(), std::logic_error, + "type must be string, but is number"); + CHECK_THROWS_NAME(json(json::value_t::number_float).get(), std::logic_error, + "type must be string, but is number"); } } @@ -1837,6 +1917,19 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::string).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_integer).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::number_float).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be boolean, but is null"); + CHECK_THROWS_NAME(json(json::value_t::object).get(), std::logic_error, + "type must be boolean, but is object"); + CHECK_THROWS_NAME(json(json::value_t::array).get(), std::logic_error, + "type must be boolean, but is array"); + CHECK_THROWS_NAME(json(json::value_t::string).get(), std::logic_error, + "type must be boolean, but is string"); + CHECK_THROWS_NAME(json(json::value_t::number_integer).get(), std::logic_error, + "type must be boolean, but is number"); + CHECK_THROWS_NAME(json(json::value_t::number_float).get(), std::logic_error, + "type must be boolean, but is number"); } } @@ -2068,6 +2161,18 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::array).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::string).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::boolean).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be number, but is null"); + CHECK_THROWS_NAME(json(json::value_t::object).get(), std::logic_error, + "type must be number, but is object"); + CHECK_THROWS_NAME(json(json::value_t::array).get(), std::logic_error, + "type must be number, but is array"); + CHECK_THROWS_NAME(json(json::value_t::string).get(), std::logic_error, + "type must be number, but is string"); + CHECK_THROWS_NAME(json(json::value_t::boolean).get(), std::logic_error, + "type must be number, but is boolean"); + CHECK_NOTHROW(json(json::value_t::number_float).get()); } } @@ -2306,6 +2411,18 @@ TEST_CASE("value conversion") CHECK_THROWS_AS(json(json::value_t::array).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::string).get(), std::logic_error); CHECK_THROWS_AS(json(json::value_t::boolean).get(), std::logic_error); + + CHECK_THROWS_NAME(json(json::value_t::null).get(), std::logic_error, + "type must be number, but is null"); + CHECK_THROWS_NAME(json(json::value_t::object).get(), std::logic_error, + "type must be number, but is object"); + CHECK_THROWS_NAME(json(json::value_t::array).get(), std::logic_error, + "type must be number, but is array"); + CHECK_THROWS_NAME(json(json::value_t::string).get(), std::logic_error, + "type must be number, but is string"); + CHECK_THROWS_NAME(json(json::value_t::boolean).get(), std::logic_error, + "type must be number, but is boolean"); + CHECK_NOTHROW(json(json::value_t::number_integer).get()); } } @@ -2381,6 +2498,8 @@ TEST_CASE("value conversion") SECTION("exception in case of a non-object type") { CHECK_THROWS_AS((json().get>()), std::logic_error); + CHECK_THROWS_NAME((json().get>()), std::logic_error, + "type must be object, but is null"); } } @@ -2445,6 +2564,15 @@ TEST_CASE("value conversion") CHECK_THROWS_AS((json().get>()), std::logic_error); CHECK_THROWS_AS((json().get>()), std::logic_error); CHECK_THROWS_AS((json().get>()), std::logic_error); + + CHECK_THROWS_NAME((json().get>()), std::logic_error, + "type must be array, but is null"); + CHECK_THROWS_NAME((json().get>()), std::logic_error, + "type must be array, but is null"); + CHECK_THROWS_NAME((json().get>()), std::logic_error, + "type must be array, but is null"); + CHECK_THROWS_NAME((json().get>()), std::logic_error, + "type must be array, but is null"); } } } @@ -2663,15 +2791,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j.at(7), std::out_of_range); CHECK_THROWS_AS(j_const.at(7), std::out_of_range); - // exception name - try - { - j.at(7); - } - catch (std::out_of_range& e) - { - CHECK(std::string(e.what()) == "array index 7 is out of range"); - } + CHECK_THROWS_NAME(j.at(7), std::out_of_range, "array index 7 is out of range"); + CHECK_THROWS_NAME(j_const.at(7), std::out_of_range, "array index 7 is out of range"); } SECTION("access on non-array type") @@ -2683,15 +2804,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with null"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with null"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with null"); } SECTION("boolean") @@ -2701,15 +2815,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with boolean"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with boolean"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with boolean"); } SECTION("string") @@ -2719,15 +2826,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with string"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with string"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with string"); } SECTION("object") @@ -2737,15 +2837,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with object"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with object"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with object"); } SECTION("number (integer)") @@ -2755,15 +2848,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with number"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with number"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with number"); } SECTION("number (floating-point)") @@ -2773,15 +2859,8 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); - // exception name - try - { - j_nonarray.at(0); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with number"); - } + CHECK_THROWS_NAME(j_nonarray.at(0), std::domain_error, "cannot use at() with number"); + CHECK_THROWS_NAME(j_nonarray_const.at(0), std::domain_error, "cannot use at() with number"); } } } @@ -2825,6 +2904,7 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_NOTHROW(j_nonarray[0]); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with null"); } SECTION("implicit transformation to properly filled array") @@ -2841,6 +2921,8 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_THROWS_AS(j_nonarray[0], std::domain_error); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray[0], std::domain_error, "cannot use operator[] with boolean"); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with boolean"); } SECTION("string") @@ -2849,6 +2931,8 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_THROWS_AS(j_nonarray[0], std::domain_error); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray[0], std::domain_error, "cannot use operator[] with string"); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with string"); } SECTION("object") @@ -2857,6 +2941,8 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_THROWS_AS(j_nonarray[0], std::domain_error); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray[0], std::domain_error, "cannot use operator[] with object"); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with object"); } SECTION("number (integer)") @@ -2865,6 +2951,8 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_THROWS_AS(j_nonarray[0], std::domain_error); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray[0], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with number"); } SECTION("number (floating-point)") @@ -2873,6 +2961,8 @@ TEST_CASE("element access") const json j_nonarray_const(j_nonarray); CHECK_THROWS_AS(j_nonarray[0], std::domain_error); CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); + CHECK_THROWS_NAME(j_nonarray[0], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_nonarray_const[0], std::domain_error, "cannot use operator[] with number"); } } } @@ -2919,6 +3009,7 @@ TEST_CASE("element access") { json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; CHECK_THROWS_AS(jarray.erase(7), std::out_of_range); + CHECK_THROWS_NAME(jarray.erase(7), std::out_of_range, "index out of range"); } } @@ -3015,6 +3106,15 @@ TEST_CASE("element access") CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error); CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), std::domain_error); CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), std::domain_error); + + CHECK_THROWS_NAME(jarray.erase(jarray2.begin()), std::domain_error, + "iterator does not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray2.begin(), jarray.end()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray2.begin(), jarray2.end()), std::domain_error, + "iterators do not fit current value"); } { json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; @@ -3023,6 +3123,15 @@ TEST_CASE("element access") CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error); CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), std::domain_error); CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::domain_error); + + CHECK_THROWS_NAME(jarray.erase(jarray2.cbegin()), std::domain_error, + "iterator does not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray2.cbegin(), jarray.cend()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::domain_error, + "iterators do not fit current value"); } } } @@ -3033,36 +3142,42 @@ TEST_CASE("element access") { json j_nonobject(json::value_t::null); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with string"); } SECTION("object") { json j_nonobject(json::value_t::object); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with object"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase(0), std::domain_error, "cannot use erase() with number"); } } } @@ -3098,16 +3213,8 @@ TEST_CASE("element access") { CHECK_THROWS_AS(j.at("foo"), std::out_of_range); CHECK_THROWS_AS(j_const.at("foo"), std::out_of_range); - - // exception name - try - { - j.at("foo"); - } - catch (std::out_of_range& e) - { - CHECK(std::string(e.what()) == "key 'foo' not found"); - } + CHECK_THROWS_NAME(j.at("foo"), std::out_of_range, "key 'foo' not found"); + CHECK_THROWS_NAME(j_const.at("foo"), std::out_of_range, "key 'foo' not found"); } SECTION("access on non-object type") @@ -3118,16 +3225,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with null"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with null"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with null"); } SECTION("boolean") @@ -3136,16 +3235,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with boolean"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with boolean"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with boolean"); } SECTION("string") @@ -3154,16 +3245,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with string"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with string"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with string"); } SECTION("array") @@ -3172,16 +3255,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with array"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with array"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with array"); } SECTION("number (integer)") @@ -3190,16 +3265,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with number"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with number"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with number"); } SECTION("number (floating-point)") @@ -3208,16 +3275,8 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - - // exception name - try - { - j_nonobject.at("foo"); - } - catch (std::domain_error& e) - { - CHECK(std::string(e.what()) == "cannot use at() with number"); - } + CHECK_THROWS_NAME(j_nonobject.at("foo"), std::domain_error, "cannot use at() with number"); + CHECK_THROWS_NAME(j_nonobject_const.at("foo"), std::domain_error, "cannot use at() with number"); } } } @@ -3273,6 +3332,9 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, "cannot use value() with null"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with null"); } SECTION("boolean") @@ -3281,6 +3343,10 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, + "cannot use value() with boolean"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with boolean"); } SECTION("string") @@ -3289,6 +3355,9 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, "cannot use value() with string"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with string"); } SECTION("array") @@ -3297,6 +3366,9 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, "cannot use value() with array"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with array"); } SECTION("number (integer)") @@ -3305,6 +3377,9 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, "cannot use value() with number"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with number"); } SECTION("number (floating-point)") @@ -3313,6 +3388,9 @@ TEST_CASE("element access") const json j_nonobject_const(j_nonobject); CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.value("foo", 1), std::domain_error, "cannot use value() with number"); + CHECK_THROWS_NAME(j_nonobject_const.value("foo", 1), std::domain_error, + "cannot use value() with number"); } } } @@ -3385,6 +3463,9 @@ TEST_CASE("element access") CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, "cannot use operator[] with null"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with null"); } SECTION("boolean") @@ -3395,6 +3476,13 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_nonobject["foo"], std::domain_error, "cannot use operator[] with boolean"); + CHECK_THROWS_NAME(j_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with boolean"); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, + "cannot use operator[] with boolean"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with boolean"); } SECTION("string") @@ -3405,6 +3493,12 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_nonobject["foo"], std::domain_error, "cannot use operator[] with string"); + CHECK_THROWS_NAME(j_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with string"); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, "cannot use operator[] with string"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with string"); } SECTION("array") @@ -3415,6 +3509,12 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_nonobject["foo"], std::domain_error, "cannot use operator[] with array"); + CHECK_THROWS_NAME(j_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with array"); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, "cannot use operator[] with array"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with array"); } SECTION("number (integer)") @@ -3425,6 +3525,12 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_nonobject["foo"], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with number"); } SECTION("number (floating-point)") @@ -3435,6 +3541,12 @@ TEST_CASE("element access") CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); + CHECK_THROWS_NAME(j_nonobject["foo"], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_const_nonobject["foo"], std::domain_error, "cannot use operator[] with number"); + CHECK_THROWS_NAME(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error, + "cannot use operator[] with number"); } } } @@ -3572,6 +3684,14 @@ TEST_CASE("element access") CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error); CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error); CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), std::domain_error); + CHECK_THROWS_NAME(jobject.erase(jobject2.begin()), std::domain_error, + "iterator does not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject2.begin(), jobject2.end()), std::domain_error, + "iterators do not fit current value"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}}; @@ -3580,6 +3700,14 @@ TEST_CASE("element access") CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error); CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error); CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::domain_error); + CHECK_THROWS_NAME(jobject.erase(jobject2.cbegin()), std::domain_error, + "iterator does not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error, + "iterators do not fit current value"); + CHECK_THROWS_NAME(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::domain_error, + "iterators do not fit current value"); } } } @@ -3590,36 +3718,42 @@ TEST_CASE("element access") { json j_nonobject(json::value_t::null); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with string"); } SECTION("array") { json j_nonobject(json::value_t::array); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); + CHECK_THROWS_NAME(j_nonobject.erase("foo"), std::domain_error, "cannot use erase() with number"); } } } @@ -3795,11 +3929,15 @@ TEST_CASE("element access") json j; CHECK_THROWS_AS(j.front(), std::out_of_range); CHECK_THROWS_AS(j.back(), std::out_of_range); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } { const json j{}; CHECK_THROWS_AS(j.front(), std::out_of_range); CHECK_THROWS_AS(j.back(), std::out_of_range); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } } @@ -3809,11 +3947,15 @@ TEST_CASE("element access") json j = "foo"; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } { const json j = "bar"; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } } @@ -3823,11 +3965,15 @@ TEST_CASE("element access") json j = false; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } { const json j = true; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } } @@ -3837,11 +3983,15 @@ TEST_CASE("element access") json j = 17; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } { const json j = 17; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } } @@ -3851,11 +4001,15 @@ TEST_CASE("element access") json j = 23.42; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } { const json j = 23.42; CHECK(j.front() == j); CHECK(j.back() == j); + CHECK_THROWS_NAME(j.front(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(j.back(), std::out_of_range, "cannot get value"); } } } @@ -3867,10 +4021,12 @@ TEST_CASE("element access") { json j; CHECK_THROWS_AS(j.erase(j.begin()), std::domain_error); + CHECK_THROWS_NAME(j.erase(j.begin()), std::domain_error, "cannot use erase() with null"); } { json j; CHECK_THROWS_AS(j.erase(j.cbegin()), std::domain_error); + CHECK_THROWS_NAME(j.erase(j.begin()), std::domain_error, "cannot use erase() with null"); } } @@ -3946,10 +4102,12 @@ TEST_CASE("element access") { json j = "foo"; CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end()), std::out_of_range, "iterator out of range"); } { json j = "bar"; CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend()), std::out_of_range, "iterator out of range"); } } @@ -3958,10 +4116,12 @@ TEST_CASE("element access") { json j = false; CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end()), std::out_of_range, "iterator out of range"); } { json j = true; CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend()), std::out_of_range, "iterator out of range"); } } @@ -3970,10 +4130,12 @@ TEST_CASE("element access") { json j = 17; CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end()), std::out_of_range, "iterator out of range"); } { json j = 17; CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend()), std::out_of_range, "iterator out of range"); } } @@ -3982,10 +4144,12 @@ TEST_CASE("element access") { json j = 23.42; CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end()), std::out_of_range, "iterator out of range"); } { json j = 23.42; CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend()), std::out_of_range, "iterator out of range"); } } } @@ -3997,10 +4161,12 @@ TEST_CASE("element access") { json j; CHECK_THROWS_AS(j.erase(j.begin(), j.end()), std::domain_error); + CHECK_THROWS_NAME(j.erase(j.begin(), j.end()), std::domain_error, "cannot use erase() with null"); } { json j; CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), std::domain_error); + CHECK_THROWS_NAME(j.erase(j.cbegin(), j.cend()), std::domain_error, "cannot use erase() with null"); } } @@ -4077,11 +4243,15 @@ TEST_CASE("element access") json j = "foo"; CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = "bar"; CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -4091,11 +4261,15 @@ TEST_CASE("element access") json j = false; CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = true; CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -4105,11 +4279,15 @@ TEST_CASE("element access") json j = 17; CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = 17; CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } @@ -4119,11 +4297,15 @@ TEST_CASE("element access") json j = 23.42; CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.end(), j.end()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.begin(), j.begin()), std::out_of_range, "iterators out of range"); } { json j = 23.42; CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); + CHECK_THROWS_NAME(j.erase(j.cend(), j.cend()), std::out_of_range, "iterators out of range"); + CHECK_THROWS_NAME(j.erase(j.cbegin(), j.cbegin()), std::out_of_range, "iterators out of range"); } } } @@ -4328,8 +4510,10 @@ TEST_CASE("iterators") auto it = j.begin(); auto cit = j_const.cbegin(); CHECK_THROWS_AS(it.key(), std::domain_error); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(it.value() == json(true)); CHECK_THROWS_AS(cit.key(), std::domain_error); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(cit.value() == json(true)); auto rit = j.rend(); @@ -4338,6 +4522,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(rit.value(), std::out_of_range); CHECK_THROWS_AS(crit.key(), std::domain_error); CHECK_THROWS_AS(crit.value(), std::out_of_range); + CHECK_THROWS_NAME(rit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(rit.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(crit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(crit.value(), std::out_of_range, "cannot get value"); } } @@ -4526,8 +4714,10 @@ TEST_CASE("iterators") auto it = j.begin(); auto cit = j_const.cbegin(); CHECK_THROWS_AS(it.key(), std::domain_error); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(it.value() == json("hello world")); CHECK_THROWS_AS(cit.key(), std::domain_error); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(cit.value() == json("hello world")); auto rit = j.rend(); @@ -4536,6 +4726,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(rit.value(), std::out_of_range); CHECK_THROWS_AS(crit.key(), std::domain_error); CHECK_THROWS_AS(crit.value(), std::out_of_range); + CHECK_THROWS_NAME(rit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(rit.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(crit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(crit.value(), std::out_of_range, "cannot get value"); } } @@ -4717,8 +4911,10 @@ TEST_CASE("iterators") auto it = j.begin(); auto cit = j_const.cbegin(); CHECK_THROWS_AS(it.key(), std::domain_error); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(it.value() == json(1)); CHECK_THROWS_AS(cit.key(), std::domain_error); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(cit.value() == json(1)); } } @@ -5092,8 +5288,10 @@ TEST_CASE("iterators") auto it = j.begin(); auto cit = j_const.cbegin(); CHECK_THROWS_AS(it.key(), std::domain_error); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); CHECK_THROWS_AS(cit.key(), std::domain_error); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); @@ -5102,6 +5300,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(rit.value(), std::out_of_range); CHECK_THROWS_AS(crit.key(), std::domain_error); CHECK_THROWS_AS(crit.value(), std::out_of_range); + CHECK_THROWS_NAME(rit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(rit.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(crit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(crit.value(), std::out_of_range, "cannot get value"); } } @@ -5290,8 +5492,10 @@ TEST_CASE("iterators") auto it = j.begin(); auto cit = j_const.cbegin(); CHECK_THROWS_AS(it.key(), std::domain_error); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(it.value() == json(23.42)); CHECK_THROWS_AS(cit.key(), std::domain_error); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); CHECK(cit.value() == json(23.42)); auto rit = j.rend(); @@ -5300,6 +5504,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(rit.value(), std::out_of_range); CHECK_THROWS_AS(crit.key(), std::domain_error); CHECK_THROWS_AS(crit.value(), std::out_of_range); + CHECK_THROWS_NAME(rit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(rit.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(crit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(crit.value(), std::out_of_range, "cannot get value"); } } @@ -5361,6 +5569,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it.value(), std::out_of_range); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK_THROWS_AS(cit.value(), std::out_of_range); + CHECK_THROWS_NAME(it.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(it.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(cit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(cit.value(), std::out_of_range, "cannot get value"); auto rit = j.rend(); auto crit = j.crend(); @@ -5368,6 +5580,10 @@ TEST_CASE("iterators") CHECK_THROWS_AS(rit.value(), std::out_of_range); CHECK_THROWS_AS(crit.key(), std::domain_error); CHECK_THROWS_AS(crit.value(), std::out_of_range); + CHECK_THROWS_NAME(rit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(rit.value(), std::out_of_range, "cannot get value"); + CHECK_THROWS_NAME(crit.key(), std::domain_error, "cannot use key() for non-object iterators"); + CHECK_THROWS_NAME(crit.value(), std::out_of_range, "cannot get value"); } } } @@ -5428,6 +5644,14 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it1_c < it2_c, std::domain_error); CHECK_THROWS_AS(it2_c < it3_c, std::domain_error); CHECK_THROWS_AS(it1_c < it3_c, std::domain_error); + CHECK_THROWS_NAME(it1 < it1, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 < it2, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2 < it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 < it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c < it1_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c < it2_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2_c < it3_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c < it3_c, std::domain_error, "cannot compare order of object iterators"); } else { @@ -5454,6 +5678,14 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error); CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error); CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error); + CHECK_THROWS_NAME(it1 <= it1, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 <= it2, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2 <= it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 <= it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c <= it1_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c <= it2_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2_c <= it3_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c <= it3_c, std::domain_error, "cannot compare order of object iterators"); } else { @@ -5481,6 +5713,14 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it1_c > it2_c, std::domain_error); CHECK_THROWS_AS(it2_c > it3_c, std::domain_error); CHECK_THROWS_AS(it1_c > it3_c, std::domain_error); + CHECK_THROWS_NAME(it1 > it1, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 > it2, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2 > it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 > it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c > it1_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c > it2_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2_c > it3_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c > it3_c, std::domain_error, "cannot compare order of object iterators"); } else { @@ -5508,6 +5748,14 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error); CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error); CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error); + CHECK_THROWS_NAME(it1 >= it1, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 >= it2, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2 >= it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1 >= it3, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c >= it1_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c >= it2_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it2_c >= it3_c, std::domain_error, "cannot compare order of object iterators"); + CHECK_THROWS_NAME(it1_c >= it3_c, std::domain_error, "cannot compare order of object iterators"); } else { @@ -5533,9 +5781,17 @@ TEST_CASE("iterators") { CHECK_THROWS_AS(j.begin() == k.begin(), std::domain_error); CHECK_THROWS_AS(j.cbegin() == k.cbegin(), std::domain_error); + CHECK_THROWS_NAME(j.begin() == k.begin(), std::domain_error, + "cannot compare iterators of different containers"); + CHECK_THROWS_NAME(j.cbegin() == k.cbegin(), std::domain_error, + "cannot compare iterators of different containers"); CHECK_THROWS_AS(j.begin() < k.begin(), std::domain_error); CHECK_THROWS_AS(j.cbegin() < k.cbegin(), std::domain_error); + CHECK_THROWS_NAME(j.begin() < k.begin(), std::domain_error, + "cannot compare iterators of different containers"); + CHECK_THROWS_NAME(j.cbegin() < k.cbegin(), std::domain_error, + "cannot compare iterators of different containers"); } } } @@ -5555,42 +5811,52 @@ TEST_CASE("iterators") { auto it = j_object.begin(); CHECK_THROWS_AS(it += 1, std::domain_error); + CHECK_THROWS_NAME(it += 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); CHECK_THROWS_AS(it += 1, std::domain_error); + CHECK_THROWS_NAME(it += 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.begin(); CHECK_THROWS_AS(it + 1, std::domain_error); + CHECK_THROWS_NAME(it + 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); CHECK_THROWS_AS(it + 1, std::domain_error); + CHECK_THROWS_NAME(it + 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.begin(); CHECK_THROWS_AS(it -= 1, std::domain_error); + CHECK_THROWS_NAME(it -= 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); CHECK_THROWS_AS(it -= 1, std::domain_error); + CHECK_THROWS_NAME(it -= 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.begin(); CHECK_THROWS_AS(it - 1, std::domain_error); + CHECK_THROWS_NAME(it - 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); CHECK_THROWS_AS(it - 1, std::domain_error); + CHECK_THROWS_NAME(it - 1, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.begin(); CHECK_THROWS_AS(it - it, std::domain_error); + CHECK_THROWS_NAME(it - it, std::domain_error, "cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); CHECK_THROWS_AS(it - it, std::domain_error); + CHECK_THROWS_NAME(it - it, std::domain_error, "cannot use offsets with object iterators"); } } @@ -6693,6 +6959,16 @@ TEST_CASE("modifiers") { json j = 1; CHECK_THROWS_AS(j.push_back("Hello"), std::domain_error); + + // exception name + try + { + j.push_back("Hello"); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } @@ -6722,6 +6998,16 @@ TEST_CASE("modifiers") json j = 1; json k("Hello"); CHECK_THROWS_AS(j.push_back(k), std::domain_error); + + // exception name + try + { + j.push_back(k); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } } @@ -6754,6 +7040,16 @@ TEST_CASE("modifiers") json j = 1; json k("Hello"); CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), std::domain_error); + + // exception name + try + { + j.push_back(k); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } } @@ -6785,6 +7081,16 @@ TEST_CASE("modifiers") { json j = 1; CHECK_THROWS_AS(j += "Hello", std::domain_error); + + // exception name + try + { + j += "Hello"; + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } @@ -6814,6 +7120,16 @@ TEST_CASE("modifiers") json j = 1; json k("Hello"); CHECK_THROWS_AS(j += k, std::domain_error); + + // exception name + try + { + j += k; + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } } @@ -6846,6 +7162,17 @@ TEST_CASE("modifiers") json j = 1; json k("Hello"); CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), std::domain_error); + + + // exception name + try + { + j += json::object_t::value_type({"one", 1}); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("cannot use push_back() with number")); + } } } } @@ -6982,6 +7309,25 @@ TEST_CASE("modifiers") CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), std::domain_error); CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), std::domain_error); + + // exception names + try + { + j_array.insert(j_array.end(), j_array.begin(), j_array.end()); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("passed iterators may not belong to container")); + } + + try + { + j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()); + } + catch (std::domain_error& e) + { + CHECK(e.what() == std::string("iterators do not fit")); + } } }