| // 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.shaking.fields.prvt; |
| |
| import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.NoVerticalClassMerging; |
| import com.android.tools.r8.shaking.fields.FieldsTestBase; |
| import com.android.tools.r8.utils.codeinspector.ClassSubject; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import com.google.common.collect.ImmutableSet; |
| import java.util.Collection; |
| import java.util.Set; |
| import org.junit.Test; |
| |
| @NoVerticalClassMerging |
| class Super { |
| private int f1; |
| } |
| |
| @NoVerticalClassMerging |
| class Sub extends Super { |
| private int f2; |
| } |
| |
| @NoVerticalClassMerging |
| class SubSub extends Sub { |
| private int f3; |
| } |
| |
| class Main { |
| |
| private static void printField(Class<?> clazz, String name) { |
| try { |
| clazz.getDeclaredField(name); |
| System.out.println(clazz.getSimpleName() + "." + name + " found"); |
| } catch (NoSuchFieldException e) { |
| System.out.println(clazz.getSimpleName() + "." + name + " not found"); |
| } |
| } |
| |
| public static void main(String[] args) { |
| printField(Super.class, "f1"); |
| printField(Sub.class, "f2"); |
| printField(SubSub.class, "f3"); |
| } |
| } |
| |
| public class PrivateFieldsTest extends FieldsTestBase { |
| |
| public Collection<Class<?>> getClasses() { |
| return ImmutableSet.of(Super.class, Sub.class, SubSub.class, getMainClass()); |
| } |
| |
| public Class<?> getMainClass() { |
| return Main.class; |
| } |
| |
| private void checkFields(CodeInspector inspector, Set<String> expected) { |
| ClassSubject superSubject = inspector.clazz(Super.class); |
| assertThat(superSubject, isPresent()); |
| assertEquals(superSubject.field("int", "f1").isPresent(), expected.contains("f1")); |
| ClassSubject subSubject = inspector.clazz(Sub.class); |
| assertThat(subSubject, isPresent()); |
| assertEquals(subSubject.field("int", "f2").isPresent(), expected.contains("f2")); |
| ClassSubject subSubSubject = inspector.clazz(SubSub.class); |
| assertThat(subSubSubject, isPresent()); |
| assertEquals(subSubSubject.field("int", "f3").isPresent(), expected.contains("f3")); |
| } |
| |
| private void checkAllFields(CodeInspector inspector) { |
| checkFields(inspector, ImmutableSet.of("f1", "f2", "f3")); |
| } |
| |
| private void checkOnlyF1(CodeInspector inspector) { |
| checkFields(inspector, ImmutableSet.of("f1")); |
| } |
| |
| private void checkOnlyF2(CodeInspector inspector) { |
| checkFields(inspector, ImmutableSet.of("f2")); |
| } |
| |
| private void checkOnlyF3(CodeInspector inspector) { |
| checkFields(inspector, ImmutableSet.of("f3")); |
| } |
| |
| @Test |
| public void testKeepAllFieldsWithWildcard() throws Throwable { |
| runTest("-keep class **.SubSub { *; }", this::checkAllFields, allFieldsOutput()); |
| } |
| |
| @Test |
| public void testKeepAllFieldsWithNameWildcard() throws Throwable { |
| runTest("-keep class **.SubSub { int f*; }", this::checkAllFields, allFieldsOutput()); |
| } |
| |
| @Test |
| public void testKeepAllFieldsWithFields() throws Throwable { |
| runTest("-keep class **.SubSub { <fields>; }", this::checkAllFields, allFieldsOutput()); |
| } |
| |
| @Test |
| public void testKeepF1() throws Throwable { |
| runTest("-keep class **.SubSub { int f1; }", this::checkOnlyF1, onlyF1Output()); |
| } |
| |
| @Test |
| public void testKeepF2() throws Throwable { |
| runTest("-keep class **.SubSub { int f2; }", this::checkOnlyF2, onlyF2Output()); |
| } |
| |
| @Test |
| public void testKeepF3() throws Throwable { |
| runTest("-keep class **.SubSub { int f3; }", this::checkOnlyF3, onlyF3Output()); |
| } |
| |
| @Test |
| public void testKeepF1WithExtends() throws Throwable { |
| runTest("-keep class * extends **.Sub { int f1; }", this::checkOnlyF1, onlyF1Output()); |
| } |
| |
| @Test |
| public void testKeepF2WithExtends() throws Throwable { |
| runTest("-keep class * extends **.Sub { int f2; }", this::checkOnlyF2, onlyF2Output()); |
| } |
| |
| @Test |
| public void testKeepF3WithExtends() throws Throwable { |
| runTest("-keep class * extends **.Sub { int f3; }", this::checkOnlyF3, onlyF3Output()); |
| } |
| } |