Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/openmbean/ConstraintTest.java
38839 views
/*1* Copyright (c) 2005, 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 620446926* @summary Test that Open MBean attributes and parameters check constraints27* @author Eamonn McManus28* @run clean ConstraintTest29* @run build ConstraintTest30* @run main ConstraintTest31*/3233import java.util.*;34import javax.management.*;35import javax.management.openmbean.*;3637public class ConstraintTest {38private static String failure;3940public static void main(String[] args) throws Exception {41for (Object[][] test : tests) {42if (test.length != 4) {43throw new Exception("Test element has wrong length: " +44Arrays.deepToString(test));45}4647if (test[0].length != 4) {48throw new Exception("Test constraints should have size 4: " +49Arrays.deepToString(test[0]));50}51Object defaultValue = test[0][0];52Comparable<?> minValue = (Comparable<?>) test[0][1];53Comparable<?> maxValue = (Comparable<?>) test[0][2];54Object[] legalValues = (Object[]) test[0][3];55System.out.println("test: defaultValue=" + defaultValue +56"; minValue=" + minValue +57"; maxValue=" + maxValue +58"; legalValues=" +59Arrays.deepToString(legalValues));6061if (test[1].length != 1) {62throw new Exception("OpenType list should have size 1: " +63Arrays.deepToString(test[1]));64}65OpenType<?> openType = (OpenType<?>) test[1][0];6667Object[] valid = test[2];68Object[] invalid = test[3];6970System.out.println("...valid=" + Arrays.deepToString(valid));71System.out.println("...invalid=" + Arrays.deepToString(invalid));7273test(openType, defaultValue, minValue, maxValue, legalValues,74valid, invalid);75}7677if (failure == null)78System.out.println("Test passed");79else80throw new Exception("TEST FAILED: " + failure);81}8283private static <T> void test(OpenType<T> openType, Object defaultValue,84Comparable<?> minValue,85Comparable<?> maxValue, Object[] legalValues,86Object[] valid, Object[] invalid)87throws Exception {88/* This hack is needed to avoid grief from the parameter checking89in the OpenMBean*InfoSupport constructors. Since they are defined90to check that the defaultValue etc are of the same type as the91OpenType<T>, there is no way to pass a defaultValue etc when92the type is OpenType<?>. So either you have to write plain93OpenType, and get unchecked warnings for every constructor94invocation, or you do this, and get the unchecked warnings just95here. */96test1(openType, (T) defaultValue, (Comparable<T>) minValue,97(Comparable<T>) maxValue, (T[]) legalValues, valid, invalid);98}99100private static <T> void test1(OpenType<T> openType, T defaultValue,101Comparable<T> minValue,102Comparable<T> maxValue, T[] legalValues,103Object[] valid, Object[] invalid)104throws Exception {105106if (legalValues != null && (minValue != null || maxValue != null))107throw new Exception("Test case has both legals and min/max");108109if (defaultValue == null && minValue == null && maxValue == null &&110legalValues == null) {111test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,112true, true, false),113valid, invalid);114test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,115true, true, false, nullD),116valid, invalid);117test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,118true, true, false, emptyD),119valid, invalid);120test(new OpenMBeanParameterInfoSupport("name", "descr", openType),121valid, invalid);122test(new OpenMBeanParameterInfoSupport("name", "descr", openType,123nullD),124valid, invalid);125test(new OpenMBeanParameterInfoSupport("name", "descr", openType,126emptyD),127valid, invalid);128}129130if (minValue == null && maxValue == null && legalValues == null) {131Descriptor d = descriptor("defaultValue", defaultValue);132test(new OpenMBeanAttributeInfoSupport("blah", "descr", openType,133true, true, false, d),134valid, invalid);135test(new OpenMBeanAttributeInfoSupport("blah", "descr",136openType, true, true,137false, defaultValue),138valid, invalid);139test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,140d),141valid, invalid);142test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,143defaultValue),144valid, invalid);145}146147if (legalValues == null) {148Descriptor d = descriptor("defaultValue", defaultValue,149"minValue", minValue,150"maxValue", maxValue);151test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,152true, true, false, d),153valid, invalid);154test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,155true, true, false,156defaultValue,157minValue, maxValue),158valid, invalid);159test(new OpenMBeanParameterInfoSupport("name", "descr", openType,160d),161valid, invalid);162test(new OpenMBeanParameterInfoSupport("name", "descr", openType,163defaultValue,164minValue, maxValue),165valid, invalid);166}167168if (minValue == null && maxValue == null) {169// Legal values in descriptor can be either an array or a set170Descriptor d1 = descriptor("defaultValue", defaultValue,171"legalValues", legalValues);172Descriptor d2;173if (legalValues == null)174d2 = d1;175else {176d2 = descriptor("defaultValue", defaultValue,177"legalValues", arraySet(legalValues));178}179test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,180true, true, false, d1),181valid, invalid);182test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,183true, true, false, d2),184valid, invalid);185test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,186true, true, false,187defaultValue, legalValues),188valid, invalid);189test(new OpenMBeanParameterInfoSupport("name", "descr", openType,190d1),191valid, invalid);192test(new OpenMBeanParameterInfoSupport("name", "descr", openType,193d2),194valid, invalid);195test(new OpenMBeanParameterInfoSupport("name", "descr", openType,196defaultValue, legalValues),197valid, invalid);198}199}200201/* Test one of the objects. Note that OpenMBeanAttributeInfo202extends OpenMBeanParameterInfo, so OpenMBeanAttributeInfoSupport203is-an OpenMBeanParameterInfo. */204private static void test(OpenMBeanParameterInfo info,205Object[] valid, Object[] invalid) {206test1(info, valid, invalid);207208// Check that the constraints can be specified as strings209// rather than objects210if (info.getOpenType() instanceof SimpleType<?>) {211Descriptor d = ((DescriptorRead) info).getDescriptor();212String[] names = d.getFieldNames();213Object[] values = d.getFieldValues(names);214for (int i = 0; i < values.length; i++) {215if (values[i] == null)216continue;217if (names[i].equals("legalValues")) {218Collection<?> legals;219if (values[i] instanceof Collection<?>)220legals = (Collection<?>) values[i];221else222legals = Arrays.asList((Object[]) values[i]);223List<String> strings = new ArrayList<String>();224for (Object legal : legals)225strings.add(legal.toString());226values[i] = strings.toArray(new String[0]);227} else if (!(values[i] instanceof OpenType<?>))228values[i] = values[i].toString();229}230d = new ImmutableDescriptor(names, values);231OpenType<?> ot = info.getOpenType();232if (info instanceof OpenMBeanAttributeInfo) {233OpenMBeanAttributeInfo ai = (OpenMBeanAttributeInfo) info;234info = new OpenMBeanAttributeInfoSupport(info.getName(),235info.getDescription(),236info.getOpenType(),237ai.isReadable(),238ai.isWritable(),239ai.isIs(),240d);241} else {242info = new OpenMBeanParameterInfoSupport(info.getName(),243info.getDescription(),244info.getOpenType(),245d);246}247test1(info, valid, invalid);248}249}250251private static void test1(OpenMBeanParameterInfo info,252Object[] valid, Object[] invalid) {253254for (Object x : valid) {255if (!info.isValue(x)) {256fail("Object should be valid but is not: " + x + " for: " +257info);258}259}260261for (Object x : invalid) {262if (info.isValue(x)) {263fail("Object should not be valid but is: " + x + " for: " +264info);265}266}267268/* If you specify e.g. minValue in a descriptor, then we arrange269for getMinValue() to return the same value, and if you specify270a minValue as a constructor parameter then we arrange for the271descriptor to have a minValue entry. Check that these values272do in fact match. */273274Descriptor d = ((DescriptorRead) info).getDescriptor();275276checkSameValue("defaultValue", info.getDefaultValue(),277d.getFieldValue("defaultValue"));278checkSameValue("minValue", info.getMinValue(),279d.getFieldValue("minValue"));280checkSameValue("maxValue", info.getMaxValue(),281d.getFieldValue("maxValue"));282checkSameValues("legalValues", info.getLegalValues(),283d.getFieldValue("legalValues"));284}285286private static void checkSameValue(String what, Object getterValue,287Object descriptorValue) {288if (getterValue == null) {289if (descriptorValue != null) {290fail("Getter returned null but descriptor has entry for " +291what + ": " + descriptorValue);292}293} else if (descriptorValue == null) {294fail("Getter returned value but descriptor has no entry for " +295what + ": " + getterValue);296} else if (!getterValue.equals(descriptorValue) &&297!getterValue.toString().equals(descriptorValue)) {298fail("For " + what + " getter returned " + getterValue +299" but descriptor entry is " + descriptorValue);300}301}302303private static void checkSameValues(String what, Set<?> getterValues,304Object descriptorValues) {305if (getterValues == null) {306if (descriptorValues != null) {307fail("Getter returned null but descriptor has entry for " +308what + ": " + descriptorValues);309}310} else if (descriptorValues == null) {311fail("Getter returned value but descriptor has no entry for " +312what + ": " + getterValues);313} else {314Set<?> descriptorValueSet;315if (descriptorValues instanceof Set<?>)316descriptorValueSet = (Set<?>) descriptorValues;317else318descriptorValueSet = arraySet((Object[]) descriptorValues);319boolean same = true;320if (getterValues.size() != descriptorValueSet.size())321same = false;322else {323for (Object x : getterValues) {324if (!descriptorValueSet.contains(x)325&& !descriptorValueSet.contains(x.toString())) {326same = false;327break;328}329}330}331if (!same) {332fail("For " + what + " getter returned " + getterValues +333" but descriptor entry is " + descriptorValueSet);334}335}336}337338private static void fail(String why) {339System.out.println("FAILED: " + why);340failure = why;341}342343private static Descriptor descriptor(Object... entries) {344if (entries.length % 2 != 0)345throw new RuntimeException("Odd length descriptor entries");346String[] names = new String[entries.length / 2];347Object[] values = new Object[entries.length / 2];348for (int i = 0; i < entries.length; i += 2) {349names[i / 2] = (String) entries[i];350values[i / 2] = entries[i + 1];351}352return new ImmutableDescriptor(names, values);353}354355private static <T> Set<T> arraySet(T[] array) {356return new HashSet<T>(Arrays.asList(array));357}358359private static final OpenType<?>360ostring = SimpleType.STRING,361oint = SimpleType.INTEGER,362obool = SimpleType.BOOLEAN,363olong = SimpleType.LONG,364obyte = SimpleType.BYTE,365ofloat = SimpleType.FLOAT,366odouble = SimpleType.DOUBLE,367ostringarray, ostringarray2;368private static final CompositeType ocomposite;369private static final CompositeData compositeData, compositeData2;370static {371try {372ostringarray = new ArrayType<String[]>(1, ostring);373ostringarray2 = new ArrayType<String[][]>(2, ostring);374ocomposite =375new CompositeType("name", "descr",376new String[] {"s", "i"},377new String[] {"sdesc", "idesc"},378new OpenType[] {ostring, oint});379compositeData =380new CompositeDataSupport(ocomposite,381new String[] {"s", "i"},382new Object[] {"foo", 23});383compositeData2 =384new CompositeDataSupport(ocomposite,385new String[] {"s", "i"},386new Object[] {"bar", -23});387} catch (OpenDataException e) { // damn checked exceptions...388throw new IllegalArgumentException(e.toString(), e);389}390}391392private static final Descriptor393nullD = null,394emptyD = ImmutableDescriptor.EMPTY_DESCRIPTOR;395396/* The elements of this array are grouped as follows. Each397element contains four Object[]s. The first one is a set of398four values: default value, min value, max value, legal values399(an Object[]), some of which can be null. These will be used400to derive the OpenMBean*Info values to be tested. The second401is an array with one element that is the OpenType that will be402given to the constructors of the OpenMBean*Infos. The third403element is a set of values that should be valid according to404the constraints in the OpenMBean*Info. The fourth is a set of405values that should be invalid according to those406constraints. */407private static final Object[][][] tests = {408409// Test cases when there are no constraints410// Validity checking is limited to type of object411412{{null, null, null, null},413{oint},414{-1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},415{null, "noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,416new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},417418{{null, null, null, null},419{obool},420{true, false},421{null, "noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,422new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},423424{{null, null, null, null},425{ostring},426{"", "yes!"},427{null, 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,428new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},429430{{null, null, null, null},431{obyte},432{Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},433{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,434new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},435436{{null, null, null, null},437{ostringarray},438{new String[0], new String[] {"hello", "world"}},439{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,440new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},441442{{null, null, null, null},443{ostringarray2},444{new String[0][0], new String[][] {{"hello", "world"},445{"goodbye", "cruel", "world"}}},446{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,447new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},448449{{null, null, null, null},450{ocomposite},451{compositeData, compositeData2},452{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,453new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},454455// Test cases where there is a default value, so null is allowed456457{{23, null, null, null},458{oint},459{null, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},460{"noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,461new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},462463{{true, null, null, null},464{obool},465{null, true, false},466{"noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,467new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},468469{{"foo", null, null, null},470{ostring},471{null, "", "yes!"},472{1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,473new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},474475{{(byte) 23, null, null, null},476{obyte},477{null, Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},478{"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,479new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},480481{{compositeData, null, null, null},482{ocomposite},483{null, compositeData, compositeData2},484{"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,485new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},486487// Test cases where there is a min and/or max, with or without default488489{{23, 0, 50, null},490{oint},491{null, 0, 25, 50},492{"noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},493494{{null, 0, 50, null},495{oint},496{0, 25, 50},497{null, "noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},498499{{null, 0, null, null},500{oint},501{0, 25, 50, Integer.MAX_VALUE},502{null, "noddy", -1, Integer.MIN_VALUE, 25L}},503504{{null, null, 50, null},505{oint},506{Integer.MIN_VALUE, -1, 0, 25, 50},507{null, "noddy", 51, Integer.MAX_VALUE, 25L}},508509{{"go", "a", "z~", null},510{ostring},511{null, "a", "z~", "zzzz", "z!"},512{"A", "~", "", -1}},513514// Test cases where there is a set of legal values515516{{23, null, null, new Integer[] {2, 3, 5, 7, 11, 13, 17, 23}},517{oint},518{null, 2, 11, 23},519{"noddy", -1, 1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},520521{{null, null, null, new CompositeData[] {compositeData}},522{ocomposite},523{compositeData},524{null, compositeData2, "noddy"}},525526{{null, null, null, new Long[0]},527{olong},528{}, // constraint is impossible to satisfy!529{null, 23L, "x", 23}},530};531}532533534