// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android.desugar;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.android.desugar.runtime.ThrowableExtensionTestUtility.getStrategyClassName;
import static com.google.devtools.build.android.desugar.runtime.ThrowableExtensionTestUtility.getTwrStrategyClassNameSpecifiedInSystemProperty;
import static com.google.devtools.build.android.desugar.runtime.ThrowableExtensionTestUtility.isMimicStrategy;
import static com.google.devtools.build.android.desugar.runtime.ThrowableExtensionTestUtility.isNullStrategy;
import static com.google.devtools.build.android.desugar.runtime.ThrowableExtensionTestUtility.isReuseStrategy;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import static org.junit.Assert.fail;
import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
import static org.objectweb.asm.Opcodes.ASM5;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;

import com.google.devtools.build.android.desugar.io.BitFlags;
import com.google.devtools.build.android.desugar.runtime.ThrowableExtension;
import com.google.devtools.build.android.desugar.testdata.ClassUsingTryWithResources;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/** This is the unit test for {@link TryWithResourcesRewriter} */
@RunWith(JUnit4.class)
public class TryWithResourcesRewriterTest {

  private final DesugaringClassLoader classLoader =
      new DesugaringClassLoader(ClassUsingTryWithResources.class.getName());
  private Class<?> desugaredClass;

  @Before
  public void setup() {
    try {
      desugaredClass = classLoader.findClass(ClassUsingTryWithResources.class.getName());
    } catch (ClassNotFoundException e) {
      throw new AssertionError(e);
    }
  }

  @Test
  public void testMethodsAreDesugared() {
    // verify whether the desugared class is indeed desugared.
    DesugaredThrowableMethodCallCounter origCounter =
        countDesugaredThrowableMethodCalls(ClassUsingTryWithResources.class);
    DesugaredThrowableMethodCallCounter desugaredCounter =
        countDesugaredThrowableMethodCalls(classLoader.classContent, classLoader);
    /**
     * In java9, javac creates a helper method {@code $closeResource(Throwable, AutoCloseable)
     * to close resources. So, the following number 3 is highly dependant on the version of javac.
     */
    assertThat(hasAutoCloseable(classLoader.classContent)).isFalse();
    assertThat(classLoader.numOfTryWithResourcesInvoked.intValue()).isAtLeast(2);
    assertThat(classLoader.visitedExceptionTypes)
        .containsExactly(
            "java/lang/Exception", "java/lang/Throwable", "java/io/UnsupportedEncodingException");
    assertDesugaringBehavior(origCounter, desugaredCounter);
  }

  @Test
  public void testCheckSuppressedExceptionsReturningEmptySuppressedExceptions() {
    {
      Throwable[] suppressed = ClassUsingTryWithResources.checkSuppressedExceptions(false);
      assertThat(suppressed).isEmpty();
    }
    try {
      Throwable[] suppressed =
          (Throwable[])
              desugaredClass
                  .getMethod("checkSuppressedExceptions", boolean.class)
                  .invoke(null, Boolean.FALSE);
      assertThat(suppressed).isEmpty();
    } catch (Exception e) {
      e.printStackTrace();
      throw new AssertionError(e);
    }
  }

  @Test
  public void testPrintStackTraceOfCaughtException() {
    {
      String trace = ClassUsingTryWithResources.printStackTraceOfCaughtException();
      assertThat(trace.toLowerCase()).contains("suppressed");
    }
    try {
      String trace =
          (String) desugaredClass.getMethod("printStackTraceOfCaughtException").invoke(null);

      if (isMimicStrategy()) {
        assertThat(trace.toLowerCase()).contains("suppressed");
      } else if (isReuseStrategy()) {
        assertThat(trace.toLowerCase()).contains("suppressed");
      } else if (isNullStrategy()) {
        assertThat(trace.toLowerCase()).doesNotContain("suppressed");
      } else {
        fail("unexpected desugaring strategy " + ThrowableExtension.getStrategy());
      }
    } catch (Exception e) {
      e.printStackTrace();
      throw new AssertionError(e);
    }
  }

