blob: 446a481aa66bdaff2756635715eb0a3d2eb6c4b5 [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.naming.applymapping;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
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.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
// Base -> X:
class Base {
// foo() -> bar
void foo() {
System.out.println("Base#foo");
}
}
// Sub -> Y:
class Sub extends Base {
// foo() -> bar
// Sub#foo ~> Base#foo by member rebinding analysis
}
class CompositionalLenseTestMain {
public static void main(String[] args) {
// Without regard to the order of member rebinding and apply mapping,
// this call should be mapped to X.bar(), not Y.bar() nor Base.foo().
new Sub().foo();
}
}
@RunWith(Parameterized.class)
public class CompositionalLenseTest extends TestBase {
private final static List<Class> CLASSES =
ImmutableList.of(Base.class, Sub.class, CompositionalLenseTestMain.class);
private Backend backend;
@Parameterized.Parameters(name = "Backend: {0}")
public static Collection<Backend> data() {
return Arrays.asList(Backend.values());
}
public CompositionalLenseTest(Backend backend) {
this.backend = backend;
}
@Test
public void test() throws Exception {
Path mapPath = temp.newFile("test-mapping.txt").toPath();
List<String> pgMap = ImmutableList.of(
"com.android.tools.r8.naming.applymapping.Base -> X:",
" void foo() -> bar",
"com.android.tools.r8.naming.applymapping.Sub -> Y:",
" void foo() -> bar"
);
FileUtils.writeTextFile(mapPath, pgMap);
AndroidApp app = readClasses(CLASSES);
R8Command.Builder builder = ToolHelper.prepareR8CommandBuilder(app, emptyConsumer(backend));
builder
.addProguardConfiguration(
ImmutableList.of(
keepMainProguardConfiguration(CompositionalLenseTestMain.class),
"-applymapping " + mapPath,
"-dontobfuscate"), // to use the renamed names in test-mapping.txt
Origin.unknown())
.addLibraryFiles(runtimeJar(backend));
AndroidApp processedApp =
ToolHelper.runR8(
builder.build(),
options -> {
options.enableInlining = false;
options.enableVerticalClassMerging = false;
});
CodeInspector codeInspector = new CodeInspector(processedApp);
ClassSubject classSubject = codeInspector.clazz(CompositionalLenseTestMain.class);
assertThat(classSubject, isPresent());
MethodSubject methodSubject = classSubject.method(CodeInspector.MAIN);
assertThat(methodSubject, isPresent());
Iterator<InstructionSubject> iterator = methodSubject.iterateInstructions();
InstructionSubject instruction = null;
boolean found = false;
while (iterator.hasNext()) {
instruction = iterator.next();
if (instruction.isInvokeVirtual()) {
found = true;
break;
}
}
assertTrue(found);
DexMethod invokedMethod = ((InvokeInstructionSubject) instruction).invokedMethod();
assertEquals("bar", invokedMethod.name.toString());
assertEquals("X", invokedMethod.getHolder().getName());
}
}