Test for adding twr synthetics to baseline profile
Bug: b/265729283
Change-Id: I9136fd23acdf5d06ba905a37f3ad028ba2d83b3c
diff --git a/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java b/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
index fae6781..156f775 100644
--- a/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/twr/TwrCloseResourceDuplicationTest.java
@@ -28,22 +28,24 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class TwrCloseResourceDuplicationTest extends TestBase {
private static final String PKG = "twrcloseresourceduplication";
private static final String EXAMPLE = "examplesJava9/" + PKG;
- private final JavaExampleClassProxy MAIN =
+ protected static final JavaExampleClassProxy MAIN =
new JavaExampleClassProxy(EXAMPLE, PKG + "/TwrCloseResourceDuplication");
- private final JavaExampleClassProxy FOO =
+ protected static final JavaExampleClassProxy FOO =
new JavaExampleClassProxy(EXAMPLE, PKG + "/TwrCloseResourceDuplication$Foo");
- private final JavaExampleClassProxy BAR =
+ protected static final JavaExampleClassProxy BAR =
new JavaExampleClassProxy(EXAMPLE, PKG + "/TwrCloseResourceDuplication$Bar");
static final int INPUT_CLASSES = 3;
- static final String EXPECTED =
+ protected static final String EXPECTED =
StringUtils.lines(
"foo opened 1",
"foo post close 1",
@@ -56,9 +58,10 @@
"bar caught from 2: RuntimeException",
"bar post close 2");
- private final TestParameters parameters;
+ @Parameter(0)
+ public TestParameters parameters;
- @Parameterized.Parameters(name = "{0}")
+ @Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters()
.withCfRuntimesStartingFromIncluding(CfVm.JDK9)
@@ -67,11 +70,7 @@
.build();
}
- public TwrCloseResourceDuplicationTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- private String getZipFile() throws IOException {
+ protected String getZipFile() throws IOException {
return ZipUtils.ZipBuilder.builder(temp.newFile("file.zip").toPath())
// DEX VMs from 4.4 up-to 9.0 including, will fail if no entry is added.
.addBytes("entry", new byte[1])
@@ -79,7 +78,7 @@
.toString();
}
- private List<Path> getProgramInputs() throws Exception {
+ protected static List<Path> getProgramInputs() {
return ImmutableList.of(JavaExampleClassProxy.examplesJar(EXAMPLE));
}
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java
new file mode 100644
index 0000000..80a799c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/TwrCloseResourceDuplicationProfileRewritingTest.java
@@ -0,0 +1,161 @@
+// Copyright (c) 2023, 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.profile.art.completeness;
+
+import static com.android.tools.r8.Jdk11TestUtils.getJdk11LibraryFiles;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.twr.TwrCloseResourceDuplicationTest;
+import com.android.tools.r8.profile.art.model.ExternalArtProfile;
+import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions.InlinerOptions;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class TwrCloseResourceDuplicationProfileRewritingTest
+ extends TwrCloseResourceDuplicationTest {
+
+ @Test
+ public void testR8ProfileRewriting() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramFiles(TwrCloseResourceDuplicationTest.getProgramInputs())
+ .addKeepMainRule(MAIN.typeName())
+ .addKeepClassAndMembersRules(FOO.typeName(), BAR.typeName())
+ .addArtProfileForRewriting(getArtProfile())
+ .addOptionsModification(InlinerOptions::disableInlining)
+ .applyIf(
+ parameters.isCfRuntime(),
+ testBuilder ->
+ testBuilder
+ .addLibraryFiles(getJdk11LibraryFiles(temp))
+ .addDefaultRuntimeLibrary(parameters)
+ .addOptionsModification(
+ options ->
+ options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces()),
+ testBuilder ->
+ testBuilder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST)))
+ .noHorizontalClassMergingOfSynthetics()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspectResidualArtProfile(this::inspect)
+ .run(parameters.getRuntime(), MAIN.typeName(), getZipFile())
+ .assertSuccessWithOutput(TwrCloseResourceDuplicationTest.EXPECTED);
+ }
+
+ private ExternalArtProfile getArtProfile() {
+ List<TypeReference> closeResourceFormalParameters =
+ ImmutableList.of(
+ Reference.classFromClass(Throwable.class),
+ Reference.classFromClass(AutoCloseable.class));
+ return ExternalArtProfile.builder()
+ .addMethodRule(
+ Reference.method(
+ FOO.getClassReference(),
+ "foo",
+ ImmutableList.of(Reference.classFromClass(String.class)),
+ null))
+ .addMethodRule(
+ Reference.method(
+ FOO.getClassReference(), "$closeResource", closeResourceFormalParameters, null))
+ .addMethodRule(
+ Reference.method(
+ BAR.getClassReference(),
+ "bar",
+ ImmutableList.of(Reference.classFromClass(String.class)),
+ null))
+ .addMethodRule(
+ Reference.method(
+ BAR.getClassReference(), "$closeResource", closeResourceFormalParameters, null))
+ .build();
+ }
+
+ private void inspect(ArtProfileInspector profileInspector, CodeInspector inspector) {
+ boolean hasTwrCloseResourceSupport =
+ parameters.isCfRuntime()
+ || parameters
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(apiLevelWithTwrCloseResourceSupport());
+
+ assertEquals(hasTwrCloseResourceSupport ? 3 : 7, inspector.allClasses().size());
+ assertThat(inspector.clazz(MAIN.typeName()), isPresent());
+
+ // Class Foo has two methods foo() and $closeResource().
+ ClassSubject fooClassSubject = inspector.clazz(FOO.typeName());
+ assertThat(fooClassSubject, isPresent());
+
+ MethodSubject fooMethodSubject = fooClassSubject.uniqueMethodWithOriginalName("foo");
+ assertThat(fooMethodSubject, isPresent());
+
+ MethodSubject fooCloseResourceMethodSubject =
+ fooClassSubject.uniqueMethodWithOriginalName("$closeResource");
+ assertThat(fooCloseResourceMethodSubject, isPresent());
+
+ // Class Bar has two methods bar() and $closeResource().
+ ClassSubject barClassSubject = inspector.clazz(BAR.typeName());
+ assertThat(barClassSubject, isPresent());
+
+ MethodSubject barMethodSubject = barClassSubject.uniqueMethodWithOriginalName("bar");
+ assertThat(barMethodSubject, isPresent());
+
+ MethodSubject barCloseResourceMethodSubject =
+ barClassSubject.uniqueMethodWithOriginalName("$closeResource");
+ assertThat(barCloseResourceMethodSubject, isPresent());
+
+ // There is a synthetic API outline, a backport and two twr classes.
+ ClassSubject syntheticApiOutlineClassSubject =
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticApiOutlineClass(BAR.getClassReference(), 0));
+ assertThat(syntheticApiOutlineClassSubject, notIf(isPresent(), hasTwrCloseResourceSupport));
+
+ ClassSubject syntheticBackportClassSubject =
+ inspector.clazz(SyntheticItemsTestUtils.syntheticBackportClass(BAR.getClassReference(), 1));
+ assertThat(syntheticBackportClassSubject, notIf(isPresent(), hasTwrCloseResourceSupport));
+
+ ClassSubject syntheticTwrCloseResourceClassSubject =
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticTwrCloseResourceClass(BAR.getClassReference(), 2));
+ assertThat(
+ syntheticTwrCloseResourceClassSubject, notIf(isPresent(), hasTwrCloseResourceSupport));
+
+ ClassSubject otherSyntheticTwrCloseResourceClassSubject =
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticTwrCloseResourceClass(BAR.getClassReference(), 3));
+ assertThat(
+ otherSyntheticTwrCloseResourceClassSubject, notIf(isPresent(), hasTwrCloseResourceSupport));
+
+ // Verify that the residual profile contains all of the above.
+ // TODO(b/265729283): Profile should include the twr syntehtic methods.
+ profileInspector
+ .assertContainsMethodRules(
+ fooMethodSubject,
+ fooCloseResourceMethodSubject,
+ barMethodSubject,
+ barCloseResourceMethodSubject)
+ .applyIf(
+ !hasTwrCloseResourceSupport,
+ i ->
+ i.assertContainsClassRules(
+ syntheticApiOutlineClassSubject, syntheticBackportClassSubject)
+ .assertContainsMethodRules(
+ syntheticApiOutlineClassSubject.uniqueMethod(),
+ syntheticBackportClassSubject.uniqueMethod()))
+ .assertContainsNoOtherRules();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/profile/art/utils/ArtProfileInspector.java b/src/test/java/com/android/tools/r8/profile/art/utils/ArtProfileInspector.java
index d498e18..3b75886 100644
--- a/src/test/java/com/android/tools/r8/profile/art/utils/ArtProfileInspector.java
+++ b/src/test/java/com/android/tools/r8/profile/art/utils/ArtProfileInspector.java
@@ -53,13 +53,20 @@
return this;
}
+ public ArtProfileInspector assertContainsClassRules(ClassReference... classReferences) {
+ for (ClassReference classReference : classReferences) {
+ assertContainsClassRule(classReference);
+ }
+ return this;
+ }
+
public ArtProfileInspector assertContainsClassRule(ClassSubject classSubject) {
return assertContainsClassRule(classSubject.getFinalReference());
}
- public ArtProfileInspector assertContainsClassRules(ClassReference... classReferences) {
- for (ClassReference classReference : classReferences) {
- assertContainsClassRule(classReference);
+ public ArtProfileInspector assertContainsClassRules(ClassSubject... classSubjects) {
+ for (ClassSubject classSubject : classSubjects) {
+ assertContainsClassRule(classSubject);
}
return this;
}