Add tests for looking up nested classes primary constructors
Bug: 188690067
Change-Id: I0fc674ac955acbfa28e8085ce12b08e07ad4876b
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
new file mode 100644
index 0000000..c38a3d7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.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.kotlin.metadata;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
+import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.ProgramConsumer;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Path;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteInnerClassTest extends KotlinMetadataTestBase {
+
+ private static final String EXPECTED =
+ StringUtils.lines(
+ "fun <init>(kotlin.Int):"
+ + " com.android.tools.r8.kotlin.metadata.nested_reflect.Outer.Nested",
+ "fun com.android.tools.r8.kotlin.metadata.nested_reflect.Outer.Inner.<init>(kotlin.Int):"
+ + " com.android.tools.r8.kotlin.metadata.nested_reflect.Outer.Inner");
+ private static final String EXPECTED_OUTER_RENAMED =
+ StringUtils.lines(
+ "fun <init>(kotlin.Int): com.android.tools.r8.kotlin.metadata.nested_reflect.Nested",
+ "fun <init>(kotlin.Int): com.android.tools.r8.kotlin.metadata.nested_reflect.Inner");
+ private static final String PKG_NESTED_REFLECT = PKG + ".nested_reflect";
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}, {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
+ getKotlinTestParameters().withAllCompilersAndTargetVersions().build());
+ }
+
+ public MetadataRewriteInnerClassTest(
+ TestParameters parameters, KotlinTestParameters kotlinParameters) {
+ super(kotlinParameters);
+ this.parameters = parameters;
+ }
+
+ private static final KotlinCompileMemoizer jarMap =
+ getCompileMemoizer(getKotlinFileInTest(PKG_PREFIX + "/nested_reflect", "main"));
+
+ @Test
+ public void smokeTest() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ Path libJar = jarMap.getForConfiguration(kotlinc, targetVersion);
+ testForRuntime(parameters)
+ .addProgramFiles(
+ ToolHelper.getKotlinStdlibJar(kotlinc), ToolHelper.getKotlinReflectJar(kotlinc), libJar)
+ .run(parameters.getRuntime(), PKG_NESTED_REFLECT + ".MainKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataOuterRenamed() throws Exception {
+ Path mainJar =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(ToolHelper.getKotlinStdlibJar(kotlinc))
+ .addClasspathFiles(ToolHelper.getKotlinReflectJar(kotlinc))
+ .addClasspathFiles(ToolHelper.getKotlinAnnotationJar(kotlinc))
+ .addProgramFiles(jarMap.getForConfiguration(kotlinc, targetVersion))
+ .addKeepRules("-keep public class " + PKG_NESTED_REFLECT + ".Outer$Nested { *; }")
+ .addKeepRules("-keep public class " + PKG_NESTED_REFLECT + ".Outer$Inner { *; }")
+ .addKeepMainRule(PKG_NESTED_REFLECT + ".MainKt")
+ .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(inspector -> inspectPruned(inspector, true))
+ .writeToZip();
+
+ runD8(mainJar, EXPECTED_OUTER_RENAMED);
+ }
+
+ @Test
+ public void testMetadataOuterNotRenamed() throws Exception {
+ Path mainJar =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(ToolHelper.getKotlinStdlibJar(kotlinc))
+ .addClasspathFiles(ToolHelper.getKotlinReflectJar(kotlinc))
+ .addClasspathFiles(ToolHelper.getKotlinAnnotationJar(kotlinc))
+ .addProgramFiles(jarMap.getForConfiguration(kotlinc, targetVersion))
+ .addKeepAttributeInnerClassesAndEnclosingMethod()
+ .addKeepRules("-keep public class " + PKG_NESTED_REFLECT + ".Outer { *; }")
+ .addKeepRules("-keep public class " + PKG_NESTED_REFLECT + ".Outer$Nested { *; }")
+ .addKeepRules("-keep public class " + PKG_NESTED_REFLECT + ".Outer$Inner { *; }")
+ .addKeepMainRule(PKG_NESTED_REFLECT + ".MainKt")
+ .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(inspector -> inspectPruned(inspector, false))
+ .writeToZip();
+
+ runD8(mainJar, EXPECTED);
+ }
+
+ private void runD8(Path jar, String expected) throws Exception {
+ Path output = temp.newFile("output.zip").toPath();
+ ProgramConsumer programConsumer =
+ parameters.isCfRuntime()
+ ? new ClassFileConsumer.ArchiveConsumer(output, true)
+ : new ArchiveConsumer(output, true);
+ testForD8(parameters.getBackend())
+ .addProgramFiles(
+ ToolHelper.getKotlinStdlibJar(kotlinc), ToolHelper.getKotlinReflectJar(kotlinc), jar)
+ .setMinApi(parameters.getApiLevel())
+ .setProgramConsumer(programConsumer)
+ .addOptionsModification(
+ options -> {
+ // Needed for passing kotlin_builtin files to output.
+ options.testing.enableD8ResourcesPassThrough = true;
+ options.dataResourceConsumer = options.programConsumer.getDataResourceConsumer();
+ })
+ .run(parameters.getRuntime(), PKG_NESTED_REFLECT + ".MainKt")
+ .assertSuccessWithOutput(expected);
+ }
+
+ private void inspectPruned(CodeInspector inspector, boolean outerRenamed) {
+ assertThat(
+ inspector.clazz(PKG_NESTED_REFLECT + ".Outer"),
+ outerRenamed ? isPresentAndRenamed() : isPresent());
+ assertThat(inspector.clazz(PKG_NESTED_REFLECT + ".Outer$Nested"), isPresent());
+ assertThat(inspector.clazz(PKG_NESTED_REFLECT + ".Outer$Inner"), isPresent());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/nested_reflect/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/nested_reflect/main.kt
new file mode 100644
index 0000000..f73e134
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/nested_reflect/main.kt
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, 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.nested_reflect
+
+import kotlin.reflect.full.primaryConstructor
+
+class Outer {
+ data class Nested(val data: Int)
+ inner class Inner(val data: Int)
+}
+
+fun main() {
+ val nestedPrimaryCtr = Outer.Nested::class.primaryConstructor
+ println(nestedPrimaryCtr?.toString() ?: "Cannot find primary constructor")
+ val innerPrimaryCtr = Outer.Inner::class.primaryConstructor
+ println(innerPrimaryCtr?.toString() ?: "Cannot find primary constructor")
+}