Reproduce missing kotlin.Metadata tracing in trace references

Bug: b/409260720
Change-Id: Ia00ab4f9442bfd63ececb69635ebf73139f4f335
diff --git a/src/test/java/com/android/tools/r8/partial/kotlin/Main.kt b/src/test/java/com/android/tools/r8/partial/kotlin/Main.kt
new file mode 100644
index 0000000..d5ce10d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/kotlin/Main.kt
@@ -0,0 +1,16 @@
+// Copyright (c) 2025, 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.partial.kotlin
+
+sealed class Greeting(val msg: String)
+
+class Message1() : Greeting("Hello, world!")
+
+// Unused, but referenced from the kotlin.Metadata of Greeting.
+// Included for shrinking in R8 partial, but should be retained.
+class Message2() : Greeting("Goodbye, world!")
+
+fun main() {
+  println(Message1().msg)
+}
diff --git a/src/test/java/com/android/tools/r8/partial/kotlin/PartialCompilationKotlinMetadataTest.java b/src/test/java/com/android/tools/r8/partial/kotlin/PartialCompilationKotlinMetadataTest.java
new file mode 100644
index 0000000..1e62fc8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/kotlin/PartialCompilationKotlinMetadataTest.java
@@ -0,0 +1,111 @@
+// Copyright (c) 2025, 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.partial.kotlin;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotNull;
+
+import com.android.tools.r8.KotlinCompilerTool.KotlinCompiler;
+import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.kotlin.KotlinMetadataWriter;
+import com.android.tools.r8.kotlin.metadata.KotlinMetadataTestBase;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Paths;
+import java.util.List;
+import kotlin.metadata.jvm.KotlinClassMetadata;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PartialCompilationKotlinMetadataTest extends KotlinMetadataTestBase {
+
+  private static final String PKG =
+      PartialCompilationKotlinMetadataTest.class.getPackage().getName();
+  private static final String GREETING_NAME = PKG + ".Greeting";
+  private static final String MAIN_NAME = PKG + ".MainKt";
+  private static final String MESSAGE1_NAME = PKG + ".Message1";
+  private static final String MESSAGE2_NAME = PKG + ".Message2";
+
+  private final TestParameters parameters;
+  private final boolean includeKotlin;
+
+  @Parameters(name = "{0}, kotlin: {1}, include kotlin.Metadata: {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withAllRuntimesAndApiLevels().build(),
+        getKotlinTestParameters().withAllCompilersLambdaGenerationsAndTargetVersions().build(),
+        BooleanUtils.values());
+  }
+
+  public PartialCompilationKotlinMetadataTest(
+      TestParameters parameters, KotlinTestParameters kotlinParameters, boolean includeKotlin) {
+    super(kotlinParameters);
+    this.parameters = parameters;
+    this.includeKotlin = includeKotlin;
+  }
+
+  @Test
+  public void test() throws Exception {
+    parameters.assumeCanUseR8Partial();
+    KotlinCompiler kotlinc = kotlinParameters.getCompiler();
+    testForR8Partial(parameters.getBackend())
+        .addProgramFiles(compiledJars.getForConfiguration(kotlinParameters))
+        .addProgramFiles(kotlinc.getKotlinStdlibJar())
+        .addProgramFiles(kotlinc.getKotlinAnnotationJar())
+        .addLibraryFiles(ToolHelper.getMostRecentAndroidJar())
+        .addKeepRuntimeVisibleAnnotations()
+        .applyIf(includeKotlin, b -> b.addKeepRules("-keep class kotlin.Metadata { *; }"))
+        .setMinApi(parameters)
+        .setR8PartialConfiguration(
+            partialConfigurationBuilder -> {
+              partialConfigurationBuilder.addJavaTypeIncludePattern(MESSAGE2_NAME);
+              if (includeKotlin) {
+                partialConfigurationBuilder.addJavaTypeIncludePattern("kotlin.**");
+              }
+            })
+        .allowDiagnosticMessages()
+        .allowUnusedDontWarnPatterns()
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), MAIN_NAME)
+        .assertSuccessWithOutputLines("Hello, world!");
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject message1Class = inspector.clazz(MESSAGE1_NAME);
+    assertThat(message1Class, isPresent());
+
+    ClassSubject message2Class = inspector.clazz(MESSAGE2_NAME);
+    assertThat(message2Class, isAbsent());
+
+    ClassSubject greetingClass = inspector.clazz(GREETING_NAME);
+    assertThat(greetingClass, isPresent());
+    KotlinClassMetadata kotlinClassMetadata = greetingClass.getKotlinClassMetadata();
+    assertNotNull(kotlinClassMetadata);
+    String metadata = KotlinMetadataWriter.kotlinMetadataToString("", kotlinClassMetadata);
+    assertThat(metadata, containsString(greetingClass.getFinalBinaryName()));
+    // TODO(b/409260720): Both Message1 and Message2 should be referenced.
+    assertThat(metadata, not(containsString(message1Class.getFinalBinaryName())));
+  }
+
+  private static KotlinCompileMemoizer compiledJars =
+      getCompileMemoizer(
+          Paths.get(
+              ToolHelper.TESTS_DIR,
+              "java",
+              DescriptorUtils.getBinaryNameFromJavaType(PKG),
+              "Main" + FileUtils.KT_EXTENSION));
+}