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   *   http://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.maven.shared.dependency.analyzer.asm;
20  
21  import org.junit.Before;
22  import org.junit.Test;
23  import org.objectweb.asm.*;
24  import org.objectweb.asm.signature.SignatureVisitor;
25  
26  import static org.assertj.core.api.Assertions.assertThat;
27  
28  /**
29   * Tests <code>DependencyVisitor</code>.
30   *
31   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
32   */
33  public class DependencyVisitorTest {
34      private final ResultCollector resultCollector = new ResultCollector();
35      private DefaultClassVisitor visitor;
36      private MethodVisitor mv;
37  
38      @Before
39      public void setUp() {
40          AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor(resultCollector);
41          SignatureVisitor signatureVisitor = new DefaultSignatureVisitor(resultCollector);
42          FieldVisitor fieldVisitor = new DefaultFieldVisitor(annotationVisitor, resultCollector);
43          mv = new DefaultMethodVisitor(annotationVisitor, signatureVisitor, resultCollector);
44          visitor = new DefaultClassVisitor(signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector);
45      }
46  
47      @Test
48      public void testVisitWithDefaultSuperclass() {
49          // class a.b.c
50          visitor.visit(50, 0, "a/b/c", null, "java/lang/Object", null);
51  
52          assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object");
53      }
54  
55      @Test
56      public void testVisitWithSuperclass() {
57          // class a.b.c
58          visitor.visit(50, 0, "a/b/c", null, "x/y/z", null);
59  
60          assertThat(resultCollector.getDependencies()).containsOnly("x.y.z");
61      }
62  
63      @Test
64      public void testVisitWithInterface() {
65          // class a.b.c implements x.y.z
66          visitor.visit(50, 0, "a/b/c", null, "java/lang/Object", new String[] {"x/y/z"});
67  
68          assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "x.y.z");
69      }
70  
71      @Test
72      public void testVisitWithInterfaces() {
73          // class a.b.c implements p.q.r, x.y.z
74          visitor.visit(50, 0, "a/b/c", null, "java/lang/Object", new String[] {"p/q/r", "x/y/z"});
75  
76          assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "p.q.r", "x.y.z");
77      }
78  
79      @Test
80      public void testVisitWithUnboundedClassTypeParameter() {
81          // class a.b.c<T>
82          String signature = "<T:Ljava/lang/Object;>Ljava/lang/Object;";
83  
84          visitor.visit(50, 0, "a/b/c", signature, "java/lang/Object", null);
85  
86          assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object");
87      }
88  
89      @Test
90      public void testVisitWithBoundedClassTypeParameter() {
91          // class a.b.c<T extends x.y.z>
92          String signature = "<T:Lx/y/z;>Ljava/lang/Object;";
93  
94          visitor.visit(50, 0, "a/b/c", signature, "java/lang/Object", null);
95  
96          assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "x.y.z");
97      }
98  
99      @Test
100     public void testVisitWithBoundedClassTypeParameters() {
101         // class a.b.c<K extends p.q.r, V extends x.y.z>
102         String signature = "<K:Lp/q/r;V:Lx/y/z;>Ljava/lang/Object;";
103 
104         visitor.visit(50, 0, "a/b/c", signature, "java/lang/Object", null);
105 
106         assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "p.q.r", "x.y.z");
107     }
108 
109     @Test
110     public void testVisitWithGenericInterface() {
111         // class a.b.c implements p.q.r<x.y.z>
112         String signature = "Ljava/lang/Object;Lp/q/r<Lx/y/z;>;";
113 
114         visitor.visit(50, 0, "a/b/c", signature, "java/lang/Object", new String[] {"p.q.r"});
115 
116         assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "p.q.r", "x.y.z");
117     }
118 
119     @Test
120     public void testVisitWithInterfaceBound() {
121         // class a.b.c<T> implements x.y.z<T>
122         String signature = "<T:Ljava/lang/Object;>Ljava/lang/Object;Lx/y/z<TT;>;";
123 
124         visitor.visit(50, 0, "a/b/c", signature, "java/lang/Object", new String[] {"x.y.z"});
125 
126         assertThat(resultCollector.getDependencies()).containsOnly("java.lang.Object", "x.y.z");
127     }
128 
129     // visitSource tests ------------------------------------------------------
130 
131     @Test
132     public void testVisitSource() {
133         visitor.visitSource(null, null);
134 
135         assertThat(resultCollector.getDependencies()).isEmpty();
136     }
137 
138     // visitOuterClass tests --------------------------------------------------
139 
140     @Test
141     public void testVisitOuterClass() {
142         // class a.b.c
143         // {
144         //     class ...
145         //     {
146         //     }
147         // }
148         visitor.visitOuterClass("a/b/c", null, null);
149 
150         assertThat(resultCollector.getDependencies()).isEmpty();
151     }
152 
153     @Test
154     public void testVisitOuterClassInMethod() {
155         // class a.b.c
156         // {
157         //     x.y.z x(p.q.r p)
158         //     {
159         //         class ...
160         //         {
161         //         }
162         //     }
163         // }
164         visitor.visitOuterClass("a/b/c", "x", "(Lp/q/r;)Lx/y/z;");
165 
166         assertThat(resultCollector.getDependencies()).isEmpty();
167     }
168 
169     // visitAnnotation tests --------------------------------------------------
170 
171     @Test
172     public void testVisitAnnotation() {
173         assertVisitor(visitor.visitAnnotation("La/b/c;", false));
174 
175         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
176     }
177 
178     @Test
179     public void testVisitAnnotationWithRuntimeVisibility() {
180         assertVisitor(visitor.visitAnnotation("La/b/c;", true));
181 
182         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
183     }
184 
185     // visitAttribute tests ---------------------------------------------------
186 
187     @Test
188     public void testVisitAttribute() {
189         visitor.visitAttribute(new MockAttribute("a"));
190 
191         assertThat(resultCollector.getDependencies()).isEmpty();
192     }
193 
194     // visitInnerClass tests --------------------------------------------------
195 
196     @Test
197     public void testVisitInnerClass() {
198         // TODO: ensure innerName is correct
199 
200         // class a.b.c { class x.y.z { } }
201         visitor.visitInnerClass("x/y/z", "a/b/c", "z", 0);
202 
203         assertThat(resultCollector.getDependencies()).isEmpty();
204     }
205 
206     @Test
207     public void testVisitInnerClassAnonymous() {
208         // class a.b.c { new class x.y.z { } }
209         visitor.visitInnerClass("x/y/z$1", "a/b/c", null, 0);
210 
211         assertThat(resultCollector.getDependencies()).isEmpty();
212     }
213 
214     // visitField tests -------------------------------------------------------
215 
216     @Test
217     public void testVisitField() {
218         // a.b.c a
219         assertVisitor(visitor.visitField(0, "a", "La/b/c;", null, null));
220 
221         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
222     }
223 
224     // TODO: determine actual use of default values
225     // public void testVisitFieldWithValue()
226     // {
227     // }
228 
229     @Test
230     public void testVisitFieldArray() {
231         // a.b.c[] a
232         assertVisitor(visitor.visitField(0, "a", "[La/b/c;", null, null));
233 
234         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
235     }
236 
237     @Test
238     public void testVisitFieldGeneric() {
239         // a.b.c<x.y.z> a
240         assertVisitor(visitor.visitField(0, "a", "La/b/c;", "La/b/c<Lx/y/z;>;", null));
241 
242         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
243     }
244 
245     // visitMethod tests ------------------------------------------------------
246 
247     @Test
248     public void testVisitMethod() {
249         // void a()
250         assertVisitor(visitor.visitMethod(0, "a", "()V", null, null));
251 
252         assertThat(resultCollector.getDependencies()).isEmpty();
253     }
254 
255     @Test
256     public void testVisitMethodWithPrimitiveArgument() {
257         // void a(int)
258         assertVisitor(visitor.visitMethod(0, "a", "(I)V", null, null));
259 
260         assertThat(resultCollector.getDependencies()).isEmpty();
261     }
262 
263     @Test
264     public void testVisitMethodWithPrimitiveArrayArgument() {
265         // void a(int[])
266         assertVisitor(visitor.visitMethod(0, "a", "([I)V", null, null));
267 
268         assertThat(resultCollector.getDependencies()).isEmpty();
269     }
270 
271     @Test
272     public void testVisitMethodWithObjectArgument() {
273         // void a(a.b.c)
274         assertVisitor(visitor.visitMethod(0, "a", "(La/b/c;)V", null, null));
275 
276         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
277     }
278 
279     @Test
280     public void testVisitMethodWithObjectArguments() {
281         // void a(a.b.c, x.y.z)
282         assertVisitor(visitor.visitMethod(0, "a", "(La/b/c;Lx/y/z;)V", null, null));
283 
284         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
285     }
286 
287     @Test
288     public void testVisitMethodWithObjectArrayArgument() {
289         // void a(a.b.c[])
290         assertVisitor(visitor.visitMethod(0, "a", "([La/b/c;)V", null, null));
291 
292         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
293     }
294 
295     @Test
296     public void testVisitMethodWithGenericArgument() {
297         // void a(a.b.c<x.y.z>)
298         assertVisitor(visitor.visitMethod(0, "a", "(La/b/c;)V", "(La/b/c<Lx/y/z;>;)V", null));
299 
300         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
301     }
302 
303     @Test
304     public void testVisitMethodWithPrimitiveReturnType() {
305         // int a()
306         assertVisitor(visitor.visitMethod(0, "a", "()I", null, null));
307 
308         assertThat(resultCollector.getDependencies()).isEmpty();
309     }
310 
311     @Test
312     public void testVisitMethodWithPrimitiveArrayReturnType() {
313         // int[] a()
314         assertVisitor(visitor.visitMethod(0, "a", "()[I", null, null));
315 
316         assertThat(resultCollector.getDependencies()).isEmpty();
317     }
318 
319     @Test
320     public void testVisitMethodWithObjectReturnType() {
321         // a.b.c a()
322         assertVisitor(visitor.visitMethod(0, "a", "()La/b/c;", null, null));
323 
324         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
325     }
326 
327     @Test
328     public void testVisitMethodWithObjectArrayReturnType() {
329         // a.b.c[] a()
330         assertVisitor(visitor.visitMethod(0, "a", "()[La/b/c;", null, null));
331 
332         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
333     }
334 
335     @Test
336     public void testVisitMethodWithException() {
337         // void a() throws a.b.c
338         assertVisitor(visitor.visitMethod(0, "a", "()V", null, new String[] {"a/b/c"}));
339 
340         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
341     }
342 
343     @Test
344     public void testVisitMethodWithExceptions() {
345         // void a() throws a.b.c, x.y.z
346         assertVisitor(visitor.visitMethod(0, "a", "()V", null, new String[] {"a/b/c", "x/y/z"}));
347 
348         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
349     }
350 
351     // visitAnnotationDefault tests -------------------------------------------
352 
353     @Test
354     public void testVisitAnnotationDefault() {
355         assertVisitor(mv.visitAnnotationDefault());
356         assertThat(resultCollector.getDependencies()).isEmpty();
357     }
358 
359     // visitParameterAnnotation tests -------------------------------------------
360 
361     @Test
362     public void testVisitParameterAnnotation() {
363         // @a.b.c
364         assertVisitor(mv.visitParameterAnnotation(0, "La/b/c;", false));
365 
366         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
367     }
368 
369     // visitCode tests --------------------------------------------------------
370 
371     @Test
372     public void testVisitCode() {
373         mv.visitCode();
374 
375         assertThat(resultCollector.getDependencies()).isEmpty();
376     }
377 
378     // visitFrame tests -------------------------------------------------------
379 
380     @Test
381     public void testVisitFrame() {
382         mv.visitFrame(Opcodes.F_NEW, 0, new Object[0], 0, new Object[0]);
383 
384         assertThat(resultCollector.getDependencies()).isEmpty();
385     }
386 
387     // visitInsn tests --------------------------------------------------------
388 
389     @Test
390     public void testVisitInsn() {
391         mv.visitInsn(Opcodes.NOP);
392 
393         assertThat(resultCollector.getDependencies()).isEmpty();
394     }
395 
396     // visitIntInsn tests -----------------------------------------------------
397 
398     @Test
399     public void testVisitIntInsn() {
400         mv.visitIntInsn(Opcodes.BIPUSH, 0);
401 
402         assertThat(resultCollector.getDependencies()).isEmpty();
403     }
404 
405     // visitVarInsn tests -----------------------------------------------------
406 
407     @Test
408     public void testVisitVarInsn() {
409         mv.visitVarInsn(Opcodes.ILOAD, 0);
410 
411         assertThat(resultCollector.getDependencies()).isEmpty();
412     }
413 
414     // visitTypeInsn tests ----------------------------------------------------
415 
416     @Test
417     public void testVisitTypeInsn() {
418         mv.visitTypeInsn(Opcodes.NEW, "a/b/c");
419 
420         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
421     }
422 
423     // visitFieldInsn tests ---------------------------------------------------
424 
425     @Test
426     public void testVisitFieldInsnWithPrimitive() {
427         mv.visitFieldInsn(Opcodes.GETFIELD, "a/b/c", "x", "I");
428 
429         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
430     }
431 
432     @Test
433     public void testVisitFieldInsnWithObject() {
434         mv.visitFieldInsn(Opcodes.GETFIELD, "a/b/c", "x", "Lx/y/z;");
435 
436         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
437     }
438 
439     // visitMethodInsn tests --------------------------------------------------
440 
441     @Test
442     public void testVisitMethodInsn() {
443         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()V", false);
444 
445         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
446     }
447 
448     @Test
449     public void testVisitMethodInsnWithPrimitiveArgument() {
450         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(I)V", false);
451 
452         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
453     }
454 
455     @Test
456     public void testVisitMethodInsnWithPrimitiveArrayArgument() {
457         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "([I)V", false);
458 
459         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
460     }
461 
462     @Test
463     public void testVisitMethodInsnWithObjectArgument() {
464         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(Lx/y/z;)V", false);
465 
466         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
467     }
468 
469     @Test
470     public void testVisitMethodInsnWithObjectArguments() {
471         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(Lp/q/r;Lx/y/z;)V", false);
472 
473         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
474     }
475 
476     @Test
477     public void testVisitMethodInsnWithObjectArrayArgument() {
478         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "([Lx/y/z;)V", false);
479 
480         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
481     }
482 
483     @Test
484     public void testVisitMethodInsnWithPrimitiveReturnType() {
485         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()I", false);
486 
487         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
488     }
489 
490     @Test
491     public void testVisitMethodInsnWithPrimitiveArrayReturnType() {
492         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()[I", false);
493 
494         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
495     }
496 
497     @Test
498     public void testVisitMethodInsnWithObjectReturnType() {
499         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()Lx/y/z;", false);
500 
501         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
502     }
503 
504     @Test
505     public void testVisitMethodInsnWithObjectArrayReturnType() {
506         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()[Lx/y/z;", false);
507 
508         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
509     }
510 
511     // visitJumpInsn tests ----------------------------------------------------
512 
513     @Test
514     public void testVisitJumpInsn() {
515         mv.visitJumpInsn(Opcodes.IFEQ, new Label());
516 
517         assertThat(resultCollector.getDependencies()).isEmpty();
518     }
519 
520     // visitLabel tests -------------------------------------------------------
521 
522     @Test
523     public void testVisitLabel() {
524         mv.visitLabel(new Label());
525 
526         assertThat(resultCollector.getDependencies()).isEmpty();
527     }
528 
529     // visitLdcInsn tests -----------------------------------------------------
530 
531     @Test
532     public void testVisitLdcInsnWithNonType() {
533         mv.visitLdcInsn("a");
534 
535         assertThat(resultCollector.getDependencies()).isEmpty();
536     }
537 
538     @Test
539     public void testVisitLdcInsnWithPrimitiveType() {
540         mv.visitLdcInsn(Type.INT_TYPE);
541 
542         assertThat(resultCollector.getDependencies()).isEmpty();
543     }
544 
545     @Test
546     public void testVisitLdcInsnWithObjectType() {
547         mv.visitLdcInsn(Type.getType("La/b/c;"));
548 
549         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
550     }
551 
552     // visitIincInsn tests ----------------------------------------------------
553 
554     @Test
555     public void testVisitIincInsn() {
556         mv.visitIincInsn(0, 1);
557 
558         assertThat(resultCollector.getDependencies()).isEmpty();
559     }
560 
561     // visitTableSwitchInsn tests ---------------------------------------------
562 
563     @Test
564     public void testVisitTableSwitchInsn() {
565         mv.visitTableSwitchInsn(0, 1, new Label(), new Label());
566 
567         assertThat(resultCollector.getDependencies()).isEmpty();
568     }
569 
570     // visitLookupSwitchInsn tests --------------------------------------------
571 
572     @Test
573     public void testVisitLookupSwitchInsn() {
574         mv.visitLookupSwitchInsn(new Label(), new int[] {0}, new Label[] {new Label()});
575 
576         assertThat(resultCollector.getDependencies()).isEmpty();
577     }
578 
579     // visitMultiANewArrayInsn tests ------------------------------------------
580 
581     @Test
582     public void testVisitMultiANewArrayInsnWithPrimitive() {
583         mv.visitMultiANewArrayInsn("I", 2);
584 
585         assertThat(resultCollector.getDependencies()).isEmpty();
586     }
587 
588     @Test
589     public void testVisitMultiANewArrayInsnWithObject() {
590         mv.visitMultiANewArrayInsn("La/b/c;", 2);
591 
592         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
593     }
594 
595     // visitTryCatchBlock tests -----------------------------------------------
596 
597     @Test
598     public void testVisitTryCatchBlock() {
599         mv.visitTryCatchBlock(new Label(), new Label(), new Label(), "a/b/c");
600 
601         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
602     }
603 
604     @Test
605     public void testVisitTryCatchBlockForFinally() {
606         mv.visitTryCatchBlock(new Label(), new Label(), new Label(), null);
607 
608         assertThat(resultCollector.getDependencies()).isEmpty();
609     }
610 
611     // visitLocalVariable tests -----------------------------------------------
612 
613     @Test
614     public void testVisitLocalVariableWithPrimitive() {
615         mv.visitLocalVariable("a", "I", null, new Label(), new Label(), 0);
616 
617         assertThat(resultCollector.getDependencies()).isEmpty();
618     }
619 
620     @Test
621     public void testVisitLocalVariableWithPrimitiveArray() {
622         mv.visitLocalVariable("a", "[I", null, new Label(), new Label(), 0);
623 
624         assertThat(resultCollector.getDependencies()).isEmpty();
625     }
626 
627     @Test
628     public void testVisitLocalVariableWithObject() {
629         mv.visitLocalVariable("a", "La/b/c;", null, new Label(), new Label(), 0);
630 
631         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
632     }
633 
634     @Test
635     public void testVisitLocalVariableWithObjectArray() {
636         mv.visitLocalVariable("a", "[La/b/c;", null, new Label(), new Label(), 0);
637 
638         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c");
639     }
640 
641     @Test
642     public void testVisitLocalVariableWithGenericObject() {
643         mv.visitLocalVariable("a", "La/b/c;", "La/b/c<Lx/y/z;>;", new Label(), new Label(), 0);
644 
645         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
646     }
647 
648     @Test
649     public void testVisitLocalVariableWithGenericObjectArray() {
650         mv.visitLocalVariable("a", "La/b/c;", "[La/b/c<Lx/y/z;>;", new Label(), new Label(), 0);
651 
652         assertThat(resultCollector.getDependencies()).containsOnly("a.b.c", "x.y.z");
653     }
654 
655     // visitLineNumber tests --------------------------------------------------
656 
657     @Test
658     public void testVisitLineNumber() {
659         mv.visitLineNumber(0, new Label());
660 
661         assertThat(resultCollector.getDependencies()).isEmpty();
662     }
663 
664     // visitMaxs tests --------------------------------------------------------
665 
666     @Test
667     public void testVisitMaxs() {
668         mv.visitMaxs(0, 0);
669 
670         assertThat(resultCollector.getDependencies()).isEmpty();
671     }
672 
673     private void assertVisitor(Object actualVisitor) {
674         // assertEquals( visitor, actualVisitor );
675     }
676 
677     /**
678      * A simple ASM <code>Attribute</code> for use in tests.
679      *
680      * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
681      */
682     static class MockAttribute extends Attribute {
683         public MockAttribute(String type) {
684             super(type);
685         }
686     }
687 }