// Copyright 2016 Google Inc. 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.archivepatcher.generator;

import com.google.archivepatcher.generator.DefaultDeflateCompressionDiviner.DivinationResult;
import com.google.archivepatcher.shared.DefaultDeflateCompatibilityWindow;
import com.google.archivepatcher.shared.JreDeflateParameters;
import com.google.archivepatcher.shared.RandomAccessFileInputStream;
import com.google.archivepatcher.shared.TypedRange;
import com.google.archivepatcher.shared.UnitTestZipArchive;
import com.google.archivepatcher.shared.UnitTestZipEntry;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link PreDiffPlanner}.
 */
@RunWith(JUnit4.class)
@SuppressWarnings("javadoc")
public class PreDiffPlannerTest {

  // All the A and B entries consist of a chunk of text followed by a standard corpus of text from
  // the DefaultDeflateCompatibilityDiviner that ensures the tests will be able to discriminate
  // between any compression level. Without this additional corpus text, multiple compression levels
  // can match the entry and the unit tests would not be accurate.
  private static final UnitTestZipEntry ENTRY_A_LEVEL_6 =
      UnitTestZipArchive.makeUnitTestZipEntry("/path A", 6, "entry A", null);
  private static final UnitTestZipEntry ENTRY_A_LEVEL_9 =
      UnitTestZipArchive.makeUnitTestZipEntry("/path A", 9, "entry A", null);
  private static final UnitTestZipEntry ENTRY_A_STORED =
      UnitTestZipArchive.makeUnitTestZipEntry("/path A", 0, "entry A", null);
  private static final UnitTestZipEntry ENTRY_B_LEVEL_6 =
      UnitTestZipArchive.makeUnitTestZipEntry("/path B", 6, "entry B", null);
  private static final UnitTestZipEntry ENTRY_B_LEVEL_9 =
      UnitTestZipArchive.makeUnitTestZipEntry("/path B", 9, "entry B", null);

  /**
   * Entry C1 is a small entry WITHOUT the standard corpus of text from
   * {@link DefaultDeflateCompatibilityWindow} appended. It has exactly the same compressed length
   * as {@link #FIXED_LENGTH_ENTRY_C2_LEVEL_6}, and can be used to test the byte-matching logic in
   * the code when the compressed lengths are identical.
   */
  private static final UnitTestZipEntry FIXED_LENGTH_ENTRY_C1_LEVEL_6 =
      new UnitTestZipEntry("/path C", 6, "qqqqqqqqqqqqqqqqqqqqqqqqqqqq", null);

  /**
   * Entry C2 is a small entry WITHOUT the standard corpus of text from
   * {@link DefaultDeflateCompatibilityWindow} appended. It has exactly the same compressed length
   * as {@link #FIXED_LENGTH_ENTRY_C1_LEVEL_6}, and can be used to test the byte-matching logic in
   * the code when the compressed lengths are identical.
   */
  private static final UnitTestZipEntry FIXED_LENGTH_ENTRY_C2_LEVEL_6 =
      new UnitTestZipEntry("/path C", 6, "rrrrrrrrrrrrrrrrrrrrrrrrrrrr", null);

  // The "shadow" entries are exact copies of ENTRY_A_* but have a different path. These are used
  // for the detection of renames that don't involve modification (i.e., the uncompressed CRC32 is
  // exactly the same as the ENTRY_A_* entries)
  private static final UnitTestZipEntry SHADOW_ENTRY_A_LEVEL_1 =
      UnitTestZipArchive.makeUnitTestZipEntry("/uncompressed data same as A", 1, "entry A", null);
  private static final UnitTestZipEntry SHADOW_ENTRY_A_LEVEL_6 =
      UnitTestZipArchive.makeUnitTestZipEntry("/same as A level 6", 6, "entry A", null);
  private static final UnitTestZipEntry SHADOW_ENTRY_A_LEVEL_9 =
      UnitTestZipArchive.makeUnitTestZipEntry("/same as A level 9", 9, "entry A", null);
  private static final UnitTestZipEntry SHADOW_ENTRY_A_STORED =
      UnitTestZipArchive.makeUnitTestZipEntry("/same as A stored", 0, "entry A", null);

  private List<File> tempFilesCreated;
  private Map<File, Map<ByteArrayHolder, MinimalZipEntry>> entriesByPathByTempFile;

  @Before
  public void setup() {
    tempFilesCreated = new LinkedList<File>();
    entriesByPathByTempFile = new HashMap<File, Map<ByteArrayHolder, MinimalZipEntry>>();
  }

