Update test to use test builder

Also extend test to test AAR's.

Bug: b/228319861
Change-Id: I0fd02913e8aba10074b1bb3c5b53db31e9f992fa
diff --git a/src/main/java/com/android/tools/r8/utils/ZipUtils.java b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
index e0863ce..9d8cedd 100644
--- a/src/main/java/com/android/tools/r8/utils/ZipUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
@@ -239,6 +239,10 @@
       return new ZipBuilder(zipFile);
     }
 
+    public ZipOutputStream getOutputStream() {
+      return stream;
+    }
+
     public ZipBuilder addFilesRelative(Path basePath, Collection<Path> filesToAdd)
         throws IOException {
       for (Path path : filesToAdd) {
@@ -269,6 +273,14 @@
       return this;
     }
 
+    public ZipBuilder addText(String path, String text) throws IOException {
+      ZipEntry zipEntry = new ZipEntry(path);
+      stream.putNextEntry(zipEntry);
+      stream.write(text.getBytes(StandardCharsets.UTF_8));
+      stream.closeEntry();
+      return this;
+    }
+
     public Path build() throws IOException {
       stream.close();
       return zipFile;
diff --git a/src/test/java/com/android/tools/r8/OriginMatcher.java b/src/test/java/com/android/tools/r8/OriginMatcher.java
index 8484ea3..4f5ad82 100644
--- a/src/test/java/com/android/tools/r8/OriginMatcher.java
+++ b/src/test/java/com/android/tools/r8/OriginMatcher.java
@@ -30,4 +30,18 @@
       }
     };
   }
+
+  public static Matcher<Origin> hasPart(String part) {
+    return new OriginMatcher() {
+      @Override
+      protected boolean matchesSafely(Origin origin) {
+        return origin.part().equals(part);
+      }
+
+      @Override
+      public void describeTo(Description description) {
+        description.appendText("part is not " + part);
+      }
+    };
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 3a482a5..21ca89e 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -690,8 +690,8 @@
   protected Path jarTestClasses(Iterable<Class<?>> classes, List<DataResource> dataResources)
       throws IOException {
     Path jar = File.createTempFile("junit", ".jar", temp.getRoot()).toPath();
-    try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jar.toFile()))) {
-      addTestClassesToJar(out, classes);
+    try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(jar.toFile()))) {
+      addTestClassesToZip(out, classes);
       if (dataResources != null) {
         addDataResourcesToJar(out, dataResources);
       }
@@ -700,7 +700,7 @@
   }
 
   /** Create a temporary JAR file containing the specified test classes. */
