You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sj...@apache.org on 2009/06/16 15:11:19 UTC

svn commit: r785196 - in /harmony/enhanced/classlib/trunk/modules/pack200/src: main/java/org/apache/harmony/pack200/ test/java/org/apache/harmony/pack200/tests/

Author: sjanuary
Date: Tue Jun 16 13:11:19 2009
New Revision: 785196

URL: http://svn.apache.org/viewvc?rev=785196&view=rev
Log:
Pack200 - support for bytecode indexes in unknown attributes and some tests for parsing unknown layouts

Added:
    harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java   (with props)
Modified:
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java?rev=785196&r1=785195&r2=785196&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java Tue Jun 16 13:11:19 2009
@@ -960,6 +960,23 @@
                 bciRenumbering, labelsToOffsets);
         renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO,
                 bciRenumbering, labelsToOffsets);
+
+        for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
+            NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
+            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+        }
+        for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
+            NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
+            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+        }
+        for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
+            NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
+            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+        }
+        for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
+            NewAttributeBands newAttributeBandSet = (NewAttributeBands) iterator.next();
+            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+        }
     }
 
     private void renumberBci(List list, IntList bciRenumbering, Map labelsToOffsets) {

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java?rev=785196&r1=785195&r2=785196&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java Tue Jun 16 13:11:19 2009
@@ -137,4 +137,8 @@
     public byte[] getBytes() {
         return contents;
     }
+
+    public Label getLabel(int index) {
+        return labels[index];
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java?rev=785196&r1=785195&r2=785196&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java Tue Jun 16 13:11:19 2009
@@ -22,10 +22,13 @@
 import java.io.OutputStream;
 import java.io.StringReader;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
+import org.objectweb.asm.Label;
 
 /**
  * Set of bands relating to a non-predefined attribute that has had a layout
@@ -34,12 +37,15 @@
  */
 public class NewAttributeBands extends BandSet {
 
-    private List attributeLayoutElements;
+    protected List attributeLayoutElements;
     private int[] backwardsCallCounts;
     private final CpBands cpBands;
     private final AttributeDefinition def;
     private boolean usedAtLeastOnce;
 
+    // used when parsing
+    private Integral lastPIntegral;
+
     public NewAttributeBands(int effort, CpBands cpBands, SegmentHeader header, AttributeDefinition def) throws IOException {
         super(effort, header);
         this.def = def;
@@ -172,6 +178,7 @@
 
     private AttributeLayoutElement readNextAttributeElement(StringReader stream)
             throws IOException {
+        stream.mark(1);
         int nextChar = stream.read();
         if (nextChar == -1) {
             return null;
@@ -180,6 +187,7 @@
             List body = readBody(getStreamUpToMatchingBracket(stream));
             return new Callable(body);
         } else {
+            stream.reset();
             return readNextLayoutElement(stream);
         }
     }
@@ -205,17 +213,19 @@
             stream.mark(1);
             if (stream.read() != 'O') {
                 stream.reset();
-                return new Integral("P" + (char) stream.read());
+                lastPIntegral = new Integral("P" + (char) stream.read());
+                return lastPIntegral;
             } else {
-                return new Integral("PO" + (char) stream.read());
+                lastPIntegral = new Integral("PO" + (char) stream.read(), lastPIntegral);
+                return lastPIntegral;
             }
         case 'O':
             stream.mark(1);
             if (stream.read() != 'S') {
                 stream.reset();
-                return new Integral("O" + (char) stream.read());
+                return new Integral("O" + (char) stream.read(), lastPIntegral);
             } else {
-                return new Integral("OS" + (char) stream.read());
+                return new Integral("OS" + (char) stream.read(), lastPIntegral);
             }
 
             // Replication
@@ -311,17 +321,17 @@
      * more bands associated with it, which transmit the AttributeElement data
      * for successive Attributes of this type.
      */
-    private interface AttributeLayoutElement {
+    public interface AttributeLayoutElement {
 
         public void addAttributeToBand(NewAttribute attribute, InputStream stream);
 
         public void pack(OutputStream out) throws IOException, Pack200Exception;
 
-        // TODO: bci renumbering
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets);
 
     }
 
-    private abstract class LayoutElement implements AttributeLayoutElement {
+    public abstract class LayoutElement implements AttributeLayoutElement {
 
         protected int getLength(char uint_type) {
             int length = 0;
@@ -343,19 +353,35 @@
         }
     }
 
-    private class Integral extends LayoutElement {
+    public class Integral extends LayoutElement {
 
         private final String tag;
-        private final IntList band = new IntList();
+
+        private final List band = new ArrayList();
         private final BHSDCodec defaultCodec;
 
+        // used for bytecode offsets (OH and POH)
+        private Integral previousIntegral;
+        private int previousPValue;
+
         public Integral(String tag) {
             this.tag = tag;
             this.defaultCodec = getCodec(tag);
         }
 
+        public Integral(String tag, Integral previousIntegral) {
+            this.tag = tag;
+            this.defaultCodec = getCodec(tag);
+            this.previousIntegral = previousIntegral;
+        }
+
+        public String getTag() {
+            return tag;
+        }
+
         public void addAttributeToBand(NewAttribute attribute,
                 InputStream stream) {
+            Object val = null;
             int value = 0;
             if (tag.equals("B") || tag.equals("FB")) {
                 value = readInteger(1, stream) & 0xFF; // unsigned byte
@@ -370,26 +396,76 @@
             } else if (tag.equals("SI")) {
                 value = readInteger(4, stream);
             } else if (tag.equals("V") || tag.equals("FV") || tag.equals("SV")) {
-                // TODO
+                // Not currently supported
             } else if (tag.startsWith("PO") || tag.startsWith("OS")) {
-                // TODO: bci renumbering
                 char uint_type = tag.substring(2).toCharArray()[0];
                 int length = getLength(uint_type);
                 value = readInteger(length, stream);
-            } else if (tag.startsWith("P") || tag.startsWith("O")) {
+                value += previousIntegral.previousPValue;
+                val = attribute.getLabel(value);
+                previousPValue = value;
+            } else if (tag.startsWith("P")) {
                 char uint_type = tag.substring(1).toCharArray()[0];
                 int length = getLength(uint_type);
                 value = readInteger(length, stream);
+                val = attribute.getLabel(value);
+                previousPValue = value;
+            } else if (tag.startsWith("O")) {
+                char uint_type = tag.substring(1).toCharArray()[0];
+                int length = getLength(uint_type);
+                value = readInteger(length, stream);
+                value += previousIntegral.previousPValue;
+                val = attribute.getLabel(value);
+                previousPValue = value;
             }
-            band.add(value);
+            if(val == null) {
+                val = new Integer(value);
+            }
+            band.add(val);
         }
 
         public void pack(OutputStream out) throws IOException, Pack200Exception {
-            out.write(encodeBandInt(tag, band.toArray(), defaultCodec));
+            out.write(encodeBandInt(tag, listToArray(band), defaultCodec));
         }
 
         public int latestValue() {
-            return band.get(band.size() - 1);
+            return ((Integer)band.get(band.size() - 1)).intValue();
+        }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            if(tag.startsWith("O") || tag.startsWith("PO")) {
+                renumberOffsetBci(previousIntegral.band, bciRenumbering, labelsToOffsets);
+            } else if (tag.startsWith("P")) {
+                for (int i = band.size() - 1; i >= 0; i--) {
+                    Object label = band.get(i);
+                    if (label instanceof Integer) {
+                        break;
+                    } else if (label instanceof Label) {
+                        band.remove(i);
+                        Integer bytecodeIndex = (Integer) labelsToOffsets
+                                .get(label);
+                        band.add(i, new Integer(bciRenumbering.get(bytecodeIndex
+                                .intValue())));
+                    }
+                }
+            }
+        }
+
+        private void renumberOffsetBci(List relative,
+                IntList bciRenumbering, Map labelsToOffsets) {
+            for (int i = band.size() - 1; i >= 0; i--) {
+                Object label = band.get(i);
+                if (label instanceof Integer) {
+                    break;
+                } else if (label instanceof Label) {
+                    band.remove(i);
+                    Integer bytecodeIndex = (Integer) labelsToOffsets.get(label);
+                    Integer renumberedOffset = new Integer(bciRenumbering
+                            .get(bytecodeIndex.intValue())
+                            - ((Integer) relative.get(i)).intValue());
+                    band.add(i, renumberedOffset);
+                }
+            }
         }
 
     }
@@ -397,12 +473,20 @@
     /**
      * A replication is an array of layout elements, with an associated count
      */
-    private class Replication extends LayoutElement {
+    public class Replication extends LayoutElement {
 
         private final Integral countElement;
 
         private final List layoutElements = new ArrayList();
 
+        public Integral getCountElement() {
+            return countElement;
+        }
+
+        public List getLayoutElements() {
+            return layoutElements;
+        }
+
         public Replication(String tag, String contents) throws IOException {
             this.countElement = new Integral(tag);
             StringReader stream = new StringReader(contents);
@@ -428,13 +512,20 @@
                 layoutElement.pack(out);
             }
         }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            for (Iterator iterator = layoutElements.iterator(); iterator.hasNext();) {
+                AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+                layoutElement.renumberBci(bciRenumbering, labelsToOffsets);
+            }
+        }
     }
 
     /**
      * A Union is a type of layout element where the tag value acts as a
      * selector for one of the union cases
      */
-    private class Union extends LayoutElement {
+    public class Union extends LayoutElement {
 
         private final Integral unionTag;
         private final List unionCases;
@@ -480,9 +571,34 @@
                 layoutElement.pack(out);
             }
         }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            for (Iterator iterator = unionCases.iterator(); iterator.hasNext();) {
+                UnionCase unionCase = (UnionCase) iterator.next();
+                unionCase.renumberBci(bciRenumbering, labelsToOffsets);
+            }
+            for (Iterator iterator = defaultCaseBody.iterator(); iterator
+                    .hasNext();) {
+                AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator
+                        .next();
+                layoutElement.renumberBci(bciRenumbering, labelsToOffsets);
+            }
+        }
+
+        public Integral getUnionTag() {
+            return unionTag;
+        }
+
+        public List getUnionCases() {
+            return unionCases;
+        }
+
+        public List getDefaultCaseBody() {
+            return defaultCaseBody;
+        }
     }
 
-    private class Call extends LayoutElement {
+    public class Call extends LayoutElement {
 
         private final int callableIndex;
         private Callable callable;
@@ -507,14 +623,26 @@
         }
 
         public void pack(OutputStream out) {
-            // do nothing here - as pack will be called on the callable at another time
+            // do nothing here as pack will be called on the callable at another time
+        }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            // do nothing here as renumberBci will be called on the callable at another time
+        }
+
+        public int getCallableIndex() {
+            return callableIndex;
+        }
+
+        public Callable getCallable() {
+            return callable;
         }
     }
 
     /**
      * Constant Pool Reference
      */
-    private class Reference extends LayoutElement {
+    public class Reference extends LayoutElement {
 
         private final String tag;
 
@@ -545,6 +673,10 @@
             // TODO method and field references
         }
 
+        public String getTag() {
+            return tag;
+        }
+
         public void pack(OutputStream out) throws IOException, Pack200Exception {
             int[] ints;
             if(nullsAllowed) {
@@ -555,9 +687,13 @@
             out.write(encodeBandInt(tag, ints, Codec.UNSIGNED5));
         }
 
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            // nothing to do here
+        }
+
     }
 
-    private class Callable implements AttributeLayoutElement {
+    public class Callable implements AttributeLayoutElement {
 
         private final List body;
 
@@ -602,19 +738,31 @@
                 layoutElement.pack(out);
             }
         }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            for (Iterator iterator = body.iterator(); iterator.hasNext();) {
+                AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+                layoutElement.renumberBci(bciRenumbering, labelsToOffsets);
+            }
+        }
+
+        public List getBody() {
+            return body;
+        }
     }
 
     /**
      * A Union case
      */
