use of com.linkedin.data.schema.validator.Validator in project rest.li by linkedin.
the class TestPatchFilterValidator method testPatchFilterValidator.
@Test
public void testPatchFilterValidator() throws IOException {
String schemaText = "{\n" + " \"type\" : \"record\",\n" + " \"name\" : \"Foo\",\n" + " \"fields\" : [\n" + " { \"name\" : \"fooInt\", \"type\" : \"int\", \"optional\" : true },\n" + " { \"name\" : \"fooString\", \"type\" : \"string\", \"optional\" : true },\n" + " {\n" + " \"name\" : \"bar\",\n" + " \"type\" : {\n" + " \"type\" : \"record\",\n" + " \"name\" : \"Bar\",\n" + " \"fields\" : [\n" + " { \"name\" : \"barInt\", \"type\" : \"int\", \"optional\" : true },\n" + " { \"name\" : \"barString\", \"type\" : \"string\", \"optional\" : true },\n" + " {\n" + " \"name\" : \"baz\",\n" + " \"type\" : {\n" + " \"type\" : \"record\",\n" + " \"name\" : \"Baz\",\n" + " \"fields\" : [\n" + " { \"name\" : \"bazInt\", \"type\" : \"int\", \"optional\" : true },\n" + " { \"name\" : \"bazString\", \"type\" : \"string\", \"optional\" : true }\n" + " ]\n" + " },\n" + " \"optional\" : true\n" + " }\n" + " ]\n" + " },\n" + " \"optional\" : true\n" + " }\n" + " ]\n" + "}\n";
Object[][] inputs = { // }
{ // deleted /fooInt
"{ }", "{ \"$delete\" : [ \"fooInt\" ] }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, ""), asList(Mode.ANCESTOR_AND_SET, "") }, { // must not call validator for parents and ancestors not modified
"{ \"fooString\" : \"excluded\", \"bar\" : { \"barInt\" : -1 } }", "{ \"$delete\" : [ \"fooInt\" ] }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, ""), asList(Mode.ANCESTOR_AND_SET, "") }, { // deleted /bar/barInt
"{ \"bar\" : { } }", "{ \"bar\" : { \"$delete\" : [ \"barInt\" ] } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar"), asList(Mode.ANCESTOR_AND_SET, "", "/bar") }, { // must not call validator for parents and ancestors not modified
"{ \"fooInt\" : -1, \"fooString\" : \"excluded\", \"bar\" : { } }", "{ \"bar\" : { \"$delete\" : [ \"barInt\" ] } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar"), asList(Mode.ANCESTOR_AND_SET, "", "/bar") }, { // deleted /bar/baz/bazInt
"{ \"bar\" : { \"baz\" : { } } }", "{ \"bar\" : { \"baz\" : { \"$delete\" : [ \"bazInt\" ] } } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar/baz"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz") }, { // must not call validator for parents and ancestors not modified
"{ \"fooInt\" : -1, \"fooString\" : \"excluded\", \"bar\" : { \"barInt\" : -1, \"baz\" : { } } }", "{ \"bar\" : { \"baz\" : { \"$delete\" : [ \"bazInt\" ] } } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar/baz"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz") }, { // deleted /bar/baz
"{ \"bar\" : { } }", "{ \"bar\" : { \"$delete\" : [ \"baz\" ] } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar"), asList(Mode.ANCESTOR_AND_SET, "", "/bar") }, { // must not call validator for parents and ancestors not modified
"{ \"fooInt\" : -1, \"fooString\" : \"excluded\", \"bar\" : { \"barInt\" : -1 } }", "{ \"bar\" : { \"$delete\" : [ \"baz\" ] } }", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET, "/bar"), asList(Mode.ANCESTOR_AND_SET, "", "/bar") }, { // set /fooInt (set field in root record)
"{ \"fooInt\" : 2 }", "{ \"$set\" : { \"fooInt\" : 2 } }", "", asList(Mode.SET_ONLY, "/fooInt"), asList(Mode.PARENT_AND_SET, "", "/fooInt"), asList(Mode.ANCESTOR_AND_SET, "", "/fooInt") }, { // must not call validator for parents and ancestors not modified
"{ \"fooInt\" : 2, \"fooString\" : \"excluded\", \"bar\" : { \"baz\" : { } } }", "{ \"$set\" : { \"fooInt\" : 2 } }", "", asList(Mode.SET_ONLY, "/fooInt"), asList(Mode.PARENT_AND_SET, "", "/fooInt"), asList(Mode.ANCESTOR_AND_SET, "", "/fooInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excluded\",\n" + " \"bar\" : {\n" + " \"barInt\" : 2,\n" + " \"barString\" : \"excluded\",\n" + " \"baz\" : {}\n" + " }\n" + "}", "{ \"bar\" : { \"$set\" : { \"barInt\" : 2 } } }", "", asList(Mode.SET_ONLY, "/bar/barInt"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/barInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/barInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : -1,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"barString\" : \"x\",\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"excludes\"\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"$set\" : { \"barString\" : \"x\" } } }", "", asList(Mode.SET_ONLY, "/bar/barString"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/barString"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/barString") }, { // set /bar/baz/bazInt (set field in nested grandchild record)
"{ \"bar\" : { \"baz\" : { \"bazInt\" : 2 } } }", "{ \"bar\" : { \"baz\" : { \"$set\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excluded\",\n" + " \"bar\" : {\n" + " \"barInt\" : 2,\n" + " \"barString\" : \"excluded\",\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"excluded\"\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"baz\" : { \"$set\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : -1,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"excludes\"\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"baz\" : { \"$set\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // set /bar (set record in root record)
"{ \"bar\" : { \"baz\" : { \"bazInt\" : 2 } } }", "{ \"$set\" : { \"bar\" : { \"baz\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar", "/bar/baz", "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excluded\",\n" + " \"bar\" : {\n" + " \"baz\" : {\n" + " \"bazInt\" : 2\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"baz\" : { \"$set\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // set /bar/baz (set record in nested child record)
"{ \"bar\" : { \"baz\" : { \"bazInt\" : 2 } } }", "{ \"bar\" : { \"$set\" : { \"baz\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excluded\",\n" + " \"bar\" : {\n" + " \"barInt\" : 2,\n" + " \"barString\" : \"excluded\",\n" + " \"baz\" : {\n" + " \"bazInt\" : 2\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"$set\" : { \"baz\" : { \"bazInt\" : 2 } } } }", "", asList(Mode.SET_ONLY, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call validator for parents and ancestors not modified
"{\n" + " \"fooInt\" : -1,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"barString\" : \"excludes\",\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "{ \"bar\" : { \"$set\" : { \"baz\" : { \"bazInt\" : 2, \"bazString\" : \"x\" } } } }", "", asList(Mode.SET_ONLY, "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString") }, { // set /fooInt, /fooString (set multiple fields in root record)
"{ \"fooInt\" : 2, \"fooString\" : \"x\" }", "{ \"$set\" : { \"fooInt\" : 2, \"fooString\" : \"x\" } }", "", asList(Mode.SET_ONLY, "/fooInt", "/fooString"), asList(Mode.PARENT_AND_SET, "", "/fooInt", "/fooString"), asList(Mode.ANCESTOR_AND_SET, "", "/fooInt", "/fooString") }, { // set /bar/barInt, /bar/barString (set multiple fields in nested child record)
"{ \"bar\" : { \"barInt\" : 2, \"barString\" : \"x\" } }", "{ \"bar\" : { \"$set\" : { \"barInt\" : 2, \"barString\" : \"x\" } } }", "", asList(Mode.SET_ONLY, "/bar/barInt", "/bar/barString"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/barInt", "/bar/barString"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/barInt", "/bar/barString") }, { // set /bar/baz/bazInt, /bar/baz/bazString (set multiple fields in nested grandchild record)
"{ \"bar\" : { \"baz\" : { \"bazInt\" : 2, \"bazString\" : \"x\" } } }", "{ \"bar\" : { \"baz\" : { \"$set\" : { \"bazInt\" : 2, \"bazString\" : \"x\" } } } }", "", asList(Mode.SET_ONLY, "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString") }, { // set /fooInt, /bar/barInt, /bar/baz/bazInt
"{\n" + " \"fooInt\" : 2,\n" + " \"bar\" : {\n" + " \"barInt\" : 2,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2\n" + " }\n" + " }\n" + "}", "{\n" + " \"$set\" : { \"fooInt\" : 2 },\n" + " \"bar\" : {\n" + " \"$set\" : { \"barInt\" : 2 },\n" + " \"baz\" : {\n" + " \"$set\" : { \"bazInt\" : 2 }\n" + " }\n" + " }\n" + "}", "", asList(Mode.SET_ONLY, "/fooInt", "/bar/barInt", "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "", "/fooInt", "/bar", "/bar/barInt", "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/fooInt", "/bar", "/bar/barInt", "/bar/baz", "/bar/baz/bazInt") }, { // nothing set
"{\n" + " \"fooInt\" : -1,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : -1,\n" + " \"bazString\" : \"excludes\"\n" + " }\n" + " }\n" + "}", "{}", "", asList(Mode.SET_ONLY), asList(Mode.PARENT_AND_SET), asList(Mode.ANCESTOR_AND_SET) }, { // must not call next validator for /fooString, /bar/barInt
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "{\n" + " \"$set\" : { \"fooInt\" : 2 },\n" + " \"bar\" : {\n" + " \"$set\" : {\n" + " \"baz\" : { \"bazInt\" : 2, \"bazString\" : \"x\" }\n" + " }\n" + " }\n" + "}", "", asList(Mode.SET_ONLY, "/fooInt", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.PARENT_AND_SET, "", "/fooInt", "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.ANCESTOR_AND_SET, "", "/fooInt", "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString") }, { // must not call next validator for /fooInt, /fooString, /bar/barInt
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "{\n" + " \"$set\" : {\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "/bar", asList(Mode.SET_ONLY, "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.PARENT_AND_SET, "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt", "/bar/baz/bazString") }, { // must not call next validator for /fooInt, /fooString, /bar/barInt
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "{\n" + " \"baz\" : {\n" + " \"$set\" : {\n" + " \"bazInt\" : 2\n" + " }\n" + " }\n" + "}", "/bar", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") }, { // must not call next validator for /fooInt, /fooString, /bar/barInt
"{\n" + " \"fooInt\" : 2,\n" + " \"fooString\" : \"excludes\",\n" + " \"bar\" : {\n" + " \"barInt\" : -1,\n" + " \"baz\" : {\n" + " \"bazInt\" : 2,\n" + " \"bazString\" : \"x\"\n" + " }\n" + " }\n" + "}", "{\n" + " \"$set\" : { \"bazInt\" : 2 }\n" + "}", "/bar/baz", asList(Mode.SET_ONLY, "/bar/baz/bazInt"), asList(Mode.PARENT_AND_SET, "/bar/baz", "/bar/baz/bazInt"), asList(Mode.ANCESTOR_AND_SET, "", "/bar", "/bar/baz", "/bar/baz/bazInt") } };
DataSchema schema = dataSchemaFromString(schemaText);
ValidationOptions options = new ValidationOptions(RequiredMode.CAN_BE_ABSENT_IF_HAS_DEFAULT, CoercionMode.NORMAL);
for (Object[] row : inputs) {
String value = (String) row[0];
String patch = (String) row[1];
String patchPath = (String) row[2];
DataMap valueMap = dataMapFromString(value);
DataMap opMap = dataMapFromString(patch);
if (debug) {
out.println("Value: " + value);
out.println("Patch: " + patch);
if (patchPath.isEmpty() == false)
out.println("PatchPath: " + patchPath);
}
for (int i = 3; i < row.length; i++) {
VisitedValidator visitedValidator = new VisitedValidator();
@SuppressWarnings("unchecked") List<Object> check = (List<Object>) row[i];
Mode mode = (Mode) check.get(0);
Validator validator;
if (patchPath.isEmpty()) {
validator = new PatchFilterValidator(visitedValidator, opMap, mode);
} else {
DataElement patchElement = DataElementUtil.element(valueMap, schema, patchPath);
assertNotSame(patchElement, null);
validator = new PatchFilterValidator(visitedValidator, opMap, mode, patchElement);
}
ValidationResult result = ValidateDataAgainstSchema.validate(valueMap, schema, options, validator);
if (debug) {
out.println("Mode: " + mode);
out.print("Result: " + result);
out.println("VisitedPaths: " + visitedValidator._visitedPaths);
}
assertTrue(result.isValid());
for (int j = 1; j < check.size(); j++) {
assertTrue(visitedValidator._visitedPaths.contains(check.get(j)));
}
assertEquals(visitedValidator._visitedPaths.size(), check.size() - 1);
}
}
}
use of com.linkedin.data.schema.validator.Validator in project rest.li by linkedin.
the class TestRestLiValidation method testCustomValidatorMap.
@Test
public void testCustomValidatorMap() {
// Provide Rest.li annotations manually since the validator is not called from the server or through generated request builders.
Map<String, List<String>> annotations = new HashMap<>();
annotations.put("createOnly", Arrays.asList("stringB", "intB", "UnionFieldWithInlineRecord/com.linkedin.restli.examples.greetings.api.myRecord/foo2", "MapWithTyperefs/*/id"));
annotations.put("readOnly", Arrays.asList("stringA", "intA", "UnionFieldWithInlineRecord/com.linkedin.restli.examples.greetings.api.myRecord/foo1", "ArrayWithInlineRecord/*/bar1", "validationDemoNext/stringB", "validationDemoNext/UnionFieldWithInlineRecord"));
// Invalid entity, because intB is not a multiple of seven.
ValidationDemo.UnionFieldWithInlineRecord unionField1 = new ValidationDemo.UnionFieldWithInlineRecord();
unionField1.setMyEnum(myEnum.FOOFOO);
ValidationDemo entity = new ValidationDemo().setIntB(24).setStringB("some string").setUnionFieldWithInlineRecord(unionField1);
// Validate without the class map
RestLiDataValidator validator = new RestLiDataValidator(annotations, ValidationDemo.class, ResourceMethod.CREATE);
ValidationResult result = validator.validateInput(entity);
Assert.assertTrue(result.isValid());
// Validate with the class map
Map<String, Class<? extends Validator>> validatorClassMap = new HashMap<>();
validatorClassMap.put("seven", SevenValidator.class);
validator = new RestLiDataValidator(annotations, ValidationDemo.class, ResourceMethod.CREATE, validatorClassMap);
result = validator.validateInput(entity);
Assert.assertFalse(result.isValid());
Assert.assertEquals(result.getMessages().size(), 1);
for (Message message : result.getMessages()) {
Assert.assertTrue(message.toString().contains("24 is not a multiple of seven"));
}
}
Aggregations