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