// Copyright 2015 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.

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;

/** JUnit tests for ijar tool. */
@RunWith(JUnit4.class)
public class IjarTests {

  private static File getTmpDir() {
    String tmpdir = System.getenv("TEST_TMPDIR");
    if (tmpdir == null) {
      // Fall back on the system temporary directory
      tmpdir = System.getProperty("java.io.tmpdir");
    }
    if (tmpdir == null) {
      fail("TEST_TMPDIR environment variable is not set!");
    }
    return new File(tmpdir);
  }

  DiagnosticCollector<JavaFileObject> diagnostics;

  private JavaCompiler.CompilationTask makeCompilationTask(String... files) throws IOException {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    fileManager.setLocation(
        StandardLocation.CLASS_PATH,
        Arrays.asList(new File("third_party/ijar/test/interface_ijar_testlib.jar")));
    fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(getTmpDir()));
    diagnostics = new DiagnosticCollector<JavaFileObject>();
    return compiler.getTask(
        null,
        fileManager,
        diagnostics,
        Arrays.asList("-Xlint:deprecation"), // used for deprecation tests
        null,
        fileManager.getJavaFileObjects(files));
  }

  /**
   * Test that the ijar tool preserves private nested classes as they may be exposed through public
   * API. This test relies on an interface jar provided through the build rule
   * :interface_ijar_testlib and the Java source file PrivateNestedClass.java.
   */
  @Test
  public void testPrivateNestedClass() throws IOException {
    if (!makeCompilationTask("third_party/ijar/test/PrivateNestedClass.java").call()) {
      fail(getFailedCompilationMessage());
    }
  }

  /** Test that the ijar tool preserves annotations, especially @Target meta-annotation. */
  @Test
  public void testRestrictedAnnotations() throws IOException {
    assertFalse(makeCompilationTask("third_party/ijar/test/UseRestrictedAnnotation.java").call());
  }

  /**
   * Test that the ijar tool preserves private nested classes as they may be exposed through public
   * API. This test relies on an interface jar provided through the build rule
   * :interface_ijar_testlib and the Java source file PrivateNestedClass.java.
   */
  @Test
  public void testDeprecatedParts() throws IOException {
    if (!makeCompilationTask("third_party/ijar/test/UseDeprecatedParts.java").call()) {
      fail(getFailedCompilationMessage());
    }
    int deprecatedWarningCount = 0;
    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
      if ((diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING)
          &&
          // Java 6:
          (diagnostic.getMessage(Locale.ENGLISH).startsWith("[deprecation]")
              ||
              // Java 7:
              diagnostic.getMessage(Locale.ENGLISH).contains("has been deprecated"))) {
        deprecatedWarningCount++;
      }
    }
    assertThat(deprecatedWarningCount).isAtLeast(16);
  }

  /**
   * Test that the ijar tool preserves EnclosingMethod attributes and doesn't prevent annotation
   * processors from accessing all the elements in a package.
   */
  @Test
  public void testEnclosingMethod() throws IOException {
    JavaCompiler.CompilationTask task =
        makeCompilationTask("third_party/ijar/test/package-info.java");
    task.setProcessors(
        Arrays.asList(
            new AbstractProcessor() {

              @Override
              public SourceVersion getSupportedSourceVersion() {
                return SourceVersion.latestSupported();
              }

              @Override
              public Set<String> getSupportedAnnotationTypes() {
                return Collections.singleton("*");
              }

              @Override
              public boolean process(
                  Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
                roundEnv.getElementsAnnotatedWith(java.lang.Override.class);
                return false;
              }
            }));
    if (!task.call()) {
      fail(getFailedCompilationMessage());
    }
  }

  @Test
  public void testVerifyStripping() throws Exception {
    ZipFile zip = new ZipFile("third_party/ijar/test/interface_ijar_testlib.jar");
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements()) {
      ZipEntry entry = entries.nextElement();
      ClassReader reader = new ClassReader(zip.getInputStream(entry));
      StripVerifyingVisitor verifier = new StripVerifyingVisitor();

      reader.accept(verifier, 0);

      if (verifier.errors.size() > 0) {
        StringBuilder builder = new StringBuilder();
        builder.append("Verification of ");
        builder.append(entry.getName());
        builder.append(" failed: ");
        for (String msg : verifier.errors) {
          builder.append(msg);
          builder.append("\t");
        }
        fail(builder.toString());
      }
    }
  }

  private String getFailedCompilationMessage() {
    StringBuilder builder = new StringBuilder();
    builder.append("Build failed unexpectedly");
    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
      builder.append(
          String.format(
              "\t%s line %d column %d: %s",
              diagnostic.getKind().toString(),
              diagnostic.getLineNumber(),
              diagnostic.getColumnNumber(),
              diagnostic.getMessage(Locale.ENGLISH)));
    }
    return builder.toString();
  }

  @Test
  public void localAndAnonymous() throws Exception {
    Map<String, byte[]> lib = readJar("third_party/ijar/test/liblocal_and_anonymous_lib.jar");
    Map<String, byte[]> ijar = readJar("third_party/ijar/test/local_and_anonymous-interface.jar");

    assertThat(lib.keySet())
        .containsExactly(
            "LocalAndAnonymous$1.class",
            "LocalAndAnonymous$2.class",
            "LocalAndAnonymous$1LocalClass.class",
            "LocalAndAnonymous.class",
            "LocalAndAnonymous$NestedClass.class",
            "LocalAndAnonymous$InnerClass.class",
            "LocalAndAnonymous$PrivateInnerClass.class");
    assertThat(ijar.keySet())
        .containsExactly(
            "LocalAndAnonymous.class",
            "LocalAndAnonymous$NestedClass.class",
            "LocalAndAnonymous$InnerClass.class",
            "LocalAndAnonymous$PrivateInnerClass.class");

    assertThat(innerClasses(lib.get("LocalAndAnonymous.class")))
        .isEqualTo(
            ImmutableMap.<String, String>builder()
                .put("LocalAndAnonymous$1", "null")
                .put("LocalAndAnonymous$2", "null")
                .put("LocalAndAnonymous$1LocalClass", "null")
                .put("LocalAndAnonymous$InnerClass", "LocalAndAnonymous")
                .put("LocalAndAnonymous$NestedClass", "LocalAndAnonymous")
                .put("LocalAndAnonymous$PrivateInnerClass", "LocalAndAnonymous")
                .buildOrThrow());
    assertThat(innerClasses(ijar.get("LocalAndAnonymous.class")))
        .containsExactly(
            "LocalAndAnonymous$InnerClass", "LocalAndAnonymous",
            "LocalAndAnonymous$NestedClass", "LocalAndAnonymous",
            "LocalAndAnonymous$PrivateInnerClass", "LocalAndAnonymous");
  }

  static Map<String, byte[]> readJar(String path) throws IOException {
    Map<String, byte[]> classes = new HashMap<>();
    try (JarFile jf = new JarFile(path)) {
      Enumeration<JarEntry> entries = jf.entries();
      while (entries.hasMoreElements()) {
        JarEntry je = entries.nextElement();
        if (!je.getName().endsWith(".class")
            && !je.getName().endsWith(".kotlin_builtins")
            && !je.getName().endsWith(".kotlin_module")
            && !je.getName().endsWith(".tasty")) {
          continue;
        }
        classes.put(je.getName(), ByteStreams.toByteArray(jf.getInputStream(je)));
      }
    }
    return classes;
  }

  static Map<String, String> innerClasses(byte[] bytes) {
    final Map<String, String> innerClasses = new HashMap<>();
    new ClassReader(bytes)
        .accept(
            new ClassVisitor(Opcodes.ASM9) {
              @Override
              public void visitInnerClass(
                  String name, String outerName, String innerName, int access) {
                innerClasses.put(name, String.valueOf(outerName));
              }
            },
            /* parsingOptions= */ 0);
    return innerClasses;
  }

  @Test
  public void moduleInfo() throws Exception {
    Map<String, byte[]> lib = readJar("third_party/ijar/test/module_info-interface.jar");
    assertThat(lib.keySet())
        .containsExactly("java/lang/String.class", "module-info.class", "foo/module-info.class");
    // ijar passes module-infos through unmodified, so it doesn't care that these ones are bogus
    assertThat(new String(lib.get("module-info.class"), UTF_8)).isEqualTo("hello");
    assertThat(new String(lib.get("foo/module-info.class"), UTF_8)).isEqualTo("goodbye");
  }

  @Test
  public void multiReleasePreserved() throws Exception {
    try (JarFile jf = new JarFile("third_party/ijar/test/multirelease-interface.jar")) {
      assertThat(jf.isMultiRelease()).isTrue();
    }
  }

  @Test
  public void kotlinModule() throws Exception {
    Map<String, byte[]> lib = readJar("third_party/ijar/test/kotlin_module-interface.jar");
    assertThat(lib.keySet())
        .containsExactly(
            "java/lang/String.class",
            "kotlin/kotlin.kotlin_builtins",
            "META-INF/bar.kotlin_module");
    // ijar passes kotlin modules and builtins through unmodified
    assertThat(new String(lib.get("META-INF/bar.kotlin_module"), UTF_8)).isEqualTo("hello");
    assertThat(new String(lib.get("kotlin/kotlin.kotlin_builtins"), UTF_8)).isEqualTo("goodbye");
  }

  @Test
  public void scalaTasty() throws Exception {
    Map<String, byte[]> lib = readJar("third_party/ijar/test/scala_tasty-interface.jar");
    assertThat(lib.keySet()).containsExactly("java/lang/String.class", "Bar.tasty");
    // ijar passes scala tasty files through unmodified
    assertThat(new String(lib.get("Bar.tasty"), UTF_8)).isEqualTo("hello");
  }

  @Test
  public void testTargetLabel() throws Exception {
    try (JarFile jf =
        new JarFile("third_party/ijar/test/interface_ijar_testlib_with_target_label.jar")) {
      ImmutableList<String> entries = jf.stream().map(JarEntry::getName).collect(toImmutableList());
      assertThat(entries.get(0)).isEqualTo("META-INF/");
      assertThat(entries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = jf.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertThat(attributes.getValue("Injecting-Rule-Kind")).isEqualTo("foo_library");
      assertThat(jf.getEntry(JarFile.MANIFEST_NAME).getTimeLocal())
          .isEqualTo(LocalDateTime.of(2010, 1, 1, 0, 0, 0));
    }
  }

  @Test
  public void testEmptyWithTargetLabel() throws Exception {
    try (JarFile jf = new JarFile("third_party/ijar/test/empty_with_target_label.jar")) {
      Manifest manifest = jf.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//empty");
      assertThat(jf.getEntry(JarFile.MANIFEST_NAME).getTimeLocal())
          .isEqualTo(LocalDateTime.of(2010, 1, 1, 0, 0, 0));
    }
  }

  // Tests --nostrip_jar with a jar that already has a manifest, but no target label
  @Test
  public void testNoStripJarWithManifest() throws Exception {
    JarFile original = new JarFile("third_party/ijar/test/jar-with-manifest.jar");
    JarFile stripped = new JarFile("third_party/ijar/test/jar-with-manifest-nostrip.jar");
    try {
      ImmutableList<String> strippedEntries =
          stripped.stream().map(JarEntry::getName).collect(toImmutableList());
      assertThat(strippedEntries.get(0)).isEqualTo("META-INF/");
      assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = stripped.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0");
      // Created-By was already in manifest, doesn't get overwritten
      assertThat(attributes.getValue("Created-By")).isEqualTo("test-code");
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertNonManifestFilesBitIdentical(original, stripped);
    } finally {
      original.close();
      stripped.close();
    }
  }

  // Tests --nostrip_jar with a jar that already has a manifest with a target label
  @Test
  public void testNoStripJarWithManifestAndTargetLabel() throws Exception {
    JarFile original = new JarFile("third_party/ijar/test/jar-with-manifest-and-target-label.jar");
    JarFile stripped =
        new JarFile("third_party/ijar/test/jar-with-manifest-and-target-label-nostrip.jar");
    try {
      ImmutableList<String> strippedEntries =
          stripped.stream().map(JarEntry::getName).collect(toImmutableList());
      assertThat(strippedEntries.get(0)).isEqualTo("META-INF/");
      assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = stripped.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0");
      // Created-By was already in manifest, doesn't get overwritten
      assertThat(attributes.getValue("Created-By")).isEqualTo("test-code");
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertNonManifestFilesBitIdentical(original, stripped);
    } finally {
      original.close();
      stripped.close();
    }
  }

  // Tests --nostrip_jar with a jar that didn't already have a manifest
  @Test
  public void testNoStripJarWithoutManifest() throws Exception {
    JarFile original = new JarFile("third_party/ijar/test/jar-without-manifest.jar");
    JarFile stripped = new JarFile("third_party/ijar/test/jar-without-manifest-nostrip.jar");
    try {
      ImmutableList<String> strippedEntries =
          stripped.stream().map(JarEntry::getName).collect(toImmutableList());
      assertThat(strippedEntries.get(0)).isEqualTo("META-INF/");
      assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = stripped.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0");
      assertThat(attributes.getValue("Created-By")).isEqualTo("bazel");
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertNonManifestFilesBitIdentical(original, stripped);
    } finally {
      original.close();
      stripped.close();
    }
  }

  @Test
  public void testPreserveManifestSections() throws Exception {
    try (JarFile original =
            new JarFile(
                "third_party/ijar/test/jar-with-target-label-and-manifest-sections-nostrip.jar");
        JarFile stripped =
            new JarFile("third_party/ijar/test/jar-with-manifest-sections-nostrip.jar")) {
      ImmutableList<String> strippedEntries =
          stripped.stream().map(JarEntry::getName).collect(toImmutableList());

      assertThat(strippedEntries.get(0)).isEqualTo("META-INF/");
      assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = stripped.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertNonManifestFilesBitIdentical(original, stripped);

      Attributes sectionAttributes1 = manifest.getAttributes("foo");
      assertThat(sectionAttributes1.getValue("Foo")).isEqualTo("bar");

      Attributes sectionAttributes2 = manifest.getAttributes("baz");
      assertThat(sectionAttributes2.getValue("Another")).isEqualTo("bar");
    }
  }

  @Test
  public void testPreserveManifestSectionsAndUpdateExistingTargetLabel() throws Exception {
    try (JarFile original =
            new JarFile(
                "third_party/ijar/test/jar-with-target-label-and-manifest-sections-nostrip.jar");
        JarFile stripped =
            new JarFile(
                "third_party/ijar/test/jar-with-target-label-and-manifest-sections-nostrip.jar")) {
      ImmutableList<String> strippedEntries =
          stripped.stream().map(JarEntry::getName).collect(toImmutableList());

      assertThat(strippedEntries.get(0)).isEqualTo("META-INF/");
      assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF");
      Manifest manifest = stripped.getManifest();
      Attributes attributes = manifest.getMainAttributes();
      assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo");
      assertNonManifestFilesBitIdentical(original, stripped);

      Attributes sectionAttributes1 = manifest.getAttributes("foo");
      assertThat(sectionAttributes1.getValue("Foo")).isEqualTo("bar");

      Attributes sectionAttributes2 = manifest.getAttributes("baz");
      assertThat(sectionAttributes2.getValue("Another")).isEqualTo("bar");
    }
  }

  // Tests idempotence of --nostrip
  @Test
  public void testNoStripIdempotence() throws Exception {
    byte[] original =
        Files.readAllBytes(Paths.get("third_party/ijar/test/jar-without-manifest-nostrip.jar"));
    byte[] stripped =
        Files.readAllBytes(
            Paths.get("third_party/ijar/test/jar-without-manifest-nostrip-idempotence.jar"));
    assertThat(original).isEqualTo(stripped);
  }

  @Test
  public void metaInfTtransitive() throws Exception {
    Map<String, byte[]> lib = readJar("third_party/ijar/test/meta_inf_transitive-interface.jar");
    assertThat(lib.keySet()).containsExactly("java/lang/String.class");
  }

  private static void assertNonManifestFilesBitIdentical(JarFile original, JarFile stripped)
      throws IOException {
    // Make sure that all other files came across bitwise equal
    for (String classEntry :
        original.stream()
            .map(JarEntry::getName)
            .filter(name -> !name.equals("META-INF/MANIFEST.MF"))
            .collect(toImmutableList())) {
      ZipEntry originalEntry = original.getEntry(classEntry);
      ZipEntry strippedEntry = stripped.getEntry(classEntry);
      InputStream originalStream = original.getInputStream(originalEntry);
      InputStream strippedStream = stripped.getInputStream(strippedEntry);
      assertThat(ByteStreams.toByteArray(strippedStream))
          .isEqualTo(ByteStreams.toByteArray(originalStream));
    }
  }
}
