// 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 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.common.collect.Iterators;
import java.io.IOException;
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 WORKING_DIR = Paths.get(System.getProperty("user.dir"));
  private static final Path INPUT_JAR = WORKING_DIR.resolve(System.getProperty("testinputjar"));
  private static final Path INPUT_JAR2 = WORKING_DIR.resolve(System.getProperty("testinputjar2"));
  private static final Path MAIN_DEX_LIST_FILE =
      WORKING_DIR.resolve(System.getProperty("testmaindexlist"));
  static final String DEX_PREFIX = "classes";

  @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);
  }

  @Test
  public void testMainDexList() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives =
        runDexSplitter(
            200,
            "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 testMinimalMainDex() throws Exception {
    Path dexArchive = buildDexArchive();
    ImmutableList<Path> outputArchives =
        runDexSplitter(
            256 * 256,
            "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);
  }

  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,
          "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 = ImmutableSet.copyOf(Iterators.filter(
          Iterators.transform(Iterators.forEnumeration(input.entries()), ZipEntryName.INSTANCE),
          Predicates.containsPattern(".*\\.class.dex$")));
      assertThat(result).isNotEmpty(); // test sanity
      return result;
    }
  }

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

  private ImmutableList<Path> runDexSplitter(
      int maxNumberOfIdxPerDex,
      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;
    DexFileSplitter.splitIntoShards(options);
    assertThat(options.outputDirectory.toFile().exists()).isTrue();
    ImmutableSet<Path> files =
        ImmutableSet.copyOf(Files.newDirectoryStream(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 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();
    }
  }
}
