blob: 84a7f627f2c007045d453d91665d870cd1573363 [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;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.naming.applymapping.ApplyMappingVirtualInvokeTest.TestClasses.LibraryBase;
import com.android.tools.r8.naming.applymapping.ApplyMappingVirtualInvokeTest.TestClasses.LibraryInterface;
import com.android.tools.r8.naming.applymapping.ApplyMappingVirtualInvokeTest.TestClasses.LibrarySubclass;
import com.android.tools.r8.naming.applymapping.ApplyMappingVirtualInvokeTest.TestClasses.ProgramClass;
import com.android.tools.r8.naming.applymapping.ApplyMappingVirtualInvokeTest.TestClasses.ProgramSubclass;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ApplyMappingVirtualInvokeTest extends TestBase {
public static final String EXPECTED_PROGRAM =
StringUtils.lines("LibraryBase.foo", "LibraryBase.bar");
public static final String EXPECTED_PROGRAM_SUBCLASS =
StringUtils.lines(
"ProgramSubclass.foo", "LibraryBase.foo", "ProgramSubclass.bar", "LibraryBase.bar");
public static class TestClasses {
public interface LibraryInterface {
void bar();
}
public static class LibraryBase implements LibraryInterface {
public void foo() {
System.out.println("LibraryBase.foo");
}
@Override
public void bar() {
System.out.println("LibraryBase.bar");
}
}
public static class LibrarySubclass extends LibraryBase {}
public static class ProgramClass {
public static void main(String[] args) {
new LibrarySubclass().foo();
new LibrarySubclass().bar();
}
}
public static class ProgramSubclass extends LibrarySubclass {
public static void main(String[] args) {
new ProgramSubclass().foo();
new ProgramSubclass().bar();
}
@Override
public void foo() {
System.out.println("ProgramSubclass.foo");
super.foo();
}
@Override
public void bar() {
System.out.println("ProgramSubclass.bar");
super.bar();
}
}
}
private static final Class<?>[] LIBRARY_CLASSES = {
LibraryInterface.class, LibraryBase.class, LibrarySubclass.class
};
private static final Class<?>[] PROGRAM_CLASSES = {ProgramClass.class, ProgramSubclass.class};
private final TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimes().build();
}
public ApplyMappingVirtualInvokeTest(TestParameters parameters) {
this.parameters = parameters;
}
private static Function<TestParameters, R8TestCompileResult> compilationResults =
memoizeFunction(ApplyMappingVirtualInvokeTest::compile);
private static R8TestCompileResult compile(TestParameters parameters)
throws CompilationFailedException {
return testForR8(getStaticTemp(), parameters.getBackend())
.addProgramClasses(LIBRARY_CLASSES)
.addKeepClassAndMembersRulesWithAllowObfuscation(LIBRARY_CLASSES)
.setMinApi(parameters.getRuntime())
.addOptionsModification(
options -> {
options.inlinerOptions().enableInlining = false;
options.enableVerticalClassMerging = false;
options.enableClassInlining = false;
})
.compile();
}
@Test
public void runJvmProgramTest()
throws ExecutionException, CompilationFailedException, IOException {
assumeTrue(parameters.isCfRuntime());
testForJvm()
.addProgramClasses(LIBRARY_CLASSES)
.addProgramClasses(PROGRAM_CLASSES)
.run(parameters.getRuntime(), ProgramClass.class)
.assertSuccessWithOutput(EXPECTED_PROGRAM);
}
@Test
public void runJvmProgramSubclassTest()
throws ExecutionException, CompilationFailedException, IOException {
assumeTrue(parameters.isCfRuntime());
testForJvm()
.addProgramClasses(LIBRARY_CLASSES)
.addProgramClasses(PROGRAM_CLASSES)
.run(parameters.getRuntime(), ProgramSubclass.class)
.assertSuccessWithOutput(EXPECTED_PROGRAM_SUBCLASS);
}
@Test
public void testProgramClass()
throws ExecutionException, CompilationFailedException, IOException {
runTest(ProgramClass.class, EXPECTED_PROGRAM);
}
@Test
public void testProgramSubClass()
throws ExecutionException, IOException, CompilationFailedException {
runTest(ProgramSubclass.class, EXPECTED_PROGRAM_SUBCLASS);
}
private void runTest(Class<?> main, String expected)
throws ExecutionException, IOException, CompilationFailedException {
R8TestCompileResult libraryCompileResult = compilationResults.apply(parameters);
Path outPath = temp.newFile("out.zip").toPath();
libraryCompileResult.writeToZip(outPath);
testForR8(parameters.getBackend())
.noTreeShaking()
.noMinification()
.addProgramClasses(PROGRAM_CLASSES)
.addApplyMapping(libraryCompileResult.getProguardMap())
.addClasspathClasses(LIBRARY_CLASSES)
.addLibraryFiles(runtimeJar(parameters.getBackend()))
.setMinApi(parameters.getRuntime())
.compile()
.addRunClasspathFiles(outPath)
.run(parameters.getRuntime(), main)
.assertSuccessWithOutput(expected);
}
}