From 2a4408e37c020f9ff9bf62c4606b4d7cb4394a18 Mon Sep 17 00:00:00 2001 From: Nikolas Falco Date: Thu, 2 Jan 2025 00:54:38 +0100 Subject: [PATCH] [JENKINS-75073] Missing serverUrl in fillCredentialsIdItems cause some credentials missing in the initial configuration If the number of server instances is only one, when a new Jenkins project is created the server list combobox is not available. This causes, in the UI component that loads credentials, to pass the stapler parameter serverUrl as an empty string. In this scenario, serverUrl must be taken from the first of configured endpoints so that it can properly filter the list of credentials. --- .../bitbucket/BitbucketGitSCMBuilder.java | 7 +- .../bitbucket/BitbucketSCMNavigator.java | 43 +- .../plugins/bitbucket/BitbucketSCMSource.java | 20 +- .../bitbucket/BitbucketSCMSourceBuilder.java | 3 +- .../client/BitbucketCloudApiFactory.java | 12 +- .../endpoints/AbstractBitbucketEndpoint.java | 9 +- .../BitbucketEndpointConfiguration.java | 73 +- .../endpoints/BitbucketServerEndpoint.java | 18 +- .../filesystem/BitbucketSCMFileSystem.java | 11 +- .../hooks/WebhookAutoRegisterListener.java | 10 +- .../bitbucket/hooks/WebhookConfiguration.java | 9 +- .../impl/util/BitbucketApiUtils.java | 41 +- .../impl/util/BitbucketCredentials.java | 33 +- .../client/BitbucketServerAPIClient.java | 12 +- .../client/BitbucketCloudApiClientTest.java | 2 +- .../BitbucketEndpointConfigurationTest.java | 890 +++++++++--------- 16 files changed, 605 insertions(+), 588 deletions(-) diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketGitSCMBuilder.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketGitSCMBuilder.java index 06988a2ec..89de17bb6 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketGitSCMBuilder.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketGitSCMBuilder.java @@ -104,10 +104,9 @@ public BitbucketGitSCMBuilder(@NonNull BitbucketSCMSource scmSource, @NonNull SC this.scmSource = scmSource; String serverURL = scmSource.getServerUrl(); - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverURL); - if (endpoint == null) { - endpoint = new BitbucketServerEndpoint(null, serverURL, false, null); - } + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(serverURL) + .orElse(new BitbucketServerEndpoint(null, serverURL, false, null)); String repositoryURL = endpoint.getRepositoryUrl(scmSource.getRepoOwner(), scmSource.getRepository()); if (BitbucketApiUtils.isCloud(endpoint.getServerUrl())) { diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMNavigator.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMNavigator.java index b9243386f..5cd9fee2d 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMNavigator.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMNavigator.java @@ -102,6 +102,7 @@ import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; +import org.kohsuke.stapler.interceptor.RequirePOST; import static com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils.getFromBitbucket; @@ -290,7 +291,7 @@ public String getServerUrl() { @DataBoundSetter public void setServerUrl(String serverUrl) { serverUrl = BitbucketEndpointConfiguration.normalizeServerUrl(serverUrl); - if (!StringUtils.equals(this.serverUrl, serverUrl)) { + if (serverUrl != null && !StringUtils.equals(this.serverUrl, serverUrl)) { this.serverUrl = serverUrl; resetId(); } @@ -384,14 +385,14 @@ public String getPattern() { @DataBoundSetter public void setBitbucketServerUrl(String url) { url = BitbucketEndpointConfiguration.normalizeServerUrl(url); - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(url); - if (endpoint != null) { - // we have a match - setServerUrl(url); - return; + url = StringUtils.defaultIfBlank(url, BitbucketCloudEndpoint.SERVER_URL); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(url) + .orElse(null); + if (endpoint == null) { + LOGGER.log(Level.WARNING, "Call to legacy setBitbucketServerUrl({0}) method is configuring a url missing " + + "from the global configuration.", url); } - LOGGER.log(Level.WARNING, "Call to legacy setBitbucketServerUrl({0}) method is configuring a url missing " - + "from the global configuration.", url); setServerUrl(url); } @@ -400,7 +401,10 @@ public void setBitbucketServerUrl(String url) { @RestrictedSince("2.2.0") @CheckForNull public String getBitbucketServerUrl() { - if (BitbucketEndpointConfiguration.get().findEndpoint(serverUrl) instanceof BitbucketCloudEndpoint) { + if (BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl) + .filter(BitbucketCloudEndpoint.class::isInstance) + .isPresent()) { return null; } return serverUrl; @@ -629,7 +633,7 @@ public String getIconClassName() { @Override public SCMNavigator newInstance(String name) { BitbucketSCMNavigator instance = new BitbucketSCMNavigator(StringUtils.defaultString(name)); - instance.setTraits((List) getTraitsDefaults()); + instance.setTraits(getTraitsDefaults()); return instance; } @@ -647,16 +651,21 @@ public ListBoxModel doFillServerUrlItems(@AncestorInPath SCMSourceOwner context) return BitbucketEndpointConfiguration.get().getEndpointItems(); } + @RequirePOST @SuppressWarnings("unused") // used By stapler - public FormValidation doCheckCredentialsId(@AncestorInPath SCMSourceOwner context, @QueryParameter String serverUrl, @QueryParameter String value) { - return BitbucketCredentials.checkCredentialsId(context, value, serverUrl); + public static FormValidation doCheckCredentialsId(@AncestorInPath SCMSourceOwner context, + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL, + @QueryParameter String value) { + return BitbucketCredentials.checkCredentialsId(context, value, serverURL); } + @RequirePOST @SuppressWarnings("unused") // used By stapler - public static FormValidation doCheckMirrorId(@QueryParameter String value, @QueryParameter String serverUrl) { + public static FormValidation doCheckMirrorId(@QueryParameter String value, + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) { if (!value.isEmpty()) { BitbucketServerWebhookImplementation webhookImplementation = - BitbucketServerEndpoint.findWebhookImplementation(serverUrl); + BitbucketServerEndpoint.findWebhookImplementation(serverURL); if (webhookImplementation == BitbucketServerWebhookImplementation.PLUGIN) { return FormValidation.error("Mirror can only be used with native webhooks"); } @@ -666,13 +675,13 @@ public static FormValidation doCheckMirrorId(@QueryParameter String value, @Quer @SuppressWarnings("unused") // used By stapler public ListBoxModel doFillCredentialsIdItems(@AncestorInPath SCMSourceOwner context, - @QueryParameter String serverUrl) { - return BitbucketCredentials.fillCredentialsIdItems(context, serverUrl); + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) { + return BitbucketCredentials.fillCredentialsIdItems(context, serverURL); } @SuppressWarnings("unused") // used By stapler public ListBoxModel doFillMirrorIdItems(@AncestorInPath SCMSourceOwner context, - @QueryParameter String serverUrl, + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverUrl, @QueryParameter String credentialsId, @QueryParameter String repoOwner) throws FormFillFailure { diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java index 01bdee406..7791a4151 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java @@ -401,7 +401,10 @@ public void setTraits(@CheckForNull List traits) { @DataBoundSetter public void setBitbucketServerUrl(String url) { url = BitbucketEndpointConfiguration.normalizeServerUrl(url); - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(url); + url = StringUtils.defaultIfBlank(url, BitbucketCloudEndpoint.SERVER_URL); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(url) + .orElse(null); if (endpoint != null) { // we have a match setServerUrl(endpoint.getServerUrl()); @@ -418,7 +421,10 @@ public void setBitbucketServerUrl(String url) { @CheckForNull public String getBitbucketServerUrl() { String serverUrl = getServerUrl(); - if (BitbucketEndpointConfiguration.get().findEndpoint(serverUrl) instanceof BitbucketCloudEndpoint) { + if (BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl) + .filter(BitbucketCloudEndpoint.class::isInstance) + .isPresent()) { return null; } return serverUrl; @@ -1336,8 +1342,8 @@ public String getDisplayName() { @SuppressWarnings("unused") // used By stapler public FormValidation doCheckCredentialsId(@CheckForNull @AncestorInPath SCMSourceOwner context, @QueryParameter String value, - @QueryParameter String serverUrl) { - return BitbucketCredentials.checkCredentialsId(context, value, serverUrl); + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) { + return BitbucketCredentials.checkCredentialsId(context, value, serverURL); } @SuppressWarnings("unused") // used By stapler @@ -1353,11 +1359,13 @@ public static FormValidation doCheckServerUrl(@AncestorInPath SCMSourceOwner con return FormValidation.ok(); } + @RequirePOST @SuppressWarnings("unused") // used By stapler - public static FormValidation doCheckMirrorId(@QueryParameter String value, @QueryParameter String serverUrl) { + public static FormValidation doCheckMirrorId(@QueryParameter String value, + @QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) { if (!value.isEmpty()) { BitbucketServerWebhookImplementation webhookImplementation = - BitbucketServerEndpoint.findWebhookImplementation(serverUrl); + BitbucketServerEndpoint.findWebhookImplementation(serverURL); if (webhookImplementation == BitbucketServerWebhookImplementation.PLUGIN) { return FormValidation.error("Mirror can only be used with native webhooks"); } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSourceBuilder.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSourceBuilder.java index 27f8145da..204f48695 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSourceBuilder.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSourceBuilder.java @@ -23,7 +23,6 @@ */ package com.cloudbees.jenkins.plugins.bitbucket; -import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import jenkins.scm.api.trait.SCMSourceBuilder; @@ -74,7 +73,7 @@ public BitbucketSCMSourceBuilder(@CheckForNull String id, @NonNull String server @NonNull String repoName, @CheckForNull String mirrorId) { super(BitbucketSCMSource.class, repoName); this.id = id; - this.serverUrl = BitbucketEndpointConfiguration.normalizeServerUrl(serverUrl); + this.serverUrl = serverUrl; this.credentialsId = credentialsId; this.mirrorId = mirrorId; this.repoOwner = repoOwner; diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiFactory.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiFactory.java index 493419c0c..dcf712209 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiFactory.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiFactory.java @@ -22,14 +22,16 @@ protected boolean isMatch(@Nullable String serverUrl) { @Override protected BitbucketApi create(@Nullable String serverUrl, @Nullable BitbucketAuthenticator authenticator, @NonNull String owner, @CheckForNull String projectKey, @CheckForNull String repository) { - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(BitbucketCloudEndpoint.SERVER_URL); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(BitbucketCloudEndpoint.SERVER_URL) + .orElse(null); boolean enableCache = false; int teamCacheDuration = 0; int repositoriesCacheDuration = 0; - if (endpoint != null && endpoint instanceof BitbucketCloudEndpoint) { - enableCache = ((BitbucketCloudEndpoint) endpoint).isEnableCache(); - teamCacheDuration = ((BitbucketCloudEndpoint) endpoint).getTeamCacheDuration(); - repositoriesCacheDuration = ((BitbucketCloudEndpoint) endpoint).getRepositoriesCacheDuration(); + if (endpoint instanceof BitbucketCloudEndpoint cloudEndpoint) { + enableCache = cloudEndpoint.isEnableCache(); + teamCacheDuration = cloudEndpoint.getTeamCacheDuration(); + repositoriesCacheDuration = cloudEndpoint.getRepositoriesCacheDuration(); } return new BitbucketCloudApiClient( enableCache, teamCacheDuration, repositoriesCacheDuration, diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/AbstractBitbucketEndpoint.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/AbstractBitbucketEndpoint.java index 7e4100fcd..c4d3558cb 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/AbstractBitbucketEndpoint.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/AbstractBitbucketEndpoint.java @@ -144,10 +144,11 @@ public void setBitbucketJenkinsRootUrl(String bitbucketJenkinsRootUrl) { */ @NonNull public String getEndpointJenkinsRootUrl() { - if (StringUtils.isBlank(bitbucketJenkinsRootUrl)) + if (StringUtils.isBlank(bitbucketJenkinsRootUrl)) { return ClassicDisplayURLProvider.get().getRoot(); - else + } else { return bitbucketJenkinsRootUrl; + } } /** @@ -172,7 +173,9 @@ public static String getEndpointJenkinsRootUrl(String serverUrl) { // Note: do not pre-initialize to the global value, so it can be // reconfigured on the fly. - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl) + .orElse(null); if (endpoint != null) { return endpoint.getEndpointJenkinsRootUrl(); } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfiguration.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfiguration.java index 1df6e0f9b..2d7943188 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfiguration.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfiguration.java @@ -36,10 +36,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Locale; +import java.util.Objects; import java.util.Optional; import java.util.Set; import jenkins.model.GlobalConfiguration; @@ -85,6 +85,7 @@ public static BitbucketEndpointConfiguration get() { public Permission getRequiredGlobalConfigPagePermission() { return Jenkins.MANAGE; } + /** * Called from a {@code readResolve()} method only to convert the old {@code bitbucketServerUrl} field into the new * {@code serverUrl} field. When called from {@link ACL#SYSTEM} this will update the configuration with the @@ -96,9 +97,10 @@ public Permission getRequiredGlobalConfigPagePermission() { @Restricted(NoExternalUse.class) // only for plugin internal use. @NonNull public String readResolveServerUrl(@CheckForNull String bitbucketServerUrl) { - String serverUrl = normalizeServerUrl(bitbucketServerUrl); - AbstractBitbucketEndpoint endpoint = findEndpoint(serverUrl); + String serverUrl = StringUtils.defaultIfBlank(bitbucketServerUrl, BitbucketCloudEndpoint.SERVER_URL); + AbstractBitbucketEndpoint endpoint = findEndpoint(serverUrl).orElse(null); if (endpoint == null && ACL.SYSTEM.equals(Jenkins.getAuthentication())) { + serverUrl = normalizeServerUrl(serverUrl); if (BitbucketCloudEndpoint.SERVER_URL.equals(serverUrl) || BitbucketCloudEndpoint.BAD_SERVER_URL.equals(serverUrl)) { // exception case @@ -107,7 +109,7 @@ public String readResolveServerUrl(@CheckForNull String bitbucketServerUrl) { addEndpoint(new BitbucketServerEndpoint(null, serverUrl, false, null)); } } - return endpoint == null ? serverUrl : endpoint.getServerUrl(); + return endpoint == null ? serverUrl : endpoint.getServerUrl(); } /** @@ -238,66 +240,65 @@ public boolean removeEndpoint(@NonNull AbstractBitbucketEndpoint endpoint) { /** * Removes an endpoint. * - * @param serverUrl the server URL to remove. + * @param serverURL the server URL to remove. * @return {@code true} if the list of endpoints was modified */ - public synchronized boolean removeEndpoint(@CheckForNull String serverUrl) { - serverUrl = normalizeServerUrl(serverUrl); - boolean modified = false; - List endpoints = new ArrayList<>(getEndpoints()); - for (Iterator iterator = endpoints.iterator(); iterator.hasNext(); ) { - if (serverUrl.equals(iterator.next().getServerUrl())) { - iterator.remove(); - modified = true; - } - } - setEndpoints(endpoints); + public synchronized boolean removeEndpoint(@CheckForNull String serverURL) { + String fixedServerURL = normalizeServerUrl(serverURL); + List newEndpoints = new ArrayList<>(getEndpoints()); + boolean modified = newEndpoints.removeIf(endpoint -> Objects.equals(fixedServerURL, endpoint.getServerUrl())); + setEndpoints(newEndpoints); return modified; } /** * Checks to see if the supplied server URL is defined in the global configuration. * - * @param serverUrl the server url to check. + * @param serverURL the server url to check. * @return the global configuration for the specified server url or {@code null} if not defined. */ - @CheckForNull - public synchronized AbstractBitbucketEndpoint findEndpoint(@CheckForNull String serverUrl) { - serverUrl = normalizeServerUrl(serverUrl); + public synchronized Optional findEndpoint(@CheckForNull String serverURL) { + serverURL = normalizeServerUrl(serverURL); for (AbstractBitbucketEndpoint endpoint : getEndpoints()) { - if (serverUrl.equals(endpoint.getServerUrl())) { - return endpoint; + if (Objects.equals(serverURL, endpoint.getServerUrl())) { + return Optional.of(endpoint); } } - return null; + return Optional.empty(); } /** * Checks to see if the supplied server URL is defined in the global configuration. * - * @param serverUrl the server url to check. + * @param serverURL the server url to check. * @param clazz the class to check. * @return the global configuration for the specified server url or {@code null} if not defined. */ - public synchronized Optional findEndpoint(@CheckForNull String serverUrl, - Class clazz) { - return getEndpoints().stream() + public synchronized Optional findEndpoint(@CheckForNull String serverURL, + Class clazz) { + return findEndpoint(serverURL) .filter(clazz::isInstance) - .filter(endpoint -> normalizeServerUrl(serverUrl).equals(endpoint.getServerUrl())) - .findFirst(); + .map(clazz::cast); + } + + @NonNull + public synchronized AbstractBitbucketEndpoint getDefaultEndpoint() { + return getEndpoints().get(0); } /** * Fix a serverUrl. * - * @param serverUrl the server URL. + * @param serverURL the server URL. * @return the normalized server URL. */ - @NonNull - public static String normalizeServerUrl(@CheckForNull String serverUrl) { - serverUrl = StringUtils.defaultIfBlank(serverUrl, BitbucketCloudEndpoint.SERVER_URL); + @CheckForNull + public static String normalizeServerUrl(@CheckForNull String serverURL) { + if (StringUtils.isBlank(serverURL)) { + return null; + } try { - URI uri = new URI(serverUrl).normalize(); + URI uri = new URI(serverURL).normalize(); String scheme = uri.getScheme(); if ("http".equals(scheme) || "https".equals(scheme)) { // we only expect http / https, but also these are the only ones where we know the authority @@ -311,7 +312,7 @@ public static String normalizeServerUrl(@CheckForNull String serverUrl) { } else if ("https".equals(scheme) && port == 443) { port = -1; } - serverUrl = new URI( + serverURL = new URI( scheme, uri.getUserInfo(), host, @@ -324,7 +325,7 @@ public static String normalizeServerUrl(@CheckForNull String serverUrl) { } catch (URISyntaxException e) { // ignore, this was a best effort tidy-up } - return serverUrl.replaceAll("/$", ""); + return serverURL.replaceAll("/$", ""); } } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint.java index cbd25577f..b05be9893 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketServerEndpoint.java @@ -122,9 +122,11 @@ public BitbucketServerEndpoint(@CheckForNull String displayName, @NonNull String @NonNull public static BitbucketServerWebhookImplementation findWebhookImplementation(String serverUrl) { - final AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl); - if (endpoint instanceof BitbucketServerEndpoint) { - return ((BitbucketServerEndpoint) endpoint).getWebhookImplementation(); + final BitbucketServerEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl, BitbucketServerEndpoint.class) + .orElse(null); + if (endpoint != null) { + return endpoint.getWebhookImplementation(); } return BitbucketServerWebhookImplementation.PLUGIN; @@ -150,12 +152,10 @@ public void setCallChanges(boolean callChanges) { @NonNull public static BitbucketServerVersion findServerVersion(String serverUrl) { - final AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl); - if (endpoint instanceof BitbucketServerEndpoint) { - return ((BitbucketServerEndpoint) endpoint).getServerVersion(); - } - - return BitbucketServerVersion.VERSION_7; + return BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl, BitbucketServerEndpoint.class) + .map(endpoint -> endpoint.getServerVersion()) + .orElse(BitbucketServerVersion.VERSION_7); } @NonNull diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/filesystem/BitbucketSCMFileSystem.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/filesystem/BitbucketSCMFileSystem.java index 863dc7141..e27f50371 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/filesystem/BitbucketSCMFileSystem.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/filesystem/BitbucketSCMFileSystem.java @@ -32,10 +32,8 @@ import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApi; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApiFactory; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator; -import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketCloudApiClient; -import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint; -import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration; import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint; +import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils; import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerVersion; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; @@ -166,7 +164,7 @@ public SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead head, @Ch return null; } - if (apiClient instanceof BitbucketCloudApiClient) { + if (BitbucketApiUtils.isCloud(apiClient)) { // support lightweight checkout for branches with same owner and repository if (prHead.getCheckoutStrategy() == ChangeRequestCheckoutStrategy.HEAD && prHead.getRepoOwner().equals(src.getRepoOwner()) && @@ -184,9 +182,8 @@ public SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead head, @Ch // Bitbucket server v7 doesn't have the `merge` ref for PRs // We don't return `ref` when working with v7 // so that pipeline falls back to heavyweight checkout properly - AbstractBitbucketEndpoint endpointConfig = BitbucketEndpointConfiguration.get().findEndpoint(src.getServerUrl()); - if (endpointConfig instanceof BitbucketServerEndpoint endpoint && - endpoint.getServerVersion() != BitbucketServerVersion.VERSION_7) { + boolean ligthCheckout = BitbucketServerEndpoint.findServerVersion(serverUrl) != BitbucketServerVersion.VERSION_7; + if (ligthCheckout) { ref = "pull-requests/" + prHead.getId() + "/merge"; } else { // returning null to fall back to heavyweight checkout diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java index d8a728aea..1a523e791 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookAutoRegisterListener.java @@ -139,8 +139,9 @@ private synchronized void registerHooks(SCMSourceOwner owner) throws IOException case DISABLE: continue; case SYSTEM: - AbstractBitbucketEndpoint endpoint = - BitbucketEndpointConfiguration.get().findEndpoint(source.getServerUrl()); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(source.getServerUrl()) + .orElse(null); if (endpoint == null || !endpoint.isManageHooks()) { continue; } @@ -215,8 +216,9 @@ private BitbucketApi bitbucketApiFor(BitbucketSCMSource source) { case DISABLE: return null; case SYSTEM: - AbstractBitbucketEndpoint endpoint = - BitbucketEndpointConfiguration.get().findEndpoint(source.getServerUrl()); + AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(source.getServerUrl()) + .orElse(null); return endpoint == null || !endpoint.isManageHooks() ? null : BitbucketApiFactory.newInstance( diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java index bbd14c4de..43275f44a 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/WebhookConfiguration.java @@ -26,7 +26,6 @@ import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketWebHook; import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketRepositoryHook; -import com.cloudbees.jenkins.plugins.bitbucket.endpoints.AbstractBitbucketEndpoint; import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint; import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration; import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint; @@ -213,9 +212,11 @@ public BitbucketWebHook getHook(BitbucketSCMSource owner) { } private static List getNativeServerEvents(String serverUrl) { - AbstractBitbucketEndpoint endpoint = BitbucketEndpointConfiguration.get().findEndpoint(serverUrl); - if (endpoint instanceof BitbucketServerEndpoint) { - switch (((BitbucketServerEndpoint) endpoint).getServerVersion()) { + BitbucketServerEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(serverUrl, BitbucketServerEndpoint.class) + .orElse(null); + if (endpoint != null) { + switch (endpoint.getServerVersion()) { case VERSION_5: return NATIVE_SERVER_EVENTS_v5; case VERSION_5_10: diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketApiUtils.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketApiUtils.java index 74f605397..11434df0e 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketApiUtils.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketApiUtils.java @@ -28,6 +28,10 @@ @Restricted(NoExternalUse.class) public class BitbucketApiUtils { + public interface BitbucketSupplier { + T get(BitbucketApi bitbucketApi) throws IOException, InterruptedException; + } + private static final Logger logger = Logger.getLogger(BitbucketApiUtils.class.getName()); public static boolean isCloud(BitbucketApi client) { @@ -39,7 +43,7 @@ public static boolean isCloud(@NonNull String serverURL) { } public static ListBoxModel getFromBitbucket(SCMSourceOwner context, - String serverUrl, + String serverURL, String credentialsId, String repoOwner, String repository, @@ -57,40 +61,35 @@ public static ListBoxModel getFromBitbucket(SCMSourceOwner context, return new ListBoxModel(); // not permitted to try connecting with these credentials } - String serverUrlFallback = BitbucketCloudEndpoint.SERVER_URL; - // if at least one bitbucket server is configured use it instead of bitbucket cloud - if (!BitbucketEndpointConfiguration.get().getEndpointItems().isEmpty()) { - serverUrlFallback = BitbucketEndpointConfiguration.get().getEndpointItems().get(0).value; - } - - serverUrl = StringUtils.defaultIfBlank(serverUrl, serverUrlFallback); + serverURL = BitbucketEndpointConfiguration.get() + .findEndpoint(serverURL) + .orElse(BitbucketEndpointConfiguration.get().getDefaultEndpoint()) + .getServerUrl(); StandardCredentials credentials = BitbucketCredentials.lookupCredentials( - serverUrl, + serverURL, context, credentialsId, StandardCredentials.class ); - BitbucketAuthenticator authenticator = AuthenticationTokens.convert(BitbucketAuthenticator.authenticationContext(serverUrl), credentials); + BitbucketAuthenticator authenticator = AuthenticationTokens.convert(BitbucketAuthenticator.authenticationContext(serverURL), credentials); try { - BitbucketApi bitbucket = BitbucketApiFactory.newInstance(serverUrl, authenticator, repoOwner, null, repository); + BitbucketApi bitbucket = BitbucketApiFactory.newInstance(serverURL, authenticator, repoOwner, null, repository); return listBoxModelSupplier.get(bitbucket); } catch (FormFillFailure | OutOfMemoryError e) { throw e; } catch (IOException e) { - if (e instanceof BitbucketRequestException) { - if (((BitbucketRequestException) e).getHttpCode() == 401) { - throw FormFillFailure.error(credentials == null - ? Messages.BitbucketSCMSource_UnauthorizedAnonymous(repoOwner) - : Messages.BitbucketSCMSource_UnauthorizedOwner(repoOwner)).withSelectionCleared(); - } - } else if (e.getCause() instanceof BitbucketRequestException) { - if (((BitbucketRequestException) e.getCause()).getHttpCode() == 401) { + if (e instanceof BitbucketRequestException bbe) { + if (bbe.getHttpCode() == 401) { throw FormFillFailure.error(credentials == null ? Messages.BitbucketSCMSource_UnauthorizedAnonymous(repoOwner) : Messages.BitbucketSCMSource_UnauthorizedOwner(repoOwner)).withSelectionCleared(); } + } else if (e.getCause() instanceof BitbucketRequestException cause && cause.getHttpCode() == 401) { + throw FormFillFailure.error(credentials == null + ? Messages.BitbucketSCMSource_UnauthorizedAnonymous(repoOwner) + : Messages.BitbucketSCMSource_UnauthorizedOwner(repoOwner)).withSelectionCleared(); } logger.log(Level.SEVERE, e.getMessage(), e); throw FormFillFailure.error(e.getMessage()); @@ -100,8 +99,4 @@ public static ListBoxModel getFromBitbucket(SCMSourceOwner context, } } - public interface BitbucketSupplier { - T get(BitbucketApi bitbucketApi) throws IOException, InterruptedException; - } - } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketCredentials.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketCredentials.java index 3bd691680..31883c001 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketCredentials.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/util/BitbucketCredentials.java @@ -24,6 +24,7 @@ package com.cloudbees.jenkins.plugins.bitbucket.impl.util; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator; +import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardCertificateCredentials; @@ -41,8 +42,6 @@ import jenkins.model.Jenkins; import jenkins.scm.api.SCMSourceOwner; import org.apache.commons.lang.StringUtils; -import org.kohsuke.stapler.AncestorInPath; -import org.kohsuke.stapler.QueryParameter; import org.springframework.security.core.Authentication; /** @@ -79,9 +78,7 @@ public static T lookupCredentials(@CheckForNull return null; } - public static ListBoxModel fillCredentialsIdItems( - @AncestorInPath SCMSourceOwner context, - @QueryParameter String serverUrl) { + public static ListBoxModel fillCredentialsIdItems(SCMSourceOwner context, String serverURL) { StandardListBoxModel result = new StandardListBoxModel(); result.includeEmptyValue(); AccessControlled contextToCheck = context == null ? Jenkins.get() : context; @@ -92,21 +89,28 @@ public static ListBoxModel fillCredentialsIdItems( ? task.getDefaultAuthentication2() : ACL.SYSTEM2; + serverURL = BitbucketEndpointConfiguration.get() + .findEndpoint(serverURL) + .orElse(BitbucketEndpointConfiguration.get().getDefaultEndpoint()) + .getServerUrl(); + result.includeMatchingAs( authentication, context, StandardCredentials.class, - URIRequirementBuilder.fromUri(serverUrl).build(), - AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) + URIRequirementBuilder.fromUri(serverURL).build(), + AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverURL)) ); return result; } - public static FormValidation checkCredentialsId( - @AncestorInPath @CheckForNull SCMSourceOwner context, - @QueryParameter String value, - @QueryParameter String serverUrl) { - if (!value.isEmpty()) { + public static FormValidation checkCredentialsId(@CheckForNull SCMSourceOwner context, String value, String serverURL) { + if (StringUtils.isNotBlank(value)) { + serverURL = BitbucketEndpointConfiguration.get() + .findEndpoint(serverURL) + .orElse(BitbucketEndpointConfiguration.get().getDefaultEndpoint()) + .getServerUrl(); + AccessControlled contextToCheck = context == null ? Jenkins.get() : context; contextToCheck.checkPermission(CredentialsProvider.VIEW); @@ -119,10 +123,10 @@ public static FormValidation checkCredentialsId( StandardCertificateCredentials.class, context, authentication, - URIRequirementBuilder.fromUri(serverUrl).build()), + URIRequirementBuilder.fromUri(serverURL).build()), CredentialsMatchers.allOf( CredentialsMatchers.withId(value), - AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) + AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverURL)) ) ) != null) { return FormValidation.warning("A certificate was selected. You will likely need to configure Checkout over SSH."); @@ -132,4 +136,5 @@ public static FormValidation checkCredentialsId( return FormValidation.warning("Credentials are required for build notifications"); } } + } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java index 06addc5fb..ccd7d59ca 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java @@ -264,8 +264,9 @@ private List getPullRequests(UriTemplate template) pullRequests.removeIf(this::shouldIgnore); - BitbucketServerEndpoint endpoint = (BitbucketServerEndpoint) BitbucketEndpointConfiguration.get(). - findEndpoint(this.baseURL, BitbucketServerEndpoint.class).orElse(null); + BitbucketServerEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(this.baseURL, BitbucketServerEndpoint.class) + .orElse(null); for (BitbucketServerPullRequest pullRequest : pullRequests) { setupPullRequest(pullRequest, endpoint); @@ -395,8 +396,11 @@ public BitbucketPullRequest getPullRequestById(@NonNull Integer id) throws IOExc try { BitbucketServerPullRequest pr = JsonParser.toJava(response, BitbucketServerPullRequest.class); setupClosureForPRBranch(pr); - setupPullRequest(pr, (BitbucketServerEndpoint) BitbucketEndpointConfiguration.get(). - findEndpoint(this.baseURL, BitbucketServerEndpoint.class).orElse(null)); + + BitbucketServerEndpoint endpoint = BitbucketEndpointConfiguration.get() + .findEndpoint(this.baseURL, BitbucketServerEndpoint.class) + .orElse(null); + setupPullRequest(pr, endpoint); return pr; } catch (IOException e) { throw new IOException("I/O error when accessing URL: " + url, e); diff --git a/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClientTest.java b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClientTest.java index ab4b756b8..6052e20d4 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClientTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClientTest.java @@ -69,7 +69,7 @@ private String loadPayload(String api) throws IOException { @Test @WithJenkins - public void test_proxy_configurad_without_password(JenkinsRule r) throws Exception { + void test_proxy_configurad_without_password(JenkinsRule r) throws Exception { Proxy proxy = mock(Proxy.class); when(proxy.address()).thenReturn(new InetSocketAddress("proxy.lan", 8080)); ProxyConfiguration proxyConfiguration = mock(ProxyConfiguration.class); diff --git a/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfigurationTest.java b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfigurationTest.java index ed5a85e9b..267ce98ca 100644 --- a/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfigurationTest.java +++ b/src/test/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/BitbucketEndpointConfigurationTest.java @@ -45,32 +45,25 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import jenkins.model.Jenkins; import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assume.assumeThat; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; -public class BitbucketEndpointConfigurationTest { +@WithJenkins +class BitbucketEndpointConfigurationTest { - @ClassRule - public static JenkinsRule j = new JenkinsRule(); - - @Before - public void cleanUp() throws IOException { + @AfterEach + void cleanUp() throws IOException { BitbucketEndpointConfiguration.get().setEndpoints(null); new XmlFile(new File(Jenkins.get().getRootDir(), BitbucketEndpointConfiguration.get().getId() + ".xml")) .delete(); @@ -79,259 +72,284 @@ public void cleanUp() throws IOException { } @Test - public void given__newInstance__when__notConfigured__then__cloudPresent() { + void given__newInstance__when__notConfigured__then__cloudPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); } @Test - public void given__newInstance__when__configuredWithEmpty__then__cloudPresent() { + void given__newInstance__when__configuredWithEmpty__then__cloudPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints(Collections.emptyList()); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); } @Test - public void given__newInstance__when__configuredWithCloud__then__cloudPresent() { + void given__newInstance__when__configuredWithCloud__then__cloudPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), not(is("dummy"))); + assumeFalse("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.setEndpoints( Collections.singletonList(new BitbucketCloudEndpoint(true, "dummy"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); } @Test - public void given__newInstance__when__configuredWithMultipleCloud__then__onlyFirstCloudPresent() { + void given__newInstance__when__configuredWithMultipleCloud__then__onlyFirstCloudPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), not(is("first"))); + assumeFalse("first".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.setEndpoints(Arrays.asList( new BitbucketCloudEndpoint(true, "first"), new BitbucketCloudEndpoint(true, "second"), new BitbucketCloudEndpoint(true, "third"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("first"); + }); } @Test - public void given__newInstance__when__configuredAsAnon__then__permissionError() { + void given__newInstance__when__configuredAsAnon__then__permissionError(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); j.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy()); try (ACLContext context = ACL.as(Jenkins.ANONYMOUS)) { - instance.setEndpoints(Arrays.asList( - new BitbucketCloudEndpoint(true, "first"), - new BitbucketCloudEndpoint(true, "second"), - new BitbucketCloudEndpoint(true, "third"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - } catch (RuntimeException x) { - assertThat(x.getMessage(), is(hudson.security.Messages.AccessDeniedException2_MissingPermission("anonymous", "Overall/Administer"))); + assertThatThrownBy(() -> instance.setEndpoints(Arrays.asList( + new BitbucketCloudEndpoint(true, "first"), + new BitbucketCloudEndpoint(true, "second"), + new BitbucketCloudEndpoint(true, "third")))) + .hasMessage(hudson.security.Messages.AccessDeniedException2_MissingPermission("anonymous", "Overall/Administer")); } finally { j.jenkins.setAuthorizationStrategy(AuthorizationStrategy.UNSECURED); } } @Test - public void given__newInstance__when__configuredAsManage__then__OK() { + void given__newInstance__when__configuredAsManage__then__OK(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - try { - j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); - MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); - mockStrategy.grant(Jenkins.MANAGE).onRoot().to("admin"); - j.jenkins.setAuthorizationStrategy(mockStrategy); - try (ACLContext context = ACL.as(User.get("admin"))) { - instance.setEndpoints(Arrays.asList( - new BitbucketCloudEndpoint(true, "first"), - new BitbucketCloudEndpoint(true, "second"), - new BitbucketCloudEndpoint(true, "third"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - } catch (RuntimeException x) { - Assertions.fail("No exception should be thrown"); - } + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); + MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); + mockStrategy.grant(Jenkins.MANAGE).onRoot().to("admin"); + j.jenkins.setAuthorizationStrategy(mockStrategy); + try (ACLContext context = ACL.as(User.get("admin"))) { + instance.setEndpoints(Arrays.asList( + new BitbucketCloudEndpoint(true, "first"), + new BitbucketCloudEndpoint(true, "second"), + new BitbucketCloudEndpoint(true, "third"))); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("first"); + }); } finally { j.jenkins.setAuthorizationStrategy(AuthorizationStrategy.UNSECURED); } } @Test - public void given__newInstance__when__configuredWithServerUsingCloudUrl__then__convertedToCloud() { + void given__newInstance__when__configuredWithServerUsingCloudUrl__then__convertedToCloud(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), not(is("dummy"))); + assumeFalse("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.setEndpoints(Arrays.asList( new BitbucketServerEndpoint("I am silly", BitbucketCloudEndpoint.SERVER_URL, true, "dummy"), new BitbucketCloudEndpoint(true, "second"), new BitbucketCloudEndpoint(true, "third"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); } @Test - public void given__newInstance__when__configuredWithServer__then__serverPresent() { + void given__newInstance__when__configuredWithServer__then__serverPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), not(is("dummy"))); + assumeFalse("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getDisplayName(), is("Example Inc")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.example.com")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(true)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(endpoint.getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(endpoint.isManageHooks()).isTrue(); + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); } @Test - public void given__newInstance__when__configuredWithTwoServers__then__serversPresent() { + void given__newInstance__when__configuredWithTwoServers__then__serversPresent(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), not(is("dummy"))); + assumeFalse("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.setEndpoints( Arrays.asList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", false, null))); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketServerEndpoint.class), instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getDisplayName(), is("Example Inc")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.example.com")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(true)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.getEndpoints().get(1).getDisplayName(), is("Example Org")); - assertThat(instance.getEndpoints().get(1).getServerUrl(), is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpoints().get(1).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is(nullValue())); + + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(endpoint.getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(endpoint.isManageHooks()).isTrue(); + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + assertThat(instance.getEndpoints()).element(1).satisfies(endpoint -> { + assertThat(endpoint.getDisplayName()).isEqualTo("Example Org"); + assertThat(endpoint.getServerUrl()).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(endpoint.isManageHooks()).isFalse(); + assertThat(endpoint.getCredentialsId()).isNull(); + }); } @Test - public void given__instanceWithCloud__when__addingAnotherCloud__then__onlyFirstCloudRetained() { + void given__instanceWithCloud__when__addingAnotherCloud__then__onlyFirstCloudRetained(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList(new BitbucketCloudEndpoint(true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.addEndpoint(new BitbucketCloudEndpoint(false, null)), is(false)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + + assertThat(instance.addEndpoint(new BitbucketCloudEndpoint(false, null))).isFalse(); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); } @Test - public void given__instanceWithServer__when__addingCloud__then__cloudAdded() { + void given__instanceWithServer__when__addingCloud__then__cloudAdded(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.addEndpoint(new BitbucketCloudEndpoint(true, "added")), is(true)); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketServerEndpoint.class), instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("added")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + + assertThat(instance.addEndpoint(new BitbucketCloudEndpoint(true, "added"))).isTrue(); + assertThat(instance.getEndpoints()).hasExactlyElementsOfTypes(BitbucketServerEndpoint.class, BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + assertThat(instance.getEndpoints()).element(1).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("added"); + }); } @Test - public void given__instanceWithServer__when__addingDifferentServer__then__serverAdded() { + void given__instanceWithServer__when__addingDifferentServer__then__serverAdded(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.addEndpoint( - new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "added")), - is(true)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class), instanceOf( - BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("added")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + + assertThat(instance.addEndpoint(new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "added"))).isTrue(); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + assertThat(instance.getEndpoints()).element(1).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("added"); + }); } @Test - public void given__instanceWithServer__when__addingSameServer__then__onlyFirstServerRetained() { + void given__instanceWithServer__when__addingSameServer__then__onlyFirstServerRetained(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.addEndpoint( - new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", false, null)), is(false)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + + assertThat(instance.addEndpoint(new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", false, null))).isFalse(); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); } @Test - public void given__instanceWithCloud__when__updatingCloud__then__cloudUpdated() { + void given__instanceWithCloud__when__updatingCloud__then__cloudUpdated(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList(new BitbucketCloudEndpoint(true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + instance.updateEndpoint(new BitbucketCloudEndpoint(false, null)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is(nullValue())); + + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isNull(); + }); } @Test - public void given__instanceWithServer__when__updatingCloud__then__cloudAdded() { + void given__instanceWithServer__when__updatingCloud__then__cloudAdded(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); instance.updateEndpoint(new BitbucketCloudEndpoint(true, "added")); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketServerEndpoint.class), instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("added")); + + assertThat(instance.getEndpoints()).hasExactlyElementsOfTypes(BitbucketServerEndpoint.class, BitbucketCloudEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + assertThat(instance.getEndpoints()).element(1).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("added"); + }); } @Test - public void given__instanceWithServer__when__updatingDifferentServer__then__serverAdded() { + void given__instanceWithServer__when__updatingDifferentServer__then__serverAdded(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - instance.updateEndpoint( - new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "added")); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class), instanceOf( - BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("added")); + assumeTrue("dummy".equals(instance.getEndpoints().get(0).getCredentialsId())); + + instance.updateEndpoint(new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "added")); + + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("dummy"); + }); + assertThat(instance.getEndpoints()).element(1).satisfies(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("added"); + }); } @Test - public void given__instanceWithServer__when__updatingSameServer__then__serverUpdated() { + void given__instanceWithServer__when__updatingSameServer__then__serverUpdated(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"))); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getDisplayName(), is("Example Inc")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.example.com")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(true)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("dummy")); - instance.updateEndpoint( - new BitbucketServerEndpoint("Example, Inc.", "https://bitbucket.example.com/", false, null)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getDisplayName(), is("Example, Inc.")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.example.com")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is(nullValue())); - } - - @Test - public void given__newInstance__when__removingCloud__then__defaultRestored() { + + instance.updateEndpoint(new BitbucketServerEndpoint("Example, Inc.", "https://bitbucket.example.com/", false, null)); + + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints()).element(0).satisfies(endpoint -> { + assertThat(endpoint.getDisplayName()).isEqualTo("Example, Inc."); + assertThat(endpoint.getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(endpoint.isManageHooks()).isFalse(); + assertThat(endpoint.getCredentialsId()).isNull(); + }); + } + + @Test + void given__newInstance__when__removingCloud__then__defaultRestored(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assumeThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is(nullValue())); - assertThat(instance.removeEndpoint(new BitbucketCloudEndpoint(true, "dummy")), is(true)); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketCloudEndpoint.class))); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isNull(); + assertThat(instance.removeEndpoint(new BitbucketCloudEndpoint(true, "dummy"))).isTrue(); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketCloudEndpoint.class); } @Test - public void given__instanceWithCloudAndServers__when__removingServer__then__matchingServerRemoved() { + void given__instanceWithCloudAndServers__when__removingServer__then__matchingServerRemoved(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -339,22 +357,18 @@ public void given__instanceWithCloudAndServers__when__removingServer__then__matc new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assumeThat(instance.getEndpoints(), - contains(instanceOf(BitbucketCloudEndpoint.class), instanceOf(BitbucketServerEndpoint.class), - instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - assumeThat(instance.getEndpoints().get(1).getCredentialsId(), is("second")); - assumeThat(instance.getEndpoints().get(2).getCredentialsId(), is("third")); - assertThat(instance.removeEndpoint( - new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", false, null)), is(true)); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketCloudEndpoint.class), instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("third")); - } - - @Test - public void given__instanceWithCloudAndServers__when__removingCloud__then__cloudRemoved() { + assumeTrue("first".equals(instance.getEndpoints().get(0).getCredentialsId())); + assumeTrue("second".equals(instance.getEndpoints().get(1).getCredentialsId())); + assumeTrue("third".equals(instance.getEndpoints().get(2).getCredentialsId())); + + assertThat(instance.removeEndpoint(new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", false, null))).isTrue(); + assertThat(instance.getEndpoints()).hasExactlyElementsOfTypes(BitbucketCloudEndpoint.class, BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isEqualTo("first"); + assertThat(instance.getEndpoints().get(1).getCredentialsId()).isEqualTo("third"); + } + + @Test + void given__instanceWithCloudAndServers__when__removingCloud__then__cloudRemoved(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -362,22 +376,18 @@ public void given__instanceWithCloudAndServers__when__removingCloud__then__cloud new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assumeThat(instance.getEndpoints(), - contains(instanceOf(BitbucketCloudEndpoint.class), instanceOf(BitbucketServerEndpoint.class), - instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - assumeThat(instance.getEndpoints().get(1).getCredentialsId(), is("second")); - assumeThat(instance.getEndpoints().get(2).getCredentialsId(), is("third")); - assertThat(instance.removeEndpoint( - new BitbucketCloudEndpoint(false, null)), is(true)); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketServerEndpoint.class), instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("second")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("third")); - } - - @Test - public void given__instanceWithCloudAndServers__when__removingNonExisting__then__noChange() { + assumeTrue("first".equals(instance.getEndpoints().get(0).getCredentialsId())); + assumeTrue("second".equals(instance.getEndpoints().get(1).getCredentialsId())); + assumeTrue("third".equals(instance.getEndpoints().get(2).getCredentialsId())); + + assertThat(instance.removeEndpoint(new BitbucketCloudEndpoint(false, null))).isTrue(); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isEqualTo("second"); + assertThat(instance.getEndpoints().get(1).getCredentialsId()).isEqualTo("third"); + } + + @Test + void given__instanceWithCloudAndServers__when__removingNonExisting__then__noChange(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -385,34 +395,29 @@ public void given__instanceWithCloudAndServers__when__removingNonExisting__then_ new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assumeThat(instance.getEndpoints(), - contains(instanceOf(BitbucketCloudEndpoint.class), instanceOf(BitbucketServerEndpoint.class), - instanceOf(BitbucketServerEndpoint.class))); - assumeThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - assumeThat(instance.getEndpoints().get(1).getCredentialsId(), is("second")); - assumeThat(instance.getEndpoints().get(2).getCredentialsId(), is("third")); - assertThat(instance.removeEndpoint( - new BitbucketServerEndpoint("Test", "http://bitbucket.test", true, "fourth")), is(false)); - assertThat(instance.getEndpoints(), - contains(instanceOf(BitbucketCloudEndpoint.class), instanceOf(BitbucketServerEndpoint.class), - instanceOf(BitbucketServerEndpoint.class))); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is("first")); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is("second")); - assertThat(instance.getEndpoints().get(2).getCredentialsId(), is("third")); - } - - @Test - public void given__instance__when__onlyOneEndpoint__then__endpointsNotSelectable() { + assumeTrue("first".equals(instance.getEndpoints().get(0).getCredentialsId())); + assumeTrue("second".equals(instance.getEndpoints().get(1).getCredentialsId())); + assumeTrue("third".equals(instance.getEndpoints().get(2).getCredentialsId())); + + assertThat(instance.removeEndpoint(new BitbucketServerEndpoint("Test", "http://bitbucket.test", true, "fourth"))).isFalse(); + assertThat(instance.getEndpoints()).hasExactlyElementsOfTypes(BitbucketCloudEndpoint.class, BitbucketServerEndpoint.class, BitbucketServerEndpoint.class); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isEqualTo("first"); + assertThat(instance.getEndpoints().get(1).getCredentialsId()).isEqualTo("second"); + assertThat(instance.getEndpoints().get(2).getCredentialsId()).isEqualTo("third"); + } + + @Test + void given__instance__when__onlyOneEndpoint__then__endpointsNotSelectable(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Collections.singletonList( new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "dummy") )); - assertThat(instance.isEndpointSelectable(), is(false)); + assertThat(instance.isEndpointSelectable()).isFalse(); } @Test - public void given__instance__when__multipleEndpoints__then__endpointsSelectable() { + void given__instance__when__multipleEndpoints__then__endpointsSelectable(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -420,11 +425,11 @@ public void given__instance__when__multipleEndpoints__then__endpointsSelectable( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assertThat(instance.isEndpointSelectable(), is(true)); + assertThat(instance.isEndpointSelectable()).isTrue(); } @Test - public void given__instanceWithCloudAndServers__when__findingExistingEndpoint__then__endpointFound() { + void given__instanceWithCloudAndServers__when__findingExistingEndpoint__then__endpointFound(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -432,47 +437,51 @@ public void given__instanceWithCloudAndServers__when__findingExistingEndpoint__t new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - AbstractBitbucketEndpoint ep = instance.findEndpoint(BitbucketCloudEndpoint.SERVER_URL); - assertThat(ep, notNullValue()); - assertThat(ep.getCredentialsId(), is("first")); + Optional ep = instance.findEndpoint(BitbucketCloudEndpoint.SERVER_URL); + assertThat(ep).isPresent() + .hasValueSatisfying(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("first"); + }); ep = instance.findEndpoint("https://bitbucket.example.com/"); - assertThat(ep, notNullValue()); - assertThat(ep.getCredentialsId(), is("second")); - - ep = instance.findEndpoint("https://bitbucket.example.com"); - assertThat(ep, notNullValue()); - assertThat(ep.getCredentialsId(), is("second")); + assertThat(ep).isPresent() + .hasValueSatisfying(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("second"); + }); ep = instance.findEndpoint("https://BITBUCKET.EXAMPLE.COM:443/"); - assertThat(ep, notNullValue()); - assertThat(ep.getCredentialsId(), is("second")); + assertThat(ep).isPresent() + .hasValueSatisfying(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("second"); + }); ep = instance.findEndpoint("http://example.org:8080/bitbucket/../bitbucket/"); - assertThat(ep, notNullValue()); - assertThat(ep.getCredentialsId(), is("third")); + assertThat(ep).isPresent() + .hasValueSatisfying(endpoint -> { + assertThat(endpoint.getCredentialsId()).isEqualTo("third"); + }); } @Test - public void given__instanceWithServers__when__findingNonExistingEndpoint__then__endpointNotFound() { + void given__instanceWithServers__when__findingNonExistingEndpoint__then__endpointNotFound(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "dummy"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "dummy") )); - assertThat(instance.findEndpoint(BitbucketCloudEndpoint.SERVER_URL), nullValue()); - assertThat(instance.findEndpoint("http://bitbucket.example.com/"), nullValue()); - assertThat(instance.findEndpoint("http://bitbucket.example.com:80/"), nullValue()); - assertThat(instance.findEndpoint("http://bitbucket.example.com:443"), nullValue()); - assertThat(instance.findEndpoint("https://BITBUCKET.EXAMPLE.COM:443/bitbucket/"), nullValue()); - assertThat(instance.findEndpoint("http://example.org/bitbucket/../bitbucket/"), nullValue()); - assertThat(instance.findEndpoint("bitbucket.org"), nullValue()); - assertThat(instance.findEndpoint("bitbucket.example.com"), nullValue()); + assertThat(instance.findEndpoint(BitbucketCloudEndpoint.SERVER_URL)).isEmpty(); + assertThat(instance.findEndpoint("http://bitbucket.example.com/")).isEmpty(); + assertThat(instance.findEndpoint("http://bitbucket.example.com:80/")).isEmpty(); + assertThat(instance.findEndpoint("http://bitbucket.example.com:443")).isEmpty(); + assertThat(instance.findEndpoint("https://BITBUCKET.EXAMPLE.COM:443/bitbucket/")).isEmpty(); + assertThat(instance.findEndpoint("http://example.org/bitbucket/../bitbucket/")).isEmpty(); + assertThat(instance.findEndpoint("bitbucket.org")).isEmpty(); + assertThat(instance.findEndpoint("bitbucket.example.com")).isEmpty(); } @Test - public void given__instanceWithCloudAndServers__when__findingInvalid__then__endpointNotFound() { + void given__instanceWithCloudAndServers__when__findingInvalid__then__endpointNotFound(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -480,13 +489,13 @@ public void given__instanceWithCloudAndServers__when__findingInvalid__then__endp new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assertThat(instance.findEndpoint("0schemes-start-with+digits:no leading slash"), nullValue()); - assertThat(instance.findEndpoint("http://host name with spaces:443"), nullValue()); - assertThat(instance.findEndpoint("http://invalid.port.test:65536/bitbucket/"), nullValue()); + assertThat(instance.findEndpoint("0schemes-start-with+digits:no leading slash")).isEmpty(); + assertThat(instance.findEndpoint("http://host name with spaces:443")).isEmpty(); + assertThat(instance.findEndpoint("http://invalid.port.test:65536/bitbucket/")).isEmpty(); } @Test - public void given__instanceWithCloudAndServers__when__populatingDropBox__then__endpointsListed() { + void given__instanceWithCloudAndServers__when__populatingDropBox__then__endpointsListed(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -495,18 +504,17 @@ public void given__instanceWithCloudAndServers__when__populatingDropBox__then__e new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); ListBoxModel items = instance.getEndpointItems(); - assertThat(items, hasSize(3)); - assertThat(items.get(0).name, is(Messages.BitbucketCloudEndpoint_displayName() + " (" - + BitbucketCloudEndpoint.SERVER_URL + ")")); - assertThat(items.get(0).value, is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(items.get(1).name, is("Example Inc (https://bitbucket.example.com)")); - assertThat(items.get(1).value, is("https://bitbucket.example.com")); - assertThat(items.get(2).name, is("Example Org (http://example.org:8080/bitbucket)")); - assertThat(items.get(2).value, is("http://example.org:8080/bitbucket")); + assertThat(items).hasSize(3); + assertThat(items.get(0).name).isEqualTo(Messages.BitbucketCloudEndpoint_displayName() + " (" + BitbucketCloudEndpoint.SERVER_URL + ")"); + assertThat(items.get(0).value).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(items.get(1).name).isEqualTo("Example Inc (https://bitbucket.example.com)"); + assertThat(items.get(1).value).isEqualTo("https://bitbucket.example.com"); + assertThat(items.get(2).name).isEqualTo("Example Org (http://example.org:8080/bitbucket)"); + assertThat(items.get(2).value).isEqualTo("http://example.org:8080/bitbucket"); } @Test - public void given__instanceWithCloudAndServers__when__resolvingExistingEndpoint__then__normalizedReturned() { + void given__instanceWithCloudAndServers__when__resolvingExistingEndpoint__then__normalizedReturned(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints( Arrays.asList( @@ -514,109 +522,93 @@ public void given__instanceWithCloudAndServers__when__resolvingExistingEndpoint_ new BitbucketServerEndpoint("Example Inc", "https://bitbucket.example.com/", true, "second"), new BitbucketServerEndpoint("Example Org", "http://example.org:8080/bitbucket/", true, "third") )); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl(null), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl(""), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("https://bitbucket.example.com"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/."), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(3)); - } - - @Test - public void - given__instanceWithCloudAndServers__when__resolvingNewEndpointAsSystem__then__addedAndNormalizedReturned() { + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl(null)).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("")).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("https://bitbucket.example.com")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/.")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(3); + } + + @Test + void + given__instanceWithCloudAndServers__when__resolvingNewEndpointAsSystem__then__addedAndNormalizedReturned(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints(Collections.singletonList( new BitbucketServerEndpoint("existing", "https://bitbucket.test", false, null))); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl(null), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(2)); - assertThat(instance.readResolveServerUrl(""), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(2)); - assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("https://bitbucket.example.com"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(3)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(4)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(4)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/."), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(4)); - assertThat(instance.getEndpoints().get(0).getDisplayName(), is("existing")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.test")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is(nullValue())); - assertThat(instance.getEndpoints().get(1).getDisplayName(), is(Messages.BitbucketCloudEndpoint_displayName())); - assertThat(instance.getEndpoints().get(1).getServerUrl(), is("https://bitbucket.org")); - assertThat(instance.getEndpoints().get(1).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(1).getCredentialsId(), is(nullValue())); - assertThat(instance.getEndpoints().get(2).getDisplayName(), is("example")); - assertThat(instance.getEndpoints().get(2).getServerUrl(), is("https://bitbucket.example.com")); - assertThat(instance.getEndpoints().get(2).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(2).getCredentialsId(), is(nullValue())); - assertThat(instance.getEndpoints().get(3).getDisplayName(), is("example")); - assertThat(instance.getEndpoints().get(3).getServerUrl(), is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpoints().get(3).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(3).getCredentialsId(), is(nullValue())); - } - - @Test - public void - given__instanceWithCloudAndServers__when__resolvingNewEndpointAsAnon__then__normalizedReturnedNotAdded() { + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl(null)).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(2); + assertThat(instance.readResolveServerUrl("")).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(2); + assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("https://bitbucket.example.com")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(3); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(4); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(4); + assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/.")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(4); + assertThat(instance.getEndpoints().get(0).getDisplayName()).isEqualTo("existing"); + assertThat(instance.getEndpoints().get(0).getServerUrl()).isEqualTo("https://bitbucket.test"); + assertThat(instance.getEndpoints().get(0).isManageHooks()).isFalse(); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isNull(); + assertThat(instance.getEndpoints().get(1).getDisplayName()).isEqualTo(Messages.BitbucketCloudEndpoint_displayName()); + assertThat(instance.getEndpoints().get(1).getServerUrl()).isEqualTo("https://bitbucket.org"); + assertThat(instance.getEndpoints().get(1).isManageHooks()).isFalse(); + assertThat(instance.getEndpoints().get(1).getCredentialsId()).isNull(); + assertThat(instance.getEndpoints().get(2).getDisplayName()).isEqualTo("example"); + assertThat(instance.getEndpoints().get(2).getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpoints().get(2).isManageHooks()).isFalse(); + assertThat(instance.getEndpoints().get(2).getCredentialsId()).isNull(); + assertThat(instance.getEndpoints().get(3).getDisplayName()).isEqualTo("example"); + assertThat(instance.getEndpoints().get(3).getServerUrl()).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpoints().get(3).isManageHooks()).isFalse(); + assertThat(instance.getEndpoints().get(3).getCredentialsId()).isNull(); + } + + @Test + void + given__instanceWithCloudAndServers__when__resolvingNewEndpointAsAnon__then__normalizedReturnedNotAdded(JenkinsRule j) { BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); instance.setEndpoints(Collections.singletonList( new BitbucketServerEndpoint("existing", "https://bitbucket.test", false, null))); try (ACLContext context = ACL.as(Jenkins.ANONYMOUS)) { - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl(null), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl(""), is(BitbucketCloudEndpoint.SERVER_URL)); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl("https://bitbucket.example.com"), - is("https://bitbucket.example.com")); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../"), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/."), - is("http://example.org:8080/bitbucket")); - assertThat(instance.getEndpointItems(), hasSize(1)); - assertThat(instance.getEndpoints().get(0).getDisplayName(), - is("existing")); - assertThat(instance.getEndpoints().get(0).getServerUrl(), is("https://bitbucket.test")); - assertThat(instance.getEndpoints().get(0).isManageHooks(), is(false)); - assertThat(instance.getEndpoints().get(0).getCredentialsId(), is(nullValue())); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl(null)).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("")).isEqualTo(BitbucketCloudEndpoint.SERVER_URL); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("https://bitbucket.EXAMPLE.COM:443/")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("https://bitbucket.example.com")).isEqualTo("https://bitbucket.example.com"); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("http://example.org:8080/bitbucket/foo/../")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.readResolveServerUrl("http://example.org:8080/foo/../bitbucket/.")).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(instance.getEndpointItems()).hasSize(1); + assertThat(instance.getEndpoints().get(0).getDisplayName()).isEqualTo("existing"); + assertThat(instance.getEndpoints().get(0).getServerUrl()).isEqualTo("https://bitbucket.test"); + assertThat(instance.getEndpoints().get(0).isManageHooks()).isFalse(); + assertThat(instance.getEndpoints().get(0).getCredentialsId()).isNull(); } } @Test - public void given__instanceWithConfig__when__configRoundtrip__then__configRetained() throws Exception { + void given__instanceWithConfig__when__configRoundtrip__then__configRetained(JenkinsRule j) throws Exception { BitbucketEndpointConfiguration instance = BitbucketEndpointConfiguration.get(); instance.setEndpoints( Arrays.asList( @@ -636,167 +628,167 @@ public void given__instanceWithConfig__when__configRoundtrip__then__configRetain j.configRoundtrip(); - assertThat(instance.getEndpoints(), hasSize(3)); + assertThat(instance.getEndpoints()).hasSize(3); BitbucketCloudEndpoint endpoint1 = (BitbucketCloudEndpoint) instance.getEndpoints().get(0); - assertThat(endpoint1.getDisplayName(), is(Messages.BitbucketCloudEndpoint_displayName())); - assertThat(endpoint1.getServerUrl(), is("https://bitbucket.org")); - assertThat(endpoint1.isManageHooks(), is(true)); - assertThat(endpoint1.getCredentialsId(), is("first")); + assertThat(endpoint1.getDisplayName()).isEqualTo(Messages.BitbucketCloudEndpoint_displayName()); + assertThat(endpoint1.getServerUrl()).isEqualTo("https://bitbucket.org"); + assertThat(endpoint1.isManageHooks()).isTrue(); + assertThat(endpoint1.getCredentialsId()).isEqualTo("first"); BitbucketServerEndpoint endpoint2 = (BitbucketServerEndpoint) instance.getEndpoints().get(1); - assertThat(endpoint2.getDisplayName(), is("Example Inc")); - assertThat(endpoint2.getServerUrl(), is("https://bitbucket.example.com")); - assertThat(endpoint2.isManageHooks(), is(true)); - assertThat(endpoint2.getCredentialsId(), is("second")); + assertThat(endpoint2.getDisplayName()).isEqualTo("Example Inc"); + assertThat(endpoint2.getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(endpoint2.isManageHooks()).isTrue(); + assertThat(endpoint2.getCredentialsId()).isEqualTo("second"); BitbucketServerEndpoint endpoint3 = (BitbucketServerEndpoint) instance.getEndpoints().get(2); - assertThat(endpoint3.getDisplayName(), is("Example Org")); - assertThat(endpoint3.getServerUrl(), is("http://example.org:8080/bitbucket")); - assertThat(endpoint3.isManageHooks(), is(false)); - assertThat(endpoint3.getCredentialsId(), is(nullValue())); + assertThat(endpoint3.getDisplayName()).isEqualTo("Example Org"); + assertThat(endpoint3.getServerUrl()).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(endpoint3.isManageHooks()).isFalse(); + assertThat(endpoint3.getCredentialsId()).isNull(); } @Test - public void given__serverConfig__without__webhookImplementation__then__usePlugin() throws Exception { + void given__serverConfig__without__webhookImplementation__then__usePlugin(JenkinsRule j) throws Exception { final URL configWithoutWebhookImpl = Resources.getResource(getClass(), "config-without-webhook-impl.xml"); final File configFile = new File(Jenkins.get().getRootDir(), BitbucketEndpointConfiguration.class.getName() + ".xml"); FileUtils.copyURLToFile(configWithoutWebhookImpl, configFile); final BitbucketEndpointConfiguration instance = new BitbucketEndpointConfiguration(); - assertThat(instance.getEndpoints(), contains(instanceOf(BitbucketServerEndpoint.class))); + assertThat(instance.getEndpoints()).hasOnlyElementsOfType(BitbucketServerEndpoint.class); final BitbucketServerEndpoint endpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(0); - assertThat(endpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); + assertThat(endpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); } @Test - public void should_support_configuration_as_code() throws Exception { + void should_support_configuration_as_code(JenkinsRule j) throws Exception { ConfigurationAsCode.get().configure(getClass().getResource(getClass().getSimpleName() + "/configuration-as-code.yml").toString()); BitbucketEndpointConfiguration instance = BitbucketEndpointConfiguration.get(); - assertThat(instance.getEndpoints(), hasSize(12)); + assertThat(instance.getEndpoints()).hasSize(12); BitbucketCloudEndpoint endpoint1 = (BitbucketCloudEndpoint) instance.getEndpoints().get(0); - assertThat(endpoint1.getDisplayName(), is(Messages.BitbucketCloudEndpoint_displayName())); - assertThat(endpoint1.getServerUrl(), is("https://bitbucket.org")); - assertThat(endpoint1.isManageHooks(), is(true)); - assertThat(endpoint1.getCredentialsId(), is("first")); - assertThat(endpoint1.isEnableCache(), is(true)); - assertThat(endpoint1.getTeamCacheDuration(), is(1)); - assertThat(endpoint1.getRepositoriesCacheDuration(), is(2)); + assertThat(endpoint1.getDisplayName()).isEqualTo(Messages.BitbucketCloudEndpoint_displayName()); + assertThat(endpoint1.getServerUrl()).isEqualTo("https://bitbucket.org"); + assertThat(endpoint1.isManageHooks()).isTrue(); + assertThat(endpoint1.getCredentialsId()).isEqualTo("first"); + assertThat(endpoint1.isEnableCache()).isTrue(); + assertThat(endpoint1.getTeamCacheDuration()).isEqualTo(1); + assertThat(endpoint1.getRepositoriesCacheDuration()).isEqualTo(2); BitbucketServerEndpoint serverEndpoint; serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(1); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("https://bitbucket.example.com")); - assertThat(serverEndpoint.isManageHooks(), is(true)); - assertThat(serverEndpoint.getCredentialsId(), is("second")); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("https://bitbucket.example.com"); + assertThat(serverEndpoint.isManageHooks()).isTrue(); + assertThat(serverEndpoint.getCredentialsId()).isEqualTo("second"); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(2); - assertThat(serverEndpoint.getDisplayName(), is("Example Org")); - assertThat(serverEndpoint.getServerUrl(), is("http://example.org:8080/bitbucket")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(true)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Org"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://example.org:8080/bitbucket"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isTrue(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(3); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8083")); - assertThat(serverEndpoint.isManageHooks(), is(true)); - assertThat(serverEndpoint.getCredentialsId(), is("third")); - assertThat(serverEndpoint.isCallCanMerge(), is(true)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.NATIVE)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8083"); + assertThat(serverEndpoint.isManageHooks()).isTrue(); + assertThat(serverEndpoint.getCredentialsId()).isEqualTo("third"); + assertThat(serverEndpoint.isCallCanMerge()).isTrue(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.NATIVE); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(4); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8084")); - assertThat(serverEndpoint.isManageHooks(), is(true)); - assertThat(serverEndpoint.getCredentialsId(), is("fourth")); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(false)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8084"); + assertThat(serverEndpoint.isManageHooks()).isTrue(); + assertThat(serverEndpoint.getCredentialsId()).isEqualTo("fourth"); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isFalse(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(5); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8085")); - assertThat(serverEndpoint.isManageHooks(), is(true)); - assertThat(serverEndpoint.getCredentialsId(), is("fifth")); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8085"); + assertThat(serverEndpoint.isManageHooks()).isTrue(); + assertThat(serverEndpoint.getCredentialsId()).isEqualTo("fifth"); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(6); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8086")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(false)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8086"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isFalse(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(7); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8087")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(false)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_7)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8087"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isFalse(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_7); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(8); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8088")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_6_5)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8088"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_6_5); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(9); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8089")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_6)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8089"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_6); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(10); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8090")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_5_10)); + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8090"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_5_10); serverEndpoint = (BitbucketServerEndpoint) instance.getEndpoints().get(11); - assertThat(serverEndpoint.getDisplayName(), is("Example Inc")); - assertThat(serverEndpoint.getServerUrl(), is("http://bitbucket.example.com:8091")); - assertThat(serverEndpoint.isManageHooks(), is(false)); - assertThat(serverEndpoint.getCredentialsId(), is(nullValue())); - assertThat(serverEndpoint.isCallCanMerge(), is(false)); - assertThat(serverEndpoint.isCallChanges(), is(true)); - assertThat(serverEndpoint.getWebhookImplementation(), is(BitbucketServerWebhookImplementation.PLUGIN)); - assertThat(serverEndpoint.getServerVersion(), is(BitbucketServerVersion.VERSION_5)); - + assertThat(serverEndpoint.getDisplayName()).isEqualTo("Example Inc"); + assertThat(serverEndpoint.getServerUrl()).isEqualTo("http://bitbucket.example.com:8091"); + assertThat(serverEndpoint.isManageHooks()).isFalse(); + assertThat(serverEndpoint.getCredentialsId()).isNull(); + assertThat(serverEndpoint.isCallCanMerge()).isFalse(); + assertThat(serverEndpoint.isCallChanges()).isTrue(); + assertThat(serverEndpoint.getWebhookImplementation()).isEqualTo(BitbucketServerWebhookImplementation.PLUGIN); + assertThat(serverEndpoint.getServerVersion()).isEqualTo(BitbucketServerVersion.VERSION_5); } + }