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 b8a0f141..05337b7e 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 @@ -19,6 +19,8 @@ import org.openapitools.openapidiff.core.model.deferred.DeferredChanged; import org.openapitools.openapidiff.core.model.deferred.RecursiveSchemaSet; import org.openapitools.openapidiff.core.model.schema.*; +import org.openapitools.openapidiff.core.model.schema.ChangedMaxItems; +import org.openapitools.openapidiff.core.model.schema.ChangedMinItems; public class SchemaDiffResult { protected ChangedSchema changedSchema; @@ -74,7 +76,9 @@ public , X> DeferredChanged diff( .setMultipleOf(new ChangedMultipleOf(left.getMultipleOf(), right.getMultipleOf())) .setNullable(new ChangedNullable(left.getNullable(), right.getNullable())) .setExamples(new ChangedExamples(left.getExamples(), right.getExamples())) - .setExample(new ChangedExample(left.getExample(), right.getExample())); + .setExample(new ChangedExample(left.getExample(), right.getExample())) + .setMaxItems(new ChangedMaxItems(left.getMaxItems(), right.getMaxItems(), context)) + .setMinItems(new ChangedMinItems(left.getMinItems(), right.getMinItems(), 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 2344a334..12f373ea 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 @@ -9,7 +9,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; 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.ChangedMinItems; import org.openapitools.openapidiff.core.model.schema.ChangedMultipleOf; import org.openapitools.openapidiff.core.model.schema.ChangedNullable; import org.openapitools.openapidiff.core.model.schema.ChangedNumericRange; @@ -41,6 +43,8 @@ public class ChangedSchema implements ComposedChanged { protected ChangedMaxLength maxLength; protected ChangedNumericRange numericRange; protected ChangedMultipleOf multipleOf; + protected ChangedMaxItems maxItems; + protected ChangedMinItems minItems; protected ChangedNullable nullable; protected boolean discriminatorPropertyChanged; protected ChangedSchema items; @@ -125,6 +129,8 @@ public List getChangedElements() { maxLength, numericRange, multipleOf, + maxItems, + minItems, nullable, extensions)) .collect(Collectors.toList()); @@ -289,6 +295,14 @@ public ChangedMultipleOf getMultipleOf() { return this.multipleOf; } + public ChangedMaxItems getMaxItems() { + return this.maxItems; + } + + public ChangedMinItems getMinItems() { + return this.minItems; + } + public ChangedNullable getNullable() { return this.nullable; } @@ -441,6 +455,18 @@ public ChangedSchema setMultipleOf(final ChangedMultipleOf multipleOf) { return this; } + public ChangedSchema setMaxItems(final ChangedMaxItems maxItems) { + clearChangedCache(); + this.maxItems = maxItems; + return this; + } + + public ChangedSchema setMinItems(final ChangedMinItems minItems) { + clearChangedCache(); + this.minItems = minItems; + return this; + } + public ChangedSchema setNullable(final ChangedNullable nullable) { clearChangedCache(); this.nullable = nullable; @@ -505,6 +531,8 @@ public boolean equals(Object o) { && Objects.equals(maxLength, that.maxLength) && Objects.equals(numericRange, that.numericRange) && Objects.equals(multipleOf, that.multipleOf) + && Objects.equals(maxItems, that.maxItems) + && Objects.equals(minItems, that.minItems) && Objects.equals(nullable, that.nullable) && Objects.equals(items, that.items) && Objects.equals(oneOfSchema, that.oneOfSchema) @@ -537,6 +565,8 @@ public int hashCode() { maxLength, numericRange, multipleOf, + maxItems, + minItems, nullable, discriminatorPropertyChanged, items, @@ -591,6 +621,10 @@ public java.lang.String toString() { + this.getNumericRange() + ", multipleOf=" + this.getMultipleOf() + + ", maxItems=" + + this.getMaxItems() + + ", minItems=" + + this.getMinItems() + ", nullable=" + this.getNullable() + ", discriminatorPropertyChanged=" diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java new file mode 100644 index 00000000..1af1134b --- /dev/null +++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java @@ -0,0 +1,43 @@ +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 ChangedMaxItems implements Changed { + private final Integer oldValue; + private final Integer newValue; + private final DiffContext context; + + public ChangedMaxItems(Integer oldValue, Integer newValue, DiffContext context) { + this.oldValue = oldValue; + this.newValue = newValue; + this.context = context; + } + + @Override + public DiffResult isChanged() { + if (oldValue == null && newValue == null) { + return DiffResult.NO_CHANGES; + } + if (oldValue == null || newValue == null) { + return DiffResult.COMPATIBLE; + } + if (newValue < oldValue) { + return DiffResult.INCOMPATIBLE; + } + return DiffResult.COMPATIBLE; + } + + public Integer getOldValue() { + return oldValue; + } + + public Integer getNewValue() { + return newValue; + } + + public DiffContext getContext() { + return context; + } +} diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java new file mode 100644 index 00000000..7791893c --- /dev/null +++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java @@ -0,0 +1,43 @@ +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 ChangedMinItems implements Changed { + private final Integer oldValue; + private final Integer newValue; + private final DiffContext context; + + public ChangedMinItems(Integer oldValue, Integer newValue, DiffContext context) { + this.oldValue = oldValue; + this.newValue = newValue; + this.context = context; + } + + @Override + public DiffResult isChanged() { + if (oldValue == null && newValue == null) { + return DiffResult.NO_CHANGES; + } + if (oldValue == null || newValue == null) { + return DiffResult.COMPATIBLE; + } + if (newValue > oldValue) { + return DiffResult.INCOMPATIBLE; + } + return DiffResult.COMPATIBLE; + } + + public Integer getOldValue() { + return oldValue; + } + + public Integer getNewValue() { + return newValue; + } + + public DiffContext getContext() { + return context; + } +} 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 318cae33..4275a4a8 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java @@ -135,6 +135,41 @@ public void changeMultipleOfHandling() { assertThat(props.get("field4").getMultipleOf().getRight()).isNull(); } + @Test // issues #480 + public void changeMinMaxItemsHandling() { + ChangedOpenApi changedOpenApi = + OpenApiCompare.fromLocations( + "schemaDiff/schema-min-max-items-diff-1.yaml", + "schemaDiff/schema-min-max-items-diff-2.yaml"); + ChangedSchema changedSchema = + getRequestBodyChangedSchema( + changedOpenApi, POST, "/schema/array/items", "application/json"); + + assertThat(changedSchema).isNotNull(); + Map props = changedSchema.getChangedProperties(); + assertThat(props).isNotEmpty(); + + // Check increasing of minItems + assertThat(props.get("field1").getMinItems().isIncompatible()).isTrue(); + assertThat(props.get("field1").getMinItems().getOldValue()).isEqualTo(1); + assertThat(props.get("field1").getMinItems().getNewValue()).isEqualTo(2); + + // Check decreasing of minItems + assertThat(props.get("field2").getMinItems().isCompatible()).isTrue(); + assertThat(props.get("field2").getMinItems().getOldValue()).isEqualTo(20); + assertThat(props.get("field2").getMinItems().getNewValue()).isEqualTo(10); + + // Check increasing of maxItems + assertThat(props.get("field3").getMaxItems().isCompatible()).isTrue(); + assertThat(props.get("field3").getMaxItems().getOldValue()).isEqualTo(90); + assertThat(props.get("field3").getMaxItems().getNewValue()).isEqualTo(100); + + // Check decreasing of maxItems + assertThat(props.get("field4").getMaxItems().isIncompatible()).isTrue(); + assertThat(props.get("field4").getMaxItems().getOldValue()).isEqualTo(100); + assertThat(props.get("field4").getMaxItems().getNewValue()).isEqualTo(90); + } + @Test // issue #482 public void changeNullabeHandling() { ChangedOpenApi changedOpenApi = diff --git a/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml new file mode 100644 index 00000000..23d84148 --- /dev/null +++ b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml @@ -0,0 +1,42 @@ +openapi: 3.1.0 +info: + description: Schema diff + title: schema diff + version: 1.0.0 +paths: + /schema/array/items: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestDTO' +components: + schemas: + TestDTO: + type: object + properties: + field1: + type: array + items: + type: string + minItems: 1 + maxItems: 100 + field2: + type: array + items: + type: string + minItems: 20 + maxItems: 100 + field3: + type: array + items: + type: string + minItems: 1 + maxItems: 90 + field4: + type: array + items: + type: string + minItems: 1 + maxItems: 100 diff --git a/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml new file mode 100644 index 00000000..0d8e6199 --- /dev/null +++ b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml @@ -0,0 +1,42 @@ +openapi: 3.1.0 +info: + description: Schema diff + title: schema diff + version: 1.0.0 +paths: + /schema/array/items: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestDTO' +components: + schemas: + TestDTO: + type: object + properties: + field1: + type: array + items: + type: string + minItems: 2 + maxItems: 100 + field2: + type: array + items: + type: string + minItems: 10 + maxItems: 100 + field3: + type: array + items: + type: string + minItems: 1 + maxItems: 100 + field4: + type: array + items: + type: string + minItems: 1 + maxItems: 90