Path: blob/master/test/jdk/javax/management/openmbean/ConstraintTest.java
41149 views
/*1* Copyright (c) 2005, 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 620446926* @summary Test that Open MBean attributes and parameters check constraints27* @author Eamonn McManus28*29* @run clean ConstraintTest30* @run build ConstraintTest31* @run main ConstraintTest32*/3334import java.util.*;35import javax.management.*;36import javax.management.openmbean.*;3738public class ConstraintTest {39private static String failure;4041public static void main(String[] args) throws Exception {42for (Object[][] test : tests) {43if (test.length != 4) {44throw new Exception("Test element has wrong length: " +45Arrays.deepToString(test));46}4748if (test[0].length != 4) {49throw new Exception("Test constraints should have size 4: " +50Arrays.deepToString(test[0]));51}52Object defaultValue = test[0][0];53Comparable<?> minValue = (Comparable<?>) test[0][1];54Comparable<?> maxValue = (Comparable<?>) test[0][2];55Object[] legalValues = (Object[]) test[0][3];56System.out.println("test: defaultValue=" + defaultValue +57"; minValue=" + minValue +58"; maxValue=" + maxValue +59"; legalValues=" +60Arrays.deepToString(legalValues));6162if (test[1].length != 1) {63throw new Exception("OpenType list should have size 1: " +64Arrays.deepToString(test[1]));65}66OpenType<?> openType = (OpenType<?>) test[1][0];6768Object[] valid = test[2];69Object[] invalid = test[3];7071System.out.println("...valid=" + Arrays.deepToString(valid));72System.out.println("...invalid=" + Arrays.deepToString(invalid));7374test(openType, defaultValue, minValue, maxValue, legalValues,75valid, invalid);76}7778if (failure == null)79System.out.println("Test passed");80else81throw new Exception("TEST FAILED: " + failure);82}8384private static <T> void test(OpenType<T> openType, Object defaultValue,85Comparable<?> minValue,86Comparable<?> maxValue, Object[] legalValues,87Object[] valid, Object[] invalid)88throws Exception {89/* This hack is needed to avoid grief from the parameter checking90in the OpenMBean*InfoSupport constructors. Since they are defined91to check that the defaultValue etc are of the same type as the92OpenType<T>, there is no way to pass a defaultValue etc when93the type is OpenType<?>. So either you have to write plain94OpenType, and get unchecked warnings for every constructor95invocation, or you do this, and get the unchecked warnings just96here. */97test1(openType, (T) defaultValue, (Comparable<T>) minValue,98(Comparable<T>) maxValue, (T[]) legalValues, valid, invalid);99}100101private static <T> void test1(OpenType<T> openType, T defaultValue,102Comparable<T> minValue,103Comparable<T> maxValue, T[] legalValues,104Object[] valid, Object[] invalid)105throws Exception {106107if (legalValues != null && (minValue != null || maxValue != null))108throw new Exception("Test case has both legals and min/max");109110if (defaultValue == null && minValue == null && maxValue == null &&111legalValues == null) {112test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,113true, true, false),114valid, invalid);115test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,116true, true, false, nullD),117valid, invalid);118test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,119true, true, false, emptyD),120valid, invalid);121test(new OpenMBeanParameterInfoSupport("name", "descr", openType),122valid, invalid);123test(new OpenMBeanParameterInfoSupport("name", "descr", openType,124nullD),125valid, invalid);126test(new OpenMBeanParameterInfoSupport("name", "descr", openType,127emptyD),128valid, invalid);129}130131if (minValue == null && maxValue == null && legalValues == null) {132Descriptor d = descriptor("defaultValue", defaultValue);133test(new OpenMBeanAttributeInfoSupport("blah", "descr", openType,134true, true, false, d),135valid, invalid);136test(new OpenMBeanAttributeInfoSupport("blah", "descr",137openType, true, true,138false, defaultValue),139valid, invalid);140test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,141d),142valid, invalid);143test(new OpenMBeanParameterInfoSupport("blah", "descr", openType,144defaultValue),145valid, invalid);146}147148if (legalValues == null) {149Descriptor d = descriptor("defaultValue", defaultValue,150"minValue", minValue,151"maxValue", maxValue);152test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,153true, true, false, d),154valid, invalid);155test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,156true, true, false,157defaultValue,158minValue, maxValue),159valid, invalid);160test(new OpenMBeanParameterInfoSupport("name", "descr", openType,161d),162valid, invalid);163test(new OpenMBeanParameterInfoSupport("name", "descr", openType,164defaultValue,165minValue, maxValue),166valid, invalid);167}168169if (minValue == null && maxValue == null) {170// Legal values in descriptor can be either an array or a set171Descriptor d1 = descriptor("defaultValue", defaultValue,172"legalValues", legalValues);173Descriptor d2;174if (legalValues == null)175d2 = d1;176else {177d2 = descriptor("defaultValue", defaultValue,178"legalValues", arraySet(legalValues));179}180test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,181true, true, false, d1),182valid, invalid);183test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,184true, true, false, d2),185valid, invalid);186test(new OpenMBeanAttributeInfoSupport("name", "descr", openType,187true, true, false,188defaultValue, legalValues),189valid, invalid);190test(new OpenMBeanParameterInfoSupport("name", "descr", openType,191d1),192valid, invalid);193test(new OpenMBeanParameterInfoSupport("name", "descr", openType,194d2),195valid, invalid);196test(new OpenMBeanParameterInfoSupport("name", "descr", openType,197defaultValue, legalValues),198valid, invalid);199}200}201202/* Test one of the objects. Note that OpenMBeanAttributeInfo203extends OpenMBeanParameterInfo, so OpenMBeanAttributeInfoSupport204is-an OpenMBeanParameterInfo. */205private static void test(OpenMBeanParameterInfo info,206Object[] valid, Object[] invalid) {207test1(info, valid, invalid);208209// Check that the constraints can be specified as strings210// rather than objects211if (info.getOpenType() instanceof SimpleType<?>) {212Descriptor d = ((DescriptorRead) info).getDescriptor();213String[] names = d.getFieldNames();214Object[] values = d.getFieldValues(names);215for (int i = 0; i < values.length; i++) {216if (values[i] == null)217continue;218if (names[i].equals("legalValues")) {219Collection<?> legals;220if (values[i] instanceof Collection<?>)221legals = (Collection<?>) values[i];222else223legals = Arrays.asList((Object[]) values[i]);224List<String> strings = new ArrayList<String>();225for (Object legal : legals)226strings.add(legal.toString());227values[i] = strings.toArray(new String[0]);228} else if (!(values[i] instanceof OpenType<?>))229values[i] = values[i].toString();230}231d = new ImmutableDescriptor(names, values);232OpenType<?> ot = info.getOpenType();233if (info instanceof OpenMBeanAttributeInfo) {234OpenMBeanAttributeInfo ai = (OpenMBeanAttributeInfo) info;235info = new OpenMBeanAttributeInfoSupport(info.getName(),236info.getDescription(),237info.getOpenType(),238ai.isReadable(),239ai.isWritable(),240ai.isIs(),241d);242} else {243info = new OpenMBeanParameterInfoSupport(info.getName(),244info.getDescription(),245info.getOpenType(),246d);247}248test1(info, valid, invalid);249}250}251252private static void test1(OpenMBeanParameterInfo info,253Object[] valid, Object[] invalid) {254255for (Object x : valid) {256if (!info.isValue(x)) {257fail("Object should be valid but is not: " + x + " for: " +258info);259}260}261262for (Object x : invalid) {263if (info.isValue(x)) {264fail("Object should not be valid but is: " + x + " for: " +265info);266}267}268269/* If you specify e.g. minValue in a descriptor, then we arrange270for getMinValue() to return the same value, and if you specify271a minValue as a constructor parameter then we arrange for the272descriptor to have a minValue entry. Check that these values273do in fact match. */274275Descriptor d = ((DescriptorRead) info).getDescriptor();276277checkSameValue("defaultValue", info.getDefaultValue(),278d.getFieldValue("defaultValue"));279checkSameValue("minValue", info.getMinValue(),280d.getFieldValue("minValue"));281checkSameValue("maxValue", info.getMaxValue(),282d.getFieldValue("maxValue"));283checkSameValues("legalValues", info.getLegalValues(),284d.getFieldValue("legalValues"));285}286287private static void checkSameValue(String what, Object getterValue,288Object descriptorValue) {289if (getterValue == null) {290if (descriptorValue != null) {291fail("Getter returned null but descriptor has entry for " +292what + ": " + descriptorValue);293}294} else if (descriptorValue == null) {295fail("Getter returned value but descriptor has no entry for " +296what + ": " + getterValue);297} else if (!getterValue.equals(descriptorValue) &&298!getterValue.toString().equals(descriptorValue)) {299fail("For " + what + " getter returned " + getterValue +300" but descriptor entry is " + descriptorValue);301}302}303304private static void checkSameValues(String what, Set<?> getterValues,305Object descriptorValues) {306if (getterValues == null) {307if (descriptorValues != null) {308fail("Getter returned null but descriptor has entry for " +309what + ": " + descriptorValues);310}311} else if (descriptorValues == null) {312fail("Getter returned value but descriptor has no entry for " +313what + ": " + getterValues);314} else {315Set<?> descriptorValueSet;316if (descriptorValues instanceof Set<?>)317descriptorValueSet = (Set<?>) descriptorValues;318else319descriptorValueSet = arraySet((Object[]) descriptorValues);320boolean same = true;321if (getterValues.size() != descriptorValueSet.size())322same = false;323else {324for (Object x : getterValues) {325if (!descriptorValueSet.contains(x)326&& !descriptorValueSet.contains(x.toString())) {327same = false;328break;329}330}331}332if (!same) {333fail("For " + what + " getter returned " + getterValues +334" but descriptor entry is " + descriptorValueSet);335}336}337}338339private static void fail(String why) {340System.out.println("FAILED: " + why);341failure = why;342}343344private static Descriptor descriptor(Object... entries) {345if (entries.length % 2 != 0)346throw new RuntimeException("Odd length descriptor entries");347String[] names = new String[entries.length / 2];348Object[] values = new Object[entries.length / 2];349for (int i = 0; i < entries.length; i += 2) {350names[i / 2] = (String) entries[i];351values[i / 2] = entries[i + 1];352}353return new ImmutableDescriptor(names, values);354}355356private static <T> Set<T> arraySet(T[] array) {357return new HashSet<T>(Arrays.asList(array));358}359360private static final OpenType<?>361ostring = SimpleType.STRING,362oint = SimpleType.INTEGER,363obool = SimpleType.BOOLEAN,364olong = SimpleType.LONG,365obyte = SimpleType.BYTE,366ofloat = SimpleType.FLOAT,367odouble = SimpleType.DOUBLE,368ostringarray, ostringarray2;369private static final CompositeType ocomposite;370private static final CompositeData compositeData, compositeData2;371static {372try {373ostringarray = new ArrayType<String[]>(1, ostring);374ostringarray2 = new ArrayType<String[][]>(2, ostring);375ocomposite =376new CompositeType("name", "descr",377new String[] {"s", "i"},378new String[] {"sdesc", "idesc"},379new OpenType[] {ostring, oint});380compositeData =381new CompositeDataSupport(ocomposite,382new String[] {"s", "i"},383new Object[] {"foo", 23});384compositeData2 =385new CompositeDataSupport(ocomposite,386new String[] {"s", "i"},387new Object[] {"bar", -23});388} catch (OpenDataException e) { // damn checked exceptions...389throw new IllegalArgumentException(e.toString(), e);390}391}392393private static final Descriptor394nullD = null,395emptyD = ImmutableDescriptor.EMPTY_DESCRIPTOR;396397/* The elements of this array are grouped as follows. Each398element contains four Object[]s. The first one is a set of399four values: default value, min value, max value, legal values400(an Object[]), some of which can be null. These will be used401to derive the OpenMBean*Info values to be tested. The second402is an array with one element that is the OpenType that will be403given to the constructors of the OpenMBean*Infos. The third404element is a set of values that should be valid according to405the constraints in the OpenMBean*Info. The fourth is a set of406values that should be invalid according to those407constraints. */408private static final Object[][][] tests = {409410// Test cases when there are no constraints411// Validity checking is limited to type of object412413{{null, null, null, null},414{oint},415{-1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},416{null, "noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,417new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},418419{{null, null, null, null},420{obool},421{true, false},422{null, "noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,423new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},424425{{null, null, null, null},426{ostring},427{"", "yes!"},428{null, 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,429new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},430431{{null, null, null, null},432{obyte},433{Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},434{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,435new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},436437{{null, null, null, null},438{ostringarray},439{new String[0], new String[] {"hello", "world"}},440{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,441new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},442443{{null, null, null, null},444{ostringarray2},445{new String[0][0], new String[][] {{"hello", "world"},446{"goodbye", "cruel", "world"}}},447{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,448new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},449450{{null, null, null, null},451{ocomposite},452{compositeData, compositeData2},453{null, "noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,454new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},455456// Test cases where there is a default value, so null is allowed457458{{23, null, null, null},459{oint},460{null, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE},461{"noddy", 1.3, false, 3L, Long.MAX_VALUE, emptyD,462new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},463464{{true, null, null, null},465{obool},466{null, true, false},467{"noddy", 1.3, 3, 3L, Long.MAX_VALUE, emptyD,468new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},469470{{"foo", null, null, null},471{ostring},472{null, "", "yes!"},473{1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,474new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},475476{{(byte) 23, null, null, null},477{obyte},478{null, Byte.MIN_VALUE, Byte.MAX_VALUE, (byte) 0},479{"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,480new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},481482{{compositeData, null, null, null},483{ocomposite},484{null, compositeData, compositeData2},485{"noddy", 1.3, 3, false, 3L, Long.MAX_VALUE, emptyD,486new int[2], new Integer[2], new Integer[] {3}, new Integer[0]}},487488// Test cases where there is a min and/or max, with or without default489490{{23, 0, 50, null},491{oint},492{null, 0, 25, 50},493{"noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},494495{{null, 0, 50, null},496{oint},497{0, 25, 50},498{null, "noddy", -1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},499500{{null, 0, null, null},501{oint},502{0, 25, 50, Integer.MAX_VALUE},503{null, "noddy", -1, Integer.MIN_VALUE, 25L}},504505{{null, null, 50, null},506{oint},507{Integer.MIN_VALUE, -1, 0, 25, 50},508{null, "noddy", 51, Integer.MAX_VALUE, 25L}},509510{{"go", "a", "z~", null},511{ostring},512{null, "a", "z~", "zzzz", "z!"},513{"A", "~", "", -1}},514515// Test cases where there is a set of legal values516517{{23, null, null, new Integer[] {2, 3, 5, 7, 11, 13, 17, 23}},518{oint},519{null, 2, 11, 23},520{"noddy", -1, 1, 51, Integer.MIN_VALUE, Integer.MAX_VALUE, 25L}},521522{{null, null, null, new CompositeData[] {compositeData}},523{ocomposite},524{compositeData},525{null, compositeData2, "noddy"}},526527{{null, null, null, new Long[0]},528{olong},529{}, // constraint is impossible to satisfy!530{null, 23L, "x", 23}},531};532}533534535