aboutsummaryrefslogtreecommitdiffstats
path: root/tests/netx/unit/sun/applet/MethodOverloadResolverTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/netx/unit/sun/applet/MethodOverloadResolverTest.java')
-rw-r--r--tests/netx/unit/sun/applet/MethodOverloadResolverTest.java383
1 files changed, 383 insertions, 0 deletions
diff --git a/tests/netx/unit/sun/applet/MethodOverloadResolverTest.java b/tests/netx/unit/sun/applet/MethodOverloadResolverTest.java
new file mode 100644
index 0000000..8fefe26
--- /dev/null
+++ b/tests/netx/unit/sun/applet/MethodOverloadResolverTest.java
@@ -0,0 +1,383 @@
+package sun.applet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.TreeSet;
+
+import net.sourceforge.jnlp.ServerAccess;
+import netscape.javascript.JSObject;
+
+import org.junit.Test;
+
+import sun.applet.MethodOverloadResolver.ResolvedMethod;
+import sun.applet.MethodOverloadResolver.WeightedCast;
+
+public class MethodOverloadResolverTest {
+
+ /**************************************************************************
+ * MethodOverloadResolver.getCostAndCastedObject tests *
+ **************************************************************************/
+
+ // Helper methods
+
+ // Helper class for overload order tests
+ static class CandidateCast implements Comparable<CandidateCast>{
+ public CandidateCast(int cost, Class<?> candidate) {
+ this.cost = cost;
+ this.candidate = candidate;
+ }
+ public int getCost() {
+ return cost;
+ }
+
+ public Class<?> getCandidate() {
+ return candidate;
+ }
+
+ @Override
+ public int compareTo(CandidateCast other) {
+ return cost > other.cost ? +1 : -1;
+ }
+
+ private int cost;
+ private Class<?> candidate;
+ }
+
+ // asserts that these overloads have the given order of preference
+ // and that none of the costs are equal
+ static private void assertOverloadOrder(Object arg, Class<?>... orderedCandidates) {
+ String argClassName = arg.getClass().getSimpleName();
+ TreeSet<CandidateCast> casts = new TreeSet<CandidateCast>();
+
+ for (Class<?> candidate : orderedCandidates) {
+ WeightedCast wc = MethodOverloadResolver.getCostAndCastedObject(arg, candidate);
+
+ assertFalse("Expected valid overload from " + argClassName + " to "
+ + candidate.getSimpleName(), wc == null);
+
+ // Check previous candidates, _should not_ be 'ambiguous', ie this cost == other cost
+ for (CandidateCast cc : casts) {
+ String failureString = "Unexpected ambiguity overloading "
+ + argClassName + " between "
+ + candidate.getSimpleName() + " and "
+ + cc.candidate.getSimpleName()
+ + " with cost " + cc.cost +"!";
+
+ assertFalse(failureString, cc.cost == wc.getCost());
+ }
+
+ casts.add(new CandidateCast(wc.getCost(), candidate));
+ }
+
+ Class<?>[] actualOrder = new Class<?>[casts.size()];
+
+ int n = 0;
+ for (CandidateCast cc : casts) {
+ actualOrder[n] = cc.candidate;
+ ServerAccess.logOutputReprint(arg.getClass().getSimpleName() + " to "
+ + cc.candidate.getSimpleName() + " has cost " + cc.cost);
+ n++;
+ }
+
+ assertArrayEquals(orderedCandidates, actualOrder);
+ }
+
+ // Asserts that the given overloads are all of same cost
+ static private void assertInvalidOverloads(Object arg, Class<?>... candidates) {
+ for (Class<?> candidate : candidates) {
+ WeightedCast wc = MethodOverloadResolver.getCostAndCastedObject(arg, candidate);
+
+ int cost = (wc != null ? wc.getCost() : 0); // Avoid NPE on non-failure
+ String argClassName = arg == null ? "null" : arg.getClass().getSimpleName();
+
+ assertTrue("Expected to be unable to cast "
+ + argClassName + " to "
+ + candidate.getSimpleName()
+ + " but was able to with cost " + cost + "!",
+ wc == null);
+ }
+ }
+
+ static private void assertNotPrimitiveCastable(Object arg) {
+ assertInvalidOverloads(arg, Double.TYPE, Float.TYPE, Long.TYPE,
+ Short.TYPE, Byte.TYPE, Character.TYPE);
+ }
+
+ static private void assertNotNumberCastable(Object arg) {
+ assertNotPrimitiveCastable(arg);
+ assertInvalidOverloads(arg, Double.class, Float.class, Long.class,
+ Short.class, Byte.class, Character.class);
+ }
+
+ // Asserts that the given overloads are all of same cost
+ static private void assertAmbiguousOverload(Object arg, Class<?>... candidates) {
+ String argClassName = arg == null ? "null" : arg.getClass().getSimpleName();
+ List<CandidateCast> casts = new ArrayList<CandidateCast>();
+
+ for (Class<?> candidate : candidates) {
+ WeightedCast wc = MethodOverloadResolver.getCostAndCastedObject(arg, candidate);
+
+ assertFalse("Expected valid overload from " + argClassName + " to "
+ + candidate.getSimpleName(), wc == null);
+
+ // Check previous candidates, _should_ all 'ambiguous', ie this cost == other cost
+ for (CandidateCast cc : casts) {
+ String failureString = "Expected ambiguity "
+ + argClassName + " between "
+ + candidate.getSimpleName() + " and "
+ + cc.candidate.getSimpleName()
+ + ", got costs " + wc.getCost() + " and " + cc.cost + "!";
+
+ assertTrue(failureString, cc.cost == wc.getCost());
+ }
+
+ casts.add(new CandidateCast(wc.getCost(), candidate));
+ }
+ }
+
+ // Test methods
+
+
+ @Test
+ public void testBooleanOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+
+ assertOverloadOrder(new Boolean(false), Boolean.TYPE, Boolean.class,
+ Double.TYPE, Object.class, String.class);
+ }
+
+ @Test
+ public void testNumberOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+
+ assertAmbiguousOverload(new Double(0), Integer.TYPE, Long.TYPE,
+ Short.TYPE, Byte.TYPE, Character.TYPE);
+
+ assertOverloadOrder(new Double(0), Double.TYPE, Double.class,
+ Float.TYPE, Boolean.TYPE, Object.class, String.class);
+ }
+
+ @Test
+ public void testStringOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+
+ assertAmbiguousOverload("1", Double.TYPE, Float.TYPE, Integer.TYPE,
+ Long.TYPE, Short.TYPE, Byte.TYPE);
+
+ assertOverloadOrder("1.0", String.class, Double.TYPE, Object.class);
+ }
+
+ // Turned off until JSObject is unit-testable (privilege problem)
+// @Test
+ public void testJSObjectOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+ assertOverloadOrder(new JSObject(0L), JSObject.class, String.class);
+ assertAmbiguousOverload(new JSObject(0L), Object[].class, String.class);
+ }
+
+ @Test
+ public void testNullOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+
+ assertNotPrimitiveCastable(null);
+ assertAmbiguousOverload(null, Object.class, String.class);
+ }
+
+ @Test
+ public void testInheritanceOverloading() {
+ // based on http://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+
+ class FooParent {}
+ class FooChild extends FooParent {}
+ class FooChildOfChild extends FooChild {}
+
+ assertNotNumberCastable(new FooChildOfChild());
+
+ // NB: this is ambiguious as far as costs are concerned, however
+ // MethodOverloadResolver.getBestOverloadMatch sorts out this ambiguity
+ assertAmbiguousOverload(new FooChildOfChild(), FooChild.class,
+ FooParent.class, Object.class);
+
+ assertOverloadOrder(new FooChild(), FooChild.class, FooParent.class, String.class);
+ }
+
+ /**************************************************************************
+ * MethodOverloadResolver.getMatchingMethod tests *
+ **************************************************************************/
+
+ // Helper methods
+
+ // Convenient representation of resulting method signature
+ static private String simpleSignature(java.lang.reflect.AccessibleObject m) {
+ StringBuilder sb = new StringBuilder();
+
+ for (Class<?> c : MethodOverloadResolver.getParameterTypesFor(m)) {
+ sb.append(c.getSimpleName());
+ sb.append(", ");
+ }
+ sb.setLength(sb.length() - 2); // Trim last ", "
+
+ return sb.toString();
+ }
+
+ static private Object[] args(Class<?> klazz, Object... params) {
+ List<Object> objects = new ArrayList<Object>();
+ objects.add(klazz);
+ // assumes our method test name is "testmethod"
+ objects.add("testmethod");
+ objects.addAll(Arrays.asList(params));
+ return objects.toArray( new Object[0]);
+ }
+
+ static private void assertExpectedOverload(Object[] params,
+ String expectedSignature, int expectedCost) {
+ Class<?> c = (Class<?>)params[0];
+ String methodName = (String)params[1];
+ Object[] args = Arrays.copyOfRange(params, 2, params.length);
+
+ ResolvedMethod result = MethodOverloadResolver.getBestMatchMethod(c, methodName, args);
+
+ // Check signature array as string for convenience
+ assertEquals(expectedSignature, simpleSignature(result.getAccessibleObject()));
+ assertEquals(expectedCost, result.getCost());
+ }
+
+ // Test methods
+
+ @Test
+ public void testMultipleArgResolve() {
+
+ @SuppressWarnings("unused")
+ abstract class MultipleArg {
+ public abstract void testmethod(String s, int i);
+ public abstract void testmethod(String s, Integer i);
+ }
+
+ // Numeric to java primitive
+ assertExpectedOverload(
+ args( MultipleArg.class, "teststring", 1 ),
+ "String, int",
+ MethodOverloadResolver.CLASS_SAME_COST + MethodOverloadResolver.NUMERIC_SAME_COST);
+
+ // String to java primitive
+ assertExpectedOverload(
+ args( MultipleArg.class, "teststring", "1.1" ),
+ "String, int",
+ MethodOverloadResolver.CLASS_SAME_COST + MethodOverloadResolver.STRING_NUMERIC_CAST_COST);
+
+ // Null to non-primitive type
+ assertExpectedOverload(
+ args( MultipleArg.class, "teststring", (Object)null ),
+ "String, Integer",
+ MethodOverloadResolver.CLASS_SAME_COST + MethodOverloadResolver.NULL_TO_OBJECT_COST);
+ }
+
+ @Test
+ public void testBoxedNumberResolve() {
+
+ @SuppressWarnings("unused")
+ abstract class BoxedNumber {
+ public abstract void testmethod(Number n);
+ public abstract void testmethod(Integer i);
+ }
+
+ assertExpectedOverload(
+ args( BoxedNumber.class, 1),
+ "Integer", MethodOverloadResolver.CLASS_SAME_COST);
+
+ assertExpectedOverload(
+ args( BoxedNumber.class, (short)1),
+ "Number", MethodOverloadResolver.CLASS_SUPERCLASS_COST);
+ }
+
+ @Test
+ public void testPrimitivesResolve() {
+
+ @SuppressWarnings("unused")
+ abstract class Primitives {
+ public abstract void testmethod(int i);
+ public abstract void testmethod(long l);
+ public abstract void testmethod(float f);
+ public abstract void testmethod(double d);
+ }
+
+ assertExpectedOverload(
+ args( Primitives.class, 1),
+ "int", MethodOverloadResolver.NUMERIC_SAME_COST);
+
+
+ assertExpectedOverload(
+ args( Primitives.class, 1L),
+ "long", MethodOverloadResolver.NUMERIC_SAME_COST);
+
+ assertExpectedOverload(
+ args( Primitives.class, 1.1f),
+ "float", MethodOverloadResolver.NUMERIC_SAME_COST);
+
+ assertExpectedOverload(
+ args( Primitives.class, 1.1),
+ "double", MethodOverloadResolver.NUMERIC_SAME_COST);
+ }
+
+ @Test
+ public void testComplexResolve() {
+
+ @SuppressWarnings("unused")
+ abstract class Complex {
+ public abstract void testmethod(float f);
+ public abstract void testmethod(String s);
+ public abstract void testmethod(JSObject j);
+ }
+
+ assertExpectedOverload(
+ args( Complex.class, 1),
+ "float", MethodOverloadResolver.NUMERIC_CAST_COST);
+
+
+ assertExpectedOverload(
+ args( Complex.class, "1"),
+ "String", MethodOverloadResolver.CLASS_SAME_COST);
+
+ assertExpectedOverload(
+ args( Complex.class, 1.1f),
+ "float", MethodOverloadResolver.NUMERIC_SAME_COST);
+
+ // This test is commented out until JSObject can be unit tested (privilege problem)
+// assertExpectedOverload(
+// args( Complex.class, new JSObject(0L)),
+// "JSObject", MethodOverloadResolver.CLASS_SAME_COST);
+ }
+
+ @Test
+ public void testInheritanceResolve() {
+
+ class FooParent {}
+ class FooChild extends FooParent {}
+ class FooChildOfChild extends FooChild {}
+
+ abstract class Inheritance {
+ public abstract void testmethod(FooParent fp);
+ public abstract void testmethod(FooChild fc);
+ }
+
+ assertExpectedOverload(
+ args( Inheritance.class, new FooParent()),
+ "FooParent", MethodOverloadResolver.CLASS_SAME_COST);
+
+
+ assertExpectedOverload(
+ args( Inheritance.class, new FooChild()),
+ "FooChild", MethodOverloadResolver.CLASS_SAME_COST);
+
+ assertExpectedOverload(
+ args( Inheritance.class, new FooChildOfChild()),
+ "FooChild", MethodOverloadResolver.CLASS_SUPERCLASS_COST);
+ }
+
+}