diff options
author | Julien Eluard <[email protected]> | 2014-03-24 08:38:06 -0300 |
---|---|---|
committer | Julien Eluard <[email protected]> | 2014-03-24 08:38:06 -0300 |
commit | 1130c9261b179f0efdf49badba9554d1c9d63822 (patch) | |
tree | b9e702c9e6d107f8b0dd930dc9aa585fb5c3d489 /api | |
parent | 37639815664ce78bb1d2c1f2240d133209ba1398 (diff) | |
parent | 69909650ee34de32eceeee0b4dc6e0ab89f2a5b3 (diff) |
Merge pull request #19 from dvryaboy/issue_18
Adding a test to demo issue #18
Diffstat (limited to 'api')
-rw-r--r-- | api/src/main/java/org/osjava/jardiff/JarDiff.java | 19 | ||||
-rw-r--r-- | api/src/test/java/org/semver/jardiff/ClassInheritanceTest.java | 103 |
2 files changed, 115 insertions, 7 deletions
diff --git a/api/src/main/java/org/osjava/jardiff/JarDiff.java b/api/src/main/java/org/osjava/jardiff/JarDiff.java index ed10e4d..9ea9dfb 100644 --- a/api/src/main/java/org/osjava/jardiff/JarDiff.java +++ b/api/src/main/java/org/osjava/jardiff/JarDiff.java @@ -24,10 +24,8 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.Set; import java.util.TreeSet; import java.util.TreeMap; import java.util.jar.JarEntry; @@ -165,8 +163,8 @@ public class JarDiff * @param reader the ClassReader * @return the ClassInfo */ - private synchronized ClassInfo loadClassInfo(ClassReader reader) - throws IOException + private synchronized ClassInfo loadClassInfo(ClassReader reader) + throws IOException { infoVisitor.reset(); reader.accept(infoVisitor, 0); @@ -180,7 +178,7 @@ public class JarDiff * which contain classes in subdirectories or in the current directory. * * @param infoMap the map to store the ClassInfo in. - * @throws DiffException if there is an exception reading info about a + * @throws DiffException if there is an exception reading info about a * class. */ private void loadClasses(Map infoMap, URL path) throws DiffException { @@ -219,7 +217,7 @@ public class JarDiff * * @param infoMap the map to store the ClassInfo in. * @param file the jarfile to load classes from. - * @throws IOException if there is an IOException reading info about a + * @throws IOException if there is an IOException reading info about a * class. */ private void loadClasses(Map infoMap, File file) throws DiffException { @@ -291,7 +289,14 @@ public class JarDiff * writing to a file caused an IOException */ public void diff(DiffHandler handler, DiffCriteria criteria) - throws DiffException + throws DiffException + { + diff(handler, criteria, oldVersion, newVersion, oldClassInfo, newClassInfo); + } + + private void diff(DiffHandler handler, DiffCriteria criteria, + String oldVersion, String newVersion, + Map oldClassInfo, Map newClassInfo) throws DiffException { // TODO: Build the name from the MANIFEST rather than the filename handler.startDiff(oldVersion, newVersion); diff --git a/api/src/test/java/org/semver/jardiff/ClassInheritanceTest.java b/api/src/test/java/org/semver/jardiff/ClassInheritanceTest.java new file mode 100644 index 0000000..34b86a8 --- /dev/null +++ b/api/src/test/java/org/semver/jardiff/ClassInheritanceTest.java @@ -0,0 +1,103 @@ +/** + * Copyright 2012 Julien Eluard and contributors. + * This project includes software developed by Julien Eluard: https://github.com/jeluard/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.semver.jardiff; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; + +import org.junit.Test; +import org.objectweb.asm.ClassReader; +import org.osjava.jardiff.ClassInfo; +import org.osjava.jardiff.DiffCriteria; +import org.osjava.jardiff.DiffHandler; +import org.osjava.jardiff.JarDiff; +import org.osjava.jardiff.SimpleDiffCriteria; +import org.semver.Delta; +import org.semver.Delta.Change; + +public class ClassInheritanceTest { + + public static abstract class InheritanceRoot { + public abstract void aMethod(); + } + + public static class DirectDescendant extends InheritanceRoot { + @Override + public void aMethod() {} + } + + public static class ClassA extends InheritanceRoot { + @Override + public void aMethod() {} + } + + public static class ClassB extends DirectDescendant { + } + + @Test + public void shouldInheritedMethodMatchImplementedMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException { + /** + * The situation we are testing is as follows: + * Abstract class InheritanceRoot is initially implemented directly by ClassA. + * ClassA is later modified to extend another implementation of InheritanceRoot + * and the methods required by InheritanceRoot are now removed from ClassA directly, + * and instead inherited from the new parent, DirectDescendant. For the purposes of + * this test, this new ClassA is represented by ClassB (as we can't have the same + * class declared twice in a test -- in real life, this would both be ClassA's, + * in different jars). + */ + Map<String, ClassInfo> oldClassInfoMap = new HashMap<String, ClassInfo>(); + Map<String, ClassInfo> newClassInfoMap = new HashMap<String, ClassInfo>(); + JarDiff jd = new JarDiff(); + Method loadInfoMethod = JarDiff.class.getDeclaredMethod("loadClassInfo", ClassReader.class); + Method diffMethod = JarDiff.class.getDeclaredMethod("diff", DiffHandler.class, DiffCriteria.class, + String.class, String.class, + Map.class, Map.class); + diffMethod.setAccessible(true); + loadInfoMethod.setAccessible(true); + addClassInfo(oldClassInfoMap, ClassA.class, jd, loadInfoMethod); + addClassInfo(oldClassInfoMap, DirectDescendant.class, jd, loadInfoMethod); + addClassInfo(oldClassInfoMap, InheritanceRoot.class, jd, loadInfoMethod); + addClassInfo(newClassInfoMap, ClassB.class, jd, loadInfoMethod); + addClassInfo(newClassInfoMap, DirectDescendant.class, jd, loadInfoMethod); + addClassInfo(newClassInfoMap, InheritanceRoot.class, jd, loadInfoMethod); + + // Make B look like A + newClassInfoMap.put(ClassA.class.getName(), newClassInfoMap.get(ClassB.class.getName())); + newClassInfoMap.remove(ClassB.class.getName()); + DifferenceAccumulatingHandler handler = new DifferenceAccumulatingHandler(); + diffMethod.invoke(jd, handler, new SimpleDiffCriteria(), + "0.1.0", "0.2.0", oldClassInfoMap, newClassInfoMap); + + for (Delta.Difference d: handler.getDelta().getDifferences()) { + System.err.println(d.getClassName() + " : " + d.getClass().getName() + + " : " + d.getInfo().getName() + " : " + d.getInfo().getAccessType()); + if (d instanceof Change) { + System.err.println(" : " + ((Change) d).getModifiedInfo().getName()); + } + } + Assert.assertEquals("differences found", 0, handler.getDelta().getDifferences().size()); + } + + private void addClassInfo(Map<String, ClassInfo> classMap, Class klass, JarDiff jd, + Method loadInfoMethod) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException { + ClassInfo classInfo = (ClassInfo) loadInfoMethod.invoke(jd, new ClassReader(ClassA.class.getName())); + classMap.put(klass.getName(), classInfo); + } + +} |