blob: 64ea0412247dc5961e8b3aba8df5094ec0698d1d [file] [log] [blame]
package org.apache.maven.shared.dependency.analyzer.asm;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.objectweb.asm.*;
import org.objectweb.asm.signature.SignatureVisitor;
import static org.junit.Assert.assertEquals;
/**
* Tests <code>DependencyVisitor</code>.
*
* @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
*/
public class DependencyVisitorTest
{
private final ResultCollector resultCollector = new ResultCollector();
private DefaultClassVisitor visitor;
private MethodVisitor mv;
@Before
public void setUp()
{
AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor( resultCollector );
SignatureVisitor signatureVisitor = new DefaultSignatureVisitor( resultCollector );
FieldVisitor fieldVisitor = new DefaultFieldVisitor( annotationVisitor, resultCollector );
mv = new DefaultMethodVisitor( annotationVisitor, signatureVisitor, resultCollector);
visitor = new DefaultClassVisitor( signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector);
}
@Test
public void testVisitWithDefaultSuperclass()
{
// class a.b.c
visitor.visit( 50, 0, "a/b/c", null, "java/lang/Object", null );
assertClasses( "java.lang.Object" );
}
@Test
public void testVisitWithSuperclass()
{
// class a.b.c
visitor.visit( 50, 0, "a/b/c", null, "x/y/z", null );
assertClasses( "x.y.z" );
}
@Test
public void testVisitWithInterface()
{
// class a.b.c implements x.y.z
visitor.visit( 50, 0, "a/b/c", null, "java/lang/Object", new String[] { "x/y/z" } );
assertClasses( "java.lang.Object", "x.y.z" );
}
@Test
public void testVisitWithInterfaces()
{
// class a.b.c implements p.q.r, x.y.z
visitor.visit( 50, 0, "a/b/c", null, "java/lang/Object", new String[] { "p/q/r", "x/y/z" } );
assertClasses( "java.lang.Object", "p.q.r", "x.y.z" );
}
@Test
public void testVisitWithUnboundedClassTypeParameter()
{
// class a.b.c<T>
String signature = "<T:Ljava/lang/Object;>Ljava/lang/Object;";
visitor.visit( 50, 0, "a/b/c", signature, "java/lang/Object", null );
assertClasses( "java.lang.Object" );
}
@Test
public void testVisitWithBoundedClassTypeParameter()
{
// class a.b.c<T extends x.y.z>
String signature = "<T:Lx/y/z;>Ljava/lang/Object;";
visitor.visit( 50, 0, "a/b/c", signature, "java/lang/Object", null );
assertClasses( "java.lang.Object", "x.y.z" );
}
@Test
public void testVisitWithBoundedClassTypeParameters()
{
// class a.b.c<K extends p.q.r, V extends x.y.z>
String signature = "<K:Lp/q/r;V:Lx/y/z;>Ljava/lang/Object;";
visitor.visit( 50, 0, "a/b/c", signature, "java/lang/Object", null );
assertClasses( "java.lang.Object", "p.q.r", "x.y.z" );
}
@Test
public void testVisitWithGenericInterface()
{
// class a.b.c implements p.q.r<x.y.z>
String signature = "Ljava/lang/Object;Lp/q/r<Lx/y/z;>;";
visitor.visit( 50, 0, "a/b/c", signature, "java/lang/Object", new String[] { "p.q.r" } );
assertClasses( "java.lang.Object", "p.q.r", "x.y.z" );
}
@Test
public void testVisitWithInterfaceBound()
{
// class a.b.c<T> implements x.y.z<T>
String signature = "<T:Ljava/lang/Object;>Ljava/lang/Object;Lx/y/z<TT;>;";
visitor.visit( 50, 0, "a/b/c", signature, "java/lang/Object", new String[] { "x.y.z" } );
assertClasses( "java.lang.Object", "x.y.z" );
}
// visitSource tests ------------------------------------------------------
@Test
public void testVisitSource()
{
visitor.visitSource( null, null );
assertNoClasses();
}
// visitOuterClass tests --------------------------------------------------
@Test
public void testVisitOuterClass()
{
// class a.b.c
// {
// class ...
// {
// }
// }
visitor.visitOuterClass( "a/b/c", null, null );
assertNoClasses();
}
@Test
public void testVisitOuterClassInMethod()
{
// class a.b.c
// {
// x.y.z x(p.q.r p)
// {
// class ...
// {
// }
// }
// }
visitor.visitOuterClass( "a/b/c", "x", "(Lp/q/r;)Lx/y/z;" );
assertNoClasses();
}
// visitAnnotation tests --------------------------------------------------
@Test
public void testVisitAnnotation()
{
assertVisitor( visitor.visitAnnotation( "La/b/c;", false ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitAnnotationWithRuntimeVisibility()
{
assertVisitor( visitor.visitAnnotation( "La/b/c;", true ) );
assertClasses( "a.b.c" );
}
// visitAttribute tests ---------------------------------------------------
@Test
public void testVisitAttribute()
{
visitor.visitAttribute( new MockAttribute( "a" ) );
assertNoClasses();
}
// visitInnerClass tests --------------------------------------------------
@Test
public void testVisitInnerClass()
{
// TODO: ensure innerName is correct
// class a.b.c { class x.y.z { } }
visitor.visitInnerClass( "x/y/z", "a/b/c", "z", 0 );
assertNoClasses();
}
@Test
public void testVisitInnerClassAnonymous()
{
// class a.b.c { new class x.y.z { } }
visitor.visitInnerClass( "x/y/z$1", "a/b/c", null, 0 );
assertNoClasses();
}
// visitField tests -------------------------------------------------------
@Test
public void testVisitField()
{
// a.b.c a
assertVisitor( visitor.visitField( 0, "a", "La/b/c;", null, null ) );
assertClasses( "a.b.c" );
}
// TODO: determine actual use of default values
// public void testVisitFieldWithValue()
// {
// }
@Test
public void testVisitFieldArray()
{
// a.b.c[] a
assertVisitor( visitor.visitField( 0, "a", "[La/b/c;", null, null ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitFieldGeneric()
{
// a.b.c<x.y.z> a
assertVisitor( visitor.visitField( 0, "a", "La/b/c;", "La/b/c<Lx/y/z;>;", null ) );
assertClasses( "a.b.c", "x.y.z" );
}
// visitMethod tests ------------------------------------------------------
@Test
public void testVisitMethod()
{
// void a()
assertVisitor( visitor.visitMethod( 0, "a", "()V", null, null ) );
assertNoClasses();
}
@Test
public void testVisitMethodWithPrimitiveArgument()
{
// void a(int)
assertVisitor( visitor.visitMethod( 0, "a", "(I)V", null, null ) );
assertNoClasses();
}
@Test
public void testVisitMethodWithPrimitiveArrayArgument()
{
// void a(int[])
assertVisitor( visitor.visitMethod( 0, "a", "([I)V", null, null ) );
assertNoClasses();
}
@Test
public void testVisitMethodWithObjectArgument()
{
// void a(a.b.c)
assertVisitor( visitor.visitMethod( 0, "a", "(La/b/c;)V", null, null ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodWithObjectArguments()
{
// void a(a.b.c, x.y.z)
assertVisitor( visitor.visitMethod( 0, "a", "(La/b/c;Lx/y/z;)V", null, null ) );
assertClasses( "a.b.c", "x.y.z" );
}
@Test
public void testVisitMethodWithObjectArrayArgument()
{
// void a(a.b.c[])
assertVisitor( visitor.visitMethod( 0, "a", "([La/b/c;)V", null, null ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodWithGenericArgument()
{
// void a(a.b.c<x.y.z>)
assertVisitor( visitor.visitMethod( 0, "a", "(La/b/c;)V", "(La/b/c<Lx/y/z;>;)V", null ) );
assertClasses( "a.b.c", "x.y.z" );
}
@Test
public void testVisitMethodWithPrimitiveReturnType()
{
// int a()
assertVisitor( visitor.visitMethod( 0, "a", "()I", null, null ) );
assertNoClasses();
}
@Test
public void testVisitMethodWithPrimitiveArrayReturnType()
{
// int[] a()
assertVisitor( visitor.visitMethod( 0, "a", "()[I", null, null ) );
assertNoClasses();
}
@Test
public void testVisitMethodWithObjectReturnType()
{
// a.b.c a()
assertVisitor( visitor.visitMethod( 0, "a", "()La/b/c;", null, null ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodWithObjectArrayReturnType()
{
// a.b.c[] a()
assertVisitor( visitor.visitMethod( 0, "a", "()[La/b/c;", null, null ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodWithException()
{
// void a() throws a.b.c
assertVisitor( visitor.visitMethod( 0, "a", "()V", null, new String[] { "a/b/c" } ) );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodWithExceptions()
{
// void a() throws a.b.c, x.y.z
assertVisitor( visitor.visitMethod( 0, "a", "()V", null, new String[] { "a/b/c", "x/y/z" } ) );
assertClasses( "a.b.c", "x.y.z" );
}
// visitAnnotationDefault tests -------------------------------------------
@Test
public void testVisitAnnotationDefault()
{
assertVisitor( mv.visitAnnotationDefault() );
assertNoClasses();
}
// visitParameterAnnotation tests -------------------------------------------
@Test
public void testVisitParameterAnnotation()
{
// @a.b.c
assertVisitor( mv.visitParameterAnnotation( 0, "La/b/c;", false ) );
assertClasses( "a.b.c" );
}
// visitCode tests --------------------------------------------------------
@Test
public void testVisitCode()
{
mv.visitCode();
assertNoClasses();
}
// visitFrame tests -------------------------------------------------------
@Test
public void testVisitFrame()
{
mv.visitFrame( Opcodes.F_NEW, 0, new Object[0], 0, new Object[0] );
assertNoClasses();
}
// visitInsn tests --------------------------------------------------------
@Test
public void testVisitInsn()
{
mv.visitInsn( Opcodes.NOP );
assertNoClasses();
}
// visitIntInsn tests -----------------------------------------------------
@Test
public void testVisitIntInsn()
{
mv.visitIntInsn( Opcodes.BIPUSH, 0 );
assertNoClasses();
}
// visitVarInsn tests -----------------------------------------------------
@Test
public void testVisitVarInsn()
{
mv.visitVarInsn( Opcodes.ILOAD, 0 );
assertNoClasses();
}
// visitTypeInsn tests ----------------------------------------------------
@Test
public void testVisitTypeInsn()
{
mv.visitTypeInsn( Opcodes.NEW, "a/b/c" );
assertClasses( "a.b.c" );
}
// visitFieldInsn tests ---------------------------------------------------
@Test
public void testVisitFieldInsnWithPrimitive()
{
mv.visitFieldInsn( Opcodes.GETFIELD, "a/b/c", "x", "I" );
assertClasses( "a.b.c" );
}
@Test
public void testVisitFieldInsnWithObject()
{
mv.visitFieldInsn( Opcodes.GETFIELD, "a/b/c", "x", "Lx/y/z;" );
assertClasses( "a.b.c" );
}
// visitMethodInsn tests --------------------------------------------------
@Test
public void testVisitMethodInsn()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithPrimitiveArgument()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(I)V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithPrimitiveArrayArgument()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "([I)V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithObjectArgument()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(Lx/y/z;)V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithObjectArguments()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "(Lp/q/r;Lx/y/z;)V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithObjectArrayArgument()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "([Lx/y/z;)V", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithPrimitiveReturnType()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()I", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithPrimitiveArrayReturnType()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()[I", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithObjectReturnType()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()Lx/y/z;", false );
assertClasses( "a.b.c" );
}
@Test
public void testVisitMethodInsnWithObjectArrayReturnType()
{
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, "a/b/c", "x", "()[Lx/y/z;", false );
assertClasses( "a.b.c" );
}
// visitJumpInsn tests ----------------------------------------------------
@Test
public void testVisitJumpInsn()
{
mv.visitJumpInsn( Opcodes.IFEQ, new Label() );
assertNoClasses();
}
// visitLabel tests -------------------------------------------------------
@Test
public void testVisitLabel()
{
mv.visitLabel( new Label() );
assertNoClasses();
}
// visitLdcInsn tests -----------------------------------------------------
@Test
public void testVisitLdcInsnWithNonType()
{
mv.visitLdcInsn( "a" );
assertNoClasses();
}
@Test
public void testVisitLdcInsnWithPrimitiveType()
{
mv.visitLdcInsn( Type.INT_TYPE );
assertNoClasses();
}
@Test
public void testVisitLdcInsnWithObjectType()
{
mv.visitLdcInsn( Type.getType( "La/b/c;" ) );
assertClasses( "a.b.c" );
}
// visitIincInsn tests ----------------------------------------------------
@Test
public void testVisitIincInsn()
{
mv.visitIincInsn( 0, 1 );
assertNoClasses();
}
// visitTableSwitchInsn tests ---------------------------------------------
@Test
public void testVisitTableSwitchInsn()
{
mv.visitTableSwitchInsn( 0, 1, new Label(), new Label() );
assertNoClasses();
}
// visitLookupSwitchInsn tests --------------------------------------------
@Test
public void testVisitLookupSwitchInsn()
{
mv.visitLookupSwitchInsn( new Label(), new int[] { 0 }, new Label[] { new Label() } );
assertNoClasses();
}
// visitMultiANewArrayInsn tests ------------------------------------------
@Test
public void testVisitMultiANewArrayInsnWithPrimitive()
{
mv.visitMultiANewArrayInsn( "I", 2 );
assertNoClasses();
}
@Test
public void testVisitMultiANewArrayInsnWithObject()
{
mv.visitMultiANewArrayInsn( "La/b/c;", 2 );
assertClasses( "a.b.c" );
}
// visitTryCatchBlock tests -----------------------------------------------
@Test
public void testVisitTryCatchBlock()
{
mv.visitTryCatchBlock( new Label(), new Label(), new Label(), "a/b/c" );
assertClasses( "a.b.c" );
}
@Test
public void testVisitTryCatchBlockForFinally()
{
mv.visitTryCatchBlock( new Label(), new Label(), new Label(), null );
assertNoClasses();
}
// visitLocalVariable tests -----------------------------------------------
@Test
public void testVisitLocalVariableWithPrimitive()
{
mv.visitLocalVariable( "a", "I", null, new Label(), new Label(), 0 );
assertNoClasses();
}
@Test
public void testVisitLocalVariableWithPrimitiveArray()
{
mv.visitLocalVariable( "a", "[I", null, new Label(), new Label(), 0 );
assertNoClasses();
}
@Test
public void testVisitLocalVariableWithObject()
{
mv.visitLocalVariable( "a", "La/b/c;", null, new Label(), new Label(), 0 );
assertClasses( "a.b.c" );
}
@Test
public void testVisitLocalVariableWithObjectArray()
{
mv.visitLocalVariable( "a", "[La/b/c;", null, new Label(), new Label(), 0 );
assertClasses( "a.b.c" );
}
@Test
public void testVisitLocalVariableWithGenericObject()
{
mv.visitLocalVariable( "a", "La/b/c;", "La/b/c<Lx/y/z;>;", new Label(), new Label(), 0 );
assertClasses( "a.b.c", "x.y.z" );
}
@Test
public void testVisitLocalVariableWithGenericObjectArray()
{
mv.visitLocalVariable( "a", "La/b/c;", "[La/b/c<Lx/y/z;>;", new Label(), new Label(), 0 );
assertClasses( "a.b.c", "x.y.z" );
}
// visitLineNumber tests --------------------------------------------------
@Test
public void testVisitLineNumber()
{
mv.visitLineNumber( 0, new Label() );
assertNoClasses();
}
// visitMaxs tests --------------------------------------------------------
@Test
public void testVisitMaxs()
{
mv.visitMaxs( 0, 0 );
assertNoClasses();
}
private void assertVisitor( Object actualVisitor )
{
//assertEquals( visitor, actualVisitor );
}
private void assertNoClasses()
{
assertClasses( Collections.<String>emptySet() );
}
private void assertClasses( String element )
{
assertClasses( Collections.singleton( element ) );
}
private void assertClasses( String expectedClass1, String expectedClass2 )
{
assertClasses( new String[] { expectedClass1, expectedClass2 } );
}
private void assertClasses( String expectedClass1, String expectedClass2, String expectedClass3 )
{
assertClasses( new String[] { expectedClass1, expectedClass2, expectedClass3 } );
}
private void assertClasses( String[] expectedClasses )
{
assertClasses( new HashSet<>( Arrays.asList( expectedClasses ) ) );
}
private void assertClasses( Set<String> expectedClasses )
{
assertEquals( expectedClasses, resultCollector.getDependencies() );
}
}