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

import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
import static com.android.tools.r8.utils.DexInspectorMatchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_SUPER;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.PUTFIELD;
import static org.objectweb.asm.Opcodes.RETURN;
import static org.objectweb.asm.Opcodes.V1_8;

import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DiagnosticsChecker;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.invokesuper.Consumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

public class MinifierClassSignatureTest extends TestBase {
  /*

  class Simple {
  }
  class Base<T> {
  }
  class Outer<T> {
    class Inner {
      class InnerInner {
      }
      class ExtendsInnerInner extends InnerInner {
      }
    }
    class ExtendsInner extends Inner {
    }
  }

  */

  String baseSignature = "<T:Ljava/lang/Object;>Ljava/lang/Object;";
  String outerSignature = "<T:Ljava/lang/Object;>Ljava/lang/Object;";
  String extendsInnerSignature = "LOuter<TT;>.Inner;";
  String extendsInnerInnerSignature = "LOuter<TT;>.Inner.InnerInner;";

  private byte[] dumpSimple(String classSignature) throws Exception {

    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    String signature = classSignature;
    cw.visit(V1_8, ACC_SUPER, "Simple", signature, "java/lang/Object", null);

    {
      mv = cw.visitMethod(0, "<init>", "()V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(1, 1);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  private byte[] dumpBase(String classSignature) throws Exception {

    final String javacClassSignature = baseSignature;
    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Base", signature, "java/lang/Object", null);

    {
      mv = cw.visitMethod(0, "<init>", "()V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(1, 1);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }


  private byte[] dumpOuter(String classSignature) {

    final String javacClassSignature = outerSignature;
    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Outer", signature, "java/lang/Object", null);

    cw.visitInnerClass("Outer$ExtendsInner", "Outer", "ExtendsInner", 0);

    cw.visitInnerClass("Outer$Inner", "Outer", "Inner", 0);

    {
      mv = cw.visitMethod(0, "<init>", "()V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(1, 1);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  private byte[] dumpInner(String classSignature) {

    final String javacClassSignature = null;
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Outer$Inner", signature, "java/lang/Object", null);

    cw.visitInnerClass("Outer$Inner", "Outer", "Inner", 0);

    cw.visitInnerClass("Outer$Inner$ExtendsInnerInner", "Outer$Inner", "ExtendsInnerInner", 0);

    cw.visitInnerClass("Outer$Inner$InnerInner", "Outer$Inner", "InnerInner", 0);

    {
      fv = cw.visitField(ACC_FINAL + ACC_SYNTHETIC, "this$0", "LOuter;", null, null);
      fv.visitEnd();
    }
    {
      mv = cw.visitMethod(0, "<init>", "(LOuter;)V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(PUTFIELD, "Outer$Inner", "this$0", "LOuter;");
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(2, 2);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  private byte[] dumpExtendsInner(String classSignature) throws Exception {

    final String javacClassSignature = extendsInnerSignature;
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Outer$ExtendsInner", signature, "Outer$Inner", null);

    cw.visitInnerClass("Outer$Inner", "Outer", "Inner", 0);

    cw.visitInnerClass("Outer$ExtendsInner", "Outer", "ExtendsInner", 0);

    {
      fv = cw.visitField(ACC_FINAL + ACC_SYNTHETIC, "this$0", "LOuter;", null, null);
      fv.visitEnd();
    }
    {
      mv = cw.visitMethod(0, "<init>", "(LOuter;)V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(PUTFIELD, "Outer$ExtendsInner", "this$0", "LOuter;");
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(INVOKESPECIAL, "Outer$Inner", "<init>", "(LOuter;)V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(2, 2);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  private byte[] dumpInnerInner(String classSignature) throws Exception {

    final String javacClassSignature = null;
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Outer$Inner$InnerInner", signature, "java/lang/Object", null);

    cw.visitInnerClass("Outer$Inner", "Outer", "Inner", 0);

    cw.visitInnerClass("Outer$Inner$InnerInner", "Outer$Inner", "InnerInner", 0);

    {
      fv = cw.visitField(ACC_FINAL + ACC_SYNTHETIC, "this$1", "LOuter$Inner;", null, null);
      fv.visitEnd();
    }
    {
      mv = cw.visitMethod(0, "<init>", "(LOuter$Inner;)V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(PUTFIELD, "Outer$Inner$InnerInner", "this$1", "LOuter$Inner;");
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(2, 2);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  private byte[] dumpExtendsInnerInner(String classSignature) throws Exception {

    final String javacClassSignature = extendsInnerInnerSignature;
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;

    String signature = classSignature != null ? classSignature : javacClassSignature;
    cw.visit(V1_8, ACC_SUPER, "Outer$Inner$ExtendsInnerInner", signature, "Outer$Inner$InnerInner",
        null);

    cw.visitInnerClass("Outer$Inner", "Outer", "Inner", 0);

    cw.visitInnerClass("Outer$Inner$InnerInner", "Outer$Inner", "InnerInner", 0);

    cw.visitInnerClass("Outer$Inner$ExtendsInnerInner", "Outer$Inner", "ExtendsInnerInner", 0);

    {
      fv = cw.visitField(ACC_FINAL + ACC_SYNTHETIC, "this$1", "LOuter$Inner;", null, null);
      fv.visitEnd();
    }
    {
      mv = cw.visitMethod(0, "<init>", "(LOuter$Inner;)V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(PUTFIELD, "Outer$Inner$ExtendsInnerInner", "this$1", "LOuter$Inner;");
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(INVOKESPECIAL, "Outer$Inner$InnerInner", "<init>", "(LOuter$Inner;)V",
          false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(2, 2);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

  public void runTest(
      ImmutableMap<String, String> signatures,
      Consumer<DiagnosticsChecker> diagnostics,
      Consumer<DexInspector> inspect)
      throws Exception {
    DiagnosticsChecker checker = new DiagnosticsChecker();
    DexInspector inspector = new DexInspector(
      ToolHelper.runR8(R8Command.builder(checker)
          .addClassProgramData(dumpSimple(signatures.get("Simple")), Origin.unknown())
          .addClassProgramData(dumpBase(signatures.get("Base")), Origin.unknown())
          .addClassProgramData(dumpOuter(signatures.get("Outer")), Origin.unknown())
          .addClassProgramData(dumpInner(signatures.get("Outer$Inner")), Origin.unknown())
          .addClassProgramData(
              dumpExtendsInner(signatures.get("Outer$ExtendsInner")), Origin.unknown())
          .addClassProgramData(
              dumpInnerInner(signatures.get("Outer$Inner$InnerInner")), Origin.unknown())
          .addClassProgramData(
              dumpExtendsInnerInner(
                  signatures.get("Outer$Inner$ExtendsInnerInner")), Origin.unknown())
          .addProguardConfiguration(ImmutableList.of(
              "-keepattributes InnerClasses,EnclosingMethod,Signature",
              "-keep,allowobfuscation class **"
          ), Origin.unknown())
          .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
          .setProguardMapConsumer(StringConsumer.emptyConsumer())
          .build()));
    // All classes are kept, and renamed.
    assertThat(inspector.clazz("Simple"), isRenamed());
    assertThat(inspector.clazz("Base"), isRenamed());
    assertThat(inspector.clazz("Outer"), isRenamed());
    assertThat(inspector.clazz("Outer$Inner"), isRenamed());
    assertThat(inspector.clazz("Outer$ExtendsInner"), isRenamed());
    assertThat(inspector.clazz("Outer$Inner$InnerInner"), isRenamed());
    assertThat(inspector.clazz("Outer$Inner$ExtendsInnerInner"), isRenamed());

    // Test that classes with have their original signature if the default was provided.
    if (!signatures.containsKey("Simple")) {
      assertNull(inspector.clazz("Simple").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Base")) {
      assertEquals(baseSignature, inspector.clazz("Base").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Outer")) {
      assertEquals(outerSignature, inspector.clazz("Outer").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Outer$Inner")) {
      assertNull(inspector.clazz("Outer$Inner").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Outer$ExtendsInner")) {
      assertEquals(extendsInnerSignature,
          inspector.clazz("Outer$ExtendsInner").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Outer$Inner$InnerInner")) {
      assertNull(inspector.clazz("Outer$Inner$InnerInner").getOriginalSignatureAttribute());
    }
    if (!signatures.containsKey("Outer$Inner$ExtendsInnerInner")) {
      assertEquals(extendsInnerInnerSignature,
          inspector.clazz("Outer$Inner$ExtendsInnerInner").getOriginalSignatureAttribute());
    }

    diagnostics.accept(checker);
    inspect.accept(inspector);
  }

  private void testSingleClass(String name, String signature,
      Consumer<DiagnosticsChecker> diagnostics,
      Consumer<DexInspector> inspector)
      throws Exception {
    ImmutableMap<String, String> signatures = ImmutableMap.of(name, signature);
    runTest(signatures, diagnostics, inspector);
  }

  private void isOriginUnknown(Origin origin) {
    assertSame(Origin.unknown(), origin);
  }

  private void noWarnings(DiagnosticsChecker checker) {
    assertEquals(0, checker.warnings.size());
  }

  private void noInspection(DexInspector inspector) {
  }

  private void noSignatureAttribute(ClassSubject clazz) {
    assertNull(clazz.getFinalSignatureAttribute());
    assertNull(clazz.getOriginalSignatureAttribute());
  }

  @Test
  public void originalJavacSignatures() throws Exception {
    // Test using the signatures generated by javac.
    runTest(ImmutableMap.of(), this::noWarnings, this::noInspection);
  }

  @Test
  public void classSignature_empty() throws Exception {
    testSingleClass("Outer", "", this::noWarnings, inspector -> {
      ClassSubject outer = inspector.clazz("Outer");
      assertNull(outer.getFinalSignatureAttribute());
      assertNull(outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureOuter_valid() throws Exception {
    // class Outer<T extends Simple> extends Base<T>
    String signature = "<T:LSimple;>LBase<TT;>;";
    testSingleClass("Outer", signature, this::noWarnings, inspector -> {
      ClassSubject outer = inspector.clazz("Outer");
      ClassSubject simple = inspector.clazz("Simple");
      ClassSubject base = inspector.clazz("Base");
      String baseDescriptorWithoutSemicolon =
          base.getFinalDescriptor().substring(0, base.getFinalDescriptor().length() - 1);
      String minifiedSignature =
          "<T:" +  simple.getFinalDescriptor() + ">" + baseDescriptorWithoutSemicolon + "<TT;>;";
      assertEquals(minifiedSignature, outer.getFinalSignatureAttribute());
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureExtendsInner_valid() throws Exception {
    String signature = "LOuter<TT;>.Inner;";
    testSingleClass("Outer$ExtendsInner", signature, this::noWarnings, inspector -> {
      ClassSubject extendsInner = inspector.clazz("Outer$ExtendsInner");
      ClassSubject outer = inspector.clazz("Outer");
      ClassSubject inner = inspector.clazz("Outer$Inner");
      String outerDescriptorWithoutSemicolon =
          outer.getFinalDescriptor().substring(0, outer.getFinalDescriptor().length() - 1);
      String innerFinalDescriptor = inner.getFinalDescriptor();
      String innerLastPart =
          innerFinalDescriptor.substring(innerFinalDescriptor.indexOf("$") + 1);
      String minifiedSignature = outerDescriptorWithoutSemicolon + "<TT;>." + innerLastPart;
      assertEquals(minifiedSignature, extendsInner.getFinalSignatureAttribute());
      assertEquals(signature, extendsInner.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureOuter_classNotFound() throws Exception {
    String signature = "<T:LNotFound;>LAlsoNotFound;";
    testSingleClass("Outer", signature, this::noWarnings, inspector -> {
      assertThat(inspector.clazz("NotFound"), not(isPresent()));
      ClassSubject outer = inspector.clazz("Outer");
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureExtendsInner_innerClassNotFound() throws Exception {
    String signature = "LOuter<TT;>.NotFound;";
    testSingleClass("Outer$ExtendsInner", signature, this::noWarnings, inspector -> {
      assertThat(inspector.clazz("NotFound"), not(isPresent()));
      ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureExtendsInner_outerAndInnerClassNotFound() throws Exception {
    String signature = "LNotFound<TT;>.AlsoNotFound;";
    testSingleClass("Outer$ExtendsInner", signature, this::noWarnings, inspector -> {
      assertThat(inspector.clazz("NotFound"), not(isPresent()));
      ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureExtendsInner_nestedInnerClassNotFound() throws Exception {
    String signature = "LOuter<TT;>.Inner.NotFound;";
    testSingleClass("Outer$ExtendsInner", signature, this::noWarnings, inspector -> {
      assertThat(inspector.clazz("NotFound"), not(isPresent()));
      ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureExtendsInner_multipleMestedInnerClassesNotFound() throws Exception {
    String signature = "LOuter<TT;>.NotFound.AlsoNotFound;";
    testSingleClass("Outer$ExtendsInner", signature, this::noWarnings, inspector -> {
      assertThat(inspector.clazz("NotFound"), not(isPresent()));
      ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
      assertEquals(signature, outer.getOriginalSignatureAttribute());
    });
  }

  @Test
  public void classSignatureOuter_invalid() throws Exception {
    testSingleClass("Outer", "X", diagnostics -> {
      assertEquals(1, diagnostics.warnings.size());
      DiagnosticsChecker.checkDiagnostic(diagnostics.warnings.get(0), this::isOriginUnknown,
          "Invalid signature for class Outer", "Expected L at position 1");
    }, inspector -> noSignatureAttribute(inspector.clazz("Outer")));
  }

  @Test
  public void classSignatureOuter_invalidEnd() throws Exception {
    testSingleClass("Outer", "<L", diagnostics -> {
      assertEquals(1, diagnostics.warnings.size());
      DiagnosticsChecker.checkDiagnostic(diagnostics.warnings.get(0), this::isOriginUnknown,
          "Invalid signature for class Outer", "Unexpected end of signature at position 3");
    }, inspector -> noSignatureAttribute(inspector.clazz("Outer")));
  }

  @Test
  public void classSignatureExtendsInner_invalid() throws Exception {
    testSingleClass("Outer$ExtendsInner", "X", diagnostics -> {
      assertEquals(1, diagnostics.warnings.size());
      DiagnosticsChecker.checkDiagnostic(diagnostics.warnings.get(0), this::isOriginUnknown,
          "Invalid signature for class Outer$ExtendsInner", "Expected L at position 1");
    }, inspector -> noSignatureAttribute(inspector.clazz("Outer$ExtendsInner")));
  }

  @Test
  public void classSignatureExtendsInnerInner_invalid() throws Exception {
    testSingleClass("Outer$Inner$ExtendsInnerInner", "X", diagnostics -> {
      assertEquals(1, diagnostics.warnings.size());
      DiagnosticsChecker.checkDiagnostic(diagnostics.warnings.get(0), this::isOriginUnknown,
          "Invalid signature for class Outer$Inner$ExtendsInnerInner",
          "Expected L at position 1");
    }, inspector -> noSignatureAttribute(inspector.clazz("Outer$Inner$ExtendsInnerInner")));
  }

  @Test
  public void multipleWarnings() throws Exception {
    runTest(ImmutableMap.of(
        "Outer", "X",
        "Outer$ExtendsInner", "X",
        "Outer$Inner$ExtendsInnerInner", "X"), diagnostics -> {
      assertEquals(3, diagnostics.warnings.size());
    }, inspector -> {
      noSignatureAttribute(inspector.clazz("Outer"));
      noSignatureAttribute(inspector.clazz("Outer$ExtendsInner"));
      noSignatureAttribute(inspector.clazz("Outer$Inner$ExtendsInnerInner"));
    });
  }
  @Test
  public void regress80029761() throws Exception {
    String signature = "LOuter<TT;>.com/example/Inner;";
    testSingleClass("Outer$ExtendsInner", signature, diagnostics -> {
      assertEquals(1, diagnostics.warnings.size());
      DiagnosticsChecker.checkDiagnostic(diagnostics.warnings.get(0), this::isOriginUnknown,
          "Invalid signature for class Outer$ExtendsInner", "Expected ; at position 16");
    }, inspector -> {
      noSignatureAttribute(inspector.clazz("Outer$ExtendsInner"));
    });
  }
}
