1 /* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6204469 27 * @summary Test that Open MBean attributes and parameters cannot have 28 * illegal constraints like min greater than max 29 * @author Eamonn McManus 30 * @modules java.management 31 * @run clean BadConstraintTest 32 * @run build BadConstraintTest 33 * @run main BadConstraintTest 34 */ 35 36 import java.io.*; 37 import java.lang.reflect.*; 38 import java.util.*; 39 import javax.management.*; 40 import javax.management.openmbean.*; 41 42 public class BadConstraintTest { 43 private static String failure; 44 45 public static void main(String[] args) throws Exception { 46 genericTests(); 47 descriptorTests(); 48 49 if (failure == null) 50 System.out.println("Test passed"); 51 else 52 throw new Exception("TEST FAILED: " + failure); 53 } 54 55 private static void genericTests() throws Exception { 56 for (Object[] test : tests) { 57 if (test.length != 5) { 58 throw new Exception("Test element has wrong length: " + 59 toString(test)); 60 } 61 62 OpenType<?> openType = (OpenType<?>) test[0]; 63 Object defaultValue = test[1]; 64 Comparable<?> minValue = (Comparable<?>) test[2]; 65 Comparable<?> maxValue = (Comparable<?>) test[3]; 66 Object[] legalValues = (Object[]) test[4]; 67 68 System.out.println("test: openType=" + openType + 69 "; defaultValue=" + defaultValue + 70 "; minValue=" + minValue + 71 "; maxValue=" + maxValue + 72 "; legalValues=" + toString(legalValues)); 73 74 genericTest(openType, defaultValue, minValue, maxValue, 75 legalValues); 76 } 77 } 78 79 private static void descriptorTests() throws Exception { 80 for (Object[][] test : descriptorTests) { 81 if (test.length != 2) { 82 throw new Exception("Test element has wrong length: " + 83 toString(test)); 84 } 85 86 if (test[0].length != 1) { 87 throw new Exception("Test element should have one OpenType: " + 88 toString(test[0])); 89 } 90 91 OpenType<?> openType = (OpenType<?>) test[0][0]; 92 Descriptor d = descriptor(test[1]); 93 94 System.out.println("test: openType=" + openType + 95 "; descriptor=" + d); 96 97 descriptorTest(openType, d); 98 } 99 } 100 101 /* Tests that apply to both the Descriptor and the non-Descriptor 102 constructors. We invoke the non-Descriptor constructors by 103 reflection, then we make the corresponding Descriptor and call 104 the descriptorTest with it. */ 105 private static void genericTest(OpenType<?> openType, 106 Object defaultValue, 107 Comparable<?> minValue, 108 Comparable<?> maxValue, 109 Object[] legalValues) 110 throws Exception { 111 112 if (minValue == null && maxValue == null && legalValues == null) { 113 if (defaultValue == null) 114 throw new Exception("What am I testing?"); 115 Class[] params1 = new Class[] { 116 String.class, String.class, OpenType.class, 117 boolean.class, boolean.class, boolean.class, 118 Object.class 119 }; 120 Constructor<OpenMBeanAttributeInfoSupport> c1 = 121 OpenMBeanAttributeInfoSupport.class.getConstructor(params1); 122 Class[] params2 = new Class[] { 123 String.class, String.class, OpenType.class, 124 Object.class 125 }; 126 Constructor<OpenMBeanParameterInfoSupport> c2 = 127 OpenMBeanParameterInfoSupport.class.getConstructor(params2); 128 ode(c1, "name", "descr", openType, true, true, false, defaultValue); 129 ode(c2, "name", "descr", openType, defaultValue); 130 descriptorTest(openType, 131 descriptor("defaultValue", defaultValue)); 132 descriptorTest(openType, 133 descriptor("defaultValue", string(defaultValue))); 134 } 135 136 if (legalValues == null) { 137 Class[] params1 = new Class[] { 138 String.class, String.class, OpenType.class, 139 boolean.class, boolean.class, boolean.class, 140 Object.class, Comparable.class, Comparable.class 141 }; 142 Constructor<OpenMBeanAttributeInfoSupport> c1 = 143 OpenMBeanAttributeInfoSupport.class.getConstructor(params1); 144 Class[] params2 = new Class[] { 145 String.class, String.class, OpenType.class, 146 Object.class, Comparable.class, Comparable.class 147 }; 148 Constructor<OpenMBeanParameterInfoSupport> c2 = 149 OpenMBeanParameterInfoSupport.class.getConstructor(params2); 150 ode(c1, "name", "descr", openType, true, true, false, defaultValue, 151 minValue, maxValue); 152 ode(c2, "name", "descr", openType, defaultValue, 153 minValue, maxValue); 154 descriptorTest(openType, 155 descriptor("defaultValue", defaultValue, 156 "minValue", minValue, 157 "maxValue", maxValue)); 158 descriptorTest(openType, 159 descriptor("defaultValue", string(defaultValue), 160 "minValue", string(minValue), 161 "maxValue", string(maxValue))); 162 } 163 164 if (legalValues != null) { 165 Class[] params1 = new Class[] { 166 String.class, String.class, OpenType.class, 167 boolean.class, boolean.class, boolean.class, 168 Object.class, Object[].class 169 }; 170 Constructor<OpenMBeanAttributeInfoSupport> c1 = 171 OpenMBeanAttributeInfoSupport.class.getConstructor(params1); 172 Class[] params2 = new Class[] { 173 String.class, String.class, OpenType.class, 174 Object.class, Object[].class 175 }; 176 Constructor<OpenMBeanParameterInfoSupport> c2 = 177 OpenMBeanParameterInfoSupport.class.getConstructor(params2); 178 ode(c1, "name", "descr", openType, true, true, false, defaultValue, 179 legalValues); 180 ode(c2, "name", "descr", openType, defaultValue, 181 legalValues); 182 descriptorTest(openType, 183 descriptor("defaultValue", defaultValue, 184 "legalValues", legalValues)); 185 descriptorTest(openType, 186 descriptor("defaultValue", defaultValue, 187 "legalValues", arraySet(legalValues))); 188 Set<String> strings = new HashSet<String>(); 189 for (Object x : legalValues) 190 strings.add(x.toString()); 191 descriptorTest(openType, 192 descriptor("defaultValue", defaultValue, 193 "legalValues", strings)); 194 descriptorTest(openType, 195 descriptor("defaultValue", defaultValue, 196 "legalValues", 197 strings.toArray(new String[0]))); 198 } 199 } 200 201 private static void descriptorTest(OpenType<?> openType, Descriptor d) 202 throws Exception { 203 Class[] params1 = new Class[] { 204 String.class, String.class, OpenType.class, 205 boolean.class, boolean.class, boolean.class, 206 Descriptor.class 207 }; 208 Constructor<OpenMBeanAttributeInfoSupport> c1 = 209 OpenMBeanAttributeInfoSupport.class.getConstructor(params1); 210 Class[] params2 = new Class[] { 211 String.class, String.class, OpenType.class, 212 Descriptor.class 213 }; 214 Constructor<OpenMBeanParameterInfoSupport> c2 = 215 OpenMBeanParameterInfoSupport.class.getConstructor(params2); 216 iae(c1, "name", "descr", openType, true, true, false, d); 217 iae(c2, "name", "descr", openType, d); 218 } 219 220 /* Check that the given constructor invocation gets an 221 IllegalArgumentException. */ 222 private static void iae(Constructor<?> con, Object... params) { 223 checkException(IllegalArgumentException.class, con, params); 224 } 225 226 /* Check that the given constructor invocation gets an 227 OpenDataException. */ 228 private static void ode(Constructor<?> con, Object... params) { 229 checkException(OpenDataException.class, con, params); 230 } 231 232 private static void checkException(Class<? extends Exception> exc, 233 Constructor<?> con, Object[] params) { 234 try { 235 con.newInstance(params); 236 fail("Constructor succeeded but should have got " + exc.getName() + 237 " with params " + Arrays.deepToString(params)); 238 } catch (InvocationTargetException e) { 239 Throwable cause = e.getCause(); 240 if (exc.isInstance(cause)) 241 return; 242 StringWriter sw = new StringWriter(); 243 PrintWriter pw = new PrintWriter(sw); 244 cause.printStackTrace(pw); 245 pw.close(); 246 fail("Constructor should have got " + exc.getName() + 247 " with params " + Arrays.deepToString(params) + ": " + sw); 248 } catch (Exception e) { 249 throw new IllegalArgumentException("Reflection failed", e); 250 } 251 } 252 253 private static void fail(String why) { 254 System.out.println("FAILED: " + why); 255 failure = why; 256 } 257 258 private static Descriptor descriptor(Object... entries) { 259 if (entries.length % 2 != 0) 260 throw new RuntimeException("Odd length descriptor entries"); 261 String[] names = new String[entries.length / 2]; 262 Object[] values = new Object[entries.length / 2]; 263 for (int i = 0; i < entries.length; i += 2) { 264 names[i / 2] = (String) entries[i]; 265 values[i / 2] = entries[i + 1]; 266 } 267 return new ImmutableDescriptor(names, values); 268 } 269 270 private static <T> Set<T> arraySet(T[] array) { 271 return new HashSet<T>(Arrays.asList(array)); 272 } 273 274 private static String toString(Object x) { 275 if (x == null) 276 return "null"; 277 else if (x.getClass().isArray()) { 278 StringBuilder sb = new StringBuilder("["); 279 int len = Array.getLength(x); 280 for (int i = 0; i < len; i++) { 281 if (i > 0) 282 sb.append(", "); 283 sb.append(toString(Array.get(x, i))); 284 } 285 sb.append("]"); 286 return sb.toString(); 287 } else 288 return x.toString(); 289 } 290 291 private static String string(Object x) { 292 if (x == null) 293 return null; 294 return toString(x); 295 } 296 297 private static final OpenType<?> 298 ostring = SimpleType.STRING, 299 oint = SimpleType.INTEGER, 300 obool = SimpleType.BOOLEAN, 301 olong = SimpleType.LONG, 302 obyte = SimpleType.BYTE, 303 ofloat = SimpleType.FLOAT, 304 odouble = SimpleType.DOUBLE, 305 ostringarray, ostringarray2; 306 private static final CompositeType ocomposite; 307 private static final CompositeData compositeData, compositeData2; 308 static { 309 try { 310 ostringarray = new ArrayType<String[]>(1, ostring); 311 ostringarray2 = new ArrayType<String[][]>(2, ostring); 312 ocomposite = 313 new CompositeType("name", "descr", 314 new String[] {"s", "i"}, 315 new String[] {"sdesc", "idesc"}, 316 new OpenType[] {ostring, oint}); 317 compositeData = 318 new CompositeDataSupport(ocomposite, 319 new String[] {"s", "i"}, 320 new Object[] {"foo", 23}); 321 compositeData2 = 322 new CompositeDataSupport(ocomposite, 323 new String[] {"s", "i"}, 324 new Object[] {"bar", -23}); 325 } catch (OpenDataException e) { // damn checked exceptions... 326 throw new IllegalArgumentException(e.toString(), e); 327 } 328 } 329 330 private static final Descriptor 331 nullD = null, 332 emptyD = ImmutableDescriptor.EMPTY_DESCRIPTOR; 333 334 /* Each element of this array contains five Objects: 335 - OpenType; 336 - defaultValue; 337 - minValue; 338 - maxValue; 339 - legalValues. The objects are used to construct tests cases 340 where all possible constructors that make sense for that 341 combination of values are invoked, and all are checked to ensure 342 that they throw the right exception. */ 343 private static final Object[][] tests = { 344 345 // Values must be of appropriate type 346 347 {oint, "oops", null, null, null}, 348 {oint, Long.MAX_VALUE, null, null, null}, 349 {oint, null, "oops", null, null}, 350 {oint, "oops", 3, null, null}, 351 {oint, 3, "oops", null, null}, 352 {oint, null, null, "oops", null}, 353 {oint, null, 3, "oops", null}, 354 {oint, null, 3, false, null}, 355 {oint, null, null, null, new String[] {"x"}}, 356 {oint, null, null, null, new Object[] {"x"}}, 357 {oint, null, null, null, new Object[] {3, "x"}}, 358 359 // If defaultValue is present then it must satisfy the constraints 360 // defined by legalValues, minValue, or maxValue when any of 361 // these is also present 362 363 {oint, 3, 4, null, null}, 364 {oint, 3, null, 2, null}, 365 {oint, 3, null, null, new Integer[] {2, 4}}, 366 367 // If minValue and maxValue are both present then minValue must 368 // not be greater than maxValue 369 370 {ostring, null, "z", "a", null}, 371 {oint, null, 3, 2, null}, 372 373 // We don't support default values or legal sets for arrays (yet) 374 375 {ostringarray, new String[] {"x"}, null, null, null}, 376 {ostringarray, null, null, null, new String[][]{new String[] {"x"}}}, 377 }; 378 379 /* The tests here can only be expressed via Descriptors because an 380 attempt to invoke one of the non-Descriptor constructors with 381 the implied parameters would not compile (or would fail at the 382 reflection stage when reflection is being used). 383 384 Each element of this array contains two subarrays. The first 385 is an array of OpenTypes that must contain exactly one element. 386 The second is an array of alternating field names and field 387 values that will be used to construct a Descriptor that is supposed 388 to fail when given to an OpenMBean*Info constructor with the given 389 OpenType. */ 390 private static final Object[][][] descriptorTests = { 391 392 // Values must be of appropriate type 393 394 {{oint}, 395 {"minValue", 25L}}, 396 397 {{oint}, 398 {"minValue", new Object()}}, // not even Comparable 399 {{oint}, 400 {"maxValue", new Object()}}, // not even Comparable 401 {{oint}, 402 {"defaultValue", 3, 403 "minValue", new Object()}}, 404 {{oint}, 405 {"defaultValue", 3, 406 "maxValue", new Object()}}, 407 408 {{oint}, 409 {"legalValues", new int[] {3}}}, // should be new Integer[] to work 410 {{oint}, 411 {"legalValues", 3}}, 412 413 // If legalValues is present then neither minValue nor maxValue 414 // must be present 415 416 {{oint}, 417 {"minValue", 3, "legalValues", new Integer[] {3, 4}}}, 418 {{oint}, 419 {"maxValue", 3, "legalValues", new Integer[] {2, 3}}}, 420 {{oint}, 421 {"defaultValue", 3, "minValue", 3, "legalValues", new Integer[] {3}}}, 422 423 // We don't support min or max arrays (what would they mean?) 424 425 {{ostringarray}, 426 {"minValue", new String[] {"x"}}}, 427 {{ostringarray}, 428 {"maxValue", new String[] {"x"}}}, 429 430 }; 431 }