  @Test
  public void testCheckSuppressedExceptionReturningOneSuppressedException() {
    {
      Throwable[] suppressed = ClassUsingTryWithResources.checkSuppressedExceptions(true);
      assertThat(suppressed).hasLength(1);
    }
    try {
      Throwable[] suppressed =
          (Throwable[])
              desugaredClass
                  .getMethod("checkSuppressedExceptions", boolean.class)
                  .invoke(null, Boolean.TRUE);

      if (isMimicStrategy()) {
        assertThat(suppressed).hasLength(1);
      } else if (isReuseStrategy()) {
        assertThat(suppressed).hasLength(1);
      } else if (isNullStrategy()) {
        assertThat(suppressed).isEmpty();
      } else {
        fail("unexpected desugaring strategy " + ThrowableExtension.getStrategy());
      }
    } catch (Exception e) {
      e.printStackTrace();
      throw new AssertionError(e);
    }
  }

  @Test
  public void testSimpleTryWithResources() throws Throwable {
    {
      RuntimeException expected =
          assertThrows(
              RuntimeException.class, () -> ClassUsingTryWithResources.simpleTryWithResources());
      assertThat(expected.getClass()).isEqualTo(RuntimeException.class);
      assertThat(expected.getSuppressed()).hasLength(1);
      assertThat(expected.getSuppressed()[0].getClass()).isEqualTo(IOException.class);
    }

    try {
      InvocationTargetException e =
          assertThrows(
              InvocationTargetException.class,
              () -> desugaredClass.getMethod("simpleTryWithResources").invoke(null));
      throw e.getCause();
    } catch (RuntimeException expected) {
      String expectedStrategyName = getTwrStrategyClassNameSpecifiedInSystemProperty();
      assertThat(getStrategyClassName()).isEqualTo(expectedStrategyName);
      if (isMimicStrategy()) {
        assertThat(expected.getSuppressed()).isEmpty();
        assertThat(ThrowableExtension.getSuppressed(expected)).hasLength(1);
        assertThat(ThrowableExtension.getSuppressed(expected)[0].getClass())
            .isEqualTo(IOException.class);
      } else if (isReuseStrategy()) {
        assertThat(expected.getSuppressed()).hasLength(1);
        assertThat(expected.getSuppressed()[0].getClass()).isEqualTo(IOException.class);
        assertThat(ThrowableExtension.getSuppressed(expected)[0].getClass())
            .isEqualTo(IOException.class);
      } else if (isNullStrategy()) {
        assertThat(expected.getSuppressed()).isEmpty();
        assertThat(ThrowableExtension.getSuppressed(expected)).isEmpty();
      } else {
        fail("unexpected desugaring strategy " + ThrowableExtension.getStrategy());
      }
    }
  }

  private static void assertDesugaringBehavior(
      DesugaredThrowableMethodCallCounter orig, DesugaredThrowableMethodCallCounter desugared) {
    assertThat(desugared.countThrowableGetSuppressed()).isEqualTo(orig.countExtGetSuppressed());
    assertThat(desugared.countThrowableAddSuppressed()).isEqualTo(orig.countExtAddSuppressed());
    assertThat(desugared.countThrowablePrintStackTrace()).isEqualTo(orig.countExtPrintStackTrace());
    assertThat(desugared.countThrowablePrintStackTracePrintStream())
        .isEqualTo(orig.countExtPrintStackTracePrintStream());
    assertThat(desugared.countThrowablePrintStackTracePrintWriter())
        .isEqualTo(orig.countExtPrintStackTracePrintWriter());

    assertThat(orig.countThrowableGetSuppressed()).isEqualTo(desugared.countExtGetSuppressed());
    // $closeResource may be specialized into multiple versions.
    assertThat(orig.countThrowableAddSuppressed()).isAtMost(desugared.countExtAddSuppressed());
    assertThat(orig.countThrowablePrintStackTrace()).isEqualTo(desugared.countExtPrintStackTrace());
    assertThat(orig.countThrowablePrintStackTracePrintStream())
        .isEqualTo(desugared.countExtPrintStackTracePrintStream());
    assertThat(orig.countThrowablePrintStackTracePrintWriter())
        .isEqualTo(desugared.countExtPrintStackTracePrintWriter());

    if (orig.getSyntheticCloseResourceCount() > 0) {
      // Depending on the specific javac version, $closeResource(Throwable, AutoCloseable) may not
      // be there.
      assertThat(orig.getSyntheticCloseResourceCount()).isEqualTo(1);
      assertThat(desugared.getSyntheticCloseResourceCount()).isAtLeast(1);
    }
    assertThat(desugared.countThrowablePrintStackTracePrintStream()).isEqualTo(0);
    assertThat(desugared.countThrowablePrintStackTracePrintStream()).isEqualTo(0);
    assertThat(desugared.countThrowablePrintStackTracePrintWriter()).isEqualTo(0);
    assertThat(desugared.countThrowableAddSuppressed()).isEqualTo(0);
    assertThat(desugared.countThrowableGetSuppressed()).isEqualTo(0);
  }

