blob: a0e9a1d2a1612a89589fc865e6145351f6696706 [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.debuginfo;
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.ProgramConsumer;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.origin.Origin;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import org.junit.Test;
public class KotlinDebugInfoTestRunner extends TestBase {
private Path buildInput(byte[] clazz, String descriptor) {
Path inputJar = temp.getRoot().toPath().resolve("input.jar");
ArchiveConsumer inputJarConsumer = new ArchiveConsumer(inputJar);
inputJarConsumer.accept(ByteDataView.of(clazz), descriptor, null);
inputJarConsumer.finished(null);
return inputJar;
}
private Path buildCf(Path inputJar) throws Exception {
Path cfJar = temp.getRoot().toPath().resolve("r8cf.jar");
build(inputJar, new ArchiveConsumer(cfJar));
return cfJar;
}
@Test
public void testRingBuffer() throws Exception {
// This test hits the case where we simplify a DebugLocalWrite v'(x) <- v
// with debug use [live: y], and y is written between v and v'.
// In this case we must not move [live: y] to the definition of v,
// since it causes the live range of y to extend to the entry to the first block.
test(KotlinRingBufferDump.dump(), KotlinRingBufferDump.CLASS_NAME);
}
@Test
public void testReflection() throws Exception {
// This test hits the case where we replace a phi(v, v) that has local info
// with v that has no local info.
test(KotlinReflectionDump.dump(), KotlinReflectionDump.CLASS_NAME);
}
@Test
public void testFoo() throws Exception {
test(DebugInfoDump.dump(), DebugInfoDump.CLASS_NAME);
}
public void test(byte[] bytes, String className) throws Exception {
String descriptor = 'L' + className.replace('.', '/') + ';';
Path inputJar = buildInput(bytes, descriptor);
ProcessResult runInput = ToolHelper.runJava(inputJar, className);
if (0 != runInput.exitCode) {
System.out.println(runInput);
}
assertEquals(0, runInput.exitCode);
Path outCf = buildCf(inputJar);
ProcessResult runCf = ToolHelper.runJava(outCf, className);
assertEquals(runInput.toString(), runCf.toString());
}
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);
}
}