diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java index 05337b7e..698eade4 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java @@ -78,7 +78,11 @@ public , X> DeferredChanged diff( .setExamples(new ChangedExamples(left.getExamples(), right.getExamples())) .setExample(new ChangedExample(left.getExample(), right.getExample())) .setMaxItems(new ChangedMaxItems(left.getMaxItems(), right.getMaxItems(), context)) - .setMinItems(new ChangedMinItems(left.getMinItems(), right.getMinItems(), context)); + .setMinItems(new ChangedMinItems(left.getMinItems(), right.getMinItems(), context)) + .setMaxProperties( + new ChangedMaxProperties(left.getMaxProperties(), right.getMaxProperties(), context)) + .setMinProperties( + new ChangedMinProperties(left.getMinProperties(), right.getMinProperties(), context)); builder .with( openApiDiff diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java index 12f373ea..db98a329 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java @@ -11,7 +11,9 @@ import org.openapitools.openapidiff.core.model.schema.ChangedEnum; import org.openapitools.openapidiff.core.model.schema.ChangedMaxItems; import org.openapitools.openapidiff.core.model.schema.ChangedMaxLength; +import org.openapitools.openapidiff.core.model.schema.ChangedMaxProperties; import org.openapitools.openapidiff.core.model.schema.ChangedMinItems; +import org.openapitools.openapidiff.core.model.schema.ChangedMinProperties; import org.openapitools.openapidiff.core.model.schema.ChangedMultipleOf; import org.openapitools.openapidiff.core.model.schema.ChangedNullable; import org.openapitools.openapidiff.core.model.schema.ChangedNumericRange; @@ -45,6 +47,8 @@ public class ChangedSchema implements ComposedChanged { protected ChangedMultipleOf multipleOf; protected ChangedMaxItems maxItems; protected ChangedMinItems minItems; + protected ChangedMaxProperties maxProperties; + protected ChangedMinProperties minProperties; protected ChangedNullable nullable; protected boolean discriminatorPropertyChanged; protected ChangedSchema items; @@ -131,6 +135,8 @@ public List getChangedElements() { multipleOf, maxItems, minItems, + maxProperties, + minProperties, nullable, extensions)) .collect(Collectors.toList()); @@ -327,6 +333,14 @@ public ChangedExtensions getExtensions() { return this.extensions; } + public ChangedMaxProperties getMaxProperties() { + return this.maxProperties; + } + + public ChangedMinProperties getMinProperties() { + return this.minProperties; + } + public ChangedSchema setContext(final DiffContext context) { this.context = context; return this; @@ -503,6 +517,18 @@ public ChangedSchema setExtensions(final ChangedExtensions extensions) { return this; } + public ChangedSchema setMaxProperties(final ChangedMaxProperties maxProperties) { + clearChangedCache(); + this.maxProperties = maxProperties; + return this; + } + + public ChangedSchema setMinProperties(final ChangedMinProperties minProperties) { + clearChangedCache(); + this.minProperties = minProperties; + return this; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -537,7 +563,9 @@ public boolean equals(Object o) { && Objects.equals(items, that.items) && Objects.equals(oneOfSchema, that.oneOfSchema) && Objects.equals(addProp, that.addProp) - && Objects.equals(extensions, that.extensions); + && Objects.equals(extensions, that.extensions) + && Objects.equals(maxProperties, that.maxProperties) + && Objects.equals(minProperties, that.minProperties); } @Override @@ -572,7 +600,9 @@ public int hashCode() { items, oneOfSchema, addProp, - extensions); + extensions, + maxProperties, + minProperties); } @java.lang.Override @@ -637,6 +667,10 @@ public java.lang.String toString() { + this.getAddProp() + ", extensions=" + this.getExtensions() + + ", maxProperties=" + + this.getMaxProperties() + + ", minProperties=" + + this.getMinProperties() + ")"; } } diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java new file mode 100644 index 00000000..c4c56af3 --- /dev/null +++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java @@ -0,0 +1,46 @@ +package org.openapitools.openapidiff.core.model.schema; + +import org.openapitools.openapidiff.core.model.Changed; +import org.openapitools.openapidiff.core.model.DiffContext; +import org.openapitools.openapidiff.core.model.DiffResult; + +public class ChangedMaxProperties implements Changed { + private Integer oldValue; + private Integer newValue; + private DiffContext context; + + public ChangedMaxProperties(Integer oldValue, Integer newValue, DiffContext context) { + this.oldValue = oldValue; + this.newValue = newValue; + this.context = context; + } + + public Integer getOldValue() { + return oldValue; + } + + public Integer getNewValue() { + return newValue; + } + + @Override + public DiffResult isChanged() { + if (oldValue == null && newValue == null) { + return DiffResult.NO_CHANGES; + } + + if (oldValue == null) { + return DiffResult.INCOMPATIBLE; + } + + if (newValue == null) { + return DiffResult.COMPATIBLE; + } + + if (!oldValue.equals(newValue)) { + return oldValue > newValue ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE; + } + + return DiffResult.NO_CHANGES; + } +} diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java new file mode 100644 index 00000000..f574b5c8 --- /dev/null +++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java @@ -0,0 +1,46 @@ +package org.openapitools.openapidiff.core.model.schema; + +import org.openapitools.openapidiff.core.model.Changed; +import org.openapitools.openapidiff.core.model.DiffContext; +import org.openapitools.openapidiff.core.model.DiffResult; + +public class ChangedMinProperties implements Changed { + private Integer oldValue; + private Integer newValue; + private DiffContext context; + + public ChangedMinProperties(Integer oldValue, Integer newValue, DiffContext context) { + this.oldValue = oldValue; + this.newValue = newValue; + this.context = context; + } + + public Integer getOldValue() { + return oldValue; + } + + public Integer getNewValue() { + return newValue; + } + + @Override + public DiffResult isChanged() { + if (oldValue == null && newValue == null) { + return DiffResult.NO_CHANGES; + } + + if (oldValue == null) { + return DiffResult.INCOMPATIBLE; + } + + if (newValue == null) { + return DiffResult.COMPATIBLE; + } + + if (!oldValue.equals(newValue)) { + return newValue > oldValue ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE; + } + + return DiffResult.NO_CHANGES; + } +} diff --git a/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java index 4275a4a8..3915789b 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java @@ -200,4 +200,39 @@ public void changeNullabeHandling() { assertThat(props.get("field3").getNullable().getLeft()).isNull(); assertThat(props.get("field3").getNullable().getRight()).isTrue(); } + + @Test // issue #479 + public void changeMinMaxPropertiesHandling() { + ChangedOpenApi changedOpenApi = + OpenApiCompare.fromLocations( + "schemaDiff/schema-min-max-properties-diff-1.yaml", + "schemaDiff/schema-min-max-properties-diff-2.yaml"); + ChangedSchema changedSchema = + getRequestBodyChangedSchema( + changedOpenApi, POST, "/schema/object/min-max-properties", "application/json"); + + assertThat(changedSchema).isNotNull(); + Map props = changedSchema.getChangedProperties(); + assertThat(props).isNotEmpty(); + + // Check increasing of minProperties + assertThat(props.get("field1").getMinProperties().isIncompatible()).isTrue(); + assertThat(props.get("field1").getMinProperties().getOldValue()).isEqualTo(1); + assertThat(props.get("field1").getMinProperties().getNewValue()).isEqualTo(10); + + // Check decreasing of minProperties + assertThat(props.get("field2").getMinProperties().isCompatible()).isTrue(); + assertThat(props.get("field2").getMinProperties().getOldValue()).isEqualTo(10); + assertThat(props.get("field2").getMinProperties().getNewValue()).isEqualTo(1); + + // Check increasing of maxProperties + assertThat(props.get("field3").getMaxProperties().isCompatible()).isTrue(); + assertThat(props.get("field3").getMaxProperties().getOldValue()).isEqualTo(10); + assertThat(props.get("field3").getMaxProperties().getNewValue()).isEqualTo(100); + + // Check decreasing of maxProperties + assertThat(props.get("field4").getMaxProperties().isIncompatible()).isTrue(); + assertThat(props.get("field4").getMaxProperties().getOldValue()).isEqualTo(100); + assertThat(props.get("field4").getMaxProperties().getNewValue()).isEqualTo(10); + } } diff --git a/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml new file mode 100644 index 00000000..263d710f --- /dev/null +++ b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml @@ -0,0 +1,30 @@ +openapi: 3.0.1 +info: + description: Schema diff + title: schema diff + version: 1.0.0 +paths: + /schema/object/min-max-properties: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestDTO' +components: + schemas: + TestDTO: + type: object + properties: + field1: + type: object + minProperties: 1 + field2: + type: object + minProperties: 10 + field3: + type: object + maxProperties: 10 + field4: + type: object + maxProperties: 100 diff --git a/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml new file mode 100644 index 00000000..17183d8a --- /dev/null +++ b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml @@ -0,0 +1,30 @@ +openapi: 3.0.1 +info: + description: Schema diff + title: schema diff + version: 1.0.0 +paths: + /schema/object/min-max-properties: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestDTO' +components: + schemas: + TestDTO: + type: object + properties: + field1: + type: object + minProperties: 10 + field2: + type: object + minProperties: 1 + field3: + type: object + maxProperties: 100 + field4: + type: object + maxProperties: 10