Add tests for @Metadata rewriting of package-level functions.

Bug: 70169921
Change-Id: Ia94df462fc12c6bdbfe9bc724f23d031e482144d
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
index 36ac4fd..d6300f3 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
@@ -79,8 +79,7 @@
     final String implClassName = pkg + ".classpath_lib_ext.Impl";
     final String extraClassName = pkg + ".classpath_lib_ext.Extra";
     compileResult.inspect(inspector -> {
-      ClassSubject impl = inspector.clazz(implClassName);
-      assertThat(impl, not(isPresent()));
+      assertThat(inspector.clazz(implClassName), not(isPresent()));
 
       ClassSubject extra = inspector.clazz(extraClassName);
       assertThat(extra, isPresent());
@@ -136,7 +135,6 @@
     final String extraClassName = pkg + ".classpath_lib_ext.Extra";
     compileResult.inspect(inspector -> {
       ClassSubject impl = inspector.clazz(implClassName);
-      assertThat(impl, isPresent());
       assertThat(impl, isRenamed());
 
       ClassSubject extra = inspector.clazz(extraClassName);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
index 2f583fa..665414a 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
@@ -72,8 +72,7 @@
     final String superClassName = pkg + ".extension_lib.Super";
     final String bClassName = pkg + ".extension_lib.B";
     compileResult.inspect(inspector -> {
-      ClassSubject sup = inspector.clazz(superClassName);
-      assertThat(sup, not(isPresent()));
+      assertThat(inspector.clazz(superClassName), not(isPresent()));
 
       ClassSubject impl = inspector.clazz(bClassName);
       assertThat(impl, isPresent());
@@ -84,6 +83,7 @@
       List<ClassSubject> superTypes = kmClass.getSuperTypes();
       assertTrue(superTypes.stream().noneMatch(
           supertype -> supertype.getFinalDescriptor().contains("Super")));
+      // TODO(b/70169921): introduce KmFunction subject and make sure extension exists.
     });
 
     Path libJar = compileResult.writeToZip();
@@ -138,6 +138,7 @@
           supertype -> supertype.getFinalDescriptor().contains("Super")));
       assertTrue(superTypes.stream().anyMatch(
           supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor())));
+      // TODO(b/70169921): introduce KmFunction subject and make sure extension exists.
     });
 
     Path libJar = compileResult.writeToZip();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java