-    private class UnionCase extends LayoutElement {
+    public class UnionCase extends LayoutElement {
 
-        private List body;
+        private final List body;
 
         private final List tags;
 
         public UnionCase(List tags) {
             this.tags = tags;
+            this.body = Collections.EMPTY_LIST;
         }
 
         public boolean hasTag(long l) {
@@ -640,6 +788,17 @@
                 element.pack(out);
             }
         }
+
+        public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+            for (int i = 0; i < body.size(); i++) {
+                LayoutElement element = (LayoutElement) body.get(i);
+                element.renumberBci(bciRenumbering, labelsToOffsets);
+            }
+        }
+
+        public List getBody() {
+            return body;
+        }
     }
 
     /**
@@ -777,4 +936,18 @@
         return layoutElements;
     }
 
+    /**
+     * Renumber any bytecode indexes or offsets as described in section 5.5.2 of
+     * the pack200 specification
+     *
+     * @param bciRenumbering
+     * @param labelsToOffsets
+     */
+    public void renumberBci(IntList bciRenumbering, Map labelsToOffsets) {
+        for (Iterator iterator = attributeLayoutElements.iterator(); iterator.hasNext();) {
+            AttributeLayoutElement element = (AttributeLayoutElement) iterator.next();
+            element.renumberBci(bciRenumbering, labelsToOffsets);
+        }
+    }
+
 }

