blob: 0ceefb4b252748b7ef1aa6227a8c9ff11d2567b3 [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.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.NeverMerge;
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;
@NeverMerge
class Super {
private int f1;
}
@NeverMerge
class Sub extends Super {
private int f2;
}
@NeverMerge
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());
}
}