#include "simdjson.h" #include "test_ondemand.h" using namespace simdjson; namespace error_location_tests { bool array() { TEST_START(); auto json = R"( [1,2,3] )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); std::vector expected = {'1','2','3'}; std::vector expected_values = {1,2,3}; size_t count{0}; for (auto value : doc) { int64_t i; const char* c; // Must call current_location first because get_int64() will consume values ASSERT_SUCCESS(doc.current_location().get(c)); ASSERT_EQUAL(*c, expected[count]); ASSERT_SUCCESS(value.get_int64().get(i)); ASSERT_EQUAL(i, expected_values[count]); count++; } ASSERT_EQUAL(count,3); ASSERT_ERROR(doc.current_location(), OUT_OF_BOUNDS); TEST_SUCCEED(); } bool object() { TEST_START(); auto json = R"( {"a":1, "b":2, "c":3} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); std::vector expected = {'1','2','3'}; std::vector expected_values = {1,2,3}; size_t count{0}; for (auto field : doc.get_object()) { int64_t i; const char* c; // Must call current_location first because get_int64() will consume values ASSERT_SUCCESS(doc.current_location().get(c)); ASSERT_EQUAL(*c,expected[count]); ASSERT_SUCCESS(field.value().get(i)); ASSERT_EQUAL(i,expected_values[count]); count++; } ASSERT_EQUAL(count,3); ASSERT_ERROR(doc.current_location(), OUT_OF_BOUNDS); TEST_SUCCEED(); } bool json_pointer() { TEST_START(); auto json = R"( {"a": [1,2,[3,4,5]], "b": {"c": [1.2, 2.3]}} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; uint64_t i; ASSERT_SUCCESS(doc.at_pointer("/a/2/1").get(i)); ASSERT_EQUAL(i, 4); ASSERT_SUCCESS(doc.current_location().get(ptr)); std::string expected = ",5]], \"b\": {\"c\": [1.2, 2.3]}} "; ASSERT_EQUAL(std::string(ptr, expected.size()), expected); double d; ASSERT_SUCCESS(doc.at_pointer("/b/c/1").get(d)); ASSERT_EQUAL(d, 2.3); ASSERT_SUCCESS(doc.current_location().get(ptr)); expected = "]}} "; ASSERT_EQUAL(std::string(ptr, expected.size()), expected); TEST_SUCCEED(); } bool json_pointer_with_errors() { TEST_START(); auto json = R"( {"a": [1,2,[3 4,5]], "b": {"c": [1.2., 2.3]}} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; double d; ASSERT_ERROR(doc.at_pointer("/b/c/0").get(d), NUMBER_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); std::string expected = "1.2., 2.3]}} "; ASSERT_EQUAL(std::string(ptr, expected.size()), expected); uint64_t i; ASSERT_ERROR(doc.at_pointer("/a/2/1").get(i), TAPE_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); expected = "4,5]], \"b\": {\"c\": [1.2., 2.3]}} "; ASSERT_EQUAL(std::string(ptr, expected.size()), expected); TEST_SUCCEED(); } bool broken_json1() { TEST_START(); auto json = " \xc3\x94\xc3\xb8\xe2\x84\xa6{\"a\":1, 3} "_padded; ondemand::parser parser; ondemand::document doc; const char * ptr; ASSERT_SUCCESS(parser.iterate(json).get(doc)); ASSERT_ERROR(doc["a"], INCORRECT_TYPE); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(std::string(ptr, 18), "\xc3\x94\xc3\xb8\xe2\x84\xa6{\"a\":1, 3} "); TEST_SUCCEED(); } bool broken_json2() { TEST_START(); auto json = R"( [[[]] )"_padded; ondemand::parser parser; ondemand::document doc; ondemand::array arr; const char * ptr; ASSERT_SUCCESS(parser.iterate(json).get(doc)); ASSERT_SUCCESS(doc.get_array().get(arr)); ASSERT_ERROR(arr.count_elements(), TAPE_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(std::string(ptr - 2,2), "] "); TEST_SUCCEED(); } bool broken_json3() { TEST_START(); auto json = R"( [1 1.23, 2] )"_padded; ondemand::parser parser; ondemand::document doc; size_t count{0}; const char * ptr; ASSERT_SUCCESS(parser.iterate(json).get(doc)); for (auto val : doc) { if (count == 1) { ASSERT_ERROR(val, TAPE_ERROR); break; } count++; } ASSERT_EQUAL(count, 1); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(std::string(ptr, strlen("1.23, 2] ")), "1.23, 2] "); TEST_SUCCEED(); } bool broken_json4() { TEST_START(); auto json = R"( {"a":1, 3.5, "b":5} )"_padded; ondemand::parser parser; ondemand::document doc; const char * ptr; ASSERT_SUCCESS(parser.iterate(json).get(doc)); ASSERT_ERROR(doc["b"], TAPE_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(std::string(ptr, strlen("3.5, \"b\":5} ")), "3.5, \"b\":5} "); TEST_SUCCEED(); } bool incomplete_json() { TEST_START(); auto json = R"( [1,2,3 )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; for (auto val : doc) { ASSERT_ERROR(val, INCOMPLETE_ARRAY_OR_OBJECT); } ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(std::string(ptr, strlen("[1,2,3 ")), "[1,2,3 "); TEST_SUCCEED(); } bool boolean_error() { TEST_START(); auto json = R"( [tru, fals] )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); for (auto val : doc) { bool b; ASSERT_ERROR(val.get(b), INCORRECT_TYPE); } ASSERT_ERROR(doc.current_location(), OUT_OF_BOUNDS); TEST_SUCCEED(); } bool no_such_field() { TEST_START(); auto json = R"( {"a":5, "b":4} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); ASSERT_ERROR(doc["c"], NO_SUCH_FIELD); ASSERT_ERROR(doc.current_location(), OUT_OF_BOUNDS); TEST_SUCCEED(); } bool object_with_no_such_field() { TEST_START(); auto json = R"( {"a":5, "b":4} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; uint64_t i; ASSERT_SUCCESS(doc["a"].get(i)); ASSERT_EQUAL(i, 5); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(ptr, ", \"b\":4} "); ASSERT_ERROR(doc["c"], NO_SUCH_FIELD); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(ptr, ", \"b\":4} "); TEST_SUCCEED(); } bool number_parsing_error() { TEST_START(); auto json = R"( [13.34.514] )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; double d; ASSERT_ERROR(doc.at_pointer("/0").get_double().get(d), NUMBER_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(ptr, "13.34.514] "); TEST_SUCCEED(); } bool number_parsing_root_error() { TEST_START(); auto json = R"( 13.34.514 )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); const char * ptr; double d; ASSERT_ERROR(doc.get_double().get(d), NUMBER_ERROR); ASSERT_SUCCESS(doc.current_location().get(ptr)); ASSERT_EQUAL(ptr, "13.34.514 "); TEST_SUCCEED(); } bool current_location_in_value() { TEST_START(); auto json = R"( {"a": {"b": "c"}} )"_padded; ondemand::parser parser; ondemand::document doc; ASSERT_SUCCESS(parser.iterate(json).get(doc)); simdjson_result a = doc["a"]; ASSERT_SUCCESS(a); const char * ptr; ASSERT_SUCCESS(a.current_location().get(ptr)); ASSERT_EQUAL(ptr, R"({"b": "c"}} )"); simdjson_result b = a["b"]; ASSERT_SUCCESS(b); ASSERT_SUCCESS(b.current_location().get(ptr)); ASSERT_EQUAL(ptr, R"("c"}} )"); double d; ASSERT_ERROR(b.get_double().get(d), INCORRECT_TYPE); ASSERT_SUCCESS(b.current_location().get(ptr)); ASSERT_EQUAL(ptr, R"("c"}} )"); TEST_SUCCEED(); } bool run() { return array() && object() && json_pointer() && json_pointer_with_errors() && broken_json1() && broken_json2() && broken_json3() && broken_json4() && incomplete_json() && boolean_error() && no_such_field() && object_with_no_such_field() && number_parsing_error() && number_parsing_root_error() && current_location_in_value() && true; } } // namespace error_location_tests int main(int argc, char *argv[]) { return test_main(argc, argv, error_location_tests::run); }