Merge commit '84e54946701200c817f8dc2c9f1b76b16863fafc' into dev-release Change-Id: I91ab887ef076515c7036e4e1fdcfe7ad966dd68a
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);