Move Java 10 backport to Java 10 module

Bug: b/380808556
Change-Id: Ia9952e85ff7c84632624001af72e8938c2d7ca29
diff --git a/d8_r8/test_modules/tests_java_10/build.gradle.kts b/d8_r8/test_modules/tests_java_10/build.gradle.kts
index fa6f761..7663224 100644
--- a/d8_r8/test_modules/tests_java_10/build.gradle.kts
+++ b/d8_r8/test_modules/tests_java_10/build.gradle.kts
@@ -19,9 +19,21 @@
   }
   sourceCompatibility = JavaVersion.VERSION_1_10
   targetCompatibility = JavaVersion.VERSION_1_10
+  toolchain {
+    languageVersion = JavaLanguageVersion.of(JvmCompatibility.release)
+  }
 }
 
-dependencies { }
+val testbaseJavaCompileTask = projectTask("testbase", "compileJava")
+val testbaseDepsJarTask = projectTask("testbase", "depsJar")
+val mainCompileTask = projectTask("main", "compileJava")
+
+dependencies {
+  implementation(files(testbaseDepsJarTask.outputs.files.getSingleFile()))
+  implementation(testbaseJavaCompileTask.outputs.files)
+  implementation(mainCompileTask.outputs.files)
+  implementation(projectTask("main", "processResources").outputs.files)
+}
 
 // We just need to register the examples jars for it to be referenced by other modules.
 val buildExampleJars = buildExampleJars("examplesJava10")
@@ -29,9 +41,19 @@
 tasks {
   withType<JavaCompile> {
     dependsOn(gradle.includedBuild("shared").task(":downloadDeps"))
-    options.setFork(true)
-    options.forkOptions.memoryMaximumSize = "3g"
-    options.forkOptions.executable = getCompilerPath(Jdk.JDK_11)
+  }
+
+  withType<Test> {
+    notCompatibleWithConfigurationCache(
+      "Failure storing the configuration cache: cannot serialize object of type 'org.gradle.api.internal.project.DefaultProject', a subtype of 'org.gradle.api.Project', as these are not supported with the configuration cache")
+    TestingState.setUpTestingState(this)
+    systemProperty("TEST_DATA_LOCATION",
+      // This should be
+      //   layout.buildDirectory.dir("classes/java/test").get().toString()
+      // once the use of 'buildExampleJars' above is removed.
+                   getRoot().resolveAll("build", "test", "examplesJava10", "classes"))
+    systemProperty("TESTBASE_DATA_LOCATION",
+                   testbaseJavaCompileTask.outputs.files.getAsPath().split(File.pathSeparator)[0])
   }
 }
 
diff --git a/d8_r8/test_modules/tests_java_10/settings.gradle.kts b/d8_r8/test_modules/tests_java_10/settings.gradle.kts
index c1ca87a..f2e1c0d 100644
--- a/d8_r8/test_modules/tests_java_10/settings.gradle.kts
+++ b/d8_r8/test_modules/tests_java_10/settings.gradle.kts
@@ -23,4 +23,7 @@
 
 rootProject.name = "tests_java_10"
 val root = rootProject.projectDir.parentFile.parentFile
+
 includeBuild(root.resolve("shared"))
