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