/*
* The MIT License
*
* Copyright 2013 Sony Mobile Communications Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.jenkins.plugins.bfa.sod;
import com.google.common.collect.Lists;
import com.sonyericsson.jenkins.plugins.bfa.PluginImpl;
import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Job;
import hudson.model.Result;
import hudson.util.RunList;
import com.sonyericsson.jenkins.plugins.bfa.db.KnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.db.LocalFileKnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication;
import hudson.matrix.MatrixBuild;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import jenkins.model.Jenkins;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.junit.Assert.assertEquals;
//CS IGNORE MagicNumber FOR NEXT 300 LINES. REASON: TestData.
/**
* Tests for the ScanOnDemandTask.
*
* @author shemeer.x.sulaiman@sonymobile.com>
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Jenkins.class, PluginImpl.class, ScanOnDemandQueue.class, ScanOnDemandTask.class })
public class ScanOnDemandTaskTest {
private AbstractProject mockproject;
private PluginImpl pluginMock;
/**
* Runs before every test.
* Mocks {@link com.sonyericsson.jenkins.plugins.bfa.PluginImpl#getInstance()} to avoid NPE's
* when checking permissions in the code under test.
*/
@Before
public void setUp() {
pluginMock = PowerMockito.mock(PluginImpl.class);
mockStatic(PluginImpl.class);
when(PluginImpl.getInstance()).thenReturn(pluginMock);
when(PluginImpl.needToAnalyze(Result.FAILURE)).thenReturn(true);
}
/**
* Happy test that should find one non scanned build found
* due to build failure.
*
* @throws Exception if so.
*/
@Test
public void testOneSODbuildfoundwithBuildFailure() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
AbstractBuild mockbuild1 = PowerMockito.mock(AbstractBuild.class);
AbstractBuild mockbuild2 = PowerMockito.mock(AbstractBuild.class);
PowerMockito.when(mockbuild1.getResult()).thenReturn(Result.SUCCESS);
PowerMockito.when(mockbuild2.getResult()).thenReturn(Result.FAILURE);
RunList<AbstractBuild> builds = new RunList<AbstractBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Arrays.asList(mockbuild1, mockbuild2));
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 1, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find two non scanned build found
* due to build failure.
*
* @throws Exception if so.
*/
@Test
public void testTwoSODbuildfoundwithBuildFailure() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
AbstractBuild mockbuild1 = PowerMockito.mock(AbstractBuild.class);
AbstractBuild mockbuild2 = PowerMockito.mock(AbstractBuild.class);
PowerMockito.when(mockbuild1.getResult()).thenReturn(Result.FAILURE);
PowerMockito.when(mockbuild2.getResult()).thenReturn(Result.FAILURE);
RunList<AbstractBuild> builds = new RunList<AbstractBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Arrays.asList(mockbuild1, mockbuild2));
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 2, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find no SOD build because
* all buld are success.
*
*/
@Test
public void testNoSODbuildfoundwithBuildSuccess() {
mockproject = PowerMockito.mock(AbstractProject.class);
AbstractBuild mockbuild1 = PowerMockito.mock(AbstractBuild.class);
AbstractBuild mockbuild2 = PowerMockito.mock(AbstractBuild.class);
PowerMockito.when(mockbuild1.getResult()).thenReturn(Result.SUCCESS);
PowerMockito.when(mockbuild2.getResult()).thenReturn(Result.SUCCESS);
RunList<AbstractBuild> builds = new RunList<AbstractBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Arrays.asList(mockbuild1, mockbuild2));
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 0, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find no SOD build because
* all buld are failed but already scanned.
*
* @throws Exception if so.
*/
@Test
public void testNoSODbuildfoundwithBuildFailedButAlreadyScanned() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
List<FoundFailureCause> foundFailureCauses = new ArrayList<FoundFailureCause>();
foundFailureCauses.add(new FoundFailureCause(configureCauseAndIndication()));
List<FailureCauseBuildAction> failureCauseBuildActions = new ArrayList<FailureCauseBuildAction>();
failureCauseBuildActions.add(new FailureCauseBuildAction(foundFailureCauses));
AbstractBuild mockbuild1 = PowerMockito.mock(AbstractBuild.class);
PowerMockito.when(mockbuild1.getResult()).thenReturn(Result.FAILURE);
FailureCauseBuildAction failureCauseBuildAction = PowerMockito.mock(FailureCauseBuildAction.class);
mockbuild1.addAction(failureCauseBuildAction);
RunList<AbstractBuild> builds = new RunList<AbstractBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Collections.singletonList(mockbuild1));
PowerMockito.when(mockbuild1.getActions(FailureCauseBuildAction.class)).thenReturn(failureCauseBuildActions);
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 0, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find one matrixbuild need
* to be scanned.
*
* @throws Exception if so.
*/
@Test
public void testOneSODMatrixbuildfoundwithBuildFailure() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
MatrixBuild matrixbuild1 = PowerMockito.mock(MatrixBuild.class);
MatrixBuild matrixbuild2 = PowerMockito.mock(MatrixBuild.class);
PowerMockito.when(matrixbuild1.getResult()).thenReturn(Result.SUCCESS);
PowerMockito.when(matrixbuild2.getResult()).thenReturn(Result.FAILURE);
RunList<MatrixBuild> builds = new RunList<MatrixBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Arrays.asList(matrixbuild1, matrixbuild2));
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 1, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find no matrixbuild since
* all builds are success.
*
* @throws Exception if so.
*/
@Test
public void testNoSODMatrixBuildfoundwithBuildSuccess() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
MatrixBuild matrixbuild1 = PowerMockito.mock(MatrixBuild.class);
MatrixBuild matrixbuild2 = PowerMockito.mock(MatrixBuild.class);
PowerMockito.when(matrixbuild1.getResult()).thenReturn(Result.SUCCESS);
PowerMockito.when(matrixbuild2.getResult()).thenReturn(Result.SUCCESS);
RunList<MatrixBuild> builds = new RunList<MatrixBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Arrays.asList(matrixbuild1, matrixbuild2));
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 0, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Happy test that should find no matrixbuild since
* build failed but already scanned.
*
* @throws Exception if so.
*/
@Test
public void testNoSODmatrixbuildfoundwithBuildFailedButAlreadyScanned() throws Exception {
mockproject = PowerMockito.mock(AbstractProject.class);
List<FoundFailureCause> foundFailureCauses = new ArrayList<FoundFailureCause>();
foundFailureCauses.add(new FoundFailureCause(configureCauseAndIndication()));
List<FailureCauseBuildAction> failureCauseBuildActions = new ArrayList<FailureCauseBuildAction>();
failureCauseBuildActions.add(new FailureCauseBuildAction(foundFailureCauses));
MatrixBuild mockbuild1 = PowerMockito.mock(MatrixBuild.class);
PowerMockito.when(mockbuild1.getResult()).thenReturn(Result.FAILURE);
FailureCauseBuildAction failureCauseBuildAction = PowerMockito.mock(FailureCauseBuildAction.class);
mockbuild1.addAction(failureCauseBuildAction);
RunList<AbstractBuild> builds = new RunList<AbstractBuild>(Collections.<Job>emptyList());
Whitebox.setInternalState(builds, "base", Collections.singletonList(mockbuild1));
PowerMockito.when(mockbuild1.getActions(FailureCauseBuildAction.class)).thenReturn(failureCauseBuildActions);
PowerMockito.when(mockproject.getBuilds()).thenReturn(builds);
ScanOnDemandBaseAction.NonScanned action = new ScanOnDemandBaseAction.NonScanned();
assertEquals("Nonscanned buils", 0, Lists.newArrayList(action.getRuns(mockproject)).size());
}
/**
* Convenience method for a standard cause that finds ERROR in the build log.
*
* @return the configured cause that was added to the global config.
* @throws Exception if something goes wrong in handling the causes.
*
* @see #configureCauseAndIndication(com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
* @see #configureCauseAndIndication(String, String,
* com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
*/
private FailureCause configureCauseAndIndication() throws Exception {
return configureCauseAndIndication(new BuildLogIndication(".*ERROR.*"));
}
//CS IGNORE LineLength FOR NEXT 10 LINES. REASON: JavaDoc.
/**
* Convenience method for the standard cause with a special indication.
*
* @param indication the indication for the cause.
* @return the configured cause that was added to the global config.
* @throws Exception if something goes wrong in handling the causes.
*
* @see #configureCauseAndIndication(String, String, com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
*/
private FailureCause configureCauseAndIndication(Indication indication) throws Exception {
return configureCauseAndIndication("Error", "This is an error", indication);
}
/**
* Convenience method for a standard cause with a category and the provided indication.
*
* @param name the name of the cause.
* @param description the description of the cause.
* @param indication the indication.
* @return the configured cause that was added to the global config.
* @throws Exception if something goes wrong in handling the causes.
*/
private FailureCause configureCauseAndIndication(String name, String description, Indication indication)
throws Exception {
return configureCauseAndIndication(name, description, "comment", "category", indication);
}
/**
* Configures the global settings with a cause that has the provided indication/
*
* @param name the name of the cause.
* @param description the description of the cause.
* @param comment the comment of the cause.
* @param category the category of the cause.
* @param indication the indication.
* @return the configured cause that was added to the global config.
* @throws Exception if something goes wrong in handling the causes.
*/
private FailureCause configureCauseAndIndication(String name, String description, String comment, String category,
Indication indication) throws Exception {
List<Indication> indicationList = new LinkedList<Indication>();
indicationList.add(indication);
FailureCause failureCause =
new FailureCause(name, name, description, comment, null, category, indicationList, null);
List<FailureCause> causeList = new LinkedList<FailureCause>();
causeList.add(failureCause);
Whitebox.setInternalState(PluginImpl.getInstance(), KnowledgeBase.class, new LocalFileKnowledgeBase(causeList));
return failureCause;
}
}