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