blob: 7bf989c83a9bf701645d4639d22a64054c331f7d [file] [log] [blame]
// Copyright (c) 2017, 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.CompilationMode;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase.MinifyMode;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/** Tests renaming of class and method names and corresponding proguard map output. */
@RunWith(Parameterized.class)
public class MinificationTest extends DebugTestBase {
private static final String SOURCE_FILE = "Minified.java";
@Parameterized.Parameters(name = "minification: {0}, proguardMap: {1}")
public static Collection minificationControl() {
ImmutableList.Builder<Object> builder = ImmutableList.builder();
for (MinifyMode mode : MinifyMode.values()) {
builder.add((Object) new Object[]{mode, false});
if (mode.isMinify()) {
builder.add((Object) new Object[]{mode, true});
}
}
return builder.build();
}
@Rule
public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
private final MinifyMode minificationMode;
private final boolean writeProguardMap;
public MinificationTest(MinifyMode minificationMode, boolean writeProguardMap) throws Exception {
this.minificationMode = minificationMode;
this.writeProguardMap = writeProguardMap;
}
private boolean minifiedNames() {
return minificationMode.isMinify() && !writeProguardMap;
}
private DebugTestConfig getTestConfig() throws Throwable {
List<String> proguardConfigurations = Collections.emptyList();
if (minificationMode.isMinify()) {
ImmutableList.Builder<String> builder = ImmutableList.builder();
builder.add("-keep public class Minified { public static void main(java.lang.String[]); }");
builder.add("-keepattributes SourceFile");
builder.add("-keepattributes LineNumberTable");
if (minificationMode == MinifyMode.AGGRESSIVE) {
builder.add("-overloadaggressively");
}
proguardConfigurations = builder.build();
}
int minSdk = ToolHelper.getMinApiLevelForDexVm(ToolHelper.getDexVm());
Path dexOutputDir = temp.newFolder().toPath();
Path proguardMap = writeProguardMap ? dexOutputDir.resolve("proguard.map") : null;
R8Command.Builder builder =
R8Command.builder()
.addProgramFiles(DEBUGGEE_JAR)
.setOutput(dexOutputDir, OutputMode.DexIndexed)
.setMinApiLevel(minSdk)
.setMode(CompilationMode.DEBUG)
.addLibraryFiles(ToolHelper.getAndroidJar(minSdk));
if (proguardMap != null) {
builder.setProguardMapOutputPath(proguardMap);
}
if (!proguardConfigurations.isEmpty()) {
builder.addProguardConfiguration(proguardConfigurations, Origin.unknown());
}
// Disable line number optimization if we're not using a Proguard map.
ToolHelper.runR8(
builder.build(),
proguardMap == null
? (oc -> oc.lineNumberOptimization = LineNumberOptimization.OFF)
: null);
DexDebugTestConfig config = new DexDebugTestConfig(dexOutputDir.resolve("classes.dex"));
config.setProguardMap(proguardMap);
return config;
}
@Test
public void testBreakInMainClass() throws Throwable {
final String className = "Minified";
final String methodName = minifiedNames() ? "a" : "test";
final String signature = "()V";
final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
final String innerMethodName = minifiedNames() ? "a" : "innerTest";
final String innerSignature = "()I";
runDebugTest(
getTestConfig(),
className,
breakpoint(className, methodName, signature),
run(),
checkMethod(className, methodName, signature),
checkLine(SOURCE_FILE, 14),
stepOver(INTELLIJ_FILTER),
checkMethod(className, methodName, signature),
checkLine(SOURCE_FILE, 15),
stepInto(INTELLIJ_FILTER),
checkMethod(innerClassName, innerMethodName, innerSignature),
checkLine(SOURCE_FILE, 8),
run());
}
@Test
public void testBreakInPossiblyRenamedClass() throws Throwable {
final String className = "Minified";
final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
final String innerMethodName = minifiedNames() ? "a" : "innerTest";
final String innerSignature = "()I";
runDebugTest(
getTestConfig(),
className,
breakpoint(innerClassName, innerMethodName, innerSignature),
run(),
checkMethod(innerClassName, innerMethodName, innerSignature),
checkLine(SOURCE_FILE, 8),
run());
}
}