1 /* 2 * Copyright (c) 2013, 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 package org.graalvm.compiler.hotspot.test; 24 25 import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; 26 import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.Enumeration; 33 import java.util.List; 34 import java.util.zip.ZipEntry; 35 import java.util.zip.ZipFile; 36 37 import org.graalvm.compiler.core.test.GraalCompilerTest; 38 import org.graalvm.compiler.test.SubprocessUtil; 39 import org.graalvm.compiler.test.SubprocessUtil.Subprocess; 40 import org.junit.Assert; 41 import org.junit.Test; 42 43 /** 44 * Tests support for dumping graphs and other info useful for debugging a compiler crash. 45 */ 46 public class CompilationWrapperTest extends GraalCompilerTest { 47 48 /** 49 * Tests compilation requested by the VM. 50 */ 51 @Test 52 public void testVMCompilation1() throws IOException, InterruptedException { 53 testHelper(Arrays.asList("-XX:+BootstrapJVMCI", 54 "-XX:+UseJVMCICompiler", 55 "-Dgraal.CompilationFailureAction=ExitVM", 56 "-Dgraal.CrashAt=Object.*,String.*", 57 "-version")); 58 } 59 60 /** 61 * Tests that {@code -Dgraal.ExitVMOnException=true} works as an alias for 62 * {@code -Dgraal.CompilationFailureAction=ExitVM}. 63 */ 64 @Test 65 public void testVMCompilation2() throws IOException, InterruptedException { 66 testHelper(Arrays.asList("-XX:+BootstrapJVMCI", 67 "-XX:+UseJVMCICompiler", 68 "-Dgraal.ExitVMOnException=true", 69 "-Dgraal.CrashAt=Object.*,String.*", 70 "-version")); 71 } 72 73 /** 74 * Tests compilation requested by Truffle. 75 */ 76 @Test 77 public void testTruffleCompilation() throws IOException, InterruptedException { 78 testHelper(Arrays.asList( 79 "-Dgraal.CompilationFailureAction=ExitVM", 80 "-Dgraal.CrashAt=root test1"), 81 "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", 82 "test"); 83 } 84 85 private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose"); 86 87 private static void testHelper(List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException { 88 final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile(); 89 List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine()); 90 vmArgs.removeIf(a -> a.startsWith("-Dgraal.")); 91 vmArgs.add("-Dgraal.DumpPath=" + dumpPath); 92 // Force output to a file even if there's a running IGV instance available. 93 vmArgs.add("-Dgraal.PrintGraphFile=true"); 94 vmArgs.addAll(extraVmArgs); 95 96 Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs); 97 if (VERBOSE) { 98 System.out.println(proc); 99 } 100 101 String forcedCrashString = "Forced crash after compiling"; 102 String diagnosticOutputFilePrefix = "Graal diagnostic output saved in "; 103 104 boolean seenForcedCrashString = false; 105 String diagnosticOutputZip = null; 106 107 for (String line : proc.output) { 108 if (line.contains(forcedCrashString)) { 109 seenForcedCrashString = true; 110 } else if (diagnosticOutputZip == null) { 111 int index = line.indexOf(diagnosticOutputFilePrefix); 112 if (index != -1) { 113 diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim(); 114 } 115 } 116 } 117 118 if (!seenForcedCrashString) { 119 Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc)); 120 } 121 if (diagnosticOutputZip == null) { 122 Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc)); 123 } 124 125 String[] dumpPathEntries = dumpPath.list(); 126 127 File zip = new File(diagnosticOutputZip).getAbsoluteFile(); 128 Assert.assertTrue(zip.toString(), zip.exists()); 129 Assert.assertArrayEquals(dumpPathEntries, new String[]{zip.getName()}); 130 try { 131 int bgv = 0; 132 int cfg = 0; 133 ZipFile dd = new ZipFile(diagnosticOutputZip); 134 List<String> entries = new ArrayList<>(); 135 for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) { 136 ZipEntry ze = e.nextElement(); 137 String name = ze.getName(); 138 entries.add(name); 139 if (name.endsWith(".bgv")) { 140 bgv++; 141 } else if (name.endsWith(".cfg")) { 142 cfg++; 143 } 144 } 145 if (bgv == 0) { 146 Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); 147 } 148 if (cfg == 0) { 149 Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries)); 150 } 151 } finally { 152 zip.delete(); 153 dumpPath.delete(); 154 } 155 } 156 }