1 /* 2 * Copyright (c) 2014, 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 import jdk.test.lib.Asserts; 26 import jdk.test.lib.OutputAnalyzer; 27 import jdk.test.lib.ProcessTools; 28 import jdk.test.lib.Utils; 29 import java.io.IOException; 30 import java.nio.file.Files; 31 import java.nio.file.Paths; 32 import java.util.Collections; 33 import java.util.LinkedList; 34 import java.util.List; 35 import java.util.Random; 36 37 /** 38 * Test runner that invokes all methods implemented by particular Expr 39 * with random arguments in two different JVM processes and compares output. 40 * JVMs being started in different modes - one in int and other in comp 41 * with C2 and disabled tiered compilation. 42 */ 43 public class BMITestRunner { 44 45 enum VMMode { 46 COMP, INT; 47 }; 48 49 public static int DEFAULT_ITERATIONS_COUNT = 4000; 50 51 /** 52 * Execute all methods implemented by <b>expr</b> in int and comp modes 53 * and compare output. 54 * Test pass only of output obtained with different VM modes is equal. 55 * To control behaviour of test following options could be passed: 56 * <ul> 57 * <li>-iterations=<N> each operation implemented by 58 * <b>expr</b> will be executed <i>N</i> times. Default value 59 * is 4000.</li> 60 * <li>-seed=<SEED> arguments for <b>expr</b>'s methods 61 * obtained via RNG initiated with seed <i>SEED</i>. By default 62 * some random seed will be used.</li> 63 * </ul> 64 * 65 * @param expr operation that should be tested 66 * @param testOpts options to control test behaviour 67 * @param additionalVMOpts additional options for VM 68 * 69 * @throws Throwable if test failed. 70 */ 71 public static void runTests(Class<? extends Expr> expr, 72 String testOpts[], 73 String... additionalVMOpts) 74 throws Throwable { 75 76 int seed = Utils.getRandomInstance().nextInt(); 77 int iterations = DEFAULT_ITERATIONS_COUNT; 78 79 for (String testOption : testOpts) { 80 if (testOption.startsWith("-iterations=")) { 81 iterations = Integer.valueOf(testOption. 82 replace("-iterations=", "")); 83 } else if (testOption.startsWith("-seed=")) { 84 seed = Integer.valueOf(testOption.replace("-seed=", "")); 85 } 86 } 87 88 OutputAnalyzer intOutput = runTest(expr, VMMode.INT, 89 additionalVMOpts, 90 seed, iterations); 91 OutputAnalyzer compOutput = runTest(expr, VMMode.COMP, 92 additionalVMOpts, 93 seed, iterations); 94 95 dumpOutput(intOutput, "int"); 96 dumpOutput(compOutput, "comp"); 97 98 Asserts.assertStringsEqual(intOutput.getStdout(), 99 compOutput.getStdout(), 100 "Results obtained in -Xint and " + 101 "-Xcomp should be the same."); 102 } 103 104 /** 105 * Execute tests on methods implemented by <b>expr</b> in new VM 106 * started in <b>testVMMode</b> mode. 107 * 108 * @param expr operation that should be tested 109 * @param testVMMode VM mode for test 110 * @param additionalVMOpts additional options for VM 111 * @param seed for RNG used it tests 112 * @param iterations that will be used to invoke <b>expr</b>'s methods. 113 * 114 * @return OutputAnalyzer for executed test. 115 * @throws Throwable when something goes wrong. 116 */ 117 public static OutputAnalyzer runTest(Class<? extends Expr> expr, 118 VMMode testVMMode, 119 String additionalVMOpts[], 120 int seed, int iterations) 121 throws Throwable { 122 123 List<String> vmOpts = new LinkedList<String>(); 124 125 Collections.addAll(vmOpts, additionalVMOpts); 126 127 //setup mode-specific options 128 switch (testVMMode) { 129 case INT: 130 Collections.addAll(vmOpts, new String[] { "-Xint" }); 131 break; 132 case COMP: 133 Collections.addAll(vmOpts, new String[] { 134 "-Xcomp", 135 "-XX:-TieredCompilation", 136 String.format("-XX:CompileCommand=compileonly,%s::*", 137 expr.getName()) 138 }); 139 break; 140 } 141 142 Collections.addAll(vmOpts, new String[] { 143 "-XX:+DisplayVMOutputToStderr", 144 "-D" + Utils.SEED_PROPERTY_NAME + "=" + seed, 145 Executor.class.getName(), 146 expr.getName(), 147 new Integer(iterations).toString() 148 }); 149 150 OutputAnalyzer outputAnalyzer = ProcessTools. 151 executeTestJvm(vmOpts.toArray(new String[vmOpts.size()])); 152 153 outputAnalyzer.shouldHaveExitValue(0); 154 155 return outputAnalyzer; 156 } 157 158 /** 159 * Dump stdout and stderr of test process to <i>prefix</i>.test.out 160 * and <i>prefix</i>.test.err respectively. 161 * 162 * @param outputAnalyzer OutputAnalyzer whom output should be dumped 163 * @param prefix Prefix that will be used in file names. 164 * @throws IOException if unable to dump output to file. 165 */ 166 protected static void dumpOutput(OutputAnalyzer outputAnalyzer, 167 String prefix) 168 throws IOException { 169 Files.write(Paths.get(prefix + ".test.out"), 170 outputAnalyzer.getStdout().getBytes()); 171 172 Files.write(Paths.get(prefix + ".test.err"), 173 outputAnalyzer.getStderr().getBytes()); 174 } 175 176 177 /** 178 * Executor that invoke all methods implemented by particular 179 * Expr instance. 180 */ 181 public static class Executor { 182 183 /** 184 * Usage: BMITestRunner$Executor <ExprClassName> <iterations> 185 */ 186 public static void main(String args[]) throws Exception { 187 @SuppressWarnings("unchecked") 188 Class<? extends Expr> exprClass = 189 (Class<? extends Expr>)Class.forName(args[0]); 190 Expr expr = exprClass.getConstructor().newInstance(); 191 int iterations = Integer.valueOf(args[1]); 192 runTests(expr, iterations, Utils.getRandomInstance()); 193 } 194 195 196 public static int[] getIntBitShifts() { 197 //SIZE+1 shift is for zero. 198 int data[] = new int[Integer.SIZE+1]; 199 for (int s = 0; s < data.length; s++) { 200 data[s] = 1<<s; 201 } 202 return data; 203 } 204 205 public static long[] getLongBitShifts() { 206 //SIZE+1 shift is for zero. 207 long data[] = new long[Long.SIZE+1]; 208 for (int s = 0; s < data.length; s++) { 209 data[s] = 1L<<s; 210 } 211 return data; 212 } 213 214 public static void log(String format, Object... args) { 215 System.out.println(String.format(format, args)); 216 } 217 218 public static void runTests(Expr expr, int iterations, Random rng) { 219 runUnaryIntRegTest(expr, iterations, rng); 220 runUnaryIntMemTest(expr, iterations, rng); 221 runUnaryLongRegTest(expr, iterations, rng); 222 runUnaryLongMemTest(expr, iterations, rng); 223 runBinaryRegRegIntTest(expr, iterations, rng); 224 runBinaryRegMemIntTest(expr, iterations, rng); 225 runBinaryMemRegIntTest(expr, iterations, rng); 226 runBinaryMemMemIntTest(expr, iterations, rng); 227 runBinaryRegRegLongTest(expr, iterations, rng); 228 runBinaryRegMemLongTest(expr, iterations, rng); 229 runBinaryMemRegLongTest(expr, iterations, rng); 230 runBinaryMemMemLongTest(expr, iterations, rng); 231 } 232 233 public static void runUnaryIntRegTest(Expr expr, int iterations, 234 Random rng) { 235 if (!(expr.isUnaryArgumentSupported() 236 && expr.isIntExprSupported())) { 237 return; 238 } 239 240 for (int value : getIntBitShifts()) { 241 log("UnaryIntReg(0X%x) -> 0X%x", 242 value, expr.intExpr(value)); 243 } 244 245 for (int i = 0; i < iterations; i++) { 246 int value = rng.nextInt(); 247 log("UnaryIntReg(0X%x) -> 0X%x", 248 value, expr.intExpr(value)); 249 } 250 } 251 252 public static void runUnaryIntMemTest(Expr expr, int iterations, 253 Random rng) { 254 if (!(expr.isUnaryArgumentSupported() 255 && expr.isIntExprSupported() 256 && expr.isMemExprSupported())) { 257 return; 258 } 259 260 for (int value : getIntBitShifts()) { 261 log("UnaryIntMem(0X%x) -> 0X%x", 262 value, expr.intExpr(new Expr.MemI(value))); 263 } 264 265 for (int i = 0; i < iterations; i++) { 266 int value = rng.nextInt(); 267 log("UnaryIntMem(0X%x) -> 0X%x", 268 value, expr.intExpr(new Expr.MemI(value))); 269 } 270 } 271 272 public static void runUnaryLongRegTest(Expr expr, int iterations, 273 Random rng) { 274 if (!(expr.isUnaryArgumentSupported() 275 && expr.isLongExprSupported())) { 276 return; 277 } 278 279 for (long value : getLongBitShifts()) { 280 log("UnaryLongReg(0X%x) -> 0X%x", 281 value, expr.longExpr(value)); 282 } 283 284 for (int i = 0; i < iterations; i++) { 285 long value = rng.nextLong(); 286 log("UnaryLongReg(0X%x) -> 0X%x", 287 value, expr.longExpr(value)); 288 } 289 } 290 291 public static void runUnaryLongMemTest(Expr expr, int iterations, 292 Random rng) { 293 if (!(expr.isUnaryArgumentSupported() 294 && expr.isLongExprSupported() 295 && expr.isMemExprSupported())) { 296 return; 297 } 298 299 for (long value : getLongBitShifts()) { 300 log("UnaryLongMem(0X%x) -> 0X%x", 301 value, expr.longExpr(new Expr.MemL(value))); 302 } 303 304 for (int i = 0; i < iterations; i++) { 305 long value = rng.nextLong(); 306 log("UnaryLongMem(0X%x) -> 0X%x", 307 value, expr.longExpr(new Expr.MemL(value))); 308 } 309 } 310 311 public static void runBinaryRegRegIntTest(Expr expr, int iterations, 312 Random rng) { 313 if (!(expr.isIntExprSupported() 314 && expr.isBinaryArgumentSupported())) { 315 return; 316 } 317 318 for (int i = 0; i < iterations; i++) { 319 int aValue = rng.nextInt(); 320 int bValue = rng.nextInt(); 321 log("BinaryIntRegReg(0X%x, 0X%x) -> 0X%x", 322 aValue, bValue, expr.intExpr(aValue, bValue)); 323 } 324 } 325 326 public static void runBinaryRegMemIntTest(Expr expr, int iterations, 327 Random rng) { 328 if (!(expr.isIntExprSupported() 329 && expr.isBinaryArgumentSupported() 330 && expr.isMemExprSupported())) { 331 return; 332 } 333 334 for (int i = 0; i < iterations; i++) { 335 int aValue = rng.nextInt(); 336 int bValue = rng.nextInt(); 337 log("BinaryIntRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 338 expr.intExpr(aValue, new Expr.MemI(bValue))); 339 } 340 } 341 342 public static void runBinaryMemRegIntTest(Expr expr, int iterations, 343 Random rng) { 344 if (!(expr.isIntExprSupported() 345 && expr.isBinaryArgumentSupported() 346 && expr.isMemExprSupported())) { 347 return; 348 } 349 350 for (int i = 0; i < iterations; i++) { 351 int aValue = rng.nextInt(); 352 int bValue = rng.nextInt(); 353 log("BinaryIntMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 354 expr.intExpr(new Expr.MemI(aValue), bValue)); 355 } 356 } 357 358 public static void runBinaryMemMemIntTest(Expr expr, int iterations, 359 Random rng) { 360 if (!(expr.isIntExprSupported() 361 && expr.isBinaryArgumentSupported() 362 && expr.isMemExprSupported())) { 363 return; 364 } 365 366 for (int i = 0; i < iterations; i++) { 367 int aValue = rng.nextInt(); 368 int bValue = rng.nextInt(); 369 log("BinaryIntMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 370 expr.intExpr(new Expr.MemI(aValue), 371 new Expr.MemI(bValue))); 372 } 373 } 374 375 public static void runBinaryRegRegLongTest(Expr expr, 376 int iterations, 377 Random rng) { 378 if (!(expr.isLongExprSupported() 379 && expr.isBinaryArgumentSupported())) { 380 return; 381 } 382 383 for (int i = 0; i < iterations; i++) { 384 long aValue = rng.nextLong(); 385 long bValue = rng.nextLong(); 386 log("BinaryLongRegReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 387 expr.longExpr(aValue, bValue)); 388 } 389 } 390 391 public static void runBinaryRegMemLongTest(Expr expr, 392 int iterations, 393 Random rng) { 394 if (!(expr.isLongExprSupported() 395 && expr.isBinaryArgumentSupported() 396 && expr.isMemExprSupported())) { 397 return; 398 } 399 400 for (int i = 0; i < iterations; i++) { 401 long aValue = rng.nextLong(); 402 long bValue = rng.nextLong(); 403 log("BinaryLongRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 404 expr.longExpr(aValue, new Expr.MemL(bValue))); 405 } 406 } 407 408 public static void runBinaryMemRegLongTest(Expr expr, 409 int iterations, 410 Random rng) { 411 if (!(expr.isLongExprSupported() 412 && expr.isBinaryArgumentSupported() 413 && expr.isMemExprSupported())) { 414 return; 415 } 416 417 for (int i = 0; i < iterations; i++) { 418 long aValue = rng.nextLong(); 419 long bValue = rng.nextLong(); 420 log("BinaryLongMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 421 expr.longExpr(new Expr.MemL(aValue), bValue)); 422 } 423 } 424 425 public static void runBinaryMemMemLongTest(Expr expr, 426 int iterations, 427 Random rng) { 428 if (!(expr.isLongExprSupported() 429 && expr.isBinaryArgumentSupported() 430 && expr.isMemExprSupported())) { 431 return; 432 } 433 434 for (int i = 0; i < iterations; i++) { 435 long aValue = rng.nextLong(); 436 long bValue = rng.nextLong(); 437 log("BinaryLongMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 438 expr.longExpr(new Expr.MemL(aValue), 439 new Expr.MemL(bValue))); 440 } 441 } 442 } 443 }