[bug][maven] Fix custom windows classpaths in maven plugin (#7587)

* [maven] Fallback to templates using classpath rather than OS-specific paths

Previous checks would cause logic in Windows to return early, for
built-in templates only. This reorganizes and simplifies the ordering
behavior.

* Match classpath check in WorkflowSettings with that in TemplateManager

* [maven] Much needed unit/integration tests

This follows similar approach used in PMD and other plugins managed by
maven.

Unit tests simply verify we can load configuration as expected into the
Mojo.

Integration tests execute actual sample projects bound to the current
build's Maven plugin. This uses maven-invoker-plugin, which also allows
for specifying the maven options in invoker.properties to execute the test.
It also provides a verification framework using groovy files with the
required naming convention of "verify.groovy". This allows us to quickly
and easily check that certain files are outputted by generation, and we
may also spotcheck file contents.

templateResourcePath option is skipped on windows. I've tested back to
version 3.3.3 and this doesn't seem to have worked consistently with how
the property works on non-Windows.

* Set groovy 3.0.5 for test harness

* Print stacktrace on Maven error in Travis

* [maven] Set groovy version in tests to supported in Java 11+

* Puts maven integration tests in separate profile called 'integration'
This commit is contained in:
Jim Schubert 2020-10-18 12:05:56 -04:00 committed by GitHub
parent 34d2e25899
commit ee1cbf6f4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1518 additions and 10 deletions

View File

@ -148,8 +148,8 @@ script:
- /bin/bash ./bin/utils/detect_tab_in_java_class.sh - /bin/bash ./bin/utils/detect_tab_in_java_class.sh
# run integration tests defined in maven pom.xml # run integration tests defined in maven pom.xml
# WARN: Travis will timeout after 10 minutes of no stdout/stderr activity, which is problematic with mvn --quiet. # WARN: Travis will timeout after 10 minutes of no stdout/stderr activity, which is problematic with mvn --quiet.
- mvn --no-snapshot-updates --quiet --batch-mode --show-version clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error - mvn -e --no-snapshot-updates --quiet --batch-mode --show-version clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- mvn --no-snapshot-updates --quiet --batch-mode --show-version verify -Psamples -Dorg.slf4j.simpleLogger.defaultLogLevel=error - mvn -e --no-snapshot-updates --quiet --batch-mode --show-version verify -Psamples -Dorg.slf4j.simpleLogger.defaultLogLevel=error
after_success: after_success:
# push to maven repo # push to maven repo
- if [ $SONATYPE_USERNAME ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - if [ $SONATYPE_USERNAME ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then

View File

@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
/** /**
* Represents those settings applied to a generation workflow. * Represents those settings applied to a generation workflow.
@ -444,10 +445,20 @@ public class WorkflowSettings {
uri = f.toURI(); uri = f.toURI();
this.templateDir = Paths.get(uri).toAbsolutePath().normalize().toString(); this.templateDir = Paths.get(uri).toAbsolutePath().normalize().toString();
} else { } else {
URL url = this.getClass().getClassLoader().getResource(templateDir); String cpDir;
// HACK: this duplicates TemplateManager.getCPResourcePath a bit. We should probably move that function to core.
if (!"/".equals(File.separator)) {
// Windows users may pass path specific to OS, but classpath must be "/" separators
cpDir = templateDir.replaceAll(Pattern.quote(File.separator), "/");
} else {
cpDir = templateDir;
}
URL url = this.getClass().getClassLoader().getResource(cpDir);
if (url != null) { if (url != null) {
try { try {
uri = url.toURI(); uri = url.toURI();
// we can freely set to templateDir here and allow templating to manage template lookups
this.templateDir = templateDir; this.templateDir = templateDir;
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
LOGGER.warn("The requested template was found on the classpath, but resulted in a syntax error."); LOGGER.warn("The requested template was found on the classpath, but resulted in a syntax error.");

View File

@ -53,8 +53,7 @@
<!-- target to generate java client code --> <!-- target to generate java client code -->
<generatorName>java</generatorName> <generatorName>java</generatorName>
<!-- hint: if you want to generate java server code, e.g. based on Spring Boot, <templateDirectory>${project.basedir}/templates</templateDirectory>
you can use the following target: <generatorName>spring</generatorName> -->
<!-- pass any necessary config options --> <!-- pass any necessary config options -->
<configOptions> <configOptions>

View File

@ -0,0 +1,21 @@
# TEST TEST TEST
# {{artifactId}}
{{appName}}
- API version: {{appVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
… etc.

View File

@ -16,6 +16,8 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.exclusions>**/src/main/java/org/openapitools/codegen/plugin/**/*</sonar.exclusions> <sonar.exclusions>**/src/main/java/org/openapitools/codegen/plugin/**/*</sonar.exclusions>
<!-- used for integration tests verification scripts, managed by the test harness plugin -->
<groovy.version>3.0.5</groovy.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -60,6 +62,24 @@
<!-- <version>4.12</version> --> <!-- <version>4.12</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<pluginManagement> <pluginManagement>
@ -108,7 +128,41 @@
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<postBuildHookScript>verify</postBuildHookScript>
<showVersion>true</showVersion>
<streamLogs>true</streamLogs>
<noLog>false</noLog>
<showErrors>true</showErrors>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile> <profile>
<id>static-analysis</id> <id>static-analysis</id>
<build> <build>

View File

@ -0,0 +1,2 @@
invoker.goals = -nsu generate-sources
invoker.name = Test Custom Templates via Resource

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools.maven.its</groupId>
<artifactId>custom-template-resource</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml</inputSpec>
<generatorName>kotlin</generatorName>
<output>${basedir}/out</output>
<!--
HACK: rather than compile our own resource, we'll pull from something that's already available: bash generator's templates
This only works because bash shares only README.mustache template with kotlin
-->
<templateResourcePath>bash</templateResourcePath>
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,39 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
File readme = new File(basedir, "out/README.md")
assert readme.isFile()
if (File.separator == "/") {
// For whatever reason, resource path templates fail in this test in Windows
assert readme.text.contains("# OpenAPI Petstore Bash client")
}
File gradle = new File(basedir, "out/build.gradle")
assert gradle.isFile()
File api = new File(basedir, "out/src/main/kotlin/org/openapitools/client/apis/PetApi.kt")
assert api.isFile()
File model = new File(basedir, "out/src/main/kotlin/org/openapitools/client/models/Pet.kt")
assert model.isFile()
// note that in Java 11+, this anything matching this condition could fail due to
// Illegal reflective access by org.codehaus.groovy.reflection.CachedClass
// and cause tests to fail. This is more to document for engineers.
if (GroovySystem.version.tokenize('.')[0].toInteger() < 3) {
throw new IllegalStateException("Found:" + GroovySystem.version + ", need Groovy 3.x or higher for Java 11+, so we require it for all versions")
}

View File

@ -0,0 +1,2 @@
invoker.goals = -nsu generate-sources
invoker.name = Test Custom Templates

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools.maven.its</groupId>
<artifactId>custom-template</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml</inputSpec>
<generatorName>kotlin</generatorName>
<output>${basedir}/out</output>
<templateDirectory>${project.basedir}/templates</templateDirectory>
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>
</configuration>
<executions>
<execution>
<id>remote</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,21 @@
# TEST TEST TEST
# {{artifactId}}
{{appName}}
- API version: {{appVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
… etc.

View File

@ -0,0 +1,38 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
File readme = new File(basedir, "out/README.md")
assert readme.isFile()
assert readme.text.contains("# TEST TEST TEST")
assert readme.text.contains("# kotlin-client")
assert readme.text.contains("OpenAPI Petstore")
File gradle = new File(basedir, "out/build.gradle")
assert gradle.isFile()
File api = new File(basedir, "out/src/main/kotlin/org/openapitools/client/apis/PetApi.kt")
assert api.isFile()
File model = new File(basedir, "out/src/main/kotlin/org/openapitools/client/models/Pet.kt")
assert model.isFile()
// note that in Java 11+, this anything matching this condition could fail due to
// Illegal reflective access by org.codehaus.groovy.reflection.CachedClass
// and cause tests to fail. This is more to document for engineers.
if (GroovySystem.version.tokenize('.')[0].toInteger() < 3) {
throw new IllegalStateException("Found:" + GroovySystem.version + ", need Groovy 3.x or higher for Java 11+, so we require it for all versions")
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.plugin;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* A base test class where we can add helper methods and whatnot
*/
public abstract class BaseTestCase extends AbstractMojoTestCase {
protected Path getUnitTestDir() {
return Paths.get(getBasedir(), "src", "test", "resources", "unit");
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.plugin;
import org.junit.Test;
import org.openapitools.codegen.plugin.stubs.StubUtility;
import java.io.File;
import java.util.Map;
public class CodeGenMojoTest extends BaseTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
}
@SuppressWarnings("unchecked")
public void testCommonConfiguration() throws Exception {
File testPom = StubUtility.basedPath(getUnitTestDir().toFile(), "common-maven", "common-maven.xml").toFile();
final CodeGenMojo mojo = (CodeGenMojo) lookupMojo("generate", testPom);
mojo.execute();
assertEquals("java", getVariableValueFromObject(mojo, "generatorName"));
assertEquals("jersey2", getVariableValueFromObject(mojo, "library"));
assertEquals("remote.org.openapitools.client.api", getVariableValueFromObject(mojo, "apiPackage"));
assertEquals("remote.org.openapitools.client.model", getVariableValueFromObject(mojo, "modelPackage"));
assertEquals("remote.org.openapitools.client", getVariableValueFromObject(mojo, "invokerPackage"));
Map<String, Object> configOptions = (Map<String, Object>) getVariableValueFromObject(mojo, "configOptions");
assertNotNull(configOptions);
assertEquals("joda", configOptions.get("dateLibrary"));
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.plugin.stubs;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
public class CommonMavenProjectStub extends MavenProjectStub {
public CommonMavenProjectStub() {
StubUtility.configureStub(this,"common-maven", "common-maven.xml");
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.plugin.stubs;
import org.apache.maven.model.Build;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.testing.stubs.ArtifactStub;
import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public abstract class StubUtility {
private StubUtility() {
throw new UnsupportedOperationException("Utility class");
}
/**
* Configures a stub to conventional directories based on test name and pom file name.
* <p>
* Taken largely from PMD plugin:
* https://github.com/apache/maven-pmd-plugin/blob/d766fdb0c93a6630ad7a788f260746b05c804a71/src/test/java/org/apache/maven/plugins/pmd/stubs/CustomConfigurationMavenProjectStub.java
* License: Apache 2.0
*
* @param configure The stub to configure
* @param testName A name used to identify this stub, used in resource lookup
* @param pomFileName The filename and extension, e.g. "my-test-pom.xml"
*/
public static void configureStub(MavenProjectStub configure, String testName, String pomFileName) {
MavenXpp3Reader pomReader = new MavenXpp3Reader();
Model model = null;
try {
File pomFile = basedPath(
configure.getBasedir(), "src", "test", "resources", "unit", testName, pomFileName
).toFile();
model = pomReader.read(new InputStreamReader(new FileInputStream(pomFile), StandardCharsets.UTF_8));
configure.setModel(model);
} catch (Exception ignored) {
}
configure.setGroupId(model.getGroupId());
configure.setArtifactId(model.getArtifactId());
configure.setVersion(model.getVersion());
configure.setName(model.getName());
configure.setUrl(model.getUrl());
configure.setPackaging(model.getPackaging());
Build build = new Build();
build.setFinalName(model.getBuild().getFinalName());
build.setDirectory(basedPath(configure.getBasedir(), "target", "test", "unit", testName, "target").toString());
build.setSourceDirectory(basedPath(configure.getBasedir(), "src", "test", "resources", "unit", testName).toString());
configure.setBuild(build);
List<String> compileSourceRoots = new ArrayList<>();
compileSourceRoots.add(basedPath(configure.getBasedir(), "src", "test", "resources", "unit", testName, "src").toString());
configure.setCompileSourceRoots(compileSourceRoots);
ArtifactStub artifactStub = new ArtifactStub();
artifactStub.setGroupId(configure.getGroupId());
artifactStub.setArtifactId(configure.getArtifactId());
artifactStub.setVersion(configure.getVersion());
artifactStub.setArtifactHandler(new DefaultArtifactHandlerStub("jar"));
configure.setArtifact(artifactStub);
configure.setFile(configure.getBasedir().toPath().resolve(pomFileName).toFile());
}
public static Path basedPath(File baseDir, String first, String... more) {
return baseDir.toPath().resolve(Paths.get(first, more)).normalize().toAbsolutePath();
}
}

View File

@ -0,0 +1,56 @@
<!--
~ Copyright 2020 OpenAPI-Generator Contributors (https://openapi-generator.tech)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>common.maven</groupId>
<artifactId>common-maven</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>OpenAPI Generator Configuration Test</name>
<url>https://openapi-generator.tech/</url>
<build>
<finalName>common-maven</finalName>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<configuration>
<project implementation="org.openapitools.codegen.plugin.stubs.CommonMavenProjectStub"/>
<inputSpec>${basedir}/src/test/resources/unit/common-maven/petstore.yaml</inputSpec>
<generatorName>java</generatorName>
<configOptions>
<dateLibrary>joda</dateLibrary>
</configOptions>
<library>jersey2</library>
<output>${basedir}/target/generated-sources/common-maven/remote-openapi</output>
<apiPackage>remote.org.openapitools.client.api</apiPackage>
<modelPackage>remote.org.openapitools.client.model</modelPackage>
<invokerPackage>remote.org.openapitools.client</invokerPackage>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,736 @@
openapi: 3.0.0
servers:
- url: 'http://petstore.swagger.io/v2'
info:
description: >-
This is a sample server Petstore server. For this sample, you can use the api key
`special-key` to test the authorization filters.
version: 1.0.0
title: OpenAPI Petstore
license:
name: Apache-2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
tags:
- name: pet
description: Everything about your Pets
- name: store
description: Access to Petstore orders
- name: user
description: Operations about user
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
$ref: '#/components/requestBodies/Pet'
put:
tags:
- pet
summary: Update an existing pet
description: ''
operationId: updatePet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
$ref: '#/components/requestBodies/Pet'
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: true
style: form
explode: false
schema:
type: array
items:
type: string
enum:
- available
- pending
- sold
default: available
responses:
'200':
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid status value
security:
- petstore_auth:
- 'read:pets'
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: >-
Multiple tags can be provided with comma separated strings. Use tag1,
tag2, tag3 for testing.
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: true
style: form
explode: false
schema:
type: array
items:
type: string
responses:
'200':
description: successful operation
content:
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- 'read:pets'
deprecated: true
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: integer
format: int64
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
description: Updated name of the pet
type: string
status:
description: Updated status of the pet
type: string
delete:
tags:
- pet
summary: Deletes a pet
description: ''
operationId: deletePet
parameters:
- name: api_key
in: header
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid pet value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
'/pet/{petId}/uploadImage':
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
additionalMetadata:
description: Additional data to pass to server
type: string
file:
description: file to upload
type: string
format: binary
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: ''
operationId: placeOrder
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid Order
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
description: order placed for purchasing the pet
required: true
'/store/order/{orderId}':
get:
tags:
- store
summary: Find purchase order by ID
description: >-
For valid response try integer IDs with value <= 5 or > 10. Other values
will generated exceptions
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of pet that needs to be fetched
required: true
schema:
type: integer
format: int64
minimum: 1
maximum: 5
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Order'
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: >-
For valid response try integer IDs with value < 1000. Anything above
1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
responses:
default:
description: successful operation
security:
- api_key: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
description: Created user object
required: true
/user/createWithArray:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithArrayInput
responses:
default:
description: successful operation
security:
- api_key: []
requestBody:
$ref: '#/components/requestBodies/UserArray'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithListInput
responses:
default:
description: successful operation
security:
- api_key: []
requestBody:
$ref: '#/components/requestBodies/UserArray'
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ''
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: true
schema:
type: string
pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$'
- name: password
in: query
description: The password for login in clear text
required: true
schema:
type: string
responses:
'200':
description: successful operation
headers:
Set-Cookie:
description: >-
Cookie authentication key for use with the `api_key`
apiKey authentication.
schema:
type: string
example: AUTH_KEY=abcde12345; Path=/; HttpOnly
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
type: integer
format: int32
X-Expires-After:
description: date in UTC when toekn expires
schema:
type: string
format: date-time
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
responses:
default:
description: successful operation
security:
- api_key: []
'/user/{username}':
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
parameters:
- name: username
in: path
description: The name that needs to be fetched. Use user1 for testing.
required: true
schema:
type: string
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/User'
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Updated user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid user supplied
'404':
description: User not found
security:
- api_key: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
description: Updated user object
required: true
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
security:
- api_key: []
externalDocs:
description: Find out more about Swagger
url: 'http://swagger.io'
components:
requestBodies:
UserArray:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
description: List of user object
required: true
Pet:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
description: Pet object that needs to be added to the store
required: true
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
scopes:
'write:pets': modify pets in your account
'read:pets': read your pets
api_key:
type: apiKey
name: api_key
in: header
schemas:
Order:
title: Pet Order
description: An order for a pets from the pet store
type: object
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
enum:
- placed
- approved
- delivered
complete:
type: boolean
default: false
xml:
name: Order
Category:
title: Pet category
description: A category for a pet
type: object
properties:
id:
type: integer
format: int64
name:
type: string
pattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$'
xml:
name: Category
User:
title: a User
description: A User who is purchasing from the pet store
type: object
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
xml:
name: User
Tag:
title: Pet Tag
description: A tag for a pet
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Tag
Pet:
title: a Pet
description: A pet for sale in the pet store
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: '#/components/schemas/Category'
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
tags:
type: array
xml:
name: tag
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: Pet
ApiResponse:
title: An uploaded response
description: Describes the result of uploading an image resource
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string

View File

@ -0,0 +1,7 @@
package com.example;
public class Example {
public static void main(String[] args) {
System.out.println("You did it!");
}
}

View File

@ -6,6 +6,7 @@ import org.openapitools.codegen.TemplateManager;
import org.openapitools.codegen.api.TemplatePathLocator; import org.openapitools.codegen.api.TemplatePathLocator;
import java.io.File; import java.io.File;
import java.nio.file.Paths;
/** /**
* Locates templates according to {@link CodegenConfig} settings. * Locates templates according to {@link CodegenConfig} settings.
@ -23,7 +24,7 @@ public class GeneratorTemplateContentLocator implements TemplatePathLocator {
} }
private String buildLibraryFilePath(String dir, String library, String file) { private String buildLibraryFilePath(String dir, String library, String file) {
return dir + File.separator + "libraries" + File.separator + library + File.separator + file; return Paths.get(dir, "libraries", library, file).normalize().toString();
} }
/** /**
@ -34,6 +35,10 @@ public class GeneratorTemplateContentLocator implements TemplatePathLocator {
* @return true if file is an embedded resource, false if it does not exist * @return true if file is an embedded resource, false if it does not exist
*/ */
public boolean embeddedTemplateExists(String name) { public boolean embeddedTemplateExists(String name) {
return classpathTemplateExists(name);
}
private boolean classpathTemplateExists(String name) {
return this.getClass().getClassLoader().getResource(TemplateManager.getCPResourcePath(name)) != null; return this.getClass().getClassLoader().getResource(TemplateManager.getCPResourcePath(name)) != null;
} }
@ -60,20 +65,26 @@ public class GeneratorTemplateContentLocator implements TemplatePathLocator {
if (StringUtils.isNotEmpty(library)) { if (StringUtils.isNotEmpty(library)) {
//look for the file in the library subfolder of the supplied template //look for the file in the library subfolder of the supplied template
final String libTemplateFile = buildLibraryFilePath(config.templateDir(), library, relativeTemplateFile); final String libTemplateFile = buildLibraryFilePath(config.templateDir(), library, relativeTemplateFile);
if (new File(libTemplateFile).exists() || this.getClass().getClassLoader().getResource(libTemplateFile) != null) { // looks for user-defined file or classpath
// supports template dir which refers to local file system or custom path in classpath as defined by templateDir
if (new File(libTemplateFile).exists() || classpathTemplateExists(libTemplateFile)) {
return libTemplateFile; return libTemplateFile;
} }
} }
//check the supplied template main folder for the file // check the supplied template main folder for the file
// File.separator is necessary here as the file load is OS-specific
final String template = config.templateDir() + File.separator + relativeTemplateFile; final String template = config.templateDir() + File.separator + relativeTemplateFile;
if (new File(template).exists() || this.getClass().getClassLoader().getResource(template) != null) { // looks for user-defined file or classpath
// supports template dir which refers to local file system or custom path in classpath as defined by templateDir
if (new File(template).exists() || classpathTemplateExists(template)) {
return template; return template;
} }
//try the embedded template library folder next //try the embedded template library folder next
if (StringUtils.isNotEmpty(library)) { if (StringUtils.isNotEmpty(library)) {
final String embeddedLibTemplateFile = buildLibraryFilePath(config.embeddedTemplateDir(), library, relativeTemplateFile); final String embeddedLibTemplateFile = buildLibraryFilePath(config.embeddedTemplateDir(), library, relativeTemplateFile);
// *only* looks for those files in classpath as defined by embeddedTemplateDir
if (embeddedTemplateExists(embeddedLibTemplateFile)) { if (embeddedTemplateExists(embeddedLibTemplateFile)) {
// Fall back to the template file embedded/packaged in the JAR file library folder... // Fall back to the template file embedded/packaged in the JAR file library folder...
return embeddedLibTemplateFile; return embeddedLibTemplateFile;
@ -82,6 +93,7 @@ public class GeneratorTemplateContentLocator implements TemplatePathLocator {
// Fall back to the template file for generator root directory embedded/packaged in the JAR file... // Fall back to the template file for generator root directory embedded/packaged in the JAR file...
String loc = config.embeddedTemplateDir() + File.separator + relativeTemplateFile; String loc = config.embeddedTemplateDir() + File.separator + relativeTemplateFile;
// *only* looks for those files in classpath as defined by embeddedTemplateDir
if (embeddedTemplateExists(loc)) { if (embeddedTemplateExists(loc)) {
return loc; return loc;
} }

View File

@ -433,4 +433,208 @@ public class DefaultGeneratorTest {
Assert.assertEquals(((Schema) codegenResponse.schema).getPattern(), expectedPattern); Assert.assertEquals(((Schema) codegenResponse.schema).getPattern(), expectedPattern);
Assert.assertEquals(codegenResponse.pattern, escapedPattern); Assert.assertEquals(codegenResponse.pattern, escapedPattern);
} }
@Test
public void testBuiltinLibraryTemplates() throws IOException {
Path target = Files.createTempDirectory("test");
File output = target.toFile();
try {
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("kotlin")
.setLibrary("jvm-okhttp4")
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString());
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 20);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
// Generated file should exist on the filesystem after generation
File generatedFile = new File(output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
Assert.assertTrue(generatedFile.exists());
// Generated file should contain some expected text
TestUtils.assertFileContains(generatedFile.toPath(), "package org.openapitools.client.infrastructure",
"open class ClientException",
"open class ServerException");
} finally {
output.delete();
}
}
@Test
public void testBuiltinNonLibraryTemplates() throws IOException {
Path target = Files.createTempDirectory("test");
File output = target.toFile();
try {
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("kotlin")
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString());
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 20);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
// Generated file should exist on the filesystem after generation
File readme = new File(output, "README.md");
Assert.assertTrue(readme.exists());
// README.md should contain some expected text
TestUtils.assertFileContains(readme.toPath(), "# org.openapitools.client - Kotlin client library for OpenAPI Petstore",
"## Requires",
"## Build",
"## Features/Implementation Notes");
} finally {
output.delete();
}
}
@Test
public void testCustomLibraryTemplates() throws IOException {
Path target = Files.createTempDirectory("test");
Path templates = Files.createTempDirectory("templates");
File output = target.toFile();
try {
// Create custom template
File customTemplate = new File(templates.toFile(), "libraries/jvm-okhttp/infrastructure/Errors.kt.mustache");
new File(customTemplate.getParent()).mkdirs();
StringBuilder sb = new StringBuilder();
sb.append("// {{someKey}}").append("\n");
sb.append("@file:Suppress(\"unused\")").append("\n");
sb.append("package org.openapitools.client.infrastructure").append("\n");
sb.append("import java.lang.RuntimeException").append("\n");
sb.append("open class CustomException(").append("\n");
sb.append(" message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) {").append("\n");
sb.append(" companion object {").append("\n");
sb.append(" private const val serialVersionUID: Long = 789L").append("\n");
sb.append(" }").append("\n");
sb.append("}").append("\n");
Files.write(customTemplate.toPath(),
sb.toString().getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE);
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("kotlin")
.addAdditionalProperty("someKey", "testCustomLibraryTemplates")
.setTemplateDir(templates.toAbsolutePath().toString())
.setLibrary("jvm-okhttp4")
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString());
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 20);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
// Generated file should exist on the filesystem after generation
File readme = new File(output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
Assert.assertTrue(readme.exists());
// Generated file should contain our custom templated text
TestUtils.assertFileContains(readme.toPath(), "// testCustomLibraryTemplates",
"package org.openapitools.client.infrastructure",
"open class CustomException(",
"private const val serialVersionUID: Long = 789L");
} finally {
output.delete();
templates.toFile().delete();
}
}
@Test
public void testCustomNonLibraryTemplates() throws IOException {
Path target = Files.createTempDirectory("test");
Path templates = Files.createTempDirectory("templates");
File output = target.toFile();
try {
// Create custom template
File customTemplate = new File(templates.toFile(), "README.mustache");
new File(customTemplate.getParent()).mkdirs();
Files.write(customTemplate.toPath(),
"# {{someKey}}".getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE);
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("kotlin")
.addAdditionalProperty("someKey", "testCustomNonLibraryTemplates")
.setTemplateDir(templates.toAbsolutePath().toString())
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString());
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.API_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.API_TESTS, "false");
List<File> files = generator.opts(clientOptInput).generate();
Assert.assertEquals(files.size(), 20);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
// Generated file should exist on the filesystem after generation
File readme = new File(output, "README.md");
Assert.assertTrue(readme.exists());
// README.md should contain our custom templated text
TestUtils.assertFileContains(readme.toPath(), "# testCustomNonLibraryTemplates");
} finally {
output.delete();
templates.toFile().delete();
}
}
} }