blob: b84b5d46e48533b31e78008c1a17dfebe752cb07 [file] [log] [blame]
// 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);
}
}