Fail in case of stdout/stderr unless explicitly allowed

Change-Id: I4fee93dadee8455220cb4dc12f6ffa9c94a32a85
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index e2881ad..37a8dc6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -95,9 +95,6 @@
       OptimizationFeedback feedback,
       MethodProcessor methodProcessor,
       Inliner inliner) {
-    if (method.method.toSourceString().contains("proto2.BuilderWithReusedSettersTestClass")) {
-      System.out.println();
-    }
     strengthenCheckCastInstructions(code);
 
     ProtoInliningReasonStrategy inliningReasonStrategy =
diff --git a/src/test/examples/classmerging/keep-rules.txt b/src/test/examples/classmerging/keep-rules.txt
index 5297ee9..64ce874 100644
--- a/src/test/examples/classmerging/keep-rules.txt
+++ b/src/test/examples/classmerging/keep-rules.txt
@@ -72,5 +72,3 @@
 -neverinline class * {
   @classmerging.NeverInline <methods>;
 }
-
--printmapping
diff --git a/src/test/java/com/android/tools/r8/DXTestBuilder.java b/src/test/java/com/android/tools/r8/DXTestBuilder.java
index 84ecee1..e621784 100644
--- a/src/test/java/com/android/tools/r8/DXTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/DXTestBuilder.java
@@ -53,7 +53,10 @@
       List<String> args = new ArrayList<>();
       args.add("--output=" + outJar.toString());
       args.addAll(injars.stream().map(Path::toString).collect(Collectors.toList()));
-      ProcessResult result = ToolHelper.runDX(args.toArray(StringUtils.EMPTY_ARRAY));
+      ProcessResult result =
+          ToolHelper.runProcess(
+              ToolHelper.createProcessBuilderForRunningDx(args.toArray(StringUtils.EMPTY_ARRAY)),
+              getStdoutForTesting());
       if (result.exitCode != 0) {
         throw new CompilationFailedException(result.toString());
       }
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
index 0ebe047..11e6692 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
@@ -137,7 +137,7 @@
       command.addAll(programJars.stream().map(Path::toString).collect(Collectors.toList()));
 
       ProcessBuilder processBuilder = new ProcessBuilder(command);
-      ProcessResult processResult = ToolHelper.runProcess(processBuilder);
+      ProcessResult processResult = ToolHelper.runProcess(processBuilder, getStdoutForTesting());
       assertEquals(processResult.stderr, 0, processResult.exitCode);
       String proguardMap =
           proguardMapFile.toFile().exists()
diff --git a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
index 9012ca4..9463a49 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
@@ -101,7 +101,7 @@
         command.add("-dontobfuscate");
       }
       ProcessBuilder pbuilder = new ProcessBuilder(command);
