Enable R8 partial in nest.dex tests

Change-Id: I16cd2446f7cf83470c36f9ba6e695de2a006c987
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index 207005d..1778fd4 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -122,6 +122,7 @@
     D8Command d8Command = d8Builder.makeD8Command(options.dexItemFactory());
     AndroidApp d8App = d8Command.getInputApp();
     InternalOptions d8Options = d8Command.getInternalOptions();
+    forwardOptions(d8Options);
     options.partialCompilationConfiguration.d8DexOptionsConsumer.accept(d8Options);
     R8PartialD8SubCompilationConfiguration subCompilationConfiguration =
         new R8PartialD8SubCompilationConfiguration(
@@ -213,6 +214,7 @@
         r8Builder.makeR8Command(options.dexItemFactory(), options.getProguardConfiguration());
     AndroidApp r8App = r8Command.getInputApp();
     InternalOptions r8Options = r8Command.getInternalOptions();
+    forwardOptions(r8Options);
     options.partialCompilationConfiguration.r8OptionsConsumer.accept(r8Options);
     r8Options.partialSubCompilationConfiguration =
         new R8PartialR8SubCompilationConfiguration(
@@ -301,4 +303,13 @@
       featureSplit.internalSetProgramResourceProviders(replacementProgramResourceProviders);
     }
   }
+
+  private void forwardOptions(InternalOptions subCompilationOptions) {
+    subCompilationOptions.emitNestAnnotationsInDex = options.emitNestAnnotationsInDex;
+    subCompilationOptions.emitRecordAnnotationsInDex = options.emitRecordAnnotationsInDex;
+    subCompilationOptions.emitPermittedSubclassesAnnotationsInDex =
+        options.emitPermittedSubclassesAnnotationsInDex;
+    subCompilationOptions.desugarState = options.desugarState;
+    subCompilationOptions.forceNestDesugaring = options.forceNestDesugaring;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 0185dc7..e8bc0b7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -1170,6 +1170,18 @@
     getNestMembersClassAttributes().forEach(member -> consumer.accept(member.getNestMember()));
   }
 
