blob: e0d32a330a40879fa6035e5ad1efe931b4048336 [file] [log] [blame]
// Copyright (c) 2019, 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.naming.applymapping.sourcelibrary;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.codeinspector.NewInstanceInstructionSubject;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ApplyMappingTest extends TestBase {
private static final Path NAMING001_JAR =
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "naming001" + FileUtils.JAR_EXTENSION);
private static final Path NAMING044_JAR =
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "naming044" + FileUtils.JAR_EXTENSION);
private static final Path APPLYMAPPING044_JAR =
Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "applymapping044" + FileUtils.JAR_EXTENSION);
@Parameter(0)
public TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withDefaultRuntimes().withApiLevel(AndroidApiLevel.B).build();
}
@Test
public void test044_apply() throws Exception {
// Make sure the given proguard map is indeed applied.
CodeInspector inspector =
testForR8(parameters.getBackend())
.addProgramFiles(APPLYMAPPING044_JAR)
.addClasspathFiles(NAMING044_JAR)
.addKeepRuleFiles(
Paths.get(
ToolHelper.EXAMPLES_DIR, "applymapping044", "keep-rules-apply-mapping.txt"))
.addDontObfuscate()
.setMinApi(parameters)
.compile()
.inspector();
MethodSubject main = inspector.clazz("applymapping044.Main").method(CodeInspector.MAIN);
Iterator<InvokeInstructionSubject> iterator =
main.iterateInstructions(InstructionSubject::isInvoke);
// B#m() -> y#n()
InvokeInstructionSubject m = iterator.next();
assertEquals("naming044.y", m.holder().toString());
assertEquals("n", m.invokedMethod().name.toString());
// sub.SubB#n() -> z.y#m()
InvokeInstructionSubject n = iterator.next();
assertEquals("naming044.z.y", n.holder().toString());
assertEquals("m", n.invokedMethod().name.toString());
// Skip A#<init>
iterator.next();
// Skip B#<init>
iterator.next();
// B#f(A) -> y#p(x)
InvokeInstructionSubject f = iterator.next();
DexType a1 = f.invokedMethod().proto.parameters.values[0];
assertEquals("naming044.x", a1.toString());
assertEquals("p", f.invokedMethod().name.toString());
// Skip AsubB#<init>
iterator.next();
// AsubB#f(A) -> AsubB#p(x)
InvokeInstructionSubject overloaded_f = iterator.next();
DexMethod aSubB_f = overloaded_f.invokedMethod();
DexType a2 = aSubB_f.proto.parameters.values[0];
assertEquals("naming044.x", a2.toString());
assertEquals("p", aSubB_f.name.toString());
// B#f == AsubB#f
assertEquals(f.invokedMethod().name.toString(), aSubB_f.name.toString());
// sub.SubB#<init>(int) -> z.y<init>(int)
InvokeInstructionSubject subBinit = iterator.next();
assertEquals("naming044.z.y", subBinit.holder().toString());
// sub.SubB#f(A) -> SubB#p(x)
InvokeInstructionSubject original_f = iterator.next();
DexMethod subB_f = original_f.invokedMethod();
DexType a3 = subB_f.proto.parameters.values[0];
assertEquals(a2, a3);
assertEquals("p", original_f.invokedMethod().name.toString());
}
@Test
public void test_naming001_rule105() throws Exception {
// keep rules to reserve D and E, along with a proguard map.
CodeInspector inspector =
testForR8(parameters.getBackend())
.addProgramFiles(NAMING001_JAR)
.addKeepRuleFiles(Paths.get(ToolHelper.EXAMPLES_DIR, "naming001", "keep-rules-105.txt"))
.addDontObfuscate()
.setMinApi(parameters)
.compile()
.inspector();
// Make sure the given proguard map is indeed applied.
ClassSubject classD = inspector.clazz("naming001.D");
assertThat(classD, isPresent());
// D must not be renamed
assertEquals("naming001.D", classD.getFinalName());
MethodSubject main = classD.method(CodeInspector.MAIN);
Iterator<InvokeInstructionSubject> iterator =
main.iterateInstructions(InstructionSubject::isInvoke);
// mapping-105 simply includes: naming001.D#keep -> peek
// naming001.E extends D, hence its keep() should be renamed to peek as well.
// Check E#<init> is not renamed.
InvokeInstructionSubject init = iterator.next();
assertEquals("Lnaming001/E;-><init>()V", init.invokedMethod().toSmaliString());
// E#keep() should be replaced with peek by applying the map.
InvokeInstructionSubject m = iterator.next();
assertEquals("peek", m.invokedMethod().name.toSourceString());
}
@Test
public void test_naming001_rule106() throws Exception {
// keep rules just to rename E
CodeInspector inspector =
testForR8(parameters.getBackend())
.addProgramFiles(NAMING001_JAR)
.addKeepRuleFiles(Paths.get(ToolHelper.EXAMPLES_DIR, "naming001", "keep-rules-106.txt"))
.noTreeShaking()
.setMinApi(parameters)
.compile()
.inspector();
// Make sure the given proguard map is indeed applied.
MethodSubject main = inspector.clazz("naming001.D").mainMethod();
assertThat(main, isPresent());
Iterator<InstructionSubject> iterator = main.iterateInstructions();
// naming001.E is renamed to a.a, so first instruction must be: new-instance La/a;
NewInstanceInstructionSubject newInstance = null;
while (iterator.hasNext()) {
InstructionSubject instruction = iterator.next();
if (instruction.isNewInstance()) {
newInstance = (NewInstanceInstructionSubject) instruction;
break;
}
}
assertNotNull(newInstance);
assertEquals( "La/a;", newInstance.getType().toSmaliString());
}
}