Reapply "Desugaring of AutoCloseable#close everywhere"
This reverts commit c44098b28724a38894a9276d8dfab7f4e32b7163.
Bug: b/369520931
Change-Id: I0035c5db369d521df2f85e9fdb5f5c4b974e1949
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
index 2deffd2..1836cf4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringCollection.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.apiconversion.DesugaredLibraryAPICallbackSynthesizer;
@@ -12,9 +13,11 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterPostProcessor;
import com.android.tools.r8.ir.desugar.itf.InterfaceMethodProcessorFacade;
import com.android.tools.r8.ir.desugar.records.RecordClassDesugaring;
+import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.Timing;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -67,7 +70,7 @@
&& !appView.options().getLibraryDesugaringOptions().isDesugaredLibraryCompilation()) {
desugarings.add(new DesugaredLibraryRetargeterPostProcessor(appView));
}
- if (appView.options().testing.enableAutoCloseableDesugaring) {
+ if (appView.options().shouldDesugarAutoCloseable()) {
desugarings.add(new AutoCloseableRetargeterPostProcessor(appView));
}
if (interfaceMethodProcessorFacade != null) {
@@ -104,8 +107,11 @@
ExecutorService executorService,
Timing timing)
throws ExecutionException {
+ Collection<DexProgramClass> sortedProgramClasses =
+ CollectionUtils.sort(programClasses, Comparator.comparing(DexClass::getType));
for (CfPostProcessingDesugaring desugaring : desugarings) {
- desugaring.postProcessingDesugaring(programClasses, eventConsumer, executorService, timing);
+ desugaring.postProcessingDesugaring(
+ sortedProgramClasses, eventConsumer, executorService, timing);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index e8080f8..81173c6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -121,8 +121,12 @@
if (desugaredLibraryRetargeter != null) {
desugarings.add(desugaredLibraryRetargeter);
}
- if (appView.options().shouldDesugarAutoCloseable()) {
- desugarings.add(new AutoCloseableRetargeter(appView));
+ AutoCloseableRetargeter autoCloseableRetargeter =
+ appView.options().shouldDesugarAutoCloseable()
+ ? new AutoCloseableRetargeter(appView)
+ : null;
+ if (autoCloseableRetargeter != null) {
+ desugarings.add(autoCloseableRetargeter);
}
disableDesugarer = DesugaredLibraryDisableDesugarer.create(appView);
if (disableDesugarer != null) {
@@ -149,6 +153,7 @@
SetUtils.newImmutableSetExcludingNullItems(
alwaysThrowingInstructionDesugaring,
backportedMethodRewriter,
+ autoCloseableRetargeter,
desugaredLibraryRetargeter),
SetUtils.newImmutableSetExcludingNullItems(
lambdaDesugaring, stringConcatDesugaring, recordRewriter));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/AutoCloseableRetargeterPostProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/AutoCloseableRetargeterPostProcessor.java
index e8019a1..2037f21 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/AutoCloseableRetargeterPostProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/AutoCloseableRetargeterPostProcessor.java
@@ -24,8 +24,10 @@
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ExecutorService;
// The rewrite of virtual calls requires to go through emulate dispatch. This class is responsible
@@ -50,23 +52,32 @@
ExecutorService executorService,
Timing timing) {
try (Timing t0 = timing.begin("Auto closeable retargeter post processor")) {
- ensureInterfacesAndForwardingMethodsSynthesized(programClasses, eventConsumer);
- }
- }
-
- @SuppressWarnings("ReferenceEquality")
- private void ensureInterfacesAndForwardingMethodsSynthesized(
- Collection<DexProgramClass> programClasses,
- AutoCloseableRetargeterPostProcessingEventConsumer eventConsumer) {
- ProcessorContext processorContext = appView.createProcessorContext();
- MainThreadContext mainThreadContext = processorContext.createMainThreadContext();
- for (DexProgramClass clazz : programClasses) {
- if (clazz.superType == null) {
- assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
- continue;
+ ProcessorContext processorContext = appView.createProcessorContext();
+ MainThreadContext mainThreadContext = processorContext.createMainThreadContext();
+ List<ProgramMethod> bridges = new ArrayList<>();
+ for (DexProgramClass clazz : programClasses) {
+ if (clazz.superType == null) {
+ assert clazz.type.isIdenticalTo(appView.dexItemFactory().objectType)
+ : clazz.type.toSourceString();
+ continue;
+ }
+ if (clazz.isInterface() && appView.options().isInterfaceMethodDesugaringEnabled()) {
+ // We cannot add default methods on interfaces if interface method desugaring is enabled.
+ continue;
+ }
+ if (implementsAutoCloseableAtLibraryBoundary(clazz)) {
+ ProgramMethod bridge =
+ ensureInterfacesAndForwardingMethodsSynthesized(
+ eventConsumer, clazz, mainThreadContext);
+ if (bridge != null) {
+ bridges.add(bridge);
+ }
+ }
}
- if (implementsAutoCloseableAtLibraryBoundary(clazz)) {
- ensureInterfacesAndForwardingMethodsSynthesized(eventConsumer, clazz, mainThreadContext);
+ // We add the bridges in the end so they don't interfer with lookups in between.
+ for (ProgramMethod bridge : bridges) {
+ bridge.getHolder().addVirtualMethod(bridge.getDefinition());
+ eventConsumer.acceptAutoCloseableForwardingMethod(bridge, bridge.getHolder());
}
}
}
@@ -75,46 +86,53 @@
if (clazz.interfaces.contains(appView.dexItemFactory().autoCloseableType)) {
return true;
}
- WorkList<DexType> workList = collectLibrarySuperTypeAndInterfaces(clazz);
+ WorkList<DexClass> workList = collectLibrarySuperTypeAndInterfaces(clazz);
return libraryTypesImplementsAutoCloseable(workList, clazz);
}
- private WorkList<DexType> collectLibrarySuperTypeAndInterfaces(DexProgramClass clazz) {
- WorkList<DexType> workList = WorkList.newIdentityWorkList();
+ private WorkList<DexClass> collectLibrarySuperTypeAndInterfaces(DexProgramClass clazz) {
+ WorkList<DexClass> workList = WorkList.newIdentityWorkList();
DexClass superclass = appView.definitionFor(clazz.superType);
- // Only performs computation if superclass is a library class, but not object to filter out
- // the most common case.
- if (superclass != null
- && superclass.isLibraryClass()
- && !superclass.type.isIdenticalTo(appView.dexItemFactory().objectType)) {
- workList.addIfNotSeen(superclass.type);
+ // R8 only performs the computation if the superclass is a library class.
+ if (superclass != null && superclass.isLibraryClass()) {
+ workList.addIfNotSeen(superclass);
}
for (DexType itf : clazz.interfaces) {
DexClass superItf = appView.definitionFor(itf);
if (superItf != null) {
- workList.addIfNotSeen(superItf.type);
+ // R8 only performs the computation if the super interface is a library class. If interface
+ // method desugaring is enabled, we need to go through all interfaces to insert the bridges
+ // on the classes and not the interfaces.
+ if (appView.options().isInterfaceMethodDesugaringEnabled() || superItf.isLibraryClass()) {
+ workList.addIfNotSeen(superItf);
+ }
}
}
return workList;
}
private boolean libraryTypesImplementsAutoCloseable(
- WorkList<DexType> workList, DexProgramClass clazz) {
+ WorkList<DexClass> workList, DexProgramClass clazz) {
while (workList.hasNext()) {
- DexType current = workList.next();
- if (current.isIdenticalTo(appView.dexItemFactory().objectType)) {
+ DexClass current = workList.next();
+ if (current.getType().isIdenticalTo(appView.dexItemFactory().objectType)) {
continue;
}
- DexClass currentClass = appView.definitionFor(current);
- if (currentClass == null) {
- reportInvalidSupertype(current, clazz);
- continue;
- }
- if (currentClass.interfaces.contains(appView.dexItemFactory().autoCloseableType)) {
+ if (current.interfaces.contains(appView.dexItemFactory().autoCloseableType)) {
return true;
}
- workList.addIfNotSeen(currentClass.superType);
- workList.addIfNotSeen(currentClass.interfaces);
+ DexClass superClass = appView.definitionFor(current.superType);
+ if (superClass == null) {
+ reportInvalidSupertype(current.superType, clazz);
+ } else {
+ workList.addIfNotSeen(superClass);
+ }
+ for (DexType itf : current.interfaces) {
+ DexClass superItf = appView.definitionFor(itf);
+ if (superItf != null) {
+ workList.addIfNotSeen(superItf);
+ }
+ }
}
return false;
}
@@ -130,7 +148,7 @@
ImmutableSet.of(getClose(origin.type)));
}
- private void ensureInterfacesAndForwardingMethodsSynthesized(
+ private ProgramMethod ensureInterfacesAndForwardingMethodsSynthesized(
AutoCloseableRetargeterPostProcessingEventConsumer eventConsumer,
DexProgramClass clazz,
MainThreadContext mainThreadContext) {
@@ -139,8 +157,9 @@
// We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
// applies up to 24.
if (appView.isAlreadyLibraryDesugared(clazz)) {
- return;
+ return null;
}
+ ProgramMethod bridge = null;
DexMethod close = getClose(clazz.type);
if (clazz.lookupVirtualMethod(close) == null) {
DexEncodedMethod newMethod =
@@ -148,20 +167,20 @@
if (newMethod == null) {
// We don't support desugaring on all subtypes, in which case there is not need to inject
// the interface.
- return;
+ return bridge;
}
- clazz.addVirtualMethod(newMethod);
- eventConsumer.acceptAutoCloseableForwardingMethod(new ProgramMethod(clazz, newMethod), clazz);
+ bridge = new ProgramMethod(clazz, newMethod);
}
DexType autoCloseableType = appView.dexItemFactory().autoCloseableType;
if (clazz.interfaces.contains(autoCloseableType)) {
- return;
+ return bridge;
}
clazz.addExtraInterfaces(
Collections.singletonList(new ClassTypeSignature(autoCloseableType)),
appView.dexItemFactory());
eventConsumer.acceptAutoCloseableInterfaceInjection(
clazz, appView.definitionFor(autoCloseableType));
+ return bridge;
}
@SuppressWarnings("ReferenceEquality")
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/EmulateDispatchSyntheticCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/EmulateDispatchSyntheticCfCodeProvider.java
index 2604cef..7f80f81 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/EmulateDispatchSyntheticCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/EmulateDispatchSyntheticCfCodeProvider.java
@@ -123,9 +123,17 @@
assert dispatchType == AUTO_CLOSEABLE;
instructions.add(new CfCheckCast(method.holder));
loadExtraParameters(instructions);
- if (appView.definitionFor(method.getHolderType()).isInterface()) {
+ // The type method.getHolderType() may not resolve if compiled without android library, for
+ // example, with the jdk as android.jar.
+ if (method
+ .getHolderType()
+ .isIdenticalTo(appView.dexItemFactory().javaUtilConcurrentExecutorServiceType)) {
+ assert appView.definitionFor(method.getHolderType()) == null
+ || appView.definitionFor(method.getHolderType()).isInterface();
instructions.add(new CfInvoke(Opcodes.INVOKEINTERFACE, method, true));
} else {
+ assert appView.definitionFor(method.getHolderType()) == null
+ || !appView.definitionFor(method.getHolderType()).isInterface();
instructions.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, method, false));
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index b7da0fc..0081000 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2129,7 +2129,7 @@
System.getProperty("com.android.tools.r8.enableKeepAnnotations") != null;
public boolean reverseClassSortingForDeterminism = false;
- public boolean enableAutoCloseableDesugaring = false;
+ public boolean enableAutoCloseableDesugaring = true;
public boolean enableNumberUnboxer = false;
public boolean printNumberUnboxed = false;
public boolean roundtripThroughLir = false;
@@ -2709,8 +2709,7 @@
public boolean shouldDesugarAutoCloseable() {
return desugarState.isOn()
&& getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K)
- && canHaveMissingImplementsAutoCloseableInterface()
- && testing.enableAutoCloseableDesugaring;
+ && canHaveMissingImplementsAutoCloseableInterface();
}
public boolean isSwitchRewritingEnabled() {
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTest.java
index ad0d144..eed8542 100644
--- a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTest.java
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTest.java
@@ -8,17 +8,16 @@
import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
-import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.ContentProviderClient;
-import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.DrmManagerClient;
-import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.MediaMetadataRetriever;
-import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.TypedArray;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.ContentProviderClientApiLevel24;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.DrmManagerClientApiLevel24;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.MediaMetadataRetrieverApiLevel29;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.TypedArrayAndroidApiLevel31;
import com.android.tools.r8.desugar.backports.AbstractBackportTest;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -82,11 +81,6 @@
}
@Override
- protected void configureD8Options(D8TestBuilder d8TestBuilder) throws IOException {
- d8TestBuilder.addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true);
- }
-
- @Override
protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
super.configureProgram(builder);
if (builder.isJvmTestBuilder()) {
@@ -153,22 +147,22 @@
private static byte[] getTestRunner() throws IOException {
return transformer(TestRunner.class)
.replaceClassDescriptorInMethodInstructions(
- descriptor(ContentProviderClient.class),
+ descriptor(ContentProviderClientApiLevel24.class),
DexItemFactory.androidContentContentProviderClientDescriptorString)
.replaceClassDescriptorInMethodInstructions(
- descriptor(DrmManagerClient.class),
+ descriptor(DrmManagerClientApiLevel24.class),
DexItemFactory.androidDrmDrmManagerClientDescriptorString)
.replaceClassDescriptorInMethodInstructions(
- descriptor(MediaMetadataRetriever.class),
+ descriptor(MediaMetadataRetrieverApiLevel29.class),
DexItemFactory.androidMediaMediaMetadataRetrieverDescriptorString)
.replaceClassDescriptorInMethodInstructions(
- descriptor(TypedArray.class),
+ descriptor(TypedArrayAndroidApiLevel31.class),
DexItemFactory.androidContentResTypedArrayDescriptorString)
.clearNest()
.transform();
}
- public static class ContentProviderClientOverride extends ContentProviderClient {
+ public static class ContentProviderClientOverride extends ContentProviderClientApiLevel24 {
public void close() {
super.close();
@@ -176,9 +170,9 @@
}
}
- public static class ContentProviderClientSub extends ContentProviderClient {}
+ public static class ContentProviderClientSub extends ContentProviderClientApiLevel24 {}
- public static class DrmManagerClientOverride extends DrmManagerClient {
+ public static class DrmManagerClientOverride extends DrmManagerClientApiLevel24 {
public void close() {
super.close();
@@ -186,9 +180,9 @@
}
}
- public static class DrmManagerClientSub extends DrmManagerClient {}
+ public static class DrmManagerClientSub extends DrmManagerClientApiLevel24 {}
- public static class MediaMetadataRetrieverOverride extends MediaMetadataRetriever {
+ public static class MediaMetadataRetrieverOverride extends MediaMetadataRetrieverApiLevel29 {
public void close() {
super.close();
@@ -196,9 +190,9 @@
}
}
- public static class MediaMetadataRetrieverSub extends MediaMetadataRetriever {}
+ public static class MediaMetadataRetrieverSub extends MediaMetadataRetrieverApiLevel29 {}
- public static class TypedArrayOverride extends TypedArray {
+ public static class TypedArrayOverride extends TypedArrayAndroidApiLevel31 {
public void close() {
super.close();
@@ -206,7 +200,7 @@
}
}
- public static class TypedArraySub extends TypedArray {}
+ public static class TypedArraySub extends TypedArrayAndroidApiLevel31 {}
public static class TestRunner extends MiniAssert {
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTwrTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTwrTest.java
index efad24f..c6b4632 100644
--- a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTwrTest.java
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidSubtypeTwrTest.java
@@ -8,11 +8,11 @@
import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
-import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.ContentProviderClientApiLevel24;
import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.DrmManagerClientApiLevel24;
@@ -36,6 +36,7 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters()
+ .withCfRuntime(CfVm.JDK21)
.withDexRuntimes()
.withApiLevelsStartingAtIncluding(AndroidApiLevel.K)
.enableApiLevelsForCf()
@@ -82,11 +83,6 @@
}
@Override
- protected void configureD8Options(D8TestBuilder d8TestBuilder) throws IOException {
- d8TestBuilder.addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true);
- }
-
- @Override
protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
super.configureProgram(builder);
if (builder.isJvmTestBuilder()) {
@@ -321,10 +317,5 @@
}
MiniAssert.assertTrue(box2[0].wasClosed);
}
-
- // Forwards to MiniAssert to avoid having to make it public.
- public static void doFail(String message) {
- MiniAssert.fail(message);
- }
}
}
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidTest.java
index 5668685..885be86 100644
--- a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidTest.java
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterAndroidTest.java
@@ -8,7 +8,6 @@
import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
-import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
@@ -54,12 +53,6 @@
registerTarget(AndroidApiLevel.B, 5);
}
- @Override
- protected void configureD8Options(D8TestBuilder d8TestBuilder) throws IOException {
- d8TestBuilder.addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true);
- }
-
- @Override
protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
super.configureProgram(builder);
if (builder.isJvmTestBuilder()) {
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTest.java
index d9c567c..f80a7a5 100644
--- a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTest.java
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTest.java
@@ -49,7 +49,23 @@
}
public static String EXPECTED_OUTPUT =
- StringUtils.lines("close", "close", "close", "close", "close", "close", "close", "SUCCESS");
+ StringUtils.lines(
+ "close",
+ "close",
+ "close",
+ "close",
+ "close",
+ "close",
+ "close",
+ "close itf",
+ "close itf",
+ "close",
+ "close",
+ "close itf",
+ "close itf",
+ "close ac",
+ "close ac direct",
+ "SUCCESS");
@Test
public void testJvm() throws Exception {
@@ -66,7 +82,6 @@
assumeTrue(parameters.isDexRuntime());
testForD8(parameters.getBackend())
.addInnerClassesAndStrippedOuter(getClass())
- .addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true)
.setMinApi(parameters)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
.addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
@@ -104,7 +119,6 @@
.addKeepMainRule(Main.class)
.addInnerClassesAndStrippedOuter(getClass())
.addInliningAnnotations()
- .addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true)
.setMinApi(parameters)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
.addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
@@ -282,6 +296,340 @@
public void execute(Runnable command) {}
}
+ public interface ExecutorItfOverride extends ExecutorService {
+ default void close() {
+ ExecutorService.super.close();
+ System.out.println("close itf");
+ }
+ }
+
+ public interface ExecutorItfSub extends ExecutorService {}
+
+ public static class ExecOverride1 implements ExecutorItfOverride {
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public static class ExecOverride2 implements ExecutorItfOverride {
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ public void close() {
+ ExecutorItfOverride.super.close();
+ System.out.println("close");
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public static class ExecSub1 implements ExecutorItfSub {
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public static class ExecSub2 implements ExecutorItfSub {
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ public void close() {
+ ExecutorItfSub.super.close();
+ System.out.println("close");
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public interface AutoCloseableOverride extends AutoCloseable {
+ default void close() {
+ System.out.println("close itf");
+ }
+ }
+
+ public interface AutoCloseablesub extends AutoCloseable {}
+
+ public static class AutoCloseableOverride1 implements AutoCloseableOverride {}
+
+ public static class AutoCloseableOverride2 implements AutoCloseableOverride {
+ public void close() {
+ AutoCloseableOverride.super.close();
+ System.out.println("close ac");
+ }
+ }
+
+ public static class AutoCloseableOverride3 implements AutoCloseablesub {
+ public void close() {
+ System.out.println("close ac direct");
+ }
+ }
+
public static class Main {
public static void main(String[] args) throws Exception {
@@ -333,6 +681,22 @@
ExecutorService executor22 = new Executor2();
close(executor22);
+ ExecOverride1 execOverride1 = new ExecOverride1();
+ execOverride1.close();
+ ExecOverride2 execOverride2 = new ExecOverride2();
+ execOverride2.close();
+ ExecSub1 execSub1 = new ExecSub1();
+ execSub1.close();
+ ExecSub2 execSub2 = new ExecSub2();
+ execSub2.close();
+
+ AutoCloseableOverride1 autoCloseableOverride1 = new AutoCloseableOverride1();
+ autoCloseableOverride1.close();
+ AutoCloseableOverride2 autoCloseableOverride2 = new AutoCloseableOverride2();
+ autoCloseableOverride2.close();
+ AutoCloseableOverride3 autoCloseableOverride3 = new AutoCloseableOverride3();
+ autoCloseableOverride3.close();
+
System.out.println("SUCCESS");
}
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTwrTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTwrTest.java
new file mode 100644
index 0000000..5a41819
--- /dev/null
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceSubtypeTwrTest.java
@@ -0,0 +1,357 @@
+// 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 autocloseable;
+
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DeterminismChecker;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.Assert;
+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 AutoCloseableRetargeterExecutorServiceSubtypeTwrTest extends TestBase {
+
+ @Parameter public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters()
+ .withCfRuntime(CfVm.JDK21)
+ .withDexRuntimes()
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.L)
+ .build();
+ }
+
+ public static String EXPECTED_OUTPUT =
+ StringUtils.lines("close", "close", "close", "close", "close", "SUCCESS");
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm(parameters)
+ .addInnerClassesAndStrippedOuter(getClass())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addInnerClassesAndStrippedOuter(getClass())
+ .setMinApi(parameters)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
+ .compile()
+ .addRunClasspathClassFileData((getAutoCloseableAndroidClassData(parameters)))
+ .inspect(this::assertCloseMethodsAndTags)
+ .run(
+ parameters.getRuntime(),
+ Main.class,
+ String.valueOf(parameters.getApiLevel().getLevel()))
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ private void assertCloseMethodsAndTags(CodeInspector inspector) {
+ for (Class<? extends ExecutorService> clazz :
+ ImmutableList.of(
+ PrintForkJoinPool.class,
+ OverrideForkJoinPool.class,
+ Executor1.class,
+ Executor2.class)) {
+ ClassSubject subj = inspector.clazz(clazz);
+ Assert.assertTrue(subj.isPresent());
+ Assert.assertTrue(subj.allMethods().stream().anyMatch(m -> m.getFinalName().equals("close")));
+ Assert.assertTrue(
+ subj.getDexProgramClass()
+ .getInterfaces()
+ .contains(inspector.getFactory().autoCloseableType));
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForR8(parameters.getBackend())
+ .addKeepMainRule(Main.class)
+ .addInnerClassesAndStrippedOuter(getClass())
+ .addInliningAnnotations()
+ .setMinApi(parameters)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
+ .compile()
+ .addRunClasspathClassFileData((getAutoCloseableAndroidClassData(parameters)))
+ .run(
+ parameters.getRuntime(),
+ Main.class,
+ String.valueOf(parameters.getApiLevel().getLevel()))
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ @Test
+ public void testD8Determinism() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ Path logDirectory = temp.newFolder().toPath();
+ Path ref = compileWithD8Determinism(logDirectory);
+ Path next = compileWithD8Determinism(logDirectory);
+ assertProgramsEqual(ref, next);
+ // Check that setting the determinism checker wrote a log file.
+ assertTrue(Files.exists(logDirectory.resolve("0.log")));
+ }
+
+ private Path compileWithD8Determinism(Path logDirectory) throws Exception {
+ return testForD8(parameters.getBackend())
+ .addInnerClassesAndStrippedOuter(getClass())
+ .setMinApi(parameters)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
+ .allowStdoutMessages()
+ .addOptionsModification(
+ options ->
+ options
+ .getTestingOptions()
+ .setDeterminismChecker(DeterminismChecker.createWithFileBacking(logDirectory)))
+ .compile()
+ .writeToZip();
+ }
+
+ public static class PrintForkJoinPool extends ForkJoinPool {
+
+ public void close() {
+ super.close();
+ System.out.println("close");
+ }
+ }
+
+ public static class OverrideForkJoinPool extends ForkJoinPool {}
+
+ public static class OverrideForkJoinPool2 extends OverrideForkJoinPool {}
+
+ public static class Executor1 implements ExecutorService {
+
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public static class Executor2 implements ExecutorService {
+
+ boolean done = false;
+
+ @Override
+ public void shutdown() {
+ done = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ done = true;
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return done;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return done;
+ }
+
+ public void close() {
+ ExecutorService.super.close();
+ System.out.println("close");
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return true;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return null;
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return null;
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+
+ @Override
+ public void execute(Runnable command) {}
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) throws Exception {
+ raw();
+ subtypes();
+ System.out.println("SUCCESS");
+ }
+
+ private static void subtypes() throws Exception {
+ try (PrintForkJoinPool forkJoinPool = new PrintForkJoinPool()) {}
+
+ try (ForkJoinPool forkJoinPool = new PrintForkJoinPool()) {}
+
+ try (ExecutorService executorService = new PrintForkJoinPool()) {}
+
+ try (OverrideForkJoinPool overrideForkJoinPool = new OverrideForkJoinPool()) {}
+
+ try (ForkJoinPool overrideForkJoinPool1 = new OverrideForkJoinPool()) {}
+
+ try (ExecutorService executorService = new OverrideForkJoinPool()) {}
+
+ try (OverrideForkJoinPool2 overrideForkJoinPool = new OverrideForkJoinPool2()) {}
+
+ try (OverrideForkJoinPool overrideForkJoinPool = new OverrideForkJoinPool2()) {}
+
+ try (ForkJoinPool overrideForkJoinPool1 = new OverrideForkJoinPool2()) {}
+
+ try (ExecutorService executorService = new OverrideForkJoinPool2()) {}
+
+ try (Executor1 executorService = new Executor1()) {}
+
+ try (ExecutorService executorService = new Executor1()) {}
+
+ try (Executor2 executorService = new Executor2()) {}
+
+ try (ExecutorService executorService = new Executor2()) {}
+ }
+
+ private static void raw() throws Exception {
+ try (ForkJoinPool forkJoinPool = new ForkJoinPool()) {}
+
+ try (ExecutorService forkJoinPool = new ForkJoinPool()) {}
+ }
+ }
+}
diff --git a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceTest.java b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceTest.java
index ae043fd..5a47d26 100644
--- a/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceTest.java
+++ b/src/test/examplesJava21/autocloseable/AutoCloseableRetargeterExecutorServiceTest.java
@@ -49,7 +49,6 @@
public void testD8() throws Exception {
testForD8(parameters.getBackend())
.addInnerClassesAndStrippedOuter(getClass())
- .addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true)
.setMinApi(parameters)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
.addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
@@ -68,7 +67,6 @@
.addKeepMainRule(Main.class)
.addInnerClassesAndStrippedOuter(getClass())
.addInliningAnnotations()
- .addOptionsModification(opt -> opt.testing.enableAutoCloseableDesugaring = true)
.setMinApi(parameters)
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
.addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters))
diff --git a/src/test/examplesJava21/twr/ExecutorServiceBackportTest.java b/src/test/examplesJava21/twr/ExecutorServiceBackportTest.java
index a57d54b..a38220c 100644
--- a/src/test/examplesJava21/twr/ExecutorServiceBackportTest.java
+++ b/src/test/examplesJava21/twr/ExecutorServiceBackportTest.java
@@ -30,6 +30,7 @@
.withCfRuntimesStartingFromIncluding(CfVm.JDK21)
.withDexRuntimesStartingFromExcluding(Version.V4_4_4)
.withAllApiLevelsAlsoForCf()
+ .withApiLevel(AndroidApiLevel.K)
.build();
}
@@ -60,11 +61,6 @@
}
}
- @Override
- public void testD8Cf() throws Exception {
- super.testD8Cf();
- }
-
public static class Main {
public static void main(String[] args) {
diff --git a/src/test/examplesJava9/twr/twraddsuppressed/TwrSuppressedExceptionsTest.java b/src/test/examplesJava9/twr/twraddsuppressed/TwrSuppressedExceptionsTest.java
index 573fc99..7efe94e 100644
--- a/src/test/examplesJava9/twr/twraddsuppressed/TwrSuppressedExceptionsTest.java
+++ b/src/test/examplesJava9/twr/twraddsuppressed/TwrSuppressedExceptionsTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -18,6 +19,7 @@
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -114,11 +116,15 @@
.addProgramClassFileData(getProgramInputs())
.setMinApi(parameters)
.addKeepMainRule(TEST_CLASS)
- // TODO(b/214250388): Don't warn about AutoClosable in synthesized code.
+ // TODO(b/214250388): Don't warn about AutoClosable and ForkJoinPool in synthesized code.
.apply(
b -> {
if (!apiLevelHasTwrCloseResourceSupport(parameters.isDexRuntime())) {
b.addDontWarn(AutoCloseable.class);
+ } else if (parameters
+ .getApiLevel()
+ .isBetweenBothIncluded(AndroidApiLevel.K, AndroidApiLevel.K_WATCH)) {
+ b.addDontWarn(ForkJoinPool.class);
}
})
.run(parameters.getRuntime(), TEST_CLASS)
diff --git a/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationProfileRewritingTest.java b/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationProfileRewritingTest.java
index 4cad84a..1713cf4 100644
--- a/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationProfileRewritingTest.java
+++ b/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationProfileRewritingTest.java
@@ -18,11 +18,13 @@
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;
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.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -137,6 +139,11 @@
if (hasTwrCloseResourceApiOutlines()) {
expectedClassCount += 4;
}
+ InternalOptions options = inspector.getApplication().options;
+ options.setMinApiLevel(parameters.getApiLevel());
+ if (options.shouldDesugarAutoCloseable()) {
+ expectedClassCount += 12;
+ }
inspector
.allClasses()
.forEach(c -> System.out.println(c.getDexProgramClass().toSourceString()));
@@ -240,6 +247,52 @@
syntheticTwrCloseResourceClassSubject5.uniqueMethod()));
}
+ profileInspector.applyIf(
+ options.shouldDesugarAutoCloseable(),
+ i ->
+ i.assertContainsClassRules(getCloseDispatcherSyntheticClasses(inspector))
+ .assertContainsMethodRules(
+ Arrays.stream(getCloseDispatcherSyntheticClasses(inspector))
+ .map(ClassSubject::uniqueMethod)
+ .toArray(MethodSubject[]::new)));
+
profileInspector.assertContainsNoOtherRules();
}
+
+ private static ClassSubject[] getCloseDispatcherSyntheticClasses(CodeInspector inspector) {
+ return new ClassSubject[] {
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableDispatcherClass(
+ Reference.classFromTypeName(FOO), 0)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableDispatcherClass(
+ Reference.classFromTypeName(FOO), 1)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableDispatcherClass(
+ Reference.classFromTypeName(BAR), 0)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableDispatcherClass(
+ Reference.classFromTypeName(BAR), 1)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableForwarderClass(
+ Reference.classFromTypeName(FOO), 2)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableForwarderClass(
+ Reference.classFromTypeName(FOO), 3)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableForwarderClass(
+ Reference.classFromTypeName(BAR), 2)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticAutoCloseableForwarderClass(
+ Reference.classFromTypeName(BAR), 3)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticThrowIAEClass(Reference.classFromTypeName(FOO), 4)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticThrowIAEClass(Reference.classFromTypeName(FOO), 5)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticThrowIAEClass(Reference.classFromTypeName(BAR), 4)),
+ inspector.clazz(
+ SyntheticItemsTestUtils.syntheticThrowIAEClass(Reference.classFromTypeName(BAR), 5))
+ };
+ }
}
diff --git a/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationTest.java b/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationTest.java
index 930ae37..471dffb 100644
--- a/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationTest.java
+++ b/src/test/examplesJava9/twr/twrcloseresourceduplication/TwrCloseResourceDuplicationTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
@@ -127,6 +128,11 @@
if (hasTwrCloseResourceApiOutlines()) {
expectedSynthetics += 1;
}
+ InternalOptions options = inspector.getApplication().options;
+ options.setMinApiLevel(parameters.getApiLevel());
+ if (options.shouldDesugarAutoCloseable()) {
+ expectedSynthetics += 3;
+ }
assertEquals(INPUT_CLASSES + expectedSynthetics, inspector.allClasses().size());
});
}
@@ -161,7 +167,19 @@
.getTypeName());
assertEquals(classOutputWithSynthetics, foundClasses);
} else {
- assertEquals(nonSyntheticClassOutput, foundClasses);
+ Set<String> classOutputWithSynthetics = new HashSet<>(nonSyntheticClassOutput);
+ if (parameters.getApiLevel().isLessThan(AndroidApiLevel.N)) {
+ // Above N, the forwarder is inlined in the dispatcher.
+ classOutputWithSynthetics.add(
+ SyntheticItemsTestUtils.syntheticAutoCloseableForwarderClass(
+ Reference.classFromTypeName(BAR), 1)
+ .getTypeName());
+ }
+ classOutputWithSynthetics.add(
+ SyntheticItemsTestUtils.syntheticAutoCloseableDispatcherClass(
+ Reference.classFromTypeName(BAR), 0)
+ .getTypeName());
+ assertEquals(classOutputWithSynthetics, foundClasses);
}
});
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ContentProviderClientBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/ContentProviderClientBackportTest.java
index 8d3b5f2..f666284 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ContentProviderClientBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ContentProviderClientBackportTest.java
@@ -4,12 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.compileAutoCloseableAndroidLibraryClasses;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.ContentProviderClient;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -22,16 +30,19 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ return getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
}
public ContentProviderClientBackportTest(TestParameters parameters) throws IOException {
super(
parameters,
- ContentProviderClientBackportTest.getContentProviderClient(parameters),
- ImmutableList.of(
- ContentProviderClientBackportTest.getTestRunner(),
- ContentProviderClientBackportTest.getContentProviderClient(parameters)));
+ DescriptorUtils.descriptorToJavaType(
+ DexItemFactory.androidContentContentProviderClientDescriptorString),
+ ImmutableList.of(ContentProviderClientBackportTest.getTestRunner()));
// The constructor is used by the test and release has been available since API 5 and is the
// method close is rewritten to.
@@ -42,6 +53,27 @@
registerTarget(AndroidApiLevel.N, 1);
}
+ @Override
+ protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
+ super.configureProgram(builder);
+ if (builder.isJvmTestBuilder()) {
+ builder.addProgramClassFileData(getAutoCloseableAndroidClassData(parameters));
+ } else {
+ builder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
+ @Override
+ protected void configure(D8TestCompileResult builder) throws Exception {
+ if (parameters.isDexRuntime()) {
+ builder.addBootClasspathFiles(compileAutoCloseableAndroidLibraryClasses(this, parameters));
+ } else {
+ builder.addRunClasspathClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
@Test
public void testJvm() throws Exception {
parameters.assumeJvmTestParameters();
@@ -49,19 +81,7 @@
.apply(this::configureProgram)
.run(parameters.getRuntime(), getTestClassName())
// Fails when not desugared.
- .assertFailureWithErrorThatMatches(containsString("Failed: close should not be called"));
- }
-
- private static byte[] getContentProviderClient(TestParameters parameters) throws IOException {
- if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)) {
- return transformer(ContentProviderClientApiLevel24.class)
- .setClassDescriptor(DexItemFactory.androidContentContentProviderClientDescriptorString)
- .transform();
- } else {
- return transformer(ContentProviderClient.class)
- .setClassDescriptor(DexItemFactory.androidContentContentProviderClientDescriptorString)
- .transform();
- }
+ .assertFailureWithErrorThatMatches(containsString("close should not be called"));
}
private static byte[] getTestRunner() throws IOException {
@@ -72,32 +92,6 @@
.transform();
}
- public static class ContentProviderClient {
- public boolean wasClosed = false;
-
- public void close() {
- TestRunner.doFail("close should not be called");
- }
-
- public boolean release() {
- wasClosed = true;
- return wasClosed;
- }
- }
-
- public static class ContentProviderClientApiLevel24 {
- public boolean wasClosed = false;
-
- public void close() {
- wasClosed = true;
- }
-
- public boolean release() {
- TestRunner.doFail("release should not be called");
- return true;
- }
- }
-
public static class TestRunner extends MiniAssert {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/DrmManagerClientBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/DrmManagerClientBackportTest.java
index 5d3ee55..ab89582 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/DrmManagerClientBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/DrmManagerClientBackportTest.java
@@ -4,12 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.compileAutoCloseableAndroidLibraryClasses;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.DrmManagerClient;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -22,16 +30,19 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ return getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
}
public DrmManagerClientBackportTest(TestParameters parameters) throws IOException {
super(
parameters,
- DrmManagerClientBackportTest.getDrmManagerClient(parameters),
- ImmutableList.of(
- DrmManagerClientBackportTest.getTestRunner(),
- DrmManagerClientBackportTest.getDrmManagerClient(parameters)));
+ DescriptorUtils.descriptorToJavaType(
+ DexItemFactory.androidDrmDrmManagerClientDescriptorString),
+ ImmutableList.of(DrmManagerClientBackportTest.getTestRunner()));
// The constructor is used by the test and release has been available since API 5 and is the
// method close is rewritten to.
@@ -42,6 +53,27 @@
registerTarget(AndroidApiLevel.N, 1);
}
+ @Override
+ protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
+ super.configureProgram(builder);
+ if (builder.isJvmTestBuilder()) {
+ builder.addProgramClassFileData(getAutoCloseableAndroidClassData(parameters));
+ } else {
+ builder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
+ @Override
+ protected void configure(D8TestCompileResult builder) throws Exception {
+ if (parameters.isDexRuntime()) {
+ builder.addBootClasspathFiles(compileAutoCloseableAndroidLibraryClasses(this, parameters));
+ } else {
+ builder.addRunClasspathClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
@Test
public void testJvm() throws Exception {
parameters.assumeJvmTestParameters();
@@ -49,19 +81,7 @@
.apply(this::configureProgram)
.run(parameters.getRuntime(), getTestClassName())
// Fails when not desugared.
- .assertFailureWithErrorThatMatches(containsString("Failed: close should not be called"));
- }
-
- private static byte[] getDrmManagerClient(TestParameters parameters) throws IOException {
- if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)) {
- return transformer(DrmManagerClientApiLevel24.class)
- .setClassDescriptor(DexItemFactory.androidDrmDrmManagerClientDescriptorString)
- .transform();
- } else {
- return transformer(DrmManagerClient.class)
- .setClassDescriptor(DexItemFactory.androidDrmDrmManagerClientDescriptorString)
- .transform();
- }
+ .assertFailureWithErrorThatMatches(containsString("close should not be called"));
}
private static byte[] getTestRunner() throws IOException {
@@ -72,30 +92,6 @@
.transform();
}
- public static class DrmManagerClient {
- public boolean wasClosed = false;
-
- public void close() {
- TestRunner.doFail("close should not be called");
- }
-
- public void release() {
- wasClosed = true;
- }
- }
-
- public static class DrmManagerClientApiLevel24 {
- public boolean wasClosed = false;
-
- public void close() {
- wasClosed = true;
- }
-
- public void release() {
- TestRunner.doFail("release should not be called");
- }
- }
-
public static class TestRunner extends MiniAssert {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java
index 144d841..3584912 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MediaDrmBackportTest.java
@@ -4,12 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.compileAutoCloseableAndroidLibraryClasses;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.MediaDrm;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -22,15 +30,18 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ return getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
}
public MediaDrmBackportTest(TestParameters parameters) throws IOException {
super(
parameters,
- MediaDrmBackportTest.getMediaDrm(parameters),
- ImmutableList.of(
- MediaDrmBackportTest.getTestRunner(), MediaDrmBackportTest.getMediaDrm(parameters)));
+ DescriptorUtils.descriptorToJavaType(DexItemFactory.androidMediaMediaDrmDescriptorString),
+ ImmutableList.of(MediaDrmBackportTest.getTestRunner()));
// The constructor is used by the test and release has been available since API 18 and is the
// method close is rewritten to.
@@ -41,6 +52,27 @@
registerTarget(AndroidApiLevel.P, 1);
}
+ @Override
+ protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
+ super.configureProgram(builder);
+ if (builder.isJvmTestBuilder()) {
+ builder.addProgramClassFileData(getAutoCloseableAndroidClassData(parameters));
+ } else {
+ builder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
+ @Override
+ protected void configure(D8TestCompileResult builder) throws Exception {
+ if (parameters.isDexRuntime()) {
+ builder.addBootClasspathFiles(compileAutoCloseableAndroidLibraryClasses(this, parameters));
+ } else {
+ builder.addRunClasspathClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
@Test
public void testJvm() throws Exception {
parameters.assumeJvmTestParameters();
@@ -48,19 +80,7 @@
.apply(this::configureProgram)
.run(parameters.getRuntime(), getTestClassName())
// Fails when not desugared.
- .assertFailureWithErrorThatMatches(containsString("Failed: close should not be called"));
- }
-
- private static byte[] getMediaDrm(TestParameters parameters) throws IOException {
- if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.P)) {
- return transformer(MediaDrmApiLevel28.class)
- .setClassDescriptor(DexItemFactory.androidMediaMediaDrmDescriptorString)
- .transform();
- } else {
- return transformer(MediaDrm.class)
- .setClassDescriptor(DexItemFactory.androidMediaMediaDrmDescriptorString)
- .transform();
- }
+ .assertFailureWithErrorThatMatches(containsString("close should not be called"));
}
private static byte[] getTestRunner() throws IOException {
@@ -70,30 +90,6 @@
.transform();
}
- public static class MediaDrm {
- public boolean wasClosed = false;
-
- public void close() {
- TestRunner.doFail("close should not be called");
- }
-
- public void release() {
- wasClosed = true;
- }
- }
-
- public static class MediaDrmApiLevel28 {
- public boolean wasClosed = false;
-
- public void close() {
- wasClosed = true;
- }
-
- public void release() {
- TestRunner.doFail("release should not be called");
- }
- }
-
public static class TestRunner extends MiniAssert {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MediaMetadataRetrieverBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/MediaMetadataRetrieverBackportTest.java
index d2cb8f8..9b324ef 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/MediaMetadataRetrieverBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MediaMetadataRetrieverBackportTest.java
@@ -4,12 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.compileAutoCloseableAndroidLibraryClasses;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.MediaMetadataRetriever;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -22,16 +30,19 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ return getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
}
public MediaMetadataRetrieverBackportTest(TestParameters parameters) throws IOException {
super(
parameters,
- MediaMetadataRetrieverBackportTest.getMediaMetadataRetriever(parameters),
- ImmutableList.of(
- MediaMetadataRetrieverBackportTest.getTestRunner(),
- MediaMetadataRetrieverBackportTest.getMediaMetadataRetriever(parameters)));
+ DescriptorUtils.descriptorToJavaType(
+ DexItemFactory.androidMediaMediaMetadataRetrieverDescriptorString),
+ ImmutableList.of(MediaMetadataRetrieverBackportTest.getTestRunner()));
// The constructor is used by the test and release has been available since API 10 and is the
// method close is rewritten to.
@@ -42,6 +53,27 @@
registerTarget(AndroidApiLevel.Q, 1);
}
+ @Override
+ protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
+ super.configureProgram(builder);
+ if (builder.isJvmTestBuilder()) {
+ builder.addProgramClassFileData(getAutoCloseableAndroidClassData(parameters));
+ } else {
+ builder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
+ @Override
+ protected void configure(D8TestCompileResult builder) throws Exception {
+ if (parameters.isDexRuntime()) {
+ builder.addBootClasspathFiles(compileAutoCloseableAndroidLibraryClasses(this, parameters));
+ } else {
+ builder.addRunClasspathClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
@Test
public void testJvm() throws Exception {
parameters.assumeJvmTestParameters();
@@ -49,19 +81,7 @@
.apply(this::configureProgram)
.run(parameters.getRuntime(), getTestClassName())
// Fails when not desugared.
- .assertFailureWithErrorThatMatches(containsString("Failed: close should not be called"));
- }
-
- private static byte[] getMediaMetadataRetriever(TestParameters parameters) throws IOException {
- if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
- return transformer(MediaMetadataRetrieverApiLevel29.class)
- .setClassDescriptor(DexItemFactory.androidMediaMediaMetadataRetrieverDescriptorString)
- .transform();
- } else {
- return transformer(MediaMetadataRetriever.class)
- .setClassDescriptor(DexItemFactory.androidMediaMediaMetadataRetrieverDescriptorString)
- .transform();
- }
+ .assertFailureWithErrorThatMatches(containsString("close should not be called"));
}
private static byte[] getTestRunner() throws IOException {
@@ -72,30 +92,6 @@
.transform();
}
- public static class MediaMetadataRetriever {
- public boolean wasClosed = false;
-
- public void close() {
- TestRunner.doFail("close should not be called");
- }
-
- public void release() {
- wasClosed = true;
- }
- }
-
- public static class MediaMetadataRetrieverApiLevel29 {
- public boolean wasClosed = false;
-
- public void close() {
- wasClosed = true;
- }
-
- public void release() {
- TestRunner.doFail("release should not be called");
- }
- }
-
public static class TestRunner extends MiniAssert {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/TypedArrayBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/TypedArrayBackportTest.java
index 1b7e834..ab6ddb3 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/TypedArrayBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/TypedArrayBackportTest.java
@@ -4,12 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.compileAutoCloseableAndroidLibraryClasses;
+import static com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.getAutoCloseableAndroidClassData;
import static org.hamcrest.CoreMatchers.containsString;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.AutoCloseableAndroidLibraryFileData.TypedArray;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -22,16 +30,19 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ return getTestParameters()
+ .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
+ .withDexRuntimes()
+ .withAllApiLevelsAlsoForCf()
+ .build();
}
public TypedArrayBackportTest(TestParameters parameters) throws IOException {
super(
parameters,
- TypedArrayBackportTest.getTypedArray(parameters),
- ImmutableList.of(
- TypedArrayBackportTest.getTestRunner(),
- TypedArrayBackportTest.getTypedArray(parameters)));
+ DescriptorUtils.descriptorToJavaType(
+ DexItemFactory.androidContentResTypedArrayDescriptorString),
+ ImmutableList.of(TypedArrayBackportTest.getTestRunner()));
// The constructor is used by the test and recycle has been available since API 1 and is the
// method close is rewritten to.
@@ -42,6 +53,27 @@
registerTarget(AndroidApiLevel.S, 1);
}
+ @Override
+ protected void configureProgram(TestBuilder<?, ?> builder) throws Exception {
+ super.configureProgram(builder);
+ if (builder.isJvmTestBuilder()) {
+ builder.addProgramClassFileData(getAutoCloseableAndroidClassData(parameters));
+ } else {
+ builder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+ .addLibraryClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
+ @Override
+ protected void configure(D8TestCompileResult builder) throws Exception {
+ if (parameters.isDexRuntime()) {
+ builder.addBootClasspathFiles(compileAutoCloseableAndroidLibraryClasses(this, parameters));
+ } else {
+ builder.addRunClasspathClassFileData(getAutoCloseableAndroidClassData(parameters));
+ }
+ }
+
@Test
public void testJvm() throws Exception {
parameters.assumeJvmTestParameters();
@@ -49,19 +81,7 @@
.apply(this::configureProgram)
.run(parameters.getRuntime(), getTestClassName())
// Fails when not desugared.
- .assertFailureWithErrorThatMatches(containsString("Failed: close should not be called"));
- }
-
- private static byte[] getTypedArray(TestParameters parameters) throws IOException {
- if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.S)) {
- return transformer(TypedArrayAndroidApiLevel31.class)
- .setClassDescriptor(DexItemFactory.androidContentResTypedArrayDescriptorString)
- .transform();
- } else {
- return transformer(TypedArray.class)
- .setClassDescriptor(DexItemFactory.androidContentResTypedArrayDescriptorString)
- .transform();
- }
+ .assertFailureWithErrorThatMatches(containsString("close should not be called"));
}
private static byte[] getTestRunner() throws IOException {
@@ -72,30 +92,6 @@
.transform();
}
- public static class TypedArray {
- public boolean wasClosed = false;
-
- public void close() {
- TestRunner.doFail("close should not be called");
- }
-
- public void recycle() {
- wasClosed = true;
- }
- }
-
- public static class TypedArrayAndroidApiLevel31 {
- public boolean wasClosed = false;
-
- public void close() {
- wasClosed = true;
- }
-
- public void recycle() {
- TestRunner.doFail("recycle should not be called");
- }
- }
-
public static class TestRunner extends MiniAssert {
public static void main(String[] args) {
diff --git a/src/test/testbase/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/testbase/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index cdbf02f..f2c3ee2 100644
--- a/src/test/testbase/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/testbase/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -242,7 +242,6 @@
.compileWithExpectedDiagnostics(this::checkDiagnostics)
.apply(this::configure)
.inspect(this::assertDesugaring)
- .apply(this::configure)
.run(parameters.getRuntime(), testClassName)
.apply(runResultConsumer);
}
diff --git a/src/test/testbase/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java b/src/test/testbase/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
index da0c617..899a073 100644
--- a/src/test/testbase/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/testbase/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -155,6 +155,20 @@
return syntheticClass(reference, naming.TWR_CLOSE_RESOURCE, id);
}
+ public static ClassReference syntheticAutoCloseableDispatcherClass(
+ ClassReference classReference, int id) {
+ return syntheticClass(classReference, naming.AUTOCLOSEABLE_DISPATCHER, id);
+ }
+
+ public static ClassReference syntheticAutoCloseableForwarderClass(
+ ClassReference classReference, int id) {
+ return syntheticClass(classReference, naming.AUTOCLOSEABLE_FORWARDER, id);
+ }
+
+ public static ClassReference syntheticThrowIAEClass(ClassReference classReference, int id) {
+ return syntheticClass(classReference, naming.THROW_IAE, id);
+ }
+
public static MethodReference syntheticLambdaMethod(Class<?> clazz, int id, Method method) {
ClassReference syntheticHolder = syntheticLambdaClass(clazz, id);
MethodReference originalMethod = Reference.methodFromMethod(method);