From 9651efe626c4e9b70bc69f8226fa941d057793fe Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sat, 6 Feb 2021 11:07:14 -0800 Subject: [PATCH] Split up tests for compile times --- tests/ondemand/CMakeLists.txt | 27 +- tests/ondemand/ondemand_array_error_tests.cpp | 160 ++++ tests/ondemand/ondemand_error_tests.cpp | 835 ------------------ .../ondemand/ondemand_object_error_tests.cpp | 544 ++++++++++++ .../ondemand_wrong_type_error_tests.cpp | 177 ++++ 5 files changed, 896 insertions(+), 847 deletions(-) create mode 100644 tests/ondemand/ondemand_array_error_tests.cpp create mode 100644 tests/ondemand/ondemand_object_error_tests.cpp create mode 100644 tests/ondemand/ondemand_wrong_type_error_tests.cpp diff --git a/tests/ondemand/CMakeLists.txt b/tests/ondemand/CMakeLists.txt index a8039e93..49f34288 100644 --- a/tests/ondemand/CMakeLists.txt +++ b/tests/ondemand/CMakeLists.txt @@ -3,18 +3,21 @@ link_libraries(simdjson) include_directories(..) add_subdirectory(compilation_failure_tests) -add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_compilation_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_error_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_key_string_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_number_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_object_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation) -add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_array_error_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_compilation_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_error_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_key_string_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_number_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_object_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_object_error_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation) +add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation) if(HAVE_POSIX_FORK AND HAVE_POSIX_WAIT) # assert tests use fork and wait, which aren't on MSVC add_cpp_test(ondemand_assert_out_of_order_values LABELS assert per_implementation explicitonly ondemand) diff --git a/tests/ondemand/ondemand_array_error_tests.cpp b/tests/ondemand/ondemand_array_error_tests.cpp new file mode 100644 index 00000000..abec5b47 --- /dev/null +++ b/tests/ondemand/ondemand_array_error_tests.cpp @@ -0,0 +1,160 @@ +#include "simdjson.h" +#include "test_ondemand.h" + +using namespace simdjson; + +namespace array_error_tests { + using namespace std; + + template + bool assert_iterate(T array, V *expected, size_t N, simdjson::error_code *expected_error, size_t N2) { + size_t count = 0; + for (auto elem : std::forward(array)) { + V actual; + auto actual_error = elem.get(actual); + if (count >= N) { + if (count >= (N+N2)) { + std::cerr << "FAIL: Extra error reported: " << actual_error << std::endl; + return false; + } + ASSERT_ERROR(actual_error, expected_error[count - N]); + } else { + ASSERT_SUCCESS(actual_error); + ASSERT_EQUAL(actual, expected[count]); + } + count++; + } + ASSERT_EQUAL(count, N+N2); + return true; + } + + template + bool assert_iterate(T &array, V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate(array, expected, N, expected_error, N2); + } + + template + bool assert_iterate(T &array, simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate(array, nullptr, 0, expected_error, N2); + } + + template + bool assert_iterate(T &array, V (&&expected)[N]) { + return assert_iterate(array, expected, N, nullptr, 0); + } + + template + bool assert_iterate(T &&array, V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate(std::forward(array), expected, N, expected_error, N2); + } + + template + bool assert_iterate(T &&array, simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate(std::forward(array), nullptr, 0, expected_error, N2); + } + + template + bool assert_iterate(T &&array, V (&&expected)[N]) { + return assert_iterate(std::forward(array), expected, N, nullptr, 0); + } + + bool top_level_array_iterate_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing comma", "[1 1]", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR })); + ONDEMAND_SUBTEST("extra comma ", "[1,,1]", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("extra comma ", "[,]", assert_iterate(doc, { INCORRECT_TYPE })); + ONDEMAND_SUBTEST("extra comma ", "[,,]", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); + TEST_SUCCEED(); + } + bool top_level_array_iterate_unclosed_error() { + TEST_START(); + ONDEMAND_SUBTEST("unclosed extra comma", "[,", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", "[1 ", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR })); + // TODO These pass the user values that may run past the end of the buffer if they aren't careful + // In particular, if the padding is decorated with the wrong values, we could cause overrun! + ONDEMAND_SUBTEST("unclosed extra comma", "[,,", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", "[1,", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", "[1", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", "[", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR })); + TEST_SUCCEED(); + } + + bool array_iterate_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing comma", R"({ "a": [1 1] })", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR })); + ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,1] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE })); + ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,] })", assert_iterate(doc["a"], { INCORRECT_TYPE })); + ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,,] })", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); + TEST_SUCCEED(); + } + bool array_iterate_unclosed_error() { + TEST_START(); + ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,,)", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1 )", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR })); + // TODO These pass the user values that may run past the end of the buffer if they aren't careful + // In particular, if the padding is decorated with the wrong values, we could cause overrun! + ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1,)", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1)", assert_iterate(doc["a"], { NUMBER_ERROR, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed ", R"({ "a": [)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR })); + TEST_SUCCEED(); + } + +#ifndef SIMDJSON_PRODUCTION + bool out_of_order_array_iteration_error() { + TEST_START(); + auto json = R"([ [ 1, 2 ] ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + for (auto subelement : element) { ASSERT_SUCCESS(subelement); } + ASSERT_ERROR( element.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + ondemand::value val; + ASSERT_SUCCESS( element.get(val) ); + for (auto subelement : val) { ASSERT_SUCCESS(subelement); } + ASSERT_ERROR( val.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + auto arr = element.get_array(); + for (auto subelement : arr) { ASSERT_SUCCESS(subelement); } + ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + SUBTEST("array", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + ondemand::array arr; + ASSERT_SUCCESS( element.get(arr) ); + for (auto subelement : arr) { ASSERT_SUCCESS(subelement); } + ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + TEST_SUCCEED(); + } +#endif // SIMDJSON_PRODUCTION + + bool run() { + return + top_level_array_iterate_error() && + top_level_array_iterate_unclosed_error() && + array_iterate_error() && + array_iterate_unclosed_error() && +#ifndef SIMDJSON_PRODUCTION + out_of_order_array_iteration_error() && +#endif + true; + } +} + +int main(int argc, char *argv[]) { + return test_main(argc, argv, array_error_tests::run); +} diff --git a/tests/ondemand/ondemand_error_tests.cpp b/tests/ondemand/ondemand_error_tests.cpp index a652b7b1..da13a27b 100644 --- a/tests/ondemand/ondemand_error_tests.cpp +++ b/tests/ondemand/ondemand_error_tests.cpp @@ -14,390 +14,6 @@ namespace error_tests { TEST_SUCCEED(); } - namespace wrong_type { - -#define TEST_CAST_ERROR(JSON, TYPE, ERROR) \ - std::cout << "- Subtest: get_" << (#TYPE) << "() - JSON: " << (JSON) << std::endl; \ - if (!test_ondemand_doc((JSON##_padded), [&](auto doc_result) { \ - ASSERT_ERROR( doc_result.get_##TYPE(), (ERROR) ); \ - return true; \ - })) { \ - return false; \ - } \ - { \ - padded_string a_json(std::string(R"({ "a": )") + JSON + " })"); \ - std::cout << R"(- Subtest: get_)" << (#TYPE) << "() - JSON: " << a_json << std::endl; \ - if (!test_ondemand_doc(a_json, [&](auto doc_result) { \ - ASSERT_ERROR( doc_result["a"].get_##TYPE(), (ERROR) ); \ - return true; \ - })) { \ - return false; \ - }; \ - } - - bool wrong_type_array() { - TEST_START(); - TEST_CAST_ERROR("[]", object, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", double, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", string, INCORRECT_TYPE); - TEST_CAST_ERROR("[]", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_object() { - TEST_START(); - TEST_CAST_ERROR("{}", array, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", double, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", string, INCORRECT_TYPE); - TEST_CAST_ERROR("{}", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_true() { - TEST_START(); - TEST_CAST_ERROR("true", array, INCORRECT_TYPE); - TEST_CAST_ERROR("true", object, INCORRECT_TYPE); - TEST_CAST_ERROR("true", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("true", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("true", double, INCORRECT_TYPE); - TEST_CAST_ERROR("true", string, INCORRECT_TYPE); - TEST_CAST_ERROR("true", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_false() { - TEST_START(); - TEST_CAST_ERROR("false", array, INCORRECT_TYPE); - TEST_CAST_ERROR("false", object, INCORRECT_TYPE); - TEST_CAST_ERROR("false", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("false", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("false", double, INCORRECT_TYPE); - TEST_CAST_ERROR("false", string, INCORRECT_TYPE); - TEST_CAST_ERROR("false", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_null() { - TEST_START(); - TEST_CAST_ERROR("null", array, INCORRECT_TYPE); - TEST_CAST_ERROR("null", object, INCORRECT_TYPE); - TEST_CAST_ERROR("null", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("null", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("null", double, INCORRECT_TYPE); - TEST_CAST_ERROR("null", string, INCORRECT_TYPE); - TEST_CAST_ERROR("null", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_1() { - TEST_START(); - TEST_CAST_ERROR("1", array, INCORRECT_TYPE); - TEST_CAST_ERROR("1", object, INCORRECT_TYPE); - TEST_CAST_ERROR("1", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("1", string, INCORRECT_TYPE); - TEST_CAST_ERROR("1", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_negative_1() { - TEST_START(); - TEST_CAST_ERROR("-1", array, INCORRECT_TYPE); - TEST_CAST_ERROR("-1", object, INCORRECT_TYPE); - TEST_CAST_ERROR("-1", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("-1", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("-1", string, INCORRECT_TYPE); - TEST_CAST_ERROR("-1", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_float() { - TEST_START(); - TEST_CAST_ERROR("1.1", array, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", object, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", string, INCORRECT_TYPE); - TEST_CAST_ERROR("1.1", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_negative_int64_overflow() { - TEST_START(); - TEST_CAST_ERROR("-9223372036854775809", array, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", object, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", string, INCORRECT_TYPE); - TEST_CAST_ERROR("-9223372036854775809", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_int64_overflow() { - TEST_START(); - TEST_CAST_ERROR("9223372036854775808", array, INCORRECT_TYPE); - TEST_CAST_ERROR("9223372036854775808", object, INCORRECT_TYPE); - TEST_CAST_ERROR("9223372036854775808", bool, INCORRECT_TYPE); - // TODO BUG: this should be an error but is presently not - // TEST_CAST_ERROR("9223372036854775808", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("9223372036854775808", string, INCORRECT_TYPE); - TEST_CAST_ERROR("9223372036854775808", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool wrong_type_uint64_overflow() { - TEST_START(); - TEST_CAST_ERROR("18446744073709551616", array, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", object, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", bool, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", int64, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", uint64, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", string, INCORRECT_TYPE); - TEST_CAST_ERROR("18446744073709551616", raw_json_string, INCORRECT_TYPE); - TEST_SUCCEED(); - } - - bool run() { - return - wrong_type_1() && - wrong_type_array() && - wrong_type_false() && - wrong_type_float() && - wrong_type_int64_overflow() && - wrong_type_negative_1() && - wrong_type_negative_int64_overflow() && - wrong_type_null() && - wrong_type_object() && - wrong_type_true() && - wrong_type_uint64_overflow() && - true; - } - - } // namespace wrong_type - - template - bool assert_iterate(T array, V *expected, size_t N, simdjson::error_code *expected_error, size_t N2) { - size_t count = 0; - for (auto elem : std::forward(array)) { - V actual; - auto actual_error = elem.get(actual); - if (count >= N) { - if (count >= (N+N2)) { - std::cerr << "FAIL: Extra error reported: " << actual_error << std::endl; - return false; - } - ASSERT_ERROR(actual_error, expected_error[count - N]); - } else { - ASSERT_SUCCESS(actual_error); - ASSERT_EQUAL(actual, expected[count]); - } - count++; - } - ASSERT_EQUAL(count, N+N2); - return true; - } - - template - bool assert_iterate(T &array, V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate(array, expected, N, expected_error, N2); - } - - template - bool assert_iterate(T &array, simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate(array, nullptr, 0, expected_error, N2); - } - - template - bool assert_iterate(T &array, V (&&expected)[N]) { - return assert_iterate(array, expected, N, nullptr, 0); - } - - template - bool assert_iterate(T &&array, V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate(std::forward(array), expected, N, expected_error, N2); - } - - template - bool assert_iterate(T &&array, simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate(std::forward(array), nullptr, 0, expected_error, N2); - } - - template - bool assert_iterate(T &&array, V (&&expected)[N]) { - return assert_iterate(std::forward(array), expected, N, nullptr, 0); - } - - bool top_level_array_iterate_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing comma", "[1 1]", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR })); - ONDEMAND_SUBTEST("extra comma ", "[1,,1]", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("extra comma ", "[,]", assert_iterate(doc, { INCORRECT_TYPE })); - ONDEMAND_SUBTEST("extra comma ", "[,,]", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); - TEST_SUCCEED(); - } - bool top_level_array_iterate_unclosed_error() { - TEST_START(); - ONDEMAND_SUBTEST("unclosed extra comma", "[,", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", "[1 ", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR })); - // TODO These pass the user values that may run past the end of the buffer if they aren't careful - // In particular, if the padding is decorated with the wrong values, we could cause overrun! - ONDEMAND_SUBTEST("unclosed extra comma", "[,,", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", "[1,", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", "[1", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", "[", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR })); - TEST_SUCCEED(); - } - - bool array_iterate_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing comma", R"({ "a": [1 1] })", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR })); - ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,1] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE })); - ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,] })", assert_iterate(doc["a"], { INCORRECT_TYPE })); - ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,,] })", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); - TEST_SUCCEED(); - } - bool array_iterate_unclosed_error() { - TEST_START(); - ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,,)", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1 )", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR })); - // TODO These pass the user values that may run past the end of the buffer if they aren't careful - // In particular, if the padding is decorated with the wrong values, we could cause overrun! - ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1,)", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1)", assert_iterate(doc["a"], { NUMBER_ERROR, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed ", R"({ "a": [)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR })); - TEST_SUCCEED(); - } - - template - bool assert_iterate_object(T &&object, const char **expected_key, V *expected, size_t N, simdjson::error_code *expected_error, size_t N2) { - size_t count = 0; - for (auto field : object) { - V actual; - auto actual_error = field.value().get(actual); - if (count >= N) { - ASSERT((count - N) < N2, "Extra error reported"); - ASSERT_ERROR(actual_error, expected_error[count - N]); - } else { - ASSERT_SUCCESS(actual_error); - ASSERT_EQUAL(field.key().first, expected_key[count]); - ASSERT_EQUAL(actual, expected[count]); - } - count++; - } - ASSERT_EQUAL(count, N+N2); - return true; - } - - template - bool assert_iterate_object(T &&object, const char *(&&expected_key)[N], V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate_object(std::forward(object), expected_key, expected, N, expected_error, N2); - } - - template - bool assert_iterate_object(T &&object, simdjson::error_code (&&expected_error)[N2]) { - return assert_iterate_object(std::forward(object), nullptr, nullptr, 0, expected_error, N2); - } - - template - bool assert_iterate_object(T &&object, const char *(&&expected_key)[N], V (&&expected)[N]) { - return assert_iterate_object(std::forward(object), expected_key, expected, N, nullptr, 0); - } - - bool object_iterate_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); - TEST_SUCCEED(); - } - bool object_iterate_wrong_key_type_error() { - TEST_START(); - ONDEMAND_SUBTEST("wrong key type", R"({ 1: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("wrong key type", R"({ true: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("wrong key type", R"({ false: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("wrong key type", R"({ null: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("wrong key type", R"({ []: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("wrong key type", R"({ {}: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - TEST_SUCCEED(); - } - bool object_iterate_unclosed_error() { - TEST_START(); - ONDEMAND_SUBTEST("unclosed", R"({ "a": 1, )", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); - // TODO These next two pass the user a value that may run past the end of the buffer if they aren't careful. - // In particular, if the padding is decorated with the wrong values, we could cause overrun! - ONDEMAND_SUBTEST("unclosed", R"({ "a": 1 )", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - ONDEMAND_SUBTEST("unclosed", R"({ )", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); - TEST_SUCCEED(); - } - - bool object_lookup_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_error(doc["a"], TAPE_ERROR)); - ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_error(doc["a"], TAPE_ERROR)); - ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_success(doc["a"])); - ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_success(doc["a"])); - TEST_SUCCEED(); - } - bool object_lookup_unclosed_error() { - TEST_START(); - // TODO This one passes the user a value that may run past the end of the buffer if they aren't careful. - // In particular, if the padding is decorated with the wrong values, we could cause overrun! - ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_success(doc["a"])); - ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_error(doc["a"], TAPE_ERROR)); - ONDEMAND_SUBTEST("unclosed", R"({ )", assert_error(doc["a"], TAPE_ERROR)); - TEST_SUCCEED(); - } - - bool object_lookup_miss_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - TEST_SUCCEED(); - } - bool object_lookup_miss_wrong_key_type_error() { - TEST_START(); - ONDEMAND_SUBTEST("wrong key type", R"({ 1: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("wrong key type", R"({ true: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("wrong key type", R"({ false: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("wrong key type", R"({ null: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("wrong key type", R"({ []: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("wrong key type", R"({ {}: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); - TEST_SUCCEED(); - } - bool object_lookup_miss_unclosed_error() { - TEST_START(); - ONDEMAND_SUBTEST("unclosed", R"({ "a": 1, )", assert_error(doc["b"], TAPE_ERROR)); - // TODO These next two pass the user a value that may run past the end of the buffer if they aren't careful. - // In particular, if the padding is decorated with the wrong values, we could cause overrun! - ONDEMAND_SUBTEST("unclosed", R"({ "a": 1 )", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_error(doc["b"], TAPE_ERROR)); - ONDEMAND_SUBTEST("unclosed", R"({ )", assert_error(doc["b"], TAPE_ERROR)); - TEST_SUCCEED(); - } - bool object_lookup_miss_next_error() { - TEST_START(); - ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", ([&]() { - auto obj = doc.get_object(); - return assert_result(obj["a"], 1) && assert_error(obj["b"], TAPE_ERROR); - })()); - TEST_SUCCEED(); - } - bool get_fail_then_succeed_bool() { TEST_START(); auto json = R"({ "val" : true })"_padded; @@ -565,462 +181,11 @@ namespace error_tests { TEST_SUCCEED(); } -#ifndef SIMDJSON_PRODUCTION - bool out_of_order_array_iteration_error() { - TEST_START(); - auto json = R"([ [ 1, 2 ] ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - for (auto subelement : element) { ASSERT_SUCCESS(subelement); } - ASSERT_ERROR( element.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - ondemand::value val; - ASSERT_SUCCESS( element.get(val) ); - for (auto subelement : val) { ASSERT_SUCCESS(subelement); } - ASSERT_ERROR( val.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - auto arr = element.get_array(); - for (auto subelement : arr) { ASSERT_SUCCESS(subelement); } - ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - SUBTEST("array", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - ondemand::array arr; - ASSERT_SUCCESS( element.get(arr) ); - for (auto subelement : arr) { ASSERT_SUCCESS(subelement); } - ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_iteration_error() { - TEST_START(); - auto json = R"([ { "x": 1, "y": 2 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - auto obj = element.get_object(); - for (auto field : obj) { ASSERT_SUCCESS(field); } - ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - for (auto element : doc) { - ondemand::object obj; - ASSERT_SUCCESS( element.get(obj) ); - for (auto field : obj) { ASSERT_SUCCESS(field); } - ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION ); - } - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_index_child_error() { - TEST_START(); - auto json = R"([ { "x": 1, "y": 2 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element.get_object(); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element; - ASSERT_SUCCESS( obj["x"] ); - } - ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - ASSERT_SUCCESS( obj["x"] ); - } - ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_index_sibling_error() { - TEST_START(); - auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element.get_object(); - uint64_t x; - ASSERT_SUCCESS(obj["x"].get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::object obj; - ASSERT_SUCCESS( element.get_object().get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj["x"].get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element; - uint64_t x; - ASSERT_SUCCESS(obj["x"].get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::value obj; - ASSERT_SUCCESS( element.get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj["x"].get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_find_field_child_error() { - TEST_START(); - auto json = R"([ { "x": 1, "y": 2 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element.get_object(); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element; - ASSERT_SUCCESS( obj.find_field("x") ); - } - ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - ASSERT_SUCCESS( obj.find_field("x") ); - } - ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_find_field_sibling_error() { - TEST_START(); - auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element.get_object(); - uint64_t x; - ASSERT_SUCCESS(obj.find_field("x").get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::object obj; - ASSERT_SUCCESS( element.get_object().get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj.find_field("x").get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element; - uint64_t x; - ASSERT_SUCCESS(obj.find_field("x").get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::value obj; - ASSERT_SUCCESS( element.get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj.find_field("x").get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_find_field_unordered_child_error() { - TEST_START(); - auto json = R"([ { "x": 1, "y": 2 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element.get_object(); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - for (auto field : obj) { ASSERT_SUCCESS(field); } - } - ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result obj; - for (auto element : doc) { - obj = element; - ASSERT_SUCCESS( obj.find_field_unordered("x") ); - } - ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value obj; - for (auto element : doc) { - ASSERT_SUCCESS( element.get(obj) ); - ASSERT_SUCCESS( obj.find_field_unordered("x") ); - } - ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); - return true; - })); - TEST_SUCCEED(); - } - - bool out_of_order_object_find_field_unordered_sibling_error() { - TEST_START(); - auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element.get_object(); - uint64_t x; - ASSERT_SUCCESS(obj.find_field_unordered("x").get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { - ondemand::object last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::object obj; - ASSERT_SUCCESS( element.get_object().get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj.find_field_unordered("x").get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { - simdjson_result last_obj; - uint64_t i = 0; - for (auto element : doc) { - auto obj = element; - uint64_t x; - ASSERT_SUCCESS(obj.find_field_unordered("x").get(x)); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - - SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { - ondemand::value last_obj; - uint64_t i = 0; - for (auto element : doc) { - ondemand::value obj; - ASSERT_SUCCESS( element.get(obj) ); - uint64_t x; - ASSERT_SUCCESS( obj.find_field_unordered("x").get(x) ); - ASSERT_EQUAL(x, i); - if (i > 0) { - ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); - break; - } - last_obj = obj; - i++; - } - return true; - })); - TEST_SUCCEED(); - } -#endif - bool run() { return empty_document_error() && - top_level_array_iterate_error() && - top_level_array_iterate_unclosed_error() && - array_iterate_error() && - array_iterate_unclosed_error() && - wrong_type::run() && - object_iterate_error() && - object_iterate_wrong_key_type_error() && - object_iterate_unclosed_error() && - object_lookup_error() && - object_lookup_unclosed_error() && - object_lookup_miss_error() && - object_lookup_miss_unclosed_error() && - object_lookup_miss_wrong_key_type_error() && - object_lookup_miss_next_error() && get_fail_then_succeed_bool() && get_fail_then_succeed_null() && -#ifndef SIMDJSON_PRODUCTION - out_of_order_array_iteration_error() && - out_of_order_object_iteration_error() && - out_of_order_object_index_child_error() && - out_of_order_object_index_sibling_error() && - out_of_order_object_find_field_child_error() && - out_of_order_object_find_field_sibling_error() && - out_of_order_object_find_field_unordered_child_error() && - out_of_order_object_find_field_unordered_sibling_error() && -#endif true; } } diff --git a/tests/ondemand/ondemand_object_error_tests.cpp b/tests/ondemand/ondemand_object_error_tests.cpp new file mode 100644 index 00000000..58f1b3b6 --- /dev/null +++ b/tests/ondemand/ondemand_object_error_tests.cpp @@ -0,0 +1,544 @@ +#include "simdjson.h" +#include "test_ondemand.h" + +using namespace simdjson; + +namespace object_error_tests { + using namespace std; + + template + bool assert_iterate_object(T &&object, const char **expected_key, V *expected, size_t N, simdjson::error_code *expected_error, size_t N2) { + size_t count = 0; + for (auto field : object) { + V actual; + auto actual_error = field.value().get(actual); + if (count >= N) { + ASSERT((count - N) < N2, "Extra error reported"); + ASSERT_ERROR(actual_error, expected_error[count - N]); + } else { + ASSERT_SUCCESS(actual_error); + ASSERT_EQUAL(field.key().first, expected_key[count]); + ASSERT_EQUAL(actual, expected[count]); + } + count++; + } + ASSERT_EQUAL(count, N+N2); + return true; + } + + template + bool assert_iterate_object(T &&object, const char *(&&expected_key)[N], V (&&expected)[N], simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate_object(std::forward(object), expected_key, expected, N, expected_error, N2); + } + + template + bool assert_iterate_object(T &&object, simdjson::error_code (&&expected_error)[N2]) { + return assert_iterate_object(std::forward(object), nullptr, nullptr, 0, expected_error, N2); + } + + template + bool assert_iterate_object(T &&object, const char *(&&expected_key)[N], V (&&expected)[N]) { + return assert_iterate_object(std::forward(object), expected_key, expected, N, nullptr, 0); + } + + bool object_iterate_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); + TEST_SUCCEED(); + } + bool object_iterate_wrong_key_type_error() { + TEST_START(); + ONDEMAND_SUBTEST("wrong key type", R"({ 1: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("wrong key type", R"({ true: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("wrong key type", R"({ false: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("wrong key type", R"({ null: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("wrong key type", R"({ []: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("wrong key type", R"({ {}: 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + TEST_SUCCEED(); + } + bool object_iterate_unclosed_error() { + TEST_START(); + ONDEMAND_SUBTEST("unclosed", R"({ "a": 1, )", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); + // TODO These next two pass the user a value that may run past the end of the buffer if they aren't careful. + // In particular, if the padding is decorated with the wrong values, we could cause overrun! + ONDEMAND_SUBTEST("unclosed", R"({ "a": 1 )", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + ONDEMAND_SUBTEST("unclosed", R"({ )", assert_iterate_object(doc.get_object(), { TAPE_ERROR })); + TEST_SUCCEED(); + } + + bool object_lookup_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_error(doc["a"], TAPE_ERROR)); + ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_error(doc["a"], TAPE_ERROR)); + ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_success(doc["a"])); + ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_success(doc["a"])); + TEST_SUCCEED(); + } + bool object_lookup_unclosed_error() { + TEST_START(); + // TODO This one passes the user a value that may run past the end of the buffer if they aren't careful. + // In particular, if the padding is decorated with the wrong values, we could cause overrun! + ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_success(doc["a"])); + ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_error(doc["a"], TAPE_ERROR)); + ONDEMAND_SUBTEST("unclosed", R"({ )", assert_error(doc["a"], TAPE_ERROR)); + TEST_SUCCEED(); + } + + bool object_lookup_miss_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + TEST_SUCCEED(); + } + bool object_lookup_miss_wrong_key_type_error() { + TEST_START(); + ONDEMAND_SUBTEST("wrong key type", R"({ 1: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("wrong key type", R"({ true: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("wrong key type", R"({ false: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("wrong key type", R"({ null: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("wrong key type", R"({ []: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("wrong key type", R"({ {}: 1, "b": 2 })", assert_error(doc["b"], TAPE_ERROR)); + TEST_SUCCEED(); + } + bool object_lookup_miss_unclosed_error() { + TEST_START(); + ONDEMAND_SUBTEST("unclosed", R"({ "a": 1, )", assert_error(doc["b"], TAPE_ERROR)); + // TODO These next two pass the user a value that may run past the end of the buffer if they aren't careful. + // In particular, if the padding is decorated with the wrong values, we could cause overrun! + ONDEMAND_SUBTEST("unclosed", R"({ "a": 1 )", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_error(doc["b"], TAPE_ERROR)); + ONDEMAND_SUBTEST("unclosed", R"({ )", assert_error(doc["b"], TAPE_ERROR)); + TEST_SUCCEED(); + } + bool object_lookup_miss_next_error() { + TEST_START(); + ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", ([&]() { + auto obj = doc.get_object(); + return assert_result(obj["a"], 1) && assert_error(obj["b"], TAPE_ERROR); + })()); + TEST_SUCCEED(); + } + +#ifndef SIMDJSON_PRODUCTION + bool out_of_order_object_iteration_error() { + TEST_START(); + auto json = R"([ { "x": 1, "y": 2 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + auto obj = element.get_object(); + for (auto field : obj) { ASSERT_SUCCESS(field); } + ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + for (auto element : doc) { + ondemand::object obj; + ASSERT_SUCCESS( element.get(obj) ); + for (auto field : obj) { ASSERT_SUCCESS(field); } + ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION ); + } + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_index_child_error() { + TEST_START(); + auto json = R"([ { "x": 1, "y": 2 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element.get_object(); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element; + ASSERT_SUCCESS( obj["x"] ); + } + ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + ASSERT_SUCCESS( obj["x"] ); + } + ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION ); + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_index_sibling_error() { + TEST_START(); + auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element.get_object(); + uint64_t x; + ASSERT_SUCCESS(obj["x"].get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::object obj; + ASSERT_SUCCESS( element.get_object().get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj["x"].get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element; + uint64_t x; + ASSERT_SUCCESS(obj["x"].get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::value obj; + ASSERT_SUCCESS( element.get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj["x"].get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj["x"].get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_find_field_child_error() { + TEST_START(); + auto json = R"([ { "x": 1, "y": 2 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element.get_object(); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element; + ASSERT_SUCCESS( obj.find_field("x") ); + } + ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + ASSERT_SUCCESS( obj.find_field("x") ); + } + ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_find_field_sibling_error() { + TEST_START(); + auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element.get_object(); + uint64_t x; + ASSERT_SUCCESS(obj.find_field("x").get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::object obj; + ASSERT_SUCCESS( element.get_object().get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj.find_field("x").get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element; + uint64_t x; + ASSERT_SUCCESS(obj.find_field("x").get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::value obj; + ASSERT_SUCCESS( element.get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj.find_field("x").get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_find_field_unordered_child_error() { + TEST_START(); + auto json = R"([ { "x": 1, "y": 2 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element.get_object(); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + for (auto field : obj) { ASSERT_SUCCESS(field); } + } + ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result obj; + for (auto element : doc) { + obj = element; + ASSERT_SUCCESS( obj.find_field_unordered("x") ); + } + ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value obj; + for (auto element : doc) { + ASSERT_SUCCESS( element.get(obj) ); + ASSERT_SUCCESS( obj.find_field_unordered("x") ); + } + ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION ); + return true; + })); + TEST_SUCCEED(); + } + + bool out_of_order_object_find_field_unordered_sibling_error() { + TEST_START(); + auto json = R"([ { "x": 0, "y": 2 }, { "x": 1, "y": 4 } ])"_padded; + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element.get_object(); + uint64_t x; + ASSERT_SUCCESS(obj.find_field_unordered("x").get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("object", test_ondemand_doc(json, [&](auto doc) { + ondemand::object last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::object obj; + ASSERT_SUCCESS( element.get_object().get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj.find_field_unordered("x").get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("simdjson_result", test_ondemand_doc(json, [&](auto doc) { + simdjson_result last_obj; + uint64_t i = 0; + for (auto element : doc) { + auto obj = element; + uint64_t x; + ASSERT_SUCCESS(obj.find_field_unordered("x").get(x)); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + + SUBTEST("value", test_ondemand_doc(json, [&](auto doc) { + ondemand::value last_obj; + uint64_t i = 0; + for (auto element : doc) { + ondemand::value obj; + ASSERT_SUCCESS( element.get(obj) ); + uint64_t x; + ASSERT_SUCCESS( obj.find_field_unordered("x").get(x) ); + ASSERT_EQUAL(x, i); + if (i > 0) { + ASSERT_ERROR(last_obj.find_field_unordered("x").get(x), OUT_OF_ORDER_ITERATION); + break; + } + last_obj = obj; + i++; + } + return true; + })); + TEST_SUCCEED(); + } +#endif + + bool run() { + return + object_iterate_error() && + object_iterate_wrong_key_type_error() && + object_iterate_unclosed_error() && + object_lookup_error() && + object_lookup_unclosed_error() && + object_lookup_miss_error() && + object_lookup_miss_unclosed_error() && + object_lookup_miss_wrong_key_type_error() && + object_lookup_miss_next_error() && +#ifndef SIMDJSON_PRODUCTION + out_of_order_object_iteration_error() && + out_of_order_object_index_child_error() && + out_of_order_object_index_sibling_error() && + out_of_order_object_find_field_child_error() && + out_of_order_object_find_field_sibling_error() && + out_of_order_object_find_field_unordered_child_error() && + out_of_order_object_find_field_unordered_sibling_error() && +#endif + true; + } +} // namespace object_error_tests + +int main(int argc, char *argv[]) { + return test_main(argc, argv, object_error_tests::run); +} diff --git a/tests/ondemand/ondemand_wrong_type_error_tests.cpp b/tests/ondemand/ondemand_wrong_type_error_tests.cpp new file mode 100644 index 00000000..1d38506c --- /dev/null +++ b/tests/ondemand/ondemand_wrong_type_error_tests.cpp @@ -0,0 +1,177 @@ +#include "simdjson.h" +#include "test_ondemand.h" + +using namespace simdjson; + +namespace wrong_type_error_tests { + using namespace std; + +#define TEST_CAST_ERROR(JSON, TYPE, ERROR) \ + std::cout << "- Subtest: get_" << (#TYPE) << "() - JSON: " << (JSON) << std::endl; \ + if (!test_ondemand_doc((JSON##_padded), [&](auto doc_result) { \ + ASSERT_ERROR( doc_result.get_##TYPE(), (ERROR) ); \ + return true; \ + })) { \ + return false; \ + } \ + { \ + padded_string a_json(std::string(R"({ "a": )") + JSON + " })"); \ + std::cout << R"(- Subtest: get_)" << (#TYPE) << "() - JSON: " << a_json << std::endl; \ + if (!test_ondemand_doc(a_json, [&](auto doc_result) { \ + ASSERT_ERROR( doc_result["a"].get_##TYPE(), (ERROR) ); \ + return true; \ + })) { \ + return false; \ + }; \ + } + + bool wrong_type_array() { + TEST_START(); + TEST_CAST_ERROR("[]", object, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", double, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", string, INCORRECT_TYPE); + TEST_CAST_ERROR("[]", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_object() { + TEST_START(); + TEST_CAST_ERROR("{}", array, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", double, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", string, INCORRECT_TYPE); + TEST_CAST_ERROR("{}", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_true() { + TEST_START(); + TEST_CAST_ERROR("true", array, INCORRECT_TYPE); + TEST_CAST_ERROR("true", object, INCORRECT_TYPE); + TEST_CAST_ERROR("true", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("true", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("true", double, INCORRECT_TYPE); + TEST_CAST_ERROR("true", string, INCORRECT_TYPE); + TEST_CAST_ERROR("true", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_false() { + TEST_START(); + TEST_CAST_ERROR("false", array, INCORRECT_TYPE); + TEST_CAST_ERROR("false", object, INCORRECT_TYPE); + TEST_CAST_ERROR("false", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("false", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("false", double, INCORRECT_TYPE); + TEST_CAST_ERROR("false", string, INCORRECT_TYPE); + TEST_CAST_ERROR("false", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_null() { + TEST_START(); + TEST_CAST_ERROR("null", array, INCORRECT_TYPE); + TEST_CAST_ERROR("null", object, INCORRECT_TYPE); + TEST_CAST_ERROR("null", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("null", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("null", double, INCORRECT_TYPE); + TEST_CAST_ERROR("null", string, INCORRECT_TYPE); + TEST_CAST_ERROR("null", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_1() { + TEST_START(); + TEST_CAST_ERROR("1", array, INCORRECT_TYPE); + TEST_CAST_ERROR("1", object, INCORRECT_TYPE); + TEST_CAST_ERROR("1", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("1", string, INCORRECT_TYPE); + TEST_CAST_ERROR("1", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_negative_1() { + TEST_START(); + TEST_CAST_ERROR("-1", array, INCORRECT_TYPE); + TEST_CAST_ERROR("-1", object, INCORRECT_TYPE); + TEST_CAST_ERROR("-1", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("-1", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("-1", string, INCORRECT_TYPE); + TEST_CAST_ERROR("-1", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_float() { + TEST_START(); + TEST_CAST_ERROR("1.1", array, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", object, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", string, INCORRECT_TYPE); + TEST_CAST_ERROR("1.1", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_negative_int64_overflow() { + TEST_START(); + TEST_CAST_ERROR("-9223372036854775809", array, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", object, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", string, INCORRECT_TYPE); + TEST_CAST_ERROR("-9223372036854775809", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_int64_overflow() { + TEST_START(); + TEST_CAST_ERROR("9223372036854775808", array, INCORRECT_TYPE); + TEST_CAST_ERROR("9223372036854775808", object, INCORRECT_TYPE); + TEST_CAST_ERROR("9223372036854775808", bool, INCORRECT_TYPE); + // TODO BUG: this should be an error but is presently not + // TEST_CAST_ERROR("9223372036854775808", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("9223372036854775808", string, INCORRECT_TYPE); + TEST_CAST_ERROR("9223372036854775808", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool wrong_type_uint64_overflow() { + TEST_START(); + TEST_CAST_ERROR("18446744073709551616", array, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", object, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", bool, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", int64, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", uint64, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", string, INCORRECT_TYPE); + TEST_CAST_ERROR("18446744073709551616", raw_json_string, INCORRECT_TYPE); + TEST_SUCCEED(); + } + + bool run() { + return + wrong_type_1() && + wrong_type_array() && + wrong_type_false() && + wrong_type_float() && + wrong_type_int64_overflow() && + wrong_type_negative_1() && + wrong_type_negative_int64_overflow() && + wrong_type_null() && + wrong_type_object() && + wrong_type_true() && + wrong_type_uint64_overflow() && + true; + } + +} // namespace wrong_type_error_tests + +int main(int argc, char *argv[]) { + return test_main(argc, argv, wrong_type_error_tests::run); +}