View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.commons.compress.harmony.unpack200;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef;
25  import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef;
26  import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
27  import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
28  import org.apache.commons.compress.harmony.unpack200.bytecode.CodeAttribute;
29  import org.apache.commons.compress.harmony.unpack200.bytecode.ExceptionTableEntry;
30  import org.apache.commons.compress.harmony.unpack200.bytecode.LocalVariableTableAttribute;
31  import org.apache.commons.compress.harmony.unpack200.bytecode.OperandManager;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Tests for CodeAttribute
36   */
37  public class CodeAttributeTest {
38  
39      public class MockCodeAttribute extends CodeAttribute {
40  
41          public MockCodeAttribute(final int maxStack, final int maxLocals, final byte[] codePacked, final Segment segment, final OperandManager operandManager,
42                  final List<ExceptionTableEntry> exceptionTable) {
43              super(maxStack, maxLocals, codePacked, segment, operandManager, exceptionTable);
44          }
45  
46          @Override
47          public int getLength() {
48              return super.getLength();
49          }
50      }
51  
52      public class MockCpBands extends CpBands {
53  
54          public MockCpBands(final Segment segment) {
55              super(segment);
56          }
57  
58          @Override
59          public CPFieldRef cpFieldValue(final int index) {
60              return null;
61          }
62  
63          @Override
64          public CPMethodRef cpMethodValue(final int index) {
65              return null;
66          }
67  
68          @Override
69          public CPString cpStringValue(final int index) {
70              return new CPString(new CPUTF8("Hello"), -1);
71          }
72  
73      }
74  
75      public class MockOperandManager extends OperandManager {
76  
77          public MockOperandManager() {
78              super(new int[] {}, // bcCaseCount
79                      new int[] {}, // bcCaseValues
80                      new int[] {}, // bcByte
81                      new int[] {}, // bcShort
82                      new int[] {}, // bcLocal
83                      new int[] {}, // bcLabel
84                      new int[] {}, // bcIntRef
85                      new int[] {}, // bcFloatRef
86                      new int[] {}, // bcLongRef
87                      new int[] {}, // bcDoubleRef
88                      new int[] { 0, 1, 2, 3, 4 }, // bcStringRef
89                      new int[] {}, // bcClassRef
90                      new int[] {}, // bcFieldRef
91                      new int[] {}, // bcMethodRef
92                      new int[] {}, // bcIMethodRef
93                      new int[] { 0, 0, 0, 0, 0, 0 }, // bcThisField
94                      new int[] {}, // bcSuperField
95                      new int[] { 0 }, // bcThisMethod
96                      new int[] {}, // bcSuperMethod
97                      new int[] {} // bcInitRef
98                      , null);
99          }
100     }
101 
102     public class MockSegment extends Segment {
103 
104         @Override
105         public SegmentConstantPool getConstantPool() {
106             return new MockSegmentConstantPool(cpBands);
107         }
108     }
109 
110     public class MockSegmentConstantPool extends SegmentConstantPool {
111 
112         public MockSegmentConstantPool(final CpBands bands) {
113             super(bands);
114         }
115 
116         @Override
117         protected int matchSpecificPoolEntryIndex(final String[] nameArray, final String compareString, final int desiredIndex) {
118             return 1;
119         }
120     }
121 
122     Segment segment = new MockSegment();
123     CpBands cpBands = new MockCpBands(segment);
124 
125     public byte[] mixedByteArray = { -47, // aload_0_getstatic_this 0, 1
126             -46, // aload_0_putstatic_this 4, 5
127             1, // aconst_null 8
128             -45, // aload_0_getfield_this 9, 10
129             // Should always end with a multibyte
130             // instruction
131             -44, // aload_0_putfield_this (int) 13, 14
132     };
133 
134     public byte[] singleByteArray = { 42, // aload_0 0
135             1, // aconst_null 1
136             18, // ldc 2
137             -49, // return 4
138     };
139 
140     @Test
141     public void testLength() {
142         final OperandManager operandManager = new MockOperandManager();
143         operandManager.setSegment(segment);
144         operandManager.setCurrentClass("java/lang/Foo");
145 
146         final MockCodeAttribute attribute = new MockCodeAttribute(3, // maxStack
147                 2, // maxLocals
148                 mixedByteArray, // codePacked
149                 segment, // segment
150                 operandManager, // operandManager
151                 new ArrayList<>());
152         assertEquals(29, attribute.getLength());
153 
154         attribute.attributes.add(new LocalVariableTableAttribute(0, null, null, null, null, null));
155         assertEquals(37, attribute.getLength());
156     }
157 
158     @Test
159     public void testMixedByteCodes() {
160         final OperandManager operandManager = new MockOperandManager();
161         operandManager.setSegment(segment);
162         operandManager.setCurrentClass("java/lang/Foo");
163 
164         final CodeAttribute attribute = new CodeAttribute(3, // maxStack
165                 2, // maxLocals
166                 mixedByteArray, // codePacked
167                 segment, // segment
168                 operandManager, // operandManager
169                 new ArrayList<>());
170         assertEquals(2, attribute.maxLocals);
171         assertEquals(3, attribute.maxStack);
172         assertEquals("aload_0_putfield_this", attribute.byteCodes.get(4).toString());
173 
174         final int[] expectedLabels = { 0, 1, 4, 5, 8, 9, 10, 13, 14 };
175         for (int index = 0; index < expectedLabels.length; index++) {
176             assertEquals(expectedLabels[index], attribute.byteCodeOffsets.get(index).intValue());
177         }
178     }
179 
180     @Test
181     public void testSingleByteCodes() {
182         final OperandManager operandManager = new MockOperandManager();
183         operandManager.setSegment(segment);
184         operandManager.setCurrentClass("java/lang/Foo");
185 
186         final CodeAttribute attribute = new CodeAttribute(4, // maxStack
187                 3, // maxLocals
188                 singleByteArray, // codePacked
189                 segment, // segment
190                 operandManager, // operandManager
191                 new ArrayList<>());
192         assertEquals(3, attribute.maxLocals);
193         assertEquals(4, attribute.maxStack);
194         assertEquals("invokespecial_this", attribute.byteCodes.get(3).toString());
195 
196         final int[] expectedLabels = { 0, 1, 2, 4 };
197         for (int index = 0; index < expectedLabels.length; index++) {
198             assertEquals(expectedLabels[index], attribute.byteCodeOffsets.get(index).intValue());
199         }
200     }
201 
202 }