  private static DesugaredThrowableMethodCallCounter countDesugaredThrowableMethodCalls(
      Class<?> klass) {
    try {
      ClassReader reader = new ClassReader(klass.getName());
      DesugaredThrowableMethodCallCounter counter =
          new DesugaredThrowableMethodCallCounter(klass.getClassLoader());
      reader.accept(counter, 0);
      return counter;
    } catch (IOException e) {
      e.printStackTrace();
      fail(e.toString());
      return null;
    }
  }

  private static DesugaredThrowableMethodCallCounter countDesugaredThrowableMethodCalls(
      byte[] content, ClassLoader loader) {
    ClassReader reader = new ClassReader(content);
    DesugaredThrowableMethodCallCounter counter = new DesugaredThrowableMethodCallCounter(loader);
    reader.accept(counter, 0);
    return counter;
  }

  /** Check whether java.lang.AutoCloseable is used as arguments of any method. */
  private static boolean hasAutoCloseable(byte[] classContent) {
    ClassReader reader = new ClassReader(classContent);
    final AtomicInteger counter = new AtomicInteger();
    ClassVisitor visitor =
        new ClassVisitor(Opcodes.ASM5) {
          @Override
          public MethodVisitor visitMethod(
              int access, String name, String desc, String signature, String[] exceptions) {
            for (Type argumentType : Type.getArgumentTypes(desc)) {
              if ("Ljava/lang/AutoCloseable;".equals(argumentType.getDescriptor())) {
                counter.incrementAndGet();
              }
            }
            return null;
          }
        };
    reader.accept(visitor, 0);
    return counter.get() > 0;
  }

  private static class DesugaredThrowableMethodCallCounter extends ClassVisitor {
    private final ClassLoader classLoader;
    private final Map<String, AtomicInteger> counterMap;
    private int syntheticCloseResourceCount;

    public DesugaredThrowableMethodCallCounter(ClassLoader loader) {
      super(ASM5);
      classLoader = loader;
      counterMap = new HashMap<>();
      TryWithResourcesRewriter.TARGET_METHODS
          .entries()
          .forEach(entry -> counterMap.put(entry.getKey() + entry.getValue(), new AtomicInteger()));
      TryWithResourcesRewriter.TARGET_METHODS
          .entries()
          .forEach(
              entry ->
                  counterMap.put(
                      entry.getKey()
                          + TryWithResourcesRewriter.METHOD_DESC_MAP.get(entry.getValue()),
                      new AtomicInteger()));
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if (BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC)
          && name.equals("$closeResource")
          && Type.getArgumentTypes(desc).length == 2
          && Type.getArgumentTypes(desc)[0].getDescriptor().equals("Ljava/lang/Throwable;")) {
        ++syntheticCloseResourceCount;
      }
      return new InvokeCounter();
    }

    private class InvokeCounter extends MethodVisitor {

      public InvokeCounter() {
        super(ASM5);
      }

      private boolean isAssignableToThrowable(String owner) {
        try {
          Class<?> ownerClass = classLoader.loadClass(owner.replace('/', '.'));
          return Throwable.class.isAssignableFrom(ownerClass);
        } catch (ClassNotFoundException e) {
          throw new AssertionError(e);
        }
      }

      @Override
      public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
        String signature = name + desc;
        if ((opcode == INVOKEVIRTUAL && isAssignableToThrowable(owner))
            || (opcode == INVOKESTATIC
                && Type.getInternalName(ThrowableExtension.class).equals(owner))) {
          AtomicInteger counter = counterMap.get(signature);
          if (counter == null) {
            return;
          }
          counter.incrementAndGet();
        }
      }
    }

    public int getSyntheticCloseResourceCount() {
      return syntheticCloseResourceCount;
    }

    public int countThrowableAddSuppressed() {
      return counterMap.get("addSuppressed(Ljava/lang/Throwable;)V").get();
    }

    public int countThrowableGetSuppressed() {
      return counterMap.get("getSuppressed()[Ljava/lang/Throwable;").get();
    }

    public int countThrowablePrintStackTrace() {
      return counterMap.get("printStackTrace()V").get();
    }

    public int countThrowablePrintStackTracePrintStream() {
      return counterMap.get("printStackTrace(Ljava/io/PrintStream;)V").get();
    }

    public int countThrowablePrintStackTracePrintWriter() {
      return counterMap.get("printStackTrace(Ljava/io/PrintWriter;)V").get();
    }

    public int countExtAddSuppressed() {
      return counterMap.get("addSuppressed(Ljava/lang/Throwable;Ljava/lang/Throwable;)V").get();
    }

    public int countExtGetSuppressed() {
      return counterMap.get("getSuppressed(Ljava/lang/Throwable;)[Ljava/lang/Throwable;").get();
    }

    public int countExtPrintStackTrace() {
      return counterMap.get("printStackTrace(Ljava/lang/Throwable;)V").get();
    }

    public int countExtPrintStackTracePrintStream() {
      return counterMap.get("printStackTrace(Ljava/lang/Throwable;Ljava/io/PrintStream;)V").get();
    }

    public int countExtPrintStackTracePrintWriter() {
      return counterMap.get("printStackTrace(Ljava/lang/Throwable;Ljava/io/PrintWriter;)V").get();
    }
  }

  private static class DesugaringClassLoader extends ClassLoader {

    private final String targetedClassName;
    private Class<?> klass;
    private byte[] classContent;
    private final Set<String> visitedExceptionTypes = new HashSet<>();
    private final AtomicInteger numOfTryWithResourcesInvoked = new AtomicInteger();

    public DesugaringClassLoader(String targetedClassName) {
      super(DesugaringClassLoader.class.getClassLoader());
      this.targetedClassName = targetedClassName;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      if (name.equals(targetedClassName)) {
        if (klass != null) {
          return klass;
        }
        // desugar the class, and return the desugared one.
        classContent = desugarTryWithResources(name);
        klass = defineClass(name, classContent, 0, classContent.length);
        return klass;
      } else {
        return super.findClass(name);
      }
    }

    private byte[] desugarTryWithResources(String className) {
      try {
        ClassReader reader = new ClassReader(className);
        CloseResourceMethodScanner scanner = new CloseResourceMethodScanner();
        reader.accept(scanner, ClassReader.SKIP_DEBUG);
        ClassWriter writer = new ClassWriter(reader, COMPUTE_MAXS);
        TryWithResourcesRewriter rewriter =
            new TryWithResourcesRewriter(
                writer,
                TryWithResourcesRewriterTest.class.getClassLoader(),
                visitedExceptionTypes,
                numOfTryWithResourcesInvoked,
                scanner.hasCloseResourceMethod());
        reader.accept(rewriter, 0);
        return writer.toByteArray();
      } catch (IOException e) {
        fail(e.toString());
        return null; // suppress compiler error.
      }
    }
  }
}
