Skip to content

Commit

Permalink
#124 added new option --ignore-missing-classes-by-regex for CLI-Tool
Browse files Browse the repository at this point in the history
  • Loading branch information
siom79 committed Jul 17, 2016
1 parent c910b5e commit 561f48f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 17 deletions.
8 changes: 7 additions & 1 deletion japicmp/src/main/java/japicmp/cli/JApiCli.java
Expand Up @@ -23,6 +23,7 @@

public class JApiCli {
public static final String IGNORE_MISSING_CLASSES = "--ignore-missing-classes";
public static final String IGNORE_MISSING_CLASSES_BY_REGEX = "--ignore-missing-classes-by-regex";
public static final String OLD_CLASSPATH = "--old-classpath";
public static final String NEW_CLASSPATH = "--new-classpath";

Expand Down Expand Up @@ -56,8 +57,10 @@ public static class Compare implements Runnable {
public boolean semanticVersioning = false;
@Option(name = { "--include-synthetic" }, description = "Include synthetic classes and class members that are hidden per default.")
public boolean includeSynthetic = false;
@Option(name = { IGNORE_MISSING_CLASSES }, description = "Ignores superclasses/interfaces missing on the classpath.")
@Option(name = { IGNORE_MISSING_CLASSES }, description = "Ignores all superclasses/interfaces missing on the classpath.")
public boolean ignoreMissingClasses = false;
@Option(name = {IGNORE_MISSING_CLASSES_BY_REGEX}, description = "Ignores only those superclasses/interface missing on the classpath that are selected by a regular expression.")
public List<String> ignoreMissingClassesByRegEx = new ArrayList<>();
@Option(name = { "--html-stylesheet" }, description = "Provides the path to your own stylesheet.")
public String pathToHtmlStylesheet;
@Option(name = { OLD_CLASSPATH }, description = "The classpath for the old version.")
Expand Down Expand Up @@ -116,6 +119,9 @@ private Options createOptionsFromCliArgs() {
options.setOldClassPath(Optional.fromNullable(oldClassPath));
options.setNewClassPath(Optional.fromNullable(newClassPath));
options.setNoAnnotations(noAnnotations);
for (String missingClassRegEx : ignoreMissingClassesByRegEx) {
options.addIgnoreMissingClassRegularExpression(missingClassRegEx);
}
options.verify();
return options;
}
Expand Down
51 changes: 50 additions & 1 deletion japicmp/src/test/java/japicmp/JApiCmpTest.java
Expand Up @@ -2,14 +2,23 @@

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import japicmp.util.CtClassBuilder;
import japicmp.util.CtConstructorBuilder;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.Assertion;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import org.junit.contrib.java.lang.system.LogMode;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import static japicmp.cli.JApiCli.IGNORE_MISSING_CLASSES_BY_REGEX;
import static japicmp.util.JarUtil.createJarFile;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -138,4 +147,44 @@ static void assertListsEquals(ImmutableList<String> expected, ImmutableList<Stri
Joiner nlJoiner = Joiner.on("\n");
assertEquals(nlJoiner.join(expected), nlJoiner.join(actual));
}
}

@Test
public void testIgnoreMissingClassesByRegExCouldNotLoad() throws IOException, CannotCompileException {
exit.expectSystemExitWithStatus(1);
exit.checkAssertionAfterwards(new Assertion() {
public void checkAssertion() {
String errLogTrimmed = errLog.getLog().trim();
assertThat(errLogTrimmed, containsString("E: Could not load 'NotExistingSuperclass'".trim()));
}
});
ClassPool cp = new ClassPool(true);
CtClass ctClassSuperclass = CtClassBuilder.create().name("NotExistingSuperclass").addToClassPool(cp);
CtConstructorBuilder.create().addToClass(ctClassSuperclass);
CtClass ctClass = CtClassBuilder.create().name("Test").withSuperclass(ctClassSuperclass).addToClassPool(cp);
Path oldPath = Paths.get(System.getProperty("user.dir"), "target", JApiCmpTest.class.getSimpleName() + "_old.jar");
createJarFile(oldPath, ctClass);
Path newPath = Paths.get(System.getProperty("user.dir"), "target", JApiCmpTest.class.getSimpleName() + "_new.jar");
createJarFile(newPath, ctClass);
JApiCmp.main(new String[]{"-n", newPath.toString(), "-o", oldPath.toString()});
}

@Test
public void testIgnoreMissingClassesByRegExMissingAreIgnore() throws IOException, CannotCompileException {
exit.checkAssertionAfterwards(new Assertion() {
public void checkAssertion() {
String outLog = JApiCmpTest.this.outLog.getLog().trim();
assertThat(outLog, containsString("Comparing".trim()));
assertThat(outLog, containsString("WARNING: You have ignored certain classes".trim()));
}
});
ClassPool cp = new ClassPool(true);
CtClass ctClassSuperclass = CtClassBuilder.create().name("NotExistingSuperclass").addToClassPool(cp);
CtConstructorBuilder.create().addToClass(ctClassSuperclass);
CtClass ctClass = CtClassBuilder.create().name("Test").withSuperclass(ctClassSuperclass).addToClassPool(cp);
Path oldPath = Paths.get(System.getProperty("user.dir"), "target", JApiCmpTest.class.getSimpleName() + "_old.jar");
createJarFile(oldPath, ctClass);
Path newPath = Paths.get(System.getProperty("user.dir"), "target", JApiCmpTest.class.getSimpleName() + "_new.jar");
createJarFile(newPath, ctClass);
JApiCmp.main(new String[]{"-n", newPath.toString(), "-o", oldPath.toString(), IGNORE_MISSING_CLASSES_BY_REGEX, ".*Superc.*"});
}
}
17 changes: 3 additions & 14 deletions japicmp/src/test/java/japicmp/cmp/IgnoreMissingClassesTest.java
Expand Up @@ -24,6 +24,7 @@
import java.util.jar.Manifest;
import java.util.regex.Pattern;

