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.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.ArrayList;
27  
28  import org.apache.commons.compress.harmony.pack200.Pack200Exception;
29  import org.apache.commons.compress.harmony.unpack200.bytecode.CPClass;
30  import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble;
31  import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef;
32  import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat;
33  import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger;
34  import org.apache.commons.compress.harmony.unpack200.bytecode.CPInterfaceMethodRef;
35  import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong;
36  import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef;
37  import org.apache.commons.compress.harmony.unpack200.bytecode.CPNameAndType;
38  import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
39  import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
40  import org.junit.jupiter.api.Disabled;
41  import org.junit.jupiter.api.Test;
42  
43  /**
44   * Tests for Pack200 bytecode bands.
45   *
46   * TODO: The number 8 is used in most of the tests in this class as a low (non-zero) number that is not likely to indicate a multiple byte number, but should be
47   * replaced with properly encoded byte arrays when encoding is implemented.
48   */
49  class BcBandsTest extends AbstractBandsTest {
50  
51      public class MockClassBands extends ClassBands {
52  
53          MockClassBands(final Segment segment) {
54              super(segment);
55          }
56  
57          @Override
58          public int[] getClassSuperInts() {
59              final int[] superClasses = new int[numClasses];
60              for (int index = 0; index < numClasses; index++) {
61                  superClasses[index] = 0;
62              }
63              return superClasses;
64          }
65  
66          @Override
67          public int[] getClassThisInts() {
68              final int[] thisClasses = new int[numClasses];
69              for (int index = 0; index < numClasses; index++) {
70                  thisClasses[index] = 0;
71              }
72              return thisClasses;
73          }
74  
75          @Override
76          public boolean[] getCodeHasAttributes() {
77              int totalMethods = 0;
78              for (int i = 0; i < numClasses; i++) {
79                  totalMethods += numMethods[i];
80              }
81              return new boolean[totalMethods];
82          }
83  
84          @Override
85          public int[] getCodeMaxNALocals() {
86              int totalMethods = 0;
87              for (int i = 0; i < numClasses; i++) {
88                  totalMethods += numMethods[i];
89              }
90              return new int[totalMethods];
91          }
92  
93          @Override
94          public int[] getCodeMaxStack() {
95              int totalMethods = 0;
96              for (int i = 0; i < numClasses; i++) {
97                  totalMethods += numMethods[i];
98              }
99              return new int[totalMethods];
100         }
101 
102         @Override
103         public ArrayList[][] getMethodAttributes() {
104             final ArrayList[][] attributes = new ArrayList[numClasses][];
105             for (int i = 0; i < attributes.length; i++) {
106                 attributes[i] = new ArrayList[numMethods[i]];
107                 for (int j = 0; j < attributes[i].length; j++) {
108                     attributes[i][j] = new ArrayList();
109                 }
110             }
111             return attributes;
112         }
113 
114         @Override
115         public String[][] getMethodDescr() {
116             final String[][] descr = new String[numClasses][];
117             for (int i = 0; i < descr.length; i++) {
118                 descr[i] = new String[numMethods[i]];
119                 for (int j = 0; j < descr[i].length; j++) {
120                     descr[i][j] = "hello()";
121                 }
122             }
123             return descr;
124         }
125 
126         @Override
127         public long[][] getMethodFlags() {
128             final long[][] flags = new long[numClasses][];
129             for (int i = 0; i < flags.length; i++) {
130                 flags[i] = new long[numMethods[i]];
131             }
132             return flags;
133         }
134 
135         @Override
136         public ArrayList getOrderedCodeAttributes() {
137             int totalMethods = 0;
138             for (final int numMethod : numMethods) {
139                 totalMethods += numMethod;
140             }
141             final ArrayList orderedAttributeList = new ArrayList();
142             for (int classIndex = 0; classIndex < totalMethods; classIndex++) {
143                 orderedAttributeList.add(new ArrayList());
144             }
145             return orderedAttributeList;
146         }
147     }
148 
149     public class MockCpBands extends CpBands {
150 
151         private final CPUTF8 cpUTF8 = new CPUTF8("java/lang/String");
152         private final CPClass cpClass = new CPClass(cpUTF8, -1);
153         private final CPNameAndType descriptor = new CPNameAndType(new CPUTF8("Hello"), new CPUTF8("(a, b, c)"), -1);
154 
155         MockCpBands(final Segment segment) {
156             super(segment);
157         }
158 
159         @Override
160         public CPClass cpClassValue(final int index) {
161             return cpClass;
162         }
163 
164         @Override
165         public CPDouble cpDoubleValue(final int index) {
166             return new CPDouble(Double.valueOf(2.5D), index);
167         }
168 
169         @Override
170         public CPFieldRef cpFieldValue(final int index) {
171             return new CPFieldRef(cpClass, descriptor, index);
172         }
173 
174         @Override
175         public CPFloat cpFloatValue(final int index) {
176             return new CPFloat(Float.valueOf(2.5F), index);
177         }
178 
179         @Override
180         public CPInterfaceMethodRef cpIMethodValue(final int index) {
181             return new CPInterfaceMethodRef(cpClass, descriptor, index);
182         }
183 
184         @Override
185         public CPInteger cpIntegerValue(final int index) {
186             return new CPInteger(Integer.valueOf(21), index);
187         }
188 
189         @Override
190         public CPLong cpLongValue(final int index) {
191             return new CPLong(Long.valueOf(21L), index);
192         }
193 
194         @Override
195         public CPMethodRef cpMethodValue(final int index) {
196             return new CPMethodRef(cpClass, descriptor, index);
197         }
198 
199         @Override
200         public CPString cpStringValue(final int index) {
201             return new CPString(cpUTF8, index);
202         }
203 
204         @Override
205         public String[] getCpClass() {
206             return new String[] { "Hello" };
207         }
208 
209         @Override
210         public String[] getCpFieldClass() {
211             return new String[] {};
212         }
213 
214         @Override
215         public String[] getCpIMethodClass() {
216             return new String[] {};
217         }
218 
219         @Override
220         public String[] getCpMethodClass() {
221             return new String[] {};
222         }
223     }
224 
225     public class MockSegment extends AbstractBandsTest.MockSegment {
226 
227         public CpBands cpBands;
228 
229         @Override
230         protected AttrDefinitionBands getAttrDefinitionBands() {
231             return new MockAttributeDefinitionBands(this);
232         }
233 
234         @Override
235         protected ClassBands getClassBands() {
236             return new MockClassBands(this);
237         }
238 
239         @Override
240         public SegmentConstantPool getConstantPool() {
241             return cpBands.getConstantPool();
242         }
243 
244         @Override
245         protected CpBands getCpBands() {
246             if (null == cpBands) {
247                 cpBands = new MockCpBands(this);
248             }
249             return cpBands;
250         }
251     }
252 
253     BcBands bcBands = new BcBands(new MockSegment());
254 
255     /**
256      * Test with codes that should require entries in the bc_byte band
257      *
258      * @throws Pack200Exception
259      * @throws IOException if an I/O error occurs.
260      */
261     @Test
262     void testBcByteBand() throws IOException, Pack200Exception {
263         final byte[] bytes = { 16, (byte) 132, (byte) 188, (byte) 197, (byte) 255, 8, 8, 8, 8, // bc_byte band
264                 8, // bc_locals band (required by iinc (132))
265                 8 }; // bc_class band (required by multianewarray (197))
266         final InputStream in = new ByteArrayInputStream(bytes);
267         bcBands.unpack(in);
268         assertEquals(4, bcBands.getMethodByteCodePacked()[0][0].length);
269         final int[] bc_byte = bcBands.getBcByte();
270         assertEquals(4, bc_byte.length);
271         for (final int element : bc_byte) {
272             assertEquals(8, element);
273         }
274         assertEquals(1, bcBands.getBcLocal().length);
275         assertEquals(1, bcBands.getBcClassRef().length);
276     }
277 
278     /**
279      * Test with codes that require entries in the bc_case_count and bc_case_value bands
280      *
281      * @throws Pack200Exception
282      * @throws IOException if an I/O error occurs.
283      */
284     @Test
285     void testBcCaseBands() throws IOException, Pack200Exception {
286         final byte[] bytes = { (byte) 170, (byte) 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 255, 2, 5, // bc_case_count
287                 0, 0, 0, 0, 0, 0, 0, // bc_case_value
288                 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // bc_label
289         final InputStream in = new ByteArrayInputStream(bytes);
290         bcBands.unpack(in);
291         assertEquals(18, bcBands.getMethodByteCodePacked()[0][0].length);
292         final int[] bc_case_count = bcBands.getBcCaseCount();
293         assertEquals(2, bc_case_count.length);
294         assertEquals(2, bc_case_count[0]);
295         assertEquals(5, bc_case_count[1]);
296         final int[] bc_case_value = bcBands.getBcCaseValue();
297         assertEquals(0, bc_case_value[0]);
298         assertEquals(0, bc_case_value[1]);
299         assertEquals(9, bcBands.getBcLabel().length);
300     }
301 
302     /**
303      * Test with codes that should require entries in the bc_classref band
304      *
305      * @throws Pack200Exception
306      * @throws IOException if an I/O error occurs.
307      */
308     @Test
309     void testBcClassRefBand() throws IOException, Pack200Exception {
310         final byte[] bytes = { (byte) 233, (byte) 236, (byte) 255, 8, 8 }; // bc_classref
311         // band
312         final InputStream in = new ByteArrayInputStream(bytes);
313         bcBands.unpack(in);
314         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
315         final int[] bc_classref = bcBands.getBcClassRef();
316         assertEquals(2, bc_classref.length);
317     }
318 
319     /**
320      * Test with codes that should require entries in the bc_doubleref band
321      *
322      * @throws Pack200Exception
323      * @throws IOException if an I/O error occurs.
324      */
325     @Test
326     void testBcDoubleRefBand() throws IOException, Pack200Exception {
327         final byte[] bytes = { (byte) 239, (byte) 255, 8 }; // bc_doubleref
328         // band
329         final InputStream in = new ByteArrayInputStream(bytes);
330         bcBands.unpack(in);
331         assertEquals(1, bcBands.getMethodByteCodePacked()[0][0].length);
332         final int[] bc_doubleref = bcBands.getBcDoubleRef();
333         assertEquals(1, bc_doubleref.length);
334     }
335 
336     @Test
337     @Disabled("TODO: Implement")
338     void testBcEscBands() {
339         // TODO
340     }
341 
342     @Test
343     @Disabled("TODO: Implement")
344     void testBcEscRefBands() {
345         // TODO
346     }
347 
348     /**
349      * Test with codes that should require entries in the bc_fieldref band
350      *
351      * @throws Pack200Exception
352      * @throws IOException if an I/O error occurs.
353      */
354     @Test
355     void testBcFieldRefBand() throws IOException, Pack200Exception {
356         final byte[] bytes = { (byte) 178, (byte) 179, (byte) 180, (byte) 181, (byte) 255, 8, 8, 8, 8 }; // bc_fieldref band
357         final InputStream in = new ByteArrayInputStream(bytes);
358         bcBands.unpack(in);
359         assertEquals(4, bcBands.getMethodByteCodePacked()[0][0].length);
360         final int[] bc_fieldref = bcBands.getBcFieldRef();
361         assertEquals(4, bc_fieldref.length);
362     }
363 
364     /**
365      * Test with codes that should require entries in the bc_floatref band
366      *
367      * @throws Pack200Exception
368      * @throws IOException if an I/O error occurs.
369      */
370     @Test
371     void testBcFloatRefBand() throws IOException, Pack200Exception {
372         final byte[] bytes = { (byte) 235, (byte) 238, (byte) 255, 8, 8 }; // bc_floatref
373         // band
374         final InputStream in = new ByteArrayInputStream(bytes);
375         bcBands.unpack(in);
376         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
377         final int[] bc_floatref = bcBands.getBcFloatRef();
378         assertEquals(2, bc_floatref.length);
379     }
380 
381     /**
382      * Test with codes that should require entries in the bc_imethodref band
383      *
384      * @throws Pack200Exception
385      * @throws IOException if an I/O error occurs.
386      */
387     @Test
388     void testBcIMethodRefBand() throws IOException, Pack200Exception {
389         final byte[] bytes = { (byte) 185, (byte) 255, 8 }; // bc_imethodref
390         // band
391         final InputStream in = new ByteArrayInputStream(bytes);
392         bcBands.unpack(in);
393         assertEquals(1, bcBands.getMethodByteCodePacked()[0][0].length);
394         final int[] bc_imethodref = bcBands.getBcIMethodRef();
395         assertEquals(1, bc_imethodref.length);
396     }
397 
398     /**
399      * Test with codes that should require entries in the bc_initrefref band
400      *
401      * @throws Pack200Exception
402      * @throws IOException if an I/O error occurs.
403      */
404     @Test
405     @Disabled("TODO: Need to fix this test so it has enough data to pass.")
406     void testBcInitRefRefBand() throws IOException, Pack200Exception {
407         final byte[] bytes = { (byte) 230, (byte) 231, (byte) 232, (byte) 255, 8, 8, 8 }; // bc_initrefref band
408         final InputStream in = new ByteArrayInputStream(bytes);
409         bcBands.unpack(in);
410         assertEquals(3, bcBands.getMethodByteCodePacked()[0][0].length);
411         final int[] bc_initrefref = bcBands.getBcInitRef();
412         assertEquals(3, bc_initrefref.length);
413     }
414 
415     /**
416      * Test with codes that should require entries in the bc_intref band
417      *
418      * @throws Pack200Exception
419      * @throws IOException if an I/O error occurs.
420      */
421     @Test
422     void testBcIntRefBand() throws IOException, Pack200Exception {
423         final byte[] bytes = { (byte) 234, (byte) 237, (byte) 255, 8, 8 }; // bc_intref
424         // band
425         final InputStream in = new ByteArrayInputStream(bytes);
426         bcBands.unpack(in);
427         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
428         final int[] bc_intref = bcBands.getBcIntRef();
429         assertEquals(2, bc_intref.length);
430     }
431 
432     /**
433      * Test with codes that should require entries in the bc_label band
434      *
435      * @throws Pack200Exception
436      * @throws IOException if an I/O error occurs.
437      */
438     @Test
439     void testBcLabelBand() throws IOException, Pack200Exception {
440         final byte[] bytes = { (byte) 159, (byte) 160, (byte) 161, (byte) 162, (byte) 163, (byte) 164, (byte) 165, (byte) 166, (byte) 167, (byte) 168,
441                 (byte) 170, (byte) 171, (byte) 198, (byte) 199, (byte) 200, (byte) 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 255,
442                 2, 2, // bc_case_count
443                 // (required
444                 // by
445                 // tableswitch
446                 // (170) and
447                 // lookupswitch
448                 // (171))
449                 0, 0, 0, 0, // bc_case_value
450                 // Now that we're actually doing real label lookup, need valid
451                 // labels
452                 // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; // bc_label
453                 // band
454                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // bc_label
455         // band
456         final InputStream in = new ByteArrayInputStream(bytes);
457         bcBands.unpack(in);
458         assertEquals(36, bcBands.getMethodByteCodePacked()[0][0].length);
459         assertEquals(20, bcBands.getBcLabel().length);
460     }
461 
462     /**
463      * Test with codes that should require entries in the bc_local band
464      *
465      * @throws Pack200Exception
466      * @throws IOException if an I/O error occurs.
467      */
468     @Test
469     void testBcLocalBand() throws IOException, Pack200Exception {
470         final byte[] bytes = { 21, 22, 23, 24, 25, 54, 55, 56, 57, 58, (byte) 169, (byte) 255, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; // bc_local
471         // band
472         final InputStream in = new ByteArrayInputStream(bytes);
473         bcBands.unpack(in);
474         assertEquals(11, bcBands.getMethodByteCodePacked()[0][0].length);
475         assertEquals(11, bcBands.getBcLocal().length);
476     }
477 
478     /**
479      * Test with codes that should require entries in the bc_longref band
480      *
481      * @throws Pack200Exception
482      * @throws IOException if an I/O error occurs.
483      */
484     @Test
485     void testBcLongRefBand() throws IOException, Pack200Exception {
486         final byte[] bytes = { 20, (byte) 255, 8 }; // bc_longref band
487         final InputStream in = new ByteArrayInputStream(bytes);
488         bcBands.unpack(in);
489         assertEquals(1, bcBands.getMethodByteCodePacked()[0][0].length);
490         final int[] bc_longref = bcBands.getBcLongRef();
491         assertEquals(1, bc_longref.length);
492     }
493 
494     /**
495      * Test with codes that should require entries in the bc_methodref band
496      *
497      * @throws Pack200Exception
498      * @throws IOException if an I/O error occurs.
499      */
500     @Test
501     void testBcMethodRefBand() throws IOException, Pack200Exception {
502         final byte[] bytes = { (byte) 182, (byte) 183, (byte) 184, (byte) 255, 8, 8, 8 }; // bc_methodref band
503         final InputStream in = new ByteArrayInputStream(bytes);
504         bcBands.unpack(in);
505         assertEquals(3, bcBands.getMethodByteCodePacked()[0][0].length);
506         final int[] bc_methodref = bcBands.getBcMethodRef();
507         assertEquals(3, bc_methodref.length);
508     }
509 
510     /**
511      * Test with codes that should require entries in the bc_short band
512      *
513      * @throws Pack200Exception
514      * @throws IOException if an I/O error occurs.
515      */
516     @Test
517     void testBcShortBand() throws IOException, Pack200Exception {
518         // TODO: Need to fix this test so it has enough data to pass.
519         final byte[] bytes = { 17, (byte) 196, (byte) 132, (byte) 255, 8, 8, // bc_short band
520                 8 }; // bc_locals band (required by wide iinc (196, 132))
521         final InputStream in = new ByteArrayInputStream(bytes);
522         bcBands.unpack(in);
523         assertEquals(3, bcBands.getMethodByteCodePacked()[0][0].length);
524         assertEquals(2, bcBands.getBcShort().length);
525         assertEquals(1, bcBands.getBcLocal().length);
526     }
527 
528     /**
529      * Test with codes that should require entries in the bc_stringref band
530      *
531      * @throws Pack200Exception
532      * @throws IOException if an I/O error occurs.
533      */
534     @Test
535     void testBcStringRefBand() throws IOException, Pack200Exception {
536         final byte[] bytes = { 18, 19, (byte) 255, 8, 8 }; // bc_stringref
537         // band
538         final InputStream in = new ByteArrayInputStream(bytes);
539         bcBands.unpack(in);
540         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
541         final int[] bc_stringref = bcBands.getBcStringRef();
542         assertEquals(2, bc_stringref.length);
543     }
544 
545     /**
546      * Test with codes that should require entries in the bc_superfield band
547      *
548      * @throws Pack200Exception
549      * @throws IOException if an I/O error occurs.
550      */
551     @Test
552     void testBcSuperFieldBand() throws IOException, Pack200Exception {
553         final byte[] bytes = { (byte) 216, (byte) 217, (byte) 218, (byte) 219, (byte) 223, (byte) 224, (byte) 225, (byte) 226, (byte) 255, 8, 8, 8, 8, 8, 8, 8,
554                 8 }; // bc_superfield band
555         final InputStream in = new ByteArrayInputStream(bytes);
556         bcBands.unpack(in);
557         assertEquals(8, bcBands.getMethodByteCodePacked()[0][0].length);
558         final int[] bc_superfield = bcBands.getBcSuperField();
559         assertEquals(8, bc_superfield.length);
560     }
561 
562     /**
563      * Test with codes that should require entries in the bc_supermethod band
564      *
565      * @throws Pack200Exception
566      * @throws IOException if an I/O error occurs.
567      */
568     @Test
569     @Disabled("TODO: Need to fix this test so it has enough data to pass.")
570     void testBcSuperMethodBand() throws IOException, Pack200Exception {
571         final byte[] bytes = { (byte) 220, (byte) 221, (byte) 222, (byte) 227, (byte) 228, (byte) 229, (byte) 255, 8, 8, 8, 8, 8, 8 }; // bc_supermethod band
572         final InputStream in = new ByteArrayInputStream(bytes);
573         bcBands.unpack(in);
574         assertEquals(6, bcBands.getMethodByteCodePacked()[0][0].length);
575         final int[] bc_supermethod = bcBands.getBcSuperMethod();
576         assertEquals(6, bc_supermethod.length);
577     }
578 
579     /**
580      * Test with codes that should require entries in the bc_thisfieldref band
581      *
582      * @throws Pack200Exception
583      * @throws IOException if an I/O error occurs.
584      */
585     @Test
586     void testBcThisFieldBand() throws IOException, Pack200Exception {
587         final byte[] bytes = { (byte) 202, (byte) 203, (byte) 204, (byte) 205, (byte) 209, (byte) 210, (byte) 211, (byte) 212, (byte) 255, 8, 8, 8, 8, 8, 8, 8,
588                 8 }; // bc_thisfieldref band
589         final InputStream in = new ByteArrayInputStream(bytes);
590         bcBands.unpack(in);
591         assertEquals(8, bcBands.getMethodByteCodePacked()[0][0].length);
592         final int[] bc_thisfield = bcBands.getBcThisField();
593         assertEquals(8, bc_thisfield.length);
594     }
595 
596     /**
597      * Test with codes that should require entries in the bc_thismethod band
598      *
599      * @throws Pack200Exception
600      * @throws IOException if an I/O error occurs.
601      */
602     @Test
603     void testBcThisMethodBand() throws IOException, Pack200Exception {
604         final byte[] bytes = { (byte) 206, (byte) 207, (byte) 208, (byte) 213, (byte) 214, (byte) 215, (byte) 255, 8, 8, 8, 8, 8, 8 }; // bc_thismethod band
605         final InputStream in = new ByteArrayInputStream(bytes);
606         bcBands.unpack(in);
607         assertEquals(6, bcBands.getMethodByteCodePacked()[0][0].length);
608         final int[] bc_thismethod = bcBands.getBcThisMethod();
609         assertEquals(6, bc_thismethod.length);
610     }
611 
612     /**
613      * Test with multiple classes but single byte instructions
614      *
615      * @throws IOException if an I/O error occurs.
616      * @throws Pack200Exception
617      */
618     @Test
619     void testMultipleClassesSimple() throws IOException, Pack200Exception {
620         numClasses = 2;
621         numMethods = new int[] { 1, 1 };
622         final byte[] bytes = { 50, 50, (byte) 255, 50, 50, (byte) 255 };
623         final InputStream in = new ByteArrayInputStream(bytes);
624         bcBands.unpack(in);
625         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
626         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
627 
628         numClasses = 1;
629         numMethods = new int[] { 1 };
630     }
631 
632     /**
633      * Test with multiple classes and multiple methods but single byte instructions
634      *
635      * @throws IOException if an I/O error occurs.
636      * @throws Pack200Exception
637      */
638     @Test
639     void testMultipleMethodsSimple() throws IOException, Pack200Exception {
640         numClasses = 2;
641         numMethods = new int[] { 3, 1 };
642         final byte[] bytes = { 50, 50, (byte) 255, 50, 50, (byte) 255, 50, 50, (byte) 255, 50, 50, (byte) 255 };
643         final InputStream in = new ByteArrayInputStream(bytes);
644         bcBands.unpack(in);
645         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
646         assertEquals(2, bcBands.getMethodByteCodePacked()[0][0].length);
647 
648         numClasses = 1;
649         numMethods = new int[] { 1 };
650     }
651 
652     /**
653      * Test with single byte instructions that mean all other bands apart from bc_codes will be empty.
654      *
655      * @throws IOException if an I/O error occurs.
656      * @throws Pack200Exception
657      */
658     @Test
659     void testSimple() throws IOException, Pack200Exception {
660         final byte[] bytes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
661                 45, 46, 47, 48, 49, 50, 51, 52, 53, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
662                 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
663                 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, (byte) 128, (byte) 129, (byte) 130, (byte) 131, (byte) 133, (byte) 134, (byte) 135,
664                 (byte) 136, (byte) 137, (byte) 138, (byte) 139, (byte) 140, (byte) 141, (byte) 142, (byte) 143, (byte) 144, (byte) 145, (byte) 146, (byte) 147,
665                 (byte) 148, (byte) 149, (byte) 150, (byte) 151, (byte) 172, (byte) 173, (byte) 174, (byte) 175, (byte) 176, (byte) 177, (byte) 190, (byte) 191,
666                 (byte) 194, (byte) 195, (byte) 255 };
667         final InputStream in = new ByteArrayInputStream(bytes);
668         bcBands.unpack(in);
669         assertEquals(bytes.length - 1, bcBands.getMethodByteCodePacked()[0][0].length);
670     }
671 
672     @Test
673     void testWideForms() throws IOException, Pack200Exception {
674         final byte[] bytes = { (byte) 196, (byte) 54, // wide istore
675                 (byte) 196, (byte) 132, // wide iinc
676                 (byte) 255, 0, // bc_short band
677                 0, 1 }; // bc_locals band
678         final InputStream in = new ByteArrayInputStream(bytes);
679         bcBands.unpack(in);
680         assertEquals(4, bcBands.getMethodByteCodePacked()[0][0].length);
681         assertEquals(2, bcBands.getBcLocal().length);
682         assertEquals(1, bcBands.getBcShort().length);
683     }
684 
685 }