+  public void forEachNestMemberOnHost(
+      DexDefinitionSupplier definitions, Consumer<DexType> consumer) {
+    if (isNestHost()) {
+      forEachNestMember(consumer);
+    } else if (isNestMember()) {
+      DexClass host = definitions.definitionFor(getNestHost());
+      if (host != null) {
+        host.forEachNestMember(consumer);
+      }
+    }
+  }
+
   public NestHostClassAttribute getNestHostClassAttribute() {
     return nestHost;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
index 2cdb601..9874af7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/R8LibraryDesugaring.java
@@ -57,13 +57,14 @@
       Timing timing)
       throws ExecutionException {
     InternalOptions options = appView.options();
-    if (options.isDesugaring()
-        && options.getLibraryDesugaringOptions().isEnabled()
-        && options.getLibraryDesugaringOptions().isLirToLirLibraryDesugaringEnabled()
-        && options.isGeneratingDex()) {
-      new R8LibraryDesugaring(appView).run(executorService, timing);
-    } else {
-      assert !appView.options().apiModelingOptions().isLirToLirApiOutliningEnabled();
+    if (options.isDesugaring()) {
+      if (options.getLibraryDesugaringOptions().isEnabled()
+          && options.getLibraryDesugaringOptions().isLirToLirLibraryDesugaringEnabled()
+          && options.isGeneratingDex()) {
+        new R8LibraryDesugaring(appView).run(executorService, timing);
+      } else {
+        assert !appView.options().apiModelingOptions().isLirToLirApiOutliningEnabled();
+      }
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NestReducer.java b/src/main/java/com/android/tools/r8/ir/optimize/NestReducer.java
index ef9e445..c174687 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NestReducer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NestReducer.java
@@ -4,9 +4,8 @@
 
 package com.android.tools.r8.ir.optimize;
 
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMember;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -41,7 +40,7 @@
     timing.begin("NestReduction");
     if (appView.options().shouldDesugarNests()) {
       removeNests();
-    } else {
+    } else if (appView.options().enableNestReduction) {
       reduceNests(executorService);
     }
     appView.notifyOptimizationFinishedForTesting();
@@ -79,29 +78,27 @@
   }
 
   private void processNestHost(DexProgramClass clazz) {
+    BooleanBox nestHasNonProgramClass = new BooleanBox();
     BooleanBox nestHasPrivateMembers =
         new BooleanBox(IterableUtils.hasNext(clazz.members(DexEncodedMember::isPrivate)));
-    clazz
-        .getNestMembersClassAttributes()
-        .removeIf(
-            attribute -> {
-              DexProgramClass member =
-                  asProgramClassOrNull(appView.definitionFor(attribute.getNestMember(), clazz));
-              if (member == null) {
-                return true;
-              }
-              nestHasPrivateMembers.computeIfNotSet(
-                  () -> IterableUtils.hasNext(member.members(DexEncodedMember::isPrivate)));
-              return false;
-            });
-    if (nestHasPrivateMembers.isFalse() && appView.options().enableNestReduction) {
-      clazz.getNestMembersClassAttributes().clear();
+    clazz.removeNestMemberAttributes(
+        attribute -> {
+          DexClass member = appView.definitionFor(attribute.getNestMember(), clazz);
+          if (member == null) {
+            return true;
+          }
+          nestHasNonProgramClass.or(!member.isProgramClass());
+          nestHasPrivateMembers.computeIfNotSet(
+              () -> IterableUtils.hasNext(member.members(DexEncodedMember::isPrivate)));
+          return false;
+        });
+    if (nestHasNonProgramClass.isFalse() && nestHasPrivateMembers.isFalse()) {
+      clazz.clearNestMembers();
     }
   }
 
   private void processNestMember(DexProgramClass clazz) {
-    DexProgramClass hostClass =
-        asProgramClassOrNull(appView.definitionFor(clazz.getNestHost(), clazz));
+    DexClass hostClass = appView.definitionFor(clazz.getNestHost(), clazz);
     if (hostClass == null || !hostClass.isNestHost()) {
       clazz.clearNestHost();
     }
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index 543c132..e807f0d 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -294,12 +294,10 @@
   private static void clearDeadNestMembers(
       DexClass nestHost, Predicate<DexType> isLive, Function<DexType, DexClass> definition) {
     // null definition should raise a warning which is raised later on in Nest specific passes.
-    nestHost
-        .getNestMembersClassAttributes()
-        .removeIf(
-            nestMemberAttr ->
-                definition.apply(nestMemberAttr.getNestMember()) != null
-                    && !isLive.test(nestMemberAttr.getNestMember()));
+    nestHost.removeNestMemberAttributes(
+        nestMemberAttr ->
+            definition.apply(nestMemberAttr.getNestMember()) != null
+                && !isLive.test(nestMemberAttr.getNestMember()));
   }
 
   @SuppressWarnings("ReferenceEquality")
diff --git a/src/main/java/com/android/tools/r8/tracereferences/UseCollector.java b/src/main/java/com/android/tools/r8/tracereferences/UseCollector.java
index 2387e8e..c32979b 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/UseCollector.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/UseCollector.java
@@ -124,6 +124,7 @@
     }
     traceInnerClasses(clazz, classContext, getDefaultEventConsumer());
     traceKotlinMetadata(clazz, classContext, kotlinMetadataEventConsumer);
+    traceNest(clazz, classContext, getDefaultEventConsumer());
     traceSignature(clazz, classContext, getDefaultEventConsumer());
   }
 
@@ -168,6 +169,17 @@
     return true;
   }
 
+  private void traceNest(
+      DexProgramClass clazz,
+      DefinitionContext classContext,
+      UseCollectorEventConsumer eventConsumer) {
+    if (clazz.isNestMember()) {
+      addType(clazz.getNestHost(), classContext, eventConsumer);
+    }
+    clazz.forEachNestMemberOnHost(
+        appView, memberType -> addType(memberType, classContext, eventConsumer));
+  }
+
   private void traceSignature(
       DexProgramClass clazz,
       DefinitionContext classContext,
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 3ffe64c..c03e7fb 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -535,7 +535,7 @@
 
   // TODO(b/293591931): Remove this flag.
   // Flag to allow permitted subclasses annotations in DEX. See b/231930852 for context.
-  private final boolean emitPermittedSubclassesAnnotationsInDex =
+  public boolean emitPermittedSubclassesAnnotationsInDex =
       System.getProperty("com.android.tools.r8.emitPermittedSubclassesAnnotationsInDex") != null;
 
   private DumpInputFlags dumpInputFlags = DumpInputFlags.getDefault();
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeInterfaceTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeInterfaceTest.java
index 722eff7..7a0ac0d 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeInterfaceTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeInterfaceTest.java
@@ -4,13 +4,12 @@
 package com.android.tools.r8.jdk11.nest.dex;
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.utils.codeinspector.AssertUtils.assertFailsCompilation;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
 
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.TestBase;
+import com.android.tools.r8.PartialCompilationTestParameters;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
@@ -24,7 +23,6 @@
 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;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Label;
@@ -32,10 +30,10 @@
 import org.objectweb.asm.Opcodes;
 
 @RunWith(Parameterized.class)
-public class NestAttributesInDexRewriteInvokeInterfaceTest extends TestBase implements Opcodes {
+public class NestAttributesInDexRewriteInvokeInterfaceTest extends NestAttributesInDexTestBase
+    implements Opcodes {
 
-  @Parameter(0)
-  public TestParameters parameters;
+  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
@@ -43,10 +41,13 @@
         .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
         .withCfRuntimesStartingFromIncluding(CfVm.JDK11)
         .withApiLevelsStartingAtIncluding(AndroidApiLevel.N)
+        .withPartialCompilation()
         .build();
   }
 
-  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
+  public NestAttributesInDexRewriteInvokeInterfaceTest(TestParameters parameters) {
+    super(parameters);
+  }
 
   @Test
   public void testRuntime() throws Exception {
@@ -77,7 +78,7 @@
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForD8()
+    testForD8(parameters)
         .addProgramClassFileData(
             dumpHost(),
             dumpMember1(),
@@ -85,8 +86,7 @@
             dumpHostImpl(),
             dumpMember1Impl(),
             dumpMember2Impl())
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(
             inspector -> {
@@ -114,11 +114,10 @@
     assertFalse(parameters.getApiLevel().getLevel() > 35);
 
     Path host =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpHost())
             .addClasspathClassFileData(dumpMember1(), dumpMember2())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -130,11 +129,10 @@
             .writeToZip();
 
     Path member1 =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpMember1())
             .addClasspathClassFileData(dumpHost(), dumpMember2())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -146,11 +144,10 @@
             .writeToZip();
 
     Path member2 =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpMember2())
             .addClasspathClassFileData(dumpHost(), dumpMember1())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -162,15 +159,15 @@
             .writeToZip();
 
     Path impls =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpHostImpl(), dumpMember1Impl(), dumpMember2Impl())
             .addClasspathClassFileData(dumpHost(), dumpMember1(), dumpMember2Impl())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .writeToZip();
 
-    testForD8()
+    // Merge using D8.
+    testForD8(Backend.DEX, PartialCompilationTestParameters.NONE)
         .addProgramFiles(host, member1, member2, impls)
         .addClasspathClassFileData(dumpMember2())
         .setMinApi(parameters)
@@ -196,18 +193,15 @@
   }
 
   @Test
-  public void testD8WithoutMembersOnClasspath() {
+  public void testD8WithoutMembersOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpHost())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
@@ -217,18 +211,15 @@
   }
 
   @Test
