Convert groovy to java (spring-cloud-contract-verifier module) (#1476)
* Convert groovy to java (gh-1470) Co-authored-by: Anatolii Zhmaiev <Anatolii_Zhmaiev@epam.com>
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardOpenOption
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.util.logging.Commons
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.packageToDirectory
|
||||
|
||||
@CompileStatic
|
||||
@PackageScope
|
||||
@Commons
|
||||
class FileSaver {
|
||||
|
||||
private final File targetDirectory
|
||||
private final SingleTestGenerator generator
|
||||
private final String fileExtension
|
||||
|
||||
FileSaver(File targetDirectory, String fileExtension, SingleTestGenerator generator) {
|
||||
this.targetDirectory = targetDirectory
|
||||
this.generator = generator
|
||||
this.fileExtension = fileExtension
|
||||
}
|
||||
|
||||
void saveClassFile(Path classPath, byte[] classBytes) {
|
||||
log.info("Creating new class file [$classPath]")
|
||||
Files.
|
||||
write(classPath, classBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
||||
}
|
||||
|
||||
protected Path pathToClass(Path testBaseDir, String fileName) {
|
||||
return Paths.get(testBaseDir.toString(),
|
||||
capitalize(fileName) + fileExtension).toAbsolutePath()
|
||||
}
|
||||
|
||||
protected Path generateTestBaseDir(String basePackageClass, String includedDirectoryRelativePath) {
|
||||
Path testBaseDir = Paths.
|
||||
get(targetDirectory.absolutePath, packageToDirectory(basePackageClass),
|
||||
beforeLast(includedDirectoryRelativePath, File.separator))
|
||||
Files.createDirectories(testBaseDir)
|
||||
return testBaseDir
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import groovy.transform.CompileDynamic
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractVerifierException
|
||||
import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.file.ContractFileScanner
|
||||
import org.springframework.cloud.contract.verifier.file.ContractFileScannerBuilder
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader
|
||||
import org.springframework.util.MultiValueMap
|
||||
import org.springframework.util.StringUtils
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.afterLast
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
@CompileStatic
|
||||
class TestGenerator {
|
||||
|
||||
private static final String DEFAULT_CLASS_PREFIX = "ContractVerifier"
|
||||
private static final String DEFAULT_TEST_PACKAGE = "org.springframework.cloud.contract.verifier.tests"
|
||||
private static final Log log = LogFactory.getLog(TestGenerator)
|
||||
|
||||
private final ContractVerifierConfigProperties configProperties
|
||||
private AtomicInteger counter = new AtomicInteger()
|
||||
private SingleTestGenerator generator
|
||||
private FileSaver saver
|
||||
private ContractFileScanner contractFileScanner
|
||||
|
||||
TestGenerator(ContractVerifierConfigProperties configProperties) {
|
||||
this(configProperties, singleTestGenerator(),
|
||||
new FileSaver(configProperties.generatedTestSourcesDir, configProperties.testFramework.classExtension,
|
||||
singleTestGenerator()))
|
||||
}
|
||||
|
||||
private static SingleTestGenerator singleTestGenerator() {
|
||||
List<SingleTestGenerator> factories = SpringFactoriesLoader.
|
||||
loadFactories(SingleTestGenerator, null)
|
||||
if (factories.empty) {
|
||||
return new JavaTestGenerator()
|
||||
}
|
||||
return factories.first()
|
||||
}
|
||||
|
||||
TestGenerator(ContractVerifierConfigProperties configProperties, SingleTestGenerator generator, FileSaver saver) {
|
||||
this.configProperties = configProperties
|
||||
if (configProperties.contractsDslDir == null) {
|
||||
throw new ContractVerifierException("Stubs directory not found under " + configProperties.contractsDslDir)
|
||||
}
|
||||
this.generator = generator
|
||||
this.saver = saver
|
||||
contractFileScanner = new ContractFileScannerBuilder()
|
||||
.baseDir(configProperties.contractsDslDir)
|
||||
.excluded(configProperties.excludedFiles as Set)
|
||||
.ignored(configProperties.ignoredFiles as Set)
|
||||
.included(configProperties.includedFiles as Set)
|
||||
.includeMatcher(this.configProperties.includedContracts)
|
||||
.build()
|
||||
}
|
||||
|
||||
protected TestGenerator(ContractVerifierConfigProperties configProperties, SingleTestGenerator generator, FileSaver saver, ContractFileScanner contractFileScanner) {
|
||||
this.configProperties = configProperties
|
||||
if (configProperties.contractsDslDir == null) {
|
||||
throw new ContractVerifierException("Stubs directory not found under " + configProperties.contractsDslDir)
|
||||
}
|
||||
this.generator = generator
|
||||
this.saver = saver
|
||||
this.contractFileScanner = contractFileScanner
|
||||
}
|
||||
|
||||
int generate() {
|
||||
generateTestClasses(basePackageName())
|
||||
NamesUtil.recrusiveDirectoryToPackage(configProperties.generatedTestSourcesDir)
|
||||
NamesUtil.recrusiveDirectoryToPackage(configProperties.generatedTestResourcesDir)
|
||||
return counter.get()
|
||||
}
|
||||
|
||||
private String basePackageName() {
|
||||
if (configProperties.basePackageForTests) {
|
||||
return configProperties.basePackageForTests
|
||||
}
|
||||
else if (configProperties.baseClassForTests) {
|
||||
return toLastDot(configProperties.baseClassForTests)
|
||||
}
|
||||
else if (configProperties.packageWithBaseClasses) {
|
||||
return configProperties.packageWithBaseClasses
|
||||
}
|
||||
return DEFAULT_TEST_PACKAGE
|
||||
}
|
||||
|
||||
@PackageScope
|
||||
void generateTestClasses(final String basePackageName) {
|
||||
MultiValueMap<Path, ContractMetadata> contracts = contractFileScanner.
|
||||
findContractsRecursively()
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found the following contracts " + contracts.keySet())
|
||||
}
|
||||
Set<Map.Entry<Path,List<ContractMetadata>>> inProgress = inProgress(contracts)
|
||||
if (!inProgress.isEmpty() && configProperties.failOnInProgress) {
|
||||
throw new IllegalStateException("In progress contracts found in paths [" + inProgress.collect { it.key.toString() }.join(",") + "] and the switch [failOnInProgress] is set to [true]. Either unmark those contracts as in progress, or set the switch to [false].")
|
||||
}
|
||||
processAllNotInProgress(contracts,basePackageName)
|
||||
}
|
||||
|
||||
@CompileDynamic
|
||||
private Set<Map.Entry<Path,List<ContractMetadata>>> inProgress(MultiValueMap<Path,ContractMetadata> contracts) {
|
||||
return contracts.entrySet()
|
||||
.findAll { Map.Entry<Path, List<ContractMetadata>> entry -> entry.getValue().any { it.anyInProgress() }}
|
||||
}
|
||||
|
||||
@PackageScope
|
||||
@CompileDynamic
|
||||
Set<Map.Entry<Path,List<ContractMetadata>>> processAllNotInProgress(MultiValueMap<Path,ContractMetadata> contracts, String basePackageName) {
|
||||
contracts.entrySet()
|
||||
.findAll { Map.Entry<Path, List<ContractMetadata>> entry -> !entry.value.any { it.anyInProgress() }}
|
||||
.each {
|
||||
Map.Entry<Path, List<ContractMetadata>> entry ->
|
||||
processIncludedDirectory(
|
||||
relativizeContractPath(entry), (Collection<ContractMetadata>) entry.
|
||||
getValue(), basePackageName)
|
||||
}
|
||||
}
|
||||
|
||||
private String relativizeContractPath(Map.Entry<Path, List<ContractMetadata>> entry) {
|
||||
Path relativePath = configProperties.contractsDslDir.toPath().
|
||||
relativize(entry.getKey())
|
||||
if (StringUtils.isEmpty(relativePath.toString())) {
|
||||
return DEFAULT_CLASS_PREFIX
|
||||
}
|
||||
return relativePath.toString()
|
||||
}
|
||||
|
||||
private void processIncludedDirectory(
|
||||
final String includedDirectoryRelativePath, Collection<ContractMetadata> contracts, final String basePackageNameForClass) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Collected contracts with metadata ${contracts} relative path is [${includedDirectoryRelativePath}]")
|
||||
}
|
||||
if (contracts.size()) {
|
||||
def className = afterLast(includedDirectoryRelativePath.toString(), File.separator) + resolveNameSuffix()
|
||||
def convertedClassName = convertIllegalPackageChars(className)
|
||||
def packageName =
|
||||
buildPackage(basePackageNameForClass, includedDirectoryRelativePath)
|
||||
Path dir = saver.generateTestBaseDir(basePackageNameForClass,
|
||||
convertIllegalPackageChars(includedDirectoryRelativePath.toString()))
|
||||
Path classPath = saver.pathToClass(dir, convertedClassName)
|
||||
def classBytes = generator.
|
||||
buildClass(configProperties, contracts, includedDirectoryRelativePath,
|
||||
new SingleTestGenerator.GeneratedClassData(convertedClassName, packageName, classPath)).
|
||||
getBytes(StandardCharsets.UTF_8)
|
||||
saver.saveClassFile(classPath, classBytes)
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveNameSuffix() {
|
||||
return configProperties.nameSuffixForTests ?: configProperties.testFramework.classNameSuffix
|
||||
}
|
||||
|
||||
protected static String buildPackage(final String packageNameForClass, final String includedDirectoryRelativePath) {
|
||||
String directory = beforeLast(includedDirectoryRelativePath, File.separator)
|
||||
String convertedPackage = "$packageNameForClass.${directoryToPackage(convertIllegalPackageChars(directory))}"
|
||||
return !directory.empty ? convertedPackage : packageNameForClass
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.builder
|
||||
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
/**
|
||||
* Builds a block of code. Allows to start, end, indent etc. pieces of code.
|
||||
*
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class BlockBuilder {
|
||||
|
||||
private final StringBuilder builder
|
||||
private final String spacer
|
||||
private int indents
|
||||
private String lineEnding = ""
|
||||
private String labelPrefix = ""
|
||||
|
||||
/**
|
||||
* @param spacer - char used for spacing
|
||||
*/
|
||||
BlockBuilder(String spacer) {
|
||||
this.spacer = spacer
|
||||
builder = new StringBuilder()
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup line ending
|
||||
*/
|
||||
BlockBuilder setupLineEnding(String lineEnding) {
|
||||
this.lineEnding = lineEnding
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup label prefix
|
||||
*/
|
||||
BlockBuilder setupLabelPrefix(String labelPrefix) {
|
||||
this.labelPrefix = labelPrefix
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
String getLineEnding() {
|
||||
return this.lineEnding
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
BlockBuilder appendWithLabelPrefix(String label) {
|
||||
return append(this.labelPrefix).append(label)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
BlockBuilder startBlock() {
|
||||
indents++
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends block by removing indents
|
||||
*/
|
||||
BlockBuilder endBlock() {
|
||||
indents--
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block and adds indents
|
||||
*/
|
||||
BlockBuilder indent() {
|
||||
startBlock().startBlock()
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes indents and closes the block
|
||||
*/
|
||||
BlockBuilder unindent() {
|
||||
endBlock().endBlock()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addLine(String line) {
|
||||
return addIndented(line).append("\n")
|
||||
}
|
||||
|
||||
BlockBuilder addIndented(String line) {
|
||||
return addIndentation().append(line)
|
||||
}
|
||||
|
||||
BlockBuilder addIndented(Runnable runnable) {
|
||||
addIndentation()
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addLineWithEnding(String line) {
|
||||
addIndentation()
|
||||
append(line).addEndingIfNotPresent().addEmptyLine()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addEndingIfNotPresent() {
|
||||
addAtTheEnd(lineEnding)
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addEmptyLine() {
|
||||
builder << '\n'
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder appendWithSpace(String text) {
|
||||
return addAtTheEnd(" ").append(text)
|
||||
}
|
||||
|
||||
BlockBuilder appendWithSpace(Runnable runnable) {
|
||||
addAtTheEnd(" ")
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
// synactic sugar
|
||||
BlockBuilder append(Runnable runnable) {
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder append(String string) {
|
||||
builder << string
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addIndentation() {
|
||||
indents.times {
|
||||
builder << spacer
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
@PackageScope
|
||||
BlockBuilder inBraces(Runnable runnable) {
|
||||
builder.append("{\n")
|
||||
startBlock()
|
||||
runnable.run()
|
||||
endBlock()
|
||||
addAtTheEnd('\n')
|
||||
addLine("}")
|
||||
return this
|
||||
}
|
||||
|
||||
boolean endsWith(String text) {
|
||||
return builder.toString().endsWith(text)
|
||||
}
|
||||
|
||||
BlockBuilder addAtTheEndIfEndsWithAChar(String toAdd) {
|
||||
char lastChar = builder.charAt(builder.length() - 1)
|
||||
if (Character.isLetter(lastChar)) {
|
||||
builder.append(toAdd)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given text at the end of the line
|
||||
*
|
||||
* @return updated BlockBuilder
|
||||
*/
|
||||
BlockBuilder addAtTheEnd(String toAdd) {
|
||||
String lastChar = builder.charAt(builder.length() - 1) as String
|
||||
String secondLastChar = builder.length() >= 2 ? builder.
|
||||
charAt(builder.length() - 2) as String : ""
|
||||
boolean isEndWithNewLine = endsWithNewLine(lastChar)
|
||||
boolean lastCharSpecial = aSpecialSign(lastChar, toAdd)
|
||||
boolean secondLastCharSpecial = aSpecialSign(secondLastChar, toAdd)
|
||||
boolean lineEndingToAdd = toAdd == lineEnding
|
||||
// lastChar = [;] , toAdd = [;]
|
||||
if (lastChar == toAdd) {
|
||||
return this
|
||||
}
|
||||
// secondLastChar = [ ], lastChar = [{] , toAdd = [;]
|
||||
else if ((!isEndWithNewLine && lastCharSpecial) && lineEndingToAdd) {
|
||||
return this
|
||||
}
|
||||
// secondLastChar = [{], lastChar = [\n] , toAdd = [;]
|
||||
else if (isEndWithNewLine && secondLastCharSpecial) {
|
||||
return this
|
||||
}
|
||||
else if (isEndWithNewLine && !secondLastCharSpecial) {
|
||||
builder.replace(builder.length() - 1, builder.length(), toAdd)
|
||||
builder << '\n'
|
||||
}
|
||||
else {
|
||||
builder << toAdd
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private boolean endsWithNewLine(String character) {
|
||||
return character as String == '\n'
|
||||
}
|
||||
|
||||
private boolean aSpecialSign(String character, String toAdd) {
|
||||
if (!character) {
|
||||
return false
|
||||
}
|
||||
return character == "{" ||
|
||||
(character == spacer && toAdd == spacer) ||
|
||||
(character == spacer && toAdd == " ") ||
|
||||
character == toAdd ||
|
||||
(endsWithNewLine(character) &&
|
||||
(toAdd == '\n' || toAdd == " " || toAdd == lineEnding))
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current text with the provided one
|
||||
*
|
||||
* @param contents - text to replace the current content with
|
||||
* @return updated Block Builder
|
||||
*/
|
||||
BlockBuilder updateContents(String contents) {
|
||||
this.builder.replace(0, this.builder.length(), contents)
|
||||
return this
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
return builder.toString()
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.builder.imports
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.CUSTOM
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT5
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.SPOCK
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.TESTNG
|
||||
|
||||
/**
|
||||
* Provides imports based on test framework.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @deprecated
|
||||
*/
|
||||
@CompileStatic
|
||||
@Deprecated
|
||||
class BaseImportProvider {
|
||||
|
||||
private static final ImportDefinitions GENERAL_IMPORTS = new ImportDefinitions([], [
|
||||
'org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat',
|
||||
'org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*'
|
||||
])
|
||||
|
||||
private static
|
||||
final Map<TestFramework, ImportDefinitions> TEST_FRAMEWORK_SPECIFIC_IMPORTS = [
|
||||
(JUNIT) : new ImportDefinitions(['org.junit.Test']),
|
||||
(JUNIT5): new ImportDefinitions(['org.junit.jupiter.api.Test']),
|
||||
(SPOCK) : new ImportDefinitions([]),
|
||||
(TESTNG): new ImportDefinitions(['org.testng.annotations.Test']),
|
||||
(CUSTOM): new ImportDefinitions([])]
|
||||
|
||||
private static final Map<TestFramework, String> RULE_IMPORT = [
|
||||
(JUNIT) : 'org.junit.Rule',
|
||||
(JUNIT5): 'org.junit.jupiter.api.extension.ExtendWith',
|
||||
(SPOCK) : 'org.junit.Rule',
|
||||
(TESTNG): 'org.junit.Rule',
|
||||
(CUSTOM): 'org.junit.Rule'
|
||||
]
|
||||
|
||||
/**
|
||||
* Returns list of imports for provided test framework.
|
||||
* @param testFramework
|
||||
* @return list of imports
|
||||
*/
|
||||
static List<String> getImports(TestFramework testFramework) {
|
||||
return GENERAL_IMPORTS.imports +
|
||||
TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).imports
|
||||
}
|
||||
|
||||
/**
|
||||
* @param testFramework test framework to pick the static imports for
|
||||
* @return list of static imports for provided test framework.
|
||||
*/
|
||||
static List<String> getStaticImports(TestFramework testFramework) {
|
||||
return GENERAL_IMPORTS.staticImports +
|
||||
TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).staticImports
|
||||
}
|
||||
|
||||
static String getRuleImport(TestFramework testFramework) {
|
||||
return RULE_IMPORT.get(testFramework)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.builder.imports
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework
|
||||
import org.springframework.cloud.contract.verifier.config.TestMode
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.CUSTOM
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT5
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.SPOCK
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.TESTNG
|
||||
import static org.springframework.cloud.contract.verifier.config.TestMode.EXPLICIT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestMode.JAXRSCLIENT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestMode.MOCKMVC
|
||||
import static org.springframework.cloud.contract.verifier.config.TestMode.WEBTESTCLIENT
|
||||
|
||||
/**
|
||||
* Provides imports based on test framework and test mode.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@Deprecated
|
||||
class HttpImportProvider {
|
||||
|
||||
private final Map<TestMode, ImportDefinitions> TEST_MODE_SPECIFIC_IMPORTS = [
|
||||
(JAXRSCLIENT) : new ImportDefinitions([], ['javax.ws.rs.client.Entity.*']),
|
||||
(MOCKMVC) : new ImportDefinitions([], ["${restAssuredPackage}.module.mockmvc.RestAssuredMockMvc.*"]),
|
||||
(EXPLICIT) : new ImportDefinitions([], ["${restAssuredPackage}.RestAssured.*"]),
|
||||
(WEBTESTCLIENT): new ImportDefinitions([], ['io.restassured.module.webtestclient.RestAssuredWebTestClient.*'])]
|
||||
|
||||
private final Map<Tuple2<TestFramework, TestMode>, ImportDefinitions> FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS = [
|
||||
(new Tuple2(JUNIT, JAXRSCLIENT)) : new ImportDefinitions(['javax.ws.rs.core.Response']),
|
||||
(new Tuple2(JUNIT5, JAXRSCLIENT)) : new ImportDefinitions(['javax.ws.rs.core.Response']),
|
||||
(new Tuple2(TESTNG, JAXRSCLIENT)) : new ImportDefinitions(['javax.ws.rs.core.Response']),
|
||||
(new Tuple2(JUNIT, MOCKMVC)) : new ImportDefinitions([
|
||||
"${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification",
|
||||
"${restAssuredPackage}.response.ResponseOptions"]),
|
||||
(new Tuple2(JUNIT, WEBTESTCLIENT)) : new ImportDefinitions([
|
||||
'io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification',
|
||||
'io.restassured.module.webtestclient.response.WebTestClientResponse']),
|
||||
(new Tuple2(JUNIT5, MOCKMVC)) : new ImportDefinitions([
|
||||
"${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification",
|
||||
"${restAssuredPackage}.response.ResponseOptions"]),
|
||||
(new Tuple2(JUNIT5, WEBTESTCLIENT)): new ImportDefinitions([
|
||||
'io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification',
|
||||
'io.restassured.module.webtestclient.response.WebTestClientResponse']),
|
||||
(new Tuple2(TESTNG, MOCKMVC)) : new ImportDefinitions([
|
||||
"${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification",
|
||||
"${restAssuredPackage}.response.ResponseOptions"]),
|
||||
(new Tuple2(TESTNG, WEBTESTCLIENT)): new ImportDefinitions([
|
||||
'io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification',
|
||||
'io.restassured.module.webtestclient.response.WebTestClientResponse']),
|
||||
(new Tuple2(JUNIT, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification",
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
(new Tuple2(JUNIT5, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification",
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
(new Tuple2(TESTNG, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification",
|
||||
"${restAssuredPackage}.response.Response"]),
|
||||
(new Tuple2(SPOCK, JAXRSCLIENT)) : new ImportDefinitions([]),
|
||||
(new Tuple2(CUSTOM, JAXRSCLIENT)) : new ImportDefinitions([]),
|
||||
(new Tuple2(SPOCK, MOCKMVC)) : new ImportDefinitions([]),
|
||||
(new Tuple2(CUSTOM, MOCKMVC)) : new ImportDefinitions([]),
|
||||
(new Tuple2(SPOCK, EXPLICIT)) : new ImportDefinitions([]),
|
||||
(new Tuple2(CUSTOM, EXPLICIT)) : new ImportDefinitions([]),
|
||||
(new Tuple2(SPOCK, WEBTESTCLIENT)) : new ImportDefinitions([]),
|
||||
(new Tuple2(CUSTOM, WEBTESTCLIENT)): new ImportDefinitions([])
|
||||
]
|
||||
|
||||
private final String restAssuredPackage
|
||||
|
||||
HttpImportProvider(String restAssuredPackage) {
|
||||
this.restAssuredPackage = restAssuredPackage
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of imports for http test contracts for provided test framework and test mode.
|
||||
* @param testFramework
|
||||
* @param testMode
|
||||
* @return list of imports
|
||||
*/
|
||||
List<String> getImports(TestFramework testFramework, TestMode testMode) {
|
||||
return TEST_MODE_SPECIFIC_IMPORTS.get(testMode).imports +
|
||||
FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS.get(new Tuple2(testFramework, testMode)).imports
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of static imports for http test contracts for provided test framework and test mode.
|
||||
* @param testFramework
|
||||
* @param testMode
|
||||
* @return list of static imports
|
||||
*/
|
||||
List<String> getStaticImports(TestFramework testFramework, TestMode testMode) {
|
||||
return TEST_MODE_SPECIFIC_IMPORTS.get(testMode).staticImports +
|
||||
FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS.get(new Tuple2(testFramework, testMode)).staticImports
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.config.framework
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
/**
|
||||
* Defines elements characteristic of TestNG test framework to be used during test class construction.
|
||||
*
|
||||
* @author André Hoffmann
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class TestNGDefinition implements TestFrameworkDefinition {
|
||||
|
||||
@Override
|
||||
String getClassModifier() {
|
||||
return 'public '
|
||||
}
|
||||
|
||||
@Override
|
||||
String getMethodModifier() {
|
||||
return 'public void '
|
||||
}
|
||||
|
||||
@Override
|
||||
String getLineSuffix() {
|
||||
return ';'
|
||||
}
|
||||
|
||||
@Override
|
||||
String getClassExtension() {
|
||||
'.java'
|
||||
}
|
||||
|
||||
@Override
|
||||
String getClassNameSuffix() {
|
||||
return 'Test'
|
||||
}
|
||||
|
||||
@Override
|
||||
String getIgnoreClass() {
|
||||
throw new UnsupportedOperationException('There is no @Ignore annotation for TestNG. A test can be disabled directly in the @Test annotation')
|
||||
}
|
||||
|
||||
@Override
|
||||
List<String> getOrderAnnotationImports() {
|
||||
throw new UnsupportedOperationException('Not implemented yet in TestNG')
|
||||
}
|
||||
|
||||
@Override
|
||||
String getOrderAnnotation() {
|
||||
throw new UnsupportedOperationException('Not implemented yet in TestNG')
|
||||
}
|
||||
|
||||
@Override
|
||||
String getIgnoreAnnotation() {
|
||||
throw new UnsupportedOperationException('There is no @Ignore annotation for TestNG. A test can be disabled directly in the @Test annotation')
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean annotationLevelRules() {
|
||||
return false
|
||||
}
|
||||
|
||||
@Override
|
||||
String getRuleAnnotation(String annotationValue) {
|
||||
throw new UnsupportedOperationException('Not available in TestNG.')
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.template
|
||||
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.WireMockHelpers
|
||||
import groovy.transform.CompileStatic
|
||||
import wiremock.com.github.jknack.handlebars.Handlebars
|
||||
import wiremock.com.github.jknack.handlebars.Template
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractTemplate
|
||||
import org.springframework.cloud.contract.spec.internal.CompositeContractTemplate
|
||||
import org.springframework.cloud.contract.spec.internal.Request
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel
|
||||
import org.springframework.cloud.contract.verifier.builder.handlebars.HandlebarsJsonPathHelper
|
||||
|
||||
/**
|
||||
* Default Handlebars template processor
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class HandlebarsTemplateProcessor implements TemplateProcessor, ContractTemplate {
|
||||
|
||||
private static final Pattern ESCAPED_LEGACY_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{\\{jsonpath this '(.*)'}}}.*\$")
|
||||
private static final Pattern ESCAPED_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{\\{jsonPath request.body '(.*)'}}}.*\$")
|
||||
private static final Pattern LEGACY_JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{jsonpath this '(.*)'}}.*\$")
|
||||
private static final Pattern JSON_PATH_PATTERN = Pattern.
|
||||
compile("^.*\\{\\{jsonPath request.body '(.*)'}}.*\$")
|
||||
private static final List<Pattern> PATTERNS = [ESCAPED_LEGACY_JSON_PATH_PATTERN,
|
||||
ESCAPED_JSON_PATH_PATTERN, LEGACY_JSON_PATH_PATTERN, JSON_PATH_PATTERN]
|
||||
private static final String LEGACY_JSON_PATH_TEMPLATE_NAME = HandlebarsJsonPathHelper.NAME
|
||||
private static final String JSON_PATH_TEMPLATE_NAME = WireMockHelpers.jsonPath.name()
|
||||
|
||||
final ContractTemplate contractTemplate = new CompositeContractTemplate()
|
||||
|
||||
@Override
|
||||
String transform(Request request, String testContents) {
|
||||
TestSideRequestTemplateModel templateModel = TestSideRequestTemplateModel.
|
||||
from(request)
|
||||
Map<String, TestSideRequestTemplateModel> model = [(HandlebarsJsonPathHelper.REQUEST_MODEL_NAME): templateModel]
|
||||
Template bodyTemplate = uncheckedCompileTemplate(testContents)
|
||||
return templatedResponseBody(model, bodyTemplate)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsTemplateEntry(String line) {
|
||||
return (line.contains(contractTemplate.openingTemplate())
|
||||
&& line.contains(contractTemplate.closingTemplate())) ||
|
||||
(line.contains(contractTemplate.escapedOpeningTemplate()) &&
|
||||
line.contains(contractTemplate.escapedClosingTemplate()))
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsJsonPathTemplateEntry(String line) {
|
||||
return line.contains(openingTemplate() + LEGACY_JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(openingTemplate() + JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + LEGACY_JSON_PATH_TEMPLATE_NAME) ||
|
||||
line.contains(escapedOpeningTemplate() + JSON_PATH_TEMPLATE_NAME)
|
||||
}
|
||||
|
||||
@Override
|
||||
String jsonPathFromTemplateEntry(String line) {
|
||||
if (!containsJsonPathTemplateEntry(line)) {
|
||||
return ""
|
||||
}
|
||||
for (Pattern pattern : PATTERNS) {
|
||||
Matcher matcher = pattern.matcher(line)
|
||||
if (matcher.matches()) {
|
||||
return matcher.group(1)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
private String templatedResponseBody(Map<String, TestSideRequestTemplateModel> model, Template bodyTemplate) {
|
||||
return uncheckedApplyTemplate(bodyTemplate, model)
|
||||
}
|
||||
|
||||
private String uncheckedApplyTemplate(Template template, Object context) {
|
||||
try {
|
||||
return template.apply(context)
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private Template uncheckedCompileTemplate(String content) {
|
||||
try {
|
||||
Handlebars handlebars = new Handlebars()
|
||||
handlebars.
|
||||
registerHelper(HandlebarsJsonPathHelper.NAME, new HandlebarsJsonPathHelper())
|
||||
handlebars.registerHelper(WireMockHelpers.jsonPath.
|
||||
name(), new HandlebarsJsonPathHelper())
|
||||
WireMockHelpers.values()
|
||||
.findAll { it != WireMockHelpers.jsonPath }
|
||||
.each { WireMockHelpers helper ->
|
||||
handlebars.registerHelper(helper.name(), helper)
|
||||
}
|
||||
return handlebars.compileInline(content)
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean startsWithTemplate(String text) {
|
||||
return this.contractTemplate.startsWithTemplate(text)
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean startsWithEscapedTemplate(String text) {
|
||||
return this.contractTemplate.startsWithEscapedTemplate(text)
|
||||
}
|
||||
|
||||
@Override
|
||||
String openingTemplate() {
|
||||
return this.contractTemplate.openingTemplate()
|
||||
}
|
||||
|
||||
@Override
|
||||
String closingTemplate() {
|
||||
return this.contractTemplate.closingTemplate()
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedOpeningTemplate() {
|
||||
return this.contractTemplate.escapedOpeningTemplate()
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedClosingTemplate() {
|
||||
return this.contractTemplate.escapedClosingTemplate()
|
||||
}
|
||||
|
||||
@Override
|
||||
String url() {
|
||||
return this.contractTemplate.url()
|
||||
}
|
||||
|
||||
@Override
|
||||
String query(String key) {
|
||||
return this.contractTemplate.query(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String query(String key, int index) {
|
||||
return this.contractTemplate.query(key, index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String path() {
|
||||
return this.contractTemplate.path()
|
||||
}
|
||||
|
||||
@Override
|
||||
String path(int index) {
|
||||
return this.contractTemplate.path(index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String header(String key) {
|
||||
return this.contractTemplate.header(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String header(String key, int index) {
|
||||
return this.contractTemplate.header(key, index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String cookie(String key) {
|
||||
return this.contractTemplate.cookie(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String body() {
|
||||
return this.contractTemplate.body()
|
||||
}
|
||||
|
||||
@Override
|
||||
String body(String jsonPath) {
|
||||
return this.contractTemplate.body(jsonPath)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedUrl() {
|
||||
return this.contractTemplate.escapedUrl()
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedQuery(String key) {
|
||||
return this.contractTemplate.escapedQuery(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedQuery(String key, int index) {
|
||||
return this.contractTemplate.escapedQuery(key, index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedPath() {
|
||||
return this.contractTemplate.escapedPath()
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedPath(int index) {
|
||||
return this.contractTemplate.escapedPath(index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedHeader(String key) {
|
||||
return this.contractTemplate.escapedHeader(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedHeader(String key, int index) {
|
||||
return this.contractTemplate.escapedHeader(key, index)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedCookie(String key) {
|
||||
return this.contractTemplate.escapedCookie(key)
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedBody() {
|
||||
return this.contractTemplate.escapedBody()
|
||||
}
|
||||
|
||||
@Override
|
||||
String escapedBody(String jsonPath) {
|
||||
return this.contractTemplate.escapedBody(jsonPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.util
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
|
||||
/**
|
||||
* Allows conversion of Contract files to files.
|
||||
*
|
||||
* WARNING: This class is incubating and experimental. It might change in the future.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
final class ToFileContractsTransformer {
|
||||
private static final Log log = LogFactory.getLog(ToFileContractsTransformer.class)
|
||||
|
||||
/**
|
||||
* Dumps contracts as files for the given {@link ContractConverter}
|
||||
*
|
||||
* - argument 1 : FQN - fully qualified name of the {@link ContractConverter} [REQUIRED]
|
||||
* - argument 2 : path - path where the dumped files should be stored [OPTIONAL - defaults to target/converted-contracts]
|
||||
* - argument 3 : path - path were the contracts should be searched for [OPTIONAL - defaults to src/test/resources/contracts]
|
||||
*/
|
||||
static void main(String[] args) {
|
||||
if (args.length == 0) {
|
||||
throw new IllegalStateException(exceptionMessage())
|
||||
}
|
||||
log.warn("You're using an incubating feature. Note, that it can be changed / removed in the future")
|
||||
String fqn = args[0]
|
||||
String outputPath = args.length >= 2 ? args[1] : "target/converted-contracts"
|
||||
String path = args.length >= 3 ? args[2] : "src/test/resources/contracts"
|
||||
new ToFileContractsTransformer().storeContractsAsFiles(path, fqn, outputPath)
|
||||
}
|
||||
|
||||
private static String exceptionMessage() {
|
||||
return "Please provide the FQN of the ContractConverter. E.g. [org.springframework.cloud.contract.verifier.converter.YamlContractConverter]"
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path - path were the contracts should be searched for
|
||||
* @param fqn - fully qualified name of the {@link ContractConverter}
|
||||
* @param outputPath - path where the dumped files should be stored
|
||||
* @return list of dumped files
|
||||
*/
|
||||
final List<File> storeContractsAsFiles(String path, String fqn, String outputPath) {
|
||||
try {
|
||||
log.info("Input path [" + path + "]")
|
||||
log.info("FQN of the converter [" + fqn + "]")
|
||||
log.info("Output path [" + outputPath + "]")
|
||||
Collection<Contract> contracts = ContractScanner.
|
||||
collectContractDescriptors(new File(path))
|
||||
log.info("Found [" + contracts.size() + "] contract definition")
|
||||
Class<?> name = Class.forName(fqn)
|
||||
ContractConverter<Collection> contractConverter = (ContractConverter) name.
|
||||
newInstance()
|
||||
Collection converted = contractConverter.convertTo(contracts)
|
||||
log.info("Successfully converted contracts definitions")
|
||||
Map<String, byte[]> stored = contractConverter.store(converted)
|
||||
File outputFolder = new File(outputPath)
|
||||
outputFolder.mkdirs()
|
||||
int i = 1
|
||||
Set<Map.Entry<String, byte[]>> entries = stored.entrySet()
|
||||
log.info("Will convert [" + entries.size() + "] contracts")
|
||||
List<File> files = new ArrayList<>()
|
||||
for (Map.Entry<String, byte[]> entry : entries) {
|
||||
File outputFile = new File(outputFolder, entry.getKey())
|
||||
Files.write(outputFile.toPath(), entry.getValue())
|
||||
log.info("[" + i + "/"
|
||||
+ entries.
|
||||
size()
|
||||
+ "] Successfully stored ["
|
||||
+ outputFile.getName()
|
||||
+ "]")
|
||||
files.add(outputFile)
|
||||
}
|
||||
return files
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.nio.file.StandardOpenOption.CREATE;
|
||||
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.packageToDirectory;
|
||||
|
||||
class FileSaver {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FileSaver.class);
|
||||
|
||||
private final File targetDirectory;
|
||||
private final String fileExtension;
|
||||
|
||||
FileSaver(File targetDirectory, String fileExtension) {
|
||||
this.targetDirectory = targetDirectory;
|
||||
this.fileExtension = fileExtension;
|
||||
}
|
||||
|
||||
public void saveClassFile(Path classPath, byte[] classBytes) {
|
||||
log.info("Creating new class file [{}]", classPath);
|
||||
try {
|
||||
Files.write(classPath, classBytes, CREATE, TRUNCATE_EXISTING);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Path pathToClass(Path testBaseDir, String fileName) {
|
||||
return Paths.get(testBaseDir.toString(), capitalize(fileName) + fileExtension)
|
||||
.toAbsolutePath();
|
||||
}
|
||||
|
||||
protected Path generateTestBaseDir(String basePackageClass,
|
||||
String includedDirectoryRelativePath) {
|
||||
Path testBaseDir = Paths.get(targetDirectory.getAbsolutePath(),
|
||||
packageToDirectory(basePackageClass),
|
||||
beforeLast(includedDirectoryRelativePath, File.separator));
|
||||
try {
|
||||
Files.createDirectories(testBaseDir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return testBaseDir;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractVerifierException;
|
||||
import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator;
|
||||
import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator;
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractFileScanner;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractFileScannerBuilder;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.afterLast;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.recrusiveDirectoryToPackage;
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot;
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
public class TestGenerator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TestGenerator.class);
|
||||
private static final String DEFAULT_CLASS_PREFIX = "ContractVerifier";
|
||||
private static final String DEFAULT_TEST_PACKAGE = "org.springframework.cloud.contract.verifier.tests";
|
||||
|
||||
private final ContractVerifierConfigProperties configProperties;
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
private final SingleTestGenerator generator;
|
||||
private final FileSaver saver;
|
||||
private final ContractFileScanner contractFileScanner;
|
||||
|
||||
public TestGenerator(ContractVerifierConfigProperties configProperties) {
|
||||
this(configProperties, singleTestGenerator(),
|
||||
new FileSaver(configProperties.getGeneratedTestSourcesDir(),
|
||||
configProperties.getTestFramework().getClassExtension()));
|
||||
}
|
||||
|
||||
private static SingleTestGenerator singleTestGenerator() {
|
||||
List<SingleTestGenerator> factories = SpringFactoriesLoader
|
||||
.loadFactories(SingleTestGenerator.class, null);
|
||||
if (factories.isEmpty()) {
|
||||
return new JavaTestGenerator();
|
||||
}
|
||||
return factories.get(0);
|
||||
}
|
||||
|
||||
public TestGenerator(ContractVerifierConfigProperties configProperties,
|
||||
SingleTestGenerator generator, FileSaver saver) {
|
||||
this(configProperties, generator, saver,
|
||||
new ContractFileScannerBuilder()
|
||||
.baseDir(configProperties.getContractsDslDir())
|
||||
.excluded(toSet(configProperties.getExcludedFiles()))
|
||||
.ignored(toSet(configProperties.getIgnoredFiles()))
|
||||
.included(toSet(configProperties.getIncludedFiles()))
|
||||
.includeMatcher(configProperties.getIncludedContracts()).build());
|
||||
}
|
||||
|
||||
private static Set<String> toSet(List<String> files) {
|
||||
return Optional.ofNullable(files).map(HashSet::new).orElseGet(HashSet::new);
|
||||
}
|
||||
|
||||
protected TestGenerator(ContractVerifierConfigProperties configProperties,
|
||||
SingleTestGenerator generator, FileSaver saver,
|
||||
ContractFileScanner contractFileScanner) {
|
||||
this.configProperties = configProperties;
|
||||
if (configProperties.getContractsDslDir() == null) {
|
||||
throw new ContractVerifierException("Stubs directory not found under "
|
||||
+ configProperties.getContractsDslDir());
|
||||
}
|
||||
|
||||
this.generator = generator;
|
||||
this.saver = saver;
|
||||
this.contractFileScanner = contractFileScanner;
|
||||
}
|
||||
|
||||
public int generate() {
|
||||
generateTestClasses(basePackageName());
|
||||
recrusiveDirectoryToPackage(configProperties.getGeneratedTestSourcesDir());
|
||||
recrusiveDirectoryToPackage(configProperties.getGeneratedTestResourcesDir());
|
||||
return counter.get();
|
||||
}
|
||||
|
||||
private String basePackageName() {
|
||||
if (StringUtils.isNotEmpty(configProperties.getBasePackageForTests())) {
|
||||
return configProperties.getBasePackageForTests();
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(configProperties.getBaseClassForTests())) {
|
||||
return toLastDot(configProperties.getBaseClassForTests());
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(configProperties.getPackageWithBaseClasses())) {
|
||||
return configProperties.getPackageWithBaseClasses();
|
||||
}
|
||||
return DEFAULT_TEST_PACKAGE;
|
||||
}
|
||||
|
||||
void generateTestClasses(final String basePackageName) {
|
||||
MultiValueMap<Path, ContractMetadata> contracts = contractFileScanner
|
||||
.findContractsRecursively();
|
||||
log.debug("Found the following contracts {}", contracts.keySet());
|
||||
|
||||
Set<Map.Entry<Path, List<ContractMetadata>>> inProgress = inProgress(contracts);
|
||||
if (!inProgress.isEmpty() && configProperties.isFailOnInProgress()) {
|
||||
String inProgressContractsPaths = inProgress.stream().map(Map.Entry::getKey)
|
||||
.map(Path::toString).collect(Collectors.joining(","));
|
||||
throw new IllegalStateException("In progress contracts found in paths ["
|
||||
+ inProgressContractsPaths
|
||||
+ "] and the switch [failOnInProgress] is set to [true]. Either unmark those contracts as in progress, or set the switch to [false].");
|
||||
}
|
||||
processAllNotInProgress(contracts, basePackageName);
|
||||
}
|
||||
|
||||
private Set<Map.Entry<Path, List<ContractMetadata>>> inProgress(
|
||||
MultiValueMap<Path, ContractMetadata> contracts) {
|
||||
return contracts.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().stream()
|
||||
.anyMatch(ContractMetadata::anyInProgress))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
void processAllNotInProgress(MultiValueMap<Path, ContractMetadata> contracts,
|
||||
final String basePackageName) {
|
||||
contracts.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().stream()
|
||||
.noneMatch(ContractMetadata::anyInProgress))
|
||||
.forEach(entry -> processIncludedDirectory(relativizeContractPath(entry),
|
||||
entry.getValue(), basePackageName));
|
||||
}
|
||||
|
||||
private String relativizeContractPath(Map.Entry<Path, List<ContractMetadata>> entry) {
|
||||
Path relativePath = configProperties.getContractsDslDir().toPath()
|
||||
.relativize(entry.getKey());
|
||||
return StringUtils.defaultIfEmpty(relativePath.toString(), DEFAULT_CLASS_PREFIX);
|
||||
}
|
||||
|
||||
private void processIncludedDirectory(final String includedDirectoryRelativePath,
|
||||
final Collection<ContractMetadata> contracts,
|
||||
final String basePackageNameForClass) {
|
||||
log.debug("Collected contracts with metadata {} relative path is [{}]", contracts,
|
||||
includedDirectoryRelativePath);
|
||||
if (!contracts.isEmpty()) {
|
||||
String className = afterLast(includedDirectoryRelativePath, File.separator)
|
||||
+ resolveNameSuffix();
|
||||
String convertedClassName = convertIllegalPackageChars(className);
|
||||
String packageName = buildPackage(basePackageNameForClass,
|
||||
includedDirectoryRelativePath);
|
||||
Path dir = saver.generateTestBaseDir(basePackageNameForClass,
|
||||
convertIllegalPackageChars(includedDirectoryRelativePath));
|
||||
Path classPath = saver.pathToClass(dir, convertedClassName);
|
||||
byte[] classBytes = generator
|
||||
.buildClass(configProperties, contracts,
|
||||
includedDirectoryRelativePath,
|
||||
new SingleTestGenerator.GeneratedClassData(convertedClassName,
|
||||
packageName, classPath))
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
saver.saveClassFile(classPath, classBytes);
|
||||
counter.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveNameSuffix() {
|
||||
return StringUtils.defaultIfEmpty(configProperties.getNameSuffixForTests(),
|
||||
configProperties.getTestFramework().getClassNameSuffix());
|
||||
}
|
||||
|
||||
protected static String buildPackage(final String packageNameForClass,
|
||||
final String includedDirectoryRelativePath) {
|
||||
String directory = beforeLast(includedDirectoryRelativePath, File.separator);
|
||||
String convertedPackage = packageNameForClass + "."
|
||||
+ directoryToPackage(convertIllegalPackageChars(directory));
|
||||
return !directory.isEmpty() ? convertedPackage : packageNameForClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* Builds a block of code. Allows to start, end, indent etc. pieces of code.
|
||||
*
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class BlockBuilder {
|
||||
|
||||
private final StringBuilder builder;
|
||||
|
||||
private final String spacer;
|
||||
|
||||
private int indents;
|
||||
|
||||
private String lineEnding = "";
|
||||
|
||||
private String labelPrefix = "";
|
||||
|
||||
/**
|
||||
* @param spacer - char used for spacing
|
||||
*/
|
||||
public BlockBuilder(String spacer) {
|
||||
this.spacer = spacer;
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup line ending
|
||||
*/
|
||||
public BlockBuilder setupLineEnding(String lineEnding) {
|
||||
this.lineEnding = lineEnding;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup label prefix
|
||||
*/
|
||||
public BlockBuilder setupLabelPrefix(String labelPrefix) {
|
||||
this.labelPrefix = labelPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getLineEnding() {
|
||||
return this.lineEnding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
public BlockBuilder appendWithLabelPrefix(String label) {
|
||||
return append(this.labelPrefix).append(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
public BlockBuilder startBlock() {
|
||||
indents++;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends block by removing indents
|
||||
*/
|
||||
public BlockBuilder endBlock() {
|
||||
indents--;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block and adds indents
|
||||
*/
|
||||
public BlockBuilder indent() {
|
||||
startBlock().startBlock();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes indents and closes the block
|
||||
*/
|
||||
public BlockBuilder unindent() {
|
||||
endBlock().endBlock();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder addLine(String line) {
|
||||
return addIndented(line).append("\n");
|
||||
}
|
||||
|
||||
public BlockBuilder addIndented(String line) {
|
||||
return addIndentation().append(line);
|
||||
}
|
||||
|
||||
public BlockBuilder addIndented(Runnable runnable) {
|
||||
addIndentation();
|
||||
runnable.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder addLineWithEnding(String line) {
|
||||
addIndentation();
|
||||
append(line).addEndingIfNotPresent().addEmptyLine();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder addEndingIfNotPresent() {
|
||||
addAtTheEnd(lineEnding);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder addEmptyLine() {
|
||||
builder.append("\n");
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder appendWithSpace(String text) {
|
||||
return addAtTheEnd(" ").append(text);
|
||||
}
|
||||
|
||||
public BlockBuilder appendWithSpace(Runnable runnable) {
|
||||
addAtTheEnd(" ");
|
||||
runnable.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder append(Runnable runnable) {
|
||||
runnable.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder append(String string) {
|
||||
builder.append(string);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockBuilder addIndentation() {
|
||||
for (int i = 0; i < indents; i++) {
|
||||
builder.append(spacer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
BlockBuilder inBraces(Runnable runnable) {
|
||||
builder.append("{\n");
|
||||
startBlock();
|
||||
runnable.run();
|
||||
endBlock();
|
||||
addAtTheEnd("\n");
|
||||
addLine("}");
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean endsWith(String text) {
|
||||
return builder.toString().endsWith(text);
|
||||
}
|
||||
|
||||
public BlockBuilder addAtTheEndIfEndsWithAChar(String toAdd) {
|
||||
char lastChar = builder.charAt(builder.length() - 1);
|
||||
if (Character.isLetter(lastChar)) {
|
||||
builder.append(toAdd);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given text at the end of the line
|
||||
* @return updated BlockBuilder
|
||||
*/
|
||||
public BlockBuilder addAtTheEnd(String toAdd) {
|
||||
String lastChar = String.valueOf(builder.charAt(builder.length() - 1));
|
||||
String secondLastChar = builder.length() >= 2
|
||||
? String.valueOf(builder.charAt(builder.length() - 2)) : "";
|
||||
boolean isEndWithNewLine = endsWithNewLine(lastChar);
|
||||
boolean lastCharSpecial = aSpecialSign(lastChar, toAdd);
|
||||
boolean secondLastCharSpecial = aSpecialSign(secondLastChar, toAdd);
|
||||
boolean lineEndingToAdd = toAdd.equals(lineEnding);
|
||||
// lastChar = [;] , toAdd = [;]
|
||||
if (lastChar.equals(toAdd)) {
|
||||
return this;
|
||||
}
|
||||
// secondLastChar = [ ], lastChar = [{] , toAdd = [;]
|
||||
else if ((!isEndWithNewLine && lastCharSpecial) && lineEndingToAdd) {
|
||||
return this;
|
||||
}
|
||||
// secondLastChar = [{], lastChar = [\n] , toAdd = [;]
|
||||
else if (isEndWithNewLine && secondLastCharSpecial) {
|
||||
return this;
|
||||
}
|
||||
else if (isEndWithNewLine && !secondLastCharSpecial) {
|
||||
builder.replace(builder.length() - 1, builder.length(), toAdd);
|
||||
builder.append("\n");
|
||||
}
|
||||
else {
|
||||
builder.append(toAdd);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean endsWithNewLine(String character) {
|
||||
return character.equals("\n");
|
||||
}
|
||||
|
||||
private boolean aSpecialSign(String character, String toAdd) {
|
||||
if (StringUtils.isEmpty(character)) {
|
||||
return false;
|
||||
}
|
||||
return character.equals("{") || (character.equals(spacer) && toAdd.equals(spacer))
|
||||
|| (character.equals(spacer) && toAdd.equals(" "))
|
||||
|| character.equals(toAdd) || (endsWithNewLine(character)
|
||||
&& StringUtils.equalsAny(toAdd, "\n", " ", lineEnding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current text with the provided one
|
||||
* @param contents - text to replace the current content with
|
||||
* @return updated Block Builder
|
||||
*/
|
||||
public BlockBuilder updateContents(String contents) {
|
||||
this.builder.replace(0, this.builder.length(), contents);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor;
|
||||
import org.springframework.cloud.contract.verifier.template.TemplateProcessor;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user