| // Copyright (c) 2018, 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.debug; |
| |
| import com.android.tools.r8.ByteDataView; |
| import com.android.tools.r8.ClassFileConsumer; |
| import com.android.tools.r8.CompilationMode; |
| import com.android.tools.r8.OutputMode; |
| import com.android.tools.r8.R8Command; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState; |
| import com.android.tools.r8.origin.Origin; |
| import com.android.tools.r8.utils.DescriptorUtils; |
| import com.google.common.collect.ImmutableList; |
| import java.nio.file.Path; |
| import java.util.stream.Stream; |
| import org.junit.Assume; |
| import org.junit.Test; |
| |
| public class NopDebugTestRunner extends DebugTestBase { |
| |
| private final Class<?> CLAZZ = NopTest.class; |
| |
| @Test |
| public void testNop() throws Exception { |
| // R8 will dead-code eliminate "args = args" in NopTest. |
| // In debug mode the programmer should still be able to break on dead code, |
| // so R8 inserts a NOP in the output. Test that CfNop.buildIR() works. |
| runTwiceTest(writeInput(CLAZZ), CLAZZ.getName()); |
| } |
| |
| private Path writeInput(Class<?> clazz) throws Exception { |
| Path inputJar = temp.getRoot().toPath().resolve("input.jar"); |
| ClassFileConsumer inputConsumer = new ClassFileConsumer.ArchiveConsumer(inputJar); |
| String descriptor = DescriptorUtils.javaTypeToDescriptor(clazz.getName()); |
| inputConsumer.accept(ByteDataView.of(ToolHelper.getClassAsBytes(clazz)), descriptor, null); |
| inputConsumer.finished(null); |
| return inputJar; |
| } |
| |
| private void runTwiceTest(Path inputJar, String mainClass) throws Exception { |
| Path output1 = runR8(inputJar, "output1.jar"); |
| Path output2 = runR8(output1, "output2.jar"); |
| stepOutput(mainClass, inputJar, output1, output2); |
| } |
| |
| private Path runR8(Path inputJar, String outputName) throws Exception { |
| Path outputJar = temp.getRoot().toPath().resolve(outputName); |
| ToolHelper.runR8( |
| R8Command.builder() |
| .addLibraryFiles(ToolHelper.getJava8RuntimeJar()) |
| .setMode(CompilationMode.DEBUG) |
| .setDisableTreeShaking(true) |
| .setDisableMinification(true) |
| .addProguardConfiguration( |
| ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), Origin.unknown()) |
| .addProgramFiles(inputJar) |
| .setOutput(outputJar, OutputMode.ClassFile) |
| .build()); |
| return outputJar; |
| } |
| |
| private void stepOutput(String mainClass, Path inputJar, Path output1, Path output2) |
| throws Exception { |
| Assume.assumeTrue( |
| "Skipping test " |
| + testName.getMethodName() |
| + " because debug tests are not yet supported on Windows", |
| !ToolHelper.isWindows()); |
| new DebugStreamComparator() |
| .add("Input", streamDebugTest(mainClass, new CfDebugTestConfig(inputJar))) |
| .add("R8/CF", streamDebugTest(mainClass, new CfDebugTestConfig(output1))) |
| .add("R8/CF^2", streamDebugTest(mainClass, new CfDebugTestConfig(output2))) |
| .compare(); |
| } |
| |
| private Stream<DebuggeeState> streamDebugTest(String mainClass, DebugTestConfig config) |
| throws Exception { |
| return streamDebugTest(config, mainClass, ANDROID_FILTER); |
| } |
| } |