// 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;

import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static com.google.common.io.ByteStreams.toByteArray;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.TraceClassVisitor;

public class CfFrontendExamplesTest extends TestBase {

  @Test
  public void testArithmetic() throws Exception {
    runTest("arithmetic.Arithmetic");
  }

  @Test
  public void testArrayAccess() throws Exception {
    runTest("arrayaccess.ArrayAccess");
  }

  @Test
  public void testBArray() throws Exception {
    runTest("barray.BArray");
  }

  @Test
  public void testBridgeMethod() throws Exception {
    runTest("bridge.BridgeMethod");
  }

  @Test
  public void testCommonSubexpressionElimination() throws Exception {
    runTest("cse.CommonSubexpressionElimination");
  }

  @Test
  public void testConstants() throws Exception {
    runTest("constants.Constants");
  }

  @Test
  public void testControlFlow() throws Exception {
    runTest("controlflow.ControlFlow");
  }

  @Test
  public void testConversions() throws Exception {
    runTest("conversions.Conversions");
  }

  @Test
  public void testFloatingPointValuedAnnotation() throws Exception {
    runTest("floating_point_annotations.FloatingPointValuedAnnotationTest");
  }

  @Test
  public void testFilledArray() throws Exception {
    runTest("filledarray.FilledArray");
  }

  @Test
  public void testHello() throws Exception {
    runTest("hello.Hello");
  }

  @Test
  public void testIfStatements() throws Exception {
    runTest("ifstatements.IfStatements");
  }

  @Test
  public void testInlining() throws Exception {
    runTest("inlining.Inlining");
  }

  @Test
  public void testInstanceVariable() throws Exception {
    runTest("instancevariable.InstanceVariable");
  }

  @Test
  public void testInstanceofString() throws Exception {
    runTest("instanceofstring.InstanceofString");
  }

  @Test
  public void testInvoke() throws Exception {
    runTest("invoke.Invoke");
  }

  @Test
  public void testJumboString() throws Exception {
    runTest("jumbostring.JumboString");
  }

  @Test
  public void testLoadConst() throws Exception {
    runTest("loadconst.LoadConst");
  }

  @Test
  public void testUdpServer() throws Exception {
    runTest("loop.UdpServer");
  }

  @Test
  public void testNewArray() throws Exception {
    runTest("newarray.NewArray");
  }

  @Test
  public void testRegAlloc() throws Exception {
    runTest("regalloc.RegAlloc");
  }

  @Test
  public void testReturns() throws Exception {
    runTest("returns.Returns");
  }

  @Test
  public void testStaticField() throws Exception {
    runTest("staticfield.StaticField");
  }

  @Test
  public void testStringBuilding() throws Exception {
    runTest("stringbuilding.StringBuilding");
  }

  @Test
  public void testSwitches() throws Exception {
    runTest("switches.Switches");
  }

  @Test
  public void testSync() throws Exception {
    runTest("sync.Sync");
  }

  @Test
  public void testThrowing() throws Exception {
    runTest("throwing.Throwing");
  }

  @Test
  public void testTrivial() throws Exception {
    runTest("trivial.Trivial");
  }

  @Test
  public void testTryCatch() throws Exception {
    runTest("trycatch.TryCatch");
  }

  @Test
  public void testNestedTryCatches() throws Exception {
    runTest("nestedtrycatches.NestedTryCatches");
  }

  @Test
  public void testTryCatchMany() throws Exception {
    runTest("trycatchmany.TryCatchMany");
  }

  @Test
  public void testInvokeEmpty() throws Exception {
    runTest("invokeempty.InvokeEmpty");
  }

  @Test
  public void testRegress() throws Exception {
    runTest("regress.Regress");
  }

  @Test
  public void testRegress2() throws Exception {
    runTest("regress2.Regress2");
  }

  @Test
  public void testRegress37726195() throws Exception {
    runTest("regress_37726195.Regress");
  }

  @Test
  public void testRegress37658666() throws Exception {
    runTest(
        "regress_37658666.Regress",
        (expected, actual) -> {
          // javac emits LDC(-0.0f) instead of the shorter FCONST_0 FNEG emitted by CfConstNumber.
          String ldc = "methodVisitor.visitLdcInsn(new Float(\"-0.0\"));";
          String constNeg = "methodVisitor.visitInsn(FCONST_0);\nmethodVisitor.visitInsn(FNEG);";
          assertEquals(expected.replace(ldc, constNeg), actual);
        });
  }

  @Test
  public void testRegress37875803() throws Exception {
    runTest("regress_37875803.Regress");
  }

  @Test
  public void testRegress37955340() throws Exception {
    runTest("regress_37955340.Regress");
  }

  @Test
  public void testRegress62300145() throws Exception {
    runTest("regress_62300145.Regress");
  }

  @Test
  public void testRegress64881691() throws Exception {
    runTest("regress_64881691.Regress");
  }

  @Test
  public void testRegress65104300() throws Exception {
    runTest("regress_65104300.Regress");
  }

  @Test
  public void testRegress70703087() throws Exception {
    runTest("regress_70703087.Test");
  }

  @Test
  public void testRegress70736958() throws Exception {
    runTest("regress_70736958.Test");
  }

  @Test
  public void testRegress70737019() throws Exception {
    runTest("regress_70737019.Test");
  }

  @Test
  public void testRegress72361252() throws Exception {
    runTest("regress_72361252.Test");
  }

  @Test
  public void testMemberrebinding2() throws Exception {
    runTest("memberrebinding2.Memberrebinding");
  }

  @Test
  public void testMemberrebinding3() throws Exception {
    runTest("memberrebinding3.Memberrebinding");
  }

