package japicmp.maven;
import com.google.common.base.Optional;
import japicmp.cmp.ClassesHelper;
import japicmp.cmp.JarArchiveComparator;
import japicmp.cmp.JarArchiveComparatorOptions;
import japicmp.config.Options;
import japicmp.maven.util.CtClassBuilder;
import japicmp.maven.util.CtFieldBuilder;
import japicmp.maven.util.CtInterfaceBuilder;
import japicmp.maven.util.CtMethodBuilder;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.junit.Test;
import org.mockito.Matchers;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class JApiCmpMojoTest {
@Test
public void testSimple() throws MojoFailureException {
JApiCmpMojo mojo = new JApiCmpMojo();
Version oldVersion = createVersion("groupId", "artifactId", "0.1.0");
Version newVersion = createVersion("groupId", "artifactId", "0.1.1");
PluginParameters pluginParameters = new PluginParameters(null, newVersion, oldVersion, new Parameter(), null, Optional.of(Paths.get(System.getProperty("user.dir"), "target", "simple").toFile()), Optional.<String>absent(), true, null, null, null, null);
ArtifactResolver artifactResolver = mock(ArtifactResolver.class);
ArtifactResolutionResult artifactResolutionResult = mock(ArtifactResolutionResult.class);
Set<Artifact> artifactSet = new HashSet<>();
Artifact resolvedArtifact = mock(Artifact.class);
artifactSet.add(resolvedArtifact);
when(resolvedArtifact.getFile()).thenReturn(Paths.get(System.getProperty("user.dir"), "target", "guava-18.0.jar").toFile());
when(artifactResolutionResult.getArtifacts()).thenReturn(artifactSet);
when(artifactResolver.resolve(Matchers.<ArtifactResolutionRequest>anyObject())).thenReturn(artifactResolutionResult);
ArtifactFactory artifactFactory = mock(ArtifactFactory.class);
when(artifactFactory.createArtifactWithClassifier(eq("groupId"), eq("artifactId"), eq("0.1.1"), anyString(), anyString())).thenReturn(mock(Artifact.class));
MavenParameters mavenParameters = new MavenParameters(new ArrayList<ArtifactRepository>(), artifactFactory, mock(ArtifactRepository.class), artifactResolver, mock(MavenProject.class), mock(MojoExecution.class), "0.0.1", mock(ArtifactMetadataSource.class));
mojo.executeWithParameters(pluginParameters, mavenParameters);
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", "japicmp.diff")), is(true));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", "japicmp.xml")), is(true));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", "japicmp.html")), is(true));
}
@Test
public void testNoXmlAndNoHtmlNoDiffReport() throws MojoFailureException {
JApiCmpMojo mojo = new JApiCmpMojo();
Version oldVersion = createVersion("groupId", "artifactId", "0.1.0");
Version newVersion = createVersion("groupId", "artifactId", "0.1.1");
Parameter parameter = new Parameter();
parameter.setSkipHtmlReport("true");
parameter.setSkipXmlReport("true");
parameter.setSkipDiffReport(true);
String reportDir = "noXmlAndNoHtmlNoDiffReport";
PluginParameters pluginParameters = new PluginParameters(null, newVersion, oldVersion, parameter, null, Optional.of(Paths.get(System.getProperty("user.dir"), "target", reportDir).toFile()), Optional.<String>absent(), true, null, null, null, null);
ArtifactResolver artifactResolver = mock(ArtifactResolver.class);
ArtifactResolutionResult artifactResolutionResult = mock(ArtifactResolutionResult.class);
Set<Artifact> artifactSet = new HashSet<>();
Artifact resolvedArtifact = mock(Artifact.class);
artifactSet.add(resolvedArtifact);
when(resolvedArtifact.getFile()).thenReturn(Paths.get(System.getProperty("user.dir"), "target", "guava-18.0.jar").toFile());
when(artifactResolutionResult.getArtifacts()).thenReturn(artifactSet);
when(artifactResolver.resolve(Matchers.<ArtifactResolutionRequest>anyObject())).thenReturn(artifactResolutionResult);
ArtifactFactory artifactFactory = mock(ArtifactFactory.class);
when(artifactFactory.createArtifactWithClassifier(eq("groupId"), eq("artifactId"), eq("0.1.1"), anyString(), anyString())).thenReturn(mock(Artifact.class));
MavenParameters mavenParameters = new MavenParameters(new ArrayList<ArtifactRepository>(), artifactFactory, mock(ArtifactRepository.class), artifactResolver, mock(MavenProject.class), mock(MojoExecution.class), "0.0.1", mock(ArtifactMetadataSource.class));
mojo.executeWithParameters(pluginParameters, mavenParameters);
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", reportDir, "japicmp", "japicmp.diff")), is(false));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", reportDir, "japicmp", "japicmp.xml")), is(false));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", reportDir, "japicmp", "japicmp.html")), is(false));
}
public static Version createVersion(String groupId, String artifactId, String version) {
Version versionInstance = new Version();
Dependency dependency = new Dependency();
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId);
dependency.setVersion(version);
versionInstance.setDependency(dependency);
return versionInstance;
}
@Test
public void testBreakBuildIfNecessaryInterfaceRemovedCausedByExclusionFalse() throws Exception {
testBreakBuildIfNecessaryInterfaceRemovedCausedByExclusion(false);
}
@Test(expected = MojoFailureException.class)
public void testBreakBuildIfNecessaryInterfaceRemovedCausedByExclusionTrue() throws Exception {
testBreakBuildIfNecessaryInterfaceRemovedCausedByExclusion(true);
}
private void testBreakBuildIfNecessaryInterfaceRemovedCausedByExclusion(boolean breakBuildIfCausedByExclusion) throws Exception {
Options options = Options.newDefault();
JarArchiveComparatorOptions jarArchiveComparatorOptions = JarArchiveComparatorOptions.of(options);
ClassesHelper.CompareClassesResult compareClassesResult = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass interfaceCtClass = CtInterfaceBuilder.create().name("japicmp.ITest").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").implementsInterface(interfaceCtClass).addToClassPool(classPool);
return Arrays.asList(interfaceCtClass, ctClass);
}
@Override
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
CtClass interfaceCtClass = CtInterfaceBuilder.create().name("japicmp.ITest").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
return Arrays.asList(interfaceCtClass, ctClass);
}
});
options.addExcludeFromArgument(Optional.of("japicmp.ITest")); // exclude japicmp.ITest
JApiCmpMojo mojo = new JApiCmpMojo();
Parameter parameterParam = new Parameter();
parameterParam.setBreakBuildIfCausedByExclusion(breakBuildIfCausedByExclusion); //do not break the build if cause is excluded
parameterParam.setBreakBuildOnBinaryIncompatibleModifications("true");
parameterParam.setBreakBuildOnSourceIncompatibleModifications("true");
mojo.breakBuildIfNecessaryByApplyingFilter(compareClassesResult.getjApiClasses(), parameterParam, options, new JarArchiveComparator(jarArchiveComparatorOptions));
}
@Test
public void testBreakBuildIfNecessaryFieldTypeChangedCausedByExclusionFalse() throws Exception {
testBreakBuildIfNecessaryFieldTypeChangedCausedByExclusion(false);
}
@Test(expected = MojoFailureException.class)
public void testBreakBuildIfNecessaryFieldTypeChangedCausedByExclusionTrue() throws Exception {
testBreakBuildIfNecessaryFieldTypeChangedCausedByExclusion(true);
}
private void testBreakBuildIfNecessaryFieldTypeChangedCausedByExclusion(boolean breakBuildIfCausedByExclusion) throws Exception {
Options options = Options.newDefault();
JarArchiveComparatorOptions jarArchiveComparatorOptions = JarArchiveComparatorOptions.of(options);
ClassesHelper.CompareClassesResult compareClassesResult = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass fieldTypeCtClass = CtClassBuilder.create().name("japicmp.FieldType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
CtFieldBuilder.create().type(fieldTypeCtClass).name("field").addToClass(ctClass);
return Arrays.asList(fieldTypeCtClass, ctClass);
}
@Override
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
CtClass fieldTypeCtClass = CtClassBuilder.create().name("japicmp.FieldType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
CtFieldBuilder.create().type(classPool.get("java.lang.String")).name("field").addToClass(ctClass);
return Arrays.asList(fieldTypeCtClass, ctClass);
}
});
options.addExcludeFromArgument(Optional.of("japicmp.FieldType")); // exclude japicmp.FieldType
JApiCmpMojo mojo = new JApiCmpMojo();
Parameter parameterParam = new Parameter();
parameterParam.setBreakBuildIfCausedByExclusion(breakBuildIfCausedByExclusion); //do not break the build if cause is excluded
parameterParam.setBreakBuildOnBinaryIncompatibleModifications("true");
parameterParam.setBreakBuildOnSourceIncompatibleModifications("true");
mojo.breakBuildIfNecessaryByApplyingFilter(compareClassesResult.getjApiClasses(), parameterParam, options, compareClassesResult.getJarArchiveComparator());
}
@Test
public void testBreakBuildIfNecessaryMethodReturnTypeChangedCausedByExclusionFalse() throws Exception {
testBreakBuildIfNecessaryMethodReturnTypeChangedCausedByExclusion(false);
}
@Test(expected = MojoFailureException.class)
public void testBreakBuildIfNecessaryMethodReturnTypeChangedCausedByExclusionTrue() throws Exception {
testBreakBuildIfNecessaryMethodReturnTypeChangedCausedByExclusion(true);
}
private void testBreakBuildIfNecessaryMethodReturnTypeChangedCausedByExclusion(boolean breakBuildIfCausedByExclusion) throws Exception {
Options options = Options.newDefault();
JarArchiveComparatorOptions jarArchiveComparatorOptions = JarArchiveComparatorOptions.of(options);
ClassesHelper.CompareClassesResult compareClassesResult = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass typeCtClass = CtClassBuilder.create().name("japicmp.MethodReturnType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
CtMethodBuilder.create().publicAccess().returnType(typeCtClass).name("test").addToClass(ctClass);
return Arrays.asList(typeCtClass, ctClass);
}
@Override
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
CtClass typeCtClass = CtClassBuilder.create().name("japicmp.MethodReturnType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
CtMethodBuilder.create().publicAccess().returnType(classPool.get("java.lang.String")).name("test").addToClass(ctClass);
return Arrays.asList(typeCtClass, ctClass);
}
});
options.addExcludeFromArgument(Optional.of("japicmp.MethodReturnType")); // exclude japicmp.MethodReturnType
JApiCmpMojo mojo = new JApiCmpMojo();
Parameter parameterParam = new Parameter();
parameterParam.setBreakBuildIfCausedByExclusion(breakBuildIfCausedByExclusion); //do not break the build if cause is excluded
parameterParam.setBreakBuildOnBinaryIncompatibleModifications("true");
parameterParam.setBreakBuildOnSourceIncompatibleModifications("true");
mojo.breakBuildIfNecessaryByApplyingFilter(compareClassesResult.getjApiClasses(), parameterParam, options, compareClassesResult.getJarArchiveComparator());
}
@Test
public void testBreakBuildIfNecessarySuperclassChangedCausedByExclusionFalse() throws Exception {
testBreakBuildIfNecessarySuperclassTypeChangedCausedByExclusion(false);
}
@Test(expected = MojoFailureException.class)
public void testBreakBuildIfNecessarySuperclassTypeChangedCausedByExclusionTrue() throws Exception {
testBreakBuildIfNecessarySuperclassTypeChangedCausedByExclusion(true);
}
private void testBreakBuildIfNecessarySuperclassTypeChangedCausedByExclusion(boolean breakBuildIfCausedByExclusion) throws Exception {
Options options = Options.newDefault();
JarArchiveComparatorOptions jarArchiveComparatorOptions = JarArchiveComparatorOptions.of(options);
ClassesHelper.CompareClassesResult compareClassesResult = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass typeCtClass = CtClassBuilder.create().name("japicmp.SuperType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").withSuperclass(typeCtClass).addToClassPool(classPool);
return Arrays.asList(typeCtClass, ctClass);
}
@Override
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
CtClass typeCtClass = CtClassBuilder.create().name("japicmp.SuperType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").withSuperclass(classPool.get("java.lang.String")).addToClassPool(classPool);
return Arrays.asList(typeCtClass, ctClass);
}
});
options.addExcludeFromArgument(Optional.of("japicmp.SuperType")); // exclude japicmp.SuperType
JApiCmpMojo mojo = new JApiCmpMojo();
Parameter parameterParam = new Parameter();
parameterParam.setBreakBuildIfCausedByExclusion(breakBuildIfCausedByExclusion); //do not break the build if cause is excluded
parameterParam.setBreakBuildOnBinaryIncompatibleModifications("true");
parameterParam.setBreakBuildOnSourceIncompatibleModifications("true");
mojo.breakBuildIfNecessaryByApplyingFilter(compareClassesResult.getjApiClasses(), parameterParam, options, compareClassesResult.getJarArchiveComparator());
}
@Test
public void testBreakBuildIfNecessaryMultipleChanges() throws Exception {
Options options = Options.newDefault();
JarArchiveComparatorOptions jarArchiveComparatorOptions = JarArchiveComparatorOptions.of(options);
ClassesHelper.CompareClassesResult compareClassesResult = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
@Override
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
CtClass typeCtClass = CtClassBuilder.create().name("japicmp.SuperType").addToClassPool(classPool);
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").withSuperclass(typeCtClass).addToClassPool(classPool);
CtFieldBuilder.create().name("field").type(CtClass.intType).addToClass(ctClass);
CtMethodBuilder.create().publicAccess().returnType(CtClass.voidType).name("method").addToClass(ctClass);
return Arrays.asList(typeCtClass, ctClass);
}
@Override
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
return Collections.singletonList(ctClass);
}
});
JApiCmpMojo mojo = new JApiCmpMojo();
Parameter parameterParam = new Parameter();
parameterParam.setBreakBuildOnBinaryIncompatibleModifications("true");
parameterParam.setBreakBuildOnSourceIncompatibleModifications("true");
try {
mojo.breakBuildIfNecessaryByApplyingFilter(compareClassesResult.getjApiClasses(), parameterParam, options, compareClassesResult.getJarArchiveComparator());
fail("No exception thrown.");
} catch (MojoFailureException e) {
String msg = e.getMessage();
assertThat(msg, containsString("japicmp.SuperType:CLASS_REMOVED"));
assertThat(msg, containsString("japicmp.Test.method():METHOD_REMOVED"));
assertThat(msg, containsString("japicmp.Test.field:FIELD_REMOVED"));
assertThat(msg, containsString("japicmp.Test:SUPERCLASS_REMOVED"));
}
}
@Test
public void testIgnoreMissingVersions() throws MojoFailureException, IOException {
JApiCmpMojo mojo = new JApiCmpMojo();
Version oldVersion = createVersion("groupId", "artifactId", "0.1.0");
Version newVersion = createVersion("groupId", "artifactId", "0.1.1");
Parameter parameterParam = new Parameter();
parameterParam.setIgnoreMissingNewVersion("true");
parameterParam.setIgnoreMissingOldVersion("true");
PluginParameters pluginParameters = new PluginParameters(null, newVersion, oldVersion, parameterParam, null, Optional.of(Paths.get(System.getProperty("user.dir"), "target", "simple").toFile()), Optional.<String>absent(), true, null, null, null, null);
ArtifactResolver artifactResolver = mock(ArtifactResolver.class);
ArtifactResolutionResult artifactResolutionResult = mock(ArtifactResolutionResult.class);
Set<Artifact> artifactSet = new HashSet<>();
when(artifactResolutionResult.getArtifacts()).thenReturn(artifactSet);
when(artifactResolver.resolve(Matchers.<ArtifactResolutionRequest>anyObject())).thenReturn(artifactResolutionResult);
ArtifactFactory artifactFactory = mock(ArtifactFactory.class);
when(artifactFactory.createArtifactWithClassifier(eq("groupId"), eq("artifactId"), eq("0.1.1"), anyString(), anyString())).thenReturn(mock(Artifact.class));
MojoExecution mojoExecution = mock(MojoExecution.class);
String executionId = "ignoreMissingVersions";
when(mojoExecution.getExecutionId()).thenReturn(executionId);
MavenParameters mavenParameters = new MavenParameters(new ArrayList<ArtifactRepository>(), artifactFactory, mock(ArtifactRepository.class), artifactResolver, mock(MavenProject.class), mojoExecution, "0.0.1", mock(ArtifactMetadataSource.class));
mojo.executeWithParameters(pluginParameters, mavenParameters);
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", executionId + ".diff")), is(false));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", executionId + ".xml")), is(false));
assertThat(Files.exists(Paths.get(System.getProperty("user.dir"), "target", "simple", "japicmp", executionId + ".html")), is(false));
}
}