+includeBuild(root.resolve("main"))
+includeBuild(root.resolve("test_modules").resolve("testbase"))
diff --git a/src/test/examplesJava10/backport/ListBackportJava10Main.java b/src/test/examplesJava10/backport/ListBackportJava10Main.java
deleted file mode 100644
index 376f67a..0000000
--- a/src/test/examplesJava10/backport/ListBackportJava10Main.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class ListBackportJava10Main {
-
-  public static void main(String[] args) {
-    testCopyOf();
-  }
-
-  private static void testCopyOf() {
-    Object anObject0 = new Object();
-    Object anObject1 = new Object();
-    List<Object> original = Arrays.asList(anObject0, anObject1);
-    List<Object> copy = List.copyOf(original);
-    assertEquals(2, copy.size());
-    assertEquals(original, copy);
-    assertSame(anObject0, copy.get(0));
-    assertSame(anObject1, copy.get(1));
-    assertMutationNotAllowed(copy);
-
-    // Mutate the original backing collection and ensure it's not reflected in copy.
-    original.set(0, new Object());
-    assertSame(anObject0, copy.get(0));
-
-    try {
-      List.copyOf(null);
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-    try {
-      List.copyOf(Arrays.asList(1, null, 2));
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  private static void assertMutationNotAllowed(List<Object> ofObject) {
-    try {
-      ofObject.add(new Object());
-      throw new AssertionError();
-    } catch (UnsupportedOperationException expected) {
-    }
-    try {
-      ofObject.set(0, new Object());
-      throw new AssertionError();
-    } catch (UnsupportedOperationException expected) {
-    }
-  }
-
-  private static void assertSame(Object expected, Object actual) {
-    if (expected != actual) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/examplesJava10/backport/ListBackportJava10Test.java b/src/test/examplesJava10/backport/ListBackportJava10Test.java
new file mode 100644
index 0000000..f8abd84
--- /dev/null
+++ b/src/test/examplesJava10/backport/ListBackportJava10Test.java
@@ -0,0 +1,101 @@
+// Copyright (c) 2019, 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 backport;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ListBackportJava10Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
+        .withDexRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .build();
+  }
+
+  public ListBackportJava10Test(TestParameters parameters) {
+    super(parameters, List.class, ListBackportJava10Main.class);
+    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+    // an actual API level, migrate these tests to ListBackportTest.
+
+    // Available since API 1 and used to test created lists.
+    ignoreInvokes("add");
+    ignoreInvokes("get");
+    ignoreInvokes("set");
+    ignoreInvokes("size");
+
+    // List.copyOf added in API 31.
+    registerTarget(AndroidApiLevel.S, 3);
+  }
+
+  public static class ListBackportJava10Main {
+
+    public static void main(String[] args) {
+      testCopyOf();
+    }
+
+    private static void testCopyOf() {
+      Object anObject0 = new Object();
+      Object anObject1 = new Object();
+      List<Object> original = Arrays.asList(anObject0, anObject1);
+      List<Object> copy = List.copyOf(original);
+      assertEquals(2, copy.size());
+      assertEquals(original, copy);
+      assertSame(anObject0, copy.get(0));
+      assertSame(anObject1, copy.get(1));
+      assertMutationNotAllowed(copy);
+
+      // Mutate the original backing collection and ensure it's not reflected in copy.
+      original.set(0, new Object());
+      assertSame(anObject0, copy.get(0));
+
+      try {
+        List.copyOf(null);
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+      try {
+        List.copyOf(Arrays.asList(1, null, 2));
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+    }
+
+    private static void assertMutationNotAllowed(List<Object> ofObject) {
+      try {
+        ofObject.add(new Object());
+        throw new AssertionError();
+      } catch (UnsupportedOperationException expected) {
+      }
+      try {
+        ofObject.set(0, new Object());
+        throw new AssertionError();
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+
+    private static void assertSame(Object expected, Object actual) {
+      if (expected != actual) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
+}
diff --git a/src/test/examplesJava10/backport/MapBackportJava10Main.java b/src/test/examplesJava10/backport/MapBackportJava10Main.java
deleted file mode 100644
index 95413e9..0000000
--- a/src/test/examplesJava10/backport/MapBackportJava10Main.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class MapBackportJava10Main {
-
-  public static void main(String[] args) {
-    testCopyOf();
-  }
-
-  private static void testCopyOf() {
-    Object key0 = new Object();
-    Object value0 = new Object();
-    Object key1 = new Object();
-    Object value1 = new Object();
-    Map<Object, Object> original = new HashMap<>();
-    original.put(key0, value0);
-    original.put(key1, value1);
-    Map<Object, Object> copy = Map.copyOf(original);
-    assertEquals(2, copy.size());
-    assertEquals(original, copy);
-    assertSame(value0, copy.get(key0));
-    assertSame(value1, copy.get(key1));
-    assertMutationNotAllowed(copy);
-
-    // Mutate the original backing collection and ensure it's not reflected in copy.
-    original.put(key0, new Object());
-    assertSame(value0, copy.get(key0));
-
-    try {
-      Map.copyOf(null);
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-    try {
-      Map<Object, Object> map = new HashMap<>();
-      map.put(null, new Object());
-      Map.copyOf(map);
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-    try {
-      Map<Object, Object> map = new HashMap<>();
-      map.put(new Object(), null);
-      Map.copyOf(map);
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  private static void assertMutationNotAllowed(Map<Object, Object> ofObject) {
-    try {
-      ofObject.put(new Object(), new Object());
-      throw new AssertionError();
-    } catch (UnsupportedOperationException expected) {
-    }
-    for (Map.Entry<Object, Object> entry : ofObject.entrySet()) {
-      try {
-        entry.setValue(new Object());
-        throw new AssertionError();
-      } catch (UnsupportedOperationException expected) {
-      }
-    }
-  }
-
-  private static void assertSame(Object expected, Object actual) {
-    if (expected != actual) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/examplesJava10/backport/MapBackportJava10Test.java b/src/test/examplesJava10/backport/MapBackportJava10Test.java
new file mode 100644
index 0000000..fa9864e
--- /dev/null
+++ b/src/test/examplesJava10/backport/MapBackportJava10Test.java
@@ -0,0 +1,116 @@
+// Copyright (c) 2019, 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 backport;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class MapBackportJava10Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
+        .withDexRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .build();
+  }
+
+  public MapBackportJava10Test(TestParameters parameters) {
+    super(parameters, Map.class, MapBackportJava10Main.class);
+    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+    // an actual API level, migrate these tests to MapBackportTest.
+
+    // Available since API 1 and used to test created maps.
+    ignoreInvokes("entrySet");
+    ignoreInvokes("get");
+    ignoreInvokes("put");
+    ignoreInvokes("size");
+
+    // Map.copyOf added in API 31.
+    registerTarget(AndroidApiLevel.S, 4);
+  }
+
+  public static class MapBackportJava10Main {
+
+    public static void main(String[] args) {
+      testCopyOf();
+    }
+
+    private static void testCopyOf() {
+      Object key0 = new Object();
+      Object value0 = new Object();
+      Object key1 = new Object();
+      Object value1 = new Object();
+      Map<Object, Object> original = new HashMap<>();
+      original.put(key0, value0);
+      original.put(key1, value1);
+      Map<Object, Object> copy = Map.copyOf(original);
+      assertEquals(2, copy.size());
+      assertEquals(original, copy);
+      assertSame(value0, copy.get(key0));
+      assertSame(value1, copy.get(key1));
+      assertMutationNotAllowed(copy);
+
+      // Mutate the original backing collection and ensure it's not reflected in copy.
+      original.put(key0, new Object());
+      assertSame(value0, copy.get(key0));
+
+      try {
+        Map.copyOf(null);
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+      try {
+        Map<Object, Object> map = new HashMap<>();
+        map.put(null, new Object());
+        Map.copyOf(map);
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+      try {
+        Map<Object, Object> map = new HashMap<>();
+        map.put(new Object(), null);
+        Map.copyOf(map);
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+    }
+
+    private static void assertMutationNotAllowed(Map<Object, Object> ofObject) {
+      try {
+        ofObject.put(new Object(), new Object());
+        throw new AssertionError();
+      } catch (UnsupportedOperationException expected) {
+      }
+      for (Map.Entry<Object, Object> entry : ofObject.entrySet()) {
+        try {
+          entry.setValue(new Object());
+          throw new AssertionError();
+        } catch (UnsupportedOperationException expected) {
+        }
+      }
+    }
+
+    private static void assertSame(Object expected, Object actual) {
+      if (expected != actual) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
+}
diff --git a/src/test/examplesJava10/backport/OptionalBackportJava10Main.java b/src/test/examplesJava10/backport/OptionalBackportJava10Main.java
deleted file mode 100644
index 3d2c919..0000000
--- a/src/test/examplesJava10/backport/OptionalBackportJava10Main.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.NoSuchElementException;
-import java.util.Optional;
-
-public final class OptionalBackportJava10Main {
-
-  public static void main(String[] args) {
-    testOrElseThrow();
-  }
-
-  private static void testOrElseThrow() {
-    Optional<String> present = Optional.of("hey");
-    assertEquals("hey", present.orElseThrow());
-
-    Optional<String> absent = Optional.empty();
-    try {
-      throw new AssertionError(absent.orElseThrow());
-    } catch (NoSuchElementException expected) {
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava10Test.java b/src/test/examplesJava10/backport/OptionalBackportJava10Test.java
similarity index 60%
rename from src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava10Test.java
rename to src/test/examplesJava10/backport/OptionalBackportJava10Test.java
index 956a2fb..86165e5 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/OptionalBackportJava10Test.java
+++ b/src/test/examplesJava10/backport/OptionalBackportJava10Test.java
@@ -2,17 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+package backport;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.NoSuchElementException;
 import java.util.Optional;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -30,11 +27,8 @@
         .build();
   }
 
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
   public OptionalBackportJava10Test(TestParameters parameters) {
-    super(parameters, Optional.class, TEST_JAR, "backport.OptionalBackportJava10Main");
+    super(parameters, Optional.class, OptionalBackportJava10Main.class);
     // Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
     // Java 11 move these tests to OptionalBackportTest (out of examplesJava10).
 
@@ -45,4 +39,28 @@
 
     registerTarget(AndroidApiLevel.T, 2);
   }
+
+  public static class OptionalBackportJava10Main {
+
+    public static void main(String[] args) {
+      testOrElseThrow();
+    }
+
+    private static void testOrElseThrow() {
+      Optional<String> present = Optional.of("hey");
+      assertEquals("hey", present.orElseThrow());
+
+      Optional<String> absent = Optional.empty();
+      try {
+        throw new AssertionError(absent.orElseThrow());
+      } catch (NoSuchElementException expected) {
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
 }
diff --git a/src/test/examplesJava10/backport/OptionalDoubleBackportJava10Main.java b/src/test/examplesJava10/backport/OptionalDoubleBackportJava10Main.java
deleted file mode 100644
index 1c27538..0000000
--- a/src/test/examplesJava10/backport/OptionalDoubleBackportJava10Main.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.NoSuchElementException;
-import java.util.OptionalDouble;
-
-public final class OptionalDoubleBackportJava10Main {
-
-  public static void main(String[] args) {
-    testOrElseThrow();
-  }
-
-  private static void testOrElseThrow() {
-    OptionalDouble present = OptionalDouble.of(2d);
-    assertEquals(2d, present.orElseThrow());
-
-    OptionalDouble absent = OptionalDouble.empty();
-    try {
-      throw new AssertionError(absent.orElseThrow());
-    } catch (NoSuchElementException expected) {
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava10Test.java b/src/test/examplesJava10/backport/OptionalDoubleBackportJava10Test.java
similarity index 60%
rename from src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava10Test.java
rename to src/test/examplesJava10/backport/OptionalDoubleBackportJava10Test.java
index 794e049..3f78ec2 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/OptionalDoubleBackportJava10Test.java
+++ b/src/test/examplesJava10/backport/OptionalDoubleBackportJava10Test.java
@@ -2,17 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+package backport;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.NoSuchElementException;
 import java.util.OptionalDouble;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -30,11 +27,8 @@
         .build();
   }
 
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
   public OptionalDoubleBackportJava10Test(TestParameters parameters) {
-    super(parameters, OptionalDouble.class, TEST_JAR, "backport.OptionalDoubleBackportJava10Main");
+    super(parameters, OptionalDouble.class, OptionalDoubleBackportJava10Main.class);
     // Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
     // Java 11 move these tests to OptionalBackportTest (out of examplesJava10).
 
@@ -45,4 +39,28 @@
 
     registerTarget(AndroidApiLevel.T, 2);
   }
+
+  public static class OptionalDoubleBackportJava10Main {
+
+    public static void main(String[] args) {
+      testOrElseThrow();
+    }
+
+    private static void testOrElseThrow() {
+      OptionalDouble present = OptionalDouble.of(2d);
+      assertEquals(2d, present.orElseThrow());
+
+      OptionalDouble absent = OptionalDouble.empty();
+      try {
+        throw new AssertionError(absent.orElseThrow());
+      } catch (NoSuchElementException expected) {
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
 }
diff --git a/src/test/examplesJava10/backport/OptionalIntBackportJava10Main.java b/src/test/examplesJava10/backport/OptionalIntBackportJava10Main.java
deleted file mode 100644
index 06c85f5..0000000
--- a/src/test/examplesJava10/backport/OptionalIntBackportJava10Main.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.NoSuchElementException;
-import java.util.OptionalInt;
-
-public final class OptionalIntBackportJava10Main {
-
-  public static void main(String[] args) {
-    testOrElseThrow();
-  }
-
-  private static void testOrElseThrow() {
-    OptionalInt present = OptionalInt.of(2);
-    assertEquals(2, present.orElseThrow());
-
-    OptionalInt absent = OptionalInt.empty();
-    try {
-      throw new AssertionError(absent.orElseThrow());
-    } catch (NoSuchElementException expected) {
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava10Test.java b/src/test/examplesJava10/backport/OptionalIntBackportJava10Test.java
similarity index 61%
rename from src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava10Test.java
rename to src/test/examplesJava10/backport/OptionalIntBackportJava10Test.java
index ab44630..1e2f17a 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/OptionalIntBackportJava10Test.java
+++ b/src/test/examplesJava10/backport/OptionalIntBackportJava10Test.java
@@ -2,17 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+package backport;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.NoSuchElementException;
 import java.util.OptionalInt;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -30,11 +27,8 @@
         .build();
   }
 
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
   public OptionalIntBackportJava10Test(TestParameters parameters) {
-    super(parameters, OptionalInt.class, TEST_JAR, "backport.OptionalIntBackportJava10Main");
+    super(parameters, OptionalInt.class, OptionalIntBackportJava10Main.class);
     // Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
     // Java 11 move these tests to OptionalBackportTest (out of examplesJava10).
 
@@ -45,4 +39,28 @@
 
     registerTarget(AndroidApiLevel.T, 2);
   }
+
+  public static class OptionalIntBackportJava10Main {
+
+    public static void main(String[] args) {
+      testOrElseThrow();
+    }
+
+    private static void testOrElseThrow() {
+      OptionalInt present = OptionalInt.of(2);
+      assertEquals(2, present.orElseThrow());
+
+      OptionalInt absent = OptionalInt.empty();
+      try {
+        throw new AssertionError(absent.orElseThrow());
+      } catch (NoSuchElementException expected) {
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
 }
diff --git a/src/test/examplesJava10/backport/OptionalLongBackportJava10Main.java b/src/test/examplesJava10/backport/OptionalLongBackportJava10Main.java
deleted file mode 100644
index e92b9a5..0000000
--- a/src/test/examplesJava10/backport/OptionalLongBackportJava10Main.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.NoSuchElementException;
-import java.util.OptionalLong;
-
-public final class OptionalLongBackportJava10Main {
-
-  public static void main(String[] args) {
-    testOrElseThrow();
-  }
-
-  private static void testOrElseThrow() {
-    OptionalLong present = OptionalLong.of(2L);
-    assertEquals(2L, present.orElseThrow());
-
-    OptionalLong absent = OptionalLong.empty();
-    try {
-      throw new AssertionError(absent.orElseThrow());
-    } catch (NoSuchElementException expected) {
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava10Test.java b/src/test/examplesJava10/backport/OptionalLongBackportJava10Test.java
similarity index 61%
rename from src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava10Test.java
rename to src/test/examplesJava10/backport/OptionalLongBackportJava10Test.java
index 5621a3c..4c0ffe3 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/OptionalLongBackportJava10Test.java
+++ b/src/test/examplesJava10/backport/OptionalLongBackportJava10Test.java
@@ -2,17 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+package backport;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.NoSuchElementException;
 import java.util.OptionalLong;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -30,11 +27,8 @@
         .build();
   }
 
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
   public OptionalLongBackportJava10Test(TestParameters parameters) {
-    super(parameters, OptionalLong.class, TEST_JAR, "backport.OptionalLongBackportJava10Main");
+    super(parameters, OptionalLong.class, OptionalLongBackportJava10Main.class);
     // Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
     // Java 11 move these tests to OptionalBackportTest (out of examplesJava10).
 
@@ -45,4 +39,28 @@
 
     registerTarget(AndroidApiLevel.T, 2);
   }
+
+  public static class OptionalLongBackportJava10Main {
+
+    public static void main(String[] args) {
+      testOrElseThrow();
+    }
+
+    private static void testOrElseThrow() {
+      OptionalLong present = OptionalLong.of(2L);
+      assertEquals(2L, present.orElseThrow());
+
+      OptionalLong absent = OptionalLong.empty();
+      try {
+        throw new AssertionError(absent.orElseThrow());
+      } catch (NoSuchElementException expected) {
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
 }
diff --git a/src/test/examplesJava10/backport/SetBackportJava10Main.java b/src/test/examplesJava10/backport/SetBackportJava10Main.java
deleted file mode 100644
index b8fb356..0000000
--- a/src/test/examplesJava10/backport/SetBackportJava10Main.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2019, 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 backport;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class SetBackportJava10Main {
-
-  public static void main(String[] args) {
-    testCopyOf();
-  }
-
-  private static void testCopyOf() {
-    Object anObject0 = new Object();
-    Object anObject1 = new Object();
-    List<Object> original = Arrays.asList(anObject0, anObject1);
-    Set<Object> copy = Set.copyOf(original);
-    assertEquals(2, copy.size());
-    assertEquals(new HashSet<>(original), copy);
-    assertTrue(copy.contains(anObject0));
-    assertTrue(copy.contains(anObject1));
-    assertMutationNotAllowed(copy);
-
-    // Mutate the original backing collection and ensure it's not reflected in copy.
-    Object newObject = new Object();
-    original.set(0, newObject);
-    assertFalse(copy.contains(newObject));
-
-    // Ensure duplicates are allowed and are de-duped.
-    assertEquals(Set.of(1, 2), Set.copyOf(List.of(1, 2, 1, 2)));
-
-    try {
-      Set.copyOf(null);
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-    try {
-      Set.copyOf(Arrays.asList(1, null, 2));
-      throw new AssertionError();
-    } catch (NullPointerException expected) {
-    }
-  }
-
-  private static void assertMutationNotAllowed(Set<Object> ofObject) {
-    try {
-      ofObject.add(new Object());
-      throw new AssertionError();
-    } catch (UnsupportedOperationException expected) {
-    }
-  }
-
-  private static void assertTrue(boolean value) {
-    if (!value) {
-      throw new AssertionError("Expected <true> but was <false>");
-    }
-  }
-
-  private static void assertFalse(boolean value) {
-    if (value) {
-      throw new AssertionError("Expected <false> but was <true>");
-    }
-  }
-
-  private static void assertEquals(Object expected, Object actual) {
-    if (expected != actual && !expected.equals(actual)) {
-      throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
-    }
-  }
-}
diff --git a/src/test/examplesJava10/backport/SetBackportJava10Test.java b/src/test/examplesJava10/backport/SetBackportJava10Test.java
new file mode 100644
index 0000000..8a4ffee
--- /dev/null
+++ b/src/test/examplesJava10/backport/SetBackportJava10Test.java
@@ -0,0 +1,109 @@
+// Copyright (c) 2019, 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 backport;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.desugar.backports.AbstractBackportTest;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SetBackportJava10Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
+        .withDexRuntimes()
+        .withAllApiLevelsAlsoForCf()
+        .build();
+  }
+
+  public SetBackportJava10Test(TestParameters parameters) {
+    super(parameters, Set.class, SetBackportJava10Main.class);
+    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+    // an actual API level, migrate these tests to SetBackportTest.
+
+    // Available since API 1 and used to test created sets.
+    ignoreInvokes("add");
+    ignoreInvokes("contains");
+    ignoreInvokes("size");
+
+    // Set.of added in API 30
+    registerTarget(AndroidApiLevel.R, 1);
+    // Set.copyOf added in API 31
+    registerTarget(AndroidApiLevel.S, 5);
+  }
+
+  public static class SetBackportJava10Main {
+
+    public static void main(String[] args) {
+      testCopyOf();
+    }
+
+    private static void testCopyOf() {
+      Object anObject0 = new Object();
+      Object anObject1 = new Object();
+      List<Object> original = Arrays.asList(anObject0, anObject1);
+      Set<Object> copy = Set.copyOf(original);
+      assertEquals(2, copy.size());
+      assertEquals(new HashSet<>(original), copy);
+      assertTrue(copy.contains(anObject0));
+      assertTrue(copy.contains(anObject1));
+      assertMutationNotAllowed(copy);
+
+      // Mutate the original backing collection and ensure it's not reflected in copy.
+      Object newObject = new Object();
+      original.set(0, newObject);
+      assertFalse(copy.contains(newObject));
+
+      // Ensure duplicates are allowed and are de-duped.
+      assertEquals(Set.of(1, 2), Set.copyOf(List.of(1, 2, 1, 2)));
+
+      try {
+        Set.copyOf(null);
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+      try {
+        Set.copyOf(Arrays.asList(1, null, 2));
+        throw new AssertionError();
+      } catch (NullPointerException expected) {
+      }
+    }
+
+    private static void assertMutationNotAllowed(Set<Object> ofObject) {
+      try {
+        ofObject.add(new Object());
+        throw new AssertionError();
+      } catch (UnsupportedOperationException expected) {
+      }
+    }
+
+    private static void assertTrue(boolean value) {
+      if (!value) {
+        throw new AssertionError("Expected <true> but was <false>");
+      }
+    }
+
+    private static void assertFalse(boolean value) {
+      if (value) {
+        throw new AssertionError("Expected <false> but was <true>");
+      }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+      if (expected != actual && !expected.equals(actual)) {
+        throw new AssertionError("Expected <" + expected + "> but was <" + actual + ">");
+      }
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava10Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava10Test.java
deleted file mode 100644
index 0f63b03..0000000
--- a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava10Test.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class ListBackportJava10Test extends AbstractBackportTest {
-  @Parameters(name = "{0}")
-  public static Iterable<?> data() {
-    return getTestParameters()
-        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
-        .withDexRuntimes()
-        .withAllApiLevelsAlsoForCf()
-        .build();
-  }
-
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
-  public ListBackportJava10Test(TestParameters parameters) {
-    super(parameters, List.class, TEST_JAR, "backport.ListBackportJava10Main");
-    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
-    // an actual API level, migrate these tests to ListBackportTest.
-
-    // Available since API 1 and used to test created lists.
-    ignoreInvokes("add");
-    ignoreInvokes("get");
-    ignoreInvokes("set");
-    ignoreInvokes("size");
-
-    // List.copyOf added in API 31.
-    registerTarget(AndroidApiLevel.S, 3);
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava10Test.java b/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava10Test.java
deleted file mode 100644
index 19c89e5..0000000
--- a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava10Test.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Map;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class MapBackportJava10Test extends AbstractBackportTest {
-  @Parameters(name = "{0}")
-  public static Iterable<?> data() {
-    return getTestParameters()
-        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
-        .withDexRuntimes()
-        .withAllApiLevelsAlsoForCf()
-        .build();
-  }
-
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
-  public MapBackportJava10Test(TestParameters parameters) {
-    super(parameters, Map.class, TEST_JAR, "backport.MapBackportJava10Main");
-    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
-    // an actual API level, migrate these tests to MapBackportTest.
-
-    // Available since API 1 and used to test created maps.
-    ignoreInvokes("entrySet");
-    ignoreInvokes("get");
-    ignoreInvokes("put");
-    ignoreInvokes("size");
-
-    // Map.copyOf added in API 31.
-    registerTarget(AndroidApiLevel.S, 4);
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava10Test.java b/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava10Test.java
deleted file mode 100644
index ec22ac6..0000000
--- a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava10Test.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.desugar.backports;
-
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Set;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class SetBackportJava10Test extends AbstractBackportTest {
-  @Parameters(name = "{0}")
-  public static Iterable<?> data() {
-    return getTestParameters()
-        .withCfRuntimesStartingFromIncluding(CfVm.JDK10)
-        .withDexRuntimes()
-        .withAllApiLevelsAlsoForCf()
-        .build();
-  }
-
-  private static final Path TEST_JAR =
-      Paths.get(ToolHelper.EXAMPLES_JAVA10_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
-
-  public SetBackportJava10Test(TestParameters parameters) {
-    super(parameters, Set.class, TEST_JAR, "backport.SetBackportJava10Main");
-    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
-    // an actual API level, migrate these tests to SetBackportTest.
-
-    // Available since API 1 and used to test created sets.
-    ignoreInvokes("add");
-    ignoreInvokes("contains");
-    ignoreInvokes("size");
-
-    // Set.of added in API 30
-    registerTarget(AndroidApiLevel.R, 1);
-    // Set.copyOf added in API 31
-    registerTarget(AndroidApiLevel.S, 5);
-  }
-}