• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ASM: a very small and fast Java bytecode manipulation framework
2 // Copyright (c) 2000-2011 INRIA, France Telecom
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holders nor the names of its
14 //    contributors may be used to endorse or promote products derived from
15 //    this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 // THE POSSIBILITY OF SUCH DAMAGE.
28 package org.objectweb.asm.tree;
29 
30 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
31 import static org.junit.jupiter.api.Assertions.assertEquals;
32 import static org.junit.jupiter.api.Assertions.assertFalse;
33 import static org.junit.jupiter.api.Assertions.assertNotNull;
34 import static org.junit.jupiter.api.Assertions.assertNotSame;
35 import static org.junit.jupiter.api.Assertions.assertNull;
36 import static org.junit.jupiter.api.Assertions.assertThrows;
37 import static org.junit.jupiter.api.Assertions.assertTrue;
38 
39 import java.util.ListIterator;
40 import java.util.NoSuchElementException;
41 import org.junit.jupiter.api.Test;
42 import org.junit.jupiter.api.function.Executable;
43 import org.objectweb.asm.Label;
44 import org.objectweb.asm.MethodVisitor;
45 import org.objectweb.asm.Opcodes;
46 
47 /**
48  * Unit tests for {@link InsnList}.
49  *
50  * @author Eric Bruneton
51  * @author Eugene Kuleshov
52  */
53 class InsnListTest {
54 
55   private final InsnNode insn1 = new InsnNode(0);
56   private final InsnNode insn2 = new InsnNode(1);
57 
58   @Test
testSize_emptyList()59   void testSize_emptyList() {
60     assertEquals(0, newInsnList().size());
61   }
62 
63   @Test
testGetFirst_emptyList()64   void testGetFirst_emptyList() {
65     assertEquals(null, newInsnList().getFirst());
66   }
67 
68   @Test
testGetLast_emptyList()69   void testGetLast_emptyList() {
70     assertEquals(null, newInsnList().getLast());
71   }
72 
73   @Test
testGet_outOfBounds()74   void testGet_outOfBounds() {
75     Executable get = () -> newInsnList().get(0);
76 
77     assertThrows(IndexOutOfBoundsException.class, get);
78   }
79 
80   @Test
testContains()81   void testContains() {
82     assertFalse(newInsnList().contains(new InsnNode(0)));
83   }
84 
85   @Test
testIndexOf_noSuchElement()86   void testIndexOf_noSuchElement() {
87     InsnList insnList = newInsnList();
88 
89     Executable indexOf = () -> insnList.indexOf(new InsnNode(0));
90 
91     assertThrows(NoSuchElementException.class, indexOf);
92   }
93 
94   @Test
testIndexOf()95   void testIndexOf() {
96     InsnList insnList = newInsnList(insn1, insn2);
97 
98     int index1 = insnList.indexOf(insn1);
99     int index2 = insnList.indexOf(insn2);
100 
101     assertEquals(0, index1);
102     assertEquals(1, index2);
103   }
104 
105   @Test
testAccept_cloneListVisitor()106   void testAccept_cloneListVisitor() {
107     InsnList insnList = newInsnList();
108     insnList.add(new InsnNode(55));
109     insnList.add(new InsnNode(77));
110     InsnList dstInsnList = new InsnList();
111 
112     insnList.accept(
113         new MethodVisitor(/* latest */ Opcodes.ASM10_EXPERIMENTAL) {
114           @Override
115           public void visitInsn(final int opcode) {
116             dstInsnList.add(new InsnNode(opcode));
117           }
118         });
119 
120     assertEquals(2, dstInsnList.size());
121     assertEquals(55, dstInsnList.get(0).opcode);
122     assertEquals(77, dstInsnList.get(1).opcode);
123   }
124 
125   @Test
testIteratorNext_noSuchElement()126   void testIteratorNext_noSuchElement() {
127     ListIterator<AbstractInsnNode> iterator = newInsnList().iterator();
128 
129     Executable next = () -> iterator.next();
130 
131     assertThrows(NoSuchElementException.class, next);
132   }
133 
134   @Test
testIteratorNext_nonEmptyList()135   void testIteratorNext_nonEmptyList() {
136     InsnList insnList = newInsnList(insn1, insn2);
137     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
138 
139     AbstractInsnNode insn = iterator.next();
140 
141     assertEquals(insn2, insn);
142     assertFalse(iterator.hasNext());
143     assertEquals(2, iterator.nextIndex());
144     assertTrue(iterator.hasPrevious());
145     assertEquals(1, iterator.previousIndex());
146   }
147 
148   @Test
testIteratorPrevious_noSuchElement()149   void testIteratorPrevious_noSuchElement() {
150     ListIterator<AbstractInsnNode> iterator = newInsnList().iterator();
151 
152     Executable previous = () -> iterator.previous();
153 
154     assertThrows(NoSuchElementException.class, previous);
155   }
156 
157   @Test
testIteratorPrevious_nonEmptyList()158   void testIteratorPrevious_nonEmptyList() {
159     InsnList insnList = newInsnList(insn1, insn2);
160     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
161 
162     AbstractInsnNode insn = iterator.previous();
163 
164     assertEquals(insn1, insn);
165     assertTrue(iterator.hasNext());
166     assertEquals(0, iterator.nextIndex());
167     assertFalse(iterator.hasPrevious());
168     assertEquals(-1, iterator.previousIndex());
169   }
170 
171   @Test
testIteratorAdd_emptyList()172   void testIteratorAdd_emptyList() {
173     InsnNode insn = new InsnNode(0);
174     InsnList insnList = newInsnList();
175 
176     insnList.iterator().add(insn);
177 
178     assertArrayEquals(new AbstractInsnNode[] {insn}, insnList.toArray());
179   }
180 
181   @Test
testIteratorAdd_firstInsn()182   void testIteratorAdd_firstInsn() {
183     InsnNode insn = new InsnNode(0);
184     InsnList insnList = newInsnList(insn1, insn2);
185     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
186 
187     iterator.add(insn);
188 
189     assertArrayEquals(new AbstractInsnNode[] {insn1, insn, insn2}, insnList.toArray());
190   }
191 
192   @Test
testIteratorRemove_illegalState()193   void testIteratorRemove_illegalState() {
194     InsnList insnList = newInsnList(insn1, insn2);
195     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
196 
197     Executable remove = () -> iterator.remove();
198 
199     assertThrows(IllegalStateException.class, remove);
200   }
201 
202   @Test
testIteratorRemove_afterNext()203   void testIteratorRemove_afterNext() {
204     InsnList insnList = newInsnList(insn1, insn2);
205     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
206     iterator.next();
207 
208     iterator.remove();
209 
210     assertArrayEquals(new AbstractInsnNode[] {insn1}, insnList.toArray());
211   }
212 
213   @Test
testIteratorRemove_afterPrevious()214   void testIteratorRemove_afterPrevious() {
215     InsnList insnList = newInsnList(insn1, insn2);
216     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
217     iterator.previous();
218 
219     iterator.remove();
220 
221     assertArrayEquals(new AbstractInsnNode[] {insn2}, insnList.toArray());
222   }
223 
224   @Test
testIteratorAdd_lastInsn()225   void testIteratorAdd_lastInsn() {
226     InsnNode insn = new InsnNode(0);
227     InsnList insnList = newInsnList(insn1, insn2);
228     ListIterator<AbstractInsnNode> iterator = insnList.iterator(2);
229 
230     iterator.add(insn);
231 
232     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2, insn}, insnList.toArray());
233   }
234 
235   @Test
testIteratorSet_illegalState()236   void testIteratorSet_illegalState() {
237     InsnNode insn = new InsnNode(0);
238     InsnList insnList = newInsnList(insn1, insn2);
239     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
240 
241     Executable set = () -> iterator.set(insn);
242 
243     assertThrows(IllegalStateException.class, set);
244   }
245 
246   @Test
testIteratorSet_afterNext()247   void testIteratorSet_afterNext() {
248     InsnNode insn = new InsnNode(0);
249     InsnList insnList = newInsnList(insn1, insn2);
250     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
251     iterator.next();
252 
253     iterator.set(insn);
254 
255     assertArrayEquals(new AbstractInsnNode[] {insn1, insn}, insnList.toArray());
256   }
257 
258   @Test
testIteratorSet_afterPrevious()259   void testIteratorSet_afterPrevious() {
260     InsnNode insn = new InsnNode(0);
261     InsnList insnList = newInsnList(insn1, insn2);
262     ListIterator<AbstractInsnNode> iterator = insnList.iterator(1);
263     iterator.previous();
264 
265     iterator.set(insn);
266 
267     assertArrayEquals(new AbstractInsnNode[] {insn, insn2}, insnList.toArray());
268   }
269 
270   @Test
testIterator_cacheIsNull()271   void testIterator_cacheIsNull() {
272     InsnList insnList = newInsnList(insn1, insn2);
273     insnList.iterator();
274     assertNull(insnList.cache);
275   }
276 
277   @Test
testToArray_emptyList()278   void testToArray_emptyList() {
279     assertEquals(0, newInsnList().toArray().length);
280   }
281 
282   @Test
testToArray_nonEmptyList()283   void testToArray_nonEmptyList() {
284     InsnList insnList = newInsnList(insn1, insn2);
285 
286     AbstractInsnNode[] insnArray = insnList.toArray();
287 
288     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2}, insnArray);
289   }
290 
291   @Test
testSet_noSuchElement()292   void testSet_noSuchElement() {
293     InsnList insnList = newInsnList();
294 
295     Executable set = () -> insnList.set(new InsnNode(0), new InsnNode(0));
296 
297     assertThrows(NoSuchElementException.class, set);
298   }
299 
300   @Test
testSet_singleInsn()301   void testSet_singleInsn() {
302     InsnList insnList = newInsnList();
303     insnList.add(insn1);
304     AbstractInsnNode insn = new InsnNode(0);
305 
306     insnList.set(insn1, insn);
307 
308     assertEquals(1, insnList.size());
309     assertEquals(insn, insnList.getFirst());
310   }
311 
312   @Test
testSet_firstInsn()313   void testSet_firstInsn() {
314     InsnList insnList = newInsnList(insn1, insn2);
315     AbstractInsnNode insn = new InsnNode(0);
316 
317     insnList.set(insn1, insn);
318 
319     assertEquals(2, insnList.size());
320     assertEquals(insn, insnList.getFirst());
321   }
322 
323   @Test
testSet_lastInsn()324   void testSet_lastInsn() {
325     InsnList insnList = newInsnList(insn1, insn2);
326     AbstractInsnNode insn = new InsnNode(0);
327     insnList.toArray();
328 
329     insnList.set(insn2, insn);
330 
331     assertEquals(2, insnList.size());
332     assertEquals(insn, insnList.getLast());
333   }
334 
335   @Test
testAdd_illegalArgument()336   void testAdd_illegalArgument() {
337     InsnList insnList = newInsnList();
338     newInsnList(insn1, insn2);
339 
340     Executable add = () -> insnList.add(insn1);
341 
342     assertThrows(IllegalArgumentException.class, add);
343   }
344 
345   @Test
testAdd_inEmptyList()346   void testAdd_inEmptyList() {
347     InsnList insnList = newInsnList();
348     InsnNode insn = new InsnNode(0);
349 
350     insnList.add(insn);
351 
352     assertEquals(1, insnList.size());
353     assertEquals(insn, insnList.getFirst());
354     assertEquals(insn, insnList.getLast());
355     assertEquals(insn, insnList.get(0));
356     assertTrue(insnList.contains(insn));
357     assertEquals(0, insnList.indexOf(insn));
358     assertArrayEquals(new AbstractInsnNode[] {insn}, insnList.toArray());
359     assertEquals(null, insn.getPrevious());
360     assertEquals(null, insn.getNext());
361   }
362 
363   @Test
testAdd_inNonEmptyList()364   void testAdd_inNonEmptyList() {
365     InsnList insnList = newInsnList();
366     insnList.add(insn1);
367     InsnNode insn = new InsnNode(0);
368 
369     insnList.add(insn);
370 
371     assertEquals(2, insnList.size());
372     assertEquals(insn, insnList.getLast());
373     assertEquals(1, insnList.indexOf(insn));
374     assertEquals(insn, insnList.get(1));
375     assertTrue(insnList.contains(insn));
376   }
377 
378   @Test
testAddList_illegalArgument()379   void testAddList_illegalArgument() {
380     InsnList insnList = newInsnList();
381 
382     Executable add = () -> insnList.add(insnList);
383 
384     assertThrows(IllegalArgumentException.class, add);
385   }
386 
387   @Test
testAddList_inEmptyList_emptyList()388   void testAddList_inEmptyList_emptyList() {
389     InsnList insnList = newInsnList();
390 
391     insnList.add(newInsnList());
392 
393     assertEquals(0, insnList.size());
394     assertEquals(null, insnList.getFirst());
395     assertEquals(null, insnList.getLast());
396     assertArrayEquals(new AbstractInsnNode[0], insnList.toArray());
397   }
398 
399   @Test
testAddList_inEmptyList_nonEmptyList()400   void testAddList_inEmptyList_nonEmptyList() {
401     InsnList insnList = newInsnList();
402 
403     insnList.add(newInsnList(insn1, insn2));
404 
405     assertEquals(2, insnList.size());
406     assertEquals(insn1, insnList.getFirst());
407     assertEquals(insn2, insnList.getLast());
408     assertEquals(insn1, insnList.get(0));
409     assertTrue(insnList.contains(insn1));
410     assertTrue(insnList.contains(insn2));
411     assertEquals(0, insnList.indexOf(insn1));
412     assertEquals(1, insnList.indexOf(insn2));
413     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2}, insnList.toArray());
414   }
415 
416   @Test
testAddList_inNonEmptyList_nonEmptyList()417   void testAddList_inNonEmptyList_nonEmptyList() {
418     InsnList insnList = newInsnList();
419     InsnNode insn = new InsnNode(0);
420     insnList.add(insn);
421 
422     insnList.add(newInsnList(insn1, insn2));
423 
424     assertEquals(3, insnList.size());
425     assertEquals(insn, insnList.getFirst());
426     assertEquals(insn2, insnList.getLast());
427     assertEquals(insn, insnList.get(0));
428     assertTrue(insnList.contains(insn));
429     assertTrue(insnList.contains(insn1));
430     assertTrue(insnList.contains(insn2));
431     assertEquals(0, insnList.indexOf(insn));
432     assertEquals(1, insnList.indexOf(insn1));
433     assertEquals(2, insnList.indexOf(insn2));
434     assertArrayEquals(new AbstractInsnNode[] {insn, insn1, insn2}, insnList.toArray());
435   }
436 
437   @Test
testInsert_illegalArgument()438   void testInsert_illegalArgument() {
439     InsnList insnList = newInsnList();
440     newInsnList(insn1, insn2);
441 
442     Executable insert = () -> insnList.insert(insn1);
443 
444     assertThrows(IllegalArgumentException.class, insert);
445   }
446 
447   @Test
testInsert_inEmptyList()448   void testInsert_inEmptyList() {
449     InsnList insnList = newInsnList();
450     InsnNode insn = new InsnNode(0);
451 
452     insnList.insert(insn);
453 
454     assertEquals(1, insnList.size());
455     assertEquals(insn, insnList.getFirst());
456     assertEquals(insn, insnList.getLast());
457     assertEquals(insn, insnList.get(0));
458     assertTrue(insnList.contains(insn));
459     assertEquals(0, insnList.indexOf(insn));
460     assertArrayEquals(new AbstractInsnNode[] {insn}, insnList.toArray());
461   }
462 
463   @Test
testInsert_inNonEmptyList()464   void testInsert_inNonEmptyList() {
465     InsnList insnList = newInsnList();
466     InsnNode insn = new InsnNode(0);
467     insnList.add(new InsnNode(0));
468 
469     insnList.insert(insn);
470 
471     assertEquals(2, insnList.size());
472     assertEquals(insn, insnList.getFirst());
473     assertEquals(insn, insnList.get(0));
474     assertTrue(insnList.contains(insn));
475     assertEquals(0, insnList.indexOf(insn));
476   }
477 
478   @Test
testInsertList_illegalArgument()479   void testInsertList_illegalArgument() {
480     InsnList insnList = newInsnList();
481 
482     Executable insert = () -> insnList.insert(insnList);
483 
484     assertThrows(IllegalArgumentException.class, insert);
485   }
486 
487   @Test
testInsertList_inEmptyList_emptyList()488   void testInsertList_inEmptyList_emptyList() {
489     InsnList insnList = newInsnList();
490 
491     insnList.insert(newInsnList());
492 
493     assertEquals(0, insnList.size());
494     assertEquals(null, insnList.getFirst());
495     assertEquals(null, insnList.getLast());
496     assertArrayEquals(new AbstractInsnNode[0], insnList.toArray());
497   }
498 
499   @Test
testInsertList_inEmptyList_nonEmptyList()500   void testInsertList_inEmptyList_nonEmptyList() {
501     InsnList insnList = newInsnList();
502 
503     insnList.insert(newInsnList(insn1, insn2));
504 
505     assertEquals(2, insnList.size(), 2);
506     assertEquals(insn1, insnList.getFirst());
507     assertEquals(insn2, insnList.getLast());
508     assertEquals(insn1, insnList.get(0));
509     assertTrue(insnList.contains(insn1));
510     assertTrue(insnList.contains(insn2));
511     assertEquals(0, insnList.indexOf(insn1));
512     assertEquals(1, insnList.indexOf(insn2));
513     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2}, insnList.toArray());
514   }
515 
516   @Test
testInsertList_inNonEmptyList_nonEmptyList()517   void testInsertList_inNonEmptyList_nonEmptyList() {
518     InsnList insnList = newInsnList();
519     InsnNode insn = new InsnNode(0);
520     insnList.add(insn);
521 
522     insnList.insert(newInsnList(insn1, insn2));
523 
524     assertEquals(3, insnList.size());
525     assertEquals(insn1, insnList.getFirst());
526     assertEquals(insn, insnList.getLast());
527     assertEquals(insn1, insnList.get(0));
528     assertTrue(insnList.contains(insn));
529     assertTrue(insnList.contains(insn1));
530     assertTrue(insnList.contains(insn2));
531     assertEquals(0, insnList.indexOf(insn1));
532     assertEquals(1, insnList.indexOf(insn2));
533     assertEquals(2, insnList.indexOf(insn));
534     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2, insn}, insnList.toArray());
535   }
536 
537   @Test
testInsertAfter_noSuchElement()538   void testInsertAfter_noSuchElement() {
539     InsnList insnList = newInsnList(insn1, insn2);
540 
541     Executable insert = () -> insnList.insert(new InsnNode(0), new InsnNode(0));
542 
543     assertThrows(NoSuchElementException.class, insert);
544   }
545 
546   @Test
testInsertAfter_lastInsn()547   void testInsertAfter_lastInsn() {
548     InsnList insnList = newInsnList(insn1, insn2);
549     InsnNode insn = new InsnNode(0);
550 
551     insnList.insert(insn2, insn);
552 
553     assertEquals(3, insnList.size());
554     assertEquals(insn1, insnList.getFirst());
555     assertEquals(insn, insnList.getLast());
556     assertEquals(insn1, insnList.get(0));
557     assertTrue(insnList.contains(insn));
558     assertEquals(2, insnList.indexOf(insn));
559     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2, insn}, insnList.toArray());
560   }
561 
562   @Test
testInsertAfter_notLastInsn()563   void testInsertAfter_notLastInsn() {
564     InsnList insnList = newInsnList(insn1, insn2);
565     InsnNode insn = new InsnNode(0);
566 
567     insnList.insert(insn1, insn);
568 
569     assertEquals(3, insnList.size());
570     assertEquals(insn1, insnList.getFirst());
571     assertEquals(insn2, insnList.getLast());
572     assertEquals(insn1, insnList.get(0));
573     assertTrue(insnList.contains(insn));
574     assertEquals(1, insnList.indexOf(insn));
575     assertArrayEquals(new AbstractInsnNode[] {insn1, insn, insn2}, insnList.toArray());
576   }
577 
578   @Test
testInsertListAfter_noSuchElement()579   void testInsertListAfter_noSuchElement() {
580     InsnList insnList = newInsnList(insn1, insn2);
581 
582     Executable insert = () -> insnList.insert(new InsnNode(0), newInsnList());
583 
584     assertThrows(NoSuchElementException.class, insert);
585   }
586 
587   @Test
testInsertListAfter_lastInsn_emptyList()588   void testInsertListAfter_lastInsn_emptyList() {
589     InsnList insnList = newInsnList();
590     InsnNode insn = new InsnNode(0);
591     insnList.add(insn);
592 
593     insnList.insert(insn, newInsnList());
594 
595     assertEquals(1, insnList.size());
596     assertEquals(insn, insnList.getFirst());
597     assertEquals(insn, insnList.getLast());
598     assertArrayEquals(new AbstractInsnNode[] {insn}, insnList.toArray());
599   }
600 
601   @Test
testInsertListAfter_lastInsn_nonEmptyList()602   void testInsertListAfter_lastInsn_nonEmptyList() {
603     InsnList insnList = newInsnList();
604     InsnNode insn = new InsnNode(0);
605     insnList.add(insn);
606 
607     insnList.insert(insn, newInsnList(insn1, insn2));
608 
609     assertEquals(3, insnList.size());
610     assertEquals(insn, insnList.getFirst());
611     assertEquals(insn2, insnList.getLast());
612     assertEquals(insn, insnList.get(0));
613     assertTrue(insnList.contains(insn));
614     assertTrue(insnList.contains(insn1));
615     assertTrue(insnList.contains(insn2));
616     assertEquals(0, insnList.indexOf(insn));
617     assertEquals(1, insnList.indexOf(insn1));
618     assertEquals(2, insnList.indexOf(insn2));
619     assertArrayEquals(new AbstractInsnNode[] {insn, insn1, insn2}, insnList.toArray());
620   }
621 
622   @Test
testInsertListAfter_notLastInsn_nonEmptyList()623   void testInsertListAfter_notLastInsn_nonEmptyList() {
624     InsnList insnList = newInsnList();
625     InsnNode insn = new InsnNode(0);
626     insnList.add(insn);
627     insnList.add(new InsnNode(0));
628 
629     insnList.insert(insn, newInsnList(insn1, insn2));
630 
631     assertEquals(4, insnList.size());
632     assertEquals(insn, insnList.getFirst());
633     assertEquals(insn, insnList.get(0));
634     assertTrue(insnList.contains(insn));
635     assertTrue(insnList.contains(insn1));
636     assertTrue(insnList.contains(insn2));
637     assertEquals(0, insnList.indexOf(insn));
638     assertEquals(1, insnList.indexOf(insn1));
639     assertEquals(2, insnList.indexOf(insn2));
640   }
641 
642   @Test
testInsertBefore_noSuchElement()643   void testInsertBefore_noSuchElement() {
644     InsnList insnList = newInsnList(insn1, insn2);
645 
646     Executable insertBefore = () -> insnList.insertBefore(new InsnNode(0), new InsnNode(0));
647 
648     assertThrows(NoSuchElementException.class, insertBefore);
649   }
650 
651   @Test
testInsertBefore_firstInsn()652   void testInsertBefore_firstInsn() {
653     InsnList insnList = newInsnList(insn1, insn2);
654     InsnNode insn = new InsnNode(0);
655 
656     insnList.insertBefore(insn1, insn);
657 
658     assertEquals(3, insnList.size());
659     assertEquals(insn, insnList.getFirst());
660     assertEquals(insn2, insnList.getLast());
661     assertEquals(insn, insnList.get(0));
662     assertTrue(insnList.contains(insn));
663     assertEquals(0, insnList.indexOf(insn));
664     assertArrayEquals(new AbstractInsnNode[] {insn, insn1, insn2}, insnList.toArray());
665   }
666 
667   @Test
testInsertBefore_notFirstInsn()668   void testInsertBefore_notFirstInsn() {
669     InsnList insnList = newInsnList(insn1, insn2);
670     InsnNode insn = new InsnNode(0);
671 
672     insnList.insertBefore(insn2, insn);
673 
674     assertEquals(3, insnList.size());
675     assertEquals(insn1, insnList.getFirst());
676     assertEquals(insn2, insnList.getLast());
677     assertEquals(insn, insnList.get(1));
678     assertTrue(insnList.contains(insn));
679     assertEquals(1, insnList.indexOf(insn));
680     assertArrayEquals(new AbstractInsnNode[] {insn1, insn, insn2}, insnList.toArray());
681   }
682 
683   @Test
testInsertListBefore_noSuchElement()684   void testInsertListBefore_noSuchElement() {
685     InsnList insnList = newInsnList(insn1, insn2);
686 
687     Executable insertBefore = () -> insnList.insertBefore(new InsnNode(0), newInsnList());
688 
689     assertThrows(NoSuchElementException.class, insertBefore);
690   }
691 
692   @Test
testInsertListBefore_firstInsn_emptyList()693   void testInsertListBefore_firstInsn_emptyList() {
694     InsnList insnList = newInsnList();
695     InsnNode insn = new InsnNode(0);
696     insnList.add(insn);
697 
698     insnList.insertBefore(insn, newInsnList());
699 
700     assertEquals(1, insnList.size());
701     assertEquals(insn, insnList.getFirst());
702     assertEquals(insn, insnList.getLast());
703     assertArrayEquals(new AbstractInsnNode[] {insn}, insnList.toArray());
704   }
705 
706   @Test
testInsertListBefore_firstInsn_nonEmptyList()707   void testInsertListBefore_firstInsn_nonEmptyList() {
708     InsnList insnList = newInsnList();
709     InsnNode insn = new InsnNode(0);
710     insnList.add(insn);
711 
712     insnList.insertBefore(insn, newInsnList(insn1, insn2));
713 
714     assertEquals(3, insnList.size());
715     assertEquals(insn1, insnList.getFirst());
716     assertEquals(insn, insnList.getLast());
717     assertEquals(insn1, insnList.get(0));
718     assertTrue(insnList.contains(insn));
719     assertTrue(insnList.contains(insn1));
720     assertTrue(insnList.contains(insn2));
721     assertEquals(2, insnList.indexOf(insn));
722     assertEquals(0, insnList.indexOf(insn1));
723     assertEquals(1, insnList.indexOf(insn2));
724     assertArrayEquals(new AbstractInsnNode[] {insn1, insn2, insn}, insnList.toArray());
725   }
726 
727   @Test
testInsertListBefore_notFirstInsn_nonEmptyList()728   void testInsertListBefore_notFirstInsn_nonEmptyList() {
729     InsnList insnList = newInsnList();
730     InsnNode insn = new InsnNode(0);
731     insnList.add(new InsnNode(0));
732     insnList.add(insn);
733 
734     insnList.insertBefore(insn, newInsnList(insn1, insn2));
735 
736     assertEquals(4, insnList.size());
737     assertEquals(insn1, insnList.get(1));
738     assertEquals(insn2, insnList.get(2));
739     assertTrue(insnList.contains(insn));
740     assertTrue(insnList.contains(insn1));
741     assertTrue(insnList.contains(insn2));
742     assertEquals(3, insnList.indexOf(insn));
743     assertEquals(1, insnList.indexOf(insn1));
744     assertEquals(2, insnList.indexOf(insn2));
745   }
746 
747   @Test
testRemove_noSuchElement()748   void testRemove_noSuchElement() {
749     InsnList insnList = newInsnList(insn1, insn2);
750 
751     Executable remove = () -> insnList.remove(new InsnNode(0));
752 
753     assertThrows(NoSuchElementException.class, remove);
754   }
755 
756   @Test
testRemove_singleInsn()757   void testRemove_singleInsn() {
758     InsnList insnList = newInsnList();
759     InsnNode insn = new InsnNode(0);
760     insnList.add(insn);
761 
762     insnList.remove(insn);
763 
764     assertEquals(0, insnList.size());
765     assertEquals(null, insnList.getFirst());
766     assertEquals(null, insnList.getLast());
767     assertFalse(insnList.contains(insn));
768     assertArrayEquals(new AbstractInsnNode[0], insnList.toArray());
769     assertEquals(null, insn.getPrevious());
770     assertEquals(null, insn.getNext());
771   }
772 
773   @Test
testRemove_firstInsn()774   void testRemove_firstInsn() {
775     InsnList insnList = newInsnList();
776     InsnNode insn = new InsnNode(0);
777     insnList.add(insn);
778     insnList.add(new InsnNode(0));
779 
780     insnList.remove(insn);
781 
782     assertFalse(insnList.contains(insn));
783     assertEquals(null, insn.getPrevious());
784     assertEquals(null, insn.getNext());
785   }
786 
787   @Test
testRemove_middleInsn()788   void testRemove_middleInsn() {
789     InsnList insnList = newInsnList();
790     InsnNode insn = new InsnNode(0);
791     insnList.add(new InsnNode(0));
792     insnList.add(insn);
793     insnList.add(new InsnNode(0));
794 
795     insnList.remove(insn);
796 
797     assertFalse(insnList.contains(insn));
798     assertEquals(null, insn.getPrevious());
799     assertEquals(null, insn.getNext());
800   }
801 
802   @Test
testRemove_lastInsn()803   void testRemove_lastInsn() {
804     InsnList insnList = newInsnList();
805     InsnNode insn = new InsnNode(0);
806     insnList.add(new InsnNode(0));
807     insnList.add(insn);
808 
809     insnList.remove(insn);
810 
811     assertFalse(insnList.contains(insn));
812     assertEquals(null, insn.getPrevious());
813     assertEquals(null, insn.getNext());
814   }
815 
816   @Test
testClear()817   void testClear() {
818     InsnList insnList = newInsnList();
819     InsnNode insn = new InsnNode(0);
820     insnList.add(new InsnNode(0));
821     insnList.add(insn);
822     insnList.add(new InsnNode(0));
823 
824     insnList.clear();
825 
826     assertEquals(0, insnList.size());
827     assertEquals(null, insnList.getFirst());
828     assertEquals(null, insnList.getLast());
829     assertFalse(insnList.contains(insn));
830     assertArrayEquals(new AbstractInsnNode[0], insnList.toArray());
831     assertEquals(null, insn.getPrevious());
832     assertEquals(null, insn.getNext());
833   }
834 
835   @Test
testResetLabels()836   void testResetLabels() {
837     InsnList insnList = newInsnList();
838     LabelNode labelNode = new LabelNode();
839     insnList.add(new InsnNode(55));
840     insnList.add(labelNode);
841     insnList.add(new InsnNode(77));
842     Label label = labelNode.getLabel();
843 
844     insnList.resetLabels();
845 
846     assertNotNull(label);
847     assertNotSame(label, labelNode.getLabel());
848   }
849 
newInsnList()850   private static InsnList newInsnList() {
851     return new CheckedInsnList();
852   }
853 
newInsnList(final InsnNode insnNode1, final InsnNode insnNode2)854   private static InsnList newInsnList(final InsnNode insnNode1, final InsnNode insnNode2) {
855     InsnList insnList = new CheckedInsnList();
856     insnList.add(insnNode1);
857     insnList.add(insnNode2);
858     return insnList;
859   }
860 
861   /** An {@link InsnList} which checks that its methods are properly used. */
862   static class CheckedInsnList extends InsnList {
863 
864     @Override
indexOf(final AbstractInsnNode insnNode)865     public int indexOf(final AbstractInsnNode insnNode) {
866       if (!contains(insnNode)) {
867         throw new NoSuchElementException();
868       }
869       return super.indexOf(insnNode);
870     }
871 
872     @Override
set(final AbstractInsnNode oldInsnNode, final AbstractInsnNode newInsnNode)873     public void set(final AbstractInsnNode oldInsnNode, final AbstractInsnNode newInsnNode) {
874       if (!contains(oldInsnNode)) {
875         throw new NoSuchElementException();
876       }
877       if (newInsnNode.index != -1) {
878         throw new IllegalArgumentException();
879       }
880       super.set(oldInsnNode, newInsnNode);
881     }
882 
883     @Override
add(final AbstractInsnNode insnNode)884     public void add(final AbstractInsnNode insnNode) {
885       if (insnNode.index != -1) {
886         throw new IllegalArgumentException();
887       }
888       super.add(insnNode);
889     }
890 
891     @Override
add(final InsnList insnList)892     public void add(final InsnList insnList) {
893       if (insnList == this) {
894         throw new IllegalArgumentException();
895       }
896       super.add(insnList);
897     }
898 
899     @Override
insert(final AbstractInsnNode insnNode)900     public void insert(final AbstractInsnNode insnNode) {
901       if (insnNode.index != -1) {
902         throw new IllegalArgumentException();
903       }
904       super.insert(insnNode);
905     }
906 
907     @Override
insert(final InsnList insnList)908     public void insert(final InsnList insnList) {
909       if (insnList == this) {
910         throw new IllegalArgumentException();
911       }
912       super.insert(insnList);
913     }
914 
915     @Override
insert(final AbstractInsnNode previousInsn, final AbstractInsnNode insnNode)916     public void insert(final AbstractInsnNode previousInsn, final AbstractInsnNode insnNode) {
917       if (!contains(previousInsn)) {
918         throw new NoSuchElementException();
919       }
920       if (insnNode.index != -1) {
921         throw new IllegalArgumentException();
922       }
923       super.insert(previousInsn, insnNode);
924     }
925 
926     @Override
insert(final AbstractInsnNode previousInsn, final InsnList insnList)927     public void insert(final AbstractInsnNode previousInsn, final InsnList insnList) {
928       if (!contains(previousInsn)) {
929         throw new NoSuchElementException();
930       }
931       if (insnList == this) {
932         throw new IllegalArgumentException();
933       }
934       super.insert(previousInsn, insnList);
935     }
936 
937     @Override
insertBefore(final AbstractInsnNode nextInsn, final AbstractInsnNode insnNode)938     public void insertBefore(final AbstractInsnNode nextInsn, final AbstractInsnNode insnNode) {
939       if (!contains(nextInsn)) {
940         throw new NoSuchElementException();
941       }
942       if (insnNode.index != -1) {
943         throw new IllegalArgumentException();
944       }
945       super.insertBefore(nextInsn, insnNode);
946     }
947 
948     @Override
insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList)949     public void insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList) {
950       if (!contains(nextInsn)) {
951         throw new NoSuchElementException();
952       }
953       if (insnList == this) {
954         throw new IllegalArgumentException();
955       }
956       super.insertBefore(nextInsn, insnList);
957     }
958 
959     @Override
remove(final AbstractInsnNode insnNode)960     public void remove(final AbstractInsnNode insnNode) {
961       if (!contains(insnNode)) {
962         throw new NoSuchElementException();
963       }
964       super.remove(insnNode);
965     }
966 
967     @Override
clear()968     public void clear() {
969       removeAll(true);
970       super.clear();
971     }
972   }
973 }
974