mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
59025bc8b1
* Avoiding the issue where doc.get_value().get_object() differs from doc.get_object() in how errors are reported. * Minor tweaks
289 lines
9.8 KiB
C++
289 lines
9.8 KiB
C++
#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<char> expected = {'1','2','3'};
|
|
std::vector<int64_t> 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<char> expected = {'1','2','3'};
|
|
std::vector<int64_t> 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<ondemand::value> a = doc["a"];
|
|
ASSERT_SUCCESS(a);
|
|
const char * ptr;
|
|
ASSERT_SUCCESS(a.current_location().get(ptr));
|
|
ASSERT_EQUAL(ptr, R"({"b": "c"}} )");
|
|
simdjson_result<ondemand::value> 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);
|
|
} |