📄 basepreverifytestcase.java
字号:
/**
* Copyright (c) 2003-2004 Craig Setera
* All Rights Reserved.
* Licensed under the Eclipse Public License - v 1.0
* For more information see http://www.eclipse.org/legal/epl-v10.html
*/
package preverification.tests;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import junit.framework.TestCase;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.attrs.StackMapAttribute;
import org.objectweb.asm.attrs.StackMapFrame;
import org.objectweb.asm.attrs.StackMapType;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.SimpleVerifier;
import org.objectweb.asm.util.TraceClassVisitor;
import org.objectweb.asm.util.attrs.ASMStackMapAttribute;
import eclipseme.preverifier.ClassPreverifier;
import eclipseme.preverifier.IPreverificationPolicy;
import eclipseme.preverifier.results.PreverificationResults;
/**
* Type description
* <p />
* Copyright (c) 2003-2004 Craig Setera<br>
* All Rights Reserved.<br>
* Licensed under the Eclipse Public License - v 1.0<p/>
* <br>
* $Revision: 1.7 $
* <br>
* $Date: 2006/02/11 21:26:41 $
* <br>
* @author Craig Setera
*/
public abstract class BasePreverifyTestCase extends TestCase {
public final static String TEST_INPUTS_PROPERTY = "preverify.test.inputs";
public final static String WTK_ROOT_PROPERTY = "preverify.wtk.root";
public final static String CLDC10_LIBS_PROPERTY = "preverify.cldc1_0.libs";
public final static String CLDC11_LIBS_PROPERTY = "preverify.cldc1_1.libs";
public final static String BASE_CLASSPATH_PROPERTY = "base.classpath";
public final static String DISASSEMBLE_OUTPUT = "preverify.disassemble.output";
/** Pump implementation for the output from the preverify process. */
private class ProcessOutputPump extends Thread {
private BufferedReader inputReader;
private PrintStream outputStream;
ProcessOutputPump(String name, InputStream inputStream, PrintStream outputStream) {
super(name);
this.inputReader = new BufferedReader(new InputStreamReader(inputStream));
this.outputStream = outputStream;
setPriority(NORM_PRIORITY - 1);
}
/**
* @see java.lang.Thread#run()
*/
public void run() {
String line = null;
try {
while ((line = inputReader.readLine()) != null) {
outputStream.println(line);
}
inputReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class LabelComparator implements Comparator {
public int compare(Object arg0, Object arg1) {
Label label1 = (Label) arg0;
Label label2 = (Label) arg1;
return label1.getOffset() - label2.getOffset();
}
}
private class LocalVariableComparator implements Comparator {
private LabelComparator labelComparator;
LocalVariableComparator() {
labelComparator = new LabelComparator();
}
public int compare(Object arg0, Object arg1) {
LocalVariableNode var1 = (LocalVariableNode) arg0;
LocalVariableNode var2 = (LocalVariableNode) arg1;
int value = labelComparator.compare(var1.start, var2.start);
if (value == 0) {
value = labelComparator.compare(var1.end, var2.end);
}
if (value == 0) {
value = var1.index - var2.index;
}
if (value == 0) {
value = var1.name.compareTo(var2.name);
}
return value;
}
}
private class TryCatchBlockComparator implements Comparator {
private LabelComparator labelComparator;
TryCatchBlockComparator() {
labelComparator = new LabelComparator();
}
public int compare(Object arg0, Object arg1) {
TryCatchBlockNode blockNode1 = (TryCatchBlockNode) arg0;
TryCatchBlockNode blockNode2 = (TryCatchBlockNode) arg1;
int value = labelComparator.compare(blockNode1.start, blockNode2.start);
if (value == 0) {
value = labelComparator.compare(blockNode1.end, blockNode2.end);
}
if (value == 0) {
value = labelComparator.compare(blockNode1.handler, blockNode2.handler);
}
return value;
}
}
/**
* Regular expression for matching replaceable values within
* a device XML property file.
*/
private static Pattern PROPS_PATTERN = Pattern.compile("\\$\\{(.*?)\\}");
/** An extended preverification policy for testing purposes. */
protected interface TestPreverificationPolicy extends IPreverificationPolicy {
URL[] getLibraries();
String getClasspath();
}
/** CLDC 1.0 Preverification policy */
protected class CLDC_1_0_Policy implements TestPreverificationPolicy {
public boolean areFinalizersAllowed() {
return false;
}
public boolean areNativeMethodsAllowed() {
return false;
}
public boolean isFloatingPointAllowed() {
return false;
}
public boolean isTraceEnabled() {
return true;
}
public URL[] getLibraries() {
return getLibrariesForProperty(CLDC10_LIBS_PROPERTY);
}
public String getClasspath() {
return getClasspathProperty(CLDC10_LIBS_PROPERTY);
}
}
/** CLDC 1.1 Preverification policy */
protected class CLDC_1_1_Policy implements TestPreverificationPolicy {
public boolean areFinalizersAllowed() {
return false;
}
public boolean areNativeMethodsAllowed() {
return false;
}
public boolean isFloatingPointAllowed() {
return true;
}
public boolean isTraceEnabled() {
return true;
}
public URL[] getLibraries() {
return getLibrariesForProperty(CLDC11_LIBS_PROPERTY);
}
public String getClasspath() {
return getClasspathProperty(CLDC11_LIBS_PROPERTY);
}
}
protected String[] getPreverificationOutputs(
TestPreverificationPolicy policy,
String className,
byte[] preverifiedClass)
throws IOException
{
InputStream checkStream = getWTKPreverifiedOutput(policy, className);
ClassNode wtkVerified = getClassNode(checkStream);
sortLocalVariables(wtkVerified);
sortTryCatchBlocks(wtkVerified);
ByteArrayInputStream bis = new ByteArrayInputStream(preverifiedClass);
ClassNode eclipsemeVerified = getClassNode(bis);
sortLocalVariables(eclipsemeVerified);
sortTryCatchBlocks(eclipsemeVerified);
normalizeStackMapAttributeTypes(eclipsemeVerified, wtkVerified);
StringWriter sw1 = new StringWriter();
eclipsemeVerified.accept(new TraceClassVisitor( new PrintWriter( sw1)));
StringWriter sw2 = new StringWriter();
wtkVerified.accept(new TraceClassVisitor( new PrintWriter( sw2)));
return new String[] { sw2.toString(), sw1.toString() };
}
/**
* @param className
* @param preverifiedClass
* @throws FileNotFoundException
*/
protected void compareWithPreverifierBinary(
TestPreverificationPolicy policy,
String className,
byte[] preverifiedClass)
throws IOException
{
String[] outputs = getPreverificationOutputs(policy, className, preverifiedClass);
assertEquals(outputs[0], outputs[1]);
}
/**
* Normalize the stack map attributes of all of the methods to make them match if they are
* valid. ASM creates "tighter" stack map attribute types than the
* WTK preverifier. This method normalizes the stack map attribute
* types to match the WTK output if possible. If not, they are left
* alone to fail during the string comparison.
*
* @param eclipsemeVerified
* @param wtkVerified
*/
private void normalizeStackMapAttributeTypes(ClassNode eclipsemeVerified, ClassNode wtkVerified) {
if (eclipsemeVerified.methods.size() == wtkVerified.methods.size()) {
for (int i = 0; i < eclipsemeVerified.methods.size(); i++) {
MethodNode eclipsemeMethod = (MethodNode) eclipsemeVerified.methods.get(i);
MethodNode wtkMethod = (MethodNode) wtkVerified.methods.get(i);
normalizeStackMapAttributeTypes(eclipsemeMethod, wtkMethod);
}
}
}
/**
* Normalize the stack map attributes of all of the methods to make them match if they are
* valid. ASM creates "tighter" stack map attribute types than the
* WTK preverifier. This method normalizes the stack map attribute
* types to match the WTK output if possible. If not, they are left
* alone to fail during the string comparison.
*
* @param eclipsemeMethod
* @param wtkMethod
*/
private void normalizeStackMapAttributeTypes(MethodNode eclipsemeMethod, MethodNode wtkMethod) {
StackMapAttribute eclipsemeAttr = findStackMapAttribute(eclipsemeMethod);
StackMapAttribute wtkAttr = findStackMapAttribute(wtkMethod);
if ((eclipsemeAttr != null) && (wtkAttr != null)) {
normalizeStackMapAttributeTypes(eclipsemeAttr, wtkAttr);
}
}
/**
* Normalize the stack map attributes of all of the methods to make them match if they are
* valid. ASM creates "tighter" stack map attribute types than the
* WTK preverifier. This method normalizes the stack map attribute
* types to match the WTK output if possible. If not, they are left
* alone to fail during the string comparison.
*
* @param eclipsemeAttr
* @param wtkAttr
*/
private void normalizeStackMapAttributeTypes(StackMapAttribute eclipsemeAttr, StackMapAttribute wtkAttr) {
if (eclipsemeAttr.getFrames().size() == wtkAttr.getFrames().size()) {
for (int i = 0; i < eclipsemeAttr.getFrames().size(); i++) {
StackMapFrame eclipsemeFrame = (StackMapFrame) eclipsemeAttr.getFrames().get(i);
StackMapFrame wtkFrame = (StackMapFrame) wtkAttr.getFrames().get(i);
normalizeStackMapAttributeTypes(eclipsemeFrame, wtkFrame);
}
}
}
/**
*
* @param eclipsemeFrame
* @param wtkFrame
*/
private void normalizeStackMapAttributeTypes(StackMapFrame eclipsemeFrame, StackMapFrame wtkFrame) {
eclipsemeFrame.locals =
normalizeStackMapAttributeTypes(eclipsemeFrame.locals, wtkFrame.locals);
normalizeStackMapAttributeTypes(eclipsemeFrame.stack, wtkFrame.stack);
}
/**
*
* @param eclipsemeTypes
* @param wtkTypes
*/
private List normalizeStackMapAttributeTypes(List eclipsemeTypes, List wtkTypes) {
List normalizedTypes = eclipsemeTypes;
if (eclipsemeTypes.size() == wtkTypes.size()) {
normalizedTypes = new ArrayList(normalizedTypes.size());
for (int i = 0; i < eclipsemeTypes.size(); i++) {
StackMapType eclipsemeType = (StackMapType) eclipsemeTypes.get(i);
StackMapType wtkType = (StackMapType) wtkTypes.get(i);
normalizedTypes.add(normalizeStackMapAttributeType(eclipsemeType, wtkType));
}
}
return normalizedTypes;
}
/**
* Normalize the specified stack map type if posssible.
*
* @param eclipsemeType
* @param wtkType
* @return
*/
private StackMapType normalizeStackMapAttributeType(StackMapType eclipsemeType, StackMapType wtkType) {
StackMapType normalized = eclipsemeType;
if (
(eclipsemeType.getType() == StackMapType.ITEM_Object) &&
(wtkType.getType() == StackMapType.ITEM_Object) &&
!wtkType.getObject().equals(eclipsemeType.getObject()))
{
try {
Class eclipsemeClass = Class.forName(eclipsemeType.getObject().replace('/', '.'));
Class wtkClass = Class.forName(wtkType.getObject().replace('/', '.'));
if (isSubclass(eclipsemeClass, wtkClass)) {
normalized = wtkType;
}
} catch (ClassNotFoundException e) { }
}
return normalized;
}
/**
* Return a boolean indicating whether or not the specified eclipseme class
* is a subclass of the specified wtk class.
*
* @param eclipsemeClass
* @param wtkClass
* @return
*/
private boolean isSubclass(Class eclipsemeClass, Class wtkClass) {
boolean isSubclass = false;
Class superClass = eclipsemeClass.getSuperclass();
if (superClass.equals(wtkClass)) {
isSubclass = true;
} else if (superClass.getName().equals("java.lang.Object")) {
isSubclass = false;
} else {
isSubclass(superClass, wtkClass);
}
return isSubclass;
}
/**
* Find the stack map attribute if there is one.
*
* @param method
* @return
*/
private StackMapAttribute findStackMapAttribute(MethodNode method) {
StackMapAttribute stackMapAttribute = null;
if (method.attrs != null) {
Iterator attrs = method.attrs.iterator();
while (attrs.hasNext()) {
Attribute attr = (Attribute) attrs.next();
if (attr instanceof StackMapAttribute) {
stackMapAttribute = (StackMapAttribute) attr;
}
}
}
return stackMapAttribute;
}
/**
* Sort the try catch blocks so that the string output matches.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -