// 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.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 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;
          options.testing.readInputStackMaps = 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);
    }
  }
}
