[core] Minor schema validations bug + add pattern property to CodegenResponse (#4724)

* [core] Fix potential mismatch of data due to ClientOptInput and DefaultCodegen#openApi

* [core] Include escaped pattern on CodegenResponse
This commit is contained in:
Jim Schubert 2019-12-08 23:02:54 -05:00 committed by William Cheng
parent 41bb41c87c
commit ebf9ba023a
6 changed files with 145 additions and 7 deletions

View File

@ -30,12 +30,12 @@ public class ClientOptInput {
private List<AuthorizationValue> auths;
public ClientOptInput openAPI(OpenAPI openAPI) {
this.openAPI = openAPI;
this.setOpenAPI(openAPI);
return this;
}
public ClientOptInput config(CodegenConfig codegenConfig) {
this.config = codegenConfig;
this.setConfig(codegenConfig);
return this;
}
@ -72,6 +72,10 @@ public class ClientOptInput {
@Deprecated
public void setConfig(CodegenConfig config) {
this.config = config;
// TODO: ClientOptInputs needs to be retired
if (this.openAPI != null) {
this.config.setOpenAPI(this.openAPI);
}
}
@Deprecated
@ -86,5 +90,9 @@ public class ClientOptInput {
@Deprecated
public void setOpenAPI(OpenAPI openAPI) {
this.openAPI = openAPI;
// TODO: ClientOptInputs needs to be retired
if (this.config != null) {
this.config.setOpenAPI(this.openAPI);
}
}
}

View File

@ -24,7 +24,7 @@ public class CodegenResponse {
public String code, message;
public boolean hasMore;
public List<Map<String, Object>> examples;
public String dataType, baseType, containerType;
public String dataType, baseType, containerType, pattern;
public boolean hasHeaders;
public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBoolean, isDate,
isDateTime, isUuid, isEmail, isModel, isFreeFormObject;
@ -46,7 +46,7 @@ public class CodegenResponse {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!(o instanceof CodegenResponse)) return false;
CodegenResponse that = (CodegenResponse) o;
return hasMore == that.hasMore &&
hasHeaders == that.hasHeaders &&
@ -79,6 +79,7 @@ public class CodegenResponse {
Objects.equals(dataType, that.dataType) &&
Objects.equals(baseType, that.baseType) &&
Objects.equals(containerType, that.containerType) &&
Objects.equals(pattern, that.pattern) &&
Objects.equals(schema, that.schema) &&
Objects.equals(jsonSchema, that.jsonSchema) &&
Objects.equals(vendorExtensions, that.vendorExtensions);
@ -86,8 +87,7 @@ public class CodegenResponse {
@Override
public int hashCode() {
return Objects.hash(headers, code, message, hasMore, examples, dataType, baseType, containerType,
return Objects.hash(headers, code, message, hasMore, examples, dataType, baseType, containerType, pattern,
hasHeaders, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray,
isBoolean, isDate, isDateTime, isUuid, isEmail, isModel, isFreeFormObject, isDefault, simpleType,
primitiveType, isMapContainer, isListContainer, isBinary, isFile, schema, jsonSchema, vendorExtensions);
@ -102,6 +102,7 @@ public class CodegenResponse {
sb.append(", hasMore=").append(hasMore);
sb.append(", examples=").append(examples);
sb.append(", dataType='").append(dataType).append('\'');
sb.append(", pattern='").append(pattern).append('\'');
sb.append(", baseType='").append(baseType).append('\'');
sb.append(", containerType='").append(containerType).append('\'');
sb.append(", hasHeaders=").append(hasHeaders);

View File

@ -2887,6 +2887,10 @@ public class DefaultCodegen implements CodegenConfig {
responseSchema = ModelUtils.getSchemaFromResponse(response);
}
r.schema = responseSchema;
if (responseSchema != null && responseSchema.getPattern() != null) {
r.pattern = toRegularExpression(responseSchema.getPattern());
}
r.message = escapeText(response.getDescription());
// TODO need to revise and test examples in responses
// ApiResponse does not support examples at the moment

View File

@ -55,7 +55,6 @@ public class ModelUtils {
return Boolean.parseBoolean(GlobalSettings.getProperty(generateAliasAsModelKey, "false"));
}
/**
* Searches for the model by name in the map of models and returns it
*

View File

@ -1,19 +1,25 @@
package org.openapitools.codegen;
import io.swagger.models.Response;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.media.IntegerSchema;
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.QueryParameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.openapitools.codegen.utils.ModelUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -74,6 +80,48 @@ public class DefaultGeneratorTest {
Assert.assertEquals(defaultList.get(1).allParams.size(), 1);
}
@Test
public void testRefModelValidationProperties(){
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/2_0/refAliasedPrimitiveWithValidation.yml");
ClientOptInput opts = new ClientOptInput();
opts.setOpenAPI(openAPI);
DefaultCodegen config = new DefaultCodegen();
config.setStrictSpecBehavior(false);
opts.setConfig(config);
DefaultGenerator generator = new DefaultGenerator();
generator.opts(opts);
String expectedPattern = "^\\d{3}-\\d{2}-\\d{4}$";
// NOTE: double-escaped regex for when the value is intended to be dumped in template into a String location.
String escapedPattern = config.toRegularExpression(expectedPattern);
Schema stringRegex = openAPI.getComponents().getSchemas().get("StringRegex");
// Sanity check.
Assert.assertEquals(stringRegex.getPattern(), expectedPattern);
// Validate when we alias/unalias
Schema unaliasedStringRegex = ModelUtils.unaliasSchema(openAPI, stringRegex);
Assert.assertEquals(unaliasedStringRegex.getPattern(), expectedPattern);
// Validate when converting to property
CodegenProperty stringRegexProperty = config.fromProperty("stringRegex", stringRegex);
Assert.assertEquals(stringRegexProperty.pattern, escapedPattern);
// Validate when converting to parameter
Operation operation = openAPI.getPaths().get("/fake/StringRegex").getPost();
RequestBody body = operation.getRequestBody();
CodegenParameter codegenParameter = config.fromRequestBody(body, new HashSet<>(), "body");
Assert.assertEquals(codegenParameter.pattern, escapedPattern);
// Validate when converting to response
ApiResponse response = operation.getResponses().get("200");
CodegenResponse codegenResponse = config.fromResponse("200", response);
Assert.assertEquals(((Schema)codegenResponse.schema).getPattern(), expectedPattern);
Assert.assertEquals(codegenResponse.pattern, escapedPattern);
}
@Test
public void minimalUpdateTest() throws IOException {

View File

@ -0,0 +1,78 @@
swagger: '2.0'
info:
description: "Tests models which trigger aliased primitives but contain JSON Schema Validation Properties"
version: 1.0.0
title: OpenAPI Petstore
license:
name: Apache-2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
host: petstore.swagger.io:80
basePath: /v2
tags:
- name: fake
description: A fake api
schemes:
- http
paths:
/fake/StringEnum:
post:
tags:
- fake
description: Test serialization of StringEnum
operationId: StringEnum
parameters:
- name: body
in: body
description: Input string as post body
schema:
$ref: '#/definitions/StringEnum'
responses:
'200':
description: Returned string
schema:
$ref: '#/definitions/StringEnum'
/fake/StringRegex:
post:
tags:
- fake
description: Test serialization of StringRegex
operationId: StringRegex
parameters:
- name: body
in: body
description: Input string as post body
schema:
$ref: '#/definitions/StringRegex'
responses:
'200':
description: Returned string
schema:
$ref: '#/definitions/StringRegex'
/fake/ObjectModelWithRefs:
post:
tags:
- fake
description: Test serialization of ObjectModelWithRefs
operationId: ObjectModelWithRefs
parameters:
- name: body
in: body
description: Input object as post body
schema:
$ref: '#/definitions/ObjectModelWithRefs'
responses:
'200':
description: Returned object
schema:
$ref: '#/definitions/ObjectModelWithRefs'
definitions:
ObjectModelWithRefs:
type: object
required:
- stringRegex
properties:
stringRegex:
$ref: '#/definitions/StringRegex'
StringRegex:
type: string
pattern: '^\d{3}-\d{2}-\d{4}$'