// 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.rewrite.assertions;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.AssertionsConfiguration;
import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.rewrite.assertions.testclasses.TestClassForInnerClass;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

@RunWith(Parameterized.class)
public class AssertionsConfigurationTest extends TestBase implements Opcodes {

  private final TestParameters parameters;

  private Class<?> class1 = com.android.tools.r8.rewrite.assertions.testclasses.Class1.class;
  private Class<?> class2 = com.android.tools.r8.rewrite.assertions.testclasses.Class2.class;
  private Class<?> subpackageClass1 =
      com.android.tools.r8.rewrite.assertions.testclasses.subpackage.Class1.class;
  private Class<?> subpackageClass2 =
      com.android.tools.r8.rewrite.assertions.testclasses.subpackage.Class2.class;

  private List<Class<?>> testClasses =
      ImmutableList.of(TestClass.class, class1, class2, subpackageClass1, subpackageClass2);

  private String packageName =
      com.android.tools.r8.rewrite.assertions.testclasses.Class1.class.getPackage().getName();
  private String subPackageName =
      com.android.tools.r8.rewrite.assertions.testclasses.subpackage.Class1.class
          .getPackage()
          .getName();

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
  }

  public AssertionsConfigurationTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  private void runD8Test(
      ThrowableConsumer<D8TestBuilder> builderConsumer,
      ThrowingConsumer<CodeInspector, RuntimeException> inspector,
      List<String> outputLines)
      throws Exception {
    testForD8()
        .addProgramClasses(testClasses)
        .setMinApi(parameters.getApiLevel())
        .apply(builderConsumer)
        .compile()
        .inspect(inspector)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(StringUtils.lines(outputLines));
  }

  public void runR8Test(
      ThrowableConsumer<R8FullTestBuilder> builderConsumer,
      ThrowingConsumer<CodeInspector, RuntimeException> inspector,
      List<String> outputLines)
      throws Exception {
    runR8Test(builderConsumer, inspector, outputLines, false);
  }

  public void runR8Test(
      ThrowableConsumer<R8FullTestBuilder> builderConsumer,
      ThrowingConsumer<CodeInspector, RuntimeException> inspector,
      List<String> outputLines,
      boolean enableJvmAssertions)
      throws Exception {

    testForR8(parameters.getBackend())
        .addProgramClasses(testClasses)
        .addKeepMainRule(TestClass.class)
        .addKeepClassAndMembersRules(class1, class2, subpackageClass1, subpackageClass2)
        .setMinApi(parameters.getApiLevel())
        .apply(builderConsumer)
        .compile()
        .inspect(inspector)
        .enableRuntimeAssertions(enableJvmAssertions)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(StringUtils.lines(outputLines));
  }

  private List<String> allAssertionsExpectedLines() {
    return ImmutableList.of(
        "AssertionError in testclasses.Class1",
        "AssertionError in testclasses.Class2",
        "AssertionError in testclasses.subpackage.Class1",
        "AssertionError in testclasses.subpackage.Class2",
        "DONE");
  }

  private List<String> noAllAssertionsExpectedLines() {
    return ImmutableList.of("DONE");
  }

  private void checkAssertionCodeRemoved(ClassSubject subject) {
    assertThat(subject, isPresent());
    // <clinit> is removed by R8 as it becomes empty.
    if (subject.uniqueMethodWithName("<clinit>").isPresent()) {
      assertFalse(
          subject
              .uniqueMethodWithName("<clinit>")
              .streamInstructions()
              .anyMatch(InstructionSubject::isStaticPut));
    }
    assertFalse(
        subject
            .uniqueMethodWithName("m")
            .streamInstructions()
            .anyMatch(InstructionSubject::isThrow));
  }

  private void checkAssertionCodeRemoved(CodeInspector inspector, Class<?> clazz) {
    checkAssertionCodeRemoved(inspector.clazz(clazz));
  }

  private void checkAssertionCodeEnabled(ClassSubject subject) {
    assertThat(subject, isPresent());
    // <clinit> is removed by R8.
    if (subject.uniqueMethodWithName("<clinit>").isPresent()) {
      assertFalse(
          subject
              .uniqueMethodWithName("<clinit>")
              .streamInstructions()
              .anyMatch(InstructionSubject::isStaticPut));
    }
    assertTrue(
        subject
            .uniqueMethodWithName("m")
            .streamInstructions()
            .anyMatch(InstructionSubject::isThrow));
  }

  private void checkAssertionCodeEnabled(CodeInspector inspector, Class<?> clazz) {
    checkAssertionCodeEnabled(inspector.clazz(clazz));
  }

  private void checkAssertionCodeLeft(CodeInspector inspector, Class<?> clazz) {
    ClassSubject subject = inspector.clazz(clazz);
    assertThat(subject, isPresent());
    assertTrue(
        subject
            .uniqueMethodWithName("<clinit>")
            .streamInstructions()
            .anyMatch(InstructionSubject::isStaticPut));
    assertTrue(
        subject
            .uniqueMethodWithName("m")
            .streamInstructions()
            .anyMatch(InstructionSubject::isThrow));
  }

  private void checkAssertionCodeRemoved(CodeInspector inspector) {
    checkAssertionCodeRemoved(inspector, class1);
    checkAssertionCodeRemoved(inspector, class2);
    checkAssertionCodeRemoved(inspector, subpackageClass1);
    checkAssertionCodeRemoved(inspector, subpackageClass2);
  }

  private void checkAssertionCodeEnabled(CodeInspector inspector) {
    checkAssertionCodeEnabled(inspector, class1);
    checkAssertionCodeEnabled(inspector, class2);
    checkAssertionCodeEnabled(inspector, subpackageClass1);
    checkAssertionCodeEnabled(inspector, subpackageClass2);
  }

  private void checkAssertionCodeLeft(CodeInspector inspector) {
    checkAssertionCodeLeft(inspector, class1);
    checkAssertionCodeLeft(inspector, class2);
    checkAssertionCodeLeft(inspector, subpackageClass1);
    checkAssertionCodeLeft(inspector, subpackageClass2);
  }

  @Test
  public void testAssertionsForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    // Leaving assertions in or disabling them on Dalvik/Art means no assertions.
    runD8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::passthroughAllAssertions),
        this::checkAssertionCodeLeft,
        noAllAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::passthroughAllAssertions),
        this::checkAssertionCodeLeft,
        noAllAssertionsExpectedLines());
    runD8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::disableAllAssertions),
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::disableAllAssertions),
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    // Compile time enabling assertions gives assertions on Dalvik/Art.
    runD8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::enableAllAssertions),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::enableAllAssertions),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
    // Enabling for the package should enable all.
    runD8Test(
        builder ->
            builder.addAssertionsConfiguration(
                b -> b.setEnable().setScopePackage(packageName).build()),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                b -> b.setEnable().setScopePackage(packageName).build()),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
  }

  @Test
  public void testAssertionsForCf() throws Exception {
    Assume.assumeTrue(parameters.isCfRuntime());
    // Leaving assertion code means assertions are controlled by the -ea flag.
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::passthroughAllAssertions),
        this::checkAssertionCodeLeft,
        noAllAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::passthroughAllAssertions),
        this::checkAssertionCodeLeft,
        allAssertionsExpectedLines(),
        true);
    // Compile time enabling or disabling assertions means the -ea flag has no effect.
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::enableAllAssertions),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::enableAllAssertions),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines(),
        true);
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::disableAllAssertions),
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                AssertionsConfiguration.Builder::disableAllAssertions),
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines(),
        true);
  }

  @Test
  public void testEnableForPackageForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    runD8Test(
        builder ->
            builder.addAssertionsConfiguration(
                b -> b.setEnable().setScopePackage(subPackageName).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, subpackageClass1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.subpackage.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
    runR8Test(
        builder ->
            builder.addAssertionsConfiguration(
                b -> b.setEnable().setScopePackage(subPackageName).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, subpackageClass1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.subpackage.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
  }

  @Test
  public void testEnableForClassForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    runD8Test(
        builder ->
            builder
                .addAssertionsConfiguration(
                    b -> b.setEnable().setScopeClass(class1.getCanonicalName()).build())
                .addAssertionsConfiguration(
                    b -> b.setEnable().setScopeClass(subpackageClass2.getCanonicalName()).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, class1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
    runR8Test(
        builder ->
            builder
                .addAssertionsConfiguration(
                    b -> b.setEnable().setScopeClass(class1.getCanonicalName()).build())
                .addAssertionsConfiguration(
                    b -> b.setEnable().setScopeClass(subpackageClass2.getCanonicalName()).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, class1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
  }

  @Test
  public void testMixedForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    runD8Test(
        builder ->
            builder
                .addAssertionsConfiguration(b -> b.setEnable().setScopePackage(packageName).build())
                .addAssertionsConfiguration(
                    b -> b.setDisable().setScopeClass(class2.getCanonicalName()).build())
                .addAssertionsConfiguration(
                    b -> b.setDisable().setScopeClass(subpackageClass1.getCanonicalName()).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, class1);
          checkAssertionCodeRemoved(inspector, class2);
          checkAssertionCodeRemoved(inspector, subpackageClass1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
    runR8Test(
        builder ->
            builder
                .addAssertionsConfiguration(b -> b.setEnable().setScopePackage(packageName).build())
                .addAssertionsConfiguration(
                    b -> b.setDisable().setScopeClass(class2.getCanonicalName()).build())
                .addAssertionsConfiguration(
                    b -> b.setDisable().setScopeClass(subpackageClass1.getCanonicalName()).build()),
        inspector -> {
          checkAssertionCodeEnabled(inspector, class1);
          checkAssertionCodeRemoved(inspector, class2);
          checkAssertionCodeRemoved(inspector, subpackageClass1);
          checkAssertionCodeEnabled(inspector, subpackageClass2);
        },
        ImmutableList.of(
            "AssertionError in testclasses.Class1",
            "AssertionError in testclasses.subpackage.Class2",
            "DONE"));
  }

  @Test
  public void testUnnamedPackageForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    testForD8()
        .addProgramClasses(class1, class2)
        .addProgramClassFileData(
            testClassForUnknownPackage(),
            classInUnnamedPackage("Class1"),
            classInUnnamedPackage("Class2"))
        .setMinApi(parameters.getApiLevel())
        .addAssertionsConfiguration(builder -> builder.setEnable().setScopePackage("").build())
        .compile()
        .inspect(
            inspector -> {
              checkAssertionCodeEnabled(inspector.clazz("Class1"));
              checkAssertionCodeEnabled(inspector.clazz("Class2"));
              checkAssertionCodeRemoved(inspector.clazz(class1));
              checkAssertionCodeRemoved(inspector.clazz(class2));
            })
        .run(parameters.getRuntime(), "Main")
        .assertSuccessWithOutputLines(
            "AssertionError in Class1", "AssertionError in Class2", "DONE");
  }

  @Test
  public void testInnerClassForJvm() throws Exception {
    Assume.assumeTrue(parameters.isCfRuntime());
    // Pointing to the outer class enables assertions for the inner as well.
    testForJvm()
        .addProgramClasses(TestClassForInnerClass.class, TestClassForInnerClass.InnerClass.class)
        .addVmArguments("-ea:" + TestClassForInnerClass.class.getCanonicalName())
        .run(parameters.getRuntime(), TestClassForInnerClass.class)
        .assertSuccessWithOutputLines(
            "AssertionError in TestClassForInnerClass",
            "AssertionError in TestClassForInnerClass.InnerClass",
            "DONE");

    // Pointing to the inner class enables no assertions.
    testForJvm()
        .addProgramClasses(TestClassForInnerClass.class, TestClassForInnerClass.InnerClass.class)
        .addVmArguments("-ea:" + TestClassForInnerClass.InnerClass.class.getCanonicalName())
        .run(parameters.getRuntime(), TestClassForInnerClass.class)
        .assertSuccessWithOutputLines("DONE");
    testForJvm()
        .addProgramClasses(TestClassForInnerClass.class, TestClassForInnerClass.InnerClass.class)
        .addVmArguments("-ea:" + TestClassForInnerClass.InnerClass.class.getTypeName())
        .run(parameters.getRuntime(), TestClassForInnerClass.class)
        .assertSuccessWithOutputLines("DONE");
  }

  @Test
  public void testInnerClassForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    testForD8()
        .addProgramClasses(TestClassForInnerClass.class, TestClassForInnerClass.InnerClass.class)
        .setMinApi(parameters.getApiLevel())
        .addAssertionsConfiguration(
            builder ->
                builder
                    .setEnable()
                    .setScopeClass(TestClassForInnerClass.class.getCanonicalName())
                    .build())
        .compile()
        .inspect(
            inspector -> {
              checkAssertionCodeEnabled(inspector.clazz(TestClassForInnerClass.class));
              checkAssertionCodeEnabled(inspector.clazz(TestClassForInnerClass.InnerClass.class));
            })
        .run(parameters.getRuntime(), TestClassForInnerClass.class)
        .assertSuccessWithOutputLines(
            "AssertionError in TestClassForInnerClass",
            "AssertionError in TestClassForInnerClass.InnerClass",
            "DONE");
  }
  /**
   * Code for the following class in the unnamed package:
   *
   * <p>public class Main { public static void main(String[] args) { try { Class1.m(); } catch
   * (AssertionError e) { System.out.println("AssertionError in Class1"); } try { Class2.m(); }
   * catch (AssertionError e) { System.out.println("AssertionError in Class2"); } try {
   * com.android.tools.r8.rewrite.assertions.Class1.m(); } catch (AssertionError e) {
   * System.out.println("AssertionError in Class1"); } try {
   * com.android.tools.r8.rewrite.assertions.Class2.m(); } catch (AssertionError e) {
   * System.out.println("AssertionError in Class2"); } System.out.println("DONE"); } }
   */
  public static byte[] testClassForUnknownPackage() {

    ClassWriter classWriter = new ClassWriter(0);
    MethodVisitor methodVisitor;

    classWriter.visit(V1_8, ACC_FINAL | ACC_SUPER, "Main", null, "java/lang/Object", null);

    classWriter.visitSource("Main.java", null);

    {
      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(1, label0);
      methodVisitor.visitVarInsn(ALOAD, 0);
      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(1, 1);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor =
          classWriter.visitMethod(
              ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      Label label1 = new Label();
      Label label2 = new Label();
      methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/AssertionError");
      Label label3 = new Label();
      Label label4 = new Label();
      Label label5 = new Label();
      methodVisitor.visitTryCatchBlock(label3, label4, label5, "java/lang/AssertionError");
      Label label6 = new Label();
      Label label7 = new Label();
      Label label8 = new Label();
      methodVisitor.visitTryCatchBlock(label6, label7, label8, "java/lang/AssertionError");
      Label label9 = new Label();
      Label label10 = new Label();
      Label label11 = new Label();
      methodVisitor.visitTryCatchBlock(label9, label10, label11, "java/lang/AssertionError");
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(4, label0);
      methodVisitor.visitMethodInsn(INVOKESTATIC, "Class1", "m", "()V", false);
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(7, label1);
      methodVisitor.visitJumpInsn(GOTO, label3);
      methodVisitor.visitLabel(label2);
      methodVisitor.visitLineNumber(5, label2);
      methodVisitor.visitFrame(
          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AssertionError"});
      methodVisitor.visitVarInsn(ASTORE, 1);
      Label label12 = new Label();
      methodVisitor.visitLabel(label12);
      methodVisitor.visitLineNumber(6, label12);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitLdcInsn("AssertionError in Class1");
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
      methodVisitor.visitLabel(label3);
      methodVisitor.visitLineNumber(9, label3);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitMethodInsn(INVOKESTATIC, "Class2", "m", "()V", false);
      methodVisitor.visitLabel(label4);
      methodVisitor.visitLineNumber(12, label4);
      methodVisitor.visitJumpInsn(GOTO, label6);
      methodVisitor.visitLabel(label5);
      methodVisitor.visitLineNumber(10, label5);
      methodVisitor.visitFrame(
          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AssertionError"});
      methodVisitor.visitVarInsn(ASTORE, 1);
      Label label13 = new Label();
      methodVisitor.visitLabel(label13);
      methodVisitor.visitLineNumber(11, label13);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitLdcInsn("AssertionError in Class2");
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
      methodVisitor.visitLabel(label6);
      methodVisitor.visitLineNumber(14, label6);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC,
          "com/android/tools/r8/rewrite/assertions/testclasses/Class1",
          "m",
          "()V",
          false);
      methodVisitor.visitLabel(label7);
      methodVisitor.visitLineNumber(17, label7);
      methodVisitor.visitJumpInsn(GOTO, label9);
      methodVisitor.visitLabel(label8);
      methodVisitor.visitLineNumber(15, label8);
      methodVisitor.visitFrame(
          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AssertionError"});
      methodVisitor.visitVarInsn(ASTORE, 1);
      Label label14 = new Label();
      methodVisitor.visitLabel(label14);
      methodVisitor.visitLineNumber(16, label14);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitLdcInsn("AssertionError in testclasses.Class1");
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
      methodVisitor.visitLabel(label9);
      methodVisitor.visitLineNumber(19, label9);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitMethodInsn(
          INVOKESTATIC,
          "com/android/tools/r8/rewrite/assertions/testclasses/Class2",
          "m",
          "()V",
          false);
      methodVisitor.visitLabel(label10);
      methodVisitor.visitLineNumber(22, label10);
      Label label15 = new Label();
      methodVisitor.visitJumpInsn(GOTO, label15);
      methodVisitor.visitLabel(label11);
      methodVisitor.visitLineNumber(20, label11);
      methodVisitor.visitFrame(
          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AssertionError"});
      methodVisitor.visitVarInsn(ASTORE, 1);
      Label label16 = new Label();
      methodVisitor.visitLabel(label16);
      methodVisitor.visitLineNumber(21, label16);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitLdcInsn("AssertionError in testclasses.Class2");
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
      methodVisitor.visitLabel(label15);
      methodVisitor.visitLineNumber(24, label15);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
      methodVisitor.visitLdcInsn("DONE");
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
      Label label17 = new Label();
      methodVisitor.visitLabel(label17);
      methodVisitor.visitLineNumber(25, label17);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(2, 2);
      methodVisitor.visitEnd();
    }
    classWriter.visitEnd();

    return classWriter.toByteArray();
  }

  /**
   * Code for the following class in the unnamed package:
   *
   * <p>public class <name> { public static void m() { assert false; } }
   */
  public static byte[] classInUnnamedPackage(String name) {

    ClassWriter classWriter = new ClassWriter(0);
    FieldVisitor fieldVisitor;
    MethodVisitor methodVisitor;

    classWriter.visit(V1_8, ACC_PUBLIC | ACC_SUPER, name, null, "java/lang/Object", null);

    classWriter.visitSource(name + ".java", null);

    {
      fieldVisitor =
          classWriter.visitField(
              ACC_FINAL | ACC_STATIC | ACC_SYNTHETIC, "$assertionsDisabled", "Z", null, null);
      fieldVisitor.visitEnd();
    }
    {
      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(1, label0);
      methodVisitor.visitVarInsn(ALOAD, 0);
      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(1, 1);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(3, label0);
      methodVisitor.visitFieldInsn(GETSTATIC, name, "$assertionsDisabled", "Z");
      Label label1 = new Label();
      methodVisitor.visitJumpInsn(IFNE, label1);
      methodVisitor.visitTypeInsn(NEW, "java/lang/AssertionError");
      methodVisitor.visitInsn(DUP);
      methodVisitor.visitMethodInsn(
          INVOKESPECIAL, "java/lang/AssertionError", "<init>", "()V", false);
      methodVisitor.visitInsn(ATHROW);
      methodVisitor.visitLabel(label1);
      methodVisitor.visitLineNumber(4, label1);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(2, 0);
      methodVisitor.visitEnd();
    }
    {
      methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
      methodVisitor.visitCode();
      Label label0 = new Label();
      methodVisitor.visitLabel(label0);
      methodVisitor.visitLineNumber(1, label0);
      methodVisitor.visitLdcInsn(Type.getType("L" + name + ";"));
      methodVisitor.visitMethodInsn(
          INVOKEVIRTUAL, "java/lang/Class", "desiredAssertionStatus", "()Z", false);
      Label label1 = new Label();
      methodVisitor.visitJumpInsn(IFNE, label1);
      methodVisitor.visitInsn(ICONST_1);
      Label label2 = new Label();
      methodVisitor.visitJumpInsn(GOTO, label2);
      methodVisitor.visitLabel(label1);
      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      methodVisitor.visitInsn(ICONST_0);
      methodVisitor.visitLabel(label2);
      methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
      methodVisitor.visitFieldInsn(PUTSTATIC, name, "$assertionsDisabled", "Z");
      methodVisitor.visitInsn(RETURN);
      methodVisitor.visitMaxs(1, 0);
      methodVisitor.visitEnd();
    }
    classWriter.visitEnd();

    return classWriter.toByteArray();
  }

  static class TestClass {
    public static void main(String[] args) {
      try {
        com.android.tools.r8.rewrite.assertions.testclasses.Class1.m();
      } catch (AssertionError e) {
        System.out.println("AssertionError in testclasses.Class1");
      }
      try {
        com.android.tools.r8.rewrite.assertions.testclasses.Class2.m();
      } catch (AssertionError e) {
        System.out.println("AssertionError in testclasses.Class2");
      }
      try {
        com.android.tools.r8.rewrite.assertions.testclasses.subpackage.Class1.m();
      } catch (AssertionError e) {
        System.out.println("AssertionError in testclasses.subpackage.Class1");
      }
      try {
        com.android.tools.r8.rewrite.assertions.testclasses.subpackage.Class2.m();
      } catch (AssertionError e) {
        System.out.println("AssertionError in testclasses.subpackage.Class2");
      }
      System.out.println("DONE");
    }
  }
}
