use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidator method testValidator.
public void testValidator(String schemaText, Object[][] input, Map<String, Class<? extends Validator>> validatorClassMap, String[] validatorCheckStrings, int tests) throws IOException, InstantiationException {
DataSchema schema = dataSchemaFromString(schemaText);
DataSchemaAnnotationValidator annotationValidator = new DataSchemaAnnotationValidator();
annotationValidator.init(schema, validatorClassMap);
if (debug)
annotationValidator.setDebugMode(true);
String annotationValidatorString = annotationValidator.toString();
if (debug)
out.println(annotationValidator);
for (String checkString : validatorCheckStrings) {
assertTrue(annotationValidatorString.contains(checkString));
}
for (Object[] row : input) {
DataMap value = (DataMap) row[0];
try {
if ((tests & SCHEMA_VALIDATOR) != 0) {
VisitedTrackingValidator visitedValidator = new VisitedTrackingValidator(annotationValidator);
ValidationOptions validationOptions = new ValidationOptions(RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.NORMAL);
ValidationResult result = ValidateDataAgainstSchema.validate(value.copy(), schema, validationOptions, visitedValidator);
checkValidationResult(value, result, row, visitedValidator);
}
if ((tests & OBJECT_VALIDATOR) != 0) {
VisitedTrackingValidator visitedValidator = new VisitedTrackingValidator(annotationValidator);
ValidationOptions validationOptions = new ValidationOptions();
ValidationResult result = ValidateDataAgainstSchema.validate(value.copy(), schema, validationOptions, visitedValidator);
checkValidationResult(value, result, row, visitedValidator);
}
} catch (CloneNotSupportedException e) {
throw new IllegalStateException("unexpected exception", e);
}
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidation method testNonRootStartDataElement.
@Test
public void testNonRootStartDataElement() throws IOException {
String schemaText = "{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " { \"name\" : \"intField\", \"type\" : \"int\", \"optional\" : true },\n" + " { \"name\" : \"stringField\", \"type\" : \"string\", \"optional\" : true },\n" + " { \"name\" : \"arrayField\", \"type\" : { \"type\" : \"array\", \"items\" : \"Foo\" }, \"optional\" : true },\n" + " { \"name\" : \"mapField\", \"type\" : { \"type\" : \"map\", \"values\" : \"Foo\" }, \"optional\" : true },\n" + " { \"name\" : \"unionField\", \"type\" : [ \"int\", \"string\", \"Foo\" ], \"optional\" : true },\n" + " { \"name\" : \"fooField\", \"type\" : \"Foo\", \"optional\" : true }\n" + " ]\n" + "}\n";
String[] empty = {};
Object[][] input = { { "{ \"intField\" : \"bad\", \"fooField\" : { \"intField\" : 32 } }", "/fooField", empty, new String[] { "ERROR" } }, { "{ \"intField\" : 32, \"fooField\" : { \"intField\" : \"bad\" } }", "/fooField", new String[] { "ERROR", "/fooField/intField" }, empty }, { "{\n" + " \"stringField\" : 32,\n" + " \"arrayField\" : [ { \"intField\" : \"bad0\" }, { \"intField\" : \"bad1\" } ]\n" + "}\n", "/arrayField/0", new String[] { "ERROR", "/arrayField/0/intField" }, new String[] { "/stringField", "/arrayField/1/intField" } }, { "{\n" + " \"stringField\" : 32,\n" + " \"mapField\" : { \"m0\" : { \"intField\" : \"bad0\" }, \"m1\" : { \"intField\" : \"bad1\" } }\n" + "}\n", "/mapField/m1", new String[] { "ERROR", "/mapField/m1/intField" }, new String[] { "/stringField", "/mapField/m0/intField" } }, { "{\n" + " \"stringField\" : 32,\n" + " \"arrayField\" : [\n" + " { \"unionField\" : { \"Foo\" : { \"intField\" : \"bad0\" } } },\n" + " { \"unionField\" : { \"int\" : \"bad1\" } }\n" + " ]\n" + "}\n", "/arrayField/0/unionField", new String[] { "ERROR", "/arrayField/0/unionField/Foo/intField" }, new String[] { "/stringField", "/arrayField/1/unionField/int" } }, { "{\n" + " \"stringField\" : 32,\n" + " \"fooField\" : {\n" + " \"stringField\" : 45,\n" + " \"fooField\" : { \"intField\" : \"bad1\" } }\n" + " }\n" + "}\n", "/fooField/fooField", new String[] { "ERROR", "/fooField/fooField/intField" }, new String[] { "/stringField", "/fooField/stringField" } } };
DataSchema schema = dataSchemaFromString(schemaText);
for (Object[] row : input) {
String dataString = (String) row[0];
String startPath = (String) row[1];
String[] expectedStrings = (String[]) row[2];
String[] notExpectedStrings = (String[]) row[3];
DataMap map = dataMapFromString(dataString);
DataElement startElement = DataElementUtil.element(map, schema, startPath);
Assert.assertNotSame(startElement, null);
ValidationResult result = validate(startElement, new ValidationOptions());
String message = result.getMessages().toString();
for (String expected : expectedStrings) {
Assert.assertTrue(message.contains(expected), message + " does not contain " + expected);
}
for (String notExpected : notExpectedStrings) {
Assert.assertFalse(message.contains(notExpected), message + " contains " + notExpected);
}
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidation method testValidationWithNormalCoercion.
@Test
public void testValidationWithNormalCoercion() throws IOException, CloneNotSupportedException {
String schemaText = "{ \"type\" : \"record\", \"name\" : \"foo\", \"fields\" : \n" + "[ { \"name\" : \"bar\", \"type\" : { \"name\" : \"barType\", \"type\" : \"record\", \"fields\" : [ \n" + "{ \"name\" : \"boolean\", \"type\" : \"boolean\", \"optional\" : true }, \n" + "{ \"name\" : \"int\", \"type\" : \"int\", \"optional\" : true }, \n" + "{ \"name\" : \"long\", \"type\" : \"long\", \"optional\" : true }, \n" + "{ \"name\" : \"float\", \"type\" : \"float\", \"optional\" : true }, \n" + "{ \"name\" : \"double\", \"type\" : \"double\", \"optional\" : true }, \n" + "{ \"name\" : \"string\", \"type\" : \"string\", \"optional\" : true }, \n" + "{ \"name\" : \"bytes\", \"type\" : \"bytes\", \"optional\" : true }, \n" + "{ \"name\" : \"array\", \"type\" : { \"type\" : \"array\", \"items\" : \"int\" }, \"optional\" : true }, \n" + "{ \"name\" : \"enum\", \"type\" : { \"type\" : \"enum\", \"name\" : \"enumType\", \"symbols\" : [ \"apple\", \"orange\", \"banana\" ] }, \"optional\" : true }, \n" + "{ \"name\" : \"fixed\", \"type\" : { \"type\" : \"fixed\", \"name\" : \"fixedType\", \"size\" : 4 }, \"optional\" : true }, \n" + "{ \"name\" : \"map\", \"type\" : { \"type\" : \"map\", \"values\" : \"int\" }, \"optional\" : true }, \n" + "{ \"name\" : \"record\", \"type\" : { \"type\" : \"record\", \"name\" : \"recordType\", \"fields\" : [ { \"name\" : \"int\", \"type\" : \"int\" } ] }, \"optional\" : true }, \n" + "{ \"name\" : \"union\", \"type\" : [ \"int\", \"recordType\", \"enumType\", \"fixedType\" ], \"optional\" : true }, \n" + "{ \"name\" : \"unionWithNull\", \"type\" : [ \"null\", \"enumType\", \"fixedType\" ], \"optional\" : true } \n" + "] } } ] }";
String key = "bar";
DataSchema schema = dataSchemaFromString(schemaText);
Object[][][] input = { { { new ValidationOptions(RequiredMode.IGNORE), new ValidationOptions(RequiredMode.MUST_BE_PRESENT), new ValidationOptions(RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT), new ValidationOptions(RequiredMode.FIXUP_ABSENT_WITH_DEFAULT) }, // int
{ new DataMap(asMap("int", 1L)), new DataMap(asMap("int", 1)) }, { new DataMap(asMap("int", 1.0f)), new DataMap(asMap("int", 1)) }, { new DataMap(asMap("int", 1.0)), new DataMap(asMap("int", 1)) }, // long
{ new DataMap(asMap("long", 1)), new DataMap(asMap("long", 1L)) }, { new DataMap(asMap("long", 1.0f)), new DataMap(asMap("long", 1L)) }, { new DataMap(asMap("long", 1.0)), new DataMap(asMap("long", 1L)) }, // float
{ new DataMap(asMap("float", 1)), new DataMap(asMap("float", 1.0f)) }, { new DataMap(asMap("float", 1L)), new DataMap(asMap("float", 1.0f)) }, { new DataMap(asMap("float", 1.0)), new DataMap(asMap("float", 1.0f)) }, // double
{ new DataMap(asMap("double", 1)), new DataMap(asMap("double", 1.0)) }, { new DataMap(asMap("double", 1L)), new DataMap(asMap("double", 1.0)) }, { new DataMap(asMap("double", 1.0f)), new DataMap(asMap("double", 1.0)) }, // array of int's
{ new DataMap(asMap("array", new DataList(asList(1, 2, 3, 1.0, 2.0, 3.0, 1.0f, 2.0f, 3.0f, 1.0, 2.0, 3.0)))), new DataMap(asMap("array", new DataList(asList(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)))) }, // map of int's
{ new DataMap(asMap("map", new DataMap(asMap("int1", 1, "long", 1L, "float", 1.0f, "double", 1.0)))), new DataMap(asMap("map", new DataMap(asMap("int1", 1, "long", 1, "float", 1, "double", 1)))) }, // record with int fields
{ new DataMap(asMap("record", new DataMap(asMap("int", 1L)))), new DataMap(asMap("record", new DataMap(asMap("int", 1)))) }, { new DataMap(asMap("record", new DataMap(asMap("int", 1.0f)))), new DataMap(asMap("record", new DataMap(asMap("int", 1)))) }, { new DataMap(asMap("record", new DataMap(asMap("int", 1.0)))), new DataMap(asMap("record", new DataMap(asMap("int", 1)))) }, // union with int
{ new DataMap(asMap("union", new DataMap(asMap("int", 1L)))), new DataMap(asMap("union", new DataMap(asMap("int", 1)))) }, { new DataMap(asMap("union", new DataMap(asMap("int", 1.0f)))), new DataMap(asMap("union", new DataMap(asMap("int", 1)))) }, { new DataMap(asMap("union", new DataMap(asMap("int", 1.0)))), new DataMap(asMap("union", new DataMap(asMap("int", 1)))) }, // union with record containing int
{ new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1L)))))), new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1)))))) }, { new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1.0f)))))), new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1)))))) }, { new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1.0)))))), new DataMap(asMap("union", new DataMap(asMap("recordType", new DataMap(asMap("int", 1)))))) } } };
testValidationWithNormalCoercion(schema, key, input);
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidation method testDisallowUnrecognizedFieldsWithAvroUnionDefault.
@Test
public void testDisallowUnrecognizedFieldsWithAvroUnionDefault() throws IOException {
ValidationOptions options = new ValidationOptions(RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.NORMAL, UnrecognizedFieldMode.DISALLOW);
options.setAvroUnionMode(true);
String schemaText = "{\n" + " \"name\" : \"Foo\",\n" + " \"type\" : \"record\",\n" + " \"fields\" : [\n" + " { \"name\" : \"primitive\", \"type\" : \"int\", \"optional\" : true },\n" + " { \"name\" : \"unionField\", \"type\" : [ \"Foo\", \"int\", \"string\" ], \"optional\" : true },\n" + " { \"name\" : \"arrayField\", \"type\" : { \"type\" : \"array\", \"items\" : \"Foo\" }, \"optional\" : true },\n" + " { \"name\" : \"mapField\", \"type\" : { \"type\" : \"map\", \"values\" : \"Foo\" }, \"optional\" : true },\n" + " { \"name\" : \"recordField\", \"type\" : \"Foo\", \"optional\" : true }\n" + " ]\n" + "}\n";
DataSchema schema = dataSchemaFromString(schemaText);
String dataString = "{\n" + " \"unionField\" : { \"primitive\": 1, \"unrecognizedInMap\": -1 },\n" + " \"arrayField\" : [ { \"unrecognizedInArray\": -2 }],\n" + " \"mapField\" : { \"key1\": { \"unrecognizedInMap\": -3 }},\n" + " \"recordField\" : { \"unrecognizedInRecord\": -4 }\n" + "}";
DataMap toValidate = dataMapFromString(dataString);
ValidationResult result = validate(toValidate, schema, options);
Assert.assertFalse(result.isValid());
String message = result.getMessages().toString();
Assert.assertEquals(result.getMessages().size(), 4);
String[] expectedStrings = new String[] { "/unionField/unrecognizedInMap :: unrecognized field found", "/arrayField/0/unrecognizedInArray :: unrecognized field found", "/mapField/key1/unrecognizedInMap :: unrecognized field found", "/recordField/unrecognizedInRecord :: unrecognized field found" };
for (String expected : expectedStrings) {
Assert.assertTrue(message.contains(expected), message + " does not contain " + expected);
}
}
use of com.linkedin.data.schema.DataSchema in project rest.li by linkedin.
the class TestValidation method testValidationWithDifferentValidationOptions.
public void testValidationWithDifferentValidationOptions(String schemaText, String key, Object[][][] goodInput, Object[][][] badInput) throws IOException {
final String[][] emptyErrorPaths = {};
DataSchema schema = dataSchemaFromString(schemaText);
Assert.assertTrue(schema != null);
DataMap map = new DataMap();
for (Object[][] rows : goodInput) {
Object[] modes = rows[0];
Object[] dataObjects = rows[1];
for (Object mode : modes) {
ValidationOptions validationOptions = (ValidationOptions) mode;
for (Object dataObject : dataObjects) {
map.put(key, dataObject);
ValidationResult result = validate(map, schema, validationOptions);
Assert.assertTrue(result.isValid());
if (result.hasFix() == false) {
Assert.assertSame(map, result.getFixed());
}
}
}
}
for (Object[][] rows : badInput) {
Object[] modes = rows[0];
Object[] dataObjects = rows[1];
String expectedString = (String) rows[2][0];
String[][] errorPaths = rows.length > 4 ? (String[][]) rows[3] : emptyErrorPaths;
for (Object mode : modes) {
ValidationOptions validationOptions = (ValidationOptions) mode;
int index = 0;
for (Object dataObject : dataObjects) {
map.put(key, dataObject);
ValidationResult result = validate(map, schema, validationOptions);
Assert.assertFalse(result.isValid());
Assert.assertSame(map, result.getFixed());
checkMessages(result.getMessages(), expectedString);
if (index < errorPaths.length) {
checkMessagesErrorPath(result.getMessages(), errorPaths[index]);
}
index++;
}
}
}
}
Aggregations