blob: 4ea1a9cae21d99ec60da8ae0693a6697761f680a [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* Licensed 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.
*/
package com.google.gwt.dev.shell;
import junit.framework.TestCase;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
/**
* Tests DispatchClassInfoTest.
*/
public class DispatchClassInfoTest extends TestCase {
/**
* Used in {@link #testInterface()}.
*/
private interface Intf {
void bar(double x);
void bar(int x);
void foo(int x);
}
public void testBasics() {
@SuppressWarnings("unused")
class Foo {
int field;
void nonOverloaded(int x) {
}
void overloaded(double x) {
}
void overloaded(int x) {
}
}
DispatchClassInfo dci = new DispatchClassInfo(Foo.class, 42);
assertField(dci, "field", "field");
assertNonExistent(dci, "bogofield");
assertMethod(dci, "nonOverloaded(I)", Foo.class, "nonOverloaded",
Integer.TYPE);
assertMethod(dci, "nonOverloaded(*)", Foo.class, "nonOverloaded",
Integer.TYPE);
assertMethod(dci, "overloaded(I)", Foo.class, "overloaded", Integer.TYPE);
assertMethod(dci, "overloaded(D)", Foo.class, "overloaded", Double.TYPE);
assertNonExistent(dci, "overloaded(*)");
assertNonExistent(dci, "bogometh(I)");
assertNonExistent(dci, "bogometh(*)");
}
public void testInheritance() {
/*
* In these two classes, foo is overloaded in the superclass but not the
* subclass, and bar vice versa.
*/
@SuppressWarnings("unused")
class Super {
int field;
void bar(int x) {
}
void foo(double x) {
}
void foo(int x) {
}
void nonover(int x) {
}
void over(double x) {
}
void over(int x) {
}
}
@SuppressWarnings("unused")
class Sub extends Super {
void bar(double x) {
}
@Override
void bar(int x) {
}
@Override
void foo(int x) {
}
}
DispatchClassInfo dci = new DispatchClassInfo(Sub.class, 42);
assertField(dci, "field", "field");
assertMethod(dci, "foo(I)", Sub.class, "foo", Integer.TYPE);
assertMethod(dci, "bar(I)", Sub.class, "bar", Integer.TYPE);
assertMethod(dci, "bar(D)", Sub.class, "bar", Double.TYPE);
assertNonExistent(dci, "foo(*)");
assertNonExistent(dci, "bar(*)");
assertMethod(dci, "nonover(I)", Super.class, "nonover", Integer.TYPE);
assertMethod(dci, "nonover(*)", Super.class, "nonover", Integer.TYPE);
assertMethod(dci, "over(I)", Super.class, "over", Integer.TYPE);
assertMethod(dci, "over(D)", Super.class, "over", Double.TYPE);
assertNonExistent(dci, "over(*)");
}
public void testInterface() {
DispatchClassInfo dci = new DispatchClassInfo(Intf.class, 42);
assertMethod(dci, "foo(I)", Intf.class, "foo", Integer.TYPE);
assertMethod(dci, "foo(*)", Intf.class, "foo", Integer.TYPE);
assertMethod(dci, "bar(I)", Intf.class, "bar", Integer.TYPE);
assertMethod(dci, "bar(D)", Intf.class, "bar", Double.TYPE);
assertNonExistent(dci, "bar(*)");
}
/**
* Test that bridge methods are ignored for wildcard lookups.
*/
public void testBridgeMethod() {
@SuppressWarnings("unused")
abstract class Super<T> {
abstract void set(T x);
}
class Sub extends Super<String> {
@Override
void set(String x) {
}
}
DispatchClassInfo dci = new DispatchClassInfo(Sub.class, 42);
assertMethod(dci, "set(Ljava/lang/String;)", Sub.class, "set", String.class);
assertMethod(dci, "set(*)", Sub.class, "set", String.class);
// For backward compatibility, allow calling a bridge method directly
assertMethod(dci, "set(Ljava/lang/Object;)", Sub.class, "set", Object.class);
}
private void assertField(DispatchClassInfo dci, String ref, String fieldName) {
Member member = lookupMember(dci, ref);
Field field = (Field) member;
assertEquals(fieldName, field.getName());
}
private void assertMethod(DispatchClassInfo dci, String ref,
Class<?> methodClass, String methodName, Class<?> paramType) {
Member member = lookupMember(dci, ref);
Method method = (Method) member;
assertSame(methodClass, member.getDeclaringClass());
assertEquals(methodName, method.getName());
assertEquals(1, method.getParameterTypes().length);
assertEquals(paramType, method.getParameterTypes()[0]);
}
private void assertNonExistent(DispatchClassInfo dci, String badref) {
int handle = dci.getMemberId(badref);
assertTrue("expected to be a bad reference: " + badref, handle < 0);
}
private Member lookupMember(DispatchClassInfo dci, String ref) {
int handle = dci.getMemberId(ref);
assertTrue("ref lookup failed: " + ref, handle >= 0);
Member member = dci.getMember(handle);
return member;
}
}