[kotlin] [bugfix] [maven-plugin]: prevent ClassCastException with boolean config options (#4361)

* fix: prevent classcast exception during execution of openapi-generator-maven-plugin.

* style: revert styling to openapi defaults

* test: unit test coverage for handling boolean config options

* fix: replace option value with boolean, if it is a string literal boolean

* style: use data type long

* test: add maven testfile kotlin.xml to travis build

* test: runnable maven test of the kotlin generator
This commit is contained in:
Jan 2019-11-08 07:38:05 +01:00 committed by William Cheng
parent b0b0e2b102
commit f9af3c2752
4 changed files with 298 additions and 7 deletions

View File

@ -138,6 +138,7 @@ script:
# test maven plugin
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/java-client.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/multi-module/pom.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/kotlin.xml
# test gradle plugin
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew buildGoSdk)
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew openApiGenerate)

View File

@ -0,0 +1,237 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>sample-project</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>sample-project</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<!-- activate the plugin -->
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>4.2.1-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<id>default</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>${project.basedir}/swagger.yaml</inputSpec>
<!-- target to generate java client code -->
<generatorName>kotlin</generatorName>
<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
you can use the following target: <generatorName>spring</generatorName> -->
<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
</configuration>
</execution>
<execution>
<id>kotlin</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml
</inputSpec>
<!-- target to generate java client code -->
<generatorName>kotlin</generatorName>
<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
you can use the following target: <generatorName>spring</generatorName> -->
<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
<output>${project.build.directory}/generated-sources/kotlin</output>
<apiPackage>kotlintest.org.openapitools.client.api</apiPackage>
<modelPackage>kotlintest.org.openapitools.client.model</modelPackage>
<invokerPackage>kotlintest.org.openapitools.client</invokerPackage>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<proc>none</proc>
</configuration>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<jvmTarget>${kotlinJvmTarget}</jvmTarget>
<javacOptions/>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.build.directory}/generated-sources/kotlin/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<pluginRepositories>
<pluginRepository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<!-- dependencies are needed for the client being generated -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<!-- You can find the dependencies for the library configuation you chose by looking in JavaClientCodegen.
Then find the corresponding dependency on Maven Central, and set the versions in the property section below -->
<!-- HTTP client: jersey-client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey-version}</version>
</dependency>
<!-- @Nullable annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<!-- JSON processing: jackson -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind-nullable-version}</version>
</dependency>
<!-- Joda time: if you use it -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>${migbase64.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
</dependency>
</dependencies>
<properties>
<swagger-annotations-version>1.5.8</swagger-annotations-version>
<jersey-version>2.27</jersey-version>
<jackson-version>2.8.9</jackson-version>
<jackson-databind-nullable-version>0.2.0</jackson-databind-nullable-version>
<jodatime-version>2.7</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.8.1</junit-version>
<kotlin.version>1.3.50</kotlin.version>
<kotlinJvmTarget>1.8</kotlinJvmTarget>
<moshi-kotlin.version>1.8.0</moshi-kotlin.version>
<migbase64.version>2.2</migbase64.version>
</properties>
</project>

View File

@ -434,19 +434,19 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
}
if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL)));
this.setSerializableModel(getBooleanOption(CodegenConstants.SERIALIZABLE_MODEL));
} else {
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
}
if (additionalProperties.containsKey(CodegenConstants.PARCELIZE_MODELS)) {
this.setParcelizeModels(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.PARCELIZE_MODELS)));
this.setParcelizeModels(getBooleanOption(CodegenConstants.PARCELIZE_MODELS));
} else {
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
}
if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
this.setNonPublicApi(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.NON_PUBLIC_API)));
this.setNonPublicApi(getBooleanOption(CodegenConstants.NON_PUBLIC_API));
} else {
additionalProperties.put(CodegenConstants.NON_PUBLIC_API, nonPublicApi);
}
@ -458,6 +458,18 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
additionalProperties.put("modelDocPath", modelDocPath);
}
private boolean getBooleanOption(String key) {
final Object booleanValue = additionalProperties.get(key);
Boolean result = Boolean.FALSE;
if (booleanValue instanceof Boolean) {
result = (Boolean) booleanValue;
} else if (booleanValue instanceof String) {
result = Boolean.parseBoolean((String) booleanValue);
}
additionalProperties.put(key, result);
return result;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
@ -501,7 +513,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
public void setSerializableModel(boolean serializableModel) {
this.serializableModel = serializableModel;
}
public boolean nonPublicApi() {
return nonPublicApi;
}

View File

@ -1,5 +1,6 @@
package org.openapitools.codegen.kotlin;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
import org.testng.Assert;
@ -53,7 +54,7 @@ public class AbstractKotlinCodegenTest {
}
@Test
public void toEnumValue(){
public void toEnumValue() {
assertEquals(codegen.toEnumValue("1", "kotlin.Int"), "1");
assertEquals(codegen.toEnumValue("1", "kotlin.Double"), "1.0");
assertEquals(codegen.toEnumValue("1.3", "kotlin.Double"), "1.3");
@ -81,14 +82,14 @@ public class AbstractKotlinCodegenTest {
}
@Test
public void isDataTypeString(){
public void isDataTypeString() {
assertFalse(codegen.isDataTypeString("kotlin.Int"));
assertTrue(codegen.isDataTypeString("kotlin.String"));
assertTrue(codegen.isDataTypeString("String"));
}
@Test
public void toModelNameShouldUseProvidedMapping() {
public void toModelNameShouldUseProvidedMapping() {
codegen.importMapping().put("json_myclass", "com.test.MyClass");
assertEquals("com.test.MyClass", codegen.toModelName("json_myclass"));
}
@ -155,5 +156,45 @@ public class AbstractKotlinCodegenTest {
Assert.assertEquals(codegen.apiTestFileFolder(), "/User/open/api/tools/test/folder/org/openapitools/codegen/api".replace('/', File.separatorChar));
}
@Test
public void processOptsBooleanTrueFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "true");
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
@Test
public void processOptsBooleanTrueFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, true);
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
@Test
public void processOptsBooleanFalseFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "false");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
@Test
public void processOptsBooleanFalseFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, false);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
@Test
public void processOptsBooleanFalseFromGarbage() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "blibb");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
@Test
public void processOptsBooleanFalseFromNumeric() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, 42L);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
}