| // 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 static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.ByteDataView; |
| import com.android.tools.r8.ClassFileConsumer; |
| import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer; |
| import com.android.tools.r8.CompilationMode; |
| import com.android.tools.r8.DexIndexedConsumer; |
| import com.android.tools.r8.ProgramConsumer; |
| import com.android.tools.r8.R8Command; |
| import com.android.tools.r8.R8Command.Builder; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.ToolHelper.DexVm; |
| import com.android.tools.r8.ToolHelper.DexVm.Version; |
| import com.android.tools.r8.ToolHelper.ProcessResult; |
| import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState; |
| import com.android.tools.r8.origin.Origin; |
| 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 IincDebugTestRunner extends DebugTestBase { |
| @Test |
| public void compareDifferentRegister() throws Exception { |
| compareOutput(IincDebugTestDump.dump(1, 2, false)); |
| } |
| |
| @Test |
| public void compareLoadStoreSameRegister() throws Exception { |
| compareOutput(IincDebugTestDump.dump(1, 1, false)); |
| } |
| |
| @Test |
| public void compareIinc() throws Exception { |
| compareOutput(IincDebugTestDump.dump(1, 1, true)); |
| } |
| |
| @Test |
| public void stepDifferentRegister() throws Exception { |
| stepOutput(IincDebugTestDump.dump(1, 2, false)); |
| } |
| |
| @Test |
| public void stepLoadStoreSameRegister() throws Exception { |
| stepOutput(IincDebugTestDump.dump(1, 1, false)); |
| } |
| |
| @Test |
| public void stepIinc() throws Exception { |
| stepOutput(IincDebugTestDump.dump(1, 1, true)); |
| } |
| |
| private void compareOutput(byte[] clazz) throws Exception { |
| Path inputJar = buildInput(clazz); |
| ProcessResult runInput = ToolHelper.runJava(inputJar, IincDebugTestDump.CLASS_NAME); |
| assertEquals(0, runInput.exitCode); |
| ProcessResult runCf = ToolHelper.runJava(buildCf(inputJar), IincDebugTestDump.CLASS_NAME); |
| assertEquals(0, runCf.exitCode); |
| assertEquals(runInput.toString(), runCf.toString()); |
| String runDex = |
| ToolHelper.runArtNoVerificationErrors( |
| buildDex(inputJar).toString(), IincDebugTestDump.CLASS_NAME); |
| assertEquals(runInput.stdout, runDex); |
| } |
| |
| private void stepOutput(byte[] clazz) throws Exception { |
| // TODO(b/199700280): Reenable on 12.0.0 when we have the libjdwp.so file include and the flags |
| // fixed. |
| Assume.assumeTrue( |
| "Skipping test " + testName.getMethodName() + " because debugging not enabled in 12.0.0", |
| !ToolHelper.getDexVm().isEqualTo(DexVm.ART_12_0_0_HOST)); |
| // See verifyStateLocation in DebugTestBase. |
| Assume.assumeTrue( |
| "Streaming on Dalvik DEX runtimes has some unknown interference issue", |
| ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V6_0_1)); |
| Assume.assumeTrue( |
| "Skipping test " |
| + testName.getMethodName() |
| + " because debug tests are not yet supported on Windows", |
| !ToolHelper.isWindows()); |
| Path inputJar = buildInput(clazz); |
| new DebugStreamComparator() |
| .add("Input", streamDebugTest(new CfDebugTestConfig(inputJar))) |
| .add("R8/DEX", streamDebugTest(new DexDebugTestConfig(buildDex(inputJar)))) |
| .add("R8/CF", streamDebugTest(new CfDebugTestConfig(buildCf(inputJar)))) |
| .compare(); |
| } |
| |
| private Stream<DebuggeeState> streamDebugTest(DebugTestConfig config) throws Exception { |
| return streamDebugTest(config, IincDebugTestDump.CLASS_NAME, ANDROID_FILTER); |
| } |
| |
| private Path buildInput(byte[] clazz) { |
| Path inputJar = temp.getRoot().toPath().resolve("input.jar"); |
| ArchiveConsumer inputJarConsumer = new ArchiveConsumer(inputJar); |
| inputJarConsumer.accept(ByteDataView.of(clazz), IincDebugTestDump.DESCRIPTOR, null); |
| inputJarConsumer.finished(null); |
| return inputJar; |
| } |
| |
| private Path buildDex(Path inputJar) throws Exception { |
| Path dexJar = temp.getRoot().toPath().resolve("r8dex.jar"); |
| build(inputJar, new DexIndexedConsumer.ArchiveConsumer(dexJar)); |
| return dexJar; |
| } |
| |
| private Path buildCf(Path inputJar) throws Exception { |
| Path cfJar = temp.getRoot().toPath().resolve("r8cf.jar"); |
| build(inputJar, new ArchiveConsumer(cfJar)); |
| return cfJar; |
| } |
| |
| private void build(Path inputJar, ProgramConsumer consumer) throws Exception { |
| Builder builder = |
| R8Command.builder() |
| .setMode(CompilationMode.DEBUG) |
| .setDisableTreeShaking(true) |
| .setDisableMinification(true) |
| .addProguardConfiguration( |
| ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), Origin.unknown()) |
| .setProgramConsumer(consumer) |
| .addProgramFiles(inputJar); |
| if ((consumer instanceof ClassFileConsumer)) { |
| builder.addLibraryFiles(ToolHelper.getJava8RuntimeJar()); |
| } else { |
| builder.addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm())); |
| } |
| ToolHelper.runR8(builder.build(), options -> options.invalidDebugInfoFatal = true); |
| } |
| } |