package com.coderising.jvm.test; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.coderising.jvm.attribute.CodeAttr; import com.coderising.jvm.clasfile.ClassFile; import com.coderising.jvm.clasfile.ClassIndex; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.MethodInfo; import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.Utf8Info; import com.coderising.jvm.field.JField; import com.coderising.jvm.loader.ClassFileLoader; import com.coderising.jvm.method.JMethod; public class ClassFileLoaderTest { private static String path1 = "D:\\MyTest\\mini-jvm\\bin"; private static String path2 = "C:\\temp"; private final static String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; private static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); String className = "com.coderising.jvm.test.EmployeeV1"; clzFile = loader.loadClass(className); } @Before public void setUp() throws Exception { } @Test public void test() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); loader.addClassPath(path2); String clzPath = loader.getClassPath(); Assert.assertEquals(path1 + ";" + path2, clzPath); } @Test public void ClassFileLengthTest() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); String className = "com.coderising.jvm.test.EmployeeV1"; byte[] bytes = loader.readBinaryCode(className); Assert.assertEquals(1056, bytes.length); } @Test public void MagicNumberTest() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); String className = "com.coderising.jvm.test.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); byte[] bytes = { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; String actualString = byteToHexString(bytes); Assert.assertEquals("cafebabe", actualString); } private String byteToHexString(byte[] bytes) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; int value = b & 0xFF; String strHex = Integer.toHexString(value); if (strHex.length() < 2) { strHex = "0" + strHex; } buffer.append(strHex); } return buffer.toString(); } @Test public void testVersion() { Assert.assertEquals(0, clzFile.getMinorVersion()); Assert.assertEquals(51, clzFile.getMajorVersion()); } @Test public void testConstant��ool() { ConstantPool pool = clzFile.getPool(); Assert.assertEquals(53, pool.getConstantNumber()); { ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); Assert.assertEquals(2, clzInfo.getUtf8Index()); Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(2); Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); } { ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); Assert.assertEquals(4, clzInfo.getUtf8Index()); Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(4); Assert.assertEquals("java/lang/Object", utf8Info.getValue()); } { Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(5); Assert.assertEquals("name", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(6); Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(7); Assert.assertEquals("age", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(8); Assert.assertEquals("I", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(9); Assert.assertEquals("<init>", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(10); Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); utf8Info = (Utf8Info) pool.getConstantInfo(11); Assert.assertEquals("Code", utf8Info.getValue()); } { MethodInfo methodRef = (MethodInfo) pool.getConstantInfo(12); Assert.assertEquals(3, methodRef.getIndex_ClassInfo()); Assert.assertEquals(13, methodRef.getIndex_NameAndType()); } { NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool .getConstantInfo(13); Assert.assertEquals(9, nameAndTypeInfo.getIndex_Name()); Assert.assertEquals(14, nameAndTypeInfo.getIndex_Describe()); } { MethodInfo methodRef = (MethodInfo) pool.getConstantInfo(45); Assert.assertEquals(1, methodRef.getIndex_ClassInfo()); Assert.assertEquals(46, methodRef.getIndex_NameAndType()); } { Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(53); Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); } { FieldRefInfo fieldRefInfo = (FieldRefInfo) pool.getConstantInfo(28); Assert.assertEquals(29, fieldRefInfo.getIndex_ClassInfo()); Assert.assertEquals(31, fieldRefInfo.getIndex_NameAndType()); } } @Test public void testClassIndex() { ClassIndex clzIndex = clzFile.getClassIndex(); ClassInfo thisClassInfo = (ClassInfo) clzFile.getPool() .getConstantInfo(clzIndex.getThisClassIndex()); ClassInfo superClassInfo = (ClassInfo) clzFile.getPool() .getConstantInfo(clzIndex.getSuperClassIndex()); Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); } /** * ������JVM������ʵ�ֲ��� */ @Test public void testReadFields() { List<JField> jfields = clzFile.getJFields(); Assert.assertEquals(2, jfields.size()); { JField jfield = jfields.get(0); Assert.assertEquals("name:Ljava/lang/String;", jfield.toString()); } { JField jfield = jfields.get(1); Assert.assertEquals("age:I", jfield.toString()); } } @Test public void testMethod() { List<JMethod> jMethods = clzFile.getMethods(); ConstantPool pool = clzFile.getPool(); { JMethod jMethod = jMethods.get(0); assertJMethodEquals(pool, jMethod, "<init>", "(Ljava/lang/String;I)V", "2ab7000c2a2bb5000f2a1cb50011b1"); } { JMethod jMethod = jMethods.get(1); assertJMethodEquals(pool,jMethod, "setName", "(Ljava/lang/String;)V", "2a2bb5000fb1"); } { JMethod jMethod = jMethods.get(2); assertJMethodEquals(pool,jMethod, "setAge", "(I)V", "2a1bb50011b1"); } { JMethod jMethod = jMethods.get(3); assertJMethodEquals(pool,jMethod, "sayHello", "()V", "b2001c1222b60024b1"); } { JMethod jMethod = jMethods.get(4); assertJMethodEquals(pool,jMethod, "main", "([Ljava/lang/String;)V", "bb000159122b101db7002d4c2bb6002fb1"); } } private void assertJMethodEquals(ConstantPool pool, JMethod jMethod, String expectedName, String expectedDescrib, String expectedCode) { String methodNameString = pool.getUtf8String(jMethod.getName_index()); String realDescrib = pool.getUtf8String(jMethod.getDescriptor_index()); String realCode = jMethod.getCodeAttr().getCodeString(); Assert.assertEquals(expectedName, methodNameString); Assert.assertEquals(expectedDescrib, realDescrib); Assert.assertEquals(expectedCode, realCode); } }