-  protected void addTestClassesToJar(JarOutputStream out, Iterable<Class<?>> classes)
+  protected void addTestClassesToZip(ZipOutputStream out, Iterable<Class<?>> classes)
       throws IOException {
     for (Class<?> clazz : classes) {
       try (FileInputStream in =
@@ -714,7 +714,7 @@
 
   /** Create a temporary JAR file containing the specified data resources. */
   protected void addDataResourcesToJar(
-      JarOutputStream out, List<? extends DataResource> dataResources) throws IOException {
+      ZipOutputStream out, List<? extends DataResource> dataResources) throws IOException {
     try {
       for (DataResource dataResource : dataResources) {
         String name = dataResource.getName();
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
index c688182..1f6a70a 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
@@ -4,50 +4,46 @@
 
 package com.android.tools.r8.shaking;
 
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticOrigin;
+import static com.android.tools.r8.OriginMatcher.hasPart;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.ClassFileConsumer;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.DataResourceProvider;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsChecker;
-import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.ProgramResource;
 import com.android.tools.r8.ProgramResource.Kind;
 import com.android.tools.r8.ProgramResourceProvider;
-import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ResourceException;
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.origin.ArchiveEntryOrigin;
 import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.ByteStreams;
-import com.google.common.io.CharSource;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.jar.JarOutputStream;
-import java.util.zip.ZipEntry;
 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)
@@ -60,7 +56,7 @@
 
     public static void main(String[] args) {
       try {
-        Class bClass = Class.forName(buildClassName("B"));
+        Class.forName(buildClassName("B"));
         System.out.println("YES");
       } catch (ClassNotFoundException e) {
         System.out.println("NO");
@@ -70,113 +66,116 @@
 
   static class B {}
 
-  private Backend backend;
+  @Parameter(0)
+  public TestParameters parameters;
 
-  @Parameters(name = "Backend: {0}")
-  public static Backend[] data() {
-    return ToolHelper.getBackends();
+  @Parameter(1)
+  public boolean isAar;
+
+  @Parameters(name = "{0} AAR: {1}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
   }
 
-  public LibraryProvidedProguardRulesTest(Backend backend) {
-    this.backend = backend;
-  }
-
-  private void addTextJarEntry(JarOutputStream out, String name, String content) throws Exception {
-    out.putNextEntry(new ZipEntry(name));
-    ByteStreams.copy(
-        CharSource.wrap(content).asByteSource(StandardCharsets.UTF_8).openBufferedStream(), out);
-    out.closeEntry();
-  }
-
-  private AndroidApp runTest(List<String> rules, DiagnosticsHandler handler) throws Exception {
-    Path jar = temp.newFile("test.jar").toPath();
-    try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jar.toFile()))) {
-      addTestClassesToJar(out, ImmutableList.of(A.class, B.class));
-      for (int i =  0; i < rules.size(); i++) {
+  private Path buildLibrary(List<String> rules) throws Exception {
+    ZipBuilder builder =
+        ZipBuilder.builder(temp.newFile(isAar ? "classes.jar" : "test.jar").toPath());
+    addTestClassesToZip(builder.getOutputStream(), ImmutableList.of(A.class, B.class));
+    if (isAar) {
+      Path jar = builder.build();
+      String allRules = StringUtils.lines(rules);
+      return ZipBuilder.builder(temp.newFile("test.aar").toPath())
+          .addFilesRelative(jar.getParent(), jar)
+          .addText("proguard.txt", allRules)
+          .build();
+    } else {
+      for (int i = 0; i < rules.size(); i++) {
         String name = "META-INF/proguard/jar" + (i == 0 ? "" : i) + ".rules";
-        addTextJarEntry(out, name, rules.get(i));
+        builder.addText(name, rules.get(i));
       }
-    }
-
-    try {
-      R8Command.Builder builder =
-          (handler != null ? R8Command.builder(handler) : R8Command.builder()).addProgramFiles(jar);
-      if (backend == Backend.DEX) {
-        builder
-            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
-            .addLibraryFiles(ToolHelper.getDefaultAndroidJar());
-      } else {
-        assert backend == Backend.CF;
-        builder
-            .setProgramConsumer(ClassFileConsumer.emptyConsumer())
-            .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
-      }
-      return ToolHelper.runR8(builder.build());
-    } catch (CompilationFailedException e) {
-      assertNotNull(handler);
-      return null;
+      return builder.build();
     }
   }
 
-  private AndroidApp runTest(String rules, DiagnosticsHandler handler) throws Exception {
-    return runTest(ImmutableList.of(rules), handler);
+  private CodeInspector runTest(List<String> rules) throws Exception {
+    return testForR8(parameters.getBackend())
+        .addProgramFiles(buildLibrary(rules))
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspector();
   }
 
+  private CodeInspector runTest(String rules) throws Exception {
+    return runTest(ImmutableList.of(rules));
+  }
 
   @Test
   public void keepOnlyA() throws Exception {
-    AndroidApp app = runTest("-keep class " + A.class.getTypeName() +" {}", null);
-    CodeInspector inspector = new CodeInspector(app);
-    assertThat(inspector.clazz(A.class), isPresent());
+    CodeInspector inspector = runTest("-keep class " + A.class.getTypeName() + " {}");
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assertThat(inspector.clazz(A.class), notIf(isPresent(), isAar));
     assertThat(inspector.clazz(B.class), not(isPresent()));
   }
 
   @Test
   public void keepOnlyB() throws Exception {
-    AndroidApp app = runTest("-keep class **B {}", null);
-    CodeInspector inspector = new CodeInspector(app);
+    CodeInspector inspector = runTest("-keep class **B {}");
     assertThat(inspector.clazz(A.class), not(isPresent()));
-    assertThat(inspector.clazz(B.class), isPresent());
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assertThat(inspector.clazz(B.class), notIf(isPresent(), isAar));
   }
 
   @Test
   public void keepBoth() throws Exception {
-    AndroidApp app = runTest("-keep class ** {}", null);
-    CodeInspector inspector = new CodeInspector(app);
-    assertThat(inspector.clazz(A.class), isPresent());
-    assertThat(inspector.clazz(B.class), isPresent());
+    CodeInspector inspector = runTest("-keep class ** {}");
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assertThat(inspector.clazz(A.class), notIf(isPresent(), isAar));
+    assertThat(inspector.clazz(B.class), notIf(isPresent(), isAar));
   }
 
   @Test
   public void multipleFiles() throws Exception {
-    AndroidApp app = runTest(ImmutableList.of("-keep class **A {}", "-keep class **B {}"), null);
-    CodeInspector inspector = new CodeInspector(app);
-    assertThat(inspector.clazz(A.class), isPresent());
-    assertThat(inspector.clazz(B.class), isPresent());
-  }
-
-  private void checkOrigin(Origin origin) {
-    assertTrue(origin instanceof ArchiveEntryOrigin);
-    assertEquals(origin.part(), "META-INF/proguard/jar.rules");
-    assertTrue(origin.parent() instanceof PathOrigin);
+    CodeInspector inspector = runTest(ImmutableList.of("-keep class **A {}", "-keep class **B {}"));
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assertThat(inspector.clazz(A.class), notIf(isPresent(), isAar));
+    assertThat(inspector.clazz(B.class), notIf(isPresent(), isAar));
   }
 
   @Test
   public void syntaxError() throws Exception {
-    DiagnosticsChecker checker = new DiagnosticsChecker();
-    AndroidApp app = runTest("error", checker);
-    assertNull(app);
-    DiagnosticsChecker.checkDiagnostic(
-        checker.errors.get(0), this::checkOrigin, 1, 1, "Expected char '-'");
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assumeTrue(!isAar);
+    assertThrows(
+        CompilationFailedException.class,
+        () ->
+            testForR8(parameters.getBackend())
+                .addProgramFiles(buildLibrary(ImmutableList.of("error")))
+                .setMinApi(parameters.getApiLevel())
+                .compileWithExpectedDiagnostics(
+                    diagnostics ->
+                        diagnostics.assertErrorThatMatches(
+                            allOf(
+                                diagnosticMessage(containsString("Expected char '-'")),
+                                diagnosticOrigin(hasPart("META-INF/proguard/jar.rules")),
+                                diagnosticOrigin(instanceOf(ArchiveEntryOrigin.class))))));
   }
 
   @Test
   public void includeError() throws Exception {
-    DiagnosticsChecker checker = new DiagnosticsChecker();
-    AndroidApp app = runTest("-include other.rules", checker);
-    assertNull(app);
-    DiagnosticsChecker.checkDiagnostic(checker.errors.get(0), this::checkOrigin, 1, 10,
-        "Options with file names are not supported");
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assumeTrue(!isAar);
+    assertThrows(
+        CompilationFailedException.class,
+        () ->
+            testForR8(parameters.getBackend())
+                .addProgramFiles(buildLibrary(ImmutableList.of("-include other.rules")))
+                .setMinApi(parameters.getApiLevel())
+                .compileWithExpectedDiagnostics(
+                    diagnostics ->
+                        diagnostics.assertErrorThatMatches(
+                            diagnosticMessage(
+                                containsString("Options with file names are not supported")))));
   }
 
   static class TestProvider implements ProgramResourceProvider, DataResourceProvider {
@@ -207,27 +206,20 @@
 
   @Test
   public void throwingDataResourceProvider() throws Exception {
-    DiagnosticsChecker checker = new DiagnosticsChecker();
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(checker).addProgramResourceProvider(new TestProvider());
-      if (backend == Backend.DEX) {
-        builder
-            .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
-            .addLibraryFiles(ToolHelper.getDefaultAndroidJar());
-      } else {
-        assert backend == Backend.CF;
-        builder
-            .setProgramConsumer(ClassFileConsumer.emptyConsumer())
-            .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
-      }
-      builder.build();
-      fail("Should not succeed");
-    } catch (CompilationFailedException e) {
-      DiagnosticsChecker.checkDiagnostic(
-          checker.errors.get(0),
-          origin -> assertSame(origin, Origin.unknown()),
-          "Cannot provide data resources after all");
-    }
+    // TODO(b/228319861): Read Proguard rules from AAR's.
+    assumeTrue(!isAar);
+    assertThrows(
+        CompilationFailedException.class,
+        () ->
+            testForR8(parameters.getBackend())
+                .addProgramResourceProviders(new TestProvider())
+                .setMinApi(parameters.getApiLevel())
+                .compileWithExpectedDiagnostics(
+                    diagnostics ->
+                        diagnostics.assertErrorThatMatches(
+                            allOf(
+                                diagnosticMessage(
+                                    containsString("Cannot provide data resources after all")),
+                                diagnosticOrigin(is(Origin.unknown()))))));
   }
 }