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());
+    }
+  }
+}