Skip to content

Commit

Permalink
test some more error pathways
Browse files Browse the repository at this point in the history
  • Loading branch information
paleolimbot committed Nov 27, 2023
1 parent d295735 commit 77f95dd
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/nanoarrow/nanoarrow_testing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,14 +669,18 @@ class TestingJSONReader {

const auto& fields = value["fields"];
NANOARROW_RETURN_NOT_OK(
Check(fields.is_array(), error, "Field fields must be array"));
Check(fields.is_array(), error, "Schema fields must be array"));
NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowSchemaAllocateChildren(schema, fields.size()),
error);
for (int64_t i = 0; i < schema->n_children; i++) {
NANOARROW_RETURN_NOT_OK(SetField(schema->children[i], fields[i], error));
}

NANOARROW_RETURN_NOT_OK(SetMetadata(schema, value["metadata"], error));

// Validate!
ArrowSchemaView schema_view;
NANOARROW_RETURN_NOT_OK(ArrowSchemaViewInit(&schema_view, schema, error));
return NANOARROW_OK;
}

Expand Down
63 changes: 63 additions & 0 deletions src/nanoarrow/nanoarrow_testing_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,12 @@ TEST(NanoarrowTestingTest, NanoarrowTestingTestReadSchema) {
EXPECT_STREQ(schema->format, "+s");
ASSERT_EQ(schema->n_children, 1);
EXPECT_STREQ(schema->children[0]->format, "n");

// Check invalid JSON
EXPECT_EQ(reader.ReadSchema(R"({)", schema.get()), EINVAL);

// Check at least one failed Check()
EXPECT_EQ(reader.ReadSchema(R"("this is not a JSON object")", schema.get()), EINVAL);
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestReadFieldBasic) {
Expand Down Expand Up @@ -683,6 +689,19 @@ TEST(NanoarrowTestingTest, NanoarrowTestingTestReadFieldBasic) {
schema.get()),
NANOARROW_OK);
EXPECT_STREQ(schema->name, "colname");

// Check invalid JSON
EXPECT_EQ(reader.ReadField(R"({)", schema.get()), EINVAL);

// Check at least one failed Check()
EXPECT_EQ(reader.ReadField(R"("this is not a JSON object")", schema.get()), EINVAL);

// Check that field is validated
EXPECT_EQ(
reader.ReadField(
R"({"name": null, "nullable": true, "type": {"name": "fixedsizebinary", "byteWidth": -1}, "children": [], "metadata": null})",
schema.get()),
EINVAL);
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestReadFieldMetadata) {
Expand Down Expand Up @@ -750,33 +769,65 @@ void TestTypeRoundtrip(const std::string& type_json) {
TestFieldRoundtrip(field_json_builder.str());
}

void TestFieldError(const std::string& field_json, const std::string& msg,
int code = EINVAL) {
nanoarrow::UniqueSchema schema;
TestingJSONReader reader;
ArrowError error;
error.message[0] = '\0';

EXPECT_EQ(reader.ReadField(field_json, schema.get(), &error), code);
EXPECT_EQ(std::string(error.message), msg);
}

void TestTypeError(const std::string& type_json, const std::string& msg,
int code = EINVAL) {
std::stringstream field_json_builder;
field_json_builder << R"({"name": null, "nullable": true, "type": )" << type_json
<< R"(, "children": [], "metadata": null})";
TestFieldError(field_json_builder.str(), msg, code);
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldPrimitive) {
TestTypeRoundtrip(R"({"name": "null"})");
TestTypeRoundtrip(R"({"name": "bool"})");
TestTypeRoundtrip(R"({"name": "utf8"})");
TestTypeRoundtrip(R"({"name": "largeutf8"})");
TestTypeRoundtrip(R"({"name": "binary"})");
TestTypeRoundtrip(R"({"name": "largebinary"})");

TestTypeError(R"({"name": "an unsupported type"})",
"Unsupported Type name: 'an unsupported type'", ENOTSUP);
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldInt) {
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 8, "isSigned": true})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 16, "isSigned": true})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 32, "isSigned": true})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 64, "isSigned": true})");

TestTypeError(R"({"name": "int", "bitWidth": 1, "isSigned": true})",
"Type[name=='int'] bitWidth must be 8, 16, 32, or 64");
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldUInt) {
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 8, "isSigned": false})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 16, "isSigned": false})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 32, "isSigned": false})");
TestTypeRoundtrip(R"({"name": "int", "bitWidth": 64, "isSigned": false})");

TestTypeError(R"({"name": "int", "bitWidth": 1, "isSigned": false})",
"Type[name=='int'] bitWidth must be 8, 16, 32, or 64");
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldFloatingPoint) {
TestTypeRoundtrip(R"({"name": "floatingpoint", "precision": "HALF"})");
TestTypeRoundtrip(R"({"name": "floatingpoint", "precision": "SINGLE"})");
TestTypeRoundtrip(R"({"name": "floatingpoint", "precision": "DOUBLE"})");

TestTypeError(
R"({"name": "floatingpoint", "precision": "NOT_A_PRECISION"})",
"Type[name=='floatingpoint'] precision must be 'HALF', 'SINGLE', or 'DOUBLE'");
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldFixedSizeBinary) {
Expand All @@ -788,6 +839,9 @@ TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldDecimal) {
R"({"name": "decimal", "bitWidth": 128, "precision": 10, "scale": 3})");
TestTypeRoundtrip(
R"({"name": "decimal", "bitWidth": 256, "precision": 10, "scale": 3})");

TestTypeError(R"({"name": "decimal", "bitWidth": 123, "precision": 10, "scale": 3})",
"Type[name=='decimal'] bitWidth must be 128 or 256");
}

TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldMap) {
Expand Down Expand Up @@ -823,4 +877,13 @@ TEST(NanoarrowTestingTest, NanoarrowTestingTestFieldUnion) {
R"({"name": null, "nullable": true, "type": {"name": "null"}, "children": [], "metadata": null}, )"
R"({"name": null, "nullable": true, "type": {"name": "utf8"}, "children": [], "metadata": null})"
R"(], "metadata": null})");

TestFieldRoundtrip(
R"({"name": null, "nullable": true, "type": {"name": "union", "mode": "SPARSE", "typeIds": [10,20]}, "children": [)"
R"({"name": null, "nullable": true, "type": {"name": "null"}, "children": [], "metadata": null}, )"
R"({"name": null, "nullable": true, "type": {"name": "utf8"}, "children": [], "metadata": null})"
R"(], "metadata": null})");

TestTypeError(R"({"name": "union", "mode": "NOT_A_MODE", "typeIds": []})",
"Type[name=='union'] mode must be 'DENSE' or 'SPARSE'");
}

0 comments on commit 77f95dd

Please sign in to comment.