/******************************************************************************* * Copyright (c) 2017 Synopsys, Inc * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Synopsys, Inc - initial implementation and documentation *******************************************************************************/ package jenkins.plugins.coverity.ws; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import javax.xml.datatype.DatatypeConfigurationException; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.coverity.ws.v9.CovRemoteServiceException_Exception; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.Descriptor; import hudson.model.Result; import jenkins.model.Jenkins; import jenkins.plugins.coverity.CIMInstance; import jenkins.plugins.coverity.CIMStream; import jenkins.plugins.coverity.CoverityBuildAction; import jenkins.plugins.coverity.CoverityPublisher; import jenkins.plugins.coverity.CoverityPublisher.DescriptorImpl; import jenkins.plugins.coverity.DefectFilters; import jenkins.plugins.coverity.Utils.CoverityPublisherBuilder; import jenkins.plugins.coverity.Utils.TestableConsoleLogger; import jenkins.plugins.coverity.ws.TestWebServiceFactory.TestDefectService; @RunWith(PowerMockRunner.class) @PrepareForTest(Jenkins.class) public class DefectReaderTest { @Mock private Jenkins jenkins; @Mock private AbstractBuild<?, ?> build; @Mock private BuildListener listener; @Mock private DescriptorImpl descriptor; private TestableConsoleLogger consoleLogger; private TestDefectService defectService; private static final String cimInstanceName = "cim-instance"; @Before public void setup() throws IOException { // setup jenkins PowerMockito.mockStatic(Jenkins.class); when(Jenkins.getInstance()).thenReturn(jenkins); // setup console logger consoleLogger = new TestableConsoleLogger(); when(listener.getLogger()).thenReturn(consoleLogger.getPrintStream()); // setup global configuration (DescriptorImpl) with TestWebService CIMInstance cimInstance = mock(CIMInstance.class); defectService = (TestDefectService)new TestWebServiceFactory().getDefectService(cimInstance); when(cimInstance.getDefectService()).thenReturn(defectService); when(descriptor.getInstance(cimInstanceName)).thenReturn(cimInstance); when(jenkins.getDescriptorOrDie(CoverityPublisher.class)).thenReturn(descriptor); } private DefectFilters getMatchingDefectFilters(){ try { return new DefectFilters( Arrays.asList("Undecided"), new ArrayList<>(Arrays.asList("High", "Medium", "Low")), Arrays.asList("Unclassified"), Arrays.asList("Unspecified", "Major", "Moderate", "Minor"), Arrays.asList("Default.Other"), Arrays.asList("TEST_CHECKER"), "2017-01-01"); } catch(Descriptor.FormException e) { return null; } } @Test public void getLatestDefectsForBuild_withNoDefectFilters_addDefectsToBuildAction() throws ParseException, DatatypeConfigurationException, IOException, CovRemoteServiceException_Exception { when(jenkins.getRootUrl()).thenReturn("rootUrl/"); when(build.getUrl()).thenReturn("buildUrl/"); CIMStream cimStream = new CIMStream(cimInstanceName, "test-project", "test-stream", null); CoverityPublisher publisher = new CoverityPublisherBuilder().withCimStream(cimStream).build(); defectService.setupMergedDefects(10); DefectReader reader = new DefectReader(build, listener, publisher); reader.getLatestDefectsForBuild(); // assert build action added to build with expected defect count ArgumentCaptor<CoverityBuildAction> buildAction = ArgumentCaptor.forClass(CoverityBuildAction.class); verify(build).addAction(buildAction.capture()); assertEquals(10, buildAction.getValue().getDefects().size()); // verify all expected log messages were written consoleLogger.verifyMessages( "[Coverity] Fetching defects for stream \"test-stream\"", "[Coverity] Found 10 defects matching all filters", "Coverity details: rootUrl/buildUrl/coverity_defects"); } @Test public void getLatestDefectsForBuild_withMatchingDefectFilters_addDefectsToBuildAction() throws ParseException, DatatypeConfigurationException, IOException, CovRemoteServiceException_Exception { when(jenkins.getRootUrl()).thenReturn("rootUrl/"); when(build.getUrl()).thenReturn("buildUrl/"); CIMStream cimStream = new CIMStream(cimInstanceName, "test-project", "test-stream", getMatchingDefectFilters()); CoverityPublisher publisher = new CoverityPublisherBuilder().withCimStream(cimStream).build(); defectService.setupMergedDefects(3); DefectReader reader = new DefectReader(build, listener, publisher); reader.getLatestDefectsForBuild(); // assert build action added to build with expected defect count ArgumentCaptor<CoverityBuildAction> buildAction = ArgumentCaptor.forClass(CoverityBuildAction.class); verify(build).addAction(buildAction.capture()); assertEquals(3, buildAction.getValue().getDefects().size()); // verify all expected log messages were written consoleLogger.verifyMessages( "[Coverity] Fetching defects for stream \"test-stream\"", "[Coverity] Found 3 defects matching all filters", "Coverity details: rootUrl/buildUrl/coverity_defects"); } @Test public void getLatestDefectsForBuild_withOverOneThousandMatchingDefects_addDefectsToBuildAction() throws Descriptor.FormException, ParseException, DatatypeConfigurationException, IOException, CovRemoteServiceException_Exception { when(jenkins.getRootUrl()).thenReturn("rootUrl/"); when(build.getUrl()).thenReturn("buildUrl/"); CIMStream cimStream = new CIMStream(cimInstanceName, "test-project", "test-stream", getMatchingDefectFilters()); CoverityPublisher publisher = new CoverityPublisherBuilder().withCimStream(cimStream).build(); defectService.setupMergedDefects(3750); DefectReader reader = new DefectReader(build, listener, publisher); reader.getLatestDefectsForBuild(); // assert build action added to build with expected defect count ArgumentCaptor<CoverityBuildAction> buildAction = ArgumentCaptor.forClass(CoverityBuildAction.class); verify(build).addAction(buildAction.capture()); assertEquals(3750, buildAction.getValue().getDefects().size()); // verify all expected log messages were written consoleLogger.verifyMessages( "[Coverity] Fetching defects for stream \"test-stream\"", "[Coverity] Fetching defects for stream \"test-stream\" (fetched 1,000 of 3,750)", "[Coverity] Fetching defects for stream \"test-stream\" (fetched 2,000 of 3,750)", "[Coverity] Fetching defects for stream \"test-stream\" (fetched 3,000 of 3,750)", "[Coverity] Found 3,750 defects matching all filters", "Coverity details: rootUrl/buildUrl/coverity_defects"); } @Test public void getLatestDefectsForBuild_withMatchingDefectFilters_setsBuildResultAsFailed() throws ParseException, DatatypeConfigurationException, IOException, CovRemoteServiceException_Exception { // set initial state as success (result can only get worse) when(build.getResult()).thenReturn(Result.SUCCESS); CIMStream cimStream = new CIMStream(cimInstanceName, "test-project", "test-stream", getMatchingDefectFilters()); CoverityPublisher publisher = new CoverityPublisherBuilder().withCimStream(cimStream).withFailBuild(true).build(); defectService.setupMergedDefects(3); DefectReader reader = new DefectReader(build, listener, publisher); reader.getLatestDefectsForBuild(); // assert build action added to build with expected defect count ArgumentCaptor<CoverityBuildAction> buildAction = ArgumentCaptor.forClass(CoverityBuildAction.class); verify(build).addAction(buildAction.capture()); assertEquals(3, buildAction.getValue().getDefects().size()); // verify all expected log messages were written consoleLogger.verifyMessages( "[Coverity] Fetching defects for stream \"test-stream\"", "[Coverity] Found 3 defects matching all filters"); } @Test public void getLatestDefectsForBuild_skipsFetchingDefects() throws Descriptor.FormException, ParseException, DatatypeConfigurationException, IOException, CovRemoteServiceException_Exception { CoverityPublisher publisher = new CoverityPublisherBuilder().withSkipFetchingDefects(true).build(); DefectReader reader = new DefectReader(build, listener, publisher); reader.getLatestDefectsForBuild(); // verify no log messages were written consoleLogger.verifyMessages(); } }