| package ioc.specs |
| |
| import org.apache.tapestry5.ioc.internal.services.MethodSignature |
| import spock.lang.Specification |
| import spock.lang.Unroll |
| |
| import java.lang.reflect.Method |
| import java.sql.SQLException |
| |
| class MethodSignatureSpec extends Specification { |
| |
| def MethodSignature find(Class sourceClass, String methodName) { |
| Method match = sourceClass.methods.find { it.name == methodName } |
| |
| if (match == null) { |
| throw new IllegalStateException("Call $sourceClass.name has no method named '$methodName'.") |
| } |
| |
| return new MethodSignature(match) |
| } |
| |
| @Unroll |
| def "#firstClass.name and #secondClass.name have identical MethodSignatures for method #methodName"() { |
| |
| when: |
| |
| def m1 = find firstClass, methodName |
| def m2 = find secondClass, methodName |
| |
| then: |
| |
| m1.hashCode() == m2.hashCode() |
| m1 == m2 |
| |
| where: |
| |
| firstClass | secondClass | methodName |
| Object | Boolean | "hashCode" |
| String | StringBuilder | "charAt" |
| ObjectInput | ObjectInputStream | "close" |
| } |
| |
| def "a null parameter or exception list is equivalent to an empty one"() { |
| def m1 = new MethodSignature(void, "foo", null, null) |
| def m2 = new MethodSignature(void, "foo", [] as Class[], [] as Class[]) |
| |
| expect: |
| |
| m1 == m2 |
| m2 == m1 |
| |
| m1.hashCode() == m2.hashCode() |
| } |
| |
| def "a mismatch of method name causes inequality"() { |
| def m1 = new MethodSignature(void, "foo", null, null) |
| def m2 = new MethodSignature(void, "bar", null, null) |
| |
| expect: |
| |
| m1 != m2 |
| } |
| |
| def "a mismatch of parameters causes inequality"() { |
| def m1 = new MethodSignature(void, "foo", [String] as Class[], null) |
| def m2 = new MethodSignature(void, "foo", [Boolean] as Class[], null) |
| |
| expect: |
| |
| m1 != m2 |
| } |
| |
| def "a MethodSignature never equals null"() { |
| |
| expect: |
| |
| new MethodSignature(void, "foo", null, null) != null |
| } |
| |
| def "a MethodSignature may only equal another MethodSignature"() { |
| |
| expect: |
| |
| new MethodSignature(void, "foo", null, null) != "Any Old Thing" |
| } |
| |
| @Unroll |
| def "MethodSignature.toString() for #clazz.name #methodName is '#toString'"() { |
| |
| def sig = find(clazz, methodName) |
| |
| expect: |
| |
| sig.toString() == toString |
| |
| where: |
| |
| clazz | methodName | toString |
| String | "getChars" | "void getChars(int, int, char[], int)" |
| Class | "newInstance" | "java.lang.Object newInstance() throws java.lang.IllegalAccessException, java.lang.InstantiationException" |
| } |
| |
| @Unroll |
| def "MethodSignature.uniqueId for #clazz.name #methodName is '#uniqueId'"() { |
| def sig = find(clazz, methodName) |
| |
| expect: |
| |
| sig.uniqueId == uniqueId |
| |
| where: |
| |
| clazz | methodName | uniqueId |
| String | "getChars" | "getChars(int,int,char[],int)" |
| Class | "newInstance" | "newInstance()" |
| } |
| |
| def "different return types will prevent override"() { |
| |
| def m1 = new MethodSignature(void, "foo", null, null) |
| def m2 = new MethodSignature(int, "foo", null, null) |
| |
| expect: |
| |
| !m1.isOverridingSignatureOf(m2) |
| } |
| |
| def "different method names will prevent override"() { |
| def m1 = new MethodSignature(int, "foo", null, null) |
| def m2 = new MethodSignature(int, "bar", null, null) |
| |
| expect: |
| |
| !m1.isOverridingSignatureOf(m2) |
| } |
| |
| def "different parameter types will prevent override"() { |
| def m1 = new MethodSignature(int, "foo", null, null) |
| def m2 = new MethodSignature(int, "foo", [String] as Class[], null) |
| |
| expect: |
| |
| !m1.isOverridingSignatureOf(m2) |
| } |
| |
| def "a difference of exceptions thrown allows for override"() { |
| def m1 = new MethodSignature(int, "foo", null, [Exception] as Class[]) |
| def m2 = new MethodSignature(int, "foo", null, [RuntimeException] as Class[]) |
| |
| expect: |
| |
| // All of m2's exceptions are assignable to at least one of m1's exceptions |
| m1.isOverridingSignatureOf(m2) |
| !m2.isOverridingSignatureOf(m1) |
| } |
| |
| def "signature with no exceptions will not override"() { |
| def m1 = new MethodSignature(int, "foo", null, null) |
| def m2 = new MethodSignature(int, "foo", null, [RuntimeException] as Class[]) |
| |
| expect: |
| |
| !m1.isOverridingSignatureOf(m2) |
| m2.isOverridingSignatureOf(m1) |
| } |
| |
| def "complex matching of signature exceptions when determining override"() { |
| def m1 = new MethodSignature(void, "close", null, |
| [SQLException, NumberFormatException] as Class[]) |
| def m2 = new MethodSignature(void.class, "close", null, |
| [SQLException, IOException] as Class[]) |
| |
| expect: |
| |
| // NumberFormatException and IOException don't fit in either direction |
| !m1.isOverridingSignatureOf(m2) |
| !m2.isOverridingSignatureOf(m1) |
| } |
| } |