From 79ced9d22377608b3b72d847b91e74b1e3b2acba Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Fri, 6 Sep 2019 22:48:32 -0400 Subject: [PATCH 1/4] [spring] Resolve regression on RequestParam for non-objects --- .../openapitools/codegen/DefaultCodegen.java | 2 +- .../java/spring/SpringCodegenTest.java | 62 +++++++++++++++++++ .../resources/3_0/3248-regression-dates.yaml | 27 ++++++++ .../test/resources/3_0/3248-regression.yaml | 47 ++++++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/3248-regression-dates.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/3248-regression.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index bfc8dbbb63c2..f76e6377df25 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -2303,8 +2303,8 @@ public CodegenProperty fromProperty(String name, Schema p) { // property.baseType = getSimpleRef(p.get$ref()); //} // --END of revision - property.isModel = ModelUtils.isModel(p); setNonArrayMapProperty(property, type); + property.isModel = ModelUtils.isObjectSchema(p) && ModelUtils.isModel(p); } LOGGER.debug("debugging from property return: " + property); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 578b485e8d1c..ba96d3005d1d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -167,6 +167,55 @@ public void doNotGenerateRequestParamForObjectQueryParam() throws IOException { checkFileNotContains(generator, outputPath + "/src/main/java/org/openapitools/api/PonyApi.java", "@RequestParam"); } + @Test + public void shouldGenerateRequestParamForRefParams_3248_Regression() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/3248-regression.yaml", null, new ParseOptions()).getOpenAPI(); + + SpringCodegen codegen = new SpringCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true"); + + ClientOptInput input = new ClientOptInput(); + input.setOpenAPI(openAPI); + input.setConfig(codegen); + + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(input).generate(); + + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/ExampleApi.java", + "@RequestParam(value = \"format\"", + "@RequestParam(value = \"query\""); + } + + @Test + public void shouldGenerateRequestParamForRefParams_3248_RegressionDates() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/3248-regression-dates.yaml", null, new ParseOptions()).getOpenAPI(); + + SpringCodegen codegen = new SpringCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true"); + + ClientOptInput input = new ClientOptInput(); + input.setOpenAPI(openAPI); + input.setConfig(codegen); + + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(input).generate(); + + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/ExampleApi.java", + "@RequestParam(value = \"start\""); + } + private void checkFileNotContains(MockDefaultGenerator generator, String path, String... lines) { String file = generator.getFiles().get(path); assertNotNull(file); @@ -174,6 +223,19 @@ private void checkFileNotContains(MockDefaultGenerator generator, String path, S assertFalse(file.contains(line)); } + private void checkFileContains(MockDefaultGenerator generator, String path, String... lines) { + String file = generator.getFiles().get(path); + assertNotNull(file); + int expectedCount = lines.length; + int actualCount = 0; + for (String line : lines) { + if (file.contains(line)) { + actualCount++; + } + } + assertEquals(actualCount, expectedCount, "File is missing " + (expectedCount - actualCount) + " expected lines."); + } + @Test public void clientOptsUnicity() { SpringCodegen codegen = new SpringCodegen(); diff --git a/modules/openapi-generator/src/test/resources/3_0/3248-regression-dates.yaml b/modules/openapi-generator/src/test/resources/3_0/3248-regression-dates.yaml new file mode 100644 index 000000000000..19a6b0e4ddc8 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/3248-regression-dates.yaml @@ -0,0 +1,27 @@ +openapi: 3.0.2 +info: + title: info + description: info + version: 0.1.0 + +paths: + /example/api: + get: + summary: summary + description: description + parameters: + - name: start + in: query + schema: + type: string + format: date-time + required: true + description: The start time. + responses: + 200: + description: response + content: + application/json: + schema: + type: string + diff --git a/modules/openapi-generator/src/test/resources/3_0/3248-regression.yaml b/modules/openapi-generator/src/test/resources/3_0/3248-regression.yaml new file mode 100644 index 000000000000..623cfa03e27a --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/3248-regression.yaml @@ -0,0 +1,47 @@ +openapi: 3.0.2 +info: + title: info + description: info + version: 0.1.0 + +paths: + /example/api: + get: + summary: summary + description: description + parameters: + - $ref: '#/components/parameters/requiredQueryParam' + - $ref: '#/components/parameters/formatParam' + responses: + 200: + description: response + content: + application/json: + schema: + type: string + +components: + parameters: + requiredQueryParam: + description: set query + in: query + name: query + required: true + schema: + type: string + formatParam: + description: set format + in: query + name: format + required: false + schema: + $ref: '#/components/schemas/format' + + schemas: + format: + default: json + description: response format + enum: + - json + - csv + type: string From 27ae0a65e16bc189fe98027bb0c759d290c489e9 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sat, 7 Sep 2019 09:24:09 -0400 Subject: [PATCH 2/4] Regenerate Go client samples --- samples/client/petstore/go/go-petstore-withXml/api_fake.go | 6 +----- samples/client/petstore/go/go-petstore/api_fake.go | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/samples/client/petstore/go/go-petstore-withXml/api_fake.go b/samples/client/petstore/go/go-petstore-withXml/api_fake.go index 08859ad9f74c..c08e9e995e90 100644 --- a/samples/client/petstore/go/go-petstore-withXml/api_fake.go +++ b/samples/client/petstore/go/go-petstore-withXml/api_fake.go @@ -835,11 +835,7 @@ func (a *FakeApiService) TestEndpointParameters(ctx _context.Context, number flo localVarFormParams.Add("date", parameterToString(localVarOptionals.Date.Value(), "")) } if localVarOptionals != nil && localVarOptionals.DateTime.IsSet() { - paramJson, err := parameterToJson(localVarOptionals.DateTime.Value()) - if err != nil { - return nil, err - } - localVarFormParams.Add("dateTime", paramJson) + localVarFormParams.Add("dateTime", parameterToString(localVarOptionals.DateTime.Value(), "")) } if localVarOptionals != nil && localVarOptionals.Password.IsSet() { localVarFormParams.Add("password", parameterToString(localVarOptionals.Password.Value(), "")) diff --git a/samples/client/petstore/go/go-petstore/api_fake.go b/samples/client/petstore/go/go-petstore/api_fake.go index 392ab5c46efb..731d5c00f421 100644 --- a/samples/client/petstore/go/go-petstore/api_fake.go +++ b/samples/client/petstore/go/go-petstore/api_fake.go @@ -834,11 +834,7 @@ func (a *FakeApiService) TestEndpointParameters(ctx _context.Context, number flo localVarFormParams.Add("date", parameterToString(localVarOptionals.Date.Value(), "")) } if localVarOptionals != nil && localVarOptionals.DateTime.IsSet() { - paramJson, err := parameterToJson(localVarOptionals.DateTime.Value()) - if err != nil { - return nil, err - } - localVarFormParams.Add("dateTime", paramJson) + localVarFormParams.Add("dateTime", parameterToString(localVarOptionals.DateTime.Value(), "")) } if localVarOptionals != nil && localVarOptionals.Password.IsSet() { localVarFormParams.Add("password", parameterToString(localVarOptionals.Password.Value(), "")) From a3b36f7a16bc7eec175fc530ce8365405df88cd4 Mon Sep 17 00:00:00 2001 From: Roger Peyer Date: Sat, 7 Sep 2019 17:13:20 -0400 Subject: [PATCH 3/4] Include testcase for issue 3248 --- .../java/spring/SpringCodegenTest.java | 31 +++++ .../src/test/resources/3_0/issue_3248.yaml | 121 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue_3248.yaml diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index ba96d3005d1d..e1023001e08d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -216,6 +216,37 @@ public void shouldGenerateRequestParamForRefParams_3248_RegressionDates() throws "@RequestParam(value = \"start\""); } + @Test + public void doGenerateRequestParamForSimpleParam() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/issue_3248.yaml", null, new ParseOptions()).getOpenAPI(); + + SpringCodegen codegen = new SpringCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true"); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.opts(input).generate(); + + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/MonkeysApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/ElephantsApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/ZebrasApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/BearsApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/CamelsApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/PandasApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/CrocodilesApi.java", "@RequestParam"); + checkFileContains(generator, outputPath + "/src/main/java/org/openapitools/api/PolarBearsApi.java", "@RequestParam"); + + } + private void checkFileNotContains(MockDefaultGenerator generator, String path, String... lines) { String file = generator.getFiles().get(path); assertNotNull(file); diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_3248.yaml b/modules/openapi-generator/src/test/resources/3_0/issue_3248.yaml new file mode 100644 index 000000000000..14a9d61659f3 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue_3248.yaml @@ -0,0 +1,121 @@ +openapi: 3.0.0 +servers: + - url: 'localhost:8080' +info: + version: 1.0.0 + title: OpenAPI Zoo + license: + name: Apache-2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +paths: + /monkeys: + get: + operationId: getMonkeys + parameters: + - $ref: '#/components/parameters/refDate' + /elephants: + get: + operationId: getElephants + parameters: + - in: query + name: someDate + required: true + schema: + type: string + format: date + /girafes: + get: + operationId: getGirafes + parameters: + - $ref: '#/components/parameters/refStatus' + /zebras: + get: + operationId: getZebras + parameters: + - in: query + name: status + required: true + schema: + type: integer + enum: [0,1] + default: 0 + /bears: + get: + operationId: getBears + parameters: + - $ref: '#/components/parameters/refCondition' + /camels: + get: + operationId: getCamels + parameters: + - in: query + name: condition + required: true + schema: + type: string + enum: + - sleeping + - awake + /pandas: + get: + operationId: getPandas + parameters: + - $ref: '#/components/parameters/refName' + /crocodiles: + get: + operationId: getCrocodiles + parameters: + - in: query + name: name + required: true + schema: + type: string + /polarBears: + get: + operationId: getPolarBears + parameters: + - $ref: '#/components/parameters/refAge' + /birds: + get: + operationId: getBirds + parameters: + - in: query + name: age + required: true + schema: + type: integer +components: + parameters: + refDate: + in: query + name: refDate + required: true + schema: + type: string + format: date + refStatus: + in: query + name: refStatus + required: true + schema: + type: integer + enum: [0,1] + default: 0 + refCondition: + in: query + name: refCondition + schema: + type: string + enum: + - sleeping + - awake + refName: + in: query + name: refName + schema: + type: string + refAge: + in: query + name: refAge + schema: + type: integer From fb16fee4df707812e41669a6519ae5a0891eaa4b Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sun, 8 Sep 2019 10:26:39 -0400 Subject: [PATCH 4/4] Set isModel appropriately for referenced schemas --- .../openapitools/codegen/DefaultCodegen.java | 3 +- .../codegen/DefaultCodegenTest.java | 36 +++++++++++++ .../src/test/resources/2_0/arrayRefBody.yaml | 52 +++++++++++++++++++ .../src/test/resources/3_0/arrayRefBody.yaml | 35 +++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 modules/openapi-generator/src/test/resources/2_0/arrayRefBody.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/arrayRefBody.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index f76e6377df25..682ca581355a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -2304,7 +2304,8 @@ public CodegenProperty fromProperty(String name, Schema p) { //} // --END of revision setNonArrayMapProperty(property, type); - property.isModel = ModelUtils.isObjectSchema(p) && ModelUtils.isModel(p); + Schema refOrCurrent = ModelUtils.getReferencedSchema(this.openAPI, p); + property.isModel = (ModelUtils.isComposedSchema(refOrCurrent) || ModelUtils.isObjectSchema(refOrCurrent)) && ModelUtils.isModel(refOrCurrent); } LOGGER.debug("debugging from property return: " + property); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 9dbb5bb5c134..26ae76afc1bc 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -27,6 +27,7 @@ import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; @@ -911,6 +912,41 @@ public void modelWithSuffixDoNotContainInheritedVars() { Assert.assertEquals(codegenModel.vars.size(), 1); } + @Test + public void arrayInnerReferencedSchemaMarkedAsModel_20() { + final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/2_0/arrayRefBody.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + Set imports = new HashSet<>(); + + RequestBody body = openAPI.getPaths().get("/examples").getPost().getRequestBody(); + + CodegenParameter codegenParameter = codegen.fromRequestBody(body, imports, ""); + + Assert.assertTrue(codegenParameter.isContainer); + Assert.assertTrue(codegenParameter.items.isModel); + Assert.assertFalse(codegenParameter.items.isContainer); + } + + @Test + public void arrayInnerReferencedSchemaMarkedAsModel_30() { + final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/arrayRefBody.yaml"); + new InlineModelResolver().flatten(openAPI); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + Set imports = new HashSet<>(); + + RequestBody body = openAPI.getPaths().get("/examples").getPost().getRequestBody(); + + CodegenParameter codegenParameter = codegen.fromRequestBody(body, imports, ""); + + Assert.assertTrue(codegenParameter.isContainer); + Assert.assertTrue(codegenParameter.items.isModel); + Assert.assertFalse(codegenParameter.items.isContainer); + } + @Test @SuppressWarnings("unchecked") public void commonLambdasRegistrationTest() { diff --git a/modules/openapi-generator/src/test/resources/2_0/arrayRefBody.yaml b/modules/openapi-generator/src/test/resources/2_0/arrayRefBody.yaml new file mode 100644 index 000000000000..b4f176b0b657 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/2_0/arrayRefBody.yaml @@ -0,0 +1,52 @@ +swagger: '2.0' +info: + version: '' + title: arrayRefBody + contact: {} +host: www.example.com +basePath: / +schemes: + - https +consumes: + - application/json +produces: + - application/json +paths: + /examples: + post: + description: Create an array of inputs + summary: '' + tags: + - Examples + operationId: createExamples + produces: + - application/json + parameters: + - name: body + in: body + required: true + description: inputs description + schema: + type: array + items: + $ref: '#/definitions/Input' + responses: + 200: + description: successful operation + headers: {} +definitions: + Input: + title: Input + type: object + properties: + id: + type: string + age: + type: integer + format: int32 + dt: + type: string + format: date-time +tags: + - name: Examples + description: 'Example inputs' diff --git a/modules/openapi-generator/src/test/resources/3_0/arrayRefBody.yaml b/modules/openapi-generator/src/test/resources/3_0/arrayRefBody.yaml new file mode 100644 index 000000000000..a77e4c308091 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/arrayRefBody.yaml @@ -0,0 +1,35 @@ +openapi: 3.0.0 +info: + title: '' + version: '' +paths: + /examples: + post: + tags: + - Examples + summary: Get a list of transactions + operationId: getFilteredTransactions + responses: + default: + description: successful operation + requestBody: + description: subscription payload + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Input' +components: + schemas: + Input: + type: object + properties: + id: + type: string + age: + type: integer + format: int32 + dt: + type: string + format: date-time