From 9a03243ec1d83163ceb7f748b57389e029c839d6 Mon Sep 17 00:00:00 2001 From: Joseph Petersen Date: Sat, 18 Dec 2021 13:35:19 +0100 Subject: [PATCH 1/3] update parent pom, use plugin bom, remove powermock powermock tests written using mockito's mockStatic added configuration-as-code test-harness update jenkins.version --- pom.xml | 38 +- .../DefaultApacheHttpNotifier.java | 2 +- .../plugins/stashNotifier/StashNotifier.java | 10 +- .../DefaultApacheHttpNotifierTest.java | 72 ++-- .../stashNotifier/DescriptorImplTest.java | 40 +- .../stashNotifier/StashNotifierTest.java | 364 ++++++++++-------- 6 files changed, 283 insertions(+), 243 deletions(-) diff --git a/pom.xml b/pom.xml index eb10a05..a6660e4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.jenkins-ci.plugins plugin - 3.57 + 4.31 hpi @@ -11,7 +11,7 @@ 1.25 -SNAPSHOT - 2.60.3 + 2.303.1 8 1.9 @@ -77,33 +77,40 @@ + + + + io.jenkins.tools.bom + bom-2.303.x + 1055.v9637a690f734 + import + pom + + + + org.jenkins-ci.plugins display-url-api - 2.0 org.jenkins-ci.plugins apache-httpcomponents-client-4-api - 4.5.5-3.0 org.jenkins-ci.plugins git - 3.0.0 jar org.jenkins-ci.plugins credentials - 2.1.4 jar org.jenkins-ci.plugins plain-credentials - 1.1 jar @@ -112,31 +119,28 @@ test - org.powermock - powermock-module-junit4 - test - - - org.powermock - powermock-api-mockito2 + org.mockito + mockito-inline test org.hamcrest hamcrest-core - 2.2 test org.jenkins-ci.plugins token-macro - 2.0 jar io.jenkins configuration-as-code - 1.8 + test + + + io.jenkins.configuration-as-code + test-harness test diff --git a/src/main/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifier.java b/src/main/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifier.java index a4ada68..f97b4b6 100644 --- a/src/main/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifier.java +++ b/src/main/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifier.java @@ -166,7 +166,7 @@ SSLContext buildSslContext(boolean ignoreUnverifiedSSL, Credentials credentials) } void configureProxy(HttpClientBuilder builder, URL url) { - Jenkins jenkins = Jenkins.getInstance(); + Jenkins jenkins = Jenkins.get(); ProxyConfiguration proxyConfig = jenkins.proxy; if (proxyConfig == null) { return; diff --git a/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java b/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java index 1b1addb..d312c86 100644 --- a/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java +++ b/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java @@ -295,7 +295,7 @@ void setHttpNotifierSelector(HttpNotifierSelector httpNotifierSelector) { HttpNotifierSelector getHttpNotifierSelector() { if (httpNotifierSelector == null) { - Jenkins jenkins = Jenkins.getInstance(); + Jenkins jenkins = Jenkins.get(); Injector injector = jenkins.getInjector(); injector.injectMembers(this); } @@ -362,7 +362,7 @@ private boolean perform(Run run, * @return Root URL contained in the global config */ private String getRootUrl() { - Jenkins instance = Jenkins.getInstance(); + Jenkins instance = Jenkins.get(); return (instance.getRootUrl() != null) ? instance.getRootUrl() : globalConfig.getUrl(); } @@ -554,7 +554,7 @@ private SSLContext buildSslContext(boolean ignoreUnverifiedSSL, Credentials cred */ @Deprecated private void configureProxy(HttpClientBuilder builder, URL url) { - Jenkins jenkins = Jenkins.getInstance(); + Jenkins jenkins = Jenkins.get(); ProxyConfiguration proxyConfig = jenkins.proxy; if (proxyConfig == null) { return; @@ -621,7 +621,7 @@ protected DescriptorImpl(boolean load) { } public ListBoxModel doFillCredentialsIdItems(@AncestorInPath Item project) { - Jenkins jenkins = Jenkins.getInstance(); + Jenkins jenkins = Jenkins.get(); if (project != null && project.hasPermission(Item.CONFIGURE)) { return new StandardListBoxModel() @@ -854,7 +854,7 @@ private T getCredentials(final Class clazz, final Ite } if (StringUtils.isNotBlank(credentialsId) && clazz != null && project != null) { credentials = CredentialsMatchers.firstOrNull( - CredentialsProvider.lookupCredentials(clazz, Jenkins.getInstance(), ACL.SYSTEM, new ArrayList<>()), + CredentialsProvider.lookupCredentials(clazz, Jenkins.get(), ACL.SYSTEM, new ArrayList<>()), CredentialsMatchers.withId(credentialsId)); } } diff --git a/src/test/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifierTest.java b/src/test/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifierTest.java index 9dbbae9..eaa83b6 100644 --- a/src/test/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifierTest.java +++ b/src/test/java/org/jenkinsci/plugins/stashNotifier/DefaultApacheHttpNotifierTest.java @@ -1,6 +1,6 @@ package org.jenkinsci.plugins.stashNotifier; -import com.cloudbees.plugins.credentials.CredentialsMatchers; +import com.cloudbees.plugins.credentials.CredentialsProvider; import hudson.EnvVars; import hudson.FilePath; import hudson.model.AbstractBuild; @@ -23,13 +23,9 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.jenkinsci.plugins.tokenmacro.TokenMacro; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; import java.io.PrintStream; @@ -37,51 +33,54 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.mockito.MockedStatic; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; -@RunWith(PowerMockRunner.class) -@PrepareForTest({Secret.class, Jenkins.class, HttpClientBuilder.class, TokenMacro.class, CredentialsMatchers.class, com.cloudbees.plugins.credentials.CredentialsProvider.class, AbstractProject.class}) -@PowerMockIgnore("javax.net.ssl.*") public class DefaultApacheHttpNotifierTest { final static String sha1 = "1234567890123456789012345678901234567890"; - private CloseableHttpClient client; + private static CloseableHttpClient client; + private static MockedStatic mockedJenkins; + private static MockedStatic mockedCredentialsProvider; + private static MockedStatic mockedSecret; + private static MockedStatic mockedHttpClientBuilder; + private static MockedStatic mockedTokenMacro; private final HttpNotifier httpNotifier = new DefaultApacheHttpNotifier(); - BuildListener buildListener; - AbstractBuild build; - Run run; - FilePath workspace; + private static BuildListener buildListener; - @Before - public void setUp() throws Exception { - PowerMockito.mockStatic(Secret.class); - PowerMockito.mockStatic(Jenkins.class); - PowerMockito.mockStatic(HttpClientBuilder.class); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.mockStatic(com.cloudbees.plugins.credentials.CredentialsProvider.class); + @BeforeClass + public static void setUp() throws Exception { + mockedSecret = mockStatic(Secret.class); + mockedJenkins = mockStatic(Jenkins.class); + mockedHttpClientBuilder = mockStatic(HttpClientBuilder.class); + mockedTokenMacro = mockStatic(TokenMacro.class); + mockedCredentialsProvider = mockStatic(com.cloudbees.plugins.credentials.CredentialsProvider.class); buildListener = mock(BuildListener.class); Jenkins jenkins = mock(Jenkins.class); - build = mock(AbstractBuild.class); - run = mock(Run.class); - AbstractProject project = PowerMockito.mock(AbstractProject.class); + AbstractBuild build = mock(AbstractBuild.class); + Run run = mock(Run.class); + + AbstractProject project = mock(AbstractProject.class); File file = mock(File.class); when(file.getPath()).thenReturn("/tmp/fake/path"); FilePath filePath = new FilePath(file); - PowerMockito.when(project.getSomeWorkspace()).thenReturn(filePath); - workspace = project.getSomeWorkspace(); + when(project.getSomeWorkspace()).thenReturn(filePath); + FilePath workspace = project.getSomeWorkspace(); EnvVars environment = mock(EnvVars.class); PrintStream logger = System.out; Secret secret = mock(Secret.class); - HttpClientBuilder httpClientBuilder = PowerMockito.mock(HttpClientBuilder.class); + HttpClientBuilder httpClientBuilder = mock(HttpClientBuilder.class); client = mock(CloseableHttpClient.class); CloseableHttpResponse resp = mock(CloseableHttpResponse.class); StatusLine statusLine = mock(StatusLine.class); @@ -90,13 +89,13 @@ public void setUp() throws Exception { Build lastBuild = mock(Build.class); List actions = Collections.singletonList(action); - when(Jenkins.getInstance()).thenReturn(jenkins); + when(Jenkins.get()).thenReturn(jenkins); when(jenkins.getRootUrl()).thenReturn("http://localhost/"); when(build.getEnvironment(buildListener)).thenReturn(environment); when(action.getLastBuiltRevision()).thenReturn(revision); when(revision.getSha1String()).thenReturn(sha1); - when(build.getProject()).thenReturn(project); - when(run.getParent()).thenReturn(project); + doReturn(project).when(build).getProject(); + doReturn(project).when(run).getParent(); when(build.getFullDisplayName()).thenReturn("foo"); when(build.getUrl()).thenReturn("foo"); when(build.getActions(BuildData.class)).thenReturn(actions); @@ -114,7 +113,7 @@ public void setUp() throws Exception { when(lastBuild.getMarked()).thenReturn(revision); when(TokenMacro.expandAll(build, buildListener, "test-project")).thenReturn("prepend-key"); - when(com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( + when(CredentialsProvider.lookupCredentials( any(), any(ItemGroup.class), any(Authentication.class), @@ -122,6 +121,15 @@ public void setUp() throws Exception { )).thenReturn(new ArrayList<>()); } + @AfterClass + public static void close() { + mockedJenkins.close(); + mockedCredentialsProvider.close(); + mockedSecret.close(); + mockedHttpClientBuilder.close(); + mockedTokenMacro.close(); + } + private NotificationResult notifyStash(int statusCode) throws Exception { PrintStream logger = mock(PrintStream.class); URI uri = BuildStatusUriFactory.create("http://localhost", "df02f57eea1cda72fa2412102f061dd7f6188e98"); diff --git a/src/test/java/org/jenkinsci/plugins/stashNotifier/DescriptorImplTest.java b/src/test/java/org/jenkinsci/plugins/stashNotifier/DescriptorImplTest.java index fa4f694..fcba3ee 100644 --- a/src/test/java/org/jenkinsci/plugins/stashNotifier/DescriptorImplTest.java +++ b/src/test/java/org/jenkinsci/plugins/stashNotifier/DescriptorImplTest.java @@ -8,17 +8,15 @@ import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.acegisecurity.Authentication; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; import org.kohsuke.stapler.*; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; +import org.mockito.MockedStatic; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -28,6 +26,7 @@ import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -35,24 +34,25 @@ * Created by Vlad Medvedev on 27.01.2016. * vladislav.medvedev@devfactory.com */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({StashNotifier.DescriptorImpl.class, CredentialsProvider.class, Jenkins.class, TokenList.class}) public class DescriptorImplTest { /** * Class under test. */ - private StashNotifier.DescriptorImpl desc; + private static StashNotifier.DescriptorImpl desc; - private JSONObject json; - private Jenkins jenkins; + private static JSONObject json; + private static Jenkins jenkins; + private static MockedStatic mockedJenkins; + private static MockedStatic mockedCredentialsProvider; - @Before - public void setUp() { - jenkins = PowerMockito.mock(Jenkins.class); + @BeforeClass + public static void setUp() { + mockedJenkins = mockStatic(Jenkins.class); + mockedCredentialsProvider = mockStatic(CredentialsProvider.class); - PowerMockito.mockStatic(Jenkins.class); - when(Jenkins.getInstance()).thenReturn(jenkins); + jenkins = mock(Jenkins.class); + when(Jenkins.get()).thenReturn(jenkins); json = new JSONObject(); json.put("considerUnstableAsSuccess", "true"); @@ -67,6 +67,12 @@ public void setUp() { desc = spy(new StashNotifier.DescriptorImpl(false)); } + @AfterClass + public static void close() { + mockedJenkins.close(); + mockedCredentialsProvider.close(); + } + @Test public void testConfigure() throws Exception { //given @@ -128,8 +134,7 @@ public void test_doFillCredentialsIdItems_has_permission() { //given Item project = mock(Item.class); when(project.hasPermission(Item.CONFIGURE)).thenReturn(true); - PowerMockito.mockStatic(CredentialsProvider.class); - PowerMockito.when(CredentialsProvider.lookupCredentials( + when(CredentialsProvider.lookupCredentials( any(), any(Item.class), any(Authentication.class), @@ -146,6 +151,7 @@ public void test_doFillCredentialsIdItems_has_permission() { @Test public void test_doCheckStashServerBaseUrl_empty() throws Exception { //when + desc.setStashRootUrl(""); FormValidation listBoxModel = desc.doCheckStashServerBaseUrl(""); //then diff --git a/src/test/java/org/jenkinsci/plugins/stashNotifier/StashNotifierTest.java b/src/test/java/org/jenkinsci/plugins/stashNotifier/StashNotifierTest.java index d99aaeb..3e91000 100644 --- a/src/test/java/org/jenkinsci/plugins/stashNotifier/StashNotifierTest.java +++ b/src/test/java/org/jenkinsci/plugins/stashNotifier/StashNotifierTest.java @@ -1,6 +1,5 @@ package org.jenkinsci.plugins.stashNotifier; -import com.cloudbees.plugins.credentials.CredentialsMatchers; import hudson.EnvVars; import hudson.FilePath; import hudson.Launcher; @@ -28,16 +27,13 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider; import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException; import org.jenkinsci.plugins.tokenmacro.TokenMacro; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; import java.io.IOException; @@ -46,6 +42,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.mockito.MockedStatic; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -60,28 +57,31 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(PowerMockRunner.class) -@PrepareForTest({Secret.class, Jenkins.class, HttpClientBuilder.class, TokenMacro.class, CredentialsMatchers.class, com.cloudbees.plugins.credentials.CredentialsProvider.class, AbstractProject.class}) -@PowerMockIgnore("javax.net.ssl.*") public class StashNotifierTest { final static String sha1 = "1234567890123456789012345678901234567890"; - private HttpClientBuilder httpClientBuilder; - private CloseableHttpClient client; - private Jenkins jenkins; - private final HttpNotifierSelector httpNotifierSelector = mock(HttpNotifierSelector.class); - private final HttpNotifier httpNotifier = mock(HttpNotifier.class); - - private StashNotifier buildStashNotifier(String stashBaseUrl) { + private static HttpClientBuilder httpClientBuilder; + private static CloseableHttpClient client; + private static Jenkins jenkins; + private static final HttpNotifierSelector httpNotifierSelector = mock(HttpNotifierSelector.class); + private static final HttpNotifier httpNotifier = mock(HttpNotifier.class); + + private static MockedStatic mockedJenkins; + private static MockedStatic mockedCredentialsProvider; + private static MockedStatic mockedSecret; + private static MockedStatic mockedHttpClientBuilder; + + private static StashNotifier buildStashNotifier(String stashBaseUrl) { return buildStashNotifier(stashBaseUrl, false, false); } - private StashNotifier buildStashNotifier(String stashBaseUrl, + private static StashNotifier buildStashNotifier(String stashBaseUrl, boolean disableInprogressNotification, boolean considerUnstableAsSuccess) { StashNotifier notifier = new StashNotifier( @@ -102,34 +102,34 @@ private StashNotifier buildStashNotifier(String stashBaseUrl, return notifier; } - StashNotifier sn; - BuildListener buildListener; - AbstractBuild build; - Run run; - FilePath workspace; + private static StashNotifier sn; + private static BuildListener buildListener; + private static AbstractBuild build; + private static Run run; + private static FilePath workspace; - @Before - public void setUp() throws Exception { - PowerMockito.mockStatic(Secret.class); - PowerMockito.mockStatic(Jenkins.class); - PowerMockito.mockStatic(HttpClientBuilder.class); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.mockStatic(com.cloudbees.plugins.credentials.CredentialsProvider.class); + @BeforeClass + public static void setUp() throws Exception { + mockedJenkins = mockStatic(Jenkins.class); + mockedSecret = mockStatic(Secret.class); + mockedHttpClientBuilder = mockStatic(HttpClientBuilder.class); + mockedCredentialsProvider = mockStatic( + com.cloudbees.plugins.credentials.CredentialsProvider.class); buildListener = mock(BuildListener.class); jenkins = mock(Jenkins.class); build = mock(AbstractBuild.class); run = mock(Run.class); - AbstractProject project = PowerMockito.mock(AbstractProject.class); + AbstractProject project = mock(FreeStyleProject.class); File file = mock(File.class); when(file.getPath()).thenReturn("/tmp/fake/path"); FilePath filePath = new FilePath(file); - PowerMockito.when(project.getSomeWorkspace()).thenReturn(filePath); + when(project.getSomeWorkspace()).thenReturn(filePath); workspace = project.getSomeWorkspace(); EnvVars environment = mock(EnvVars.class); PrintStream logger = System.out; Secret secret = mock(Secret.class); - httpClientBuilder = PowerMockito.mock(HttpClientBuilder.class); + httpClientBuilder = mock(HttpClientBuilder.class); client = mock(CloseableHttpClient.class); CloseableHttpResponse resp = mock(CloseableHttpResponse.class); HttpUriRequest req = mock(HttpUriRequest.class); @@ -139,13 +139,14 @@ public void setUp() throws Exception { Build lastBuild = mock(Build.class); List actions = Collections.singletonList(action); - when(Jenkins.getInstance()).thenReturn(jenkins); + when(Jenkins.get()).thenReturn(jenkins); when(jenkins.getRootUrl()).thenReturn("http://localhost/"); when(build.getEnvironment(buildListener)).thenReturn(environment); when(action.getLastBuiltRevision()).thenReturn(revision); when(revision.getSha1String()).thenReturn(sha1); - when(build.getProject()).thenReturn(project); - when(run.getParent()).thenReturn(project); + doReturn(project).when(build).getProject(); + doReturn(project).when(build).getParent(); + doReturn(project).when(run).getParent(); when(build.getFullDisplayName()).thenReturn("foo"); when(build.getUrl()).thenReturn("foo"); when(build.getActions(BuildData.class)).thenReturn(actions); @@ -162,7 +163,6 @@ public void setUp() throws Exception { action.lastBuild = lastBuild; when(lastBuild.getMarked()).thenReturn(revision); - when(TokenMacro.expandAll(build, buildListener, "test-project")).thenReturn("prepend-key"); when(com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( any(), any(ItemGroup.class), @@ -174,6 +174,14 @@ public void setUp() throws Exception { sn = buildStashNotifier("http://localhost"); } + @AfterClass + public static void close() { + mockedJenkins.close(); + mockedCredentialsProvider.close(); + mockedSecret.close(); + mockedHttpClientBuilder.close(); + } + @Test public void test_prebuild_normal() { assertTrue(sn.prebuild(build, buildListener)); @@ -479,56 +487,58 @@ public void test_perform_simple_build_step_empty_hash() throws Exception { @Test public void lookupCommitSha1s() throws Exception { //given - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(build, buildListener, sha1)).thenReturn(sha1); - sn = new StashNotifier( - "https://localhost", - "scot", - true, - sha1, - null, - null, - true, - null, - false, - false, - false, - mock(JenkinsLocationConfiguration.class)); - - //when - Collection hashes = sn.lookupCommitSha1s(build, null, buildListener); - - //then - assertThat(hashes.size(), is(1)); - assertThat(hashes.iterator().next(), is(sha1)); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any())).thenReturn(sha1); + sn = new StashNotifier( + "https://localhost", + "scot", + true, + sha1, + null, + null, + true, + null, + false, + false, + false, + mock(JenkinsLocationConfiguration.class)); + + //when + Collection hashes = sn.lookupCommitSha1s(build, null, buildListener); + + //then + assertThat(hashes.size(), is(1)); + assertThat(hashes.iterator().next(), is(sha1)); + } } private void lookupCommitSha1s_Exception(Exception e) throws InterruptedException, MacroEvaluationException, IOException { //given PrintStream logger = mock(PrintStream.class); when(buildListener.getLogger()).thenReturn(logger); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(build, buildListener, sha1)).thenThrow(e); - sn = new StashNotifier( - "http://localhost", - "scot", - true, - sha1, - null, - null, - true, - null, - false, - false, - false, - mock(JenkinsLocationConfiguration.class)); - - //when - Collection hashes = sn.lookupCommitSha1s(build, null, buildListener); - - //then - assertThat(hashes.isEmpty(), is(true)); - verify(logger).println("Unable to expand commit SHA value"); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any())).thenThrow(e); + sn = new StashNotifier( + "http://localhost", + "scot", + true, + sha1, + null, + null, + true, + null, + false, + false, + false, + mock(JenkinsLocationConfiguration.class)); + + //when + Collection hashes = sn.lookupCommitSha1s(build, null, buildListener); + + //then + assertThat(hashes.isEmpty(), is(true)); + verify(logger).println("Unable to expand commit SHA value"); + } } @Test @@ -679,28 +689,29 @@ public void test_getBuildKey() throws Exception { String key = "someKey"; PrintStream logger = mock(PrintStream.class); when(buildListener.getLogger()).thenReturn(logger); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(build, buildListener, key)).thenReturn(key); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any())).thenReturn(key); - sn = new StashNotifier( - "", - "scot", - true, - null, - null, - "build-name", - true, - key, - true, - false, - false, - mock(JenkinsLocationConfiguration.class)); + sn = new StashNotifier( + "", + "scot", + true, + null, + null, + "build-name", + true, + key, + true, + false, + false, + mock(JenkinsLocationConfiguration.class)); - //when - String buildKey = sn.getBuildKey(build, buildListener); + //when + String buildKey = sn.getBuildKey(build, buildListener); - //then - assertThat(buildKey, is(key)); + //then + assertThat(buildKey, is(key)); + } } @Test @@ -742,28 +753,30 @@ public void test_getRunKey() throws Exception { when(buildListener.getLogger()).thenReturn(logger); final File tempDir = File.createTempFile("stashNotifier", null); when(run.getRootDir()).thenReturn(tempDir); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(run, new FilePath(tempDir), buildListener, key)).thenReturn(key); - - sn = new StashNotifier( - "", - "scot", - true, - null, - null, - null, - true, - key, - true, - false, - false, - mock(JenkinsLocationConfiguration.class)); - - //when - String buildKey = sn.getBuildKey(run, buildListener); - - //then - assertThat(buildKey, is(key)); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any(), any())) + .thenReturn(key); + + sn = new StashNotifier( + "", + "scot", + true, + null, + null, + null, + true, + key, + true, + false, + false, + mock(JenkinsLocationConfiguration.class)); + + //when + String buildKey = sn.getBuildKey(run, buildListener); + + //then + assertThat(buildKey, is(key)); + } } private void getBuildKey_Exception(Exception e) throws InterruptedException, MacroEvaluationException, IOException { @@ -771,29 +784,30 @@ private void getBuildKey_Exception(Exception e) throws InterruptedException, Mac String key = "someKey"; PrintStream logger = mock(PrintStream.class); when(buildListener.getLogger()).thenReturn(logger); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(build, buildListener, key)).thenThrow(e); - - sn = new StashNotifier( - "", - "scot", - true, - null, - null, - null, - true, - key, - true, - false, - false, - mock(JenkinsLocationConfiguration.class)); - - //when - String buildKey = sn.getBuildKey(build, buildListener); - - //then - assertThat(buildKey, is("null-0-http:\\/\\/localhost\\/")); - verify(logger).println("Cannot expand build key from parameter. Processing with default build key"); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any())).thenThrow(e); + + sn = new StashNotifier( + "", + "scot", + true, + null, + null, + null, + true, + key, + true, + false, + false, + mock(JenkinsLocationConfiguration.class)); + + //when + String buildKey = sn.getBuildKey(build, buildListener); + + //then + assertThat(buildKey, is("null-0-http:\\/\\/localhost\\/")); + verify(logger).println("Cannot expand build key from parameter. Processing with default build key"); + } } private void getRunKey_Exception(Exception e) throws InterruptedException, MacroEvaluationException, IOException { @@ -803,29 +817,32 @@ private void getRunKey_Exception(Exception e) throws InterruptedException, Macro when(buildListener.getLogger()).thenReturn(logger); final File tempDir = File.createTempFile("stashNotifier", null); when(run.getRootDir()).thenReturn(tempDir); - PowerMockito.mockStatic(TokenMacro.class); - PowerMockito.when(TokenMacro.expandAll(run, new FilePath(tempDir), buildListener, key)).thenThrow(e); - - sn = new StashNotifier( - "", - "scot", - true, - null, - null, - null, - true, - key, - true, - false, - false, - mock(JenkinsLocationConfiguration.class)); - - //when - String buildKey = sn.getBuildKey(run, buildListener); - - //then - assertThat(buildKey, is("null-0-http:\\/\\/localhost\\/")); - verify(logger).println("Cannot expand build key from parameter. Processing with default build key"); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class)) { + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any(), any())) + .thenThrow(e); + + sn = new StashNotifier( + "", + "scot", + true, + null, + null, + null, + true, + key, + true, + false, + false, + mock(JenkinsLocationConfiguration.class)); + + //when + String buildKey = sn.getBuildKey(run, buildListener); + + //then + assertThat(buildKey, is("null-0-http:\\/\\/localhost\\/")); + verify(logger).println( + "Cannot expand build key from parameter. Processing with default build key"); + } } @Test @@ -861,6 +878,8 @@ public void test_getRunKey_MacroEvaluationException() throws Exception { private NotificationResult notifyStash(int statusCode) throws Exception { sn = spy(this.sn); PrintStream logger = mock(PrintStream.class); + DisplayURLProvider displayURLProvider = mock(DisplayURLProvider.class); + when(displayURLProvider.getRunURL(run)).thenReturn("http://localhost"); when(buildListener.getLogger()).thenReturn(logger); doReturn("someKey1").when(sn).getBuildKey(eq(build), eq(buildListener)); HttpPost httpPost = mock(HttpPost.class); @@ -870,9 +889,12 @@ private NotificationResult notifyStash(int statusCode) throws Exception { when(resp.getStatusLine()).thenReturn(sl); when(resp.getEntity()).thenReturn(new StringEntity("")); when(client.execute(eq(httpPost))).thenReturn(resp); - when(TokenMacro.expandAll(build, buildListener, "http://localhost")).thenReturn("http://localhost"); - doReturn(client).when(sn).getHttpClient(any(PrintStream.class), any(AbstractBuild.class), anyString()); - return sn.notifyStash(logger, build, sha1, buildListener, StashBuildState.FAILED); + try (MockedStatic tokenMacroMock = mockStatic(TokenMacro.class); MockedStatic displayURLProviderMock = mockStatic(DisplayURLProvider.class)) { + displayURLProviderMock.when(DisplayURLProvider::get).thenReturn(displayURLProvider); + tokenMacroMock.when(() -> TokenMacro.expandAll(any(), any(), any())).thenReturn("http://localhost"); + doReturn(client).when(sn).getHttpClient(any(PrintStream.class), any(AbstractBuild.class), anyString()); + return sn.notifyStash(logger, build, sha1, buildListener, StashBuildState.FAILED); + } } @Test From 2b81645bbc928788aa8bf7ea46cd0195bd3ad4ef Mon Sep 17 00:00:00 2001 From: Joseph Petersen Date: Sat, 18 Dec 2021 11:25:06 +0100 Subject: [PATCH 2/3] update configuration as code test --- .../stashNotifier/ConfigAsCodeTest.java | 47 +++++++------------ .../configuration-as-code-expected.yml | 7 +++ .../configuration-as-code.yml | 0 3 files changed, 25 insertions(+), 29 deletions(-) create mode 100644 src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code-expected.yml rename src/test/resources/org/jenkinsci/plugins/stashNotifier/{ConfigAsCodeTest => }/configuration-as-code.yml (100%) diff --git a/src/test/java/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest.java b/src/test/java/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest.java index 581f58c..909243f 100644 --- a/src/test/java/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest.java +++ b/src/test/java/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest.java @@ -1,27 +1,26 @@ package org.jenkinsci.plugins.stashNotifier; -import io.jenkins.plugins.casc.ConfigurationAsCode; -import org.apache.commons.io.IOUtils; +import io.jenkins.plugins.casc.ConfigurationContext; +import io.jenkins.plugins.casc.ConfiguratorRegistry; +import io.jenkins.plugins.casc.misc.ConfiguredWithCode; +import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule; +import io.jenkins.plugins.casc.model.CNode; import org.junit.Rule; import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; - -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.net.URL; +import static io.jenkins.plugins.casc.misc.Util.getUnclassifiedRoot; +import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile; +import static io.jenkins.plugins.casc.misc.Util.toYamlString; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.core.Is.is; public class ConfigAsCodeTest { - @Rule - public JenkinsRule rule = new JenkinsRule(); + @Rule public JenkinsConfiguredWithCodeRule rule = new JenkinsConfiguredWithCodeRule(); @Test + @ConfiguredWithCode("configuration-as-code.yml") public void should_support_jcasc_from_yaml() throws Exception { - URL configFileUrl = ConfigAsCodeTest.class.getResource(getClass().getSimpleName() + "/configuration-as-code.yml"); - ConfigurationAsCode.get().configure(configFileUrl.toString()); StashNotifier.DescriptorImpl stashNotifierConfig = rule.jenkins.getDescriptorByType(StashNotifier.DescriptorImpl.class); assertThat(stashNotifierConfig.isConsiderUnstableAsSuccess(), equalTo(true)); @@ -34,26 +33,16 @@ public void should_support_jcasc_from_yaml() throws Exception { } @Test + @ConfiguredWithCode("configuration-as-code.yml") public void should_support_jcasc_to_yaml() throws Exception { - StashNotifier.DescriptorImpl stashNotifierConfig = rule.jenkins.getDescriptorByType(StashNotifier.DescriptorImpl.class); - - stashNotifierConfig.setConsiderUnstableAsSuccess(true); - stashNotifierConfig.setCredentialsId("bitbucket-credentials"); - stashNotifierConfig.setDisableInprogressNotification(true); - stashNotifierConfig.setIgnoreUnverifiedSsl(true); - stashNotifierConfig.setIncludeBuildNumberInKey(true); - stashNotifierConfig.setPrependParentProjectKey(true); - stashNotifierConfig.setStashRootUrl("https://my.company.intranet/bitbucket"); + ConfiguratorRegistry registry = ConfiguratorRegistry.get(); + ConfigurationContext context = new ConfigurationContext(registry); + CNode yourAttribute = getUnclassifiedRoot(context).get("notifyBitbucket"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ConfigurationAsCode.get().export(outputStream); - String exportedYaml = outputStream.toString("UTF-8"); + String exported = toYamlString(yourAttribute); - InputStream yamlStream = getClass().getResourceAsStream(getClass().getSimpleName() + "/configuration-as-code.yml"); - String expectedYaml = IOUtils.toString(yamlStream, "UTF-8") - .replaceAll("\r\n?", "\n") - .replace("unclassified:\n", ""); + String expected = toStringFromYamlFile(this, "configuration-as-code-expected.yml"); - assertThat(exportedYaml, containsString(expectedYaml)); + assertThat(exported, is(expected)); } } diff --git a/src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code-expected.yml b/src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code-expected.yml new file mode 100644 index 0000000..82123f5 --- /dev/null +++ b/src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code-expected.yml @@ -0,0 +1,7 @@ +considerUnstableAsSuccess: true +credentialsId: "bitbucket-credentials" +disableInprogressNotification: true +ignoreUnverifiedSsl: true +includeBuildNumberInKey: true +prependParentProjectKey: true +stashRootUrl: "https://my.company.intranet/bitbucket" diff --git a/src/test/resources/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest/configuration-as-code.yml b/src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code.yml similarity index 100% rename from src/test/resources/org/jenkinsci/plugins/stashNotifier/ConfigAsCodeTest/configuration-as-code.yml rename to src/test/resources/org/jenkinsci/plugins/stashNotifier/configuration-as-code.yml From 1b0db32ce54a256a99fbe702e30d0c90554d9a67 Mon Sep 17 00:00:00 2001 From: Joseph Petersen Date: Sat, 18 Dec 2021 11:25:43 +0100 Subject: [PATCH 3/3] fix spotbugs issues --- .../plugins/stashNotifier/StashNotifier.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java b/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java index d312c86..a0db096 100644 --- a/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java +++ b/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java @@ -297,7 +297,9 @@ HttpNotifierSelector getHttpNotifierSelector() { if (httpNotifierSelector == null) { Jenkins jenkins = Jenkins.get(); Injector injector = jenkins.getInjector(); - injector.injectMembers(this); + if (injector != null) { + injector.injectMembers(this); + } } return httpNotifierSelector; } @@ -1082,10 +1084,12 @@ protected String getBuildDescription( final Run run, final StashBuildState state) { - if (run.getDescription() != null - && run.getDescription().trim().length() > 0) { + String runDescription = run.getDescription(); + + if (runDescription != null + && runDescription.trim().length() > 0) { - return run.getDescription(); + return runDescription; } else { switch (state) { case INPROGRESS: