From c438dfef3eef4f529658718b48426d2ce1ad4cab Mon Sep 17 00:00:00 2001 From: Marco Vermeulen Date: Tue, 5 Dec 2017 08:47:23 +0000 Subject: [PATCH] Perform candidate cache check in main function. --- src/main/bash/sdkman-init.sh | 24 +-- src/main/bash/sdkman-main.sh | 4 +- src/test/cucumber/upgrade_candidate.feature | 1 + .../specs/BetaChannelBootstrapSpec.groovy | 2 +- .../specs/CandidatesCacheBootstrapSpec.groovy | 176 ------------------ .../specs/CandidatesCacheUpdateSpec.groovy | 91 +++++++++ .../sdkman/specs/CurrentCommandSpec.groovy | 9 +- .../sdkman/specs/InitialisationSpec.groovy | 1 - .../sdkman/specs/SdkCompatibilitySpec.groovy | 1 - src/test/groovy/sdkman/steps/env.groovy | 2 + .../sdkman/steps/initialisation_steps.groovy | 5 + .../groovy/sdkman/steps/stub_steps.groovy | 5 + .../groovy/sdkman/steps/update_steps.groovy | 13 ++ .../groovy/sdkman/stubs/WebServiceStub.groovy | 2 - 14 files changed, 133 insertions(+), 203 deletions(-) delete mode 100644 src/test/groovy/sdkman/specs/CandidatesCacheBootstrapSpec.groovy create mode 100644 src/test/groovy/sdkman/specs/CandidatesCacheUpdateSpec.groovy create mode 100644 src/test/groovy/sdkman/steps/update_steps.groovy diff --git a/src/main/bash/sdkman-init.sh b/src/main/bash/sdkman-init.sh index 131aa704..4b67ffeb 100644 --- a/src/main/bash/sdkman-init.sh +++ b/src/main/bash/sdkman-init.sh @@ -98,25 +98,6 @@ fi if [[ -z "$sdkman_curl_connect_timeout" ]]; then sdkman_curl_connect_timeout=7; fi if [[ -z "$sdkman_curl_max_time" ]]; then sdkman_curl_max_time=10; fi -# fabricate list of candidates -SDKMAN_CANDIDATES_CACHE="${SDKMAN_DIR}/var/candidates" -if [[ -f "$SDKMAN_CANDIDATES_CACHE" && -n "$(cat "$SDKMAN_CANDIDATES_CACHE")" && -z "$(find "$SDKMAN_CANDIDATES_CACHE" -mmin +$((60*24)))" ]]; then - __sdkman_echo_debug "Using existing candidates cache: $SDKMAN_CANDIDATES_CACHE" -else - CANDIDATES_URI="${SDKMAN_CURRENT_API}/candidates/all" - __sdkman_echo_debug "Using candidates endpoint: $CANDIDATES_URI" - SDKMAN_FRESH_CANDIDATES_CSV=$(__sdkman_secure_curl_with_timeouts "$CANDIDATES_URI") - __sdkman_echo_debug "Fetched candidates csv: $SDKMAN_FRESH_CANDIDATES_CSV" - DETECT_HTML="$(echo "$SDKMAN_FRESH_CANDIDATES_CSV" | tr '[:upper:]' '[:lower:]' | grep 'html')" - if [[ -n "$SDKMAN_FRESH_CANDIDATES_CSV" && -z "$DETECT_HTML" ]]; then - __sdkman_echo_debug "Overwriting candidates cache with: $SDKMAN_FRESH_CANDIDATES_CSV" - echo "$SDKMAN_FRESH_CANDIDATES_CSV" > "$SDKMAN_CANDIDATES_CACHE" - fi - unset CANDIDATES_URI SDKMAN_FRESH_CANDIDATES_CSV DETECT_HTML -fi - -SDKMAN_CANDIDATES_CSV=$(cat "$SDKMAN_CANDIDATES_CACHE") - # determine if up to date SDKMAN_VERSION_FILE="${SDKMAN_DIR}/var/version" if [[ "$sdkman_beta_channel" != "true" && -f "$SDKMAN_VERSION_FILE" && -z "$(find "$SDKMAN_VERSION_FILE" -mmin +$((60*24)))" ]]; then @@ -144,7 +125,10 @@ else fi fi -# Set the candidate array +# Read list of candidates and set array +SDKMAN_CANDIDATES_CACHE="${SDKMAN_DIR}/var/candidates" +SDKMAN_CANDIDATES_CSV=$(cat "$SDKMAN_CANDIDATES_CACHE") +__sdkman_echo_debug "Setting candidates csv: $SDKMAN_CANDIDATES_CSV" if [[ "$zsh_shell" == 'true' ]]; then SDKMAN_CANDIDATES=( ${(s:,:)SDKMAN_CANDIDATES_CSV} ) else diff --git a/src/main/bash/sdkman-main.sh b/src/main/bash/sdkman-main.sh index 1b131fdb..452ad94a 100644 --- a/src/main/bash/sdkman-main.sh +++ b/src/main/bash/sdkman-main.sh @@ -53,7 +53,9 @@ function sdk { # # Various sanity checks and default settings # - mkdir -p "$SDKMAN_DIR" + + # Check candidates cache + ___sdkman_check_candidates_cache "$SDKMAN_CANDIDATES_CACHE" || return 1 # Always presume internet availability SDKMAN_AVAILABLE="true" diff --git a/src/test/cucumber/upgrade_candidate.feature b/src/test/cucumber/upgrade_candidate.feature index 1d85bfc5..0ad61993 100644 --- a/src/test/cucumber/upgrade_candidate.feature +++ b/src/test/cucumber/upgrade_candidate.feature @@ -2,6 +2,7 @@ Feature: Upgrade Candidate Background: Given the internet is reachable + And the candidates cache is initialised with "grails" And an initialised environment Scenario: Display upgradable candidate version in use when it is upgradable diff --git a/src/test/groovy/sdkman/specs/BetaChannelBootstrapSpec.groovy b/src/test/groovy/sdkman/specs/BetaChannelBootstrapSpec.groovy index 9637b18b..e7c05793 100644 --- a/src/test/groovy/sdkman/specs/BetaChannelBootstrapSpec.groovy +++ b/src/test/groovy/sdkman/specs/BetaChannelBootstrapSpec.groovy @@ -13,7 +13,7 @@ class BetaChannelBootstrapSpec extends SdkmanEnvSpecification { def setup() { versionCache = new File("${sdkmanDotDirectory}/var", "version") - sdkmanBashEnvBuilder.withCandidatesCache(["groovy"]) + sdkmanBashEnvBuilder.withCandidates(["groovy"]) } void "should attempt immediate upgrade of stable to beta version if beta channel is first enabled"() { diff --git a/src/test/groovy/sdkman/specs/CandidatesCacheBootstrapSpec.groovy b/src/test/groovy/sdkman/specs/CandidatesCacheBootstrapSpec.groovy deleted file mode 100644 index 4f1f3a6c..00000000 --- a/src/test/groovy/sdkman/specs/CandidatesCacheBootstrapSpec.groovy +++ /dev/null @@ -1,176 +0,0 @@ -package sdkman.specs - -import sdkman.support.SdkmanEnvSpecification - -import static java.lang.System.currentTimeMillis - -class CandidatesCacheBootstrapSpec extends SdkmanEnvSpecification { - - static final MORE_THAN_A_DAY_IN_MILLIS = 24 * 61 * 60 * 1000 - - static final LEGACY_API = "http://localhost:8080/1" - static final LEGACY_VERSIONS_STABLE_ENDPOINT = "$LEGACY_API/candidates/app/stable" - static final LEGACY_VERSIONS_BETA_ENDPOINT = "$LEGACY_API/candidates/app/beta" - - static final CURRENT_API = "http://localhost:8080/2" - static final CURRENT_CANDIDATES_ENDPOINT = "$CURRENT_API/candidates/all" - - File candidatesCache - - def setup() { - candidatesCache = new File("${sdkmanDotDirectory}/var", "candidates") - curlStub.primeWith(LEGACY_VERSIONS_STABLE_ENDPOINT, "echo x.y.y") - .primeWith(LEGACY_VERSIONS_BETA_ENDPOINT, "echo x.y.z") - sdkmanBashEnvBuilder.withConfiguration("sdkman_debug_mode", "true") - } - - void "should not query server if unexpired candidates cache is found"() { - given: - bash = sdkmanBashEnvBuilder - .withCandidatesCache(['gradle', 'sbt']) - .build() - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.exists() - candidatesCache.text.contains("gradle,sbt") - - and: - bash.output.contains "gradle,sbt" - } - - void "should fetch and store candidates in cache if cache is empty"() { - given: - curlStub.primeWith(CURRENT_CANDIDATES_ENDPOINT, "echo groovy,scala") - bash = sdkmanBashEnvBuilder - .withCandidatesCache([]) - .withLegacyService(LEGACY_API) - .build() - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.exists() - candidatesCache.text.contains("groovy,scala") - - and: - bash.output.contains("groovy,scala") - } - - void "should fetch candidates and refresh cache if older than a day"() { - given: - curlStub.primeWith(CURRENT_CANDIDATES_ENDPOINT, "echo groovy,scala") - bash = sdkmanBashEnvBuilder - .withLegacyService(LEGACY_API) - .withCandidatesCache(['groovy']) - .build() - - and: - candidatesCache.setLastModified(currentTimeMillis() - MORE_THAN_A_DAY_IN_MILLIS) - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.exists() - candidatesCache.text.contains('groovy,scala') - - and: - bash.output.contains("groovy,scala") - } - - void "should ignore candidates if api is offline"() { - given: - def candidates = ['groovy', 'scala'] - curlStub.primeWith(CURRENT_CANDIDATES_ENDPOINT, "echo ''") - bash = sdkmanBashEnvBuilder - .withLegacyService(LEGACY_API) - .withCandidatesCache(candidates) - .build() - - and: - candidatesCache.setLastModified(currentTimeMillis() - MORE_THAN_A_DAY_IN_MILLIS) - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.text.contains('groovy,scala') - - and: - bash.output.contains("groovy,scala") - } - - void "should ignore candidates if api returns garbage"() { - given: - def candidates = ['groovy', 'scala'] - curlStub.primeWith(CURRENT_CANDIDATES_ENDPOINT, "echo 'sorry'") - bash = sdkmanBashEnvBuilder - .withLegacyService(LEGACY_API) - .withCandidatesCache(candidates) - .build() - - and: - candidatesCache.setLastModified(currentTimeMillis() - MORE_THAN_A_DAY_IN_MILLIS) - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.text.contains('groovy,scala') - - and: - bash.output.contains("groovy,scala") - } - - void "should query api if not subscribed to beta channel"() { - given: - curlStub.primeWith(CURRENT_CANDIDATES_ENDPOINT, "echo groovy,scala") - bash = sdkmanBashEnvBuilder - .withLegacyService(LEGACY_API) - .withCurrentService(CURRENT_API) - .withConfiguration("sdkman_beta_channel", "false") - .withCandidatesCache(['groovy']) - .build() - - and: - candidatesCache.setLastModified(currentTimeMillis() - MORE_THAN_A_DAY_IN_MILLIS) - - and: - bash.start() - - when: - bash.execute("source $bootstrapScript") - bash.execute('echo $SDKMAN_CANDIDATES_CSV') - - then: - candidatesCache.exists() - candidatesCache.text.contains('groovy,scala') - - and: - bash.output.contains("groovy,scala") - } -} diff --git a/src/test/groovy/sdkman/specs/CandidatesCacheUpdateSpec.groovy b/src/test/groovy/sdkman/specs/CandidatesCacheUpdateSpec.groovy new file mode 100644 index 00000000..1bba5277 --- /dev/null +++ b/src/test/groovy/sdkman/specs/CandidatesCacheUpdateSpec.groovy @@ -0,0 +1,91 @@ +package sdkman.specs + +import sdkman.support.SdkmanEnvSpecification + +class CandidatesCacheUpdateSpec extends SdkmanEnvSpecification { + + static final LEGACY_API = "http://localhost:8080/1" + static final LEGACY_VERSIONS_STABLE_ENDPOINT = "$LEGACY_API/candidates/app/stable" + static final LEGACY_VERSIONS_BETA_ENDPOINT = "$LEGACY_API/candidates/app/beta" + + static final CURRENT_API = "http://localhost:8080/2" + static final BROADCAST_API_LATEST_ID_ENDPOINT = "$CURRENT_API/broadcast/latest/id" + + File candidatesCache + + def setup() { + candidatesCache = new File("${sdkmanDotDirectory}/var", "candidates") + curlStub.primeWith(LEGACY_VERSIONS_STABLE_ENDPOINT, "echo x.y.y") + .primeWith(LEGACY_VERSIONS_BETA_ENDPOINT, "echo x.y.z") + .primeWith(BROADCAST_API_LATEST_ID_ENDPOINT, "echo dbfb025be9f97fda2052b5febcca0155") + sdkmanBashEnvBuilder.withConfiguration("sdkman_debug_mode", "true") + } + + void "should issue a warning if cache is empty"() { + given: + bash = sdkmanBashEnvBuilder + .withCandidates([]) + .withLegacyService(LEGACY_API) + .build() + + and: + bash.start() + + when: + bash.execute("source $bootstrapScript") + bash.execute("sdk version") + + then: + bash.output.contains('Warning! Cache is corrupt. SDKMAN can not be used until updated.') + bash.output.contains('$ sdk update') + + and: + !bash.output.contains("SDKMAN 5.0.0") + } + + void "should issue a warning if cache is older than a month"() { + given: + bash = sdkmanBashEnvBuilder + .withLegacyService(LEGACY_API) + .withCandidates(['groovy']) + .build() + + and: + candidatesCache.setLastModified(((new Date() - 31) as Date).time) + + and: + bash.start() + + when: + bash.execute("source $bootstrapScript") + bash.execute("sdk version") + + then: + bash.output.contains('Warning! SDKMAN out-of-date and requires an update.') + bash.output.contains('$ sdk update') + + and: + bash.output.contains('SDKMAN 5.0.0') + } + + void "should log a success message in debug mode when no update needed"() { + given: + bash = sdkmanBashEnvBuilder + .withLegacyService(LEGACY_API) + .withCandidates(['groovy']) + .build() + + and: + bash.start() + + when: + bash.execute("source $bootstrapScript") + bash.execute("sdk version") + + then: + bash.output.contains('No update needed. Using existing candidates cache') + + and: + bash.output.contains('SDKMAN 5.0.0') + } +} diff --git a/src/test/groovy/sdkman/specs/CurrentCommandSpec.groovy b/src/test/groovy/sdkman/specs/CurrentCommandSpec.groovy index e8612481..b701da64 100644 --- a/src/test/groovy/sdkman/specs/CurrentCommandSpec.groovy +++ b/src/test/groovy/sdkman/specs/CurrentCommandSpec.groovy @@ -8,6 +8,13 @@ import static java.nio.file.Files.createSymbolicLink class CurrentCommandSpec extends SdkmanEnvSpecification { + static final CURRENT_API = "http://localhost:8080/2" + static final BROADCAST_API_LATEST_ID_ENDPOINT = "$CURRENT_API/broadcast/latest/id" + + def setup() { + curlStub.primeWith(BROADCAST_API_LATEST_ID_ENDPOINT, "echo dbfb025be9f97fda2052b5febcca0155") + } + void "should display current version of all candidates installed"() { given: def installedCandidates = [ @@ -34,7 +41,7 @@ class CurrentCommandSpec extends SdkmanEnvSpecification { bash = sdkmanBashEnvBuilder .withOfflineMode(false) - .withCandidatesCache(allCandidates) + .withVersionCache("5.0.0") .withCandidates(installedCandidates.keySet().toList()) .build() diff --git a/src/test/groovy/sdkman/specs/InitialisationSpec.groovy b/src/test/groovy/sdkman/specs/InitialisationSpec.groovy index b71a4e8b..1f006902 100644 --- a/src/test/groovy/sdkman/specs/InitialisationSpec.groovy +++ b/src/test/groovy/sdkman/specs/InitialisationSpec.groovy @@ -12,7 +12,6 @@ class InitialisationSpec extends SdkmanEnvSpecification { def setup() { bash = sdkmanBashEnvBuilder - .withCandidatesCache(allCandidates) .withCandidates(allCandidates) .withVersionCache("x.y.z") .build() diff --git a/src/test/groovy/sdkman/specs/SdkCompatibilitySpec.groovy b/src/test/groovy/sdkman/specs/SdkCompatibilitySpec.groovy index 53fd42dc..86340f17 100644 --- a/src/test/groovy/sdkman/specs/SdkCompatibilitySpec.groovy +++ b/src/test/groovy/sdkman/specs/SdkCompatibilitySpec.groovy @@ -11,7 +11,6 @@ class SdkCompatibilitySpec extends SdkmanEnvSpecification { def setup() { bash = sdkmanBashEnvBuilder - .withCandidatesCache(allCandidates) .withCandidates(allCandidates) .withVersionCache("x.y.z") .build() diff --git a/src/test/groovy/sdkman/steps/env.groovy b/src/test/groovy/sdkman/steps/env.groovy index 79da16fe..344220d4 100644 --- a/src/test/groovy/sdkman/steps/env.groovy +++ b/src/test/groovy/sdkman/steps/env.groovy @@ -44,6 +44,8 @@ candidatesFile = new File(varDir, "candidates") versionFile = new File(varDir, "version") initScript = new File(binDir, "sdkman-init.sh") +localCandidates = ['groovy', 'grails', 'java', 'kotlin', 'scala'] + bash = null if(!binding.hasVariable("wireMock")) { diff --git a/src/test/groovy/sdkman/steps/initialisation_steps.groovy b/src/test/groovy/sdkman/steps/initialisation_steps.groovy index 565f44f9..5a09a199 100644 --- a/src/test/groovy/sdkman/steps/initialisation_steps.groovy +++ b/src/test/groovy/sdkman/steps/initialisation_steps.groovy @@ -94,6 +94,7 @@ And(~'^an initialised environment$') {-> .withJdkHome(javaHome) .withHttpProxy(HTTP_PROXY) .withVersionCache(sdkmanVersion) + .withCandidates(localCandidates) .withSdkmanVersion(sdkmanVersion) .build() } @@ -133,4 +134,8 @@ And(~'^the system is bootstrapped again$') {-> And(~/^the sdkman version is "([^"]*)"$/) { String version -> sdkmanVersion = version +} + +And(~/^the candidates cache is initialised with "(.*)"$/) { String candidate -> + localCandidates << candidate } \ No newline at end of file diff --git a/src/test/groovy/sdkman/steps/stub_steps.groovy b/src/test/groovy/sdkman/steps/stub_steps.groovy index 296dc6b0..2f4822ae 100644 --- a/src/test/groovy/sdkman/steps/stub_steps.groovy +++ b/src/test/groovy/sdkman/steps/stub_steps.groovy @@ -1,5 +1,6 @@ package sdkman.steps +import cucumber.api.DataTable import sdkman.support.UnixUtils import static cucumber.api.groovy.EN.And @@ -100,3 +101,7 @@ And(~/^a download request was made for "(.*)" "(.*)" on "(.*)" with cookie "(.*) And(~/^a cookie is required for installing "(.*)" "(.*)" on "(.*)"$/) { String candidate, String version, String platform -> //handled by the hook in subsequent step } + +And(~/^the following candidates are currently available from remote API:$/) { DataTable dt -> + primeEndpointWithString("/candidates/all", dt.asList(String).drop(1).join(",")) +} \ No newline at end of file diff --git a/src/test/groovy/sdkman/steps/update_steps.groovy b/src/test/groovy/sdkman/steps/update_steps.groovy new file mode 100644 index 00000000..7ad48ff7 --- /dev/null +++ b/src/test/groovy/sdkman/steps/update_steps.groovy @@ -0,0 +1,13 @@ +package sdkman.steps + +import cucumber.api.DataTable + +import static cucumber.api.groovy.EN.* + +And(~/^the following candidates are available for installation in local cache:$/) { DataTable dt -> + localCandidates = dt.asList(String).drop(1) +} + +And(~/^the Candidates cache should contain "(.*)"$/) { String candidates -> + assert candidatesFile.text.trim() == candidates +} \ No newline at end of file diff --git a/src/test/groovy/sdkman/stubs/WebServiceStub.groovy b/src/test/groovy/sdkman/stubs/WebServiceStub.groovy index 8c143e7b..60b8af83 100644 --- a/src/test/groovy/sdkman/stubs/WebServiceStub.groovy +++ b/src/test/groovy/sdkman/stubs/WebServiceStub.groovy @@ -1,7 +1,5 @@ package sdkman.stubs -import sdkman.support.UnixUtils - import static com.github.tomakehurst.wiremock.client.WireMock.* class WebServiceStub {