  @Test
  public void testMinification() throws Exception {
    runTest("minification.Minification");
  }

  @Test
  public void testEnclosingmethod() throws Exception {
    runTest("enclosingmethod.Main");
  }

  @Test
  public void testEnclosingmethodProguarded() throws Exception {
    runTest("enclosingmethod_proguarded.Main");
  }

  @Test
  public void testInterfaceInlining() throws Exception {
    runTest("interfaceinlining.Main");
  }

  @Test
  public void testSwitchmaps() throws Exception {
    runTest("switchmaps.Switches");
  }

  private void runTest(String clazz) throws Exception {
    runTest(
        clazz, (expected, actual) -> assertEquals("Class " + clazz + " differs", expected, actual));
  }

  private void runTest(String clazz, BiConsumer<String, String> comparator) throws Exception {
    assert comparator != null;
    String pkg = clazz.substring(0, clazz.lastIndexOf('.'));
    String suffix = "_debuginfo_all";
    Path inputJar = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, pkg + suffix + JAR_EXTENSION);
    Path outputJar = temp.getRoot().toPath().resolve("output.jar");
    R8Command command =
        R8Command.builder()
            .addProgramFiles(inputJar)
            .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
            .setMode(CompilationMode.DEBUG)
            .setDisableTreeShaking(true)
            .setDisableMinification(true)
            .addProguardConfiguration(ImmutableList.of("-keepattributes *"), Origin.unknown())
            .setOutput(outputJar, OutputMode.ClassFile)
            .build();
    ToolHelper.runR8(
        command,
        options -> {
          options.skipIR = true;
          options.enableCfFrontend = true;
        });
    ArchiveClassFileProvider expected = new ArchiveClassFileProvider(inputJar);
    ArchiveClassFileProvider actual = new ArchiveClassFileProvider(outputJar);
    assertEquals(getSortedDescriptorList(expected), getSortedDescriptorList(actual));
    for (String descriptor : expected.getClassDescriptors()) {
      byte[] expectedBytes = getClassAsBytes(expected, descriptor);
      byte[] actualBytes = getClassAsBytes(actual, descriptor);
      if (!Arrays.equals(expectedBytes, actualBytes)) {
        String expectedString = replaceCatchThrowableByCatchAll(asmToString(expectedBytes));
        String actualString = asmToString(actualBytes);
        comparator.accept(expectedString, actualString);
      }
    }
  }

  private static String replaceCatchThrowableByCatchAll(String content) {
    String catchThrowablePrefix = "methodVisitor.visitTryCatchBlock(";
    String catchThrowableSuffix = ", \"java/lang/Throwable\");";
    StringBuilder expected = new StringBuilder();
    List<String> expectedLines = StringUtils.splitLines(content);
    for (String line : expectedLines) {
      if (line.startsWith(catchThrowablePrefix) && line.endsWith(catchThrowableSuffix)) {
        expected.append(line.replace("\"java/lang/Throwable\"", "null"));
      } else {
        expected.append(line);
      }
      expected.append('\n');
    }
    return expected.toString();
  }

  private static List<String> getSortedDescriptorList(ArchiveClassFileProvider inputJar) {
    ArrayList<String> descriptorList = new ArrayList<>(inputJar.getClassDescriptors());
    Collections.sort(descriptorList);
    return descriptorList;
  }

  private static byte[] getClassAsBytes(ArchiveClassFileProvider inputJar, String descriptor)
      throws Exception {
    return toByteArray(inputJar.getProgramResource(descriptor).getByteStream());
  }

  private static String asmToString(byte[] clazz) {
    StringWriter stringWriter = new StringWriter();
    printAsm(new PrintWriter(stringWriter), clazz);
    return stringWriter.toString();
  }

  private static void printAsm(PrintWriter pw, byte[] clazz) {
    new ClassReader(clazz).accept(new TraceClassVisitor(null, new ASMifierSorted(), pw), 0);
  }

  /** Sort methods and fields in the output of ASMifier to make diffing possible. */
  private static class ASMifierSorted extends ASMifier {
    private static class Part implements Comparable<Part> {

      private final String key;
      private final int start;
      private final int end;

      Part(String key, int start, int end) {
        this.key = key;
        this.start = start;
        this.end = end;
      }

      @Override
      public int compareTo(Part part) {
        int i = key.compareTo(part.key);
        return i != 0 ? i : Integer.compare(start, part.start);
      }
    }

    private final List<Part> parts = new ArrayList<>();

    ASMifierSorted() {
      super(InternalOptions.ASM_VERSION, "cw", 0);
    }

    @Override
    public ASMifier visitField(
        int access, String name, String desc, String signature, Object value) {
      init();
      int i = text.size();
      ASMifier res = super.visitField(access, name, desc, signature, value);
      parts.add(new Part((String) text.get(i), i, text.size()));
      return res;
    }

    @Override
    public ASMifier visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      init();
      int i = text.size();
      ASMifier res = super.visitMethod(access, name, desc, signature, exceptions);
      parts.add(new Part((String) text.get(i), i, text.size()));
      return res;
    }

    private void init() {
      if (parts.isEmpty()) {
        parts.add(new Part("", 0, text.size()));
      }
    }

    @Override
    public void print(PrintWriter pw) {
      init();
      int end = parts.get(parts.size() - 1).end;
      Collections.sort(parts);
      parts.add(new Part("", end, text.size()));
      ArrayList<Object> tmp = new ArrayList<>(text);
      text.clear();
      for (Part part : parts) {
        for (int i = part.start; i < part.end; i++) {
          text.add(tmp.get(i));
        }
      }
      super.print(pw);
    }
  }
}