new file mode 100644
index 0000000..4e117ef
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java
@@ -0,0 +1,155 @@
+// Copyright (c) 2020, 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.kotlin.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+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.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.KmClassSubject;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRenameInFunctionTest extends KotlinMetadataTestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0} target: {1}")
+  public static Collection<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+  }
+
+  public MetadataRenameInFunctionTest(
+      TestParameters parameters, KotlinTargetVersion targetVersion) {
+    super(targetVersion);
+    this.parameters = parameters;
+  }
+
+  private static Path funLibJar;
+
+  @BeforeClass
+  public static void createLibJar() throws Exception {
+    String funLibFolder = PKG_PREFIX + "/function_lib";
+    funLibJar =
+        kotlinc(KOTLINC, KotlinTargetVersion.JAVA_8)
+            .addSourceFiles(getKotlinFileInTest(funLibFolder, "B"))
+            .compile();
+  }
+
+  @Test
+  public void testMetadataInFunction_merged() throws Exception {
+    R8TestCompileResult compileResult =
+        testForR8(parameters.getBackend())
+            .addProgramFiles(funLibJar)
+            // Keep the B class and its interface (which has the doStuff method).
+            .addKeepRules("-keep class **.B")
+            .addKeepRules("-keep class **.I { <methods>; }")
+            // Keep the BKt method, which will be called from other kotlin code.
+            .addKeepRules("-keep class **.BKt { <methods>; }")
+            .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+            .addOptionsModification(InternalOptions::enableKotlinMetadataRewriting)
+            .compile();
+    String pkg = getClass().getPackage().getName();
+    final String superClassName = pkg + ".function_lib.Super";
+    final String bClassName = pkg + ".function_lib.B";
+    compileResult.inspect(inspector -> {
+      assertThat(inspector.clazz(superClassName), not(isPresent()));
+
+      ClassSubject impl = inspector.clazz(bClassName);
+      assertThat(impl, isPresent());
+      assertThat(impl, not(isRenamed()));
+      // API entry is kept, hence the presence of Metadata.
+      KmClassSubject kmClass = impl.getKmClass();
+      assertThat(kmClass, isPresent());
+      List<ClassSubject> superTypes = kmClass.getSuperTypes();
+      assertTrue(superTypes.stream().noneMatch(
+          supertype -> supertype.getFinalDescriptor().contains("Super")));
+      // TODO(b/70169921): introduce KmFunction subject and make sure function exists.
+    });
+
+    Path libJar = compileResult.writeToZip();
+
+    String appFolder = PKG_PREFIX + "/function_app";
+    ProcessResult kotlinTestCompileResult =
+        kotlinc(parameters.getRuntime().asCf(), KOTLINC, KotlinTargetVersion.JAVA_8)
+            .addClasspathFiles(libJar)
+            .addSourceFiles(getKotlinFileInTest(appFolder, "main"))
+            .setOutputPath(temp.newFolder().toPath())
+            // TODO(b/70169921): update to just .compile() once fixed.
+            .compileRaw();
+    // TODO(b/70169921): should be able to compile!
+    assertNotEquals(0, kotlinTestCompileResult.exitCode);
+    assertThat(kotlinTestCompileResult.stderr, containsString("unresolved reference: `fun`"));
+  }
+
+  @Test
+  public void testMetadataInFunction_renamed() throws Exception {
+    R8TestCompileResult compileResult =
+        testForR8(parameters.getBackend())
+            .addProgramFiles(funLibJar)
+            // Keep the B class and its interface (which has the doStuff method).
+            .addKeepRules("-keep class **.B")
+            .addKeepRules("-keep class **.I { <methods>; }")
+            // Keep Super, but allow minification.
+            .addKeepRules("-keep,allowobfuscation class **.Super")
+            // Keep the BKt method, which will be called from other kotlin code.
+            .addKeepRules("-keep class **.BKt { <methods>; }")
+            .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+            .addOptionsModification(InternalOptions::enableKotlinMetadataRewriting)
+            .compile();
+    String pkg = getClass().getPackage().getName();
+    final String superClassName = pkg + ".function_lib.Super";
+    final String bClassName = pkg + ".function_lib.B";
+    compileResult.inspect(inspector -> {
+      ClassSubject sup = inspector.clazz(superClassName);
+      assertThat(sup, isRenamed());
+
+      ClassSubject impl = inspector.clazz(bClassName);
+      assertThat(impl, isPresent());
+      assertThat(impl, not(isRenamed()));
+      // API entry is kept, hence the presence of Metadata.
+      KmClassSubject kmClass = impl.getKmClass();
+      assertThat(kmClass, isPresent());
+      List<ClassSubject> superTypes = kmClass.getSuperTypes();
+      assertTrue(superTypes.stream().noneMatch(
+          supertype -> supertype.getFinalDescriptor().contains("Super")));
+      assertTrue(superTypes.stream().anyMatch(
+          supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor())));
+      // TODO(b/70169921): introduce KmFunction subject and make sure function exists.
+    });
+
+    Path libJar = compileResult.writeToZip();
+
+    String appFolder = PKG_PREFIX + "/function_app";
+    ProcessResult kotlinTestCompileResult =
+        kotlinc(parameters.getRuntime().asCf(), KOTLINC, KotlinTargetVersion.JAVA_8)
+            .addClasspathFiles(libJar)
+            .addSourceFiles(getKotlinFileInTest(appFolder, "main"))
+            .setOutputPath(temp.newFolder().toPath())
+            // TODO(b/70169921): update to just .compile() once fixed.
+            .compileRaw();
+    // TODO(b/70169921): should be able to compile!
+    assertNotEquals(0, kotlinTestCompileResult.exitCode);
+    assertThat(kotlinTestCompileResult.stderr, containsString("unresolved reference: `fun`"));
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInMultifileClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInMultifileClassTest.java
index 4adeb3f..80a2641 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInMultifileClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInMultifileClassTest.java
@@ -86,13 +86,11 @@
       // TODO(b/70169921): need further inspection.
 
       ClassSubject signed = inspector.clazz(signedClassName);
-      assertThat(signed, isPresent());
       assertThat(signed, isRenamed());
       commaJoinOfInt = signed.uniqueMethodWithName("commaSeparatedJoinOfInt");
       assertThat(commaJoinOfInt, isPresent());
       assertThat(commaJoinOfInt, not(isRenamed()));
       joinOfInt = signed.uniqueMethodWithName("joinOfInt");