  @After
  public void tearDown() {
    for (File file : tempFilesCreated) {
      try {
        file.delete();
      } catch (Exception ignored) {
        // Nothing
      }
    }
  }

  /**
   * Stores the specified bytes to disk in a temp file, returns the temp file and caches the zip
   * entries for the file for use in later code.
   * @param data the bytes to store, expected to be a valid zip file
   * @throws IOException if it fails
   */
  private File storeAndMapArchive(byte[] data) throws IOException {
    File file = File.createTempFile("pdpt", "zip");
    tempFilesCreated.add(file);
    file.deleteOnExit();
    FileOutputStream out = new FileOutputStream(file);
    out.write(data);
    out.flush();
    out.close();
    Map<ByteArrayHolder, MinimalZipEntry> entriesByPath = new HashMap<>();
    for (MinimalZipEntry zipEntry : MinimalZipArchive.listEntries(file)) {
      ByteArrayHolder key = new ByteArrayHolder(zipEntry.getFileNameBytes());
      entriesByPath.put(key, zipEntry);
    }
    entriesByPathByTempFile.put(file, entriesByPath);
    return file;
  }

  /**
   * Finds a unit test entry in the specified temp file.
   * @param tempFile the archive to search within
   * @param unitTestEntry the unit test entry to look up
   * @return the {@link MinimalZipEntry} corresponding to the unit test entry
   */
  private MinimalZipEntry findEntry(File tempFile, UnitTestZipEntry unitTestEntry) {
    Map<ByteArrayHolder, MinimalZipEntry> subMap = entriesByPathByTempFile.get(tempFile);
    Assert.assertNotNull("temp file not mapped", subMap);
    ByteArrayHolder key;
    try {
      key = new ByteArrayHolder(unitTestEntry.path.getBytes("UTF8"));
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
    return subMap.get(key);
  }

  /**
   * Finds the {@link TypedRange} corresponding to the compressed data for the specified unit test
   * entry in the specified temp file.
   * @param tempFile the archive to search within
   * @param unitTestEntry the unit test entry to look up
   * @return the {@link TypedRange} for the unit test entry's compressed data
   */
  private TypedRange<Void> findRangeWithoutParams(File tempFile, UnitTestZipEntry unitTestEntry) {
    MinimalZipEntry found = findEntry(tempFile, unitTestEntry);
    Assert.assertNotNull("entry not found in temp file", found);
    return new TypedRange<Void>(
        found.getFileOffsetOfCompressedData(), found.getCompressedSize(), null);
  }

  /**
   * Finds the {@link TypedRange} corresponding to the compressed data for the specified unit test
   * entry in the specified temp file.
   * @param tempFile the archive to search within
   * @param unitTestEntry the unit test entry to look up
   * @return the {@link TypedRange} for the unit test entry's compressed data
   */
  private TypedRange<JreDeflateParameters> findRangeWithParams(
      File tempFile, UnitTestZipEntry unitTestEntry) {
    MinimalZipEntry found = findEntry(tempFile, unitTestEntry);
    Assert.assertNotNull("entry not found in temp file", found);
    return new TypedRange<JreDeflateParameters>(
        found.getFileOffsetOfCompressedData(),
        found.getCompressedSize(),
        JreDeflateParameters.of(unitTestEntry.level, 0, true));
  }

  /**
   * Deliberately introduce an error into the specified entry. This will make the entry impossible
   * to divine the settings for, because it is broken.
   * @param tempFile the archive to search within
   * @param unitTestEntry the unit test entry to deliberately corrupt
   */
  private void corruptEntryData(File tempFile, UnitTestZipEntry unitTestEntry) throws IOException {
    TypedRange<Void> range = findRangeWithoutParams(tempFile, unitTestEntry);
    Assert.assertTrue("range too short to corrupt with 'junk'", range.getLength() >= 4);
    try (RandomAccessFile raf = new RandomAccessFile(tempFile, "rw")) {
      raf.seek(range.getOffset());
      raf.write("junk".getBytes("UTF8"));
    }
  }

  /**
   * Deliberately garble the compression method in the specified entry such that it is no longer
   * deflate.
   * @param tempFile the archive to search within
   * @param unitTestEntry the unit test entry to deliberately corrupt
   */
  private void corruptCompressionMethod(File tempFile, UnitTestZipEntry unitTestEntry)
      throws IOException {
    long centralDirectoryRecordOffset = -1;
    try (RandomAccessFileInputStream rafis = new RandomAccessFileInputStream(tempFile)) {
      long startOfEocd = MinimalZipParser.locateStartOfEocd(rafis, 32768);
      rafis.setRange(startOfEocd, tempFile.length() - startOfEocd);
      MinimalCentralDirectoryMetadata centralDirectoryMetadata = MinimalZipParser.parseEocd(rafis);
      int numEntries = centralDirectoryMetadata.getNumEntriesInCentralDirectory();
      rafis.setRange(
          centralDirectoryMetadata.getOffsetOfCentralDirectory(),
          centralDirectoryMetadata.getLengthOfCentralDirectory());
      for (int x = 0; x < numEntries; x++) {
        long recordStartOffset = rafis.getPosition();
        MinimalZipEntry candidate = MinimalZipParser.parseCentralDirectoryEntry(rafis);
        if (candidate.getFileName().equals(unitTestEntry.path)) {
          // Located! Track offset and bail out.
          centralDirectoryRecordOffset = recordStartOffset;
          x = numEntries;
        }
      }
    }

    Assert.assertNotEquals("Entry not found", -1L, centralDirectoryRecordOffset);
    try (RandomAccessFile raf = new RandomAccessFile(tempFile, "rw")) {
      // compression method is a 2 byte field stored 10 bytes into the record
      raf.seek(centralDirectoryRecordOffset + 10);
      raf.write(7);
      raf.write(7);
    }
  }

  private PreDiffPlan invokeGeneratePreDiffPlan(
      File oldFile, File newFile, RecommendationModifier... recommendationModifiers)
      throws IOException {
    Map<ByteArrayHolder, MinimalZipEntry> originalOldArchiveZipEntriesByPath =
        new LinkedHashMap<ByteArrayHolder, MinimalZipEntry>();
    Map<ByteArrayHolder, MinimalZipEntry> originalNewArchiveZipEntriesByPath =
        new LinkedHashMap<ByteArrayHolder, MinimalZipEntry>();
    Map<ByteArrayHolder, JreDeflateParameters> originalNewArchiveJreDeflateParametersByPath =
        new LinkedHashMap<ByteArrayHolder, JreDeflateParameters>();

    for (MinimalZipEntry zipEntry : MinimalZipArchive.listEntries(oldFile)) {
      ByteArrayHolder key = new ByteArrayHolder(zipEntry.getFileNameBytes());
      originalOldArchiveZipEntriesByPath.put(key, zipEntry);
    }

    DefaultDeflateCompressionDiviner diviner = new DefaultDeflateCompressionDiviner();
    for (DivinationResult divinationResult : diviner.divineDeflateParameters(newFile)) {
      ByteArrayHolder key = new ByteArrayHolder(divinationResult.minimalZipEntry.getFileNameBytes());
      originalNewArchiveZipEntriesByPath.put(key, divinationResult.minimalZipEntry);
      originalNewArchiveJreDeflateParametersByPath.put(key, divinationResult.divinedParameters);
    }

    PreDiffPlanner preDiffPlanner =
        new PreDiffPlanner(
            oldFile,
            originalOldArchiveZipEntriesByPath,
            newFile,
            originalNewArchiveZipEntriesByPath,
            originalNewArchiveJreDeflateParametersByPath,
            recommendationModifiers);
    return preDiffPlanner.generatePreDiffPlan();
  }

  private void checkRecommendation(PreDiffPlan plan, QualifiedRecommendation... expected) {
    Assert.assertNotNull(plan.getQualifiedRecommendations());
    Assert.assertEquals(expected.length, plan.getQualifiedRecommendations().size());
    for (int x = 0; x < expected.length; x++) {
      QualifiedRecommendation actual = plan.getQualifiedRecommendations().get(x);
      Assert.assertEquals(
          expected[x].getOldEntry().getFileName(), actual.getOldEntry().getFileName());
      Assert.assertEquals(
          expected[x].getNewEntry().getFileName(), actual.getNewEntry().getFileName());
      Assert.assertEquals(expected[x].getRecommendation(), actual.getRecommendation());
      Assert.assertEquals(expected[x].getReason(), actual.getReason());
    }
  }

  @Test
  public void testGeneratePreDiffPlan_OneCompressedEntry_Unchanged() throws IOException {
    byte[] bytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    File oldFile = storeAndMapArchive(bytes);
    File newFile = storeAndMapArchive(bytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to leave the entry alone in both the old and new archives (empty plans).
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_LEVEL_6),
        findEntry(newFile, ENTRY_A_LEVEL_6),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.COMPRESSED_BYTES_IDENTICAL));
  }

  @Test
  public void testGeneratePreDiffPlan_OneCompressedEntry_LengthsChanged() throws IOException {
    // Test detection of compressed entry differences based on length mismatch.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress the entry in both the old and new archives.
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertEquals(1, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithParams(newFile, ENTRY_A_LEVEL_9), plan.getNewFileUncompressionPlan().get(0));
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_LEVEL_6),
        findEntry(newFile, ENTRY_A_LEVEL_9),
        Recommendation.UNCOMPRESS_BOTH,
        RecommendationReason.COMPRESSED_BYTES_CHANGED));
  }

  @Test
  public void testGeneratePreDiffPlan_OneCompressedEntry_BytesChanged() throws IOException {
    // Test detection of compressed entry differences based on binary content mismatch where the
    // compressed lengths are exactly the same - i.e., force a byte-by-byte comparison of the
    // compressed data in the two entries.
    byte[] oldBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(FIXED_LENGTH_ENTRY_C1_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(FIXED_LENGTH_ENTRY_C2_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress the entry in both the old and new archives.
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(1, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, FIXED_LENGTH_ENTRY_C1_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertEquals(
        findRangeWithParams(newFile, FIXED_LENGTH_ENTRY_C2_LEVEL_6),
        plan.getNewFileUncompressionPlan().get(0));
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, FIXED_LENGTH_ENTRY_C1_LEVEL_6),
        findEntry(newFile, FIXED_LENGTH_ENTRY_C2_LEVEL_6),
        Recommendation.UNCOMPRESS_BOTH,
        RecommendationReason.COMPRESSED_BYTES_CHANGED));
  }

  @Test
  public void testGeneratePreDiffPlan_OneUncompressedEntry() throws IOException {
    // Test with uncompressed old and new. It doesn't matter whether the bytes are changed or
    // unchanged in this case.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing because both entries are already uncompressed
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_STORED),
        findEntry(newFile, ENTRY_A_STORED),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.BOTH_ENTRIES_UNCOMPRESSED));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_CompressedToUncompressed() throws IOException {
    // Test the migration of an entry from compressed (old archive) to uncompressed (new archive).
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_9));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress the entry in the old archive and do nothing in the new
    // archive (empty plan)
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_9),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_LEVEL_9),
        findEntry(newFile, ENTRY_A_STORED),
        Recommendation.UNCOMPRESS_OLD,
        RecommendationReason.COMPRESSED_CHANGED_TO_UNCOMPRESSED));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_UncompressedToCompressed() throws IOException {
    // Test the migration of an entry from uncompressed (old archive) to compressed (new archive).
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing in the old archive (empty plan) and uncompress the entry in
    // the new archive
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertEquals(1, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithParams(newFile, ENTRY_A_LEVEL_6), plan.getNewFileUncompressionPlan().get(0));
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_STORED),
        findEntry(newFile, ENTRY_A_LEVEL_6),
        Recommendation.UNCOMPRESS_NEW,
        RecommendationReason.UNCOMPRESSED_CHANGED_TO_COMPRESSED));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_UncompressedToUndivinable() throws IOException {
    // Test the migration of an entry from uncompressed (old archive) to compressed (new archive),
    // but make the new entry un-divinable and therefore un-recompressible.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    // Deliberately break the entry in the new file so that it will not be divinable
    corruptEntryData(newFile, ENTRY_A_LEVEL_6);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan WOULD be to do nothing in the old archive (empty plan) and uncompress the entry in
    // the new archive, but because the new entry is un-divinable it cannot be recompressed and so
    // the plan for the new archive should be empty as well.
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_STORED),
        findEntry(newFile, ENTRY_A_LEVEL_6),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.UNSUITABLE));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_OldUncompressed_NewNonDeflate() throws IOException {
    // Test the case where the entry is compressed with something other than deflate in the new
    // archive; it is thus not reproducible, not divinable, and therefore cannot be uncompressed.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    corruptCompressionMethod(newFile, ENTRY_A_LEVEL_9);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing (empty plans) because the the entry in the old archive is
    // already uncompressed and the entry in the new archive is not compressed with deflate (i.e.,
    // cannot be recompressed so cannot be touched).
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_STORED),
        findEntry(newFile, ENTRY_A_LEVEL_9),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.UNSUITABLE));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_OldNonDeflate_NewUncompressed() throws IOException {
    // Test the case where the entry is compressed with something other than deflate in the old
    // archive; it can't be uncompressed, so there's no point in modifying the new entry either.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_9));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    corruptCompressionMethod(oldFile, ENTRY_A_LEVEL_9);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing (empty plans) because the the entry in the old archive is
    // not compressed with deflate, so there is no point in trying to do anything at all.
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_LEVEL_9),
        findEntry(newFile, ENTRY_A_STORED),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.UNSUITABLE));
  }

  @Test
  public void testGeneratePreDiffPlan_OneEntry_BothNonDeflate() throws IOException {
    // Test the case where the entry is compressed with something other than deflate; it is thus
    // not reproducible, not divinable, and therefore cannot be uncompressed.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    corruptCompressionMethod(oldFile, ENTRY_A_LEVEL_6);
    corruptCompressionMethod(newFile, ENTRY_A_LEVEL_9);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing (empty plans) because the entries are not compressed with
    // deflate
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(plan, new QualifiedRecommendation(
        findEntry(oldFile, ENTRY_A_LEVEL_6),
        findEntry(newFile, ENTRY_A_LEVEL_9),
        Recommendation.UNCOMPRESS_NEITHER,
        RecommendationReason.UNSUITABLE));
  }

  @Test
  public void testGeneratePreDiffPlan_TwoDifferentEntries_DifferentPaths() throws IOException {
    // Test the case where file paths are different as well as content within those files, i.e. each
    // entry is exclusive to its archive and is not the same
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_B_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing (empty plans) because entry A is only in the old archive and
    // entry B is only in the new archive, so there is nothing to diff.
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getQualifiedRecommendations().isEmpty());
  }

  @Test
  public void testGeneratePreDiffPlan_TwoEntriesEachArchive_SwappingOrder() throws IOException {
    // Test the case where two entries in each archive have both changed, AND they have changed
    // places in the file. The plan is supposed to be in file order, so that streaming is possible;
    // check that it is so.
    byte[] oldBytes =
        UnitTestZipArchive.makeTestZip(Arrays.asList(ENTRY_A_LEVEL_6, ENTRY_B_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Arrays.asList(ENTRY_B_LEVEL_9, ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress both entries, but the order is important. File order should
    // be in both plans.
    Assert.assertEquals(2, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(2, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_B_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(1));
    Assert.assertEquals(
        findRangeWithParams(newFile, ENTRY_B_LEVEL_9), plan.getNewFileUncompressionPlan().get(0));
    Assert.assertEquals(
        findRangeWithParams(newFile, ENTRY_A_LEVEL_9), plan.getNewFileUncompressionPlan().get(1));
  }

  @Test
  public void testGeneratePreDiffPlan_SimpleRename_Unchanged() throws IOException {
    // Test the case where file paths are different but the uncompressed content is the same.
    // The compression method used for both entries is identical, as are the compressed bytes.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(SHADOW_ENTRY_A_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to do nothing (empty plans) because the bytes are identical in both files
    // so the entries should remain compressed. However, unlike the case where there was no match,
    // there is now a qualified recommendation in the returned list.
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(
        plan,
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_LEVEL_6),
            findEntry(newFile, SHADOW_ENTRY_A_LEVEL_6),
            Recommendation.UNCOMPRESS_NEITHER,
            RecommendationReason.COMPRESSED_BYTES_IDENTICAL));
  }

  @Test
  public void testGeneratePreDiffPlan_SimpleRename_CompressionLevelChanged() throws IOException {
    // Test the case where file paths are different but the uncompressed content is the same.
    // The compression method used for each entry is different but the CRC32 is still the same, so
    // unlike like the plan with identical entries this time the plan should be to uncompress both
    // entries, allowing a super-efficient delta.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(SHADOW_ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress both entries so that a super-efficient delta can be done.
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertEquals(1, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithParams(newFile, SHADOW_ENTRY_A_LEVEL_9),
        plan.getNewFileUncompressionPlan().get(0));
    checkRecommendation(
        plan,
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_LEVEL_6),
            findEntry(newFile, SHADOW_ENTRY_A_LEVEL_9),
            Recommendation.UNCOMPRESS_BOTH,
            RecommendationReason.COMPRESSED_BYTES_CHANGED));
  }

  @Test
  public void testGeneratePreDiffPlan_ClonedAndCompressionLevelChanged() throws IOException {
    // Test the case where an entry exists in both old and new APK with identical uncompressed
    // content but different compressed content ***AND*** additionally a new copy exists in the new
    // archive, also with identical uncompressed content and different compressed content, i.e.:
    //
    // OLD APK:                                NEW APK:
    // ------------------------------------    -----------------------------------------------
    // foo.xml (compressed level 6)            foo.xml (compressed level 9, content unchanged)
    //                                         bar.xml (copy of foo.xml, compressed level 1)
    //
    // This test ensures that in such cases the foo.xml from the old apk is only enqueued for
    // uncompression ONE TIME.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(
            Arrays.asList(SHADOW_ENTRY_A_LEVEL_1, SHADOW_ENTRY_A_LEVEL_9));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress both entries so that a super-efficient delta can be done.
    // Critically there should only be ONE command for the old file uncompression step!
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertEquals(2, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithParams(newFile, SHADOW_ENTRY_A_LEVEL_1),
        plan.getNewFileUncompressionPlan().get(0));
    Assert.assertEquals(
        findRangeWithParams(newFile, SHADOW_ENTRY_A_LEVEL_9),
        plan.getNewFileUncompressionPlan().get(1));
    checkRecommendation(
        plan,
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_LEVEL_6),
            findEntry(newFile, SHADOW_ENTRY_A_LEVEL_1),
            Recommendation.UNCOMPRESS_BOTH,
            RecommendationReason.COMPRESSED_BYTES_CHANGED),
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_LEVEL_6),
            findEntry(newFile, SHADOW_ENTRY_A_LEVEL_9),
            Recommendation.UNCOMPRESS_BOTH,
            RecommendationReason.COMPRESSED_BYTES_CHANGED));
  }

  @Test
  public void testGeneratePreDiffPlan_SimpleRename_CompressedToUncompressed() throws IOException {
    // Test the case where file paths are different but the uncompressed content is the same.
    // The compression method is changed from compressed to uncompressed but the rename should still
    // be detected and the plan should be to uncompress the old entry only.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_LEVEL_6));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(SHADOW_ENTRY_A_STORED));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress the old entry so that a super-efficient delta can be done.
    // The new entry isn't touched because it is already uncompressed.
    Assert.assertEquals(1, plan.getOldFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithoutParams(oldFile, ENTRY_A_LEVEL_6),
        plan.getOldFileUncompressionPlan().get(0));
    Assert.assertTrue(plan.getNewFileUncompressionPlan().isEmpty());
    checkRecommendation(
        plan,
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_LEVEL_6),
            findEntry(newFile, SHADOW_ENTRY_A_STORED),
            Recommendation.UNCOMPRESS_OLD,
            RecommendationReason.COMPRESSED_CHANGED_TO_UNCOMPRESSED));
  }

  @Test
  public void testGeneratePreDiffPlan_SimpleRename_UncompressedToCompressed() throws IOException {
    // Test the case where file paths are different but the uncompressed content is the same.
    // The compression method is changed from uncompressed to compressed but the rename should still
    // be detected and the plan should be to uncompress the new entry only.
    byte[] oldBytes = UnitTestZipArchive.makeTestZip(Collections.singletonList(ENTRY_A_STORED));
    byte[] newBytes =
        UnitTestZipArchive.makeTestZip(Collections.singletonList(SHADOW_ENTRY_A_LEVEL_6));
    File oldFile = storeAndMapArchive(oldBytes);
    File newFile = storeAndMapArchive(newBytes);
    PreDiffPlan plan = invokeGeneratePreDiffPlan(oldFile, newFile);
    Assert.assertNotNull(plan);
    // The plan should be to uncompress the new entry so that a super-efficient delta can be done.
    // The old entry isn't touched because it is already uncompressed.
    Assert.assertTrue(plan.getOldFileUncompressionPlan().isEmpty());
    Assert.assertEquals(1, plan.getNewFileUncompressionPlan().size());
    Assert.assertEquals(
        findRangeWithParams(newFile, SHADOW_ENTRY_A_LEVEL_6),
        plan.getNewFileUncompressionPlan().get(0));
    checkRecommendation(
        plan,
        new QualifiedRecommendation(
            findEntry(oldFile, ENTRY_A_STORED),
            findEntry(newFile, SHADOW_ENTRY_A_LEVEL_6),
            Recommendation.UNCOMPRESS_NEW,
            RecommendationReason.UNCOMPRESSED_CHANGED_TO_COMPRESSED));
  }

}
