rfield@1422: /* katleman@1448: * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. rfield@1422: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. rfield@1422: * rfield@1422: * This code is free software; you can redistribute it and/or modify it rfield@1422: * under the terms of the GNU General Public License version 2 only, as rfield@1422: * published by the Free Software Foundation. Oracle designates this rfield@1422: * particular file as subject to the "Classpath" exception as provided rfield@1422: * by Oracle in the LICENSE file that accompanied this code. rfield@1422: * rfield@1422: * This code is distributed in the hope that it will be useful, but WITHOUT rfield@1422: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rfield@1422: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License rfield@1422: * version 2 for more details (a copy is included in the LICENSE file that rfield@1422: * accompanied this code). rfield@1422: * rfield@1422: * You should have received a copy of the GNU General Public License version rfield@1422: * 2 along with this work; if not, write to the Free Software Foundation, rfield@1422: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. rfield@1422: * rfield@1422: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA rfield@1422: * or visit www.oracle.com if you need additional information or have any rfield@1422: * questions. rfield@1422: */ rfield@1422: rfield@1422: package org.openjdk.tests.vm; rfield@1422: rfield@1422: import java.lang.reflect.*; rfield@1422: import java.util.*; rfield@1422: import java.io.File; rfield@1422: import java.io.IOException; rfield@1422: rfield@1422: import org.testng.annotations.Test; rfield@1422: import org.openjdk.tests.separate.*; rfield@1422: import org.openjdk.tests.separate.Compiler; rfield@1422: rfield@1422: import static org.testng.Assert.*; rfield@1422: import static org.openjdk.tests.separate.SourceModel.*; rfield@1422: import static org.openjdk.tests.separate.SourceModel.Class; rfield@1422: rfield@1422: @Test(groups = "vm") rfield@1422: public class DefaultMethodsTest extends TestHarness { rfield@1422: public DefaultMethodsTest() { rfield@1422: super(false, false); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * class C { public int m() { return 22; } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 22 rfield@1422: */ rfield@1422: public void testHarnessInvokeVirtual() { rfield@1422: Class C = new Class("C", ConcreteMethod.std("22")); rfield@1422: assertInvokeVirtualEquals(22, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m(); } rfield@1422: * class C implements I { public int m() { return 33; } } rfield@1422: * rfield@1422: * TEST: I i = new C(); i.m() == 33; rfield@1422: */ rfield@1422: public void testHarnessInvokeInterface() { rfield@1422: Interface I = new Interface("I", AbstractMethod.std()); rfield@1422: Class C = new Class("C", I, ConcreteMethod.std("33")); rfield@1422: assertInvokeInterfaceEquals(33, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * class C {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws NoSuchMethod rfield@1422: */ rfield@1422: public void testHarnessThrows() { rfield@1422: Class C = new Class("C"); rfield@1422: assertThrows(NoSuchMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m() default { return 44; } } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 44; rfield@1422: * TEST: I i = new C(); i.m() == 44; rfield@1422: */ rfield@1422: public void testBasicDefault() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("44")); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: assertInvokeVirtualEquals(44, C); rfield@1422: assertInvokeInterfaceEquals(44, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 44; } } rfield@1422: * interface J extends I {} rfield@1422: * interface K extends J {} rfield@1422: * class C implements K {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 44; rfield@1422: * TEST: I i = new C(); i.m() == 44; rfield@1422: */ rfield@1422: public void testFarDefault() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("44")); rfield@1422: Interface J = new Interface("J", I); rfield@1422: Interface K = new Interface("K", J); rfield@1422: Class C = new Class("C", K); rfield@1422: rfield@1422: assertInvokeVirtualEquals(44, C); rfield@1422: assertInvokeInterfaceEquals(44, C, K); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m(); } rfield@1422: * interface J extends I { default int m() { return 44; } } rfield@1422: * interface K extends J {} rfield@1422: * class C implements K {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 44; rfield@1422: * TEST: K k = new C(); k.m() == 44; rfield@1422: */ rfield@1422: public void testOverrideAbstract() { rfield@1422: Interface I = new Interface("I", AbstractMethod.std()); rfield@1422: Interface J = new Interface("J", I, DefaultMethod.std("44")); rfield@1422: Interface K = new Interface("K", J); rfield@1422: Class C = new Class("C", K); rfield@1422: rfield@1422: assertInvokeVirtualEquals(44, C); rfield@1422: assertInvokeInterfaceEquals(44, C, K); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m() default { return 44; } } rfield@1422: * class C implements I { public int m() { return 55; } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 55; rfield@1422: * TEST: I i = new C(); i.m() == 55; rfield@1422: */ rfield@1422: public void testExisting() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("44")); rfield@1422: Class C = new Class("C", I, ConcreteMethod.std("55")); rfield@1422: rfield@1422: assertInvokeVirtualEquals(55, C); rfield@1422: assertInvokeInterfaceEquals(55, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * class B implements I {} rfield@1422: * class C extends B {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 99; rfield@1422: * TEST: I i = new C(); i.m() == 99; rfield@1422: */ rfield@1422: public void testInherited() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Class B = new Class("B", I); rfield@1422: Class C = new Class("C", B); rfield@1422: rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: assertInvokeInterfaceEquals(99, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * class C { public int m() { return 11; } } rfield@1422: * class D extends C implements I {} rfield@1422: * rfield@1422: * TEST: D d = new D(); d.m() == 11; rfield@1422: * TEST: I i = new D(); i.m() == 11; rfield@1422: */ rfield@1422: public void testExistingInherited() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Class C = new Class("C", ConcreteMethod.std("11")); rfield@1422: Class D = new Class("D", C, I); rfield@1422: rfield@1422: assertInvokeVirtualEquals(11, D); rfield@1422: assertInvokeInterfaceEquals(11, D, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 44; } } rfield@1422: * class C implements I { public int m() { return 11; } } rfield@1422: * class D extends C { public int m() { return 22; } } rfield@1422: * rfield@1422: * TEST: D d = new D(); d.m() == 22; rfield@1422: * TEST: I i = new D(); i.m() == 22; rfield@1422: */ rfield@1422: void testExistingInheritedOverride() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Class C = new Class("C", I, ConcreteMethod.std("11")); rfield@1422: Class D = new Class("D", C, ConcreteMethod.std("22")); rfield@1422: rfield@1422: assertInvokeVirtualEquals(22, D); rfield@1422: assertInvokeInterfaceEquals(22, D, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * interface J { defaultint m() { return 88; } } rfield@1422: * class C implements I { public int m() { return 11; } } rfield@1422: * class D extends C { public int m() { return 22; } } rfield@1422: * class E extends D implements J {} rfield@1422: * rfield@1422: * TEST: E e = new E(); e.m() == 22; rfield@1422: * TEST: J j = new E(); j.m() == 22; rfield@1422: */ rfield@1422: public void testExistingInheritedPlusDefault() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", DefaultMethod.std("88")); rfield@1422: Class C = new Class("C", I, ConcreteMethod.std("11")); rfield@1422: Class D = new Class("D", C, ConcreteMethod.std("22")); rfield@1422: Class E = new Class("E", D, J); rfield@1422: rfield@1422: assertInvokeVirtualEquals(22, E); rfield@1422: assertInvokeInterfaceEquals(22, E, J); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * class B implements I {} rfield@1422: * class C extends B { public int m() { return 77; } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 77; rfield@1422: * TEST: I i = new C(); i.m() == 77; rfield@1422: */ rfield@1422: public void testInheritedWithConcrete() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Class B = new Class("B", I); rfield@1422: Class C = new Class("C", B, ConcreteMethod.std("77")); rfield@1422: rfield@1422: assertInvokeVirtualEquals(77, C); rfield@1422: assertInvokeInterfaceEquals(77, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * class B implements I {} rfield@1422: * class C extends B implements I { public int m() { return 66; } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 66; rfield@1422: * TEST: I i = new C(); i.m() == 66; rfield@1422: */ rfield@1422: public void testInheritedWithConcreteAndImpl() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Class B = new Class("B", I); rfield@1422: Class C = new Class("C", B, I, ConcreteMethod.std("66")); rfield@1422: rfield@1422: assertInvokeVirtualEquals(66, C); rfield@1422: assertInvokeInterfaceEquals(66, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * interface J { default int m() { return 88; } } rfield@1422: * class C implements I, J {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: */ rfield@1422: public void testConflict() { rfield@1422: // debugTest(); rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", DefaultMethod.std("88")); rfield@1422: Class C = new Class("C", I, J); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m(); } rfield@1422: * interface J { default int m() { return 88; } } rfield@1422: * class C implements I, J {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: */ rfield@1422: public void testAmbiguousReabstract() { rfield@1422: Interface I = new Interface("I", AbstractMethod.std()); rfield@1422: Interface J = new Interface("J", DefaultMethod.std("88")); rfield@1422: Class C = new Class("C", I, J); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * interface J extends I { } rfield@1422: * interface K extends I { } rfield@1422: * class C implements J, K {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 99 rfield@1422: * TEST: J j = new C(); j.m() == 99 rfield@1422: * TEST: K k = new C(); k.m() == 99 rfield@1422: * TEST: I i = new C(); i.m() == 99 rfield@1422: */ rfield@1422: public void testDiamond() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", I); rfield@1422: Interface K = new Interface("K", I); rfield@1422: Class C = new Class("C", J, K); rfield@1422: rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: assertInvokeInterfaceEquals(99, C, J); rfield@1422: assertInvokeInterfaceEquals(99, C, K); rfield@1422: assertInvokeInterfaceEquals(99, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * interface J extends I { } rfield@1422: * interface K extends I { } rfield@1422: * interface L extends I { } rfield@1422: * interface M extends I { } rfield@1422: * class C implements I, J, K, L, M {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 99 rfield@1422: * TEST: J j = new C(); j.m() == 99 rfield@1422: * TEST: K k = new C(); k.m() == 99 rfield@1422: * TEST: I i = new C(); i.m() == 99 rfield@1422: * TEST: L l = new C(); l.m() == 99 rfield@1422: * TEST: M m = new C(); m.m() == 99 rfield@1422: */ rfield@1422: public void testExpandedDiamond() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", I); rfield@1422: Interface K = new Interface("K", I); rfield@1422: Interface L = new Interface("L", I); rfield@1422: Interface M = new Interface("M", L); rfield@1422: Class C = new Class("C", I, J, K, L, M); rfield@1422: rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: assertInvokeInterfaceEquals(99, C, J); rfield@1422: assertInvokeInterfaceEquals(99, C, K); rfield@1422: assertInvokeInterfaceEquals(99, C, I); rfield@1422: assertInvokeInterfaceEquals(99, C, L); rfield@1422: assertInvokeInterfaceEquals(99, C, M); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m() default { return 99; } } rfield@1422: * interface J extends I { int m(); } rfield@1422: * class C implements J {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: */ rfield@1422: public void testReabstract() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", I, AbstractMethod.std()); rfield@1422: Class C = new Class("C", J); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 88; } } rfield@1422: * interface J extends I { default int m() { return 99; } } rfield@1422: * class C implements J {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 99; rfield@1422: * TEST: J j = new C(); j.m() == 99; rfield@1422: * TEST: I i = new C(); i.m() == 99; rfield@1422: */ rfield@1422: public void testShadow() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("88")); rfield@1422: Interface J = new Interface("J", I, DefaultMethod.std("99")); rfield@1422: Class C = new Class("C", J); rfield@1422: rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: assertInvokeInterfaceEquals(99, C, J); rfield@1422: assertInvokeInterfaceEquals(99, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 88; } } rfield@1422: * interface J extends I { default int m() { return 99; } } rfield@1422: * class C implements I, J {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 99; rfield@1422: * TEST: J j = new C(); j.m() == 99; rfield@1422: * TEST: I i = new C(); i.m() == 99; rfield@1422: */ rfield@1422: public void testDisqualified() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("88")); rfield@1422: Interface J = new Interface("J", I, DefaultMethod.std("99")); rfield@1422: Class C = new Class("C", I, J); rfield@1422: rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: assertInvokeInterfaceEquals(99, C, J); rfield@1422: assertInvokeInterfaceEquals(99, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m(T t) { return 99; } } rfield@1422: * Class C implements I { public int m() { return 88; } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 88; rfield@1422: * TEST: I i = new C(); i.m() == 88; rfield@1422: */ rfield@1422: public void testSelfFill() { rfield@1422: // This test ensures that a concrete method overrides a default method rfield@1422: // that matches at the language-level, but has a different method rfield@1422: // signature due to erasure. rfield@1422: rfield@1422: // debugTest(); rfield@1422: rfield@1422: DefaultMethod dm = new DefaultMethod( rfield@1422: "int", "m", "return 99;", new MethodParameter("T", "t")); rfield@1422: ConcreteMethod cm = new ConcreteMethod( rfield@1422: "int", "m", "return 88;", AccessFlag.PUBLIC, rfield@1422: new MethodParameter("String", "s")); rfield@1422: rfield@1422: Interface I = new Interface("I", new TypeParameter("T"), dm); rfield@1422: Class C = new Class("C", I.with("String"), cm); rfield@1422: rfield@1422: AbstractMethod pm = new AbstractMethod( rfield@1422: "int", "m", new MethodParameter("T", "t")); rfield@1422: rfield@1422: assertInvokeVirtualEquals(new Integer(88), C, cm, "-1", "\"string\""); rfield@1422: assertInvokeInterfaceEquals( rfield@1422: new Integer(88), C, I.with("String"), pm, "\"string\""); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: C.class.getMethod("m").invoke(new C()) == 99 rfield@1422: */ rfield@1422: public void testReflectCall() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); mcimadamore@1675: //workaround accessibility issue when loading C with DirectedClassLoader mcimadamore@1675: I.addAccessFlag(AccessFlag.PUBLIC); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: Compiler.Flags[] flags = this.verbose ? rfield@1422: new Compiler.Flags[] { Compiler.Flags.VERBOSE } : rfield@1422: new Compiler.Flags[] {}; rfield@1422: Compiler compiler = new Compiler(flags); rfield@1422: java.lang.Class cls = null; rfield@1422: try { rfield@1422: cls = compiler.compileAndLoad(C); rfield@1422: } catch (ClassNotFoundException e) { rfield@1422: fail("Could not load class"); rfield@1422: } rfield@1422: rfield@1422: java.lang.reflect.Method method = null; rfield@1422: try { rfield@1422: method = cls.getMethod(stdMethodName); rfield@1422: } catch (NoSuchMethodException e) { rfield@1422: fail("Could not find method in class"); rfield@1422: } rfield@1422: assertNotNull(method); rfield@1422: rfield@1422: Object c = null; rfield@1422: try { rfield@1422: c = cls.newInstance(); rfield@1422: } catch (InstantiationException | IllegalAccessException e) { rfield@1422: fail("Could not create instance of class"); rfield@1422: } rfield@1422: assertNotNull(c); rfield@1422: rfield@1422: Integer res = null; rfield@1422: try { rfield@1422: res = (Integer)method.invoke(c); rfield@1422: } catch (IllegalAccessException | rfield@1422: java.lang.reflect.InvocationTargetException e) { rfield@1422: fail("Could not invoke default instance method"); rfield@1422: } rfield@1422: assertNotNull(res); rfield@1422: rfield@1422: assertEquals(res.intValue(), 99); rfield@1422: rfield@1422: compiler.cleanup(); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m(T t, V v, W w) { return 99; } } rfield@1422: * interface J extends I { int m(T t, V v, String w); } } rfield@1422: * interface K extends J { int m(T t, String v, String w); } } rfield@1422: * class C implements K { rfield@1422: * public int m(String t, String v, String w) { return 88; } rfield@1422: * } rfield@1422: * rfield@1422: * TEST: I i = new C(); i.m("A","B","C") == 88; rfield@1422: * TEST: J j = new C(); j.m("A","B","C") == 88; rfield@1422: * TEST: K k = new C(); k.m("A","B","C") == 88; rfield@1422: */ rfield@1422: public void testBridges() { rfield@1422: DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;", rfield@1422: new MethodParameter("T", "t"), new MethodParameter("V", "v"), rfield@1422: new MethodParameter("W", "w")); rfield@1422: rfield@1422: AbstractMethod pm0 = new AbstractMethod("int", stdMethodName, rfield@1422: new MethodParameter("T", "t"), new MethodParameter("V", "v"), rfield@1422: new MethodParameter("W", "w")); rfield@1422: rfield@1422: AbstractMethod pm1 = new AbstractMethod("int", stdMethodName, rfield@1422: new MethodParameter("T", "t"), new MethodParameter("V", "v"), rfield@1422: new MethodParameter("String", "w")); rfield@1422: rfield@1422: AbstractMethod pm2 = new AbstractMethod("int", stdMethodName, rfield@1422: new MethodParameter("T", "t"), new MethodParameter("String", "v"), rfield@1422: new MethodParameter("String", "w")); rfield@1422: rfield@1422: ConcreteMethod cm = new ConcreteMethod("int",stdMethodName,"return 88;", rfield@1422: AccessFlag.PUBLIC, rfield@1422: new MethodParameter("String", "t"), rfield@1422: new MethodParameter("String", "v"), rfield@1422: new MethodParameter("String", "w")); rfield@1422: rfield@1422: Interface I = new Interface("I", new TypeParameter("T"), rfield@1422: new TypeParameter("V"), new TypeParameter("W"), dm); rfield@1422: Interface J = new Interface("J", rfield@1422: new TypeParameter("T"), new TypeParameter("V"), rfield@1422: I.with("String", "T", "V"), pm1); rfield@1422: Interface K = new Interface("K", new TypeParameter("T"), rfield@1422: J.with("String", "T"), pm2); rfield@1422: Class C = new Class("C", K.with("String"), cm); rfield@1422: rfield@1422: String[] args = new String[] { "\"A\"", "\"B\"", "\"C\"" }; rfield@1422: assertInvokeInterfaceEquals(new Integer(88), C, rfield@1422: I.with("String", "String", "String"), pm0, args); rfield@1422: assertInvokeInterfaceEquals(new Integer(88), C, rfield@1422: J.with("String", "String"), pm1, args); rfield@1422: assertInvokeInterfaceEquals(new Integer(88), C, rfield@1422: K.with("String"), pm2, args); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface J { default int m() { return 88; } } rfield@1422: * interface I extends J { default int m() { return J.super.m(); } } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() == 88; rfield@1422: * TEST: I i = new C(); i.m() == 88; rfield@1422: */ rfield@1422: public void testSuperBasic() { rfield@1422: // debugTest(); rfield@1422: rfield@1422: Interface J = new Interface("J", DefaultMethod.std("88")); rfield@1422: Interface I = new Interface("I", J, new DefaultMethod( rfield@1422: "int", stdMethodName, "return J.super.m();")); rfield@1422: I.addCompilationDependency(J.findMethod(stdMethodName)); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: assertInvokeVirtualEquals(88, C); rfield@1422: assertInvokeInterfaceEquals(88, C, I); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface K { int m() default { return 99; } } rfield@1422: * interface L { int m() default { return 101; } } rfield@1422: * interface J extends K, L {} rfield@1422: * interface I extends J, K { int m() default { J.super.m(); } } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: * TODO: add case for K k = new C(); k.m() throws AME rfield@1422: */ rfield@1422: public void testSuperConflict() { rfield@1422: // debugTest(); rfield@1422: rfield@1422: Interface K = new Interface("K", DefaultMethod.std("99")); rfield@1422: Interface L = new Interface("L", DefaultMethod.std("101")); rfield@1422: Interface J = new Interface("J", K, L); rfield@1422: Interface I = new Interface("I", J, K, new DefaultMethod( rfield@1422: "int", stdMethodName, "return J.super.m();")); rfield@1422: Interface Jstub = new Interface("J", DefaultMethod.std("-1")); rfield@1422: I.addCompilationDependency(Jstub); rfield@1422: I.addCompilationDependency(Jstub.findMethod(stdMethodName)); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default int m() { return 99; } } rfield@1422: * interface J extends I { default int m() { return 55; } } rfield@1422: * class C implements I, J { public int m() { return I.super.m(); } } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: * TODO: add case for J j = new C(); j.m() throws AME rfield@1422: */ rfield@1422: public void testSuperDisqual() { rfield@1422: Interface I = new Interface("I", DefaultMethod.std("99")); rfield@1422: Interface J = new Interface("J", I, DefaultMethod.std("55")); rfield@1422: Class C = new Class("C", I, J, rfield@1422: new ConcreteMethod("int", stdMethodName, "return I.super.m();", rfield@1422: AccessFlag.PUBLIC)); rfield@1422: C.addCompilationDependency(I.findMethod(stdMethodName)); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface J { int m(); } rfield@1422: * interface I extends J { default int m() { return J.super.m(); } } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m() throws AME rfield@1422: * TODO: add case for I i = new C(); i.m() throws AME rfield@1422: */ rfield@1422: public void testSuperNull() { rfield@1422: Interface J = new Interface("J", AbstractMethod.std()); rfield@1422: Interface I = new Interface("I", J, new DefaultMethod( rfield@1422: "int", stdMethodName, "return J.super.m();")); rfield@1422: Interface Jstub = new Interface("J", DefaultMethod.std("99")); rfield@1422: I.addCompilationDependency(Jstub); rfield@1422: I.addCompilationDependency(Jstub.findMethod(stdMethodName)); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface J { default int m(T t) { return 88; } } rfield@1422: * interface I extends J { rfield@1422: * int m(String s) default { return J.super.m(); } rfield@1422: * } rfield@1422: * class C implements I {} rfield@1422: * rfield@1422: * TEST: I i = new C(); i.m("") == 88; rfield@1422: */ rfield@1422: public void testSuperGeneric() { rfield@1422: Interface J = new Interface("J", new TypeParameter("T"), rfield@1422: new DefaultMethod("int", stdMethodName, "return 88;", rfield@1422: new MethodParameter("T", "t"))); rfield@1422: Interface I = new Interface("I", J.with("String"), rfield@1422: new DefaultMethod("int", stdMethodName, "return J.super.m(s);", rfield@1422: new MethodParameter("String", "s"))); rfield@1422: I.addCompilationDependency(J.findMethod(stdMethodName)); rfield@1422: Class C = new Class("C", I); rfield@1422: rfield@1422: AbstractMethod pm = new AbstractMethod("int", stdMethodName, rfield@1422: new MethodParameter("String", "s")); rfield@1422: rfield@1422: assertInvokeInterfaceEquals( rfield@1422: new Integer(88), C, new Extends(I), pm, "\"\""); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m(T t) default { return 44; } } rfield@1422: * interface J extends I { int m(String s) default { return 55; } } rfield@1422: * class C implements I, J { rfield@1422: * public int m(String s) { return I.super.m(s); } rfield@1422: * } rfield@1422: * rfield@1422: * TEST: C c = new C(); c.m("string") throws AME rfield@1422: */ rfield@1422: public void testSuperGenericDisqual() { rfield@1422: MethodParameter t = new MethodParameter("T", "t"); rfield@1422: MethodParameter s = new MethodParameter("String", "s"); rfield@1422: rfield@1422: Interface I = new Interface("I", new TypeParameter("T"), rfield@1422: new DefaultMethod("int", stdMethodName, "return 44;", t)); rfield@1422: Interface J = new Interface("J", I.with("String"), rfield@1422: new DefaultMethod("int", stdMethodName, "return 55;", s)); rfield@1422: Class C = new Class("C", I.with("String"), J, rfield@1422: new ConcreteMethod("int", stdMethodName, rfield@1422: "return I.super.m(s);", AccessFlag.PUBLIC, s)); rfield@1422: C.addCompilationDependency(I.findMethod(stdMethodName)); rfield@1422: rfield@1422: assertThrows(AbstractMethodError.class, C, rfield@1422: new ConcreteMethod( rfield@1422: "int", stdMethodName, "return -1;", AccessFlag.PUBLIC, s), rfield@1422: "-1", "\"string\""); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default Integer m() { return new Integer(88); } } rfield@1422: * class C { Number m() { return new Integer(99); } } rfield@1422: * class D extends C implements I {} rfield@1422: * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; rfield@1422: * TEST: S s = new S(); s.foo() == new Integer(99) rfield@1422: */ rfield@1422: public void testCovarBridge() { rfield@1422: Interface I = new Interface("I", new DefaultMethod( rfield@1422: "Integer", "m", "return new Integer(88);")); rfield@1422: Class C = new Class("C", new ConcreteMethod( rfield@1422: "Number", "m", "return new Integer(99);", AccessFlag.PUBLIC)); rfield@1422: Class D = new Class("D", I, C); rfield@1422: rfield@1422: ConcreteMethod DstubMethod = new ConcreteMethod( rfield@1422: "Integer", "m", "return null;", AccessFlag.PUBLIC); rfield@1422: Class Dstub = new Class("D", DstubMethod); rfield@1422: rfield@1422: ConcreteMethod toCall = new ConcreteMethod( rfield@1422: "Object", "foo", "return (new D()).m();", AccessFlag.PUBLIC); rfield@1422: Class S = new Class("S", D, toCall); rfield@1422: S.addCompilationDependency(Dstub); rfield@1422: S.addCompilationDependency(DstubMethod); rfield@1422: rfield@1422: assertInvokeVirtualEquals(new Integer(99), S, toCall, "null"); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { default Integer m() { return new Integer(88); } } rfield@1422: * class C { int m() { return 99; } } rfield@1422: * class D extends C implements I {} rfield@1422: * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; rfield@1422: * TEST: S s = new S(); s.foo() == new Integer(88) rfield@1422: */ rfield@1422: public void testNoCovarNoBridge() { rfield@1422: Interface I = new Interface("I", new DefaultMethod( rfield@1422: "Integer", "m", "return new Integer(88);")); rfield@1422: Class C = new Class("C", new ConcreteMethod( rfield@1422: "int", "m", "return 99;", AccessFlag.PUBLIC)); rfield@1422: Class D = new Class("D", I, C); rfield@1422: rfield@1422: ConcreteMethod DstubMethod = new ConcreteMethod( rfield@1422: "Integer", "m", "return null;", AccessFlag.PUBLIC); rfield@1422: Class Dstub = new Class("D", DstubMethod); rfield@1422: rfield@1422: ConcreteMethod toCall = new ConcreteMethod( rfield@1422: "Object", "foo", "return (new D()).m();", AccessFlag.PUBLIC); rfield@1422: Class S = new Class("S", D, toCall); rfield@1422: S.addCompilationDependency(Dstub); rfield@1422: S.addCompilationDependency(DstubMethod); rfield@1422: rfield@1422: assertInvokeVirtualEquals(new Integer(88), S, toCall, "null"); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface J { int m(); } rfield@1422: * interface I extends J { default int m() { return 99; } } rfield@1422: * class B implements J {} rfield@1422: * class C extends B implements I {} rfield@1422: * TEST: C c = new C(); c.m() == 99 rfield@1422: * rfield@1422: * The point of this test is that B does not get default method analysis, rfield@1422: * and C does not generate any new miranda methods in the vtable. rfield@1422: * It verifies that default method analysis occurs when mirandas have been rfield@1422: * inherited and the supertypes don't have any overpass methods. rfield@1422: */ rfield@1422: public void testNoNewMiranda() { rfield@1422: Interface J = new Interface("J", AbstractMethod.std()); rfield@1422: Interface I = new Interface("I", J, DefaultMethod.std("99")); rfield@1422: Class B = new Class("B", J); rfield@1422: Class C = new Class("C", B, I); rfield@1422: assertInvokeVirtualEquals(99, C); rfield@1422: } rfield@1422: rfield@1422: /** rfield@1422: * interface I { int m(T t, V v, W w); } rfield@1422: * interface J implements I { int m(T t, V v, String w); } rfield@1422: * interface K implements J { rfield@1422: * int m(T t, String v, String w); { return 99; } } rfield@1422: * class C implements K { rfield@1422: * public int m(Object t, Object v, String w) { return 77; } rfield@1422: * } rfield@1422: * TEST C = new C(); ((I)c).m(Object,Object,Object) == 99 rfield@1422: * TEST C = new C(); ((J)c).m(Object,Object,String) == 77 rfield@1422: * TEST C = new C(); ((K)c).m(Object,String,String) == 99 rfield@1422: * rfield@1422: * Test that a erased-signature-matching method does not implement rfield@1422: * non-language-level matching methods rfield@1422: */ rfield@1422: public void testNonConcreteFill() { rfield@1422: AbstractMethod ipm = new AbstractMethod("int", "m", rfield@1422: new MethodParameter("T", "t"), rfield@1422: new MethodParameter("V", "s"), rfield@1422: new MethodParameter("W", "w")); rfield@1422: Interface I = new Interface("I", rfield@1422: new TypeParameter("T"), rfield@1422: new TypeParameter("V"), rfield@1422: new TypeParameter("W"), ipm); rfield@1422: rfield@1422: AbstractMethod jpm = new AbstractMethod("int", "m", rfield@1422: new MethodParameter("T", "t"), rfield@1422: new MethodParameter("V", "s"), rfield@1422: new MethodParameter("String", "w")); rfield@1422: Interface J = new Interface("J", rfield@1422: new TypeParameter("T"), rfield@1422: new TypeParameter("V"), rfield@1422: I.with("T", "V", "String"), jpm); rfield@1422: rfield@1422: AbstractMethod kpm = new AbstractMethod("int", "m", rfield@1422: new MethodParameter("T", "t"), rfield@1422: new MethodParameter("String", "s"), rfield@1422: new MethodParameter("String", "w")); rfield@1422: Interface K = new Interface("K", rfield@1422: new TypeParameter("T"), rfield@1422: J.with("T", "String"), rfield@1422: new DefaultMethod("int", "m", "return 99;", rfield@1422: new MethodParameter("T", "t"), rfield@1422: new MethodParameter("String", "v"), rfield@1422: new MethodParameter("String", "w"))); rfield@1422: rfield@1422: Class C = new Class("C", rfield@1422: K.with("String"), rfield@1422: new ConcreteMethod("int", "m", "return 77;", rfield@1422: AccessFlag.PUBLIC, rfield@1422: new MethodParameter("Object", "t"), rfield@1422: new MethodParameter("Object", "v"), rfield@1422: new MethodParameter("String", "w"))); rfield@1422: rfield@1422: String a = "\"\""; rfield@1422: assertInvokeInterfaceEquals(99, C, rfield@1422: K.with("String"), kpm, a, a, a); rfield@1422: assertInvokeInterfaceEquals(77, C, rfield@1422: J.with("String", "String"), jpm, a, a, a); rfield@1422: assertInvokeInterfaceEquals(99, C, rfield@1422: I.with("String", "String", "String"), ipm, a, a, a); rfield@1422: } rfield@1422: rfield@1422: public void testStrictfpDefault() { rfield@1422: try { rfield@1422: java.lang.Class.forName("org.openjdk.tests.vm.StrictfpDefault"); rfield@1422: } catch (Exception e) { rfield@1422: fail("Could not load class", e); rfield@1422: } rfield@1422: } rfield@1422: } rfield@1422: rfield@1422: interface StrictfpDefault { rfield@1422: default strictfp void m() {} rfield@1422: }