| // 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.b116840216; |
| |
| import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; |
| import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| |
| import com.android.tools.r8.CompatProguardCommandBuilder; |
| import com.android.tools.r8.NeverInline; |
| import com.android.tools.r8.NeverMerge; |
| import com.android.tools.r8.R8Command; |
| import com.android.tools.r8.TestBase; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.origin.Origin; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.codeinspector.ClassSubject; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import com.android.tools.r8.utils.codeinspector.MethodSubject; |
| import com.google.common.collect.ImmutableList; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| @NeverMerge |
| class Outer { |
| |
| @NeverMerge |
| static class Inner { |
| @NeverInline |
| static void foo() { |
| System.out.println("Inner.foo"); |
| } |
| } |
| |
| @NeverInline |
| static void bar() { |
| System.out.println("Outer.bar"); |
| } |
| } |
| |
| class TestMain { |
| public static void main(String[] args) { |
| Outer.Inner.foo(); |
| Outer.bar(); |
| } |
| } |
| |
| @RunWith(Parameterized.class) |
| public class ReserveOuterClassNameTest extends TestBase { |
| private Backend backend; |
| |
| @Parameters(name = "Backend: {0}") |
| public static Backend[] data() { |
| return ToolHelper.getBackends(); |
| } |
| |
| public ReserveOuterClassNameTest(Backend backend){ |
| this.backend = backend; |
| } |
| |
| private void runTest(boolean keepOuterName) throws Exception { |
| Class mainClass = TestMain.class; |
| R8Command.Builder builder = new CompatProguardCommandBuilder(true); |
| builder.addProgramFiles( |
| ToolHelper.getClassFileForTestClass(mainClass), |
| ToolHelper.getClassFileForTestClass(Outer.class), |
| ToolHelper.getClassFileForTestClass(Outer.Inner.class), |
| ToolHelper.getClassFileForTestClass(NeverInline.class)); |
| builder.setProgramConsumer(emptyConsumer(backend)); |
| builder.addLibraryFiles(runtimeJar(backend)); |
| builder.addProguardConfiguration( |
| ImmutableList.of( |
| "-printmapping", |
| "-keepattributes EnclosingMethod,InnerClasses,Signature", |
| keepMainProguardConfigurationWithInliningAnnotation(mainClass), |
| // Note that reproducing b/116840216 relies on the order of following rules that cause |
| // the visiting of classes during class minification to be Outer$Inner before Outer. |
| "-keepnames class " + Outer.class.getCanonicalName() + "$Inner", |
| keepOuterName ? "-keepnames class " + Outer.class.getCanonicalName() : "", |
| "-nevermerge @com.android.tools.r8.NeverMerge class *"), |
| Origin.unknown()); |
| |
| ToolHelper.allowTestProguardOptions(builder); |
| AndroidApp processedApp = ToolHelper.runR8(builder.build()); |
| |
| CodeInspector inspector = new CodeInspector(processedApp); |
| ClassSubject mainSubject = inspector.clazz(mainClass); |
| assertThat(mainSubject, isPresent()); |
| assertThat(mainSubject, not(isRenamed())); |
| MethodSubject mainMethod = mainSubject.mainMethod(); |
| assertThat(mainMethod, isPresent()); |
| assertThat(mainMethod, not(isRenamed())); |
| |
| ClassSubject outer = inspector.clazz(Outer.class); |
| assertThat(outer, isPresent()); |
| assertThat(outer, not(isRenamed())); |
| MethodSubject bar = outer.method("void", "bar", ImmutableList.of()); |
| assertThat(bar, isPresent()); |
| assertThat(bar, isRenamed()); |
| |
| ClassSubject inner = inspector.clazz(Outer.Inner.class); |
| assertThat(inner, isPresent()); |
| assertThat(inner, not(isRenamed())); |
| MethodSubject foo = inner.method("void", "foo", ImmutableList.of()); |
| assertThat(foo, isPresent()); |
| assertThat(foo, isRenamed()); |
| } |
| |
| @Test |
| public void test_keepOuterName() throws Exception { |
| runTest(true); |
| } |
| |
| @Test |
| public void test_keepInnerNameOnly() throws Exception { |
| runTest(false); |
| } |
| } |