/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/java/beans/Introspector/DefaultMethodBeanPropertyTest.java
577 строк
19 KB
Roman Marchenko
8347826: Introspector shows wrong method list after 8071693
03 июн 2025, 09:00
03 июн 2025, 09:00
c5f235c
Код
Авторство
О чём код?
/* * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8071693 8347826 * @summary Verify that the Introspector finds default methods inherited * from interfaces */ import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.NavigableSet; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class DefaultMethodBeanPropertyTest { ////////////////////////////////////// // // // SCENARIO 1 // // // ////////////////////////////////////// public interface A1 { default int getValue() { return 0; } default Object getObj() { return null; } public static int getStaticValue() { return 0; } } public interface B1 extends A1 { } public interface C1 extends A1 { Number getFoo(); } public class D1 implements C1 { @Override public Integer getFoo() { return null; } @Override public Float getObj() { return null; } } public static void testScenario1() { verifyMethods(D1.class, "public static int DefaultMethodBeanPropertyTest$A1.getStaticValue()", "public default int DefaultMethodBeanPropertyTest$A1.getValue()", "public java.lang.Integer DefaultMethodBeanPropertyTest$D1.getFoo()", "public java.lang.Float DefaultMethodBeanPropertyTest$D1.getObj()" ); verifyProperties(D1.class, "public final native java.lang.Class java.lang.Object.getClass()", "public default int DefaultMethodBeanPropertyTest$A1.getValue()", "public java.lang.Integer DefaultMethodBeanPropertyTest$D1.getFoo()", "public java.lang.Float DefaultMethodBeanPropertyTest$D1.getObj()" ); } ////////////////////////////////////// // // // SCENARIO 2 // // // ////////////////////////////////////// public interface A2 { default Object getFoo() { return null; } } public interface B2 extends A2 { } public interface C2 extends A2 { } public class D2 implements B2, C2 { } public static void testScenario2() { verifyMethods(D2.class, "public default java.lang.Object DefaultMethodBeanPropertyTest$A2.getFoo()" ); verifyProperties(D2.class, "public final native java.lang.Class java.lang.Object.getClass()", "public default java.lang.Object DefaultMethodBeanPropertyTest$A2.getFoo()" ); } ////////////////////////////////////// // // // SCENARIO 3 // // // ////////////////////////////////////// public interface A3 { default Object getFoo() { return null; } } public interface B3 extends A3 { @Override Set<?> getFoo(); } public interface C3 extends A3 { @Override Collection<?> getFoo(); } public class D3 implements B3, C3 { @Override public NavigableSet<?> getFoo() { return null; } } public static void testScenario3() { verifyMethods(D3.class, "public java.util.NavigableSet DefaultMethodBeanPropertyTest$D3.getFoo()" ); verifyProperties(D3.class, "public final native java.lang.Class java.lang.Object.getClass()", "public java.util.NavigableSet DefaultMethodBeanPropertyTest$D3.getFoo()" ); } ////////////////////////////////////// // // // SCENARIO 4 // // // ////////////////////////////////////// public interface A4 { default Object getDefault0() { return null; } default Object getDefault1() { return null; } default Object getDefault2() { return null; } default Object getDefault3() { return null; } Object getNonDefault(); } public class B4 implements A4 { @Override public Object getDefault1() { return new B4(); } @Override public String getDefault2() { return null; } @Override public Float getDefault3() { return null; } public Long getNonDefault() { return null; } } public static void testScenario4() { verifyMethods(B4.class, "public default java.lang.Object DefaultMethodBeanPropertyTest$A4.getDefault0()", "public java.lang.Object DefaultMethodBeanPropertyTest$B4.getDefault1()", "public java.lang.String DefaultMethodBeanPropertyTest$B4.getDefault2()", "public java.lang.Float DefaultMethodBeanPropertyTest$B4.getDefault3()", "public java.lang.Long DefaultMethodBeanPropertyTest$B4.getNonDefault()" ); verifyProperties(B4.class, "public final native java.lang.Class java.lang.Object.getClass()", "public default java.lang.Object DefaultMethodBeanPropertyTest$A4.getDefault0()", "public java.lang.Object DefaultMethodBeanPropertyTest$B4.getDefault1()", "public java.lang.String DefaultMethodBeanPropertyTest$B4.getDefault2()", "public java.lang.Float DefaultMethodBeanPropertyTest$B4.getDefault3()", "public java.lang.Long DefaultMethodBeanPropertyTest$B4.getNonDefault()" ); } ////////////////////////////////////// // // // SCENARIO 5 // // // ////////////////////////////////////// public interface A5 { public default void setParentFoo(Integer num) { } public default void setFoo(String num) { } public static int getStaticValue() { return 0; } private int getPrivateValue() { return 0; } } public class B5 implements A5 { public void setFoo(Number num) { } public void setLocalFoo(Long num) { } public static int getStaticValue() { return 0; } } public static void testScenario5() { verifyMethods(B5.class, "public static int DefaultMethodBeanPropertyTest$B5.getStaticValue()", "public default void DefaultMethodBeanPropertyTest$A5.setFoo(java.lang.String)", "public default void DefaultMethodBeanPropertyTest$A5.setParentFoo(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$B5.setFoo(java.lang.Number)", "public void DefaultMethodBeanPropertyTest$B5.setLocalFoo(java.lang.Long)" ); verifyProperties(B5.class, "public final native java.lang.Class java.lang.Object.getClass()", "public default void DefaultMethodBeanPropertyTest$A5.setParentFoo(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$B5.setFoo(java.lang.Number)", "public void DefaultMethodBeanPropertyTest$B5.setLocalFoo(java.lang.Long)" ); } ////////////////////////////////////// // // // SCENARIO 6 // // // ////////////////////////////////////// public class A6 { public void setParentFoo(Integer num) { } public void setFoo(Integer num) { } public static int getStaticValue() { return 0; } private int getPrivateValue() { return 0; } } public class B6 extends A6 { public void setFoo(String num) { } public void setLocalFoo(Long num) { } public static int getStaticValue() { return 0; } } public static void testScenario6() { verifyMethods(B6.class, "public static int DefaultMethodBeanPropertyTest$B6.getStaticValue()", "public void DefaultMethodBeanPropertyTest$A6.setFoo(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$A6.setParentFoo(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$B6.setFoo(java.lang.String)", "public void DefaultMethodBeanPropertyTest$B6.setLocalFoo(java.lang.Long)" ); verifyProperties(B6.class, "public final native java.lang.Class java.lang.Object.getClass()", "public void DefaultMethodBeanPropertyTest$A6.setParentFoo(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$B6.setFoo(java.lang.String)", "public void DefaultMethodBeanPropertyTest$B6.setLocalFoo(java.lang.Long)" ); } ////////////////////////////////////// // // // SCENARIO 7 // // // ////////////////////////////////////// interface A7<T> { T getValue(); } interface B7 { Runnable getValue(); } interface AB7 extends B7, A7<Object> { Runnable getValue(); } abstract class D7 implements AB7 { public void setValue(Runnable value) { } } public static void testScenario7() { verifyMethods(D7.class, "public void DefaultMethodBeanPropertyTest$D7.setValue(java.lang.Runnable)" ); verifyProperties(D7.class, "public final native java.lang.Class java.lang.Object.getClass()", "public void DefaultMethodBeanPropertyTest$D7.setValue(java.lang.Runnable)" ); } ////////////////////////////////////// // // // SCENARIO 8 // // // ////////////////////////////////////// public interface A8 { public default void setFoo(Float num) { } public default void setFoo2(Integer num) { } } public interface B8 extends A8 { public default void setFoo(Integer num) { } public default void setFoo2(Float num) { } } public class C8 implements B8 { } public static void testScenario8() { verifyMethods(C8.class, "public default void DefaultMethodBeanPropertyTest$A8.setFoo(java.lang.Float)", "public default void DefaultMethodBeanPropertyTest$A8.setFoo2(java.lang.Integer)", "public default void DefaultMethodBeanPropertyTest$B8.setFoo(java.lang.Integer)", "public default void DefaultMethodBeanPropertyTest$B8.setFoo2(java.lang.Float)" ); verifyProperties(C8.class, "public final native java.lang.Class java.lang.Object.getClass()", "public default void DefaultMethodBeanPropertyTest$B8.setFoo(java.lang.Integer)", "public default void DefaultMethodBeanPropertyTest$B8.setFoo2(java.lang.Float)" ); } ////////////////////////////////////// // // // SCENARIO 9 // // // ////////////////////////////////////// public class A9 { public void setFoo(Object value) { } public void setFoo(String value) { } public void setFoo2(Object value) { } public void setFoo2(Integer value) { } // For the same setters with inconvertible arg types PropertyInfo behavior is undefined. // public void setLocalFoo3(Long num) { } // public void setLocalFoo3(Float num) { } } public static void testScenario9() { verifyMethods(A9.class, "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.String)", "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.Object)", "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Integer)", "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Object)" ); verifyProperties(A9.class, "public final native java.lang.Class java.lang.Object.getClass()", "public void DefaultMethodBeanPropertyTest$A9.setFoo(java.lang.String)", "public void DefaultMethodBeanPropertyTest$A9.setFoo2(java.lang.Integer)" ); } ////////////////////////////////////// // // // SCENARIO 10 // // // ////////////////////////////////////// public static class A10 { public Object getProp() { return null; } } public static interface B10 { Object getProp(); } public static class C10_1 extends A10 implements B10 { } public static class C10_2 extends A10 implements B10 { } public static class A10BeanInfo extends SimpleBeanInfo { public MethodDescriptor[] getMethodDescriptors() { try { Class params[] = {}; MethodDescriptor md = new MethodDescriptor(A10.class.getDeclaredMethod("getProp", params)); md.setDisplayName("display name"); MethodDescriptor res[] = { md }; return res; } catch (Exception exception) { throw new Error("unexpected exception", exception); } } } public static class C10_1BeanInfo extends SimpleBeanInfo { public BeanInfo[] getAdditionalBeanInfo() { try { BeanInfo res[] = { Introspector.getBeanInfo(A10.class), Introspector.getBeanInfo(B10.class) }; return res; } catch (IntrospectionException exception) { throw new Error("unexpected exception", exception); } } } public static class C10_2BeanInfo extends SimpleBeanInfo { public BeanInfo[] getAdditionalBeanInfo() { try { BeanInfo res[] = { Introspector.getBeanInfo(B10.class), Introspector.getBeanInfo(A10.class) }; return res; } catch (IntrospectionException exception) { throw new Error("unexpected exception", exception); } } } public static void testScenario10() { { var md = getMethodDescriptor(C10_1.class, A10.class, "getProp"); assertEquals("display name", md.getDisplayName(), "getDisplayName()"); } { var md = getMethodDescriptor(C10_2.class, A10.class, "getProp"); assertEquals("display name", md.getDisplayName(), "getDisplayName()"); } } // Helper methods private static void verifyEquality(String title, Set<String> expected, Set<String> actual) { if (!actual.equals(expected)) { throw new Error(title + " mismatch: " + "\nACTUAL:\n " + actual.stream() .map(Object::toString) .collect(Collectors.joining("\n ")) + "\nEXPECTED:\n " + expected.stream() .map(Object::toString) .collect(Collectors.joining("\n "))); } } public static void verifyProperties(Class<?> type, String... methodNames) { try { final Set<String> expected = new HashSet<>(Arrays.asList(methodNames)); final Set<String> actual = Arrays .stream(Introspector.getBeanInfo(type) .getPropertyDescriptors()) .flatMap(pd -> Stream.of(pd.getReadMethod(), pd.getWriteMethod())) .filter(Objects::nonNull) .map((Method m) -> m.toString()) .collect(Collectors.toSet()); verifyEquality("properties", expected, actual); } catch (IntrospectionException exception) { throw new Error("unexpected exception", exception); } } public static void verifyMethods(Class<?> type, String... methodNames) { try { final Set<String> expected = new HashSet<>(Arrays.asList(methodNames)); final Set<String> actual = Arrays .stream(Introspector.getBeanInfo(type, Object.class) .getMethodDescriptors()) .map(MethodDescriptor::getMethod) .map(Method::toString) .collect(Collectors.toSet()); verifyEquality("methods", expected, actual); } catch (IntrospectionException exception) { throw new Error("unexpected exception", exception); } } private static MethodDescriptor getMethodDescriptor(Class cls, Class stop, String name) { try { for (var md : Introspector.getBeanInfo(cls, stop).getMethodDescriptors()) { if (md.getName().equals(name)) { return md; } } return null; } catch (IntrospectionException exception) { throw new Error("unexpected exception", exception); } } private static void assertEquals(Object expected, Object actual, String msg) { if (!expected.equals(actual)) { throw new Error(msg + ":\nACTUAL: " + actual + "\nEXPECTED: " + expected); } } // Main method public static void main(String[] args) throws Exception { testScenario1(); testScenario2(); testScenario3(); testScenario4(); testScenario5(); testScenario6(); testScenario7(); testScenario8(); testScenario9(); testScenario10(); } }