1 /* 2 * Copyright (c) 2015, 2016, 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 import java.io.Serializable; 25 import java.lang.invoke.*; 26 import java.util.concurrent.Callable; 27 28 /** 29 * @test 30 * @summary Test input invariants for StringConcatFactory 31 * 32 * @compile StringConcatFactoryInvariants.java 33 * 34 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB StringConcatFactoryInvariants 35 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED StringConcatFactoryInvariants 36 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED StringConcatFactoryInvariants 37 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT StringConcatFactoryInvariants 38 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT StringConcatFactoryInvariants 39 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT StringConcatFactoryInvariants 40 * 41 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 42 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 43 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 44 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 45 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 46 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants 47 * 48 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 49 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 50 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 51 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 52 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 53 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 54 * 55 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 56 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 57 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 58 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 59 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 60 * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants 61 * 62 */ 63 public class StringConcatFactoryInvariants { 64 65 private static final char TAG_ARG = '\u0001'; 66 private static final char TAG_CONST = '\u0002'; 67 68 public static void main(String[] args) throws Throwable { 69 MethodHandles.Lookup lookup = MethodHandles.lookup(); 70 String methodName = "foo"; 71 MethodType mt = MethodType.methodType(String.class, String.class, int.class); 72 String recipe = "" + TAG_ARG + TAG_ARG + TAG_CONST; 73 Object[] constants = new String[] { "bar" }; 74 Object[] intConstants = new Integer[] { 1 }; 75 Object[] shortConstants = new Short[] { 1 }; 76 Object[] longConstants = new Long[] { 1L }; 77 Object[] booleanConstants = new Boolean[] { true }; 78 Object[] charConstants = new Character[] { 'a' }; 79 Object[] byteConstants = new Byte[] { 1 }; 80 81 final int LIMIT = 200; 82 83 // Simple factory: check for dynamic arguments overflow 84 Class<?>[] underThreshold = new Class<?>[LIMIT - 1]; 85 Class<?>[] threshold = new Class<?>[LIMIT]; 86 Class<?>[] overThreshold = new Class<?>[LIMIT + 1]; 87 88 StringBuilder sbUnderThreshold = new StringBuilder(); 89 sbUnderThreshold.append(TAG_CONST); 90 for (int c = 0; c < LIMIT - 1; c++) { 91 underThreshold[c] = int.class; 92 threshold[c] = int.class; 93 overThreshold[c] = int.class; 94 sbUnderThreshold.append(TAG_ARG); 95 } 96 threshold[LIMIT - 1] = int.class; 97 overThreshold[LIMIT - 1] = int.class; 98 overThreshold[LIMIT] = int.class; 99 100 String recipeEmpty = ""; 101 String recipeUnderThreshold = sbUnderThreshold.toString(); 102 String recipeThreshold = sbUnderThreshold.append(TAG_ARG).toString(); 103 String recipeOverThreshold = sbUnderThreshold.append(TAG_ARG).toString(); 104 105 MethodType mtEmpty = MethodType.methodType(String.class); 106 MethodType mtUnderThreshold = MethodType.methodType(String.class, underThreshold); 107 MethodType mtThreshold = MethodType.methodType(String.class, threshold); 108 MethodType mtOverThreshold = MethodType.methodType(String.class, overThreshold); 109 110 111 // Check the basic functionality is working 112 { 113 CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, mt); 114 test("foo42", (String) cs.getTarget().invokeExact("foo", 42)); 115 } 116 117 { 118 CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, constants); 119 test("foo42bar", (String) cs.getTarget().invokeExact("foo", 42)); 120 } 121 122 { 123 CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, intConstants); 124 test("foo421", (String) cs.getTarget().invokeExact("foo", 42)); 125 } 126 127 { 128 CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, booleanConstants); 129 test("foo42true", (String) cs.getTarget().invokeExact("foo", 42)); 130 } 131 132 // Simple factory, check for nulls: 133 failNPE("Lookup is null", 134 () -> StringConcatFactory.makeConcat(null, methodName, mt)); 135 136 failNPE("Method name is null", 137 () -> StringConcatFactory.makeConcat(lookup, null, mt)); 138 139 failNPE("MethodType is null", 140 () -> StringConcatFactory.makeConcat(lookup, methodName, null)); 141 142 // Advanced factory, check for nulls: 143 failNPE("Lookup is null", 144 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, constants)); 145 146 failNPE("Lookup is null", 147 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, shortConstants)); 148 149 failNPE("Lookup is null", 150 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, intConstants)); 151 152 failNPE("Lookup is null", 153 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, longConstants)); 154 155 failNPE("Lookup is null", 156 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, booleanConstants)); 157 158 failNPE("Lookup is null", 159 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, byteConstants)); 160 161 failNPE("Lookup is null", 162 () -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, charConstants)); 163 164 failNPE("Method name is null", 165 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, constants)); 166 167 failNPE("Method name is null", 168 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, shortConstants)); 169 170 failNPE("Method name is null", 171 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, intConstants)); 172 173 failNPE("Method name is null", 174 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, longConstants)); 175 176 failNPE("Method name is null", 177 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, booleanConstants)); 178 179 failNPE("Method name is null", 180 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, byteConstants)); 181 182 failNPE("Method name is null", 183 () -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, charConstants)); 184 185 failNPE("MethodType is null", 186 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, constants)); 187 188 failNPE("MethodType is null", 189 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, shortConstants)); 190 191 failNPE("MethodType is null", 192 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, intConstants)); 193 194 failNPE("MethodType is null", 195 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, longConstants)); 196 197 failNPE("MethodType is null", 198 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, booleanConstants)); 199 200 failNPE("MethodType is null", 201 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, byteConstants)); 202 203 failNPE("MethodType is null", 204 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, charConstants)); 205 206 failNPE("Recipe is null", 207 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, constants)); 208 209 failNPE("Recipe is null", 210 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, shortConstants)); 211 212 failNPE("Recipe is null", 213 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, intConstants)); 214 215 failNPE("Recipe is null", 216 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, longConstants)); 217 218 failNPE("Recipe is null", 219 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, booleanConstants)); 220 221 failNPE("Recipe is null", 222 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, byteConstants)); 223 224 failNPE("Recipe is null", 225 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, charConstants)); 226 227 failNPE("Constants vararg is null", 228 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, (Object[])null)); 229 230 // Simple factory, check for return type 231 fail("Return type: void", 232 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(void.class, String.class, int.class))); 233 234 fail("Return type: int", 235 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(int.class, String.class, int.class))); 236 237 fail("Return type: StringBuilder", 238 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class))); 239 240 ok("Return type: Object", 241 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class))); 242 243 ok("Return type: CharSequence", 244 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class))); 245 246 ok("Return type: Serializable", 247 () -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class))); 248 249 // Advanced factory, check for return types 250 fail("Return type: void", 251 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, constants)); 252 253 fail("Return type: void", 254 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, intConstants)); 255 256 fail("Return type: void", 257 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, shortConstants)); 258 259 fail("Return type: void", 260 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, longConstants)); 261 262 fail("Return type: void", 263 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, booleanConstants)); 264 265 fail("Return type: void", 266 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, byteConstants)); 267 268 fail("Return type: void", 269 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, charConstants)); 270 271 fail("Return type: int", 272 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(int.class, String.class, int.class), recipe, constants)); 273 274 fail("Return type: StringBuilder", 275 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class), recipe, constants)); 276 277 ok("Return type: Object", 278 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, constants)); 279 280 ok("Return type: Object", 281 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, intConstants)); 282 283 ok("Return type: Object", 284 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, shortConstants)); 285 286 ok("Return type: Object", 287 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, longConstants)); 288 289 ok("Return type: Object", 290 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, booleanConstants)); 291 292 ok("Return type: Object", 293 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, byteConstants)); 294 295 ok("Return type: Object", 296 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, charConstants)); 297 298 ok("Return type: CharSequence", 299 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, constants)); 300 301 ok("Return type: CharSequence", 302 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, intConstants)); 303 304 ok("Return type: CharSequence", 305 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, shortConstants)); 306 307 ok("Return type: CharSequence", 308 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, longConstants)); 309 310 ok("Return type: CharSequence", 311 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, booleanConstants)); 312 313 ok("Return type: CharSequence", 314 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, byteConstants)); 315 316 ok("Return type: CharSequence", 317 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, charConstants)); 318 319 ok("Return type: Serializable", 320 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, constants)); 321 322 ok("Return type: Serializable", 323 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, intConstants)); 324 325 ok("Return type: Serializable", 326 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, shortConstants)); 327 328 ok("Return type: Serializable", 329 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, longConstants)); 330 331 ok("Return type: Serializable", 332 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, booleanConstants)); 333 334 ok("Return type: Serializable", 335 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, byteConstants)); 336 337 ok("Return type: Serializable", 338 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, charConstants)); 339 340 // Simple factory: check for dynamic arguments overflow 341 ok("Dynamic arguments is under limit", 342 () -> StringConcatFactory.makeConcat(lookup, methodName, mtUnderThreshold)); 343 344 ok("Dynamic arguments is at the limit", 345 () -> StringConcatFactory.makeConcat(lookup, methodName, mtThreshold)); 346 347 fail("Dynamic arguments is over the limit", 348 () -> StringConcatFactory.makeConcat(lookup, methodName, mtOverThreshold)); 349 350 // Advanced factory: check for dynamic arguments overflow 351 ok("Dynamic arguments is under limit", 352 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtUnderThreshold, recipeUnderThreshold, constants)); 353 354 ok("Dynamic arguments is at the limit", 355 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants)); 356 357 fail("Dynamic arguments is over the limit", 358 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtOverThreshold, recipeOverThreshold, constants)); 359 360 // Advanced factory: check for mismatched recipe and Constants 361 ok("Static arguments and recipe match", 362 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar")); 363 364 fail("Static arguments and recipe mismatch", 365 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", "baz")); 366 367 // Advanced factory: check for mismatched recipe and dynamic arguments 368 fail("Dynamic arguments and recipe mismatch", 369 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeUnderThreshold, constants)); 370 371 ok("Dynamic arguments and recipe match", 372 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants)); 373 374 fail("Dynamic arguments and recipe mismatch", 375 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeOverThreshold, constants)); 376 377 // Test passing array as constant 378 { 379 Object[] arg = {"boo", "bar"}; 380 381 CallSite cs1 = StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST + TAG_CONST, arg); 382 test("42boobar", (String) cs1.getTarget().invokeExact(42)); 383 } 384 385 // Test passing null constant 386 ok("Can pass regular constants", 387 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, "foo")); 388 389 failNPE("Cannot pass null constants", 390 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, new Object[]{null})); 391 392 // Simple factory: test empty arguments 393 ok("Ok to pass empty arguments", 394 () -> StringConcatFactory.makeConcat(lookup, methodName, mtEmpty)); 395 396 // Advanced factory: test empty arguments 397 ok("Ok to pass empty arguments", 398 () -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtEmpty, recipeEmpty)); 399 400 // Simple factory: public Lookup is rejected 401 fail("Passing public Lookup", 402 () -> StringConcatFactory.makeConcat(MethodHandles.publicLookup(), methodName, mtEmpty)); 403 404 // Advanced factory: public Lookup is rejected 405 fail("Passing public Lookup", 406 () -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty)); 407 } 408 409 public static void ok(String msg, Callable runnable) { 410 try { 411 runnable.call(); 412 } catch (Throwable e) { 413 e.printStackTrace(); 414 throw new IllegalStateException(msg + ", should have passed", e); 415 } 416 } 417 418 public static void fail(String msg, Callable runnable) { 419 boolean expected = false; 420 try { 421 runnable.call(); 422 } catch (StringConcatException e) { 423 expected = true; 424 } catch (Throwable e) { 425 e.printStackTrace(); 426 } 427 428 if (!expected) { 429 throw new IllegalStateException(msg + ", should have failed with StringConcatException"); 430 } 431 } 432 433 434 public static void failNPE(String msg, Callable runnable) { 435 boolean expected = false; 436 try { 437 runnable.call(); 438 } catch (NullPointerException e) { 439 expected = true; 440 } catch (Throwable e) { 441 e.printStackTrace(); 442 } 443 444 if (!expected) { 445 throw new IllegalStateException(msg + ", should have failed with NullPointerException"); 446 } 447 } 448 449 public static void test(String expected, String actual) { 450 // Fingers crossed: String concat should work. 451 if (!expected.equals(actual)) { 452 StringBuilder sb = new StringBuilder(); 453 sb.append("Expected = "); 454 sb.append(expected); 455 sb.append(", actual = "); 456 sb.append(actual); 457 throw new IllegalStateException(sb.toString()); 458 } 459 } 460 461 }