Path: blob/master/test/jdk/javax/management/MBeanInfo/MBeanInfoEqualsTest.java
41149 views
/*1* Copyright (c) 2003, 2015, 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*29* @run clean MBeanInfoEqualsTest30* @run build MBeanInfoEqualsTest31* @run main MBeanInfoEqualsTest32*/3334/* Test that MBeanInfo and its referenced classes implement the equals35and hashCode methods correctly. These classes include some magic36to improve performance based on the classes' immutability. The37logic checks that any subclasses encountered remain immutable, and38falls back on less performant code if not. */3940import javax.management.*;41import java.lang.reflect.*;4243public class MBeanInfoEqualsTest {44// Class just used for reflection45private static class Toy {46public Toy() {}47public Toy(int a, String b) {}48public int getA() {return 0;}49public void setA(int a) {}50public boolean isB() {return false;}51public void setB(boolean b) {}52public void run() {}53public void blah(int a, String b) {}54}5556static final Class toy = Toy.class;57static final Constructor con1, con2;58static final Method getA, setA, isB, setB, run, blah;59static {60try {61con1 = toy.getConstructor(new Class[] {});62con2 = toy.getConstructor(new Class[] {Integer.TYPE,63String.class});64getA = toy.getMethod("getA", new Class[] {});65setA = toy.getMethod("setA", new Class[] {Integer.TYPE});66isB = toy.getMethod("isB", new Class[] {});67setB = toy.getMethod("setB", new Class[] {Boolean.TYPE});68run = toy.getMethod("run", new Class[] {});69blah = toy.getMethod("blah", new Class[] {Integer.TYPE,70String.class});71} catch (Exception e) {72throw new Error(e.getMessage());73}74}7576private static final MBeanAttributeInfo77newMBeanAttributeInfo(String name, String description,78Method getter, Method setter) {79try {80return new MBeanAttributeInfo(name, description, getter, setter);81} catch (IntrospectionException e) {82throw new Error(e.getMessage());83}84}8586static final MBeanAttributeInfo87a1a = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",88true, true, false),89a1b = new MBeanAttributeInfo("thing", "java.foo.bar", "an attribute",90true, true, false),91a2a = new MBeanAttributeInfo("splob", "java.foo.bar", "an attribute",92true, true, false),93a2b = new MBeanAttributeInfo(a2a.getName(), a2a.getType(),94a2a.getDescription(), a2a.isReadable(),95a2a.isWritable(), a2a.isIs()),96a3 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",97true, true, false),98a4 = new MBeanAttributeInfo("splob", "java.foo.bar", "a whatsit",99false, true, false),100a5a = newMBeanAttributeInfo("a", "an attribute", getA, setA),101a5b = new MBeanAttributeInfo("a", "int", "an attribute",102true, true, false),103a6a = newMBeanAttributeInfo("a", "an attribute", getA, null),104a6b = new MBeanAttributeInfo("a", "int", "an attribute",105true, false, false),106a7a = newMBeanAttributeInfo("a", "an attribute", null, setA),107a7b = new MBeanAttributeInfo("a", "int", "an attribute",108false, true, false),109a8a = newMBeanAttributeInfo("b", "an attribute", isB, setB),110a8b = new MBeanAttributeInfo("b", "boolean", "an attribute",111true, true, true),112a9a = newMBeanAttributeInfo("b", "an attribute", isB, null),113a9b = new MBeanAttributeInfo("b", "boolean", "an attribute",114true, false, true);115116static final MBeanParameterInfo117p1a = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),118p1b = new MBeanParameterInfo("thing", "java.foo.bar", "a parameter"),119p2 = new MBeanParameterInfo("splob", "java.foo.bar", "a parameter"),120p3 = new MBeanParameterInfo("thing", "java.foo.bax", "a parameter"),121p4 = new MBeanParameterInfo("thing", "java.foo.bar", "a whatsit");122123static final MBeanConstructorInfo124c1a = new MBeanConstructorInfo("a constructor", con1),125c1b = new MBeanConstructorInfo(c1a.getName(), "a constructor",126new MBeanParameterInfo[0]),127c1c = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),128c1a.getSignature()),129c1d = new MBeanConstructorInfo(c1a.getName(), c1a.getDescription(),130null),131c2a = new MBeanConstructorInfo("another constructor", con2),132c2b = new MBeanConstructorInfo(c2a.getName(),133c2a.getDescription(),134c2a.getSignature()),135c3a = new MBeanConstructorInfo("conName", "a constructor",136new MBeanParameterInfo[] {p2, p3}),137c3b = new MBeanConstructorInfo("conName", "a constructor",138new MBeanParameterInfo[] {p2, p3}),139c4 = new MBeanConstructorInfo("conName", "a constructor",140new MBeanParameterInfo[] {p3, p2}),141c5 = new MBeanConstructorInfo("otherName", "a constructor",142new MBeanParameterInfo[] {p3, p2}),143c6 = new MBeanConstructorInfo("otherName", "another constructor",144new MBeanParameterInfo[] {p3, p2});145146static final MBeanOperationInfo147o1a = new MBeanOperationInfo("an operation", run),148o1b = new MBeanOperationInfo("an operation", run),149o1c = new MBeanOperationInfo("run", "an operation",150o1a.getSignature(), "void",151o1a.getImpact()),152o1d = new MBeanOperationInfo("run", "an operation",153new MBeanParameterInfo[0], "void",154o1a.getImpact()),155o1e = new MBeanOperationInfo("run", "an operation",156null, "void",157o1a.getImpact()),158o2a = new MBeanOperationInfo("another operation", blah),159o2b = new MBeanOperationInfo(o2a.getName(), o2a.getDescription(),160o2a.getSignature(), o2a.getReturnType(),161o2a.getImpact());162163static final MBeanNotificationInfo164n1a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},165"x.y.z",166"a notification info"),167n1b = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},168"x.y.z",169"a notification info"),170n2a = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},171"x.y.z",172"another notification info"),173n2b = new MBeanNotificationInfo(n2a.getNotifTypes(),174n2a.getName(),175n2a.getDescription()),176n3 = new MBeanNotificationInfo(new String[] {"a.b", "c.d"},177"x.y.zz",178"a notification info"),179n4 = new MBeanNotificationInfo(new String[] {"c.d", "a.b"},180"x.y.z",181"a notification info");182183static final MBeanAttributeInfo[]184xa1a = {a1a, a2a},185xa1b = {a1b, a2b},186xa2a = {a2a, a1a};187188static final MBeanConstructorInfo[]189xc1a = {c1a, c2a},190xc1b = {c1b, c2b},191xc2a = {c2a, c1a};192193static final MBeanOperationInfo[]194xo1a = {o1a, o2a},195xo1b = {o1b, o2b},196xo2a = {o2a, o1a};197198static final MBeanNotificationInfo[]199xn1a = {n1a, n2a},200xn1b = {n1b, n2b},201xn2a = {n2a, n1a};202203static final MBeanInfo204i1a = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),205i1b = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn1a),206i1c = new MBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b, xn1b),207i1d = new MutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b, xo1b,208xn1b),209i1e = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,210xo1b, xn1b),211i1f = new ImmutableMBeanInfo("a.b.c", "an MBean info", xa1b, xc1b,212xo1b, xn1b),213i2a = new MBeanInfo("a.b.cc", "an MBean info", xa1a, xc1a, xo1a, xn1a),214i2b = new MBeanInfo(i2a.getClassName(), i2a.getDescription(),215i2a.getAttributes(), i2a.getConstructors(),216i2a.getOperations(), i2a.getNotifications()),217i3 = new MBeanInfo("a.b.c", "another MBean info", xa1a, xc1a, xo1a,218xn1a),219i4 = new MBeanInfo("a.b.c", "an MBean info", xa2a, xc1a, xo1a, xn1a),220i5 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc2a, xo1a, xn1a),221i6 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo2a, xn1a),222i7 = new MBeanInfo("a.b.c", "an MBean info", xa1a, xc1a, xo1a, xn2a);223224static final Object[][] equivalenceClasses = {225{a1a, a1b}, {a2a, a2b}, {a3}, {a4}, {a5a, a5b}, {a6a, a6b}, {a7a, a7b},226{a8a, a8b}, {a9a, a9b},227{c1a, c1b, c1c, c1d}, {c2a, c2b}, {c3a, c3b}, {c4}, {c5}, {c6},228{o1a, o1b, o1c, o1d, o1e}, {o2a, o2b},229{p1a, p1b}, {p2}, {p3}, {p4},230{n1a, n1b}, {n2a, n2b}, {n3}, {n4},231{i1a, i1b, i1c, i1d, i1e, i1f}, {i2a, i2b}, {i3}, {i4}, {i5}, {i6},232{i7},233};234235private static class ImmutableMBeanInfo extends MBeanInfo {236ImmutableMBeanInfo(String className,237String description,238MBeanAttributeInfo[] attributes,239MBeanConstructorInfo[] constructors,240MBeanOperationInfo[] operations,241MBeanNotificationInfo[] notifications) {242super(className, description, attributes, constructors, operations,243notifications);244}245}246247/* This class checks that the MBeanInfo.equals() method really248does call getClassName() etc rather than referring to its249private fields. */250private static class MutableMBeanInfo extends MBeanInfo {251private final String className;252private final String description;253private final MBeanAttributeInfo[] attributes;254private final MBeanOperationInfo[] operations;255private final MBeanConstructorInfo[] constructors;256private final MBeanNotificationInfo[] notifications;257258MutableMBeanInfo(String className,259String description,260MBeanAttributeInfo[] attributes,261MBeanConstructorInfo[] constructors,262MBeanOperationInfo[] operations,263MBeanNotificationInfo[] notifications) {264super("bogus", null, null, null, null, null);265this.className = className;266this.description = description;267this.attributes = attributes;268this.constructors = constructors;269this.operations = operations;270this.notifications = notifications;271}272273public String getClassName() {274return className;275}276277public String getDescription() {278return description;279}280281public MBeanAttributeInfo[] getAttributes() {282return attributes;283}284285public MBeanOperationInfo[] getOperations() {286return operations;287}288289public MBeanConstructorInfo[] getConstructors() {290return constructors;291}292293public MBeanNotificationInfo[] getNotifications() {294return notifications;295}296}297298private static boolean checkEquals(String what, Object[][] equivs) {299boolean ok = true;300/* The equivs array is an array of equivalence classes. The members301of each equivalence class must be equal among themselves.302Each member of each equivalence class must be different from303each member of each other equivalence class. */304for (int ei = 0; ei < equivs.length; ei++) {305Object[] ec1 = equivs[ei];306ok &= checkSame(what + " equivalence class " + ei, ec1);307for (int ej = 0; ej < equivs.length; ej++) {308if (ei == ej)309continue;310Object[] ec2 = equivs[ej];311ok &= checkDifferent(what + " equivalence classes " +312ei + " and " + ej, ec1, ec2);313}314}315if (ok)316System.out.println("equals test for " + what + " passed");317return ok;318}319320/* We could simplify this test to compare every element with every321other and choose whether they are supposed to be the same based322on whether they are in the same equivalence class. A bit323simpler, but so what. */324325private static boolean checkSame(String what, Object[] equiv) {326boolean ok = true;327for (int i = 0; i < equiv.length; i++) {328final Object o1 = equiv[i];329for (int j = 0; j < equiv.length; j++) {330final Object o2 = equiv[j];331if (!o1.equals(o2)) {332System.out.println("equals test: " + what +333": !obj[" + i +334"].equals(obj[" + j + "])");335System.out.println("..." + o1 + " " + o2);336ok = false;337}338if (o1.hashCode() != o2.hashCode()) {339System.out.println("equals test: " + what +340": obj[" + i +341"].hashCode() != obj[" + j +342"].hashCode()");343System.out.println("..." + o1 + " " + o2);344ok = false;345}346}347}348return ok;349}350351private static boolean checkDifferent(String what, Object[] equiv1,352Object[] equiv2) {353boolean ok = true;354for (int i = 0; i < equiv1.length; i++) {355final Object o1 = equiv1[i];356for (int j = 0; j < equiv2.length; j++) {357final Object o2 = equiv2[j];358if (o1.equals(o2)) {359System.out.println("equals test " + what + ": obj[" +360i + "].equals(obj[" + j + "])");361System.out.println("..." + o1 + " " + o2);362ok = false;363}364}365}366return ok;367}368369public static void main(String[] args) throws Exception {370boolean ok = true;371ok &= checkEquals("equivalence", equivalenceClasses);372if (ok) {373System.out.println("all tests passed");374} else {375System.out.println("at least one test failed");376System.exit(1);377}378}379}380381382