Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/MBeanInfo/MBeanInfoEqualsTest.java
38841 views
/*1* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 471992326* @summary Test that MBeanInfo.equals works even for mutable subclasses27* @author Eamonn McManus28* @run clean MBeanInfoEqualsTest29* @run build MBeanInfoEqualsTest30* @run main MBeanInfoEqualsTest31*/3233/* Test that MBeanInfo and its referenced classes implement the equals34and hashCode methods correctly. These classes include some magic35to improve performance based on the classes' immutability. The36logic checks that any subclasses encountered remain immutable, and37falls back on less performant code if not. */3839import javax.management.*;40import java.lang.reflect.*;4142public class MBeanInfoEqualsTest {43// Class just used for reflection44private static class Toy {45public Toy() {}46public Toy(int a, String b) {}47public int getA() {return 0;}48public void setA(int a) {}49public boolean isB() {return false;}50public void setB(boolean b) {}51public void run() {}52public void blah(int a, String b) {}53}5455static final Class toy = Toy.class;56static final Constructor con1, con2;57static final Method getA, setA, isB, setB, run, blah;58static {59try {60con1 = toy.getConstructor(new Class[] {});61con2 = toy.getConstructor(new Class[] {Integer.TYPE,62String.class});63getA = toy.getMethod("getA", new Class[] {});64setA = toy.getMethod("setA", new Class[] {Integer.TYPE});65isB = toy.getMethod("isB", new Class[] {});66setB = toy.getMethod("setB", new Class[] {Boolean.TYPE});67run = toy.getMethod("run", new Class[] {});68blah = toy.getMethod("blah", new Class[] {Integer.TYPE,69String.class});70} catch (Exception e) {71throw new Error(e.getMessage());72}73}7475private static final MBeanAttributeInfo76newMBeanAttributeInfo(String name, String description,77Method getter, Method setter) {78try {79return new MBeanAttributeInfo(name, description, getter, setter);80} catch (IntrospectionException e) {81throw new Error(e.getMessage());82}83}8485static final MBeanAttributeInfo86a1a = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",87true, true, false),88a1b = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",89true, true, false),90a2a = new MBeanAttributeInfo("splob", "java.foo.bar", "an attribute",91true, true, false),92a2b = new MBeanAttributeInfo(a2a.getName(), a2a.getType(),93a2a.getDescription(), a2a.isReadable(),94a2a.isWritable(), a2a.isIs()),95a3 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",96true, true, false),97a4 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",98false, true, false),99a5a = newMBeanAttributeInfo("a", "an attribute", getA, setA),100a5b = new MBeanAttributeInfo("a", "int", "an attribute",101true, true, false),102a6a = newMBeanAttributeInfo("a", "an attribute", getA, null),103a6b = new MBeanAttributeInfo("a", "int", "an attribute",104true, false, false),105a7a = newMBeanAttributeInfo("a", "an attribute", null, setA),106a7b = new MBeanAttributeInfo("a", "int", "an attribute",107false, true, false),108a8a = newMBeanAttributeInfo("b", "an attribute", isB, setB),109a8b = new MBeanAttributeInfo("b", "boolean", "an attribute",110true, true, true),111a9a = newMBeanAttributeInfo("b", "an attribute", isB, null),112a9b = new MBeanAttributeInfo("b", "boolean", "an attribute",113true, false, true);114115static final MBeanParameterInfo116p1a = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),117p1b = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),118p2 = new MBeanParameterInfo("splob", "java.foo.bar", "a parameter"),119p3 = new MBeanParameterInfo("thing", "java.foo.bax", "a parameter"),120p4 = new MBeanParameterInfo("thing", "java.foo.bar", "a whatsit");121122static final MBeanConstructorInfo123c1a = new MBeanConstructorInfo("a constructor", con1),124c1b = new MBeanConstructorInfo(c1a.getName(), "a constructor",125new MBeanParameterInfo[0]),126c1c = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),127c1a.getSignature()),128c1d = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),129null),130c2a = new MBeanConstructorInfo("another constructor", con2),131c2b = new MBeanConstructorInfo(c2a.getName(),132c2a.getDescription(),133c2a.getSignature()),134c3a = new MBeanConstructorInfo("conName", "a constructor",135new MBeanParameterInfo[] {p2, p3}),136c3b = new MBeanConstructorInfo("conName", "a constructor",137new MBeanParameterInfo[] {p2, p3}),138c4 = new MBeanConstructorInfo("conName", "a constructor",139new MBeanParameterInfo[] {p3, p2}),140c5 = new MBeanConstructorInfo("otherName", "a constructor",141new MBeanParameterInfo[] {p3, p2}),142c6 = new MBeanConstructorInfo("otherName", "another constructor",143new MBeanParameterInfo[] {p3, p2});144145static final MBeanOperationInfo146o1a = new MBeanOperationInfo("an operation", run),147o1b = new MBeanOperationInfo("an operation", run),148o1c = new MBeanOperationInfo("run", "an operation",149o1a.getSignature(), "void",150o1a.getImpact()),151o1d = new MBeanOperationInfo("run", "an operation",152new MBeanParameterInfo[0], "void",153o1a.getImpact()),154o1e = new MBeanOperationInfo("run", "an operation",155null, "void",156o1a.getImpact()),157o2a = new MBeanOperationInfo("another operation", blah),158o2b = new MBeanOperationInfo(o2a.getName(), o2a.getDescription(),159o2a.getSignature(), o2a.getReturnType(),160o2a.getImpact());161162static final MBeanNotificationInfo163n1a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},164"x.y.z",165"a notification info"),166n1b = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},167"x.y.z",168"a notification info"),169n2a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},170"x.y.z",171"another notification info"),172n2b = new MBeanNotificationInfo(n2a.getNotifTypes(),173n2a.getName(),174n2a.getDescription()),175n3 = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},176"x.y.zz",177"a notification info"),178n4 = new MBeanNotificationInfo(new String[] {"c.d", "a.b"},179"x.y.z",180"a notification info");181182static final MBeanAttributeInfo[]183xa1a = {a1a, a2a},184xa1b = {a1b, a2b},185xa2a = {a2a, a1a};186187static final MBeanConstructorInfo[]188xc1a = {c1a, c2a},189xc1b = {c1b, c2b},190xc2a = {c2a, c1a};191192static final MBeanOperationInfo[]193xo1a = {o1a, o2a},194xo1b = {o1b, o2b},195xo2a = {o2a, o1a};196197static final MBeanNotificationInfo[]198xn1a = {n1a, n2a},199xn1b = {n1b, n2b},200xn2a = {n2a, n1a};201202static final MBeanInfo203i1a = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),204i1b = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),205i1c = new MBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b, xn1b),206i1d = new MutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b,207xn1b),208i1e = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,209xo1b, xn1b),210i1f = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,211xo1b, xn1b),212i2a = new MBeanInfo("a.b.cc", "an MBean info", xa1a, xc1a, xo1a, xn1a),213i2b = new MBeanInfo(i2a.getClassName(), i2a.getDescription(),214i2a.getAttributes(), i2a.getConstructors(),215i2a.getOperations(), i2a.getNotifications()),216i3 = new MBeanInfo("a.b.c", "another MBean info", xa1a, xc1a, xo1a,217xn1a),218i4 = new MBeanInfo("a.b.c", "an MBean info", xa2a, xc1a, xo1a, xn1a),219i5 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc2a, xo1a, xn1a),220i6 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo2a, xn1a),221i7 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn2a);222223static final Object[][] equivalenceClasses = {224{a1a, a1b}, {a2a, a2b}, {a3}, {a4}, {a5a, a5b}, {a6a, a6b}, {a7a, a7b},225{a8a, a8b}, {a9a, a9b},226{c1a, c1b, c1c, c1d}, {c2a, c2b}, {c3a, c3b}, {c4}, {c5}, {c6},227{o1a, o1b, o1c, o1d, o1e}, {o2a, o2b},228{p1a, p1b}, {p2}, {p3}, {p4},229{n1a, n1b}, {n2a, n2b}, {n3}, {n4},230{i1a, i1b, i1c, i1d, i1e, i1f}, {i2a, i2b}, {i3}, {i4}, {i5}, {i6},231{i7},232};233234private static class ImmutableMBeanInfo extends MBeanInfo {235ImmutableMBeanInfo(String className,236String description,237MBeanAttributeInfo[] attributes,238MBeanConstructorInfo[] constructors,239MBeanOperationInfo[] operations,240MBeanNotificationInfo[] notifications) {241super(className, description, attributes, constructors, operations,242notifications);243}244}245246/* This class checks that the MBeanInfo.equals() method really247does call getClassName() etc rather than referring to its248private fields. */249private static class MutableMBeanInfo extends MBeanInfo {250private final String className;251private final String description;252private final MBeanAttributeInfo[] attributes;253private final MBeanOperationInfo[] operations;254private final MBeanConstructorInfo[] constructors;255private final MBeanNotificationInfo[] notifications;256257MutableMBeanInfo(String className,258String description,259MBeanAttributeInfo[] attributes,260MBeanConstructorInfo[] constructors,261MBeanOperationInfo[] operations,262MBeanNotificationInfo[] notifications) {263super("bogus", null, null, null, null, null);264this.className = className;265this.description = description;266this.attributes = attributes;267this.constructors = constructors;268this.operations = operations;269this.notifications = notifications;270}271272public String getClassName() {273return className;274}275276public String getDescription() {277return description;278}279280public MBeanAttributeInfo[] getAttributes() {281return attributes;282}283284public MBeanOperationInfo[] getOperations() {285return operations;286}287288public MBeanConstructorInfo[] getConstructors() {289return constructors;290}291292public MBeanNotificationInfo[] getNotifications() {293return notifications;294}295}296297private static boolean checkEquals(String what, Object[][] equivs) {298boolean ok = true;299/* The equivs array is an array of equivalence classes. The members300of each equivalence class must be equal among themselves.301Each member of each equivalence class must be different from302each member of each other equivalence class. */303for (int ei = 0; ei < equivs.length; ei++) {304Object[] ec1 = equivs[ei];305ok &= checkSame(what + " equivalence class " + ei, ec1);306for (int ej = 0; ej < equivs.length; ej++) {307if (ei == ej)308continue;309Object[] ec2 = equivs[ej];310ok &= checkDifferent(what + " equivalence classes " +311ei + " and " + ej, ec1, ec2);312}313}314if (ok)315System.out.println("equals test for " + what + " passed");316return ok;317}318319/* We could simplify this test to compare every element with every320other and choose whether they are supposed to be the same based321on whether they are in the same equivalence class. A bit322simpler, but so what. */323324private static boolean checkSame(String what, Object[] equiv) {325boolean ok = true;326for (int i = 0; i < equiv.length; i++) {327final Object o1 = equiv[i];328for (int j = 0; j < equiv.length; j++) {329final Object o2 = equiv[j];330if (!o1.equals(o2)) {331System.out.println("equals test: " + what +332": !obj[" + i +333"].equals(obj[" + j + "])");334System.out.println("..." + o1 + " " + o2);335ok = false;336}337if (o1.hashCode() != o2.hashCode()) {338System.out.println("equals test: " + what +339": obj[" + i +340"].hashCode() != obj[" + j +341"].hashCode()");342System.out.println("..." + o1 + " " + o2);343ok = false;344}345}346}347return ok;348}349350private static boolean checkDifferent(String what, Object[] equiv1,351Object[] equiv2) {352boolean ok = true;353for (int i = 0; i < equiv1.length; i++) {354final Object o1 = equiv1[i];355for (int j = 0; j < equiv2.length; j++) {356final Object o2 = equiv2[j];357if (o1.equals(o2)) {358System.out.println("equals test " + what + ": obj[" +359i + "].equals(obj[" + j + "])");360System.out.println("..." + o1 + " " + o2);361ok = false;362}363}364}365return ok;366}367368public static void main(String[] args) throws Exception {369boolean ok = true;370ok &= checkEquals("equivalence", equivalenceClasses);371if (ok) {372System.out.println("all tests passed");373} else {374System.out.println("at least one test failed");375System.exit(1);376}377}378}379380381