⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basepreverifytestcase.java

📁 eclipseme的最新版本的source,欢迎j2me程序员使用
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * 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 + -