use of com.linkedin.data.schema.annotation.SchemaAnnotationHandler.AnnotationCompatibilityResult in project rest.li by linkedin.
the class TestAnnotationCompatibilityChecker method testCheckCompatibility.
@Test(dataProvider = "annotationCompatibilityCheckTestData")
public void testCheckCompatibility(String prevSchemaFile, String currSchemaFile, List<SchemaAnnotationHandler> handlers, List<AnnotationCompatibilityResult> expectedResults) throws IOException {
DataSchema prevSchema = TestUtil.dataSchemaFromPdlInputStream(getClass().getResourceAsStream(prevSchemaFile));
DataSchema currSchema = TestUtil.dataSchemaFromPdlInputStream(getClass().getResourceAsStream(currSchemaFile));
List<AnnotationCompatibilityResult> results = AnnotationCompatibilityChecker.checkPegasusSchemaAnnotation(prevSchema, currSchema, handlers);
Assert.assertEquals(results.size(), expectedResults.size());
for (int i = 0; i < results.size(); i++) {
Assert.assertEquals(results.get(i).getMessages().size(), expectedResults.get(i).getMessages().size());
List<CompatibilityMessage> actualCompatibilityMessage = (List<CompatibilityMessage>) results.get(i).getMessages();
List<CompatibilityMessage> expectCompatibilityMessage = (List<CompatibilityMessage>) expectedResults.get(i).getMessages();
for (int j = 0; j < actualCompatibilityMessage.size(); j++) {
Assert.assertEquals(actualCompatibilityMessage.get(j).toString(), expectCompatibilityMessage.get(j).toString());
}
}
}
use of com.linkedin.data.schema.annotation.SchemaAnnotationHandler.AnnotationCompatibilityResult in project rest.li by linkedin.
the class TestAnnotationCompatibilityChecker method annotationCompatibilityCheckTestData.
@DataProvider
private Object[][] annotationCompatibilityCheckTestData() throws IOException {
// Set up expected result: both previous schema and current schema contain the same PathSpecs.
CompatibilityCheckContext checkContext = generateAnnotationCheckContext(new PathSpec("TestSchema1/field1/$field"));
CompatibilityCheckContext checkContext1 = generateAnnotationCheckContext(new PathSpec("TestSchema1/field2/$field"));
AnnotationCompatibilityResult expectResultWithCompatibleChange1 = generateExpectResult(new CompatibilityMessage(checkContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Updating annotation field \"%s\" value is backward compatible change", ANNOTATION_FIELD_NAME));
AnnotationCompatibilityResult expectResultWithInCompatibleChange1 = generateExpectResult(new CompatibilityMessage(checkContext1.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Deleting existed annotation \"%s\" is backward incompatible change", BAR_ANNOTATION_NAMESPACE));
// Set up expected result: only previous schema contains the resolvedProperty with the same annotation namespace as SchemaAnnotationHandler
CompatibilityCheckContext checkContext2 = generateAnnotationCheckContext(new PathSpec("TestSchema2/field1/$field"));
AnnotationCompatibilityResult expectResult2 = generateExpectResult(new CompatibilityMessage(checkContext2.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Adding new annotation \"%s\" is backward compatible change", BAR_ANNOTATION_NAMESPACE));
// Set up expected result: only current schema contains the resolvedProperty with the same annotation namespace as SchemaAnnotationHandler
CompatibilityCheckContext checkContext3 = generateAnnotationCheckContext(new PathSpec("TestSchema3/field1/$field"));
AnnotationCompatibilityResult expectResult3 = generateExpectResult(new CompatibilityMessage(checkContext3.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Deleting existed annotation \"%s\" is backward incompatible change", BAR_ANNOTATION_NAMESPACE));
// Set up expected results: multiple handlers.
CompatibilityCheckContext checkContext4 = generateAnnotationCheckContext(new PathSpec("TestSchema4/field1/$field"));
AnnotationCompatibilityResult barHandlerExpectResult = generateExpectResult(new CompatibilityMessage(checkContext4.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Adding new annotation \"%s\" is backward compatible change", BAR_ANNOTATION_NAMESPACE));
AnnotationCompatibilityResult bazHandlerExpectResult = generateExpectResult(new CompatibilityMessage(checkContext4.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Updating annotation field \"%s\" value is backward compatible change", ANNOTATION_FIELD_NAME));
// Set up expected results: field has annotation, field type schema also has annotation.
AnnotationCompatibilityResult fieldAnnotationResult = new AnnotationCompatibilityResult();
CompatibilityCheckContext checkContext5 = generateAnnotationCheckContext(new PathSpec("TestSchema5/field1"));
AnnotationCompatibilityResult fieldTypeSchemaAnnotationResult = generateExpectResult(new CompatibilityMessage(checkContext5.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Updating annotation field \"%s\" value is backward compatible change", ANNOTATION_FIELD_NAME));
// Set up expected results: field has annotation, field type schema also has annotation.
CompatibilityCheckContext unionMemberKeyCheckContext = generateAnnotationCheckContext(new PathSpec("TestSchema6/field1/u1/$unionMemberKey"));
AnnotationCompatibilityResult unionMemberKeyAnnotationResult = generateExpectResult(new CompatibilityMessage(unionMemberKeyCheckContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Updating annotation field \"%s\" value is backward compatible change", ANNOTATION_FIELD_NAME));
CompatibilityCheckContext unionMemberSchemaCheckContext = generateAnnotationCheckContext(new PathSpec("TestSchema6/field1/u1"));
AnnotationCompatibilityResult unionMemberSchemaAnnotationResult = generateExpectResult(new CompatibilityMessage(unionMemberSchemaCheckContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Updating annotation field \"%s\" value is backward compatible change", ANNOTATION_FIELD_NAME));
// Set up expected result: an extension annotation field value is updated.
CompatibilityCheckContext schoolContext = generateAnnotationCheckContext(new PathSpec("SchoolExtensions/testField/$field"));
AnnotationCompatibilityResult schoolExtensionExpectResult = generateExpectResult(new CompatibilityMessage(schoolContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Updating extension annotation field: \"%s\" value is considering as a backward incompatible change.", "using"));
// Set up expected result: an extension annotation field is removed.
CompatibilityCheckContext fruitContext = generateAnnotationCheckContext(new PathSpec("FruitExtensions/testField/$field"));
AnnotationCompatibilityResult fruitExtensionExpectResult = generateExpectResult(new CompatibilityMessage(fruitContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Removing extension annotation field: \"%s\" is considering as a backward incompatible change.", "params"));
// Set up expected result: a new field with annotation is added.
CompatibilityCheckContext fooContext = generateAnnotationCheckContext(new PathSpec("FooExtensions/barField/$field"));
AnnotationCompatibilityResult fooExtensionExpectResult = generateExpectResult(new CompatibilityMessage(fooContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_COMPATIBLE_CHANGE, "Adding extension annotation on new field: \"%s\" is backward compatible change", "barField"));
// Existing fields annotations do not change, checkCompatibility will return an empty result.
AnnotationCompatibilityResult emptyResult = new AnnotationCompatibilityResult();
// Set up expected result: an extension annotation is removed.
CompatibilityCheckContext albumContext = generateAnnotationCheckContext(new PathSpec("AlbumExtensions/testField/$field"));
AnnotationCompatibilityResult albumExtensionExpectResult = generateExpectResult(new CompatibilityMessage(albumContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Removing extension annotation is a backward incompatible change.", ""));
// Set up expected result: an extension annotation is removed.
CompatibilityCheckContext companyContext = generateAnnotationCheckContext(new PathSpec("CompanyExtensions/testField/$field"));
AnnotationCompatibilityResult companyExtensionExpectResult = generateExpectResult(new CompatibilityMessage(companyContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Adding extension annotation field: \"%s\" is a backward incompatible change.", "using"));
// Set up expected result: a field with extension annotation is removed.
CompatibilityCheckContext bookContext = generateAnnotationCheckContext(new PathSpec("BookExtensions/testField/$field"));
AnnotationCompatibilityResult bookExtensionExpectResult = generateExpectResult(new CompatibilityMessage(bookContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Removing field: \"%s\" with extension annotation is a backward incompatible change.", "testField"));
// Set up expected result: adding extension annotation on an existing field
CompatibilityCheckContext jobContext = generateAnnotationCheckContext(new PathSpec("JobExtensions/testField/$field"));
AnnotationCompatibilityResult jobExtensionExpectResult = generateExpectResult(new CompatibilityMessage(jobContext.getPathSpecToSchema(), CompatibilityMessage.Impact.ANNOTATION_INCOMPATIBLE_CHANGE, "Adding extension annotation on an existing field: \"%s\" is backward incompatible change", "testField"));
return new Object[][] { { "previousSchema/TestSchema1.pdl", "currentSchema/TestSchema1.pdl", Collections.singletonList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE)), Arrays.asList(expectResultWithCompatibleChange1, expectResultWithInCompatibleChange1) }, { "previousSchema/TestSchema2.pdl", "currentSchema/TestSchema2.pdl", Collections.singletonList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE)), Collections.singletonList(expectResult2) }, { "previousSchema/TestSchema3.pdl", "currentSchema/TestSchema3.pdl", Collections.singletonList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE)), Collections.singletonList(expectResult3) }, { "previousSchema/TestSchema4.pdl", "currentSchema/TestSchema4.pdl", Arrays.asList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE), generateSchemaAnnotationHandler(BAZ_ANNOTATION_NAMESPACE)), Arrays.asList(barHandlerExpectResult, bazHandlerExpectResult) }, { "previousSchema/TestSchema5.pdl", "currentSchema/TestSchema5.pdl", Arrays.asList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE), generateSchemaAnnotationHandler(BAZ_ANNOTATION_NAMESPACE)), Arrays.asList(fieldAnnotationResult, fieldTypeSchemaAnnotationResult) }, { "previousSchema/TestSchema6.pdl", "currentSchema/TestSchema6.pdl", Arrays.asList(generateSchemaAnnotationHandler(BAR_ANNOTATION_NAMESPACE), generateSchemaAnnotationHandler(BAZ_ANNOTATION_NAMESPACE)), Arrays.asList(unionMemberSchemaAnnotationResult, unionMemberKeyAnnotationResult) }, { "previousSchema/SchoolExtensions.pdl", "currentSchema/SchoolExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(schoolExtensionExpectResult) }, { "previousSchema/FruitExtensions.pdl", "currentSchema/FruitExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(fruitExtensionExpectResult) }, { "previousSchema/FooExtensions.pdl", "currentSchema/FooExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Arrays.asList(emptyResult, fooExtensionExpectResult) }, { "previousSchema/AlbumExtensions.pdl", "currentSchema/AlbumExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(albumExtensionExpectResult) }, { "previousSchema/CompanyExtensions.pdl", "currentSchema/CompanyExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(companyExtensionExpectResult) }, { "previousSchema/BookExtensions.pdl", "currentSchema/BookExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Arrays.asList(bookExtensionExpectResult, emptyResult) }, { "previousSchema/JobExtensions.pdl", "currentSchema/JobExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(jobExtensionExpectResult) }, { "previousSchema/IdentityExtensions.pdl", "currentSchema/IdentityExtensions.pdl", Collections.singletonList(new ExtensionSchemaAnnotationHandler()), Collections.singletonList(emptyResult) } };
}
use of com.linkedin.data.schema.annotation.SchemaAnnotationHandler.AnnotationCompatibilityResult in project rest.li by linkedin.
the class AnnotationCompatibilityChecker method getCompatibilityResult.
/**
* Iterate the nodeToResolverPropertiesMap, if a node's resolvedProperty contains the same annotationNamespace as SchemaAnnotationHandler,
* calling annotationCompatibilityCheck api which is provided in the SchemaAnnotationHandler to do the annotation compatibility check.
*/
private static List<AnnotationCompatibilityResult> getCompatibilityResult(Map<PathSpec, Pair<CompatibilityCheckContext, Map<String, Object>>> prevResolvedPropertiesMap, Map<PathSpec, Pair<CompatibilityCheckContext, Map<String, Object>>> currResolvedPropertiesMap, List<SchemaAnnotationHandler> handlers) {
List<AnnotationCompatibilityResult> results = new ArrayList<>();
prevResolvedPropertiesMap.forEach((pathSpec, prevCheckContextAndResolvedProperty) -> {
Map<String, Object> prevResolvedProperties = prevCheckContextAndResolvedProperty.getValue();
handlers.forEach(handler -> {
String annotationNamespace = handler.getAnnotationNamespace();
if (currResolvedPropertiesMap.containsKey(pathSpec)) {
// If previous schema node and current schema node have the same pathSpec,
// they may or may not contain the same annotation namespace as SchemaAnnotationHandler, we need to check further.
Pair<CompatibilityCheckContext, Map<String, Object>> currCheckContextAndResolvedProperty = currResolvedPropertiesMap.get(pathSpec);
Map<String, Object> currResolvedProperties = currCheckContextAndResolvedProperty.getValue();
// we do the annotation check.
if (prevResolvedProperties.containsKey(annotationNamespace) || currResolvedProperties.containsKey(annotationNamespace)) {
AnnotationCompatibilityResult result = handler.checkCompatibility(prevResolvedProperties, currResolvedProperties, prevCheckContextAndResolvedProperty.getKey(), currCheckContextAndResolvedProperty.getKey());
results.add(result);
}
} else {
if (prevResolvedProperties.containsKey(annotationNamespace)) {
// prevResolvedPropertiesMap has a pathSpec which the newResolvedPropertiesMap does not have,
// it means an existing field is removed.
// pass an empty currResolvedPropertiesMap and empty currAnnotationContext to the annotation check.
AnnotationCompatibilityResult result = handler.checkCompatibility(prevResolvedProperties, new HashMap<>(), prevCheckContextAndResolvedProperty.getKey(), new CompatibilityCheckContext());
results.add(result);
}
}
});
if (currResolvedPropertiesMap.containsKey(pathSpec)) {
currResolvedPropertiesMap.remove(pathSpec);
}
});
currResolvedPropertiesMap.forEach((pathSpec, currCheckContextAndResolvedProperty) -> {
handlers.forEach(handler -> {
String annotationNamespace = handler.getAnnotationNamespace();
Map<String, Object> currResolvedProperties = currCheckContextAndResolvedProperty.getValue();
if (currResolvedProperties.containsKey(annotationNamespace)) {
// currResolvedPropertiesMap has a PathSpec which the prevResolvedPropertiesMap does not have,
// it means there is a new field with new annotations,
// pass an empty prevResolvedPropertiesMap and empty prevAnnotationContext to the annotation check.
AnnotationCompatibilityResult result = handler.checkCompatibility(new HashMap<>(), currResolvedProperties, new CompatibilityCheckContext(), currCheckContextAndResolvedProperty.getKey());
results.add(result);
}
});
});
return results;
}
use of com.linkedin.data.schema.annotation.SchemaAnnotationHandler.AnnotationCompatibilityResult in project rest.li by linkedin.
the class TestAnnotationCompatibilityChecker method generateExpectResult.
private AnnotationCompatibilityResult generateExpectResult(CompatibilityMessage compatibilityMessage) {
SchemaAnnotationHandler.AnnotationCompatibilityResult result = new SchemaAnnotationHandler.AnnotationCompatibilityResult();
result.addMessage(compatibilityMessage);
return result;
}
Aggregations