www.pudn.com > bluecove-1.2.1-src.zip > APIDeclarationsTester.java, change:2007-01-07,size:15323b
package org.microemu;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassWorld;
public class APIDeclarationsTester extends TestCase {
protected boolean verbose = false;
protected boolean reportOnly = true;
protected boolean reportConstructors = true;
protected boolean reportExtra = true;
private int classDiffCount = 0;
public APIDeclarationsTester() {
}
public APIDeclarationsTester(String name) {
super(name);
}
protected ClassLoader getClassLoader(List jarURLList) throws Exception {
ClassWorld world = new ClassWorld();
ClassRealm containerRealm = world.newRealm("container");
for (Iterator i = jarURLList.iterator(); i.hasNext();) {
containerRealm.addConstituent((URL) i.next());
}
return containerRealm.getClassLoader();
}
protected ClassPool getClassPool(List jarURLList) throws Exception {
ClassPool refClassPool = new ClassPool();
for (Iterator i = jarURLList.iterator(); i.hasNext();) {
refClassPool.appendClassPath(((URL) i.next()).getFile());
}
return refClassPool;
}
protected void verifyClassList(List names, ClassLoader refLoader, ClassLoader implLoader, ClassPool refClassPool)
throws Exception {
for (Iterator i = names.iterator(); i.hasNext();) {
verifyClass(refLoader, implLoader, (String) i.next(), refClassPool);
}
}
protected void verifyClass(ClassLoader refLoader, ClassLoader implLoader, String className, ClassPool refClassPool)
throws Exception {
classDiffCount = 0;
if (verbose) {
System.out.println("Testing class " + className);
}
Class refClass = refLoader.loadClass(className);
Class implClass;
try {
implClass = implLoader.loadClass(className);
} catch (ClassNotFoundException e) {
reportFail(className + " not implemented");
return;
}
String classResourceName = className.replace('.', '/') + ".class";
URL implURL = implLoader.getResource(classResourceName);
URL refURL = refLoader.getResource(classResourceName);
if (verbose) {
System.out.println("Found ref class " + refURL);
System.out.println("Found impl class " + implURL);
}
reportTrue(className + " Reference class not in jar", refURL.toExternalForm().startsWith("jar"));
reportFalse(className + " Implementation and Reference classes are mixed-up", refURL.sameFile(implURL));
compareClasses(refClass, implClass, className, refClassPool);
// if ((classDiffCount > 0) && (!verbose)) {
// System.out.println("Found impl class " + implURL);
// }
}
public void reportFail(String message) {
if (reportOnly) {
System.out.println(message);
classDiffCount++;
} else {
fail(message);
}
}
public void reportTrue(String message, boolean condition) {
try {
assertTrue(message, condition);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportFalse(String message, boolean condition) {
try {
assertFalse(message, condition);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportEquals(String message, boolean expected, boolean actual) {
try {
assertEquals(message, expected, actual);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportEquals(String message, int expected, int actual) {
try {
assertEquals(message, expected, actual);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportEquals(String message, String expected, String actual) {
try {
assertEquals(message, expected, actual);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportNotNull(String message, Object object) {
try {
assertNotNull(message, object);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public void reportNull(String message, Object object) {
try {
assertNull(message, object);
} catch (AssertionFailedError e) {
if (reportOnly) {
System.out.println(e.getMessage());
classDiffCount++;
} else {
throw e;
}
}
}
public static String getSimpleName(Object obj) {
// Java 1.5
// obj.getClass().getSimpleName()
String simpleName = obj.getClass().getName();
// strip the package name
return simpleName.substring(simpleName.lastIndexOf(".") + 1);
}
private void compareClasses(Class refClass, Class implClass, String className, ClassPool refClassPool)
throws Exception {
reportEquals(className + " isInterface", refClass.isInterface(), implClass.isInterface());
reportEquals(className + " getModifiers", refClass.getModifiers(), implClass.getModifiers());
Class[] refInterfaces = refClass.getInterfaces();
Class[] implInterfaces = implClass.getInterfaces();
if (verbose) {
System.out.println("interfaces implemented " + implInterfaces.length);
}
reportEquals(className + " interfaces implemented", refInterfaces.length, implInterfaces.length);
compareInterfaces(refInterfaces, implInterfaces, className);
if (refClass.getSuperclass() != null) {
reportEquals(className + "Superclass", refClass.getSuperclass().getName(), implClass.getSuperclass()
.getName());
} else {
reportNull(className + "Superclass", implClass.getSuperclass());
}
// Constructors
Constructor[] refConstructors = refClass.getDeclaredConstructors();
Constructor[] implConstructors = implClass.getDeclaredConstructors();
compareConstructors(refConstructors, implConstructors, className);
// Methods
Method[] refMethods = refClass.getDeclaredMethods();
Method[] implMethods = implClass.getDeclaredMethods();
compareMethods(refMethods, implMethods, className);
// all accessible public fields
Field[] refFields = refClass.getFields();
Field[] implFields = implClass.getFields();
compareFields(refFields, implFields, className, refClass, implClass, refClassPool);
}
private void compareInterfaces(Class[] refInterfaces, Class[] implInterfacess, String className) throws Exception {
List implNames = new Vector();
for (int i = 0; i implInterfacess.length; i++) {
implNames.add(implInterfacess[i].getName());
}
for (int i = 0; i refInterfaces.length; i++) {
String interfaceName = refInterfaces[i].getName();
reportTrue(className + "Interface " + interfaceName, implNames.contains(interfaceName));
}
}
private Map buildNameMap(Member[] members, String className) throws Exception {
Map namesMap = new Hashtable();
for (int i = 0; i members.length; i++) {
if (ignoreMember(members[i])) {
//System.out.println("ignore " + members[i].getName());
continue;
}
String name = getName4Map(members[i]);
if (namesMap.containsKey(name)) {
Member exists = (Member)namesMap.get(name);
if (exists.getDeclaringClass().getName().equals(className)) {
continue;
}
//throw new Error("duplicate member name " + name + " " + members[i].getName()+ " = " + ((Member)namesMap.get(name)).getName());
}
namesMap.put(name, members[i]);
}
return namesMap;
}
private boolean ignoreMember(Member member) {
if (Modifier.isPublic(member.getModifiers())) {
return false;
} else if (Modifier.isProtected(member.getModifiers())) {
return false;
} else {
return true;
}
}
private int getModifiers(Member member) {
int mod = member.getModifiers();
if (Modifier.isNative(mod)) {
mod = mod - Modifier.NATIVE;
}
return mod;
}
private void compareConstructors(Constructor[] refConstructors, Constructor[] implConstructors, String className)
throws Exception {
Map implNames = buildNameMap(implConstructors, className);
int compared = 0;
for (int i = 0; i refConstructors.length; i++) {
if (ignoreMember(refConstructors[i])) {
continue;
}
compareConstructor(refConstructors[i], (Constructor) implNames.get(getName4Map(refConstructors[i])),
className);
compared++;
implNames.remove(getName4Map(refConstructors[i]));
}
if (!reportConstructors) {
return;
}
reportEquals(className + " number of Constructors ", compared, implNames.size() + compared);
for (Iterator i = implNames.keySet().iterator(); i.hasNext();) {
System.out.println(" extra constructor " + i.next());
}
}
private void compareConstructor(Constructor refConstructor, Constructor implConstructor, String className)
throws Exception {
String name = refConstructor.getName();
reportNotNull(className + " Constructor " + name + " is Missing", implConstructor);
if (implConstructor == null) {
return;
}
reportEquals(className + ". Constructor " + name + " getModifiers", Modifier
.toString(getModifiers(refConstructor)), Modifier.toString(getModifiers(implConstructor)));
}
private void compareMember(Member refMember, Member implMember, String className) throws Exception {
String name = refMember.getName();
reportNotNull(className + "." + name + " is Missing", implMember);
if (implMember == null) {
return;
}
reportEquals(className + "." + name + " getModifiers", Modifier.toString(getModifiers(refMember)), Modifier
.toString(getModifiers(implMember)));
}
private String getName4Map(Member member) {
StringBuffer name = new StringBuffer();
name.append(member.getName());
if ((member instanceof Method) || (member instanceof Constructor)) {
// Overloaded Methods should have different names
Class[] param;
if (member instanceof Method) {
param = ((Method) member).getParameterTypes();
} else if (member instanceof Constructor) {
param = ((Constructor) member).getParameterTypes();
} else {
throw new Error("intenal test error");
}
name.append("(");
for (int i = 0; i param.length; i++) {
if (i != 0) {
name.append(" ,");
}
name.append(param[i].getName());
}
name.append(")");
}
return name.toString();
}
private void compareMethods(Method[] refMethods, Method[] implMethods, String className) throws Exception {
Map implNames = buildNameMap(implMethods, className);
int compared = 0;
for (int i = 0; i refMethods.length; i++) {
if (ignoreMember(refMethods[i])) {
continue;
}
compareMethod(refMethods[i], (Method) implNames.get(getName4Map(refMethods[i])), className);
compared++;
implNames.remove(getName4Map(refMethods[i]));
}
if (!reportExtra) {
return;
}
reportEquals(className + " number of Methods ", compared, implNames.size() + compared);
for (Iterator i = implNames.keySet().iterator(); i.hasNext();) {
System.out.println(" extra method " + i.next());
}
}
private void compareMethod(Method refMethod, Method implMethod, String className) throws Exception {
compareMember(refMethod, implMethod, className);
if (implMethod == null) {
return;
}
String name = refMethod.getName();
reportEquals(className + "." + name + " getReturnType", refMethod.getReturnType().getName(), implMethod
.getReturnType().getName());
}
private void compareFields(Field[] refFields, Field[] implFields, String className, Class refClass,
Class implClass, ClassPool refClassPool) throws Exception {
Map implNames = buildNameMap(implFields, className);
Map implNamesTested = new Hashtable();
int compared = 0;
for (int i = 0; i refFields.length; i++) {
if (ignoreMember(refFields[i])) {
continue;
}
String name = getName4Map(refFields[i]);
if (verbose) {
System.out.println("compareField " + className + "." + refFields[i].getName());
}
Field impl = (Field) implNames.get(name);
if ((impl == null) && (implNamesTested.containsKey(name))) {
continue;
}
compareField(refFields[i], impl, className, refClass, implClass, refClassPool);
compared++;
implNamesTested.put(name, impl);
implNames.remove(name);
}
if (!reportExtra) {
return;
}
reportEquals(className + " number of Fields ", compared, implNames.size() + compared);
for (Iterator i = implNames.keySet().iterator(); i.hasNext();) {
System.out.println(" extra field " + i.next());
}
}
private void compareField(Field refField, Field implField, String className, Class refClass, Class implClass,
ClassPool refClassPool) throws Exception {
String name = refField.getName();
compareMember(refField, implField, className);
if (implField == null) {
return;
}
reportEquals(className + "." + name + " getType", refField.getType().getName(), implField.getType().getName());
if ((Modifier.isFinal(refField.getModifiers())) && (Modifier.isStatic(refField.getModifiers()))) {
// Compare value
CtClass klass = refClassPool.get(className);
CtField field = klass.getField(name);
Object refConstValue = field.getConstantValue();
Object implConstValue = implField.get(implClass);
if (refConstValue == null) {
if (implConstValue != null) {
if (verbose) {
System.out.println("Not implemented comparison for " + refField.getType().getName() + " of "
+ className + "." + name);
}
}
return;
}
String value = refConstValue.toString();
String implValue = null;
if (refField.getType().getName().equals("int")) {
implValue = String.valueOf(implField.getInt(implClass));
} else if (refField.getType().getName().equals("byte")) {
implValue = String.valueOf(implField.getByte(implClass));
} else if (refField.getType().getName().equals("long")) {
implValue = String.valueOf(implField.getLong(implClass));
} else if (refField.getType().getName().equals("java.lang.String")) {
implValue = implField.get(implClass).toString();
} else {
System.out.println("Not implemented comparison for " + refField.getType().getName() + " of "
+ className + "." + name);
}
reportEquals(className + "." + name + " value ", value, implValue);
// //java.lang.UnsatisfiedLinkError: isNetworkMonitorActive
// //at
// javax.microedition.io.Connector.isNetworkMonitorActive(Native
// Method)
// if (refField.getType().getName().equals("int")) {
// reportEquals(className + "." + name + " value ",
// refField.getInt(refClass),
// implField.getInt(implClass));
// } else {
// System.out.println("Not implemented comparison for " +
// refField.getType().getName() + " of " + className + "." + name);
// }
} else {
System.out.println("ignore comparison for " + className + "." + name);
}
}
}