diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ClasspathStubProvider.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ClasspathStubProvider.java index 993b394fa6..830008990f 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ClasspathStubProvider.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ClasspathStubProvider.java @@ -16,19 +16,6 @@ package org.springframework.cloud.contract.stubrunner; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.MatchResult; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; @@ -36,9 +23,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties; import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.util.StringUtils; /** @@ -73,188 +58,37 @@ public class ClasspathStubProvider implements StubDownloaderBuilder { private static final Log log = LogFactory.getLog(ClasspathStubProvider.class); - private static final int TEMP_DIR_ATTEMPTS = 10000; - - private final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( - new DefaultResourceLoader()); - @Override public StubDownloader build(final StubRunnerOptions stubRunnerOptions) { if (stubRunnerOptions.stubsMode != StubRunnerProperties.StubsMode.CLASSPATH) { return null; } log.info("Will download stubs from classpath"); - return new StubDownloader() { - @Override - public Map.Entry downloadAndUnpackStubJar( - StubConfiguration config) { - List repoRoots = repoRoot(stubRunnerOptions, config); - List paths = toPaths(repoRoots); - List resources = resolveResources(paths); - if (log.isDebugEnabled()) { - log.debug("For paths " + paths + " found following resources " - + resources); - } - if (resources.isEmpty()) { - throw new IllegalStateException( - "No stubs were found on classpath for [" + config.getGroupId() - + ":" + config.getArtifactId() + "]"); - } - final File tmp = createTempDir(); - if (stubRunnerOptions.isDeleteStubsAfterTest()) { - tmp.deleteOnExit(); - } - Pattern groupAndArtifactPattern = Pattern.compile("^(.*)(" - + config.getGroupId() + "." + config.getArtifactId() + ")(.*)$"); - String version = config.getVersion(); - for (Resource resource : resources) { - try { - String relativePath = relativePathPicker(resource, - groupAndArtifactPattern); - if (log.isDebugEnabled()) { - log.debug("Relative path for resource is [" + relativePath - + "]"); - } - // the relative path is OS agnostic and contains / only - int lastIndexOf = relativePath.lastIndexOf("/"); - String relativePathWithoutFile = lastIndexOf > -1 - ? relativePath.substring(0, lastIndexOf) : relativePath; - if (log.isDebugEnabled()) { - log.debug("Relative path without file name is [" - + relativePathWithoutFile + "]"); - } - Path directory = Files.createDirectories( - new File(tmp, relativePathWithoutFile).toPath()); - File newFile = new File(directory.toFile(), - resource.getFilename()); - if (!newFile.exists() && !isDirectory(resource)) { - try (InputStream stream = resource.getInputStream()) { - Files.copy(stream, newFile.toPath()); - } - } - if (log.isDebugEnabled()) { - log.debug("Stored file [" + newFile + "]"); - } - } - catch (IOException e) { - log.error("Exception occurred while trying to create dirs", e); - throw new IllegalStateException(e); - } - } - log.info("Unpacked files for [" + config.getGroupId() + ":" - + config.getArtifactId() + ":" + version + "] to folder [" + tmp - + "]"); - return new AbstractMap.SimpleEntry<>( - new StubConfiguration(config.getGroupId(), config.getArtifactId(), - version, config.getClassifier()), - tmp); - } - - boolean isDirectory(Resource resource) { - try { - return resource.getFile().isDirectory(); - } - catch (Exception e) { - if (log.isTraceEnabled()) { - log.trace( - "Exception occurred while trying to convert path to file for resource [" - + resource + "]", - e); - } - return false; - } - } - - String relativePathPicker(Resource resource, Pattern groupAndArtifactPattern) - throws IOException { - String uri = resource.getURI().toString(); - Matcher groupAndArtifactMatcher = groupAndArtifactPattern.matcher(uri); - if (groupAndArtifactMatcher.matches()) { - MatchResult groupAndArtifactResult = groupAndArtifactMatcher - .toMatchResult(); - return groupAndArtifactResult.group(2) - + groupAndArtifactResult.group(3); - } - else { - throw new IllegalArgumentException("Illegal uri [" + uri + "]"); - } - } - }; + return new ResourceResolvingStubDownloader(stubRunnerOptions, this::repoRoot, + this::gavPattern); } - private List toPaths(List repoRoots) { - List list = new ArrayList<>(); - for (RepoRoot repoRoot : repoRoots) { - list.add(repoRoot.fullPath); - } - return list; - } - - List resolveResources(List paths) { - List resources = new ArrayList<>(); - for (String path : paths) { - try { - List list = Arrays.asList(this.resolver.getResources(path)); - resources.addAll(list); - } - catch (IOException e) { - log.error("Exception occurred while trying to fetch resources from [" - + path + "]"); - throw new IllegalStateException(e); - } - } - return resources; - } - - private List repoRoot(StubRunnerOptions stubRunnerOptions, + private RepoRoots repoRoot(StubRunnerOptions stubRunnerOptions, StubConfiguration configuration) { Resource repositoryRoot = stubRunnerOptions.getStubRepositoryRoot(); if (repositoryRoot instanceof ClassPathResource) { ClassPathResource classPathResource = (ClassPathResource) repositoryRoot; String path = classPathResource.getPath(); if (StringUtils.hasText(path)) { - return Collections.singletonList( + return RepoRoots.asList( new RepoRoot(stubRunnerOptions.getStubRepositoryRootAsString())); } } String path = "/**/" + configuration.getGroupId() + "/" + configuration.getArtifactId(); - return Arrays.asList(new RepoRoot("classpath*:/META-INF" + path, "/**/*.*"), + return RepoRoots.asList(new RepoRoot("classpath*:/META-INF" + path, "/**/*.*"), new RepoRoot("classpath*:/contracts" + path, "/**/*.*"), new RepoRoot("classpath*:/mappings" + path, "/**/*.*")); } - // Taken from Guava - private File createTempDir() { - File baseDir = new File(System.getProperty("java.io.tmpdir")); - String baseName = System.currentTimeMillis() + "-"; - for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { - File tempDir = new File(baseDir, baseName + counter); - if (tempDir.mkdir()) { - return tempDir; - } - } - throw new IllegalStateException("Failed to create directory within " - + TEMP_DIR_ATTEMPTS + " attempts (tried " + baseName + "0 to " + baseName - + (TEMP_DIR_ATTEMPTS - 1) + ")"); - } - - private static class RepoRoot { - - final String repoRoot; - - final String fullPath; - - RepoRoot(String repoRoot) { - this.repoRoot = repoRoot; - this.fullPath = repoRoot + ""; - } - - RepoRoot(String repoRoot, String suffix) { - this.repoRoot = repoRoot; - this.fullPath = repoRoot + suffix; - } - + private Pattern gavPattern(StubConfiguration config) { + String ga = config.getGroupId() + "." + config.getArtifactId(); + return Pattern.compile("^(.*)(" + ga + ")(.*)$"); } } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/FileStubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/FileStubDownloader.java new file mode 100644 index 0000000000..0b6174ebae --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/FileStubDownloader.java @@ -0,0 +1,209 @@ +/* + * 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 + * + * 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.stubrunner; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties; +import org.springframework.core.io.AbstractResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.StringUtils; + +/** + * Allows to read stubs and contracts from a given location. Contrary to + * {@link org.springframework.cloud.contract.stubrunner.AetherStubDownloaderBuilder}, + * doesn't require the location to be a maven repository. + * + * @author Marcin Grzejszczak + */ +public class FileStubDownloader implements StubDownloaderBuilder { + + private static final List ACCEPTABLE_PROTOCOLS = Collections + .singletonList("stubs"); + + /** + * Does any of the accepted protocols matches the URL of the repository. + * @param url - of the repository + * @return {@code true} if protocol is accepted + */ + public static boolean isProtocolAccepted(String url) { + return ACCEPTABLE_PROTOCOLS.stream().anyMatch(url::startsWith); + } + + @Override + public StubDownloader build(StubRunnerOptions stubRunnerOptions) { + // should work only in remote and local option + if (stubRunnerOptions.getStubsMode() == StubRunnerProperties.StubsMode.CLASSPATH + || stubRunnerOptions.getStubRepositoryRoot() == null) { + return null; + } + Resource resource = stubRunnerOptions.getStubRepositoryRoot(); + // we verify whether the protocol starts with `stubs://` + if (!(resource instanceof StubsResource)) { + return null; + } + return new StubsStubDownloader(stubRunnerOptions); + } + + @Override + public Resource resolve(String location, ResourceLoader resourceLoader) { + if (StringUtils.isEmpty(location) || !isProtocolAccepted(location)) { + return null; + } + return new StubsResource(location); + } + +} + +/** + * Primitive version of a Stubs {@link Resource}. Automatically makes Spring convert the + * URL to a Resource. + */ +class StubsResource extends AbstractResource { + + private final String rawLocation; + + StubsResource(String location) { + this.rawLocation = location; + } + + @Override + public String getDescription() { + return this.rawLocation; + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + + @Override + public URI getURI() throws IOException { + return URI.create(this.rawLocation); + } + +} + +/** + * Concrete logic of picking stubs. + */ +class StubsStubDownloader implements StubDownloader { + + private static final Log log = LogFactory.getLog(StubsStubDownloader.class); + + private static final String STUBS_FIND_PRODUCER_PROPERTY = "stubs.find-producer"; + + private static final String LATEST_VERSION = "+"; + + private final StubRunnerOptions stubRunnerOptions; + + StubsStubDownloader(StubRunnerOptions stubRunnerOptions) { + this.stubRunnerOptions = stubRunnerOptions; + } + + // StubConfiguration is the concrete stub to be fetched + @Override + public Map.Entry downloadAndUnpackStubJar( + StubConfiguration stubConfiguration) { + boolean shouldFindProducer = shouldFindProducer(); + if (!shouldFindProducer) { + String schemeSpecific = schemeSpecificPart(); + log.info("Stubs are present under [" + schemeSpecific + "]"); + return new AbstractMap.SimpleEntry<>(stubConfiguration, + new File(schemeSpecific)); + } + return new ResourceResolvingStubDownloader(stubRunnerOptions, this::repoRoot, + this::gavPattern).downloadAndUnpackStubJar(stubConfiguration); + } + + // for group id a.b.c and artifact id d + // a.b.c/d + // a/b/c/d + private RepoRoots repoRoot(StubRunnerOptions stubRunnerOptions, + StubConfiguration configuration) { + String pathWithGroupAndArtifactId = "/" + configuration.getGroupId() + "/" + + configuration.getArtifactId(); + String pathWithGroupAndArtifactIdSlashSeparated = "/" + + configuration.getGroupId().replace(".", File.separator) + "/" + + configuration.getArtifactId(); + String anyFileSuffix = "/**/*.*"; + RepoRoots roots = RepoRoots.asList( + new RepoRoot(schemeSpecificPart() + pathWithGroupAndArtifactId, + anyFileSuffix), + new RepoRoot( + schemeSpecificPart() + pathWithGroupAndArtifactIdSlashSeparated, + anyFileSuffix), + new RepoRoot(schemeSpecificPart() + anyFileSuffix)); + if (!latestVersionIsSet(configuration)) { + String pathWithGAV = pathWithGroupAndArtifactId + "/" + + configuration.getVersion(); + String pathWithSlashSeparatedGAV = pathWithGroupAndArtifactIdSlashSeparated + + "/" + configuration.getVersion(); + roots.addAll(RepoRoots.asList( + new RepoRoot(schemeSpecificPart() + pathWithGAV, anyFileSuffix), + new RepoRoot(schemeSpecificPart() + pathWithSlashSeparatedGAV, + anyFileSuffix))); + } + return roots; + } + + private Pattern gavPattern(StubConfiguration config) { + String version = config.getVersion(); + String ga = config.getGroupId() + "." + config.getArtifactId(); + String gav = latestVersionIsSet(config) ? ga : (ga + "." + version); + return Pattern.compile("^(.*)(" + gav + ")(.*)$"); + } + + private boolean latestVersionIsSet(StubConfiguration configuration) { + return LATEST_VERSION.equals(configuration.getVersion()); + } + + private boolean shouldFindProducer() { + Map args = this.stubRunnerOptions.getProperties(); + String findProducer = StubRunnerPropertyUtils.getProperty(args, + STUBS_FIND_PRODUCER_PROPERTY); + return Boolean.parseBoolean(findProducer); + } + + // stubs://foo -> foo + private String schemeSpecificPart() { + try { + String part = this.stubRunnerOptions.getStubRepositoryRoot().getURI() + .getSchemeSpecificPart(); + if (StringUtils.isEmpty(part)) { + return part; + } + return part.startsWith("//") ? part.substring(2) : part; + } + catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java new file mode 100644 index 0000000000..f14759e184 --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java @@ -0,0 +1,243 @@ +/* + * 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 + * + * 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.stubrunner; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import shaded.com.google.common.base.Function; + +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.util.StringUtils; + +class ResourceResolvingStubDownloader implements StubDownloader { + + private static final Log log = LogFactory + .getLog(ResourceResolvingStubDownloader.class); + + private static final int TEMP_DIR_ATTEMPTS = 10000; + + private static final String LATEST_VERSION = "+"; + + private final StubRunnerOptions stubRunnerOptions; + + private final BiFunction repoRootFunction; + + private final Function gavPattern; + + private final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( + new DefaultResourceLoader()); + + ResourceResolvingStubDownloader(StubRunnerOptions stubRunnerOptions, + BiFunction repoRootFunction, + Function gavPattern) { + this.stubRunnerOptions = stubRunnerOptions; + this.repoRootFunction = repoRootFunction; + this.gavPattern = gavPattern; + } + + @Override + public Map.Entry downloadAndUnpackStubJar( + StubConfiguration config) { + List repoRoots = repoRootFunction.apply(stubRunnerOptions, config); + List paths = toPaths(repoRoots); + List resources = resolveResources(paths); + if (log.isDebugEnabled()) { + log.debug("For paths " + paths + " found following resources " + resources); + } + if (resources.isEmpty()) { + throw new IllegalStateException("No stubs were found on classpath for [" + + config.getGroupId() + ":" + config.getArtifactId() + "]"); + } + final File tmp = createTempDir(); + if (stubRunnerOptions.isDeleteStubsAfterTest()) { + tmp.deleteOnExit(); + } + boolean atLeastOneFound = false; + for (Resource resource : resources) { + try { + String relativePath = relativePathPicker(resource, + this.gavPattern.apply(config)); + if (log.isDebugEnabled()) { + log.debug("Relative path for resource is [" + relativePath + "]"); + } + if (StringUtils.isEmpty(relativePath)) { + log.warn("Unable to match the URI [" + resource.getURI() + "]"); + continue; + } + atLeastOneFound = true; + copyTheFoundFiles(tmp, resource, relativePath); + } + catch (IOException e) { + log.error("Exception occurred while trying to create dirs", e); + throw new IllegalStateException(e); + } + } + if (!atLeastOneFound) { + log.warn("Didn't find any matching stubs"); + return null; + } + log.info("Unpacked files for [" + config.getGroupId() + ":" + + config.getArtifactId() + ":" + config.getVersion() + "] to folder [" + + tmp + "]"); + return new AbstractMap.SimpleEntry<>(new StubConfiguration(config.getGroupId(), + config.getArtifactId(), config.getVersion(), config.getClassifier()), + tmp); + } + + private void copyTheFoundFiles(File tmp, Resource resource, String relativePath) + throws IOException { + // the relative path is OS agnostic and contains / only + int lastIndexOf = relativePath.lastIndexOf("/"); + String relativePathWithoutFile = lastIndexOf > -1 + ? relativePath.substring(0, lastIndexOf) : relativePath; + if (log.isDebugEnabled()) { + log.debug("Relative path without file name is [" + relativePathWithoutFile + + "]"); + } + Path directory = Files + .createDirectories(new File(tmp, relativePathWithoutFile).toPath()); + File newFile = new File(directory.toFile(), resource.getFilename()); + if (!newFile.exists() && !isDirectory(resource)) { + try (InputStream stream = resource.getInputStream()) { + Files.copy(stream, newFile.toPath()); + } + } + if (log.isDebugEnabled()) { + log.debug("Stored file [" + newFile + "]"); + } + } + + boolean isDirectory(Resource resource) { + try { + return resource.getFile().isDirectory(); + } + catch (Exception e) { + if (log.isTraceEnabled()) { + log.trace( + "Exception occurred while trying to convert path to file for resource [" + + resource + "]", + e); + } + return false; + } + } + + String relativePathPicker(Resource resource, Pattern groupAndArtifactPattern) + throws IOException { + String uri = resource.getURI().toString(); + Matcher groupAndArtifactMatcher = groupAndArtifactPattern.matcher(uri); + if (groupAndArtifactMatcher.matches()) { + MatchResult groupAndArtifactResult = groupAndArtifactMatcher.toMatchResult(); + return groupAndArtifactResult.group(2) + groupAndArtifactResult.group(3); + } + else { + return ""; + } + } + + private List toPaths(List repoRoots) { + List list = new ArrayList<>(); + for (RepoRoot repoRoot : repoRoots) { + list.add(repoRoot.fullPath); + } + return list; + } + + List resolveResources(List paths) { + List resources = new ArrayList<>(); + for (String path : paths) { + try { + List list = Arrays.asList(this.resolver.getResources(path)); + resources.addAll(list); + } + catch (IOException e) { + log.error("Exception occurred while trying to fetch resources from [" + + path + "]"); + throw new IllegalStateException(e); + } + } + return resources; + } + + // Taken from Guava + private File createTempDir() { + File baseDir = new File(System.getProperty("java.io.tmpdir")); + String baseName = System.currentTimeMillis() + "-"; + for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { + File tempDir = new File(baseDir, baseName + counter); + if (tempDir.mkdir()) { + return tempDir; + } + } + throw new IllegalStateException("Failed to create directory within " + + TEMP_DIR_ATTEMPTS + " attempts (tried " + baseName + "0 to " + baseName + + (TEMP_DIR_ATTEMPTS - 1) + ")"); + } + +} + +class RepoRoot { + + final String repoRoot; + + final String fullPath; + + RepoRoot(String repoRoot) { + this.repoRoot = repoRoot; + this.fullPath = repoRoot; + } + + RepoRoot(String repoRoot, String suffix) { + this.repoRoot = repoRoot; + this.fullPath = repoRoot + suffix; + } + +} + +class RepoRoots extends LinkedList { + + RepoRoots() { + } + + RepoRoots(Collection c) { + super(c); + } + + static RepoRoots asList(RepoRoot... repoRoots) { + return new RepoRoots(Arrays.asList(repoRoots)); + } + +} diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java index 7c25120735..e4769fe953 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubDownloaderBuilderProvider.java @@ -62,7 +62,7 @@ public class StubDownloaderBuilderProvider { List defaultStubDownloaderBuilders() { return Arrays.asList(new ScmStubDownloaderBuilder(), new ClasspathStubProvider(), - new AetherStubDownloaderBuilder()); + new FileStubDownloader(), new AetherStubDownloaderBuilder()); } } diff --git a/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/StubsStubDownloaderTests.java b/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/StubsStubDownloaderTests.java new file mode 100644 index 0000000000..00cda7106a --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/StubsStubDownloaderTests.java @@ -0,0 +1,85 @@ +/* + * 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 + * + * 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.stubrunner; + +import java.io.File; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.assertj.core.api.BDDAssertions; +import org.junit.Test; + +public class StubsStubDownloaderTests { + + URL url = StubsStubDownloaderTests.class.getResource("/repository/mappings"); + + @Test + public void should_pick_stubs_from_a_given_location() { + String path = url.getPath(); + StubRunnerOptions options = new StubRunnerOptionsBuilder() + .withStubRepositoryRoot("stubs://file://" + path).build(); + StubsStubDownloader downloader = new StubsStubDownloader(options); + + Map.Entry entry = downloader + .downloadAndUnpackStubJar(new StubConfiguration("lv.spring.cloud:bye")); + + BDDAssertions.then(entry).isNotNull(); + BDDAssertions.then(entry.getValue().getPath()).endsWith("repository/mappings"); + } + + @Test + public void should_pick_stubs_from_a_given_location_for_a_find_producer_with_ga() { + String path = url.getPath(); + StubRunnerOptions options = new StubRunnerOptionsBuilder() + .withStubRepositoryRoot("stubs://file://" + path) + .withProperties(propsWithFindProducer()).build(); + StubsStubDownloader downloader = new StubsStubDownloader(options); + + Map.Entry entry = downloader + .downloadAndUnpackStubJar(new StubConfiguration("lv.spring.cloud:bye")); + + BDDAssertions.then(entry).isNotNull(); + File stub = new File(entry.getValue().getPath(), + "lv/spring/cloud/bye/lv_bye.json"); + BDDAssertions.then(stub).exists(); + } + + @Test + public void should_pick_stubs_from_a_given_location_for_a_find_producer_with_gav() { + String path = url.getPath(); + StubRunnerOptions options = new StubRunnerOptionsBuilder() + .withStubRepositoryRoot("stubs://file://" + path) + .withProperties(propsWithFindProducer()).build(); + StubsStubDownloader downloader = new StubsStubDownloader(options); + + Map.Entry entry = downloader + .downloadAndUnpackStubJar(new StubConfiguration("lv.spring:cloud:bye")); + + BDDAssertions.then(entry).isNotNull(); + File stub = new File(entry.getValue().getPath(), + "lv/spring/cloud/bye/lv_bye.json"); + BDDAssertions.then(stub).exists(); + } + + private Map propsWithFindProducer() { + Map map = new HashMap<>(); + map.put("stubs.find-producer", "true"); + return map; + } + +}