-      ProcessResult result = ToolHelper.runProcess(pbuilder);
+      ProcessResult result = ToolHelper.runProcess(pbuilder, getStdoutForTesting());
       if (result.exitCode != 0) {
         throw new CompilationFailedException(result.toString());
       }
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index c1a612f..5e0b7d8 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -72,7 +72,6 @@
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.io.ByteStreams;
@@ -82,7 +81,6 @@
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -437,12 +435,12 @@
   protected static AndroidApp.Builder buildClasses(
       Collection<Class<?>> programClasses, Collection<Class<?>> libraryClasses) throws IOException {
     AndroidApp.Builder builder = AndroidApp.builder();
-    for (Class clazz : programClasses) {
+    for (Class<?> clazz : programClasses) {
       builder.addProgramFiles(ToolHelper.getClassFileForTestClass(clazz));
     }
     if (!libraryClasses.isEmpty()) {
       PreloadedClassFileProvider.Builder libraryBuilder = PreloadedClassFileProvider.builder();
-      for (Class clazz : libraryClasses) {
+      for (Class<?> clazz : libraryClasses) {
         Path file = ToolHelper.getClassFileForTestClass(clazz);
         libraryBuilder.addResource(DescriptorUtils.javaTypeToDescriptor(clazz.getCanonicalName()),
             Files.readAllBytes(file));
@@ -455,7 +453,7 @@
   protected static AndroidApp readClassesAndRuntimeJar(
       List<Class<?>> programClasses, Backend backend) throws IOException {
     AndroidApp.Builder builder = AndroidApp.builder();
-    for (Class clazz : programClasses) {
+    for (Class<?> clazz : programClasses) {
       builder.addProgramFiles(ToolHelper.getClassFileForTestClass(clazz));
     }
     if (backend == Backend.DEX) {
@@ -477,7 +475,7 @@
    * Copy test classes to the specified directory.
    */
   protected void copyTestClasses(Path dest, Class... classes) throws IOException {
-    for (Class clazz : classes) {
+    for (Class<?> clazz : classes) {
       Path path = dest.resolve(clazz.getCanonicalName().replace('.', '/') + ".class");
       Files.createDirectories(path.getParent());
       Files.copy(ToolHelper.getClassFileForTestClass(clazz), path);
@@ -510,7 +508,7 @@
   /** Create a temporary JAR file containing the specified test classes. */
   protected void addTestClassesToJar(JarOutputStream out, Iterable<Class<?>> classes)
       throws IOException {
-    for (Class clazz : classes) {
+    for (Class<?> clazz : classes) {
       try (FileInputStream in =
           new FileInputStream(ToolHelper.getClassFileForTestClass(clazz).toFile())) {
         out.putNextEntry(new ZipEntry(ToolHelper.getJarEntryForTestClass(clazz)));
@@ -645,7 +643,7 @@
   }
 
   protected static DexMethod buildNullaryVoidMethod(
-      Class clazz, String name, DexItemFactory factory) {
+      Class<?> clazz, String name, DexItemFactory factory) {
     return buildMethod(
         Reference.method(Reference.classFromClass(clazz), name, Collections.emptyList(), null),
         factory);
@@ -659,7 +657,7 @@
   }
 
   private static List<ProguardConfigurationRule> buildKeepRuleForClass(
-      Class clazz, DexItemFactory factory) {
+      Class<?> clazz, DexItemFactory factory) {
     Builder keepRuleBuilder = ProguardKeepRule.builder();
     keepRuleBuilder.setSource("buildKeepRuleForClass " + clazz.getTypeName());
     keepRuleBuilder.setType(ProguardKeepRuleType.KEEP);
@@ -671,7 +669,7 @@
   }
 
   private static List<ProguardConfigurationRule> buildKeepRuleForClassAndMethods(
-      Class clazz, DexItemFactory factory) {
+      Class<?> clazz, DexItemFactory factory) {
     Builder keepRuleBuilder = ProguardKeepRule.builder();
     keepRuleBuilder.setSource("buildKeepRuleForClass " + clazz.getTypeName());
     keepRuleBuilder.setType(ProguardKeepRuleType.KEEP);
@@ -735,20 +733,6 @@
     return jarTestClasses(classes.toArray(new Class<?>[]{}));
   }
 
-  /**
-   * Get the class name generated by javac.
-   */
-  protected static String getJavacGeneratedClassName(Class clazz) {
-    List<String> parts = Lists.newArrayList(clazz.getCanonicalName().split("\\."));
-    Class enclosing = clazz;
-    while (enclosing.getEnclosingClass() != null) {
-      parts.set(parts.size() - 2, parts.get(parts.size() - 2) + "$" + parts.get(parts.size() - 1));
-      parts.remove(parts.size() - 1);
-      enclosing = clazz.getEnclosingClass();
-    }
-    return String.join(".", parts);
-  }
-
   protected static List<Object[]> buildParameters(Object... arraysOrIterables) {
     Function<Object, List<Object>> arrayOrIterableToList =
         arrayOrIterable -> {
@@ -897,23 +881,16 @@
    * Generate a Proguard configuration for keeping the "static void main(String[])" method of the
    * specified class.
    */
-  public static String keepMainProguardConfiguration(Class clazz) {
-    return keepMainProguardConfiguration(clazz, ImmutableList.of());
+  public static String keepMainProguardConfiguration(Class<?> clazz) {
+    return keepMainProguardConfiguration(clazz.getTypeName());
   }
 
   /**
    * Generate a Proguard configuration for keeping the "static void main(String[])" method of the
    * specified class.
    */
-  public static String keepMainProguardConfiguration(Class clazz, List<String> additionalLines) {
-    String modifier = (clazz.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC ? "public " : "";
-    return String.join(System.lineSeparator(),
-        Iterables.concat(ImmutableList.of(
-            "-keep " + modifier + "class " + getJavacGeneratedClassName(clazz) + " {",
-            "  public static void main(java.lang.String[]);",
-            "}",
-            "-printmapping"),
-            additionalLines));
+  public static String keepMainProguardConfiguration(Class<?> clazz, List<String> additionalLines) {
+    return keepMainProguardConfiguration(clazz.getTypeName()) + StringUtils.lines(additionalLines);
   }
 
   /**
@@ -923,15 +900,12 @@
    * The class is assumed to be public.
    */
   public static String keepMainProguardConfiguration(String clazz) {
-    return "-keep public class " + clazz + " {\n"
-        + "  public static void main(java.lang.String[]);\n"
-        + "}\n"
-        + "-printmapping\n";
+    return StringUtils.lines(
+        "-keep class " + clazz + " {", "  public static void main(java.lang.String[]);", "}");
   }
 
   public static String noShrinkingNoMinificationProguardConfiguration() {
-    return "-dontshrink\n"
-        + "-dontobfuscate\n";
+    return StringUtils.lines("-dontshrink", "-dontobfuscate");
   }
 
   /**
@@ -939,7 +913,7 @@
    * specified class and specify if -allowaccessmodification and -dontobfuscate are added as well.
    */
   public static String keepMainProguardConfiguration(
-      Class clazz, boolean allowaccessmodification, boolean obfuscate) {
+      Class<?> clazz, boolean allowaccessmodification, boolean obfuscate) {
     return keepMainProguardConfiguration(clazz)
         + (allowaccessmodification ? "-allowaccessmodification\n" : "")
         + (obfuscate ? "-printmapping\n" : "-dontobfuscate\n");
@@ -956,7 +930,7 @@
    * Generate a Proguard configuration for keeping the "static void main(String[])" method of the
    * specified class and add rules to inline methods with the inlining annotation.
    */
-  public static String keepMainProguardConfigurationWithInliningAnnotation(Class clazz) {
+  public static String keepMainProguardConfigurationWithInliningAnnotation(Class<?> clazz) {
     return "-forceinline class * { @com.android.tools.r8.ForceInline *; }"
         + System.lineSeparator()
         + "-neverinline class * { @com.android.tools.r8.NeverInline *; }"
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index 628e9c5..5f0843f 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import com.android.tools.r8.TestBase.Backend;
 import com.android.tools.r8.debug.DebugTestConfig;
 import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase.KeepRuleConsumer;
@@ -12,6 +16,7 @@
 import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.ForwardingOutputStream;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThrowingOutputStream;
 import com.google.common.base.Suppliers;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -52,7 +57,9 @@
   private AndroidApiLevel defaultMinApiLevel = ToolHelper.getMinApiLevelForDexVm();
   private Consumer<InternalOptions> optionsConsumer = DEFAULT_OPTIONS;
   private ByteArrayOutputStream stdout = null;
+  private PrintStream oldStdout = null;
   private ByteArrayOutputStream stderr = null;
+  private PrintStream oldStderr = null;
   protected OutputMode outputMode = OutputMode.DexIndexed;
 
   TestCompilerBuilder(TestState state, B builder, Backend backend) {
@@ -95,34 +102,43 @@
         builder.addLibraryFiles(TestBase.runtimeJar(backend));
       }
     }
-    PrintStream oldOut = System.out;
-    PrintStream oldErr = System.err;
-    CR cr = null;
+    assertNull(oldStdout);
+    oldStdout = System.out;
+    assertNull(oldStderr);
+    oldStderr = System.err;
+    CR cr;
     try {
       if (stdout != null) {
+        assertTrue(allowStdoutMessages);
         System.setOut(new PrintStream(new ForwardingOutputStream(stdout, System.out)));
+      } else if (!allowStdoutMessages) {
+        System.setOut(
+            new PrintStream(
+                new ThrowingOutputStream<>(
+                    () -> new AssertionError("Unexpected print to stdout"))));
       }
       if (stderr != null) {
+        assertTrue(allowStderrMessages);
         System.setErr(new PrintStream(new ForwardingOutputStream(stderr, System.err)));
+      } else if (!allowStderrMessages) {
+        System.setErr(
+            new PrintStream(
+                new ThrowingOutputStream<>(
+                    () -> new AssertionError("Unexpected print to stderr"))));
       }
-      cr = internalCompile(builder, optionsConsumer, Suppliers.memoize(sink::build));
-      cr.addRunClasspathFiles(additionalRunClassPath);
+      cr =
+          internalCompile(builder, optionsConsumer, Suppliers.memoize(sink::build))
+              .addRunClasspathFiles(additionalRunClassPath);
       return cr;
     } finally {
       if (stdout != null) {
         getState().setStdout(stdout.toString());
-        System.setOut(oldOut);
-        if (cr != null && !allowStdoutMessages) {
-          cr.assertNoStdout();
-        }
       }
+      System.setOut(oldStdout);
       if (stderr != null) {
         getState().setStderr(stderr.toString());
-        System.setErr(oldErr);
-        if (cr != null && !allowStderrMessages) {
-          cr.assertNoStderr();
-        }
       }
+      System.setErr(oldStderr);
     }
   }
 
@@ -319,6 +335,16 @@
     return allowStdoutMessages();
   }
 
+  /**
+   * If {@link #allowStdoutMessages} is false, then {@link System#out} will be replaced temporarily
+   * by a {@link ThrowingOutputStream}. To allow the testing infrastructure to print messages to the
+   * terminal, this method provides a reference to the original {@link System#out}.
+   */
+  public PrintStream getStdoutForTesting() {
+    assertNotNull(oldStdout);
+    return oldStdout;
+  }
+
   public T allowStderrMessages() {
     allowStdoutMessages = true;
     return self();
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index effe9d9..648126c 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1244,6 +1244,15 @@
   }
 
   public static ProcessResult runDX(Path workingDirectory, String... args) throws IOException {
+    return runProcess(createProcessBuilderForRunningDx(workingDirectory, args));
+  }
+
+  public static ProcessBuilder createProcessBuilderForRunningDx(String... args) {
+    return createProcessBuilderForRunningDx(null, args);
+  }
+
+  public static ProcessBuilder createProcessBuilderForRunningDx(
+      Path workingDirectory, String... args) {
     Assume.assumeTrue(ToolHelper.artSupported());
     DXCommandBuilder builder = new DXCommandBuilder();
     for (String arg : args) {
@@ -1253,7 +1262,7 @@
     if (workingDirectory != null) {
       pb.directory(workingDirectory.toFile());
     }
-    return runProcess(pb);
+    return pb;
   }
 
   public static ProcessResult runJava(Class clazz) throws Exception {
@@ -1968,8 +1977,13 @@
   }
 
   public static ProcessResult runProcess(ProcessBuilder builder) throws IOException {
+    return runProcess(builder, System.out);
+  }
+
+  public static ProcessResult runProcess(ProcessBuilder builder, PrintStream out)
+      throws IOException {
     String command = String.join(" ", builder.command());
-    System.out.println(command);
+    out.println(command);
     return drainProcessOutputStreams(builder.start(), command);
   }
 
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/RemoveVisibilityBridgeMethodsTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/RemoveVisibilityBridgeMethodsTest.java
index c37c71b..6bc3814 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/RemoveVisibilityBridgeMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/RemoveVisibilityBridgeMethodsTest.java
@@ -5,67 +5,65 @@
 package com.android.tools.r8.bridgeremoval;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.bridgeremoval.bridgestoremove.Main;
-import com.android.tools.r8.bridgeremoval.bridgestoremove.Outer;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
-import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
-import java.lang.reflect.Method;
-import java.nio.file.Path;
 import java.util.Collections;
 import java.util.List;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+@RunWith(Parameterized.class)
 public class RemoveVisibilityBridgeMethodsTest extends TestBase {
 
-  private void run(boolean obfuscate) throws Exception {
-    List<Class<?>> classes = ImmutableList.of(Outer.class, Main.class);
-    String proguardConfig = keepMainProguardConfiguration(Main.class, true, obfuscate);
-    CodeInspector inspector = new CodeInspector(compileWithR8(classes, proguardConfig));
+  private final boolean minification;
+  private final TestParameters parameters;
 
-    List<Method> removedMethods = ImmutableList.of(
-        Outer.SubClass.class.getMethod("method"),
-        Outer.StaticSubClass.class.getMethod("method"));
+  @Parameterized.Parameters(name = "{1}, minification: {0}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
+  }
 
-    removedMethods.forEach(method -> assertFalse(inspector.method(method).isPresent()));
+  public RemoveVisibilityBridgeMethodsTest(boolean minification, TestParameters parameters) {
+    this.minification = minification;
+    this.parameters = parameters;
   }
 
   @Test
-  public void testWithObfuscation() throws Exception {
-    run(true);
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(RemoveVisibilityBridgeMethodsTest.class)
+        .addKeepMainRule(Main.class)
+        .allowAccessModification()
+        .minification(minification)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccess();
   }
 
-  @Test
-  public void testWithoutObfuscation() throws Exception {
-    run(false);
-  }
-
-  @Test
-  public void regressionTest_b76383728_WithObfuscation() throws Exception {
-    runRegressionTest_b76383728(true);
-  }
-
-  @Test
-  public void regressionTest_b76383728_WithoutObfuscation() throws Exception {
-    runRegressionTest_b76383728(false);
+  private void inspect(CodeInspector inspector) throws Exception {
+    assertThat(inspector.method(Outer.SubClass.class.getMethod("method")), not(isPresent()));
+    assertThat(inspector.method(Outer.StaticSubClass.class.getMethod("method")), not(isPresent()));
   }
 
   /**
    * Regression test for b76383728 to make sure we correctly identify and remove real visibility
    * forward bridge methods synthesized by javac.
    */
-  private void runRegressionTest_b76383728(boolean obfuscate) throws Exception {
+  @Test
+  public void regressionTest_b76383728() throws Exception {
     JasminBuilder jasminBuilder = new JasminBuilder();
 
     ClassBuilder superClass = jasminBuilder.addClass("SuperClass");
@@ -92,39 +90,71 @@
         "dup",
         "invokespecial " + subclass.name + "/<init>()V",
         "invokevirtual " + subclass.name + "/getMethod()Ljava/lang/String;",
-        "invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
-        "return"
-    );
+        "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
+        "return");
 
-    final String mainClassName = mainClass.name;
-
-    String proguardConfig = keepMainProguardConfiguration(mainClass.name, true, obfuscate);
+    List<byte[]> programClassFileData = jasminBuilder.buildClasses();
 
     // Run input program on java.
-    Path outputDirectory = temp.newFolder().toPath();
-    jasminBuilder.writeClassFiles(outputDirectory);
-    ProcessResult javaResult = ToolHelper.runJava(outputDirectory, mainClassName);
-    assertEquals(0, javaResult.exitCode);
+    if (parameters.isCfRuntime()) {
+      testForJvm()
+          .addProgramClassFileData(programClassFileData)
+          .run(parameters.getRuntime(), mainClass.name)
+          .assertSuccessWithOutputLines("Hello World");
+    }
 
-    AndroidApp optimizedApp = compileWithR8(jasminBuilder.build(), proguardConfig,
-        // Disable inlining to avoid the (short) tested method from being inlined and then removed.
-        internalOptions -> internalOptions.enableInlining = false);
+    testForR8(parameters.getBackend())
+        .addProgramClassFileData(programClassFileData)
+        .addKeepMainRule(mainClass.name)
+        .addOptionsModification(options -> options.enableInlining = false)
+        .allowAccessModification()
+        .minification(minification)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(
+            inspector -> {
+              ClassSubject classSubject = inspector.clazz(superClass.name);
+              assertThat(classSubject, isPresent());
+              MethodSubject methodSubject =
+                  classSubject.method("java.lang.String", "method", Collections.emptyList());
+              assertThat(methodSubject, isPresent());
 
-    // Run optimized (output) program on ART
-    String artResult = runOnArt(optimizedApp, mainClassName);
-    assertEquals(javaResult.stdout, artResult);
+              classSubject = inspector.clazz(subclass.name);
+              assertThat(classSubject, isPresent());
+              methodSubject =
+                  classSubject.method("java.lang.String", "getMethod", Collections.emptyList());
+              assertThat(methodSubject, isPresent());
+            })
+        .run(parameters.getRuntime(), mainClass.name)
+        .assertSuccessWithOutputLines("Hello World");
+  }
 
-    CodeInspector inspector = new CodeInspector(optimizedApp);
+  static class Main {
 
-    ClassSubject classSubject = inspector.clazz(superClass.name);
-    assertThat(classSubject, isPresent());
-    MethodSubject methodSubject = classSubject
-        .method("java.lang.String", "method", Collections.emptyList());
-    assertThat(methodSubject, isPresent());
+    public static void main(String[] args) {
+      new Outer().create().method();
+      new Outer.StaticSubClass().method();
+    }
+  }
 
-    classSubject = inspector.clazz(subclass.name);
-    assertThat(classSubject, isPresent());
-    methodSubject = classSubject.method("java.lang.String", "getMethod", Collections.emptyList());
-    assertThat(methodSubject, isPresent());
+  static class Outer {
+
+    class SuperClass {
+      public void method() {}
+    }
+
+    // As SuperClass is package private SubClass will have a bridge method for "method".
+    public class SubClass extends SuperClass {}
+
+    public SubClass create() {
+      return new SubClass();
+    }
+
+    static class StaticSuperClass {
+      public void method() {}
+    }
+
+    // As SuperClass is package private SubClass will have a bridge method for "method".
+    public static class StaticSubClass extends StaticSuperClass {}
   }
 }
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/bridgestoremove/Main.java b/src/test/java/com/android/tools/r8/bridgeremoval/bridgestoremove/Main.java
index 4c8ac31..28ad6b9 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/bridgestoremove/Main.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/bridgestoremove/Main.java
@@ -7,7 +7,7 @@
 public class Main {
 
   public static void main(String[] args) {
-    (new Outer()).create().method();
-    (new Outer.StaticSubClass()).method();
+    new Outer().create().method();
+    new Outer.StaticSubClass().method();
   }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTest.java b/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTest.java
index b81d457..16dfaa7 100644
--- a/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTest.java
+++ b/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTest.java
@@ -1,23 +1,77 @@
 // Copyright (c) 2018, 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.cf;
 
-public class InlineCmpDoubleTest {
-  public static void main(String[] args) {
-   inlinee(42);
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class InlineCmpDoubleTest extends TestBase {
+
+  private final boolean enableInlining;
+  private final TestParameters parameters;
+
+  public InlineCmpDoubleTest(boolean enableInlining, TestParameters parameters) {
+    this.enableInlining = enableInlining;
+    this.parameters = parameters;
   }
 
-  public static void inlinee(int x) {
-    inlineMe(x + 41);
+  @Parameters(name = "{1}, inlining: {0}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
   }
 
-  public static int inlineMe(int x) {
-    // Side effect to ensure that the invocation is not removed simply because the method does not
-    // have any side effects.
-    System.out.println("In InlineCmpDoubleTest.inlineMe()");
-    double a = x / 255.0;
-    return a < 64.0 ? 42 : 43;
+  @Test
+  public void test() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(TestClass.class)
+        .addKeepMainRule(TestClass.class)
+        .addOptionsModification(options -> options.enableInlining = enableInlining)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspect(this::inspect)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccess();
+  }
+
+  private void inspect(CodeInspector inspector) {
+    ClassSubject clazz = inspector.clazz(TestClass.class);
+    MethodSubject method =
+        clazz.method(new MethodSignature("inlineMe", "int", ImmutableList.of("int")));
+    assertEquals(enableInlining, !method.isPresent());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      inlinee(42);
+    }
+
+    public static void inlinee(int x) {
+      inlineMe(x + 41);
+    }
+
+    public static int inlineMe(int x) {
+      // Side effect to ensure that the invocation is not removed simply because the method does not
+      // have any side effects.
+      System.out.println("In InlineCmpDoubleTest.inlineMe()");
+      double a = x / 255.0;
+      return a < 64.0 ? 42 : 43;
+    }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTestRunner.java b/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTestRunner.java
deleted file mode 100644
index dbcf557..0000000
--- a/src/test/java/com/android/tools/r8/cf/InlineCmpDoubleTestRunner.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2018, 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.cf;
-
-import static org.junit.Assert.assertEquals;
-
-import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.R8Command;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.AndroidAppConsumers;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
-import java.nio.file.Path;
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class InlineCmpDoubleTestRunner {
-
-  private static final Class CLASS = InlineCmpDoubleTest.class;
-
-  private final boolean enableInlining;
-
-  @Rule
-  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
-
-  public InlineCmpDoubleTestRunner(boolean enableInlining) {
-    this.enableInlining = enableInlining;
-  }
-
-  @Parameters(name = "inlining={0}")
-  public static Boolean[] data() {
-    return new Boolean[]{true, false};
-  }
-
-  @Test
-  public void test() throws Exception {
-    byte[] inputClass = ToolHelper.getClassAsBytes(CLASS);
-    AndroidAppConsumers appBuilder = new AndroidAppConsumers();
-    Path outPath = temp.getRoot().toPath().resolve("out.jar");
-    List<String> proguardKeepMain = ImmutableList.of(TestBase.keepMainProguardConfiguration(CLASS));
-    R8Command command =  R8Command.builder()
-        .setMode(CompilationMode.RELEASE)
-        .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
-        .setProgramConsumer(appBuilder.wrapClassFileConsumer(new ArchiveConsumer(outPath)))
-        .addProguardConfiguration(proguardKeepMain, Origin.unknown())
-        .addClassProgramData(inputClass, Origin.unknown())
-        .build();
-
-    AndroidApp app = ToolHelper.runR8(command, options -> {
-          options.enableInlining = enableInlining;
-    });
-
-    assertEquals(0, ToolHelper.runJava(outPath, CLASS.getCanonicalName()).exitCode);
-
-    CodeInspector inspector = new CodeInspector(app);
-    ClassSubject clazz = inspector.clazz(CLASS);
-    MethodSubject method =
-        clazz.method(new MethodSignature("inlineMe", "int", ImmutableList.of("int")));
-    assertEquals(enableInlining, !method.isPresent());
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
index 8bc0e79..d1ecf46 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexTracingTest.java
@@ -9,10 +9,18 @@
 import static com.android.tools.r8.utils.FileUtils.withNativeFileSeparators;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import com.android.tools.r8.GenerateMainDexList;
 import com.android.tools.r8.GenerateMainDexListCommand;
+import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompilerBuilder;
+import com.android.tools.r8.ThrowableConsumer;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ir.desugar.LambdaRewriter;
 import com.android.tools.r8.references.Reference;
@@ -21,7 +29,6 @@
 import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -35,11 +42,9 @@
 import java.util.Enumeration;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
-import org.junit.Assert;
 import org.junit.Test;
 
 public class MainDexTracingTest extends TestBase {
@@ -61,9 +66,10 @@
         Paths.get(EXAMPLE_SRC_DIR, "multidex", "main-dex-rules-whyareyoukeeping.txt"),
         Paths.get(EXAMPLE_SRC_DIR, "multidex001", "ref-list-1.txt"),
         Paths.get(EXAMPLE_SRC_DIR, "multidex001", "ref-list-1.txt"),
-        AndroidApiLevel.I);
+        AndroidApiLevel.I,
+        TestCompilerBuilder::allowStdoutMessages);
     String output = new String(baos.toByteArray(), Charset.defaultCharset());
-    Assert.assertThat(output, containsString("is referenced in keep rule:"));
+    assertThat(output, containsString("is referenced in keep rule:"));
     System.setOut(stdout);
   }
 
@@ -78,10 +84,12 @@
         Paths.get(EXAMPLE_SRC_DIR, "multidex001", "ref-list-1.txt"),
         Paths.get(EXAMPLE_SRC_DIR, "multidex001", "ref-list-1.txt"),
         AndroidApiLevel.I,
-        options -> {
-          options.enableInlining = false;
-          options.mainDexKeptGraphConsumer = graphConsumer;
-        });
+        builder ->
+            builder.addOptionsModification(
+                options -> {
+                  options.enableInlining = false;
+                  options.mainDexKeptGraphConsumer = graphConsumer;
+                }));
     {
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       graphConsumer.printWhyAreYouKeeping(
@@ -92,7 +100,7 @@
               "multidex001.MainActivity",
               "|- is referenced in keep rule:",
               withNativeFileSeparators("|  src/test/examples/multidex/main-dex-rules.txt:14:1"));
-      Assert.assertEquals(expected, output);
+      assertEquals(expected, output);
     }
     {
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -110,7 +118,7 @@
                   "|- is referenced in keep rule:",
                   withNativeFileSeparators(
                       "|  src/test/examples/multidex/main-dex-rules.txt:14:1"));
-      Assert.assertEquals(expected, output);
+      assertEquals(expected, output);
     }
   }
 
@@ -271,9 +279,7 @@
         expectedR8MainDexList,
         expectedMainDexList,
         minSdk,
-        (options) -> {
-          options.enableInlining = false;
-        });
+        builder -> builder.addOptionsModification(options -> options.enableInlining = false));
   }
 
   private void doTest(
@@ -284,7 +290,7 @@
       Path expectedR8MainDexList,
       Path expectedMainDexList,
       AndroidApiLevel minSdk,
-      Consumer<InternalOptions> optionsConsumer)
+      ThrowableConsumer<R8FullTestBuilder> configuration)
       throws Throwable {
     Path out = temp.getRoot().toPath().resolve(testName + ZIP_EXTENSION);
 
@@ -328,7 +334,7 @@
         .addProgramFiles(Paths.get(EXAMPLE_BUILD_DIR, "multidexfakeframeworks" + JAR_EXTENSION))
         .addKeepRules("-keepattributes *Annotation*")
         .addMainDexRuleFiles(mainDexRules)
-        .addOptionsModification(optionsConsumer)
+        .apply(configuration)
         .allowDiagnosticWarningMessages()
         .assumeAllMethodsMayHaveSideEffects()
         .setMinApi(minSdk)
@@ -351,7 +357,7 @@
     for (int i = 0; i < r8RefList.length; i++) {
       String reference = r8RefList[i].trim();
       if (r8MainDexList.size() <= i) {
-        Assert.fail("R8 main dex list is missing '" + reference + "'");
+        fail("R8 main dex list is missing '" + reference + "'");
       }
       checkSameMainDexEntry(reference, r8MainDexList.get(i));
     }
@@ -363,7 +369,7 @@
       // The main dex list generator does not do any lambda desugaring.
       if (!isLambda(reference)) {
         if (mainDexGeneratorMainDexList.size() <= i - nonLambdaOffset) {
-          Assert.fail("Main dex list generator is missing '" + reference + "'");
+          fail("Main dex list generator is missing '" + reference + "'");
         }
         checkSameMainDexEntry(reference, mainDexGeneratorMainDexList.get(i - nonLambdaOffset));
         checkSameMainDexEntry(
@@ -389,9 +395,9 @@
         continue;
       }
       if (index == 0) {
-        Assert.assertEquals("classes.dex", entry.getName());
+        assertEquals("classes.dex", entry.getName());
       } else {
-        Assert.assertEquals("classes" + (index + 1) + ".dex", entry.getName());
+        assertEquals("classes" + (index + 1) + ".dex", entry.getName());
       }
       index++;
     }
@@ -399,7 +405,7 @@
     String[] entriesUnsorted = entryNames.toArray(StringUtils.EMPTY_ARRAY);
     String[] entriesSorted = entryNames.toArray(StringUtils.EMPTY_ARRAY);
     Arrays.sort(entriesSorted);
-    Assert.assertArrayEquals(entriesUnsorted, entriesSorted);
+    assertArrayEquals(entriesUnsorted, entriesSorted);
   }
 
   private boolean isLambda(String mainDexEntry) {
@@ -407,7 +413,7 @@
   }
 
   private String mainDexStringToDescriptor(String mainDexString) {
-    Assert.assertTrue(mainDexString.endsWith(FileUtils.CLASS_EXTENSION));
+    assertTrue(mainDexString.endsWith(FileUtils.CLASS_EXTENSION));
     return DescriptorUtils.getDescriptorFromClassBinaryName(
         mainDexString.substring(0, mainDexString.length() - FileUtils.CLASS_EXTENSION.length()));
   }
@@ -421,6 +427,6 @@
       reference = reference.substring(0, reference.lastIndexOf('$'));
       computed = computed.substring(0, computed.lastIndexOf('$'));
     }
-    Assert.assertEquals(reference, computed);
+    assertEquals(reference, computed);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java b/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
index cd80843..c4a616c 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/whyareyoukeeping/MainDexListWhyAreYouKeeping.java
@@ -90,14 +90,15 @@
             .setMinApi(AndroidApiLevel.K)
             .addProgramClasses(CLASSES)
             .addMainDexRules(keepMainProguardConfiguration(HelloWorldMain.class))
-            .setMainDexKeptGraphConsumer(consumer);
+            .setMainDexKeptGraphConsumer(consumer)
+            .allowStdoutMessages();
     if (rule != null) {
       builder.addMainDexRules(rule);
     }
     builder.compile();
   }
 
-  private String runTest(Class clazz) throws Exception {
+  private String runTest(Class<?> clazz) throws Exception {
     PrintStream stdout = System.out;
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     String rule = null;
diff --git a/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java b/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java
index f1d0cda..15fba7f 100644
--- a/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/b113138046/NativeMethodTest.java
@@ -85,7 +85,6 @@
         "-keep class " + Outer.class.getCanonicalName() + " {",
         "  onEvent(...);",
         "}",
-        "-printmapping",
         "-keepattributes InnerClasses,EnclosingMethod,Signature",
         "-allowaccessmodification");
     test(config, compatMode);
@@ -106,7 +105,6 @@
         "  @**.Keep <fields>;",
         "  @**.Keep <methods>;",
         "}",
-        "-printmapping",
         "-keepattributes InnerClasses,EnclosingMethod,Signature",
         "-allowaccessmodification");
     test(config, true);
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
index ab46041..7752712 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/defaultctor/ImplicitlyKeptDefaultConstructorTest.java
@@ -243,11 +243,11 @@
   public void testStaticFieldWithoutInitializationStaticClassKept() throws Exception {
     // An explicit keep rule keeps the default constructor.
     Class<?> mainClass = MainGetStaticFieldNotInitialized.class;
-    String proguardConfiguration = keepMainProguardConfiguration(
-        mainClass,
-        ImmutableList.of(
-            "-keep class " + getJavacGeneratedClassName(StaticFieldNotInitialized.class) + " {",
-            "}"));
+    String proguardConfiguration =
+        keepMainProguardConfiguration(
+            mainClass,
+            ImmutableList.of(
+                "-keep class " + StaticFieldNotInitialized.class.getTypeName() + " {", "}"));
     runTest(
         mainClass,
         ImmutableList.of(mainClass, StaticFieldNotInitialized.class),
@@ -259,11 +259,11 @@
   public void testStaticFieldWithInitializationStaticClassKept() throws Exception {
     // An explicit keep rule keeps the default constructor.
     Class<?> mainClass = MainGetStaticFieldInitialized.class;
-    String proguardConfiguration = keepMainProguardConfiguration(
-        mainClass,
-        ImmutableList.of(
-            "-keep class " + getJavacGeneratedClassName(StaticFieldInitialized.class) + " {",
-            "}"));
+    String proguardConfiguration =
+        keepMainProguardConfiguration(
+            mainClass,
+            ImmutableList.of(
+                "-keep class " + StaticFieldInitialized.class.getTypeName() + " {", "}"));
     runTest(
         mainClass,
         ImmutableList.of(mainClass, StaticFieldInitialized.class),
@@ -275,11 +275,10 @@
   public void testStaticMethodStaticClassKept() throws Exception {
     // An explicit keep rule keeps the default constructor.
     Class<?> mainClass = MainCallStaticMethod.class;
-    String proguardConfiguration = keepMainProguardConfiguration(
-        mainClass,
-        ImmutableList.of(
-            "-keep class " + getJavacGeneratedClassName(StaticMethod.class) + " {",
-            "}"));
+    String proguardConfiguration =
+        keepMainProguardConfiguration(
+            mainClass,
+            ImmutableList.of("-keep class " + StaticMethod.class.getTypeName() + " {", "}"));
     runTest(
         mainClass,
         ImmutableList.of(mainClass, StaticMethod.class),
diff --git a/src/test/java/com/android/tools/r8/utils/ThrowingOutputStream.java b/src/test/java/com/android/tools/r8/utils/ThrowingOutputStream.java
new file mode 100644
index 0000000..2542264
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/ThrowingOutputStream.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, 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.utils;
+
+import java.io.OutputStream;
+import java.util.function.Supplier;
+
+public class ThrowingOutputStream<T extends Error> extends OutputStream {
+
+  private final Supplier<T> exceptionSupplier;
+
+  public ThrowingOutputStream(Supplier<T> exceptionSupplier) {
+    this.exceptionSupplier = exceptionSupplier;
+  }
+
+  @Override
+  public void write(int b) {
+    throw exceptionSupplier.get();
+  }
+
+  @Override
+  public void write(byte[] b) {
+    throw exceptionSupplier.get();
+  }
+
+  @Override
+  public void write(byte[] b, int off, int len) {
+    throw exceptionSupplier.get();
+  }
+
+  @Override
+  public void flush() {
+    throw exceptionSupplier.get();
+  }
+
+  @Override
+  public void close() {
+    throw exceptionSupplier.get();
+  }
+}