package org.pitest.maven;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import org.apache.maven.model.Build;
import org.apache.maven.model.Scm;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.scm.ChangeFile;
import org.apache.maven.scm.ChangeSet;
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFile;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.ScmFileStatus;
import org.apache.maven.scm.command.changelog.ChangeLogScmRequest;
import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
import org.apache.maven.scm.command.changelog.ChangeLogSet;
import org.apache.maven.scm.command.status.StatusScmResult;
import org.apache.maven.scm.manager.ScmManager;
import org.apache.maven.scm.repository.ScmRepository;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.pitest.functional.predicate.True;
import org.pitest.mutationtest.config.PluginServices;
import org.pitest.mutationtest.config.ReportOptions;
public class ScmMojoTest extends BasePitMojoTest {
private ScmMojo testee;
@Mock
private Build build;
@Mock
private Scm scm;
@Mock
private ScmManager manager;
@Mock
private ScmRepository repository;
@Override
public void setUp() throws Exception {
super.setUp();
this.testee = new ScmMojo(this.executionStrategy, this.manager,
this.filter, this.plugins, false, True.<MavenProject>all());
this.testee.setScmRootDir(new File("foo"));
when(this.project.getBuild()).thenReturn(this.build);
when(this.build.getSourceDirectory()).thenReturn("foo");
when(this.build.getOutputDirectory()).thenReturn("foo");
when(this.project.getScm()).thenReturn(this.scm);
when(this.manager.makeScmRepository(any(String.class))).thenReturn(
this.repository);
configurePitMojo(this.testee, createPomWithConfiguration(""));
}
public void testThrowsAnExceptionWhenNoScmConfigured() throws Exception {
try {
when(this.project.getScm()).thenReturn(null);
this.testee.execute();
fail("Exception expected");
} catch (final MojoExecutionException ex) {
assertEquals("No SCM Connection configured.", ex.getMessage());
}
}
public void testUsesCorrectConnectionWhenDeveloperConnectionSet()
throws Exception {
final String devUrl = "devcon";
when(this.scm.getDeveloperConnection()).thenReturn(devUrl);
setupToReturnNoModifiedFiles();
this.testee.setConnectionType("developerconnection");
this.testee.execute();
verify(this.manager).makeScmRepository(devUrl);
}
public void testUsesCorrectConnectionWhenNonDeveloperConnectionSet()
throws Exception {
final String url = "prodcon";
when(this.scm.getConnection()).thenReturn(url);
setupToReturnNoModifiedFiles();
this.testee.setConnectionType("connection");
this.testee.execute();
verify(this.manager).makeScmRepository(url);
}
public void testClassesAddedToScmAreMutationTested() throws Exception {
setupConnection();
setFileWithStatus(ScmFileStatus.ADDED);
this.testee.execute();
verify(this.executionStrategy).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
private void setFileWithStatus(final ScmFileStatus status)
throws ScmException {
when(this.manager.status(any(ScmRepository.class), any(ScmFileSet.class)))
.thenReturn(
new StatusScmResult("", Arrays.asList(new ScmFile(
"foo/bar/Bar.java", status))));
}
public void testModifiedClassesAreMutationTested() throws Exception {
setupConnection();
setFileWithStatus(ScmFileStatus.MODIFIED);
this.testee.execute();
verify(this.executionStrategy).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
public void testLastCommitIsMutationTested() throws Exception {
setupConnection();
configurePitMojo(
this.testee,
createPomWithConfiguration("<analyseLastCommit>true</analyseLastCommit>"));
givenChangeLogWithLastCommit();
this.testee.execute();
verify(this.executionStrategy).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
private void givenChangeLogWithLastCommit() throws ScmException {
when(this.manager.changeLog(any(ChangeLogScmRequest.class)))
.thenReturn(new ChangeLogScmResult("", new ChangeLogSet(Arrays.asList(aChangeSetWithAddedFile()),
new Date(), new Date())));
}
private ChangeSet aChangeSetWithAddedFile() {
return new ChangeSet(new Date(), "", "", Arrays.asList(aChangeFile(ScmFileStatus.ADDED)));
}
private ChangeFile aChangeFile(ScmFileStatus fileStatus) {
ChangeFile changeFile = new ChangeFile("foo/bar/Bar.java");
changeFile.setAction(fileStatus);
return changeFile;
}
public void testUnknownAndDeletedClassesAreNotMutationTested()
throws Exception {
setupConnection();
when(this.manager.status(any(ScmRepository.class), any(ScmFileSet.class)))
.thenReturn(
new StatusScmResult("", Arrays.asList(new ScmFile(
"foo/bar/Bar.java", ScmFileStatus.DELETED), new ScmFile(
"foo/bar/Bar.java", ScmFileStatus.UNKNOWN))));
this.testee.execute();
verify(this.executionStrategy, never()).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
public void testCanOverrideInspectedStatus() throws Exception {
setupConnection();
setFileWithStatus(ScmFileStatus.UNKNOWN);
configurePitMojo(
this.testee,
createPomWithConfiguration("<include><value>DELETED</value><value>UNKNOWN</value></include>"));
this.testee.execute();
verify(this.executionStrategy, times(1)).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
public void testDoesNotAnalysePomProjects() throws Exception {
setupConnection();
setFileWithStatus(ScmFileStatus.MODIFIED);
when(this.project.getPackaging()).thenReturn("pom");
this.testee.execute();
verify(this.executionStrategy, never()).execute(any(File.class),
any(ReportOptions.class), any(PluginServices.class), anyMap());
}
private void setupConnection() {
when(this.scm.getConnection()).thenReturn("url");
this.testee.setConnectionType("connection");
}
private void setupToReturnNoModifiedFiles() throws ScmException {
when(this.manager.status(any(ScmRepository.class), any(ScmFileSet.class)))
.thenReturn(new StatusScmResult("", Collections.<ScmFile> emptyList()));
}
private Map<String, String> anyMap() {
return Matchers.<Map<String, String>> any();
}
}