blob: 258d8695bf5379c4af0441c7229ed0bd368abaf9 [file] [log] [blame]
// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.retrace;
import static com.android.tools.r8.ToolHelper.LINE_SEPARATOR;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hamcrest.Matcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class RetraceCommandLineTests {
private static final boolean testExternal = true;
@Rule public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testPrintIdentityStackTraceFile() throws IOException {
runTest("", nonMappableStackTrace, false, nonMappableStackTrace);
}
@Test
public void testPrintIdentityStackTraceInput() throws IOException {
runTest("", nonMappableStackTrace, true, nonMappableStackTrace);
}
@Test
public void testNoMappingFileSpecified() throws IOException {
runAbortTest(containsString("Mapping file not specified"));
}
@Test
public void testMissingMappingFile() throws IOException {
runAbortTest(containsString("Could not find mapping file 'foo.txt'"), "foo.txt");
}
@Test
public void testVerbose() throws IOException {
runAbortTest(containsString("Currently no support for --verbose"), "--verbose");
}
@Test
public void testEmpty() throws IOException {
runTest("", "", false, "");
}
@Test
public void testHelp() throws IOException {
ProcessResult processResult = runRetraceCommandLine(null, "--help");
assertEquals(0, processResult.exitCode);
assertEquals(Retrace.USAGE_MESSAGE, processResult.stdout);
}
private final String nonMappableStackTrace =
StringUtils.lines(
"com.android.r8.R8Exception: Problem when compiling program",
" at r8.a.a(App:42)",
" at r8.a.b(App:10)",
" at r8.a.c(App:266)",
" at r8.main(App:800)",
"Caused by: com.android.r8.R8InnerException: You have to write the program first",
" at r8.retrace(App:184)",
" ... 7 more");
private void runTest(String mapping, String stackTrace, boolean stacktraceStdIn, String expected)
throws IOException {
ProcessResult result = runRetrace(mapping, stackTrace, stacktraceStdIn);
assertEquals(0, result.exitCode);
assertEquals(expected, result.stdout);
}
private void runAbortTest(Matcher<String> errorMatch, String... args) throws IOException {
ProcessResult result = runRetraceCommandLine(null, args);
assertEquals(1, result.exitCode);
assertThat(result.stderr, errorMatch);
}
private ProcessResult runRetrace(String mapping, String stackTrace, boolean stacktraceStdIn)
throws IOException {
Path mappingFile = folder.newFile("mapping.txt").toPath();
Files.write(mappingFile, mapping.getBytes());
File stackTraceFile = folder.newFile("stacktrace.txt");
Files.write(stackTraceFile.toPath(), stackTrace.getBytes());
if (stacktraceStdIn) {
return runRetraceCommandLine(stackTraceFile, mappingFile.toString());
} else {
return runRetraceCommandLine(
null, mappingFile.toString(), stackTraceFile.toPath().toString());
}
}
private ProcessResult runRetraceCommandLine(File stdInput, String... args) throws IOException {
if (testExternal) {
List<String> command = new ArrayList<>();
command.add(ToolHelper.getSystemJavaExecutable());
command.add("-ea");
command.add("-cp");
command.add(ToolHelper.R8_JAR.toString());
command.add("com.android.tools.r8.retrace.Retrace");
command.addAll(Arrays.asList(args));
ProcessBuilder builder = new ProcessBuilder(command);
if (stdInput != null) {
builder.redirectInput(stdInput);
}
return ToolHelper.runProcess(builder);
} else {
InputStream originalIn = System.in;
PrintStream originalOut = System.out;
PrintStream originalErr = System.err;
if (stdInput != null) {
System.setIn(new FileInputStream(stdInput));
}
ByteArrayOutputStream outputByteStream = new ByteArrayOutputStream();
System.setOut(new PrintStream(outputByteStream));
ByteArrayOutputStream errorByteStream = new ByteArrayOutputStream();
System.setErr(new PrintStream(errorByteStream));
int exitCode = 0;
try {
Retrace.run(args);
} catch (Throwable t) {
exitCode = 1;
}
if (originalIn != null) {
System.setIn(originalIn);
}
System.setOut(originalOut);
System.setErr(originalErr);
return new ProcessResult(
exitCode,
outputByteStream.toString(),
errorByteStream.toString(),
StringUtils.join(LINE_SEPARATOR, args));
}
}
}