import static japicmp.util.JarUtil.createJarFile;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.core.StringContains.containsString;
Expand Down Expand Up @@ -105,7 +106,7 @@ public void testClassMissingWithIgnoreClassByRegex() throws Exception {
@Test
public void testClassMissingWithIgnoreByRegexThatDoesNotMatch() throws Exception {
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
options.getIgnoreMissingClasses().setIgnoreMissingClassRegularExpression(Arrays.asList(Pattern.compile("WrongPattern")));
options.getIgnoreMissingClasses().setIgnoreMissingClassRegularExpression(Collections.singletonList(Pattern.compile("WrongPattern")));
JarArchiveComparator jarArchiveComparator = new JarArchiveComparator(options);
ClassPool classPool = jarArchiveComparator.getCommonClassPool();
CtClass ctSuperclass = CtClassBuilder.create().name("SuperclassNotExisting").addToClassPool(classPool);
Expand All @@ -125,17 +126,5 @@ public void testClassMissingWithIgnoreByRegexThatDoesNotMatch() throws Exception
}
}

private void createJarFile(Path jarFileName, CtClass... ctClasses) throws IOException, CannotCompileException {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
try (JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jarFileName.toString()), manifest)) {
for (CtClass ctClass : ctClasses) {
JarEntry entry = new JarEntry(ctClass.getSimpleName() + ".class");
jarStream.putNextEntry(entry);
byte[] bytecode = ctClass.toBytecode();
jarStream.write(bytecode, 0, bytecode.length);
jarStream.closeEntry();
}
}
}

}
29 changes: 29 additions & 0 deletions japicmp/src/test/java/japicmp/util/JarUtil.java
@@ -0,0 +1,29 @@
package japicmp.util;

import javassist.CannotCompileException;
import javassist.CtClass;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

public class JarUtil {

public static void createJarFile(Path jarFileName, CtClass... ctClasses) throws IOException, CannotCompileException {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
try (JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jarFileName.toString()), manifest)) {
for (CtClass ctClass : ctClasses) {
JarEntry entry = new JarEntry(ctClass.getSimpleName() + ".class");
jarStream.putNextEntry(entry);
byte[] bytecode = ctClass.toBytecode();
jarStream.write(bytecode, 0, bytecode.length);
jarStream.closeEntry();
}
}
}
}
7 changes: 6 additions & 1 deletion src/site/markdown/CliTool.md
Expand Up @@ -9,6 +9,7 @@ SYNOPSIS
[--html-file <pathToHtmlOutputFile>]
[--html-stylesheet <pathToHtmlStylesheet>]
[(-i <includes> | --include <includes>)] [--ignore-missing-classes]
[--ignore-missing-classes-by-regex <ignoreMissingClassesByRegEx>...]
[--include-synthetic] [(-m | --only-modified)]
[(-n <pathToNewVersionJar> | --new <pathToNewVersionJar>)]
[--new-classpath <newClassPath>] [--no-annotations]
Expand Down Expand Up @@ -47,7 +48,11 @@ OPTIONS
mypackage;my.Class;other.Class#method(int,long);foo.Class#field;@my.Annotation.
--ignore-missing-classes
Ignores superclasses/interfaces missing on the classpath.
Ignores all superclasses/interfaces missing on the classpath.
--ignore-missing-classes-by-regex <ignoreMissingClassesByRegEx>
Ignores only those superclasses/interface missing on the classpath that are selected by a regular
expression.
--include-synthetic
Include synthetic classes and class members that are hidden per
Expand Down

0 comments on commit 561f48f

Please sign in to comment.