-  public void testD8WithoutHostOnClasspath() {
+  public void testD8WithoutHostOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpMember1(), dumpMember2())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSpecialTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSpecialTest.java
index ebbda78..fb7f97c 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSpecialTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSpecialTest.java
@@ -10,7 +10,6 @@
 import static org.junit.Assert.assertFalse;
 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.utils.AndroidApiLevel;
@@ -22,24 +21,24 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
 @RunWith(Parameterized.class)
 public class NestAttributesInDexRewriteInvokeSpecialTest extends NestAttributesInDexTestBase {
 
-  @Parameter(0)
-  public TestParameters parameters;
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return TestBase.getTestParameters().withAllRuntimes().withAllApiLevels().build();
-  }
-
   private static final String EXPECTED_OUTPUT =
       StringUtils.lines(
           "m1", "m2", "m3", "s1", "s2", "m1", "m2", "m3", "s1", "s2", "s1", "s2", "s1", "s2");
 
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().withPartialCompilation().build();
+  }
+
+  public NestAttributesInDexRewriteInvokeSpecialTest(TestParameters parameters) {
+    super(parameters);
+  }
+
   @Test
   public void testRuntime() throws Exception {
     assumeTrue(parameters.isCfRuntime() && isRuntimeWithNestSupport(parameters.asCfRuntime()));
@@ -52,9 +51,8 @@
   @Test
   public void testD8() throws Exception {
     parameters.assumeDexRuntime();
-    testForD8()
+    testForD8(parameters)
         .addProgramClassesAndInnerClasses(NestHierachy.class)
-        .setMinApi(parameters)
         .compile()
         .run(parameters.getRuntime(), NestHierachy.class)
         .assertSuccessWithOutput(EXPECTED_OUTPUT);
@@ -166,10 +164,10 @@
     assumeTrue(parameters.getApiLevel().getLevel() >= 35);
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForD8()
+    testForD8(parameters)
         .addProgramClassesAndInnerClasses(NestHierachy.class)
         .setMinApi(AndroidApiLevel.U)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(
             inspector -> {
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSuperTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSuperTest.java
index a327fd8..0adf57e 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSuperTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeSuperTest.java
@@ -4,14 +4,13 @@
 package com.android.tools.r8.jdk11.nest.dex;
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.utils.codeinspector.AssertUtils.assertFailsCompilation;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.TestBase;
+import com.android.tools.r8.PartialCompilationTestParameters;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
@@ -24,7 +23,6 @@
 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;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Label;
@@ -32,17 +30,23 @@
 import org.objectweb.asm.Opcodes;
 
 @RunWith(Parameterized.class)
-public class NestAttributesInDexRewriteInvokeSuperTest extends TestBase implements Opcodes {
+public class NestAttributesInDexRewriteInvokeSuperTest extends NestAttributesInDexTestBase
+    implements Opcodes {
 
-  @Parameter(0)
-  public TestParameters parameters;
+  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+    return getTestParameters()
+        .withAllRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .withPartialCompilation()
+        .build();
   }
 
-  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
+  public NestAttributesInDexRewriteInvokeSuperTest(TestParameters parameters) {
+    super(parameters);
+  }
 
   @Test
   public void testRuntime() throws Exception {
@@ -70,10 +74,9 @@
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForD8()
+    testForD8(parameters)
         .addProgramClassFileData(dumpHost(), dumpMember(), dumpSubMember())
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(
             inspector -> {
@@ -105,11 +108,10 @@
     assertFalse(parameters.getApiLevel().getLevel() > 35);
 
     Path host =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpHost())
             .addClasspathClassFileData(dumpMember(), dumpSubMember())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -125,11 +127,10 @@
             .writeToZip();
 
     Path member =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpMember())
             .addClasspathClassFileData(dumpHost(), dumpSubMember())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -141,11 +142,10 @@
             .writeToZip();
 
     Path subMember =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpSubMember())
             .addClasspathClassFileData(dumpHost(), dumpMember())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -156,11 +156,12 @@
                 })
             .writeToZip();
 
-    testForD8()
+    // Merge using D8.
+    testForD8(Backend.DEX, PartialCompilationTestParameters.NONE)
         .addProgramFiles(host, member, subMember)
         .addClasspathClassFileData(dumpSubMember())
+        .apply(this::configureEmitNestAnnotationsInDex)
         .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
         .compile()
         .inspect(
             inspector -> {
@@ -186,18 +187,15 @@
   }
 
   @Test
-  public void testD8WithoutMembersOnClasspath() {
+  public void testD8WithoutMembersOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpHost())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
@@ -207,18 +205,15 @@
   }
 
   @Test
-  public void testD8WithoutHostOnClasspath() {
+  public void testD8WithoutHostOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpMember(), dumpSubMember())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeVirtualTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeVirtualTest.java
index ace8343..9b5bf8b 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeVirtualTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexRewriteInvokeVirtualTest.java
@@ -4,14 +4,13 @@
 package com.android.tools.r8.jdk11.nest.dex;
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.utils.codeinspector.AssertUtils.assertFailsCompilation;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.TestBase;
+import com.android.tools.r8.PartialCompilationTestParameters;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
@@ -24,7 +23,6 @@
 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;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Label;
@@ -32,17 +30,23 @@
 import org.objectweb.asm.Opcodes;
 
 @RunWith(Parameterized.class)
-public class NestAttributesInDexRewriteInvokeVirtualTest extends TestBase implements Opcodes {
+public class NestAttributesInDexRewriteInvokeVirtualTest extends NestAttributesInDexTestBase
+    implements Opcodes {
 
-  @Parameter(0)
-  public TestParameters parameters;
+  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+    return getTestParameters()
+        .withAllRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .withPartialCompilation()
+        .build();
   }
 
-  private static final List<String> EXPECTED_OUTPUT_LINES = ImmutableList.of("Hello, world!");
+  public NestAttributesInDexRewriteInvokeVirtualTest(TestParameters parameters) {
+    super(parameters);
+  }
 
   @Test
   public void testRuntime() throws Exception {
@@ -70,10 +74,9 @@
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForD8()
+    testForD8(parameters)
         .addProgramClassFileData(dumpHost(), dumpMember1(), dumpMember2())
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(
             inspector -> {
@@ -105,11 +108,10 @@
     assertFalse(parameters.getApiLevel().getLevel() > 35);
 
     Path host =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpHost())
             .addClasspathClassFileData(dumpMember1(), dumpMember2())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -125,11 +127,10 @@
             .writeToZip();
 
     Path member1 =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpMember1())
             .addClasspathClassFileData(dumpHost(), dumpMember2())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -141,11 +142,10 @@
             .writeToZip();
 
     Path member2 =
-        testForD8()
+        testForD8(parameters)
             .addProgramClassFileData(dumpMember2())
             .addClasspathClassFileData(dumpHost(), dumpMember1())
-            .setMinApi(parameters)
-            .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+            .apply(this::configureEmitNestAnnotationsInDex)
             .compile()
             .inspect(
                 inspector -> {
@@ -156,11 +156,12 @@
                 })
             .writeToZip();
 
-    testForD8()
+    // Merge using D8.
+    testForD8(Backend.DEX, PartialCompilationTestParameters.NONE)
         .addProgramFiles(host, member1, member2)
         .addClasspathClassFileData(dumpMember2())
         .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(
             inspector -> {
@@ -186,18 +187,15 @@
   }
 
   @Test
-  public void testD8WithoutMembersOnClasspath() {
+  public void testD8WithoutMembersOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpHost())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
@@ -207,18 +205,15 @@
   }
 
   @Test
-  public void testD8WithoutHostOnClasspath() {
+  public void testD8WithoutHostOnClasspath() throws Exception {
     parameters.assumeDexRuntime();
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8()
+            testForD8(parameters)
                 .addProgramClassFileData(dumpMember1(), dumpMember2())
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+                .apply(this::configureEmitNestAnnotationsInDex)
                 .compileWithExpectedDiagnostics(
                     diagnostics -> {
                       diagnostics.assertOnlyErrors();
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingFieldsTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingFieldsTest.java
index 19b0298..d2ed4a2 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingFieldsTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingFieldsTest.java
@@ -3,13 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jdk11.nest.dex;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.AnyOf.anyOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -18,7 +20,6 @@
 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;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.FieldVisitor;
@@ -30,21 +31,25 @@
 public class NestAttributesInDexShrinkingFieldsTest extends NestAttributesInDexTestBase
     implements Opcodes {
 
-  @Parameter() public TestParameters parameters;
+  private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+    return getTestParameters()
+        .withAllRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .withPartialCompilation()
+        .build();
   }
 
-  private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");
+  public NestAttributesInDexShrinkingFieldsTest(TestParameters parameters) {
+    super(parameters);
+  }
 
   @Test
-  public void testRuntime() throws Exception {
-    assumeTrue(
-        parameters.isCfRuntime()
-            && isRuntimeWithNestSupport(parameters.asCfRuntime())
-            && parameters.getApiLevel().isEqualTo(AndroidApiLevel.B));
+  public void testJvm() throws Exception {
+    parameters.assumeJvmTestParameters();
+    assumeTrue(isRuntimeWithNestSupport(parameters.asCfRuntime()));
     testForJvm(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -52,20 +57,42 @@
         .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
+  @Test
+  public void testD8() throws Exception {
+    parameters.assumeDexRuntime();
+    testForD8(parameters)
+        .addProgramClassFileData(
+            dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
+        .apply(this::configureEmitNestAnnotationsInDex)
+        .run(parameters.getRuntime(), "Host")
+        .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+  }
+
   private void inspect(CodeInspector inspector, boolean expectNestAttributes) {
     ClassSubject host = inspector.clazz("Host");
     ClassSubject member1 = inspector.clazz("Host$Member1");
     ClassSubject member2 = inspector.clazz("Host$Member2");
-    if (expectNestAttributes) {
-      assertEquals(
-          ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()),
-          host.getFinalNestMembersAttribute());
+    if (parameters.isRandomPartialCompilation()) {
+      assertThat(
+          host.getFinalNestMembersAttribute(),
+          anyOf(
+              equalTo(ImmutableList.of()),
+              equalTo(ImmutableList.of(member1.asTypeSubject())),
+              equalTo(ImmutableList.of(member2.asTypeSubject())),
+              equalTo(ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()))));
     } else {
-      assertEquals(0, host.getFinalNestMembersAttribute().size());
+      if (expectNestAttributes) {
+        assertEquals(
+            ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()),
+            host.getFinalNestMembersAttribute());
+      } else {
+        assertEquals(0, host.getFinalNestMembersAttribute().size());
+      }
+
+      TypeSubject expectedNestHostAttribute = expectNestAttributes ? host.asTypeSubject() : null;
+      assertEquals(expectedNestHostAttribute, member1.getFinalNestHostAttribute());
+      assertEquals(expectedNestHostAttribute, member2.getFinalNestHostAttribute());
     }
-    TypeSubject expectedNestHostAttribute = expectNestAttributes ? host.asTypeSubject() : null;
-    assertEquals(expectedNestHostAttribute, member1.getFinalNestHostAttribute());
-    assertEquals(expectedNestHostAttribute, member2.getFinalNestHostAttribute());
   }
 
   private void expectNestAttributes(CodeInspector inspector) {
@@ -82,16 +109,24 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
         .addKeepMainRule("Host")
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
-        .inspect(inspector -> assertEquals(1, inspector.allClasses().size()))
+        .inspectIf(
+            !parameters.isRandomPartialCompilation(),
+            inspector -> assertEquals(1, inspector.allClasses().size()))
         .run(parameters.getRuntime(), "Host")
-        .assertSuccessWithOutput(EXPECTED_OUTPUT);
+        .applyIf(
+            parameters.isRandomPartialCompilation(),
+            rr ->
+                rr.applyIf(
+                    rr.getExitCode() == 0,
+                    ignore -> rr.assertSuccessWithOutput(EXPECTED_OUTPUT),
+                    ignore -> rr.assertFailureWithErrorThatThrows(IllegalAccessError.class)),
+            rr -> rr.assertSuccessWithOutput(EXPECTED_OUTPUT));
   }
 
   @Test
@@ -100,11 +135,10 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule("Host")
         .addKeepClassAndMembersRules("Host", "Host$Member1", "Host$Member2")
         .compile()
@@ -122,11 +156,10 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PUBLIC), dumpMember1(ACC_PUBLIC), dumpMember2(ACC_PUBLIC))
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule("Host")
         .addKeepClassAndMembersRules("Host", "Host$Member1", "Host$Member2")
         .compile()
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingMethodsTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingMethodsTest.java
index 80c7b1b..f368942 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingMethodsTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexShrinkingMethodsTest.java
@@ -3,13 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jdk11.nest.dex;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.AnyOf.anyOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -18,7 +20,6 @@
 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;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Label;
@@ -29,21 +30,25 @@
 public class NestAttributesInDexShrinkingMethodsTest extends NestAttributesInDexTestBase
     implements Opcodes {
 
-  @Parameter() public TestParameters parameters;
+  private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+    return getTestParameters()
+        .withAllRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .withPartialCompilation()
+        .build();
   }
 
-  private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");
+  public NestAttributesInDexShrinkingMethodsTest(TestParameters parameters) {
+    super(parameters);
+  }
 
   @Test
-  public void testRuntime() throws Exception {
-    assumeTrue(
-        parameters.isCfRuntime()
-            && isRuntimeWithNestSupport(parameters.asCfRuntime())
-            && parameters.getApiLevel().isEqualTo(AndroidApiLevel.B));
+  public void testJvm() throws Exception {
+    parameters.assumeJvmTestParameters();
+    assumeTrue(isRuntimeWithNestSupport(parameters.asCfRuntime()));
     testForJvm(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
@@ -51,20 +56,42 @@
         .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
+  @Test
+  public void testD8() throws Exception {
+    parameters.assumeDexRuntime();
+    testForD8(parameters)
+        .addProgramClassFileData(
+            dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
+        .apply(this::configureEmitNestAnnotationsInDex)
+        .run(parameters.getRuntime(), "Host")
+        .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+  }
+
   private void inspect(CodeInspector inspector, boolean expectNestAttributes) {
     ClassSubject host = inspector.clazz("Host");
     ClassSubject member1 = inspector.clazz("Host$Member1");
     ClassSubject member2 = inspector.clazz("Host$Member2");
-    if (expectNestAttributes) {
-      assertEquals(
-          ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()),
-          host.getFinalNestMembersAttribute());
+    if (parameters.isRandomPartialCompilation()) {
+      assertThat(
+          host.getFinalNestMembersAttribute(),
+          anyOf(
+              equalTo(ImmutableList.of()),
+              equalTo(ImmutableList.of(member1.asTypeSubject())),
+              equalTo(ImmutableList.of(member2.asTypeSubject())),
+              equalTo(ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()))));
     } else {
-      assertEquals(0, host.getFinalNestMembersAttribute().size());
+      if (expectNestAttributes) {
+        assertEquals(
+            ImmutableList.of(member2.asTypeSubject(), member1.asTypeSubject()),
+            host.getFinalNestMembersAttribute());
+      } else {
+        assertEquals(0, host.getFinalNestMembersAttribute().size());
+      }
+
+      TypeSubject expectedNestHostAttribute = expectNestAttributes ? host.asTypeSubject() : null;
+      assertEquals(expectedNestHostAttribute, member1.getFinalNestHostAttribute());
+      assertEquals(expectedNestHostAttribute, member2.getFinalNestHostAttribute());
     }
-    TypeSubject expectedNestHostAttribute = expectNestAttributes ? host.asTypeSubject() : null;
-    assertEquals(expectedNestHostAttribute, member1.getFinalNestHostAttribute());
-    assertEquals(expectedNestHostAttribute, member2.getFinalNestHostAttribute());
   }
 
   private void expectNestAttributes(CodeInspector inspector) {
@@ -81,16 +108,24 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
         .addKeepMainRule("Host")
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
-        .inspect(inspector -> assertEquals(1, inspector.allClasses().size()))
+        .inspectIf(
+            !parameters.isRandomPartialCompilation(),
+            inspector -> assertEquals(1, inspector.allClasses().size()))
         .run(parameters.getRuntime(), "Host")
-        .assertSuccessWithOutput(EXPECTED_OUTPUT);
+        .applyIf(
+            parameters.isRandomPartialCompilation(),
+            rr ->
+                rr.applyIf(
+                    rr.getExitCode() == 0,
+                    ignore -> rr.assertSuccessWithOutput(EXPECTED_OUTPUT),
+                    ignore -> rr.assertFailureWithErrorThatThrows(IllegalAccessError.class)),
+            rr -> rr.assertSuccessWithOutput(EXPECTED_OUTPUT));
   }
 
   @Test
@@ -99,11 +134,10 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PRIVATE), dumpMember1(ACC_PRIVATE), dumpMember2(ACC_PRIVATE))
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule("Host")
         .addKeepClassAndMembersRules("Host", "Host$Member1", "Host$Member2")
         .compile()
@@ -121,11 +155,10 @@
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
     // TODO(b/247047415): Update test when a DEX VM natively supporting nests is added.
     assertFalse(parameters.getApiLevel().getLevel() > 35);
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(
             dumpHost(ACC_PUBLIC), dumpMember1(ACC_PUBLIC), dumpMember2(ACC_PUBLIC))
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule("Host")
         .addKeepClassAndMembersRules("Host", "Host$Member1", "Host$Member2")
         .compile()
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTest.java
index 7bd72ce..4122b8f 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTest.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.jdk11.nest.dex;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
@@ -32,18 +31,23 @@
 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;
 import org.objectweb.asm.Opcodes;
 
 @RunWith(Parameterized.class)
 public class NestAttributesInDexTest extends NestAttributesInDexTestBase {
 
-  @Parameter() public TestParameters parameters;
-
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+    return getTestParameters()
+        .withAllRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .withPartialCompilation()
+        .build();
+  }
+
+  public NestAttributesInDexTest(TestParameters parameters) {
+    super(parameters);
   }
 
   private static final String EXPECTED_OUTPUT =
@@ -95,6 +99,9 @@
   }
 
   private void inspect(CodeInspector inspector, boolean emitNestAnnotationsInDex) {
+    if (parameters.isRandomPartialCompilation()) {
+      return;
+    }
     ClassSubject host = inspector.clazz(Host.class);
     ClassSubject member1 = inspector.clazz(Member1.class);
     ClassSubject member2 = inspector.clazz(Member2.class);
@@ -114,13 +121,13 @@
   @Test
   public void testD8() throws Exception {
     parameters.assumeDexRuntime();
-    testForD8()
+    testForD8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addStrippedOuter(getClass())
+        .addStrippedOuter(AdditionalClassAPIs.class)
         .addClasspathClasses(AdditionalClassAPIs.class)
         .addProgramClasses(OtherHost.class)
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .compile()
         .inspect(inspector -> inspect(inspector, true))
         .run(parameters.getRuntime(), TestClass.class)
@@ -130,12 +137,11 @@
   @Test
   public void testD8NoDesugar() throws Exception {
     parameters.assumeDexRuntime();
-    testForD8(parameters.getBackend())
+    testForD8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addProgramClasses(OtherHost.class)
         .disableDesugaring()
-        .setMinApi(parameters)
-        .addOptionsModification(options -> assertFalse(options.emitNestAnnotationsInDex))
+        .apply(this::assertEmitNestAnnotationsInDexIsFalse)
         .compile()
         .inspect(inspector -> inspect(inspector, false))
         .run(parameters.getRuntime(), TestClass.class)
@@ -146,12 +152,12 @@
   public void testR8NoKeep() throws Exception {
     parameters.assumeR8TestParameters();
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addStrippedOuter(getClass())
+        .addStrippedOuter(AdditionalClassAPIs.class)
         .addProgramClasses(OtherHost.class)
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule(TestClass.class)
         .compile()
         // Don't expect any nest info. The classes Host, Member1, Member2 and OtherHost remains
@@ -166,12 +172,12 @@
   public void testR8KeepHost() throws Exception {
     parameters.assumeR8TestParameters();
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addStrippedOuter(getClass())
+        .addStrippedOuter(AdditionalClassAPIs.class)
         .addProgramClasses(OtherHost.class)
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule(TestClass.class)
         .addKeepClassRules(Host.class)
         .compile()
@@ -188,12 +194,12 @@
   public void testR8KeepMembers() throws Exception {
     parameters.assumeR8TestParameters();
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addStrippedOuter(getClass())
+        .addStrippedOuter(AdditionalClassAPIs.class)
         .addProgramClasses(OtherHost.class)
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule(TestClass.class)
         .addKeepClassRules(Member1.class, Member2.class)
         .compile()
@@ -210,12 +216,12 @@
   public void testR8KeepBoth() throws Exception {
     parameters.assumeR8TestParameters();
     assumeTrue(parameters.isDexRuntime() || isRuntimeWithNestSupport(parameters.asCfRuntime()));
-    testForR8(parameters.getBackend())
+    testForR8(parameters)
         .addProgramClassFileData(getTransformedClasses())
         .addStrippedOuter(getClass())
+        .addStrippedOuter(AdditionalClassAPIs.class)
         .addProgramClasses(OtherHost.class)
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
+        .apply(this::configureEmitNestAnnotationsInDex)
         .addKeepMainRule(TestClass.class)
         .addKeepClassRules(Host.class, Member1.class, Member2.class)
         .compile()
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTestBase.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTestBase.java
index 7a7b587..37a208e 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTestBase.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesInDexTestBase.java
@@ -3,7 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jdk11.nest.dex;
 
+import static org.junit.Assert.assertFalse;
+
+import com.android.tools.r8.SingleTestRunResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompilerBuilder;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime;
 import com.android.tools.r8.TestRuntime.CfRuntime;
 import com.android.tools.r8.TestRuntime.CfVm;
@@ -14,6 +19,39 @@
 @RunWith(Parameterized.class)
 public abstract class NestAttributesInDexTestBase extends TestBase {
 
+  protected TestParameters parameters;
+
+  public NestAttributesInDexTestBase(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  protected void assertEmitNestAnnotationsInDexIsFalse(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> builder) {
+    builder.applyIf(
+        parameters.getPartialCompilationTestParameters().isSome(),
+        b ->
+            b.addR8PartialOptionsModification(o -> assertFalse(o.emitNestAnnotationsInDex))
+                .addR8PartialD8OptionsModification(o -> assertFalse(o.emitNestAnnotationsInDex))
+                .addR8PartialR8OptionsModification(o -> assertFalse(o.emitNestAnnotationsInDex)),
+        b -> b.addOptionsModification(o -> assertFalse(o.emitNestAnnotationsInDex)));
+  }
+
+  protected void configureEmitNestAnnotationsInDex(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> builder) {
+    builder.applyIf(
+        parameters.getPartialCompilationTestParameters().isSome(),
+        b -> b.addR8PartialOptionsModification(o -> o.emitNestAnnotationsInDex = true),
+        b -> b.addOptionsModification(o -> o.emitNestAnnotationsInDex = true));
+  }
+
+  protected void configureForceNestDesugaring(
+      TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> builder) {
+    builder.applyIf(
+        parameters.getPartialCompilationTestParameters().isSome(),
+        b -> b.addR8PartialOptionsModification(o -> o.forceNestDesugaring = true),
+        b -> b.addOptionsModification(o -> o.forceNestDesugaring = true));
+  }
+
   protected boolean isRuntimeWithNestSupport(TestRuntime runtime) {
     if (runtime.isCf()) {
       return isRuntimeWithNestSupport(runtime.asCf());
diff --git a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesNotInDexWithForceNestDesugaringTest.java b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesNotInDexWithForceNestDesugaringTest.java
index 09c7ae3..2cc9d39 100644
--- a/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesNotInDexWithForceNestDesugaringTest.java
+++ b/src/test/java11/com/android/tools/r8/jdk11/nest/dex/NestAttributesNotInDexWithForceNestDesugaringTest.java
@@ -3,12 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jdk11.nest.dex;
 
+import static com.android.tools.r8.utils.codeinspector.AssertUtils.assertFailsCompilation;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentIf;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.jdk11.nest.dex.NestAttributesNotInDexWithForceNestDesugaringTest.Host.Member1;
@@ -23,31 +22,32 @@
 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 NestAttributesNotInDexWithForceNestDesugaringTest extends NestAttributesInDexTestBase {
 
-  @Parameter(0)
-  public TestParameters parameters;
-
-  @Parameter(1)
-  public boolean forceNestDesugaring;
+  private final boolean forceNestDesugaring;
 
   @Parameters(name = "{0}, forceNestDesugaring: {1}")
   public static List<Object[]> data() {
     return buildParameters(
-        getTestParameters().withDexRuntimesAndAllApiLevels().build(), BooleanUtils.values());
+        getTestParameters().withDexRuntimesAndAllApiLevels().withPartialCompilation().build(),
+        BooleanUtils.values());
+  }
+
+  public NestAttributesNotInDexWithForceNestDesugaringTest(
+      TestParameters parameters, boolean forceNestDesugaring) {
+    super(parameters);
+    this.forceNestDesugaring = forceNestDesugaring;
   }
 
   @Test
   public void testD8() throws Exception {
-    testForD8()
+    testForD8(parameters)
         .addProgramClassFileData(getTransformedClasses())
-        .setMinApi(parameters)
-        .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
-        .addOptionsModification(options -> options.forceNestDesugaring = forceNestDesugaring)
+        .apply(this::configureEmitNestAnnotationsInDex)
+        .applyIf(forceNestDesugaring, this::configureForceNestDesugaring)
         .compile()
         .inspect(
             inspector -> {
@@ -71,18 +71,15 @@
   }
 
   @Test
-  public void testD8NoDesugar() {
+  public void testD8NoDesugar() throws Exception {
     assumeTrue(forceNestDesugaring);
-    assertThrows(
-        CompilationFailedException.class,
+    assertFailsCompilation(
         () ->
-            testForD8(parameters.getBackend())
+            testForD8(parameters)
                 .addProgramClassFileData(getTransformedClasses())
                 .disableDesugaring()
-                .setMinApi(parameters)
-                .addOptionsModification(options -> options.emitNestAnnotationsInDex = true)
-                .addOptionsModification(
-                    options -> options.forceNestDesugaring = forceNestDesugaring)
+                .apply(this::configureEmitNestAnnotationsInDex)
+                .apply(this::configureForceNestDesugaring)
                 .compile());
   }
 
diff --git a/src/test/java17/com/android/tools/r8/jdk17/records/RecordOnlyReferencedFromCodeTest.java b/src/test/java17/com/android/tools/r8/jdk17/records/RecordOnlyReferencedFromCodeTest.java
index 9d70c53..1601300 100644
--- a/src/test/java17/com/android/tools/r8/jdk17/records/RecordOnlyReferencedFromCodeTest.java
+++ b/src/test/java17/com/android/tools/r8/jdk17/records/RecordOnlyReferencedFromCodeTest.java
@@ -28,11 +28,10 @@
 
   @Test
   public void testD8() throws Exception {
-    testForD8()
+    testForD8(parameters)
         .addInnerClassesAndStrippedOuter(getClass())
         .addLibraryFiles(ToolHelper.getMostRecentAndroidJar())
         .release()
-        .setMinApi(parameters)
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutputLines("false");
   }
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
index b32e58b..7deeb82 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
@@ -164,10 +164,12 @@
             + "Did you mean addD8PartialOptionsModification or addR8PartialOptionsModification?");
   }
 
+  @Override
   public R8PartialTestBuilder addR8PartialOptionsModification(Consumer<InternalOptions> consumer) {
     return super.addOptionsModification(consumer);
   }
 
+  @Override
   public R8PartialTestBuilder addR8PartialD8OptionsModification(
       Consumer<InternalOptions> consumer) {
     return super.addOptionsModification(
diff --git a/src/test/testbase/java/com/android/tools/r8/TestBase.java b/src/test/testbase/java/com/android/tools/r8/TestBase.java
index 62cd540..05a2f29 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestBase.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestBase.java
@@ -285,7 +285,7 @@
   }
 
   public D8TestBuilder testForD8() {
-    return testForD8(temp, Backend.DEX);
+    return testForD8(Backend.DEX);
   }
 
   public D8TestBuilder testForD8(Backend backend) {
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index d1d17d3..d7718cd 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -234,6 +234,16 @@
     return self();
   }
 
+  public T addR8PartialOptionsModification(Consumer<InternalOptions> optionsConsumer) {
+    // Intentionally empty. Overridden in R8PartialTestBuilder.
+    return self();
+  }
+
+  public T addR8PartialD8OptionsModification(Consumer<InternalOptions> optionsConsumer) {
+    // Intentionally empty. Overridden in R8PartialTestBuilder.
+    return self();
+  }
+
   public T addR8PartialR8OptionsModification(Consumer<InternalOptions> optionsConsumer) {
     // Intentionally empty. Overridden in R8PartialTestBuilder.
     return self();