Index: src/main/java/org/apache/harmony/pack200/AttributeLayout.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayout.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/AttributeLayout.java (working copy) @@ -157,15 +157,7 @@ return Codec.SIGNED5; } else if (layout.indexOf("B") >= 0) { //$NON-NLS-1$ return Codec.BYTE1; - } - /* - * TODO Add this as a test (and don't commit since this is copyright - * text) && ) If the layout contains 'O', use BRANCH5. Otherwise, if the - * layout contains 'P', use BCI5. Otherwise, if the layout contains 'S' - * but not 'KS' or 'RS', use SIGNED5. Otherwise, if the layout contains - * 'B', use BYTE1. For all other layouts use UNSIGNED5. - */ - else { + } else { return Codec.UNSIGNED5; } } Index: src/main/java/org/apache/harmony/pack200/BandSet.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BandSet.java (revision 588229) +++ src/main/java/org/apache/harmony/pack200/BandSet.java (working copy) @@ -194,10 +194,10 @@ result[i] = new long[counts[i]]; sum += counts[i]; } - int[] hi = null; + long[] hi = null; int[] lo; if(hiCodec != null) { - hi = decodeBandInt(name, in, hiCodec, sum); + hi = decodeBandLong(name, in, hiCodec, sum); lo = decodeBandInt(name, in, loCodec, sum); } else { lo = decodeBandInt(name, in, loCodec, sum); Index: src/main/java/org/apache/harmony/pack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 588229) +++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy) @@ -20,11 +20,12 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Arrays; +import org.apache.harmony.pack200.IcBands.ICTuple; import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.ConstantValueAttribute; import org.apache.harmony.pack200.bytecode.ExceptionsAttribute; +import org.apache.harmony.pack200.bytecode.SourceFileAttribute; /** * @@ -44,6 +45,12 @@ private String[] classThis; private ArrayList[] classAttributes; + + private int[] classVersionMajor; + + private int[] classVersionMinor; + + private IcBands.ICTuple[][] icLocal; private int[] codeHandlerCount; @@ -51,8 +58,6 @@ private int[] codeMaxStack; - private int fieldAttrCount; - private ArrayList[][] fieldAttributes; private String[][] fieldDescr; @@ -59,13 +64,9 @@ private long[][] fieldFlags; - private int methodAttrCount; - private ArrayList[][] methodAttributes; private String[][] methodDescr; - - private ExceptionsAttribute[][] methodExceptions; private long[][] methodFlags; @@ -134,13 +135,7 @@ classFieldCount, cpBands.getCpDescriptor()); fieldFlags = parseFlags("field_flags", in, classFieldCount, Codec.UNSIGNED5, options.hasFieldFlagsHi()); - for (int i = 0; i < fieldFlags.length; i++) { - for (int j = 0; j < fieldFlags[i].length; j++) { - long flag = fieldFlags[i][j]; - if ((flag & (1 << 16)) != 0) - fieldAttrCount++; - } - } + int fieldAttrCount = SegmentUtils.countBit16(fieldFlags); int[] fieldAttrCounts = decodeBandInt("field_attr_count", in, Codec.UNSIGNED5, fieldAttrCount); int[][] fieldAttrIndexes = decodeBandInt("field_attr_indexes", in, Codec.UNSIGNED5, fieldAttrCounts); int callCount = 0; @@ -151,71 +146,63 @@ callCount += layout.numBackwardsCallables(); } } - int[] fieldAttrCalls = decodeBandInt("field_attr_calls", in, Codec.UNSIGNED5, callCount); - AttributeLayout layout = attrMap.getAttributeLayout("ConstantValue", - AttributeLayout.CONTEXT_FIELD); - int constantCount = SegmentUtils.countMatches(fieldFlags, layout); - if(constantCount > 0) { - int[] field_constantValue_KQ = decodeBandInt("field_ConstantValue_KQ", in, Codec.UNSIGNED5, constantCount); - int index = 0; - fieldAttributes = new ArrayList[classCount][]; - for (int i = 0; i < classCount; i++) { - fieldAttributes[i] = new ArrayList[fieldFlags[i].length]; - for (int j = 0; j < fieldFlags[i].length; j++) { - fieldAttributes[i][j] = new ArrayList(); - long flag = fieldFlags[i][j]; - if (layout.matches(flag)) { - // we've got a value to read - long result = field_constantValue_KQ[index]; - String desc = fieldDescr[i][j]; - int colon = desc.indexOf(':'); - // String name = desc.substring(0, colon); - String type = desc.substring(colon + 1); - // TODO Got to get better at this ... in any case, it should - // be e.g. KIB or KIH - if (type.equals("B") || type.equals("H")) - type = "I"; - Object value = layout.getValue(result, type, cpBands - .getConstantPool()); - fieldAttributes[i][j] - .add(new ConstantValueAttribute(value)); - debug("Processed value " + value + " for ConstantValue"); - index++; - } - } + int layoutsUsed = 0; + for (int i = 0; i < fieldFlags.length; i++) { + for (int j = 0; j < fieldFlags[i].length; j++) { + layoutsUsed |= fieldFlags[i][j]; + } + } + for (int i = 0; i < 16; i++) { + if((layoutsUsed & 1< 0) { - int[] fieldSignatureRS = decodeBandInt("field_Signature_RS", in, Codec.UNSIGNED5, signatureCount); - int index = 0; - fieldAttributes = new ArrayList[classCount][]; - for (int i = 0; i < classCount; i++) { - fieldAttributes[i] = new ArrayList[fieldFlags[i].length]; - for (int j = 0; j < fieldFlags[i].length; j++) { - fieldAttributes[i][j] = new ArrayList(); - long flag = fieldFlags[i][j]; - if (layout.matches(flag)) { - // we've got a signature attribute - long result = fieldSignatureRS[index]; - String desc = fieldDescr[i][j]; - int colon = desc.indexOf(':'); - // String name = desc.substring(0, colon); - String type = desc.substring(colon + 1); - // TODO Got to get better at this ... in any case, it should - // be e.g. KIB or KIH - if (type.equals("B") || type.equals("H")) - type = "I"; - Object value = layout.getValue(result, type, cpBands - .getConstantPool()); - fieldAttributes[i][j] - .add(new ConstantValueAttribute(value)); - index++; - debug("Found a signature attribute: " + result); - } + int constantCount = SegmentUtils.countMatches(fieldFlags, constantValueLayout); + int[] field_constantValue_KQ = decodeBandInt("field_ConstantValue_KQ", in, Codec.UNSIGNED5, constantCount); + int constantValueIndex = 0; + + AttributeLayout signatureLayout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, + AttributeLayout.CONTEXT_FIELD); + int signatureCount = SegmentUtils.countMatches(fieldFlags, signatureLayout); + int[] fieldSignatureRS = decodeBandInt("field_Signature_RS", in, Codec.UNSIGNED5, signatureCount); + int signatureIndex = 0; + + fieldAttributes = new ArrayList[classCount][]; + for (int i = 0; i < classCount; i++) { + fieldAttributes[i] = new ArrayList[fieldFlags[i].length]; + for (int j = 0; j < fieldFlags[i].length; j++) { + fieldAttributes[i][j] = new ArrayList(); + long flag = fieldFlags[i][j]; + if (constantValueLayout.matches(flag)) { + // we've got a value to read + long result = field_constantValue_KQ[constantValueIndex]; + String desc = fieldDescr[i][j]; + int colon = desc.indexOf(':'); + String type = desc.substring(colon + 1); + if (type.equals("B") || type.equals("S") || type.equals("C") || type.equals("Z")) + type = "I"; + Object value = constantValueLayout.getValue(result, type, + cpBands.getConstantPool()); + fieldAttributes[i][j] + .add(new ConstantValueAttribute(value)); + constantValueIndex++; + } + if (signatureLayout.matches(flag)) { + // we've got a signature attribute + long result = fieldSignatureRS[signatureIndex]; + String desc = fieldDescr[i][j]; + int colon = desc.indexOf(':'); + String type = desc.substring(colon + 1); + Object value = signatureLayout.getValue(result, type, cpBands + .getConstantPool()); + fieldAttributes[i][j] + .add(new ConstantValueAttribute(value)); + signatureIndex++; } } } @@ -228,13 +215,8 @@ classMethodCount, cpBands.getCpDescriptor()); methodFlags = parseFlags("method_flags", in, classMethodCount, Codec.UNSIGNED5, options.hasMethodFlagsHi()); - for (int i = 0; i < classCount; i++) { - for (int j = 0; j < methodFlags[i].length; j++) { - long flag = methodFlags[i][j]; - if ((flag & (1 << 16)) != 0) - methodAttrCount++; - } - } + + int methodAttrCount = SegmentUtils.countBit16(methodFlags); int[] methodAttrCounts = decodeBandInt("method_attr_count", in, Codec.UNSIGNED5, methodAttrCount); int[][] methodAttrIndexes = decodeBandInt("method_attr_indexes", in, Codec.UNSIGNED5, methodAttrCounts); int callCount = 0; @@ -246,6 +228,7 @@ } } methodAttrCalls = decodeBandInt("code_attr_calls", in, Codec.UNSIGNED5, callCount); + // assign empty method attributes methodAttributes = new ArrayList[classCount][]; for (int i = 0; i < classCount; i++) { @@ -273,7 +256,6 @@ long result = methodSignatureRS[index]; String desc = methodDescr[i][j]; int colon = desc.indexOf(':'); - // String name = desc.substring(0, colon); String type = desc.substring(colon + 1); // TODO Got to get better at this ... in any case, it should // be e.g. KIB or KIH @@ -284,7 +266,6 @@ methodAttributes[i][j] .add(new ConstantValueAttribute(value)); index++; - debug("Found a signature attribute: " + result); } } } @@ -299,7 +280,6 @@ throws Pack200Exception, IOException { AttributeLayout layout = attrMap.getAttributeLayout("Exceptions", AttributeLayout.CONTEXT_METHOD); - methodExceptions = new ExceptionsAttribute[classCount][]; int count = SegmentUtils.countMatches(methodFlags, layout); int[] numExceptions = decodeBandInt("method_Exceptions_n", in, Codec.UNSIGNED5, count); String[][] methodExceptionsRS = parseReferences("method_Exceptions_RC", in, Codec.UNSIGNED5, numExceptions, cpBands.getCpClass()); @@ -305,7 +285,6 @@ String[][] methodExceptionsRS = parseReferences("method_Exceptions_RC", in, Codec.UNSIGNED5, numExceptions, cpBands.getCpClass()); int index = 0; for (int i = 0; i < classCount; i++) { - methodExceptions[i] = new ExceptionsAttribute[methodFlags[i].length]; for (int j = 0; j < methodFlags[i].length; j++) { long flag = methodFlags[i][j]; if(layout.matches(flag)) { @@ -315,8 +294,7 @@ for (int k = 0; k < n; k++) { exceptionClasses[k] = new CPClass(exceptions[k]); } - methodExceptions[i][j] = new ExceptionsAttribute(exceptionClasses); - methodAttributes[i][j].add(methodExceptions[i][j]); + methodAttributes[i][j].add(new ExceptionsAttribute(exceptionClasses)); index ++; } } @@ -325,14 +303,12 @@ private void parseClassAttrBands(InputStream in) throws IOException, Pack200Exception { + String[] cpUTF8 = cpBands.getCpUTF8(); + String[] cpClass = cpBands.getCpClass(); + classFlags = parseFlags("class_flags", in, classCount, Codec.UNSIGNED5, options.hasClassFlagsHi()); - int classAttrCount = 0; - for (int i = 0; i < classFlags.length; i++) { - long flag = classFlags[i]; - if ((flag & (1 << 16)) != 0) - classAttrCount++; - } + int classAttrCount = SegmentUtils.countBit16(classFlags); int[] classAttrCounts = decodeBandInt("class_attr_count", in, Codec.UNSIGNED5, classAttrCount); int[][] classAttrIndexes = decodeBandInt("class_attr_indexes", in, Codec.UNSIGNED5, classAttrCounts); int callCount = 0; @@ -402,7 +378,12 @@ "class_file_version_minor_H", in, Codec.UNSIGNED5, versionCount); int[] classFileVersionMajorH = decodeBandInt( "class_file_version_major_H", in, Codec.UNSIGNED5, versionCount); - + if(versionCount > 0) { + classVersionMajor = new int[classCount]; + classVersionMinor = new int[classCount]; + } + int defaultVersionMajor = header.getDefaultClassMajorVersion(); + int defaultVersionMinor = header.getDefaultClassMinorVersion(); // Now process the attribute bands we have parsed int sourceFileIndex = 0; @@ -409,32 +390,87 @@ int enclosingMethodIndex = 0; int signatureIndex = 0; int innerClassIndex = 0; + int innerClassC2NIndex = 0; int versionIndex = 0; classAttributes = new ArrayList[classCount]; + icLocal = new IcBands.ICTuple[classCount][]; for (int i = 0; i < classCount; i++) { classAttributes[i] = new ArrayList(); long flag = classFlags[i]; + if (sourceFileLayout.matches(flag)) { long result = classSourceFile[sourceFileIndex]; - // we've got a value to read - // TODO File this as a sourcefile attribute and don't generate - // everything below - Object value = sourceFileLayout.getValue(result, cpBands + String value = (String) sourceFileLayout.getValue(result, cpBands .getConstantPool()); - debug("Processed value " + value + " for SourceFile"); + if(value == null) { + // Remove package prefix + String className = classThis[i].substring(classThis[i].lastIndexOf('/') + 1); + className = className.substring(className.lastIndexOf('.') + 1); + + // Remove mangled nested class names + char[] chars = className.toCharArray(); + int index = -1; + for (int j = 0; j < chars.length; j++) { + if(chars[j] <= 0x2D) { + index = j; + break; + } + } + if(index > -1) { + className = className.substring(0, index); + } + // Add .java to the end + value = className + ".java"; + } + classAttributes[i].add(new SourceFileAttribute(value)); sourceFileIndex++; } if(enclosingMethodLayout.matches(flag)) { - // TODO +// long result = } if(signatureLayout.matches(flag)) { -// TODO + long result = classSignature[signatureIndex]; + Object value = signatureLayout.getValue(result, cpBands + .getConstantPool()); + classAttributes[i].add(new ConstantValueAttribute(value)); + signatureIndex++; } if(innerClassLayout.matches(flag)) { - // TODO + // Just create the tuples for now because the attributes are + // decided at the end when creating class constant pools + icLocal[i] = new IcBands.ICTuple[classInnerClassesN[innerClassIndex]]; + for (int j = 0; j < icLocal[i].length; j++) { + IcBands.ICTuple icTuple = new IcBands.ICTuple(); + icTuple.C = cpClass[classInnerClassesRC[innerClassIndex][j]]; + icTuple.F = classInnerClassesF[innerClassIndex][j]; + if(icTuple.F != 0) { + icTuple.C2 = cpClass[classInnerClassesOuterRCN[innerClassC2NIndex]]; + icTuple.N = cpUTF8[classInnerClassesNameRUN[innerClassC2NIndex]]; + innerClassC2NIndex++; + } else { + // Get from icBands + IcBands icBands = segment.getIcBands(); + ICTuple[] icAll = icBands.getIcTuples(); + for (int k = 0; k < icAll.length; k++) { + if(icAll[k].C.equals(icTuple.C)) { + icTuple.C2 = icAll[k].C2; + icTuple.N = icAll[k].N; + break; + } + } + } + icLocal[i][j] = icTuple; + } + innerClassIndex++; } if(versionLayout.matches(flag)) { - // TODO + classVersionMajor[i] = classFileVersionMajorH[versionIndex]; + classVersionMinor[i] = classFileVersionMinorH[versionIndex]; + versionIndex++; + } else if(classVersionMajor != null) { + // Fill in with defaults + classVersionMajor[i] = defaultVersionMajor; + classVersionMinor[i] = defaultVersionMinor; } } } @@ -505,12 +541,7 @@ private void parseCodeAttrBands(InputStream in, int codeFlagsCount) throws IOException, Pack200Exception { long[] codeFlags = parseFlags("code_flags", in, codeFlagsCount, Codec.UNSIGNED5, segment.getSegmentHeader().getOptions().hasCodeFlagsHi()); - int codeAttrCount = 0; - for (int i = 0; i < codeFlagsCount; i++) { - long flag = codeFlags[i]; - if ((flag & (1 << 16)) != 0) - codeAttrCount++; - } + int codeAttrCount = SegmentUtils.countBit16(codeFlags); int[] codeAttrCounts = decodeBandInt("code_attr_count", in, Codec.UNSIGNED5, codeAttrCount); int[][] codeAttrIndexes = decodeBandInt("code_attr_indexes", in, Codec.UNSIGNED5, codeAttrCounts); int callCount = 0; @@ -731,10 +762,6 @@ return codeMaxStack; } - public int getFieldAttrCount() { - return fieldAttrCount; - } - public ArrayList[][] getFieldAttributes() { return fieldAttributes; } @@ -755,10 +782,6 @@ return methodDescr; } - public ExceptionsAttribute[][] getMethodExceptions() { - return methodExceptions; - } - public long[][] getMethodFlags() { return methodFlags; } @@ -763,4 +786,26 @@ return methodFlags; } + /** + * Returns null if all classes should use the default major and minor + * version or an array of integers containing the major version numberss to + * use for each class in the segment + * + * @return Class file major version numbers, or null if none specified + */ + public int[] getClassVersionMajor() { + return classVersionMajor; + } + + /** + * Returns null if all classes should use the default major and minor + * version or an array of integers containing the minor version numberss to + * use for each class in the segment + * + * @return Class file minor version numbers, or null if none specified + */ + public int[] getClassVersionMinor() { + return classVersionMinor; + } + } Index: src/main/java/org/apache/harmony/pack200/Codec.java =================================================================== --- src/main/java/org/apache/harmony/pack200/Codec.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/Codec.java (working copy) @@ -91,8 +91,7 @@ * assumes that other combinations of values can result in more specific and * efficient formats. There are also a sequence of canonical encodings defined * by the Pack200 specification, which allow a codec to be referred to by - * canonical number. TODO Add links to canonical numbers when this has been - * done. + * canonical number. {@link CodecEncoding#canonicalCodec}) */ public abstract class Codec { /** Index: src/main/java/org/apache/harmony/pack200/FileBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/FileBands.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/FileBands.java (working copy) @@ -19,7 +19,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Arrays; /** * Parses the file band headers (not including the actual bits themselves). @@ -28,7 +27,6 @@ * remaining in the stream with BYTE1 compression. A decent implementation * will probably just stream the bytes out to the reconstituted Jar rather * than caching them. - * */ public class FileBands extends BandSet { @@ -94,9 +92,8 @@ fileBits = new byte[numberOfFiles][]; for (int i = 0; i < numberOfFiles; i++) { int size = (int) fileSize[i]; - // TODO This buggers up if file_size > 2^32. Probably an array is - // not the right choice, and - // we should just serialize the bugger here? + // TODO This breaks if file_size > 2^32. Probably an array is + // not the right choice, and we should just serialize it here? fileBits[i] = new byte[size]; for (int j = 0; j < size; j++) { fileBits[i][j] = (byte) Codec.BYTE1.decode(in); Index: src/main/java/org/apache/harmony/pack200/IcBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/IcBands.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/IcBands.java (working copy) @@ -21,17 +21,20 @@ import java.io.OutputStream; /** - * + * Pack200 Inner Class Bands */ public class IcBands extends BandSet { - private int[] icFlags; + public static class ICTuple { - private Object icName; + public String C; // this class + public int F; // flags + public String C2; // outer class + public String N; // name - private String[] icOuterClass; + } - private String[] icThisClass; + private ICTuple[] icAll; private String[] cpUTF8; @@ -59,19 +62,35 @@ */ public void unpack(InputStream in) throws IOException, Pack200Exception { + // Read IC bands int innerClassCount = header.getInnerClassCount(); - icThisClass = parseReferences("ic_this_class", in, Codec.UDELTA5, + String[] icThisClass = parseReferences("ic_this_class", in, Codec.UDELTA5, innerClassCount, cpClass); - icFlags = decodeBandInt("ic_flags", in, Codec.UNSIGNED5, innerClassCount); - int outerClasses = 0; - for (int i = 0; i < innerClassCount; i++) { - if ((icFlags[i] & 1 << 16) != 0) - outerClasses++; - } - icOuterClass = parseReferences("ic_outer_class", in, Codec.DELTA5, + int[] icFlags = decodeBandInt("ic_flags", in, Codec.UNSIGNED5, innerClassCount); + int outerClasses = SegmentUtils.countBit16(icFlags); + String[] icOuterClass = parseReferences("ic_outer_class", in, Codec.DELTA5, outerClasses, cpClass); - icName = parseReferences("ic_name", in, Codec.DELTA5, outerClasses, + String[] icName = parseReferences("ic_name", in, Codec.DELTA5, outerClasses, cpUTF8); + + // Construct IC tuples + icAll = new ICTuple[icThisClass.length]; + int index = 0; + for (int i = 0; i < icThisClass.length; i++) { + icAll[i] = new ICTuple(); + icAll[i].C = icThisClass[i]; + icAll[i].F = icFlags[i]; + if((icFlags[i] & 1<<16) != 0) { + icAll[i].C2 = icOuterClass[index]; + icAll[i].N = icName[index]; + index++; + } + } } -} + public ICTuple[] getIcTuples() { + return icAll; + } + + +} \ No newline at end of file Index: src/main/java/org/apache/harmony/pack200/PopulationCodec.java =================================================================== --- src/main/java/org/apache/harmony/pack200/PopulationCodec.java (revision 588229) +++ src/main/java/org/apache/harmony/pack200/PopulationCodec.java (working copy) @@ -18,7 +18,6 @@ import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; public class PopulationCodec extends Codec { private Codec favouredCodec; @@ -53,7 +52,7 @@ public long[] decode(int n, InputStream in) throws IOException, Pack200Exception { - long favoured[] =new long[n]; // there must be <= n values, but probably a lot less + long favoured[] = new long[n]; // there must be <= n values, but probably a lot less long result[]; // read table of favorites first long smallest = Long.MAX_VALUE; @@ -90,8 +89,8 @@ } } // read favorites - result = tokenCodec.decode(n, in); - // read unfavorites + result = tokenCodec.decode(n, in); + // read unfavorites last = 0; for(int i = 0; i < n; i++) { int index = (int) result[i]; Index: src/main/java/org/apache/harmony/pack200/SegmentUtils.java =================================================================== --- src/main/java/org/apache/harmony/pack200/SegmentUtils.java (revision 565676) +++ src/main/java/org/apache/harmony/pack200/SegmentUtils.java (working copy) @@ -18,6 +18,7 @@ // TODO Write doc public final class SegmentUtils { + public static int countArgs(String descriptor) { int bra = descriptor.indexOf("("); int ket = descriptor.indexOf(")"); @@ -50,6 +51,35 @@ } return count; } + + public static int countBit16(int[] flags) { + int count = 0; + for (int i = 0; i < flags.length; i++) { + if ((flags[i] & (1 << 16)) != 0) + count++; + } + return count; + } + + public static int countBit16(long[] flags) { + int count = 0; + for (int i = 0; i < flags.length; i++) { + if ((flags[i] & (1 << 16)) != 0) + count++; + } + return count; + } + + public static int countBit16(long[][] flags) { + int count = 0; + for (int i = 0; i < flags.length; i++) { + for (int j = 0; j < flags[i].length; j++) { + if ((flags[i][j] & (1 << 16)) != 0) + count++; + } + } + return count; + } public static int countMatches(long[][] flags, IMatcher matcher) { int count = 0; Index: src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java (revision 587112) +++ src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java (working copy) @@ -19,6 +19,7 @@ import junit.framework.TestCase; import org.apache.harmony.pack200.AttributeLayout; +import org.apache.harmony.pack200.Codec; import org.apache.harmony.pack200.Pack200Exception; import org.apache.harmony.pack200.Segment; import org.apache.harmony.pack200.SegmentConstantPool; @@ -24,6 +25,7 @@ import org.apache.harmony.pack200.SegmentConstantPool; public class AttributeLayoutTest extends TestCase { + public class TestSegment extends Segment { public SegmentConstantPool getConstantPool() { final Object[][] data = new Object[][] { @@ -41,6 +43,7 @@ }; } } + public void testBadData() { assertTrue(throwsException(null,AttributeLayout.CONTEXT_CLASS,"")); assertTrue(throwsException("",AttributeLayout.CONTEXT_CLASS,"")); @@ -51,6 +54,7 @@ assertTrue(throwsException("name",-1,"")); assertTrue(throwsException("name",1234,"")); } + public void testLayoutRU() throws Pack200Exception { AttributeLayout layout = new AttributeLayout("RU",AttributeLayout.CONTEXT_CLASS,"RU", 1); Segment segment = new TestSegment(); @@ -58,6 +62,7 @@ assertEquals("Zero",layout.getValue(0, segment.getConstantPool())); assertEquals("One",layout.getValue(1, segment.getConstantPool())); } + public void testLayoutRUN() throws Pack200Exception { AttributeLayout layout = new AttributeLayout("RUN",AttributeLayout.CONTEXT_CLASS,"RUN", 1); Segment segment = new TestSegment(); @@ -65,6 +70,7 @@ assertEquals("Zero",layout.getValue(1, segment.getConstantPool())); assertEquals("One",layout.getValue(2, segment.getConstantPool())); } + public void testLayoutRS() throws Pack200Exception { AttributeLayout layout = new AttributeLayout("RS",AttributeLayout.CONTEXT_CLASS,"RS", 1); Segment segment = new TestSegment(); @@ -72,7 +78,8 @@ assertEquals("Ein",layout.getValue(0, segment.getConstantPool())); assertEquals("Zwei",layout.getValue(1, segment.getConstantPool())); } - public void testLayoutRSN() throws Pack200Exception { + + public void testLayoutRSN() throws Pack200Exception { AttributeLayout layout = new AttributeLayout("RSN",AttributeLayout.CONTEXT_CLASS,"RSN", 1); Segment segment = new TestSegment(); assertNull(layout.getValue(0, segment.getConstantPool())); @@ -79,6 +86,22 @@ assertEquals("Ein",layout.getValue(1, segment.getConstantPool())); assertEquals("Zwei",layout.getValue(2, segment.getConstantPool())); } + + public void testGetCodec() throws Pack200Exception { + AttributeLayout layout = new AttributeLayout("O", AttributeLayout.CONTEXT_CLASS, "HOBS", 1); + assertEquals(Codec.BRANCH5, layout.getCodec()); + layout = new AttributeLayout("P", AttributeLayout.CONTEXT_METHOD, "PIN", 1); + assertEquals(Codec.BCI5, layout.getCodec()); + layout = new AttributeLayout("S", AttributeLayout.CONTEXT_FIELD, "HS", 1); + assertEquals(Codec.SIGNED5, layout.getCodec()); + layout = new AttributeLayout("RS", AttributeLayout.CONTEXT_CODE, "RRRS", 1); + assertEquals(Codec.UNSIGNED5, layout.getCodec()); + layout = new AttributeLayout("KS", AttributeLayout.CONTEXT_CLASS, "RKS", 1); + assertEquals(Codec.UNSIGNED5, layout.getCodec()); + layout = new AttributeLayout("B", AttributeLayout.CONTEXT_CLASS, "TRKSB", 1); + assertEquals(Codec.BYTE1, layout.getCodec()); + } + public boolean throwsException(String name, int context, String layout) { try { new AttributeLayout(name,context,layout,-1);