Added: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java?rev=785196&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java (added)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java Tue Jun 16 13:11:19 2009
@@ -0,0 +1,213 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.harmony.pack200.tests;
+
+import java.io.IOException;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.pack200.AttributeDefinitionBands;
+import org.apache.harmony.pack200.CPUTF8;
+import org.apache.harmony.pack200.CpBands;
+import org.apache.harmony.pack200.NewAttributeBands;
+import org.apache.harmony.pack200.SegmentHeader;
+import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
+import org.apache.harmony.pack200.NewAttributeBands.Call;
+import org.apache.harmony.pack200.NewAttributeBands.Callable;
+import org.apache.harmony.pack200.NewAttributeBands.Integral;
+import org.apache.harmony.pack200.NewAttributeBands.Reference;
+import org.apache.harmony.pack200.NewAttributeBands.Replication;
+import org.apache.harmony.pack200.NewAttributeBands.Union;
+import org.apache.harmony.pack200.NewAttributeBands.UnionCase;
+
+/**
+ * Tests for pack200 support for non-predefined attributes
+ */
+public class NewAttributeBandsTest extends TestCase {
+
+    public void testEmptyLayout() throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8("");
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(0, layoutElements.size());
+    }
+
+    public void testIntegralLayouts() throws IOException {
+        tryIntegral("B");
+        tryIntegral("FB");
+        tryIntegral("SB");
+        tryIntegral("H");
+        tryIntegral("FH");
+        tryIntegral("SH");
+        tryIntegral("I");
+        tryIntegral("FI");
+        tryIntegral("SI");
+        tryIntegral("PB");
+        tryIntegral("OB");
+        tryIntegral("OSB");
+        tryIntegral("POB");
+        tryIntegral("PH");
+        tryIntegral("OH");
+        tryIntegral("OSH");
+        tryIntegral("POH");
+        tryIntegral("PI");
+        tryIntegral("OI");
+        tryIntegral("OSI");
+        tryIntegral("POI");
+    }
+
+    private void tryIntegral(String layoutStr) throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8(layoutStr);
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(1, layoutElements.size());
+        Integral element = (Integral) layoutElements.get(0);
+        assertEquals(layoutStr, element.getTag());
+    }
+
+    public void testReplicationLayouts() throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8("NH[PHOHRUHRSHH]");
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(1, layoutElements.size());
+        Replication element = (Replication) layoutElements.get(0);
+        Integral countElement = element.getCountElement();
+        assertEquals("H", countElement.getTag());
+        List replicatedElements = element.getLayoutElements();
+        assertEquals(5, replicatedElements.size());
+        Integral firstElement = (Integral) replicatedElements.get(0);
+        assertEquals("PH", firstElement.getTag());
+        Integral secondElement = (Integral) replicatedElements.get(1);
+        assertEquals("OH", secondElement.getTag());
+        Reference thirdElement = (Reference) replicatedElements.get(2);
+        assertEquals("RUH", thirdElement.getTag());
+        Reference fourthElement = (Reference) replicatedElements.get(3);
+        assertEquals("RSH", fourthElement.getTag());
+        Integral fifthElement = (Integral) replicatedElements.get(4);
+        assertEquals("H", fifthElement.getTag());
+    }
+
+    public void testReferenceLayouts() throws IOException {
+        tryReference("KIB");
+        tryReference("KIH");
+        tryReference("KII");
+        tryReference("KINH");
+        tryReference("KJH");
+        tryReference("KDH");
+        tryReference("KSH");
+        tryReference("KQH");
+        tryReference("RCH");
+        tryReference("RSH");
+        tryReference("RDH");
+        tryReference("RFH");
+        tryReference("RMH");
+        tryReference("RIH");
+        tryReference("RUH");
+        tryReference("RQH");
+        tryReference("RQNH");
+        tryReference("RQNI");
+    }
+
+    private void tryReference(String layoutStr) throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8(layoutStr);
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(1, layoutElements.size());
+        Reference element = (Reference) layoutElements.get(0);
+        assertEquals(layoutStr, element.getTag());
+    }
+
+    public void testUnionLayout() throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8("TB(55)[FH](23)[]()[RSH]");
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(1, layoutElements.size());
+        Union element = (Union) layoutElements.get(0);
+        Integral tag = element.getUnionTag();
+        assertEquals("B", tag.getTag());
+        List unionCases = element.getUnionCases();
+        assertEquals(2, unionCases.size());
+        UnionCase firstCase = (UnionCase) unionCases.get(0);
+        assertTrue(firstCase.hasTag(55));
+        assertFalse(firstCase.hasTag(23));
+        List body = firstCase.getBody();
+        assertEquals(1, body.size());
+        Integral bodyElement = (Integral) body.get(0);
+        assertEquals("FH", bodyElement.getTag());
+        UnionCase secondCase = (UnionCase) unionCases.get(1);
+        assertTrue(secondCase.hasTag(23));
+        assertFalse(secondCase.hasTag(55));
+        body = secondCase.getBody();
+        assertEquals(0, body.size());
+        List defaultBody = element.getDefaultCaseBody();
+        assertEquals(1, defaultBody.size());
+        Reference ref = (Reference) defaultBody.get(0);
+        assertEquals("RSH", ref.getTag());
+    }
+
+    public void testLayoutWithCalls() throws IOException {
+        CPUTF8 name = new CPUTF8("TestAttribute");
+        CPUTF8 layout = new CPUTF8(
+                "[NH[(1)]][RSH NH[RUH(1)]][TB(66,67,73,83,90)[KIH](68)[KDH](70)[KFH](74)[KJH](99)[RSH](101)[RSH RUH](115)[RUH](91)[NH[(0)]](64)[RSH[RUH(0)]]()[]]");
+        MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1,
+                null, null, new AttributeDefinition(35,
+                        AttributeDefinitionBands.CONTEXT_CLASS, name, layout));
+        List layoutElements = newAttributeBands.getLayoutElements();
+        assertEquals(3, layoutElements.size());
+        Callable firstCallable = (Callable) layoutElements.get(0);
+        Callable secondCallable = (Callable) layoutElements.get(1);
+        Callable thirdCallable = (Callable) layoutElements.get(2);
+        List firstBody = firstCallable.getBody();
+        assertEquals(1, firstBody.size());
+        Replication rep = (Replication) firstBody.get(0);
+        List repBody = rep.getLayoutElements();
+        assertEquals(1, repBody.size());
+        Call call = (Call) repBody.get(0);
+        assertEquals(1, call.getCallableIndex());
+        assertEquals(secondCallable, call.getCallable());
+    }
+
+    private class MockNewAttributeBands extends NewAttributeBands {
+
+        public MockNewAttributeBands(int effort, CpBands cpBands,
+                SegmentHeader header, AttributeDefinition def)
+                throws IOException {
+            super(effort, cpBands, header, def);
+        }
+
+        public List getLayoutElements() {
+            return attributeLayoutElements;
+        }
+    }
+
+}

Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain