Add a field naming test for -useuniqueclassmembernames
Bug: 129258741, 128973195
Change-Id: If3c85ba9a97c2ab2abd7c21a22269a36d3654a93
diff --git a/src/test/java/com/android/tools/r8/naming/UniqueFieldMemberNamesTest.java b/src/test/java/com/android/tools/r8/naming/UniqueFieldMemberNamesTest.java
new file mode 100644
index 0000000..bda2ba8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/UniqueFieldMemberNamesTest.java
@@ -0,0 +1,140 @@
+// 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;
+
+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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.jasmin.JasminBuilder;
+import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FieldSubject;
+import java.nio.file.Path;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class UniqueFieldMemberNamesTest extends TestBase {
+
+ @ClassRule public static TemporaryFolder tempFolder = ToolHelper.getTemporaryFolderForTest();
+
+ private static Path programClassA;
+ private static Path programClassB;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ {
+ JasminBuilder builder = new JasminBuilder();
+ ClassBuilder classBuilder = builder.addClass("A", "java/lang/Object");
+ classBuilder.addField("public", "a", "Ljava/lang/Object;", null);
+ classBuilder.addField("public", "f", "Ljava/lang/Object;", null);
+ programClassA = tempFolder.getRoot().toPath().resolve("input.jar");
+ builder.writeJar(programClassA);
+ }
+ {
+ JasminBuilder builder = new JasminBuilder();
+ ClassBuilder classBuilder = builder.addClass("B", "java/lang/Object");
+ classBuilder.addField("public", "f", "Ljava/lang/Object;", null);
+ classBuilder.addField("public", "f", "Ljava/lang/String;", null);
+ programClassB = tempFolder.getRoot().toPath().resolve("library.jar");
+ builder.writeJar(programClassB);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ runTest(testForR8(Backend.DEX), true);
+ }
+
+ @Test
+ public void testR8WithLibrary() throws Exception {
+ runTestWithLibrary(testForR8(Backend.DEX), true);
+ }
+
+ @Test
+ public void testProguard() throws Exception {
+ runTest(testForProguard(), false);
+ }
+
+ @Test
+ public void testProguardWithLibrary() throws Exception {
+ runTestWithLibrary(testForProguard(), false);
+ }
+
+ private void runTest(TestShrinkerBuilder<?, ?, ?, ?, ?> builder, boolean isR8) throws Exception {
+ CodeInspector inspector =
+ builder
+ .addProgramFiles(programClassA, programClassB)
+ .addKeepRules("-useuniqueclassmembernames")
+ .addKeepRules("-keep class A { java.lang.Object a; }")
+ .noTreeShaking()
+ .compile()
+ .inspector();
+
+ ClassSubject aClassSubject = inspector.clazz("A");
+ assertThat(aClassSubject, isPresent());
+
+ ClassSubject bClassSubject = inspector.clazz("B");
+ assertThat(bClassSubject, isPresent());
+
+ FieldSubject fieldSubject1 = aClassSubject.field("java.lang.Object", "f");
+ assertThat(fieldSubject1, isPresent());
+ assertThat(fieldSubject1, isRenamed());
+ assertNotEquals("a", fieldSubject1.getFinalName());
+
+ FieldSubject fieldSubject2 = bClassSubject.field("java.lang.Object", "f");
+ assertThat(fieldSubject2, isPresent());
+ assertThat(fieldSubject2, isRenamed());
+ assertEquals(fieldSubject2.getFinalName(), fieldSubject1.getFinalName());
+
+ FieldSubject fieldSubject3 = bClassSubject.field("java.lang.String", "f");
+ assertThat(fieldSubject3, isPresent());
+ assertThat(fieldSubject3, isRenamed());
+ if (isR8) {
+ // TODO(b/128973195): Fields should be given distinct names due to -useuniqueclassmembernames.
+ assertEquals(fieldSubject2.getFinalName(), fieldSubject3.getFinalName());
+ } else {
+ assertNotEquals(fieldSubject2.getFinalName(), fieldSubject3.getFinalName());
+ }
+ }
+
+ private void runTestWithLibrary(TestShrinkerBuilder<?, ?, ?, ?, ?> builder, boolean isR8)
+ throws Exception {
+ CodeInspector inspector =
+ builder
+ .addProgramFiles(programClassB)
+ .addLibraryFiles(programClassA, runtimeJar(Backend.DEX))
+ .addKeepRules("-useuniqueclassmembernames")
+ .addKeepRules("-keep class A { java.lang.Object a; }")
+ .noTreeShaking()
+ .compile()
+ .inspector();
+
+ ClassSubject bClassSubject = inspector.clazz("B");
+ assertThat(bClassSubject, isPresent());
+
+ FieldSubject fieldSubject2 = bClassSubject.field("java.lang.Object", "f");
+ assertThat(fieldSubject2, isPresent());
+ assertThat(fieldSubject2, not(isRenamed()));
+
+ FieldSubject fieldSubject3 = bClassSubject.field("java.lang.String", "f");
+ assertThat(fieldSubject3, isPresent());
+ if (isR8) {
+ // TODO(b/128973195): Fields should be given distinct names due to -useuniqueclassmembernames.
+ assertThat(fieldSubject3, not(isRenamed()));
+ } else {
+ assertThat(fieldSubject3, isRenamed());
+ }
+ }
+}