From 8ca2ed6b225dce462fb02f0930f384214873c71b Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 28 Apr 2017 12:46:45 +0200 Subject: [PATCH] Fixed the way package and class names are generated with the new layout of contracts and stubs the package name was improperly generated (for chars like +, or digits) with this change we're converting those chars to _ fixes #276 --- .../cloud/contract/verifier/FileSaver.groovy | 1 - .../contract/verifier/TestGenerator.groovy | 10 ++-- .../contract/verifier/util/NamesUtil.groovy | 7 ++- .../verifier/builder/ClassBuilderSpec.groovy | 4 +- .../builder/SingleTestGeneratorSpec.groovy | 54 +++++++++++++++++-- .../verifier/util/NamesUtilSpec.groovy | 35 +++++++----- 6 files changed, 84 insertions(+), 27 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/FileSaver.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/FileSaver.groovy index fe0b525301..b479fb18d0 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/FileSaver.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/FileSaver.groovy @@ -42,7 +42,6 @@ class FileSaver { } void saveClassFile(String fileName, String basePackageClass, String includedDirectoryRelativePath, byte[] classBytes) { - Path testBaseDir = Paths.get(targetDirectory.absolutePath, packageToDirectory(basePackageClass), beforeLast(includedDirectoryRelativePath, File.separator)) Files.createDirectories(testBaseDir) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy index f72ae700d4..bdef6387b9 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy @@ -87,9 +87,10 @@ class TestGenerator { final String includedDirectoryRelativePath, Collection contracts, final String basePackageNameForClass) { if (contracts.size()) { def className = afterLast(includedDirectoryRelativePath.toString(), File.separator) + resolveNameSuffix() + def convertedClassName = convertIllegalPackageChars(className) def packageName = buildPackage(basePackageNameForClass, includedDirectoryRelativePath) - def classBytes = generator.buildClass(contracts, className, packageName, includedDirectoryRelativePath).getBytes(StandardCharsets.UTF_8) - saver.saveClassFile(className, basePackageNameForClass, convertIllegalPackageChars(includedDirectoryRelativePath.toString()), classBytes) + def classBytes = generator.buildClass(contracts, convertedClassName, packageName, includedDirectoryRelativePath).getBytes(StandardCharsets.UTF_8) + saver.saveClassFile(convertedClassName, basePackageNameForClass, convertIllegalPackageChars(includedDirectoryRelativePath.toString()), classBytes) counter.incrementAndGet() } } @@ -98,9 +99,10 @@ class TestGenerator { return configProperties.nameSuffixForTests ?: configProperties.targetFramework.classNameSuffix } - private static String buildPackage(final String packageNameForClass, final String includedDirectoryRelativePath) { + protected static String buildPackage(final String packageNameForClass, final String includedDirectoryRelativePath) { String directory = beforeLast(includedDirectoryRelativePath, File.separator) - return !directory.empty ? "$packageNameForClass.${directoryToPackage(convertIllegalPackageChars(directory))}" : packageNameForClass + String convertedPackage = "$packageNameForClass.${directoryToPackage(convertIllegalPackageChars(directory))}" + return !directory.empty ? convertedPackage : packageNameForClass } } \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/NamesUtil.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/NamesUtil.groovy index a3febc5e98..0a80145e4c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/NamesUtil.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/NamesUtil.groovy @@ -99,13 +99,16 @@ class NamesUtil { * Converts the path format to a Java package notation */ static String directoryToPackage(String directory) { - return directory.replace(File.separator, '.') + return directory + .replace('.', '_') + .replace(File.separator, '.') + .replaceAll('\\.([0-9])', '._$1') } /** * Converts illegal package characters to underscores */ static String convertIllegalPackageChars(String packageName) { - return packageName.replaceAll('[_\\- .]', '_') + return packageName.replaceAll('[_\\- .+]', '_') } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy index a575718526..5c7020876e 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy @@ -63,9 +63,9 @@ class ClassBuilderSpec extends Specification { def "should return a class from the generated path by when external contracts are picked"() { given: ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: "foo.Bar") - String contractRelativeFolder = ["org","springframework","cloud","contract","verifier","tests","META_INF","com.example","hello_world","1.0.0"].join(File.separator) + String contractRelativeFolder = ["org","springframework","cloud","contract","verifier","tests","META_INF","com.example","hello_world","0.1.0_dev.1.uncommitted+d1174dd"].join(File.separator) expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world1_0_0Base' + ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world0_1_0_dev_1_uncommitted_d1174ddBase' } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy index 2b7e79364b..0e9d871bb8 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy @@ -18,6 +18,7 @@ package org.springframework.cloud.contract.verifier.builder import org.junit.Rule import org.junit.rules.TemporaryFolder +import org.springframework.cloud.contract.verifier.TestGenerator import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.config.TestMode import org.springframework.cloud.contract.verifier.file.ContractMetadata @@ -82,14 +83,26 @@ class SingleTestGeneratorSpec extends Specification { public static final Closure JAVA_ASSERTER = { String classToTest -> String name = Math.abs(new Random().nextInt()) - String changedTest = classToTest.replace("public class Test", "public class Test${name}") - SyntaxChecker.tryToCompileJavaWithoutImports("test.Test${name}", changedTest) + String changedTest = classToTest + .replace("public class Test", "public class Test${name}") + .replace("public class ContractsTest", "public class Test${name}") + String fqn = FQN(classToTest) + SyntaxChecker.tryToCompileJavaWithoutImports("${fqn}${name}", changedTest) + } + + static String FQN(String classToTest) { + return classToTest.contains("0_1_0_dev_1_uncommitted_d1174dd") ? + "org.springframework.cloud.contract.verifier.tests.com_uscm.dale_api44_spec._0_1_0_dev_1_uncommitted_d1174dd.Test" : + "test.Test" } public static final Closure JAVA_JAXRS_ASSERTER = { String classToTest -> String name = Math.abs(new Random().nextInt()) - String changedTest = classToTest.replace("public class Test {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") - SyntaxChecker.tryToCompileJavaWithoutImports("test.Test${name}", changedTest) + String changedTest = classToTest + .replace("public class Test {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") + .replace("public class ContractsTest {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") + String fqn = FQN(classToTest) + SyntaxChecker.tryToCompileJavaWithoutImports("${fqn}${name}", changedTest) } public static final Closure GROOVY_ASSERTER = { String classToTest -> @@ -98,6 +111,10 @@ class SingleTestGeneratorSpec extends Specification { def setup() { file = tmpFolder.newFile() + wiriteContract(file) + } + + private wiriteContract(File file) { file.write(""" org.springframework.cloud.contract.spec.Contract.make { request { @@ -136,6 +153,33 @@ class SingleTestGeneratorSpec extends Specification { SPOCK | TestMode.EXPLICIT | explicitSpockClassStrings | GROOVY_ASSERTER } + def "should build test class for #testFramework when the path contains bizarre signs"() { + given: + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() + properties.targetFramework = testFramework + properties.basePackageForTests = "org.springframework.cloud.contract.verifier.tests" + and: + File newFolder = tmpFolder.newFolder("META_INF") + File subfolders = new File(newFolder, "/com.uscm/dale_api44_spec/0.1.0_dev.1.uncommitted+d1174dd/contracts/") + subfolders.mkdirs() + File newFile = new File(subfolders, "contract.groovy") + newFile.createNewFile() + wiriteContract(newFile) + properties.contractsDslDir = newFolder + properties.generatedTestSourcesDir = newFolder.parentFile + when: + int size = new TestGenerator(properties).generate() + then: + size > 0 + asserter(new File(newFolder.parent, "/org/springframework/cloud/contract/verifier/tests/com_uscm/dale_api44_spec/0_1_0_dev_1_uncommitted_d1174dd/${testName}").text) + where: + testFramework | mode | asserter | testName + JUNIT | TestMode.MOCKMVC | JAVA_ASSERTER | "ContractsTest.java" + JUNIT | TestMode.EXPLICIT | JAVA_ASSERTER | "ContractsTest.java" + SPOCK | TestMode.MOCKMVC | GROOVY_ASSERTER | "ContractsSpec.groovy" + SPOCK | TestMode.EXPLICIT | GROOVY_ASSERTER | "ContractsSpec.groovy" + } + def "should build test class for #testFramework with Rest Assured 3.0"() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() @@ -406,4 +450,6 @@ class SingleTestGeneratorSpec extends Specification { } + + } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/NamesUtilSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/NamesUtilSpec.groovy index 3d08a99885..23903c89bb 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/NamesUtilSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/NamesUtilSpec.groovy @@ -11,90 +11,97 @@ class NamesUtilSpec extends Specification { given: String string = "a.b.c.d.e" expect: - "a.b.c.d" == NamesUtil.beforeLast(string, ".") + NamesUtil.beforeLast(string, ".") == "a.b.c.d" } def "should return empty string when no token was found for before last"() { given: String string = "a.b.c.d.e" expect: - "" == NamesUtil.beforeLast(string, "/") + NamesUtil.beforeLast(string, "/") == "" } def "should return first token after the last one"() { given: String string = "a.b.c.d.e" expect: - "e" == NamesUtil.afterLast(string, ".") + NamesUtil.afterLast(string, ".") == "e" } def "should return the input string when no token was found for after last"() { given: String string = "a.b.c.d.e" expect: - string == NamesUtil.afterLast(string, "/") + NamesUtil.afterLast(string, "/") == string } def "should return first token after the last dot"() { given: String string = "a.b.c.d.e" expect: - "e" == NamesUtil.afterLastDot(string) + NamesUtil.afterLastDot(string) == "e" } def "should return the input string when no token was found for after last dot"() { given: String string = "abcde" expect: - string == NamesUtil.afterLastDot(string) + NamesUtil.afterLastDot(string) == string } def "should return camel case version of a string"() { given: String string = "BlaBlaBla" expect: - "blaBlaBla" == NamesUtil.camelCase(string) + NamesUtil.camelCase(string) == "blaBlaBla" } def "should return capitalized version of a string"() { given: String string = "blaBlaBla" expect: - "BlaBlaBla" == NamesUtil.capitalize(string) + NamesUtil.capitalize(string) == "BlaBlaBla" } def "should return all text to last dot"() { given: String string = "a.b.c.d.e" expect: - "a.b.c.d" == NamesUtil.toLastDot(string) + NamesUtil.toLastDot(string) == "a.b.c.d" } def "should return the input string when no token was found for to last dot"() { given: String string = "abcde" expect: - string == NamesUtil.toLastDot(string) + NamesUtil.toLastDot(string) == string } def "should convert a package notation to directory"() { given: String string = "a.b.c.d.e" expect: - "a/b/c/d/e".replace("/", File.separator) == NamesUtil.packageToDirectory(string) + NamesUtil.packageToDirectory(string) == "a/b/c/d/e".replace("/", File.separator) } def "should convert a directory notation to package"() { given: String string = "a/b/c/d/e".replace("/", File.separator) expect: - "a.b.c.d.e" == NamesUtil.directoryToPackage(string) + NamesUtil.directoryToPackage(string) == "a.b.c.d.e" + } + + def "should convert a directory notation to package when folder is a digit"() { + given: + String string = "a/b/c/1.0.0/e".replace("/", File.separator) + expect: + NamesUtil.directoryToPackage(string) == "a.b.c._1_0_0.e" } def "should convert all illegal package chars to legal ones"() { given: - String string = "a-b c.1.0.x" + String string = "a-b c.1.0.x+d1174dd" expect: - "a_b_c_1_0_x" == NamesUtil.convertIllegalPackageChars(string) + NamesUtil.convertIllegalPackageChars(string) == "a_b_c_1_0_x_d1174dd" } }