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

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

import com.android.dx.command.dexer.DxContext;
import com.android.dx.dex.code.PositionList;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.runfiles.Runfiles;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link DexFileSplitter}. */
@RunWith(JUnit4.class)
public class DexFileSplitterTest {

  private static final Path INPUT_JAR;
  private static final Path INPUT_JAR2;
  private static final Path MAIN_DEX_LIST_FILE;
  static final String DEX_PREFIX = "classes";

  static {
    try {
      Runfiles runfiles = Runfiles.create();

      INPUT_JAR = Paths.get(runfiles.rlocation(System.getProperty("testinputjar")));
      INPUT_JAR2 = Paths.get(runfiles.rlocation(System.getProperty("testinputjar2")));
      MAIN_DEX_LIST_FILE = Paths.get(runfiles.rlocation(System.getProperty("testmaindexlist")));
    } catch (Exception e) {
      throw new ExceptionInInitializerError(e);
    }
  }

  @Test
  public void testSingleInputSingleOutput() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives = runDexSplitter(256 * 256, "from_single", dexArchive);
    assertThat(outputArchives).hasSize(1);

    ImmutableSet<String> expectedFiles = dexEntries(dexArchive);
    assertThat(dexEntries(outputArchives.get(0))).containsExactlyElementsIn(expectedFiles);
  }

  @Test
  public void testDuplicateInputIgnored() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives =
        runDexSplitter(256 * 256, "from_duplicate", dexArchive, dexArchive);
    assertThat(outputArchives).hasSize(1);

    ImmutableSet<String> expectedFiles = dexEntries(dexArchive);
    assertThat(dexEntries(outputArchives.get(0))).containsExactlyElementsIn(expectedFiles);
  }

  @Test
  public void testSingleInputMultidexOutput() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives = runDexSplitter(200, "multidex_from_single", dexArchive);
    assertThat(outputArchives.size()).isGreaterThan(1); // test sanity

    ImmutableSet<String> expectedEntries = dexEntries(dexArchive);
    assertExpectedEntries(outputArchives, expectedEntries);
  }

  @Test
  public void testMultipleInputsMultidexOutput() throws Exception {
    Path dexArchive = buildDexArchive();
    Path dexArchive2 = buildDexArchive(INPUT_JAR2, "jar2.dex.zip");
    ImmutableList<Path> outputArchives = runDexSplitter(200, "multidex", dexArchive, dexArchive2);
    assertThat(outputArchives.size()).isGreaterThan(1); // test sanity

    HashSet<String> expectedEntries = new HashSet<>();
    expectedEntries.addAll(dexEntries(dexArchive));
    expectedEntries.addAll(dexEntries(dexArchive2));
    assertExpectedEntries(outputArchives, expectedEntries);
  }

  /**
   * Tests that the same input creates identical output in 2 runs.  Flakiness here would indicate
   * race conditions or other concurrency issues.
   */
  @Test
  public void testDeterminism() throws Exception {
    Path dexArchive = buildDexArchive();
    Path dexArchive2 = buildDexArchive(INPUT_JAR2, "jar2.dex.zip");
    ImmutableList<Path> outputArchives = runDexSplitter(200, "det1", dexArchive, dexArchive2);
    assertThat(outputArchives.size()).isGreaterThan(1); // test sanity
    ImmutableList<Path> outputArchives2 = runDexSplitter(200, "det2", dexArchive, dexArchive2);
    assertThat(outputArchives2).hasSize(outputArchives.size()); // paths differ though

    Path outputRoot2 = outputArchives2.get(0).getParent();
    for (Path outputArchive : outputArchives) {
      ImmutableList<ZipEntry> expectedEntries;
      try (ZipFile zip = new ZipFile(outputArchive.toFile())) {
        expectedEntries = zip.stream().collect(ImmutableList.<ZipEntry>toImmutableList());
      }
      ImmutableList<ZipEntry> actualEntries;
      try (ZipFile zip2 = new ZipFile(outputRoot2.resolve(outputArchive.getFileName()).toFile())) {
        actualEntries = zip2.stream().collect(ImmutableList.<ZipEntry>toImmutableList());
      }
      int len = expectedEntries.size();
      assertThat(actualEntries).hasSize(len);
      for (int i = 0; i < len; ++i) {
        ZipEntry expected = expectedEntries.get(i);
        ZipEntry actual = actualEntries.get(i);
        assertThat(actual.getName()).named(actual.getName()).isEqualTo(expected.getName());
        assertThat(actual.getSize()).named(actual.getName()).isEqualTo(expected.getSize());
        assertThat(actual.getCrc()).named(actual.getName()).isEqualTo(expected.getCrc());
      }
    }
  }

  @Test
  public void testMainDexList() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives =
        runDexSplitter(
            200,
            /*inclusionFilterJar=*/ null,
            "main_dex_list",
            MAIN_DEX_LIST_FILE,
            /*minimalMainDex=*/ false,
            dexArchive);

    ImmutableSet<String> expectedEntries = dexEntries(dexArchive);
    assertThat(outputArchives.size()).isGreaterThan(1); // test sanity
    assertThat(dexEntries(outputArchives.get(0)))
        .containsAllIn(expectedMainDexEntries());
    assertExpectedEntries(outputArchives, expectedEntries);
  }

  @Test
  public void testMainDexList_containsForbidden() throws Exception {
    Path dexArchive = buildDexArchive();
    Path mainDexFile = Files.createTempFile("main_dex_list", ".txt");
    Files.write(mainDexFile, ImmutableList.of("com/google/Ok.class", "j$/my/Bad.class"), UTF_8);
    try {
      runDexSplitter(
          256 * 256,
          /*inclusionFilterJar=*/ null,
          "invalid_main_dex_list",
          mainDexFile,
          /*minimalMainDex=*/ false,
          dexArchive);
      fail("IllegalArgumentException expected");
    } catch (IllegalArgumentException e) {
      assertThat(e).hasMessageThat().contains("j$");
    }
  }

  @Test
  public void testMinimalMainDex() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives =
        runDexSplitter(
            256 * 256,
            /*inclusionFilterJar=*/ null,
            "minimal_main_dex",
            MAIN_DEX_LIST_FILE,
            /*minimalMainDex=*/ true,
            dexArchive);

    ImmutableSet<String> expectedEntries = dexEntries(dexArchive);
    assertThat(outputArchives.size()).isGreaterThan(1); // test sanity
    assertThat(dexEntries(outputArchives.get(0)))
        .containsExactlyElementsIn(expectedMainDexEntries());
    assertExpectedEntries(outputArchives, expectedEntries);
  }

  @Test
  public void testInclusionFilterJar() throws Exception {
    Path dexArchive = buildDexArchive();
    Path dexArchive2 = buildDexArchive(INPUT_JAR2, "jar2.dex.zip");
    ImmutableList<Path> outputArchives =
        runDexSplitter(
            256 * 256,
            INPUT_JAR2,
            "filtered",
            /*mainDexList=*/ null,
            /*minimalMainDex=*/ false,
            dexArchive,
            dexArchive2);

    // Only expect entries from the Jar we filtered by
    assertExpectedEntries(outputArchives, dexEntries(dexArchive2));
  }

  private static Iterable<String> expectedMainDexEntries() throws IOException {
    return Iterables.transform(
        Files.readAllLines(MAIN_DEX_LIST_FILE),
        new Function<String, String>() {
          @Override
          public String apply(String input) {
            return input + ".dex";
          }
        });
  }

  @Test
  public void testMultidexOffWithMultidexFlags() throws Exception {
    Path dexArchive = buildDexArchive();
    try {
      runDexSplitter(
          200,
          /*inclusionFilterJar=*/ null,
          "should_fail",
          /*mainDexList=*/ null,
          /*minimalMainDex=*/ true,
          dexArchive);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException e) {
      assertThat(e)
          .hasMessageThat()
          .isEqualTo("--minimal-main-dex not allowed without --main-dex-list");
    }
  }

  private void assertExpectedEntries(
      ImmutableList<Path> outputArchives, Set<String> expectedEntries) throws IOException {
    ImmutableSet.Builder<String> actualFiles = ImmutableSet.builder();
    for (Path outputArchive : outputArchives) {
      actualFiles.addAll(dexEntries(outputArchive));
    }
    // ImmutableSet.Builder.build would fail if there were duplicates.  Additionally we make sure
    // all expected files are here
    assertThat(actualFiles.build()).containsExactlyElementsIn(expectedEntries);
  }

  private ImmutableSet<String> dexEntries(Path dexArchive) throws IOException {
    try (ZipFile input = new ZipFile(dexArchive.toFile())) {
      ImmutableSet<String> result =
          input.stream()
              .map(ZipEntryName.INSTANCE)
              .filter(Predicates.containsPattern(".*\\.class.dex$"))
              .collect(ImmutableSet.<String>toImmutableSet());
      assertThat(result).isNotEmpty(); // test sanity
      return result;
    }
  }

  private ImmutableList<Path> runDexSplitter(int maxNumberOfIdxPerDex, String outputRoot,
      Path... dexArchives) throws IOException {
    return runDexSplitter(
        maxNumberOfIdxPerDex,
        /*inclusionFilterJar=*/ null,
        outputRoot,
        /*mainDexList=*/ null,
        /*minimalMainDex=*/ false,
        dexArchives);
  }

  private ImmutableList<Path> runDexSplitter(
      int maxNumberOfIdxPerDex,
      @Nullable Path inclusionFilterJar,
      String outputRoot,
      @Nullable Path mainDexList,
      boolean minimalMainDex,
      Path... dexArchives)
      throws IOException {
    DexFileSplitter.Options options = new DexFileSplitter.Options();
    options.inputArchives = ImmutableList.copyOf(dexArchives);
    options.outputDirectory =
        FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"), outputRoot);
    options.maxNumberOfIdxPerDex = maxNumberOfIdxPerDex;
    options.mainDexListFile = mainDexList;
    options.minimalMainDex = minimalMainDex;
    options.inclusionFilterJar = inclusionFilterJar;
    DexFileSplitter.splitIntoShards(options);
    assertThat(options.outputDirectory.toFile().exists()).isTrue();
    ImmutableSet<Path> files = readFiles(options.outputDirectory, "*.zip");

    ImmutableList.Builder<Path> result = ImmutableList.builder();
    for (int i = 1; i <= files.size(); ++i) {
      Path path = options.outputDirectory.resolve(i + ".shard.zip");
      assertThat(files).contains(path);
      result.add(path);
    }
    return result.build(); // return expected files in sorted order
  }

  private static ImmutableSet<Path> readFiles(Path directory, String glob) throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, glob)) {
      return ImmutableSet.copyOf(stream);
    }
  }

  private Path buildDexArchive() throws Exception {
    return buildDexArchive(INPUT_JAR, "libtests.dex.zip");
  }

  private Path buildDexArchive(Path inputJar, String outputZip) throws Exception {
    DexBuilder.Options options = new DexBuilder.Options();
    // Use Jar file that has this test in it as the input Jar
    options.inputJar = inputJar;
    options.outputZip =
        FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"), outputZip);
    options.maxThreads = 1;
    Dexing.DexingOptions dexingOptions = new Dexing.DexingOptions();
    dexingOptions.optimize = true;
    dexingOptions.positionInfo = PositionList.LINES;
    DexBuilder.buildDexArchive(options, new Dexing(new DxContext(), dexingOptions));
    return options.outputZip;
  }

  // Can't use lambda for Java 7 compatibility so we can run this Jar through dx without desugaring.
  private enum ZipEntryName implements Function<ZipEntry, String> {
    INSTANCE;
    @Override
    public String apply(ZipEntry input) {
      return input.getName();
    }
  }
}
