// 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.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
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 java.util.function.Function;
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(
      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
          assertionsConfigurationBuilder,
      ThrowingConsumer<CodeInspector, RuntimeException> inspector,
      List<String> outputLines)
      throws Exception {
    testForD8()
        .addProgramClasses(testClasses)
        .setMinApi(parameters.getApiLevel())
        .addAssertionsConfiguration(assertionsConfigurationBuilder)
        .compile()
        .inspect(inspector)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(StringUtils.lines(outputLines));
  }

  public void runR8Test(
      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
          assertionsConfigurationBuilder,
      ThrowingConsumer<CodeInspector, RuntimeException> inspector,
      List<String> outputLines)
      throws Exception {
    runR8Test(assertionsConfigurationBuilder, inspector, outputLines, false);
  }

  public void runR8Test(
      Function<AssertionsConfiguration.Builder, AssertionsConfiguration>
          assertionsConfigurationBuilder,
      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())
        .addAssertionsConfiguration(assertionsConfigurationBuilder)
        .compile()
        .inspect(inspector)
        .enableRuntimeAssertions(enableJvmAssertions)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(StringUtils.lines(outputLines));
  }

  private AssertionsConfiguration enableAllAssertions(AssertionsConfiguration.Builder builder) {
    return builder.enable().build();
  }

  private AssertionsConfiguration disableAllAssertions(AssertionsConfiguration.Builder builder) {
    return builder.disable().build();
  }

  private AssertionsConfiguration leaveAllAssertions(AssertionsConfiguration.Builder builder) {
    return builder.passthrough().build();
  }

  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(
        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
    runR8Test(
        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
    runD8Test(
        this::disableAllAssertions,
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    runR8Test(
        this::disableAllAssertions,
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    // Compile time enabling assertions gives assertions on Dalvik/Art.
    runD8Test(
        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
    runR8Test(
        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
    // Enabling for the package should enable all.
    runD8Test(
        builder -> builder.enableForPackage(packageName).build(),
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines());
    runR8Test(
        builder -> builder.enableForPackage(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(
        this::leaveAllAssertions, this::checkAssertionCodeLeft, noAllAssertionsExpectedLines());
    runR8Test(
        this::leaveAllAssertions, this::checkAssertionCodeLeft, allAssertionsExpectedLines(), true);
    // Compile time enabling or disabling assertions means the -ea flag has no effect.
    runR8Test(
        this::enableAllAssertions, this::checkAssertionCodeEnabled, allAssertionsExpectedLines());
    runR8Test(
        this::enableAllAssertions,
        this::checkAssertionCodeEnabled,
        allAssertionsExpectedLines(),
        true);
    runR8Test(
        this::disableAllAssertions,
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines());
    runR8Test(
        this::disableAllAssertions,
        this::checkAssertionCodeRemoved,
        noAllAssertionsExpectedLines(),
        true);
  }

  @Test
  public void testEnableForPackageForDex() throws Exception {
    Assume.assumeTrue(parameters.isDexRuntime());
    runD8Test(
        builder -> builder.enableForPackage(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.enableForPackage(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
                .enableForClass(class1.getCanonicalName())
                .enableForClass(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
                .enableForClass(class1.getCanonicalName())
                .enableForClass(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
                .enableForPackage(packageName)
                .disableForClass(class2.getCanonicalName())
                .disableForClass(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
                .enableForPackage(packageName)
                .disableForClass(class2.getCanonicalName())
                .disableForClass(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.enableForPackage("").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.enableForClass(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");
    }
  }
}
