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 73fb8bb426..f8e959170c 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 @@ -52,7 +52,7 @@ class FileSaver { } protected Path pathToClass(Path testBaseDir, String fileName) { - Paths.get(testBaseDir.toString(), capitalize(fileName) + generator.fileExtension(this.properties)).toAbsolutePath() + return Paths.get(testBaseDir.toString(), capitalize(fileName) + generator.fileExtension(this.properties)).toAbsolutePath() } protected Path generateTestBaseDir(String basePackageClass, String includedDirectoryRelativePath) { 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 bf5b95efb7..5b9cbe64d7 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 @@ -16,10 +16,16 @@ 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.CompileStatic import groovy.transform.PackageScope import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory +import wiremock.com.google.common.collect.ListMultimap + import org.springframework.cloud.contract.spec.ContractVerifierException import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator @@ -27,13 +33,9 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig 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.StringUtils -import wiremock.com.google.common.collect.ListMultimap - -import java.nio.charset.StandardCharsets -import java.nio.file.Path -import java.util.concurrent.atomic.AtomicInteger import static org.springframework.cloud.contract.verifier.util.NamesUtil.afterLast import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast @@ -87,6 +89,8 @@ class TestGenerator { int generate() { generateTestClasses(basePackageName()) + NamesUtil.recrusiveDirectoryToPackage(configProperties.generatedTestSourcesDir) + NamesUtil.recrusiveDirectoryToPackage(configProperties.generatedTestResourcesDir) return counter.get() } 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 46b4d48dcf..f427eda8ad 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 @@ -15,6 +15,13 @@ */ package org.springframework.cloud.contract.verifier.util + +import java.nio.file.FileVisitResult +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.SimpleFileVisitor +import java.nio.file.attribute.BasicFileAttributes + /** * A utility class that helps to convert names * @@ -131,6 +138,58 @@ class NamesUtil { .replace('.', '_') .replace(File.separator, '.') .replaceAll('\\.([0-9])', '._$1') + .replaceAll('^([0-9].*)', '_$1') + } + + /** + * Traverses the directories and converts renames illegal folder names + * to package names + * + * @param rootDir - folder from which to start traversing + */ + static void recrusiveDirectoryToPackage(File rootDir) { + try { + if (!rootDir.exists()) { + return + } + InvalidFolderRenamer renamer = new InvalidFolderRenamer() + Files.walkFileTree(rootDir.toPath(), renamer) + renamer.rename() + } + catch (IOException ex) { + throw new IllegalStateException(ex) + } + } + + private static class InvalidFolderRenamer extends SimpleFileVisitor { + + private Deque filesToRename = new ArrayDeque<>() + + @Override + FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + String name = dir.toFile().getName() + String convertedName = directoryToPackage(name) + if (name != convertedName) { + this.filesToRename.addFirst(new FileAndNewName(dir.toFile(), convertedName)) + } + return FileVisitResult.CONTINUE + } + + void rename() { + this.filesToRename.each { + it.file.renameTo(new File(it.file.parentFile, it.newName)) + } + } + } + + private static class FileAndNewName { + private final File file + private final String newName + + private FileAndNewName(File file, String newName) { + this.file = file + this.newName = newName + } } /** 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 563dec111b..74ca558dea 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 @@ -212,7 +212,7 @@ class SingleTestGeneratorSpec extends Specification { 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) + 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 | MOCKMVC | JAVA_ASSERTER | 'ContractsTest.java' 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 efbc74c4d9..7cfefd2f42 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 @@ -1,12 +1,17 @@ package org.springframework.cloud.contract.verifier.util +import org.junit.Rule +import org.junit.rules.TemporaryFolder import spock.lang.Specification +import org.springframework.util.FileSystemUtils /** * @author Marcin Grzejszczak */ class NamesUtilSpec extends Specification { + @Rule TemporaryFolder folder = new TemporaryFolder() + def "should return the whole string before the last one"() { given: String string = "a.b.c.d.e" @@ -98,6 +103,13 @@ class NamesUtilSpec extends Specification { NamesUtil.directoryToPackage(string) == "a.b.c._1_0_0.e" } + def "should convert a directory notation to package when folder is only a digit"() { + given: + String string = "1.0.0" + expect: + NamesUtil.directoryToPackage(string) == "_1_0_0" + } + def "should convert all illegal package chars to legal ones"() { given: String string = "a-b c.1.0.x+d1174dd" @@ -111,4 +123,30 @@ class NamesUtilSpec extends Specification { expect: NamesUtil.convertIllegalMethodNameChars(string) == '10a_b_c_1_0_x_d1174$dd' } + + def "should recursively convert the names of folders to package names"() { + given: + File tmp = folder.newFolder() + URL resource = getClass().getResource("/prependFolderName") + File folder = new File(resource.toURI()) + FileSystemUtils.copyRecursively(folder, tmp) + when: + NamesUtil.recrusiveDirectoryToPackage(tmp) + then: + new File(tmp, "META-INF/1_0_0_SNAPSHOT").exists() == false + new File(tmp, "META-INF/2_0_0_SNAPSHOT").exists() == false + new File(tmp, "META-INF/1_0_0_SNAPSHOT/3_0_0_SNAPSHOT").exists() == false + new File(tmp, "META-INF/_1_0_0_SNAPSHOT").exists() == true + new File(tmp, "META-INF/_2_0_0_SNAPSHOT").exists() == true + new File(tmp, "META-INF/_1_0_0_SNAPSHOT/_3_0_0_SNAPSHOT").exists() == true + new File(tmp, "META-INF/_1_0_0_SNAPSHOT/normal").exists() == true + new File(tmp, "META-INF/_1_0_0_SNAPSHOT/_3_0_0_SNAPSHOT/normal").exists() == true + } + + def "should not throw exception if folder does not exist"() { + when: + NamesUtil.recrusiveDirectoryToPackage(new File("I/do/not/exist")) + then: + noExceptionThrown() + } } diff --git a/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/01_login.groovy new file mode 100644 index 0000000000..60d5cfa55a --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/01_login.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2013-2019 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 + * + * 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. + */ + diff --git a/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/01_login.groovy new file mode 100644 index 0000000000..60d5cfa55a --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/01_login.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2013-2019 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 + * + * 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. + */ + diff --git a/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/normal/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/normal/01_login.groovy new file mode 100644 index 0000000000..60d5cfa55a --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/3.0.0.SNAPSHOT/normal/01_login.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2013-2019 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 + * + * 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. + */ + diff --git a/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/normal/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/normal/01_login.groovy new file mode 100644 index 0000000000..60d5cfa55a --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/1.0.0.SNAPSHOT/normal/01_login.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2013-2019 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 + * + * 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. + */ + diff --git a/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/2.0.0.SNAPSHOT/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/2.0.0.SNAPSHOT/01_login.groovy new file mode 100644 index 0000000000..60d5cfa55a --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/prependFolderName/META-INF/2.0.0.SNAPSHOT/01_login.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2013-2019 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 + * + * 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. + */ +