From 8de4d742fe57b97c01e87437687d7e6712732ef2 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 29 Apr 2016 22:22:29 +0200 Subject: [PATCH] Added possibility to pass version (#258) fixes #257 --- docs/src/docs/asciidoc/stubrunner.adoc | 7 +- .../stubrunner/boot/StubRunnerBootSpec.groovy | 16 ++-- .../stubrunner/junit/AccurestRule.java | 23 +++++- .../junit/AccurestRuleSysPropsSpec.groovy | 43 ----------- .../src/test/resources/application.yml | 2 +- .../src/test/resources/application.yml | 2 +- stub-runner/stub-runner/README.adoc | 4 +- .../stubrunner/AetherStubDownloader.groovy | 70 ++++++++++++----- .../accurest/stubrunner/RunningStubs.groovy | 18 +---- .../stubrunner/StubConfiguration.groovy | 77 ++++++++++++++++--- .../accurest/stubrunner/StubDownloader.groovy | 9 +++ .../stubrunner/StubRunnerExecutor.groovy | 2 +- .../stubrunner/StubRunnerFactory.groovy | 11 +-- .../stubrunner/RunningStubsSpec.groovy | 32 +++++--- .../stubrunner/StubConfigurationSpec.groovy | 21 +++++ .../stubrunner/StubRunnerExecutorSpec.groovy | 7 +- .../stubrunner/StubRunnerFactorySpec.groovy | 3 +- 17 files changed, 223 insertions(+), 124 deletions(-) delete mode 100644 stub-runner/stub-runner-junit/src/test/groovy/io/codearte/accurest/stubrunner/junit/AccurestRuleSysPropsSpec.groovy create mode 100644 stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubConfigurationSpec.groovy diff --git a/docs/src/docs/asciidoc/stubrunner.adoc b/docs/src/docs/asciidoc/stubrunner.adoc index e42aeb54c4..06aea3f697 100644 --- a/docs/src/docs/asciidoc/stubrunner.adoc +++ b/docs/src/docs/asciidoc/stubrunner.adoc @@ -68,12 +68,13 @@ You can provide the stubs to download via the `stubrunner.stubs.ids` system prop [source,java,indent=0] ---- -groupId:artifactId:classifier:port +groupId:artifactId:version:classifier:port ---- -`classifier` and `port` are optional. +`version`, `classifier` and `port` are optional. -* If you don't provide the `classifier` then the default one will be taken. * If you don't provide the `port` then a random one will be picked +* If you don't provide the `classifier` then the default one will be taken. +* If you don't provide the `version` then the `+` will be passed and the latest one will be downloaded Where `port` means the port of the WireMock server. \ No newline at end of file diff --git a/stub-runner/stub-runner-boot/src/test/groovy/io/codearte/accurest/stubrunner/boot/StubRunnerBootSpec.groovy b/stub-runner/stub-runner-boot/src/test/groovy/io/codearte/accurest/stubrunner/boot/StubRunnerBootSpec.groovy index ccb8daf018..5a02291f2b 100644 --- a/stub-runner/stub-runner-boot/src/test/groovy/io/codearte/accurest/stubrunner/boot/StubRunnerBootSpec.groovy +++ b/stub-runner/stub-runner-boot/src/test/groovy/io/codearte/accurest/stubrunner/boot/StubRunnerBootSpec.groovy @@ -26,12 +26,12 @@ class StubRunnerBootSpec extends Specification { new TriggerController(stubRunning)) } - def 'should return a list of running stub servers in "ivy:port" notation'() { + def 'should return a list of running stub servers in "full ivy:port" notation'() { when: String response = RestAssuredMockMvc.get('/stubs').body.asString() then: def root = new JsonSlurper().parseText(response) - root.'io.codearte.accurest.stubs:streamService:stubs' instanceof Integer + root.'io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs' instanceof Integer } def 'should return a port on which a [#stubId] stub is running'() { @@ -41,7 +41,11 @@ class StubRunnerBootSpec extends Specification { response.statusCode == 200 response.body.as(Integer) > 0 where: - stubId << ['io.codearte.accurest.stubs:streamService:stubs', 'io.codearte.accurest.stubs:streamService', 'streamService'] + stubId << ['io.codearte.accurest.stubs:streamService:+:stubs', + 'io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs', + 'io.codearte.accurest.stubs:streamService:+', + 'io.codearte.accurest.stubs:streamService', + 'streamService'] } def 'should return 404 when missing stub was called'() { @@ -51,12 +55,12 @@ class StubRunnerBootSpec extends Specification { response.statusCode == 404 } - def 'should return a list of messaging labels that can be triggered'() { + def 'should return a list of messaging labels that can be triggered when version and classifier are passed'() { when: String response = RestAssuredMockMvc.get('/triggers').body.asString() then: def root = new JsonSlurper().parseText(response) - root.'io.codearte.accurest.stubs:streamService:stubs'.containsAll(["delete_book","return_book_1","return_book_2"]) + root.'io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book","return_book_1","return_book_2"]) } def 'should trigger a messaging label'() { @@ -91,7 +95,7 @@ class StubRunnerBootSpec extends Specification { then: response.statusCode == 404 def root = new JsonSlurper().parseText(response.body.asString()) - root.'io.codearte.accurest.stubs:streamService:stubs'.containsAll(["delete_book","return_book_1","return_book_2"]) + root.'io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book","return_book_1","return_book_2"]) } } diff --git a/stub-runner/stub-runner-junit/src/main/groovy/io/codearte/accurest/stubrunner/junit/AccurestRule.java b/stub-runner/stub-runner-junit/src/main/groovy/io/codearte/accurest/stubrunner/junit/AccurestRule.java index ab31e7ff74..75ba7705ab 100644 --- a/stub-runner/stub-runner-junit/src/main/groovy/io/codearte/accurest/stubrunner/junit/AccurestRule.java +++ b/stub-runner/stub-runner-junit/src/main/groovy/io/codearte/accurest/stubrunner/junit/AccurestRule.java @@ -29,6 +29,7 @@ import io.codearte.accurest.stubrunner.util.StubsParser; */ public class AccurestRule implements TestRule, StubFinder { private static final String DELIMITER = ":"; + public static final String LATEST_VERSION = "+"; private LinkedList stubs = new LinkedList<>(); private StubRunnerOptions stubRunnerOptions = defaultStubRunnerOptions(); @@ -109,10 +110,26 @@ public class AccurestRule implements TestRule, StubFinder { } /** - * Group Id, artifact Id and classifier of a single stub to download + * Group Id, artifact Id, version and classifier of a single stub to download */ - public AccurestRule downloadStub(String groupId, String artifactId, String classifier) { - addStub(groupId + DELIMITER + artifactId + DELIMITER + classifier); + public AccurestRule downloadStub(String groupId, String artifactId, String version, String classifier) { + addStub(groupId + DELIMITER + artifactId + DELIMITER + version + DELIMITER + classifier); + return this; + } + + /** + * Group Id, artifact Id and classifier of a single stub to download in the latest version + */ + public AccurestRule downloadLatestStub(String groupId, String artifactId, String classifier) { + addStub(groupId + DELIMITER + artifactId + DELIMITER + LATEST_VERSION + DELIMITER + classifier); + return this; + } + + /** + * Group Id, artifact Id and version of a single stub to download + */ + public AccurestRule downloadStub(String groupId, String artifactId, String version) { + addStub(groupId + DELIMITER + artifactId + DELIMITER + version); return this; } diff --git a/stub-runner/stub-runner-junit/src/test/groovy/io/codearte/accurest/stubrunner/junit/AccurestRuleSysPropsSpec.groovy b/stub-runner/stub-runner-junit/src/test/groovy/io/codearte/accurest/stubrunner/junit/AccurestRuleSysPropsSpec.groovy deleted file mode 100644 index 00e4065198..0000000000 --- a/stub-runner/stub-runner-junit/src/test/groovy/io/codearte/accurest/stubrunner/junit/AccurestRuleSysPropsSpec.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package io.codearte.accurest.stubrunner.junit - -import org.junit.AfterClass -import org.junit.BeforeClass -import org.junit.ClassRule -import spock.lang.Shared -import spock.lang.Specification - -/** - * @author Marcin Grzejszczak - */ -class AccurestRuleSysPropsSpec extends Specification { - - @BeforeClass - void setProps() { - System.properties.setProperty("stubrunner.stubs.repository.root", AccurestRuleSysPropsSpec.getResource("/m2repo").toURI().toString()) - System.properties.setProperty("stubrunner.stubs.classifier", 'classifier that will be overridden') - } - - @AfterClass - void cleanupProps() { - System.getProperties().setProperty("stubrunner.stubs.repository.root", ""); - System.getProperties().setProperty("stubrunner.stubs.classifier", "stubs"); - } - - @ClassRule @Shared AccurestRule rule = new AccurestRule() - .downloadStub("io.codearte.accurest.stubs", "loanIssuance", "stubs") - .downloadStub("io.codearte.accurest.stubs:fraudDetectionServer:stubs") - - def 'should start WireMock servers'() { - expect: 'WireMocks are running' - rule.findStubUrl('io.codearte.accurest.stubs', 'loanIssuance') != null - rule.findStubUrl('loanIssuance') != null - rule.findStubUrl('loanIssuance') == rule.findStubUrl('io.codearte.accurest.stubs', 'loanIssuance') - rule.findStubUrl('io.codearte.accurest.stubs:fraudDetectionServer') != null - and: 'Stubs were registered' - "${rule.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance' - "${rule.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer' - cleanup: - System.properties.setProperty("stubrunner.stubs.repository.root", "") - System.properties.setProperty("stubrunner.stubs.classifier", 'stubs') - } -} diff --git a/stub-runner/stub-runner-messaging/stub-runner-messaging-integration/src/test/resources/application.yml b/stub-runner/stub-runner-messaging/stub-runner-messaging-integration/src/test/resources/application.yml index 890cbe6dd8..3bec94b4b9 100644 --- a/stub-runner/stub-runner-messaging/stub-runner-messaging-integration/src/test/resources/application.yml +++ b/stub-runner/stub-runner-messaging/stub-runner-messaging-integration/src/test/resources/application.yml @@ -1,2 +1,2 @@ stubrunner.stubs.repository.root: classpath:m2repo/repository/ -stubrunner.stubs.ids: io.codearte.accurest.stubs:integrationService \ No newline at end of file +stubrunner.stubs.ids: io.codearte.accurest.stubs:integrationService:0.0.1-SNAPSHOT \ No newline at end of file diff --git a/stub-runner/stub-runner-messaging/stub-runner-messaging-stream/src/test/resources/application.yml b/stub-runner/stub-runner-messaging/stub-runner-messaging-stream/src/test/resources/application.yml index e83bb967d7..0bcac69997 100644 --- a/stub-runner/stub-runner-messaging/stub-runner-messaging-stream/src/test/resources/application.yml +++ b/stub-runner/stub-runner-messaging/stub-runner-messaging-stream/src/test/resources/application.yml @@ -1,5 +1,5 @@ stubrunner.stubs.repository.root: classpath:m2repo/repository/ -stubrunner.stubs.ids: io.codearte.accurest.stubs:streamService +stubrunner.stubs.ids: io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs spring: cloud: diff --git a/stub-runner/stub-runner/README.adoc b/stub-runner/stub-runner/README.adoc index af37e01bfc..075d1c7a6a 100644 --- a/stub-runner/stub-runner/README.adoc +++ b/stub-runner/stub-runner/README.adoc @@ -22,7 +22,7 @@ You can set the following options to the main class: (default: 10000) -s (--stubs) VAL : Comma separated list of Ivy representation of jars with stubs. Eg. groupid:artifactid1,group - id2:artifactid2:classifier + id2:artifactid2:version:classifier -sr (--stubRepositoryRoot) VAL : Location of a Jar containing server where you keep your stubs (e.g. http://nexus.net/content /repositories/repository) @@ -48,7 +48,7 @@ and inside the `build/lib` there will be a Fat Jar with classifier `fatJar` wait [source,groovy,indent=0] ---- -java -jar stub-runner/stub-runner/build/libs/stub-runner-1.0.1-SNAPSHOT-fatJar.jar -sr http://a.b.com -s a:b:c,d:e,f:g:h +java -jar stub-runner/stub-runner/build/libs/stub-runner-1.0.1-SNAPSHOT-fatJar.jar -sr http://a.b.com -s a:b:c,d:e,f:g:h:i ---- ==== Stub runner configuration diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/AetherStubDownloader.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/AetherStubDownloader.groovy index 15e36801be..b5b875d163 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/AetherStubDownloader.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/AetherStubDownloader.groovy @@ -12,19 +12,14 @@ import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory import org.eclipse.aether.impl.DefaultServiceLocator import org.eclipse.aether.repository.LocalRepository import org.eclipse.aether.repository.RemoteRepository -import org.eclipse.aether.resolution.ArtifactRequest -import org.eclipse.aether.resolution.ArtifactResult -import org.eclipse.aether.resolution.VersionRangeRequest -import org.eclipse.aether.resolution.VersionRangeResult +import org.eclipse.aether.resolution.* import org.eclipse.aether.spi.connector.RepositoryConnectorFactory import org.eclipse.aether.spi.connector.transport.TransporterFactory import org.eclipse.aether.transport.file.FileTransporterFactory import org.eclipse.aether.transport.http.HttpTransporterFactory -import org.eclipse.aether.version.Version import static io.codearte.accurest.stubrunner.util.ZipCategory.unzipTo import static java.nio.file.Files.createTempDirectory - /** * @author Mariusz Smykula */ @@ -35,7 +30,8 @@ class AetherStubDownloader implements StubDownloader { private static final String MAVEN_LOCAL_REPOSITORY_LOCATION = 'maven.repo.local' private static final String ACCUREST_TEMP_DIR_PREFIX = 'accurest' private static final String ARTIFACT_EXTENSION = 'jar' - private static final String ARTIFACT_VERSION = '(0,]' + private static final String LATEST_ARTIFACT_VERSION = '(0,]' + private static final String LATEST_VERSION_IN_IVY = "+" private final List remoteRepos private final RepositorySystem repositorySystem @@ -79,25 +75,63 @@ class AetherStubDownloader implements StubDownloader { @Override public File downloadAndUnpackStubJar(boolean workOffline, String stubRepositoryRoot, String stubsGroup, String stubsModule, String classifier) { - Version highestVersion = resolveArtifactVersion(stubsGroup, stubsModule, classifier); - log.info("Resolved highest version is $highestVersion") - if (!highestVersion) { + String version = getVersion(stubsGroup, stubsModule, LATEST_VERSION_IN_IVY, classifier) + return unpackedJar(version, stubsGroup, stubsModule, classifier, stubRepositoryRoot) + } + + private File unpackedJar(String resolvedVersion, String stubsGroup, String stubsModule, String classifier, String stubRepositoryRoot) { + log.info("Resolved version is $resolvedVersion") + if (!resolvedVersion) { log.warn("Stub for group [$stubsGroup] module [$stubsModule] and classifier [$classifier] not found in [$stubRepositoryRoot]") return null } - Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, highestVersion.toString()) + Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, resolvedVersion) ArtifactRequest request = new ArtifactRequest(artifact: artifact, repositories: remoteRepos) - log.info("Resolving artifact $artifact from ${remoteRepos?:'local maven repo'}") - ArtifactResult result = repositorySystem.resolveArtifact(session, request) - log.info("Resolved artifact $artifact to ${result.artifact.file} from ${result.repository}") - return unpackStubJarToATemporaryFolder(result.artifact.file.toURI()) + log.info("Resolving artifact $artifact from ${remoteRepos ?: 'local maven repo'}") + try { + ArtifactResult result = repositorySystem.resolveArtifact(session, request) + log.info("Resolved artifact $artifact to ${result.artifact.file} from ${result.repository}") + return unpackStubJarToATemporaryFolder(result.artifact.file.toURI()) + } catch (Exception e) { + log.warn("Exception occured while trying to download a stub for group [$stubsGroup] module [$stubsModule] and classifier [$classifier] in [$stubRepositoryRoot]", e) + return null + } + } - private Version resolveArtifactVersion(String stubsGroup, String stubsModule, String classifier) { - Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, ARTIFACT_VERSION) + private String getVersion(String stubsGroup, String stubsModule, String version, String classifier) { + if (!version || LATEST_VERSION_IN_IVY == version) { + log.info("Desired version is [$version] - will try to resolve the latest version") + return resolveHighestArtifactVersion(stubsGroup, stubsModule, classifier); + } + log.info("Will try to resolve version [$version]") + return resolveArtifactVersion(stubsGroup, stubsModule, version, classifier) + } + + @Override + Map.Entry downloadAndUnpackStubJar(StubRunnerOptions options, StubConfiguration stubConfiguration) { + String version = getVersion(stubConfiguration.groupId, stubConfiguration.artifactId, stubConfiguration.version, stubConfiguration.classifier) + File unpackedJar = unpackedJar(version, stubConfiguration.groupId, stubConfiguration.artifactId, + stubConfiguration.classifier, options.stubRepositoryRoot) + if(!unpackedJar) { + return null + } + return new AbstractMap.SimpleEntry(new StubConfiguration(stubConfiguration.groupId, stubConfiguration.artifactId, version, stubConfiguration.classifier), + unpackedJar) + } + + private String resolveHighestArtifactVersion(String stubsGroup, String stubsModule, String classifier) { + Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, LATEST_ARTIFACT_VERSION) VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, remoteRepos, null); VersionRangeResult rangeResult = repositorySystem.resolveVersionRange(session, versionRangeRequest); - return rangeResult.highestVersion; + return rangeResult.highestVersion ?: '' + } + + private String resolveArtifactVersion(String stubsGroup, String stubsModule, String version, String classifier) { + Artifact artifact = new DefaultArtifact(stubsGroup, stubsModule, classifier, ARTIFACT_EXTENSION, version) + VersionRequest versionRequest = new VersionRequest(artifact, remoteRepos, null) + VersionResult versionResult = repositorySystem.resolveVersion(session, versionRequest); + return versionResult.version ?: '' } private static File unpackStubJarToATemporaryFolder(URI stubJarUri) { diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/RunningStubs.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/RunningStubs.groovy index 1483b81926..90520ca15d 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/RunningStubs.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/RunningStubs.groovy @@ -26,26 +26,14 @@ class RunningStubs { } Map.Entry getEntry(String artifactId) { - def strings = artifactId.split(':') - if (strings.length == 1) { - return namesAndPorts.entrySet().find { - it.key.artifactId == artifactId - } - } else if(strings.length == 2) { - return namesAndPorts.entrySet().find { - it.key.groupId == strings[0] && it.key.artifactId == strings[1] - } - } return namesAndPorts.entrySet().find { - it.key.groupId == strings[0] && - it.key.artifactId == strings[1] && - it.key.classifier == strings[2] + it.key.matchesIvyNotation(artifactId) } } Integer getPort(String groupId, String artifactId) { return namesAndPorts.entrySet().find { - it.key.artifactId == artifactId && it.key.groupId == groupId + it.key.matchesIvyNotation("$groupId:$artifactId") }?.value } @@ -55,7 +43,7 @@ class RunningStubs { boolean isPresent(String groupId, String artifactId) { return namesAndPorts.entrySet().find { - it.key.artifactId == artifactId && it.key.groupId == groupId + it.key.matchesIvyNotation("$groupId:$artifactId") } } diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubConfiguration.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubConfiguration.groovy index fa22eae5a7..5d04e09850 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubConfiguration.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubConfiguration.groovy @@ -12,54 +12,72 @@ import io.codearte.accurest.stubrunner.util.StringUtils @EqualsAndHashCode public class StubConfiguration { private static final String STUB_COLON_DELIMITER = ":" + private static final String DEFAULT_VERSION = "+" + private static final String DEFAULT_CLASSIFIER = "stubs" final String groupId final String artifactId + final String version final String classifier - public StubConfiguration(String groupId, String artifactId, String classifier) { + public StubConfiguration(String groupId, String artifactId, String version) { this.groupId = groupId this.artifactId = artifactId + this.version = version + this.classifier = DEFAULT_CLASSIFIER + } + + public StubConfiguration(String groupId, String artifactId, String version, String classifier) { + this.groupId = groupId + this.artifactId = artifactId + this.version = version this.classifier = classifier } - public StubConfiguration(String stubPath, String defaultClassifier = "stubs") { + public StubConfiguration(String stubPath, String defaultClassifier) { String[] parsedPath = parsedPathEmptyByDefault(stubPath, STUB_COLON_DELIMITER, defaultClassifier) this.groupId = parsedPath[0] this.artifactId = parsedPath[1] - this.classifier = parsedPath[2] + this.version = parsedPath[2] + this.classifier = parsedPath[3] + } + + public StubConfiguration(String stubPath) { + String[] parsedPath = parsedPathEmptyByDefault(stubPath, STUB_COLON_DELIMITER, DEFAULT_CLASSIFIER) + this.groupId = parsedPath[0] + this.artifactId = parsedPath[1] + this.version = parsedPath[2] + this.classifier = parsedPath[3] } private List parsedPathEmptyByDefault(String path, String delimiter, String defaultClassifier) { String[] splitPath = path.split(delimiter) String stubsGroupId = "" String stubsArtifactId = "" + String stubsVersion = "" String stubsClassifier = "" if (splitPath.length >= 2) { stubsGroupId = splitPath[0] stubsArtifactId = splitPath[1] - stubsClassifier = splitPath.length == 3 ? splitPath[2] : defaultClassifier + stubsVersion = splitPath.length >= 3 ? splitPath[2] : DEFAULT_VERSION + stubsClassifier = splitPath.length == 4 ? splitPath[3] : defaultClassifier } - return [stubsGroupId, stubsArtifactId, stubsClassifier] + return [stubsGroupId, stubsArtifactId, stubsVersion, stubsClassifier] } private boolean isDefined() { return StringUtils.hasText(groupId) && StringUtils.hasText(this.artifactId) } - boolean hasClassifier() { - return StringUtils.hasText(classifier) - } - String toColonSeparatedDependencyNotation() { if(!isDefined()) { return "" } - return [groupId, artifactId, classifier].join(STUB_COLON_DELIMITER) + return [groupId, artifactId, version, classifier].join(STUB_COLON_DELIMITER) } @CompileDynamic - boolean matches(String ivyNotationAsString) { + boolean groupIdAndArtifactMatches(String ivyNotationAsString) { def (String groupId, String artifactId) = ivyNotationFrom(ivyNotationAsString) if (!groupId) { return this.artifactId == artifactId @@ -67,6 +85,43 @@ public class StubConfiguration { return this.groupId == groupId && this.artifactId == artifactId } + boolean equals(o) { + if (this.is(o)) return true + if (getClass() != o.class) return false + + StubConfiguration that = (StubConfiguration) o + + if (artifactId != that.artifactId) return false + if (groupId != that.groupId) return false + + return true + } + + int hashCode() { + int result + result = (groupId != null ? groupId.hashCode() : 0) + result = 31 * result + (artifactId != null ? artifactId.hashCode() : 0) + return result + } + + boolean matchesIvyNotation(String ivyNotationAsString) { + def strings = ivyNotationAsString.split(':') + if (strings.length == 1) { + return artifactId == ivyNotationAsString + } else if(strings.length == 2) { + return groupId == strings[0] && + artifactId == strings[1] + } else if(strings.length == 3) { + return groupId == strings[0] && + artifactId == strings[1] && + (strings[2] == DEFAULT_VERSION || version == strings[2]) + } + return groupId == strings[0] && + artifactId == strings[1] && + (strings[2] == DEFAULT_VERSION || version == strings[2]) && + classifier == strings[3] + } + private String[] ivyNotationFrom(String ivyNotation) { String[] splitString = ivyNotation.split(":") if (splitString.length == 1) { diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubDownloader.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubDownloader.groovy index 006e639cfd..def3d78ae6 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubDownloader.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubDownloader.groovy @@ -2,6 +2,15 @@ package io.codearte.accurest.stubrunner interface StubDownloader { + @Deprecated File downloadAndUnpackStubJar(boolean workOffline, String stubRepositoryRoot, String stubsGroup, String stubsModule, String classifier) + + /** + * Returns a mapping of updated StubConfiguration (it will contain the resolved version) and the location of the downloaded JAR. + * If there was no artifact this method will return {@code null}. + */ + Map.Entry downloadAndUnpackStubJar(StubRunnerOptions options, StubConfiguration stubConfiguration) + + } \ No newline at end of file diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutor.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutor.groovy index 0f30354e36..2852327f13 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutor.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutor.groovy @@ -71,7 +71,7 @@ class StubRunnerExecutor implements StubFinder { @Override boolean trigger(String ivyNotationAsString, String labelName) { Collection matchingContracts = getAccurestContracts().findAll { - it.key.matches(ivyNotationAsString) + it.key.groupIdAndArtifactMatches(ivyNotationAsString) }.values().flatten() as Collection return triggerForDsls(matchingContracts, labelName) } diff --git a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerFactory.groovy b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerFactory.groovy index 9a969213bf..51a77acb7c 100644 --- a/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerFactory.groovy +++ b/stub-runner/stub-runner/src/main/groovy/io/codearte/accurest/stubrunner/StubRunnerFactory.groovy @@ -27,14 +27,15 @@ class StubRunnerFactory { Collection createStubsFromServiceConfiguration() { return collaborators.collect { StubConfiguration stubsConfiguration -> - final File unzipedStubDir = stubDownloader.downloadAndUnpackStubJar(stubRunnerOptions.workOffline, - stubRunnerOptions.stubRepositoryRoot, - stubsConfiguration.groupId, stubsConfiguration.artifactId, stubsConfiguration.classifier) - return createStubRunner(unzipedStubDir, stubsConfiguration) + Map.Entry entry = stubDownloader.downloadAndUnpackStubJar(stubRunnerOptions, stubsConfiguration) + if (!entry) { + return null + } + return createStubRunner(entry.key, entry.value) }.findAll { it != null } } - private StubRunner createStubRunner(File unzipedStubDir, StubConfiguration stubsConfiguration) { + private StubRunner createStubRunner(StubConfiguration stubsConfiguration, File unzipedStubDir) { if (!unzipedStubDir) { return null } diff --git a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/RunningStubsSpec.groovy b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/RunningStubsSpec.groovy index d9cf63516b..11acce3339 100644 --- a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/RunningStubsSpec.groovy +++ b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/RunningStubsSpec.groovy @@ -6,26 +6,31 @@ import spock.lang.Specification * @author Marcin Grzejszczak */ class RunningStubsSpec extends Specification { - RunningStubs runningStubs = new RunningStubs([(new StubConfiguration('a', 'b', 'c')) : 100]) + RunningStubs runningStubs = new RunningStubs([(new StubConfiguration('group', 'artifact', 'version', 'classifier')) : 100]) def "should get port by group and artifact id"() { expect: - runningStubs.getPort('a', 'b') == 100 + runningStubs.getPort('group', 'artifact') == 100 } def "should get port by artifact id"() { expect: - runningStubs.getPort('b') == 100 + runningStubs.getPort('artifact') == 100 } def "should get port by group and artifact id in Ivy notation"() { expect: - runningStubs.getPort('a:b') == 100 + runningStubs.getPort('group:artifact') == 100 } - def "should get port by group, artifact id and classifier in Ivy notation"() { + def "should get port by group, artifact id and version in Ivy notation"() { expect: - runningStubs.getPort('a:b:c') == 100 + runningStubs.getPort('group:artifact:version') == 100 + } + + def "should get port by group, artifact id, version and classifier in Ivy notation"() { + expect: + runningStubs.getPort('group:artifact:version:classifier') == 100 } def "should return null if no stub has been found"() { @@ -35,22 +40,27 @@ class RunningStubsSpec extends Specification { def "should find stub by group and artifact id"() { expect: - runningStubs.isPresent('a', 'b') + runningStubs.isPresent('group', 'artifact') } def "should find stub by artifact id"() { expect: - runningStubs.isPresent('b') + runningStubs.isPresent('artifact') } def "should find stub by group and artifact id in Ivy notation"() { expect: - runningStubs.isPresent('a:b') + runningStubs.isPresent('group:artifact') } - def "should find stub by group, artifact id and classifier in Ivy notation"() { + def "should find stub by group, artifact id and version in Ivy notation"() { expect: - runningStubs.isPresent('a:b:c') + runningStubs.isPresent('group:artifact:version') + } + + def "should find stub by group, artifact id, version and classifier in Ivy notation"() { + expect: + runningStubs.isPresent('group:artifact:version:classifier') } def "should return false if no stub has been found"() { diff --git a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubConfigurationSpec.groovy b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubConfigurationSpec.groovy new file mode 100644 index 0000000000..87b346da94 --- /dev/null +++ b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubConfigurationSpec.groovy @@ -0,0 +1,21 @@ +package io.codearte.accurest.stubrunner + +import spock.lang.Specification + +/** + * @author Marcin Grzejszczak + */ +class StubConfigurationSpec extends Specification { + + def 'should parse ivy notation'() { + given: + String ivy = 'group:artifact:version:classifier' + when: + StubConfiguration stubConfiguration = new StubConfiguration(ivy) + then: + stubConfiguration.artifactId == 'artifact' + stubConfiguration.groupId == 'group' + stubConfiguration.classifier == 'classifier' + stubConfiguration.version == 'version' + } +} diff --git a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutorSpec.groovy b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutorSpec.groovy index fc30f2978e..25add46ece 100644 --- a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutorSpec.groovy +++ b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerExecutorSpec.groovy @@ -4,9 +4,8 @@ import spock.lang.Specification class StubRunnerExecutorSpec extends Specification { - static final URL EXPECTED_STUB_URL = new URL('http://localhost:8999') static final int MIN_PORT = 8999 - static final int MAX_PORT = 8999 + static final int MAX_PORT = 9999 private AvailablePortScanner portScanner private StubRepository repository @@ -24,7 +23,9 @@ class StubRunnerExecutorSpec extends Specification { when: executor.runStubs(stubRunnerOptions, repository, stub) then: - executor.findStubUrl("group", "artifact") == EXPECTED_STUB_URL + URL url = executor.findStubUrl("group", "artifact") + url.port >= MIN_PORT + url.port <= MAX_PORT and: executor.findAllRunningStubs().isPresent('artifact') executor.findAllRunningStubs().isPresent('group', 'artifact') diff --git a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerFactorySpec.groovy b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerFactorySpec.groovy index 0d368096bb..19481ce7e0 100644 --- a/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerFactorySpec.groovy +++ b/stub-runner/stub-runner/src/test/groovy/io/codearte/accurest/stubrunner/StubRunnerFactorySpec.groovy @@ -18,7 +18,8 @@ class StubRunnerFactorySpec extends Specification { def "Should download stub definitions many times"() { given: folder.newFolder("mappings") - 2 * downloader.downloadAndUnpackStubJar(_, _, _, _, _) >> folder.root + 1 * downloader.downloadAndUnpackStubJar(_, _) >> new AbstractMap.SimpleEntry(new StubConfiguration('a:b'), folder.root) + 1 * downloader.downloadAndUnpackStubJar(_, _) >> new AbstractMap.SimpleEntry(new StubConfiguration('c:d'), folder.root) stubRunnerOptions.stubRepositoryRoot = folder.root.absolutePath when: Collection stubRunners = collectOnlyPresentValues(factory.createStubsFromServiceConfiguration())