-      assertThat(joinOfInt, isPresent());
       assertThat(joinOfInt, isRenamed());
       // API entry is kept, hence the presence of Metadata.
       annotationSubject = util.annotation(METADATA_TYPE);
@@ -148,13 +146,11 @@
       // TODO(b/70169921): need further inspection.
 
       ClassSubject signed = inspector.clazz(signedClassName);
-      assertThat(signed, isPresent());
       assertThat(signed, isRenamed());
       commaJoinOfInt = signed.uniqueMethodWithName("commaSeparatedJoinOfInt");
       assertThat(commaJoinOfInt, isPresent());
       assertThat(commaJoinOfInt, not(isRenamed()));
       joinOfInt = signed.uniqueMethodWithName("joinOfInt");
-      assertThat(joinOfInt, isPresent());
       assertThat(joinOfInt, isRenamed());
       // API entry is kept, hence the presence of Metadata.
       annotationSubject = util.annotation(METADATA_TYPE);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInParameterTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInParameterTypeTest.java
index e493ba2..61ede88 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInParameterTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInParameterTypeTest.java
@@ -71,7 +71,6 @@
     final String implClassName = pkg + ".parametertype_lib.Impl";
     compileResult.inspect(inspector -> {
       ClassSubject itf = inspector.clazz(itfClassName);
-      assertThat(itf, isPresent());
       assertThat(itf, isRenamed());
 
       ClassSubject impl = inspector.clazz(implClassName);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInPropertyTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInPropertyTypeTest.java
index 2c51bff..696cd03 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInPropertyTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInPropertyTypeTest.java
@@ -71,7 +71,6 @@
     final String implClassName = pkg + ".propertytype_lib.Impl";
     compileResult.inspect(inspector -> {
       ClassSubject itf = inspector.clazz(itfClassName);
-      assertThat(itf, isPresent());
       assertThat(itf, isRenamed());
 
       ClassSubject impl = inspector.clazz(implClassName);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInReturnTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInReturnTypeTest.java
index 1dc6c14..25ee2f8 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInReturnTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInReturnTypeTest.java
@@ -70,7 +70,6 @@
     final String implClassName = pkg + ".returntype_lib.Impl";
     compileResult.inspect(inspector -> {
       ClassSubject itf = inspector.clazz(itfClassName);
-      assertThat(itf, isPresent());
       assertThat(itf, isRenamed());
 
       ClassSubject impl = inspector.clazz(implClassName);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInSuperTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInSuperTypeTest.java
index 4ad8e97..722004a 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInSuperTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInSuperTypeTest.java
@@ -68,8 +68,7 @@
     final String itfClassName = pkg + ".supertype_lib.internal.Itf";
     final String implClassName = pkg + ".supertype_lib.Impl";
     compileResult.inspect(inspector -> {
-      ClassSubject itf = inspector.clazz(itfClassName);
-      assertThat(itf, not(isPresent()));
+      assertThat(inspector.clazz(itfClassName), not(isPresent()));
 
       ClassSubject impl = inspector.clazz(implClassName);
       assertThat(impl, isPresent());
@@ -117,7 +116,6 @@
     final String implClassName = pkg + ".supertype_lib.Impl";
     compileResult.inspect(inspector -> {
       ClassSubject itf = inspector.clazz(itfClassName);
-      assertThat(itf, isPresent());
       assertThat(itf, isRenamed());
 
       ClassSubject impl = inspector.clazz(implClassName);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/function_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/function_app/main.kt
new file mode 100644
index 0000000..2f51f32
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/function_app/main.kt
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.kotlin.metadata.function_app
+
+import com.android.tools.r8.kotlin.metadata.function_lib.B
+import com.android.tools.r8.kotlin.metadata.function_lib.`fun`
+
+fun main() {
+  B().doStuff()
+  `fun`(B())
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/function_lib/B.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/function_lib/B.kt
new file mode 100644
index 0000000..d327fda
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/function_lib/B.kt
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, 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.kotlin.metadata.function_lib
+
+interface I {
+  fun doStuff()
+}
+
+open class Super : I {
+  override fun doStuff() {
+    println("do stuff")
+  }
+}
+
+class B : Super()
+
+fun `fun`(b: B) {
+  b.doStuff()
+}