Update tests to latest Kotlin-dev compiler
* Test already failing on Koltin 2.2
* Context receivers no longer supported. Added test for context
parameters
* Difference in in `toString` for inner primary constructor
Fixes: b/463524093
Change-Id: I65c330fe4837669c2827b3844a2defdc5ed45c39
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
index be1f81a..ca7a345 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinInlineTest.java
@@ -270,7 +270,10 @@
@Test
public void testNestedInlining() throws Throwable {
// TODO(b/416189028): Triage this.
- assumeFalse(kotlinParameters.getCompilerVersion().equals(KotlinCompilerVersion.KOTLINC_2_2_0));
+ assumeFalse(
+ kotlinParameters
+ .getCompilerVersion()
+ .isGreaterThanOrEqualTo(KotlinCompilerVersion.KOTLINC_2_2_0));
// Count the number of lines in the source file. This is needed to check that inlined code
// refers to non-existing line numbers.
Path sourceFilePath =
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextParametersTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextParametersTest.java
new file mode 100644
index 0000000..b0f5dc1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextParametersTest.java
@@ -0,0 +1,193 @@
+// 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.kotlin.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_2_2_0;
+import static com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion.JAVA_8;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.KotlinCompileMemoizer;
+import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+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 MetadataRewriteContextParametersTest extends KotlinMetadataTestBase {
+
+ private static final String PKG_LIB = PKG + ".context_parameters_lib";
+ private static final String PKG_APP = PKG + ".context_parameters_app";
+ private static final Path LIB_FILE =
+ getFileInTest(PKG_PREFIX + "/context_parameters_lib", "lib.txt");
+ private static final Path MAIN_FILE =
+ getFileInTest(PKG_PREFIX + "/context_parameters_app", "main.txt");
+ private static final String MAIN = PKG_APP + ".MainKt";
+ private final TestParameters parameters;
+
+ private static final String EXPECTED =
+ StringUtils.lines(
+ "FooImpl::m1",
+ "BarImpl::m2",
+ "BazImpl::m3",
+ "BazImpl::m3",
+ "FooImpl::m1",
+ "BarImpl::m2",
+ "Hello World!");
+
+ @Parameterized.Parameters(name = "{0}, {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(),
+ getKotlinTestParameters()
+ .withCompilersStartingFromIncluding(KOTLINC_2_2_0)
+ .withAllLambdaGenerations()
+ .withTargetVersion(JAVA_8)
+ .build());
+ }
+
+ public MetadataRewriteContextParametersTest(
+ TestParameters parameters, KotlinTestParameters kotlinParameters) {
+ super(kotlinParameters);
+ this.parameters = parameters;
+ }
+
+ private static final KotlinCompileMemoizer libJars =
+ getCompileMemoizer()
+ .configure(
+ kotlinc ->
+ kotlinc
+ .addSourceFilesWithNonKtExtension(getStaticTemp(), LIB_FILE)
+ .enableExperimentalContextParameters());
+
+ @Test
+ public void smokeTest() throws Exception {
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), kotlinParameters)
+ .addClasspathFiles(libJars.getForConfiguration(kotlinParameters))
+ .addSourceFilesWithNonKtExtension(temp, MAIN_FILE)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextParameters()
+ .compile();
+ testForJvm(parameters)
+ .addRunClasspathFiles(
+ kotlinc.getKotlinStdlibJar(),
+ kotlinc.getKotlinReflectJar(),
+ libJars.getForConfiguration(kotlinParameters))
+ .addClasspath(output)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataForCompilationWithKeepAll() throws Exception {
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(kotlinc.getKotlinAnnotationJar())
+ .addProgramFiles(
+ libJars.getForConfiguration(kotlinParameters), kotlinc.getKotlinStdlibJar())
+ .addKeepClassAndMembersRules(PKG_LIB + ".*")
+ .addKeepAttributes(
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .addKeepKotlinMetadata()
+ .addOptionsModification(
+ options -> options.testing.keepMetadataInR8IfNotRewritten = false)
+ .compile()
+ // Since this has a keep-all classes rule assert that the meta-data is equal to the
+ // original one.
+ .inspect(
+ inspector ->
+ assertEqualDeserializedMetadata(
+ inspector,
+ new CodeInspector(libJars.getForConfiguration(kotlinParameters))))
+ .writeToZip();
+ Path main =
+ kotlinc(parameters.getRuntime().asCf(), kotlinParameters)
+ .addClasspathFiles(libJar)
+ .addSourceFilesWithNonKtExtension(temp, MAIN_FILE)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextParameters()
+ .compile();
+ testForJvm(parameters)
+ .addRunClasspathFiles(kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinReflectJar(), libJar)
+ .addClasspath(main)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataInExtensionFunction_renamedKotlinSources() throws Exception {
+ R8TestCompileResult r8LibraryResult =
+ testForR8(parameters.getBackend())
+ .addClasspathFiles(kotlinc.getKotlinStdlibJar(), kotlinc.getKotlinAnnotationJar())
+ .addProgramFiles(libJars.getForConfiguration(kotlinParameters))
+ // Ensure that we do not rename members
+ .addKeepRules("-keepclassmembers class * { *; }")
+ // Keep the Foo class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Foo")
+ // Keep the Bar class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Bar")
+ // Keep the Baz class but rename it.
+ .addKeepRules("-keep,allowobfuscation class " + PKG_LIB + ".Baz")
+ // Keep all Printer fields.
+ .addKeepRules("-keep class " + PKG_LIB + ".Printer { *; }")
+ // Keep Super, but allow minification.
+ .addKeepRules("-keep class " + PKG_LIB + ".LibKt { <methods>; }")
+ .addKeepRuntimeVisibleAnnotations()
+ .compile();
+
+ // Rewrite the kotlin source to rewrite the classes from the mapping file
+ String kotlinSource = FileUtils.readTextFile(MAIN_FILE, StandardCharsets.UTF_8);
+
+ CodeInspector inspector = r8LibraryResult.inspector();
+ // Rewrite the source kotlin file that reference the renamed classes uses in the context
+ // parameters.
+ for (String className : new String[] {"Foo", "Bar", "Baz"}) {
+ String originalClassName = PKG_LIB + "." + className;
+ ClassSubject clazz = inspector.clazz(originalClassName);
+ assertThat(clazz, isPresentAndRenamed());
+ kotlinSource =
+ kotlinSource.replace("import " + originalClassName, "import " + clazz.getFinalName());
+ kotlinSource =
+ kotlinSource.replace(
+ ": " + className + " {",
+ ": "
+ + DescriptorUtils.getSimpleClassNameFromDescriptor(clazz.getFinalDescriptor())
+ + " {");
+ }
+
+ Path newSource = temp.newFolder().toPath().resolve("main.kt");
+ Files.write(newSource, kotlinSource.getBytes(StandardCharsets.UTF_8));
+
+ Path libJar = r8LibraryResult.writeToZip();
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), kotlinParameters)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(newSource)
+ .setOutputPath(temp.newFolder().toPath())
+ .enableExperimentalContextParameters()
+ .compile();
+
+ testForJvm(parameters)
+ .addRunClasspathFiles(kotlinc.getKotlinStdlibJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java
index ba78e54..a6f1498 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteContextReceiverTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.kotlin.metadata;
import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_1_8_0;
+import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.KOTLINC_2_2_0;
import static com.android.tools.r8.KotlinCompilerTool.KotlinTargetVersion.JAVA_8;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -55,6 +56,7 @@
getTestParameters().withCfRuntimes().build(),
getKotlinTestParameters()
.withCompilersStartingFromIncluding(KOTLINC_1_8_0)
+ .withCompilersEndingAtIncluding(KOTLINC_2_2_0)
.withOldCompilersStartingFrom(KOTLINC_1_8_0)
.withAllLambdaGenerations()
.withTargetVersion(JAVA_8)
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
index cae7834..29b850c 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInnerClassTest.java
@@ -36,6 +36,14 @@
+ ".Outer.Inner.<init>(kotlin.Int): "
+ PKG_NESTED_REFLECT
+ ".Outer.Inner");
+ private static final String EXPECTED_DEV =
+ StringUtils.lines(
+ "fun <init>(kotlin.Int): " + PKG_NESTED_REFLECT + ".Outer.Nested",
+ "fun "
+ + PKG_NESTED_REFLECT
+ + ".Outer.<init>(kotlin.Int): "
+ + PKG_NESTED_REFLECT
+ + ".Outer.Inner");
private static final String EXPECTED_OUTER_RENAMED =
StringUtils.lines(
"fun <init>(kotlin.Int): " + PKG_NESTED_REFLECT + ".`Outer$Nested`",
@@ -44,7 +52,8 @@
private final TestParameters parameters;
private String getExpected() {
- return replaceInitNameInExpectedBasedOnKotlinVersion(EXPECTED);
+ return replaceInitNameInExpectedBasedOnKotlinVersion(
+ kotlinParameters.isKotlinDev() ? EXPECTED_DEV : EXPECTED);
}
private String getExpectedOuterRenamed() {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_app/main.txt b/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_app/main.txt
new file mode 100644
index 0000000..f419f9b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_app/main.txt
@@ -0,0 +1,46 @@
+// 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.kotlin.metadata.context_parameters_app
+
+import com.android.tools.r8.kotlin.metadata.context_parameters_lib.Bar
+import com.android.tools.r8.kotlin.metadata.context_parameters_lib.Foo
+import com.android.tools.r8.kotlin.metadata.context_parameters_lib.Baz
+import com.android.tools.r8.kotlin.metadata.context_parameters_lib.Printer
+import com.android.tools.r8.kotlin.metadata.context_parameters_lib.callFooBar
+
+class FooImpl : Foo {
+
+ override fun m1(): String {
+ println("FooImpl::m1")
+ return "Hello "
+ }
+}
+
+class BarImpl : Bar {
+ override fun m2(): String {
+ println("BarImpl::m2")
+ return "World!"
+ }
+}
+
+class BazImpl : Baz {
+ override fun m3(): String {
+ println("BazImpl::m3")
+ return "BazImpl::m3"
+ }
+}
+
+fun main() {
+ with (FooImpl()) {
+ with (BarImpl()) {
+ val printer = Printer()
+ printer.fooBar()
+ with (BazImpl()) {
+ println(printer.getValue)
+ println(callFooBar())
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_lib/lib.txt b/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_lib/lib.txt
new file mode 100644
index 0000000..b4d0415
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/context_parameters_lib/lib.txt
@@ -0,0 +1,35 @@
+// 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.kotlin.metadata.context_parameters_lib
+
+interface Foo {
+ fun m1(): String
+}
+
+interface Bar {
+ fun m2(): String
+}
+
+interface Baz {
+ fun m3(): String
+}
+
+class Printer {
+
+ context(foo: Foo, bar: Bar)
+ fun fooBar() {
+ foo.m1();
+ bar.m2();
+ }
+
+ context(baz: Baz)
+ val getValue: String
+ get() = if (System.currentTimeMillis() == 0L) "foo" else baz.m3()
+}
+
+context(foo: Foo, bar: Bar)
+fun callFooBar() : String {
+ return foo.m1() + bar.m2();
+}
\ No newline at end of file
diff --git a/src/test/testbase/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/testbase/java/com/android/tools/r8/KotlinCompilerTool.java
index 02359cc..df6040f 100644
--- a/src/test/testbase/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/testbase/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -313,6 +313,10 @@
return this;
}
+ public KotlinCompilerTool enableExperimentalContextParameters() {
+ return addArguments("-Xcontext-parameters");
+ }
+
public KotlinCompilerTool enableExperimentalContextReceivers() {
return addArguments("-Xcontext-receivers");
}
diff --git a/src/test/testbase/java/com/android/tools/r8/KotlinTestParameters.java b/src/test/testbase/java/com/android/tools/r8/KotlinTestParameters.java
index 05be21f..81bb6ea 100644
--- a/src/test/testbase/java/com/android/tools/r8/KotlinTestParameters.java
+++ b/src/test/testbase/java/com/android/tools/r8/KotlinTestParameters.java
@@ -100,8 +100,8 @@
private Predicate<KotlinTargetVersion> targetVersionFilter = defaultTargetVersionFilter;
private Predicate<KotlinLambdaGeneration> lambdaGenerationFilter =
defaultLambdaGenerationFilter;
- private boolean withDevCompiler =
- System.getProperty("com.android.tools.r8.kotlincompilerdev") != null;
+ private boolean withDevCompiler = true;
+ // System.getProperty("com.android.tools.r8.kotlincompilerdev") != null;
private boolean withOldCompilers =
System.getProperty("com.android.tools.r8.kotlincompilerold") != null;
@@ -203,6 +203,11 @@
return this;
}
+ public Builder withCompilersEndingAtIncluding(KotlinCompilerVersion version) {
+ withCompilerFilter(c -> c.isLessThanOrEqualTo(version));
+ return this;
+ }
+
public KotlinTestParametersCollection build() {
List<KotlinTestParameters> testParameters = new ArrayList<>();
int index = 0;