This is an automated email from the ASF dual-hosted git repository.

apkhmv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 0430e3c6530 IGNITE-25831 Add enums support to OpenAPI test (#6287)
0430e3c6530 is described below

commit 0430e3c6530c319449f79f596500b59b319328e7
Author: Vadim Pakhnushev <[email protected]>
AuthorDate: Mon Jul 21 22:29:18 2025 +0300

    IGNITE-25831 Add enums support to OpenAPI test (#6287)
---
 .../org/apache/ignite/internal/OpenApiMatcher.java | 114 +++++++++++++++------
 .../apache/ignite/internal/OpenApiMatcherTest.java |  67 ++++++++++--
 2 files changed, 139 insertions(+), 42 deletions(-)

diff --git 
a/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcher.java
 
b/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcher.java
index cb4be431f63..5d5e327fe08 100644
--- 
a/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcher.java
+++ 
b/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcher.java
@@ -29,6 +29,7 @@ import io.swagger.v3.oas.models.Paths;
 import io.swagger.v3.oas.models.media.Content;
 import io.swagger.v3.oas.models.media.MediaType;
 import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.parameters.RequestBody;
 import io.swagger.v3.oas.models.responses.ApiResponse;
@@ -330,6 +331,11 @@ public class OpenApiMatcher extends 
TypeSafeDiagnosingMatcher<OpenAPI> {
                 return false;
             }
 
+            if (!Objects.equals(baseSchema.getFormat(), 
currentSchema.getFormat())) {
+                mismatchDescription.appendText("Schema 
").appendValue(path).appendText(" has different formats");
+                return false;
+            }
+
             String baseRef = baseSchema.get$ref();
             if (!Objects.equals(baseRef, currentSchema.get$ref())) {
                 mismatchDescription.appendText("Schema 
").appendValue(path).appendText(" has different reference");
@@ -363,53 +369,93 @@ public class OpenApiMatcher extends 
TypeSafeDiagnosingMatcher<OpenAPI> {
             }
 
             if ("object".equals(baseType)) {
-                // Detect new required properties only for responses
-                if (isRequest) {
-                    Set<String> baseRequired = new 
HashSet<>(ofNullable(baseSchema.getRequired()).orElse(List.of()));
+                return compareObjectSchema(path, mismatchDescription, 
baseSchema, currentSchema);
+            }
 
-                    Set<String> newRequired = 
ofNullable(currentSchema.getRequired()).orElse(List.of()).stream()
-                            .filter(Predicate.not(baseRequired::contains))
-                            .collect(toSet());
+            if ("string".equals(baseType)) {
+                return compareStringSchema(path, mismatchDescription, 
baseSchema, currentSchema);
+            }
 
-                    if (!newRequired.isEmpty()) {
-                        mismatchDescription.appendText("Schema 
").appendValue(path)
-                                .appendText(" has new required properties 
").appendValue(newRequired);
-                        return false;
-                    }
-                } else {
-                    Set<String> currentRequired = new 
HashSet<>(ofNullable(currentSchema.getRequired()).orElse(List.of()));
+            return true;
+        }
 
-                    Set<String> newOptional = 
ofNullable(baseSchema.getRequired()).orElse(List.of()).stream()
-                            .filter(Predicate.not(currentRequired::contains))
-                            .collect(toSet());
+        private boolean compareObjectSchema(String path, Description 
mismatchDescription, Schema<?> baseSchema, Schema<?> currentSchema) {
+            if (isRequest) {
+                Set<String> baseRequired = new 
HashSet<>(ofNullable(baseSchema.getRequired()).orElse(List.of()));
 
-                    if (!newOptional.isEmpty()) {
-                        mismatchDescription.appendText("Schema 
").appendValue(path)
-                                .appendText(" has new optional properties 
").appendValue(newOptional);
-                        return false;
-                    }
-                }
+                Set<String> newRequired = 
ofNullable(currentSchema.getRequired()).orElse(List.of()).stream()
+                        .filter(Predicate.not(baseRequired::contains))
+                        .collect(toSet());
 
-                Map<String, Schema> baseProperties = 
ofNullable(baseSchema.getProperties()).orElse(Map.of());
-                Map<String, Schema> currentProperties = 
ofNullable(currentSchema.getProperties()).orElse(Map.of());
-                if (!compareProperties(path + "/object", mismatchDescription, 
baseProperties, currentProperties)) {
+                if (!newRequired.isEmpty()) {
+                    mismatchDescription.appendText("Schema ").appendValue(path)
+                            .appendText(" has new required properties 
").appendValue(newRequired);
                     return false;
                 }
+            } else {
+                Set<String> currentRequired = new 
HashSet<>(ofNullable(currentSchema.getRequired()).orElse(List.of()));
 
-                Object baseAdditionalProperties = 
baseSchema.getAdditionalProperties();
-                Object currentAdditionalProperties = 
currentSchema.getAdditionalProperties();
-                if (baseAdditionalProperties instanceof Schema && 
currentAdditionalProperties instanceof Schema) {
-                    return compareSchema(
-                            path + "/additionalProperties",
-                            mismatchDescription,
-                            ((Schema) baseAdditionalProperties),
-                            ((Schema) currentAdditionalProperties)
-                    );
+                Set<String> newOptional = 
ofNullable(baseSchema.getRequired()).orElse(List.of()).stream()
+                        .filter(Predicate.not(currentRequired::contains))
+                        .collect(toSet());
+
+                if (!newOptional.isEmpty()) {
+                    mismatchDescription.appendText("Schema ").appendValue(path)
+                            .appendText(" has new optional properties 
").appendValue(newOptional);
+                    return false;
                 }
+            }
+
+            Map<String, Schema> baseProperties = 
ofNullable(baseSchema.getProperties()).orElse(Map.of());
+            Map<String, Schema> currentProperties = 
ofNullable(currentSchema.getProperties()).orElse(Map.of());
+            if (!compareProperties(path + "/object", mismatchDescription, 
baseProperties, currentProperties)) {
+                return false;
+            }
+
+            Object baseAdditionalProperties = 
baseSchema.getAdditionalProperties();
+            Object currentAdditionalProperties = 
currentSchema.getAdditionalProperties();
+            if (baseAdditionalProperties instanceof Schema && 
currentAdditionalProperties instanceof Schema) {
+                return compareSchema(
+                        path + "/additionalProperties",
+                        mismatchDescription,
+                        ((Schema) baseAdditionalProperties),
+                        ((Schema) currentAdditionalProperties)
+                );
+            }
 
+            return true;
+        }
+
+        private boolean compareStringSchema(String path, Description 
mismatchDescription, Schema<?> baseSchema, Schema<?> currentSchema) {
+            if (!(baseSchema instanceof StringSchema) || !(currentSchema 
instanceof StringSchema)) {
                 return true;
             }
 
+            if (isRequest) {
+                Set<String> currentEnum = new 
HashSet<>(ofNullable(((StringSchema) 
currentSchema).getEnum()).orElse(List.of()));
+
+                Set<String> missingValues = ofNullable(((StringSchema) 
baseSchema).getEnum()).orElse(List.of()).stream()
+                        .filter(Predicate.not(currentEnum::contains))
+                        .collect(toSet());
+
+                if (!missingValues.isEmpty()) {
+                    mismatchDescription.appendText("Schema ").appendValue(path)
+                            .appendText(" has missing enum values 
").appendValue(missingValues);
+                    return false;
+                }
+            } else {
+                Set<String> baseEnum = new 
HashSet<>(ofNullable(((StringSchema) baseSchema).getEnum()).orElse(List.of()));
+
+                Set<String> newValues = ofNullable(((StringSchema) 
currentSchema).getEnum()).orElse(List.of()).stream()
+                        .filter(Predicate.not(baseEnum::contains))
+                        .collect(toSet());
+
+                if (!newValues.isEmpty()) {
+                    mismatchDescription.appendText("Schema ").appendValue(path)
+                            .appendText(" has new enum values 
").appendValue(newValues);
+                    return false;
+                }
+            }
             return true;
         }
 
diff --git 
a/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcherTest.java
 
b/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcherTest.java
index 6d4fd0ede64..33934e8a4c5 100644
--- 
a/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcherTest.java
+++ 
b/modules/compatibility-tests/src/testFixtures/java/org/apache/ignite/internal/OpenApiMatcherTest.java
@@ -28,6 +28,7 @@ import io.swagger.v3.oas.models.PathItem;
 import io.swagger.v3.oas.models.media.Content;
 import io.swagger.v3.oas.models.media.MediaType;
 import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.parameters.RequestBody;
 import io.swagger.v3.oas.models.responses.ApiResponse;
@@ -151,6 +152,17 @@ class OpenApiMatcherTest {
                 + "of parameter \"param\" : Schema \"test/param\" has 
different type");
     }
 
+    @Test
+    void differentParameterSchemaFormat() {
+        OpenAPI baseApi = new OpenAPI().path("test", new PathItem().get(new 
Operation()
+                .addParametersItem(new Parameter().name("param").schema(new 
Schema().type("integer").format("int32")))));
+        OpenAPI currentApi = new OpenAPI().path("test", new PathItem().get(new 
Operation()
+                .addParametersItem(new Parameter().name("param").schema(new 
Schema().type("integer").format("int64")))));
+
+        assertThatMismatchedWithDescription(baseApi, currentApi, "operation 
<GET> at path \"test\" has incompatible schemas "
+                + "of parameter \"param\" : Schema \"test/param\" has 
different formats");
+    }
+
     @Test
     void differentParameterSchemaRef() {
         OpenAPI baseApi = new OpenAPI().path("test", new PathItem().get(new 
Operation()
@@ -164,8 +176,7 @@ class OpenApiMatcherTest {
 
     @Test
     void differentComponentsSchemaType() {
-        PathItem pathItem = new PathItem().get(new 
Operation().addParametersItem(new Parameter().name("param")
-                .schema(new 
Schema().$ref("#/components/schemas/testSchema"))));
+        PathItem pathItem = createPathItem();
         OpenAPI baseApi = new OpenAPI().path("test", pathItem)
                 .components(new Components().addSchemas("testSchema", new 
Schema().type("object")));
         OpenAPI currentApi = new OpenAPI().path("test", pathItem)
@@ -177,8 +188,7 @@ class OpenApiMatcherTest {
 
     @Test
     void differentComponentsSchemaAdditionalType() {
-        PathItem pathItem = new PathItem().get(new 
Operation().addParametersItem(new Parameter().name("param")
-                .schema(new 
Schema().$ref("#/components/schemas/testSchema"))));
+        PathItem pathItem = createPathItem();
         OpenAPI baseApi = new OpenAPI().path("test", pathItem)
                 .components(new Components().addSchemas("testSchema", new 
Schema().type("object")
                         .additionalProperties(new Schema().type("object"))));
@@ -192,8 +202,7 @@ class OpenApiMatcherTest {
 
     @Test
     void differentComponentsSchemaInnerType() {
-        PathItem pathItem = new PathItem().get(new 
Operation().addParametersItem(new Parameter().name("param")
-                .schema(new 
Schema().$ref("#/components/schemas/testSchema"))));
+        PathItem pathItem = createPathItem();
         OpenAPI baseApi = new OpenAPI().path("test", pathItem)
                 .components(new Components().addSchemas("testSchema", new 
Schema().type("object")
                         .addProperty("value", new Schema().type("object"))));
@@ -207,8 +216,7 @@ class OpenApiMatcherTest {
 
     @Test
     void newRequiredParameters() {
-        PathItem pathItem = new PathItem().get(new 
Operation().addParametersItem(new Parameter().name("param")
-                .schema(new 
Schema().$ref("#/components/schemas/testSchema"))));
+        PathItem pathItem = createPathItem();
         OpenAPI baseApi = new OpenAPI().path("test", pathItem)
                 .components(new Components().addSchemas("testSchema", new 
Schema().type("object")
                         .addProperty("prop", new Schema())));
@@ -242,6 +250,44 @@ class OpenApiMatcherTest {
                 + "incompatible content: Schema 
\"#/components/schemas/testSchema\" has new optional properties <[prop]>");
     }
 
+    @Test
+    void newEnumValuesInRequest() {
+        PathItem pathItem = createPathItem();
+        StringSchema baseSchema = new StringSchema().type("string");
+        baseSchema.addEnumItemObject("FIRST");
+        baseSchema.addEnumItemObject("SECOND");
+        OpenAPI baseApi = new OpenAPI().path("test", pathItem)
+                .components(new Components().addSchemas("testSchema", 
baseSchema));
+        StringSchema currentSchema = new StringSchema().type("string");
+        currentSchema.addEnumItemObject("FIRST");
+        OpenAPI currentApi = new OpenAPI().path("test", pathItem)
+                .components(new Components().addSchemas("testSchema", 
currentSchema));
+
+        assertThatMismatchedWithDescription(baseApi, currentApi, "operation 
<GET> at path \"test\" has incompatible schemas "
+                + "of parameter \"param\" : Schema 
\"#/components/schemas/testSchema\" has missing enum values <[SECOND]>");
+    }
+
+    @Test
+    void newEnumValuesInResponse() {
+        PathItem pathItem = new PathItem().get(new Operation()
+                .responses(new ApiResponses().addApiResponse("200", new 
ApiResponse().content(new Content()
+                        .addMediaType("application/json", new MediaType()
+                                .schema(new 
Schema().$ref("#/components/schemas/testSchema")))))));
+        StringSchema baseSchema = new StringSchema().type("string");
+        baseSchema.addEnumItemObject("FIRST");
+        OpenAPI baseApi = new OpenAPI().path("test", pathItem)
+                .components(new Components().addSchemas("testSchema", 
baseSchema));
+        StringSchema currentSchema = new StringSchema().type("string");
+        currentSchema.addEnumItemObject("FIRST");
+        currentSchema.addEnumItemObject("SECOND");
+        OpenAPI currentApi = new OpenAPI().path("test", pathItem)
+                .components(new Components().addSchemas("testSchema", 
currentSchema));
+
+        assertThatMismatchedWithDescription(baseApi, currentApi,
+                "operation <GET> at path \"test\" response \"200\" has 
incompatible content: "
+                + "Schema \"#/components/schemas/testSchema\" has new enum 
values <[SECOND]>");
+    }
+
     private static void assertThatMismatchedWithDescription(OpenAPI baseApi, 
OpenAPI currentApi, String description) {
         Matcher<OpenAPI> matcher = isCompatibleWith(baseApi);
         assertThat(matcher.matches(currentApi), is(false));
@@ -250,4 +296,9 @@ class OpenApiMatcherTest {
         matcher.describeMismatch(currentApi, stringDescription);
         assertThat(stringDescription.toString(), is(description));
     }
+
+    private static PathItem createPathItem() {
+        return new PathItem().get(new Operation().addParametersItem(new 
Parameter().name("param")
+                .schema(new 
Schema().$ref("#/components/schemas/testSchema"))));
+    }
 }

Reply via email to