/* * 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; } }