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