// 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.
package com.google.devtools.build.android.ziputils;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENHOW;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENLEN;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENOFF;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENSIZ;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDOFF;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDSIG;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDSIZ;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDSUB;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDTOT;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.fail;

import com.google.devtools.build.android.ziputils.ZipIn.ZipEntry;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipInputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Unit tests for {@link ZipIn}.
 */
@RunWith(JUnit4.class)
public class ZipInTest {

  private static final int ENTRY_COUNT = 1000;
  private FakeFileSystem fileSystem;

  @Before
  public void setUp() throws Exception {
    fileSystem = new FakeFileSystem();
  }

  /**
   * Test of endOfCentralDirectory method, of class ZipIn.
   */
  @Test
  public void testEndOfCentralDirectory() throws Exception {

    String filename = "test.zip";
    byte[] bytes;
    ByteBuffer buffer;
    String comment;
    int commentLen;
    int offset;
    ZipIn zipIn;
    EndOfCentralDirectory result;
    String subcase;

    // Find it, even if it's the only useful thing in the file.
    subcase = " EOCD found it, ";
    bytes = new byte[] {
      0x50, 0x4b, 0x05, 0x06, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    result = zipIn.endOfCentralDirectory();
    assertWithMessage(subcase + "found").that(result).isNotNull();

    subcase = " EOCD not there at all, ";
    bytes = new byte[]{
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    try {
      zipIn.endOfCentralDirectory();
      fail(subcase + "expected IllegalStateException");
    } catch (Exception ex) {
      assertWithMessage(subcase + "caught exception")
          .that(ex.getClass())
          .isSameAs(IllegalStateException.class);
    }

    // If we can't read it, it's not there
    subcase = " EOCD too late to read, ";
    bytes = new byte[] {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0x50, 0x4b, 0x05, 0x06, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    try {
      zipIn.endOfCentralDirectory();
      fail(subcase + "expected IndexOutOfBoundsException");
    } catch (Exception ex) {
      assertWithMessage(subcase + "caught exception")
          .that(ex.getClass())
          .isSameAs(IndexOutOfBoundsException.class);
    }

    // Current implementation doesn't know to scan past a bad EOCD record.
    // I'm not sure if it should.
    subcase = " EOCD good hidden by bad, ";
    bytes = new byte[] {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0x50, 0x4b, 0x05, 0x06, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0x50, 0x4b, 0x05, 0x06, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    try {
      zipIn.endOfCentralDirectory();
      fail(subcase + "expected IndexOutOfBoundsException");
    } catch (Exception ex) {
      assertWithMessage(subcase + "caught exception")
          .that(ex.getClass())
          .isSameAs(IndexOutOfBoundsException.class);
    }

    // Minimal format checking here, assuming the EndOfDirectoryTest class
    // test for that.

    subcase = " EOCD truncated comment, ";
    bytes = new byte[100];
    buffer = ByteBuffer.wrap(bytes);
    comment = "optional file comment";
    commentLen = comment.getBytes(UTF_8).length;
    offset = bytes.length - ZipInputStream.ENDHDR - commentLen;
    buffer.position(offset);
    EndOfCentralDirectory.view(buffer, comment);
    byte[] truncated = Arrays.copyOf(bytes, bytes.length - 5);
    fileSystem.addFile(filename, truncated);
    zipIn = newZipIn(filename);
    try { // not sure this is the exception we want!
      zipIn.endOfCentralDirectory();
      fail(subcase + "expected IllegalArgumentException");
    } catch (Exception ex) {
      assertWithMessage(subcase + "caught exception")
          .that(ex.getClass())
          .isSameAs(IllegalArgumentException.class);
    }

    subcase = " EOCD no comment, ";
    bytes = new byte[100];
    buffer = ByteBuffer.wrap(bytes);
    comment = null;
    commentLen = 0;
    offset = bytes.length - ZipInputStream.ENDHDR - commentLen;
    buffer.position(offset);
    EndOfCentralDirectory.view(buffer, comment);
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    result = zipIn.endOfCentralDirectory();
    assertWithMessage(subcase + "found").that(result).isNotNull();
    assertWithMessage(subcase + "comment").that(result.getComment()).isEqualTo("");
    assertWithMessage(subcase + "marker")
        .that((int) result.get(ENDSIG))
        .isEqualTo(ZipInputStream.ENDSIG);

    subcase = " EOCD comment, ";
    bytes = new byte[100];
    buffer = ByteBuffer.wrap(bytes);
    comment = "optional file comment";
    commentLen = comment.getBytes(UTF_8).length;
    offset = bytes.length - ZipInputStream.ENDHDR - commentLen;
    buffer.position(offset);
    EndOfCentralDirectory.view(buffer, comment);
    assertWithMessage(subcase + "setup")
        .that(new String(bytes, bytes.length - commentLen, commentLen, UTF_8))
        .isEqualTo(comment);
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    result = zipIn.endOfCentralDirectory();
    assertWithMessage(subcase + "found").that(result).isNotNull();
    assertWithMessage(subcase + "comment").that(result.getComment()).isEqualTo(comment);
    assertWithMessage(subcase + "marker")
        .that((int) result.get(ENDSIG))
        .isEqualTo(ZipInputStream.ENDSIG);

    subcase = " EOCD extra data, ";
    bytes = new byte[100];
    buffer = ByteBuffer.wrap(bytes);
    comment = null;
    commentLen = 0;
    offset = bytes.length - ZipInputStream.ENDHDR - commentLen - 10;
    buffer.position(offset);
    EndOfCentralDirectory.view(buffer, comment);
    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    result = zipIn.endOfCentralDirectory();
    assertWithMessage(subcase + "found").that(result).isNotNull();
    assertWithMessage(subcase + "comment").that(result.getComment()).isEqualTo("");
    assertWithMessage(subcase + "marker")
        .that((int) result.get(ENDSIG))
        .isEqualTo(ZipInputStream.ENDSIG);
  }

  /**
   * Test of centralDirectory method, of class ZipIn.
   */
  @Test
  public void testCentralDirectory() throws Exception {
    String filename = "test.zip";
    ByteBuffer buffer;
    int offset;
    ZipIn zipIn;
    String subcase;
    subcase = " EOCD extra data, ";
    String commonName = "thisIsNotNormal.txt";
    int filenameLen = commonName.getBytes(UTF_8).length;
    int count = ENTRY_COUNT;
    int dirEntry = ZipInputStream.CENHDR;
    int before = count;
    int between = 0; // implementation doesn't tolerate data between dir entries, does the spec?
    int after = 20;
    int eocd = ZipInputStream.ENDHDR;
    int total = before + (count * (dirEntry + filenameLen)) + ((count - 1) * between)
        + after + eocd;
    byte[] bytes = new byte[total];
    offset = before;
    for (int i = 0; i < count; i++) {
      if (i > 0) {
        offset += between;
      }
      buffer = ByteBuffer.wrap(bytes, offset, bytes.length - offset);
      DirectoryEntry.view(buffer, commonName, null, null)
          .set(CENHOW, (short) 8)
          .set(CENSIZ, before)
          .set(CENLEN, 2 * before)
          .set(CENOFF, i); // Not valid of course, but we're only testing central dir parsing.
          // and there are currently no checks in the parser to see if offset makes sense.
      offset += dirEntry + filenameLen;
    }
    offset += after;
    buffer = ByteBuffer.wrap(bytes, offset, bytes.length - offset);
    EndOfCentralDirectory.view(buffer, null)
        .set(ENDOFF, before)
        .set(ENDSIZ, offset - before - after)
        .set(ENDTOT, (short) count)
        .set(ENDSUB, (short) count);

    fileSystem.addFile(filename, bytes);
    zipIn = newZipIn(filename);
    CentralDirectory result = zipIn.centralDirectory();
    assertWithMessage(subcase + "found").that(result).isNotNull();
    List<DirectoryEntry> list = result.list();
    assertWithMessage(subcase + "size").that(list.size()).isEqualTo(count);
    for (int i = 0; i < list.size(); i++) {
      assertWithMessage(subcase + "offset check[" + i + "]")
          .that(list.get(i).get(CENOFF))
          .isEqualTo(i);
    }
  }

  /**
   * Test of scanEntries method, of class ZipIn.
   */
  @Test
  public void testScanEntries() throws Exception {
    int count = ENTRY_COUNT * 100;
    String filename = "test.jar";

    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);

    final ZipIn zipIn = newZipIn(filename);
    zipIn.scanEntries(
        new EntryHandler() {
          int count = 0;

          @Override
          public void handle(
              ZipIn in, LocalFileHeader header, DirectoryEntry dirEntry, ByteBuffer data)
              throws IOException {
            assertThat(in).isSameAs(zipIn);
            String filename = "pkg/f" + count + ".class";
            assertThat(header.getFilename()).isEqualTo(filename);
            assertThat(dirEntry.getFilename()).isEqualTo(filename);
            count++;
          }
        });
  }

  /**
   * Test of nextHeaderFrom method, of class ZipIn.
   */
  @Test
  public void testNextHeaderFrom_long() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.endOfCentralDirectory();
    count = 0;
    int offset = 0;
    LocalFileHeader header;
    do {
      header = zipIn.nextHeaderFrom(offset);
      String name = "pkg/f" + count + ".class";
      if (header != null) {
        assertThat(header.getFilename()).isEqualTo(name);
        count++;
        offset = (int) header.fileOffset() + 4;
      }
    } while(header != null);
    assertThat(count).isEqualTo(ENTRY_COUNT);
  }

  /**
   * Test of nextHeaderFrom method, of class ZipIn.
   */
  @Test
  public void testNextHeaderFrom_DirectoryEntry() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    List<DirectoryEntry> list = zipIn.centralDirectory().list();
    count = 0;
    String name;
    LocalFileHeader header = zipIn.nextHeaderFrom(null);
    for (DirectoryEntry dirEntry : list) {
      name = "pkg/f" + count + ".class";
      assertThat(dirEntry.getFilename()).isEqualTo(name);
      assertThat(header.getFilename()).isEqualTo(name);
      header = zipIn.nextHeaderFrom(dirEntry);
      count++;
    }
    assertThat(header).isNull();
  }

  /**
   * Test of localHeaderFor method, of class ZipIn.
   */
  @Test
  public void testLocalHeaderFor() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    List<DirectoryEntry> list = zipIn.centralDirectory().list();
    count = 0;
    String name;
    LocalFileHeader header;
    for (DirectoryEntry dirEntry : list) {
      name = "pkg/f" + count + ".class";
      header = zipIn.localHeaderFor(dirEntry);
      assertThat(dirEntry.getFilename()).isEqualTo(name);
      assertThat(header.getFilename()).isEqualTo(name);
      count++;
    }
  }

  /**
   * Test of localHeaderAt method, of class ZipIn.
   */
  @Test
  public void testLocalHeaderAt() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    List<DirectoryEntry> list = zipIn.centralDirectory().list();
    count = 0;
    String name;
    LocalFileHeader header;
    for (DirectoryEntry dirEntry : list) {
      name = "pkg/f" + count + ".class";
      header = zipIn.localHeaderAt(dirEntry.get(CENOFF));
      assertThat(dirEntry.getFilename()).isEqualTo(name);
      assertThat(header.getFilename()).isEqualTo(name);
      count++;
    }
  }

  /**
   * Test of nextFrom method, of class ZipIn.
   */
  @Test
  public void testNextFrom_long() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    count = 0;
    int offset = 0;
    ZipEntry zipEntry;
    do {
      zipEntry = zipIn.nextFrom(offset);
      String name = "pkg/f" + count + ".class";
      if (zipEntry.getCode() != ZipEntry.Status.ENTRY_NOT_FOUND) {
        assertThat(zipEntry.getHeader()).isNotNull();
        assertThat(zipEntry.getDirEntry()).isNotNull();
        assertThat(zipEntry.getHeader().getFilename()).isEqualTo(name);
        assertThat(zipEntry.getDirEntry().getFilename()).isEqualTo(name);
        count++;
        offset = (int) zipEntry.getHeader().fileOffset() + 4;
      }
    } while(zipEntry.getCode() != ZipEntry.Status.ENTRY_NOT_FOUND);
    assertThat(count).isEqualTo(ENTRY_COUNT);
  }

  /**
   * Test of nextFrom method, of class ZipIn.
   */
  @Test
  public void testNextFrom_DirectoryEntry() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    List<DirectoryEntry> list = zipIn.centralDirectory().list();
    count = 0;
    String name;
    ZipEntry zipEntry = zipIn.nextFrom(null);
    for (DirectoryEntry dirEntry : list) {
      if (zipEntry.getCode() == ZipEntry.Status.ENTRY_NOT_FOUND) {
        break;
      }
      name = "pkg/f" + count + ".class";
      assertThat(zipEntry.getHeader()).isNotNull();
      assertThat(zipEntry.getDirEntry()).isNotNull();
      assertThat(zipEntry.getHeader().getFilename()).isEqualTo(name);
      assertThat(zipEntry.getDirEntry().getFilename()).isEqualTo(name);
      zipEntry = zipIn.nextFrom(dirEntry);
      count++;
    }
    assertThat(count).isEqualTo(ENTRY_COUNT);
  }

  /**
   * Test of entryAt method, of class ZipIn.
   */
  @Test
  public void testEntryAt() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    List<DirectoryEntry> list = zipIn.centralDirectory().list();
    count = 0;
    String name;
    ZipEntry zipEntry;
    for (DirectoryEntry dirEntry : list) {
      zipEntry = zipIn.entryAt(dirEntry.get(CENOFF));
      name = "pkg/f" + count + ".class";
      assertThat(zipEntry.getHeader()).isNotNull();
      assertThat(zipEntry.getDirEntry()).isNotNull();
      assertThat(zipEntry.getHeader().getFilename()).isEqualTo(name);
      assertThat(zipEntry.getDirEntry().getFilename()).isEqualTo(name);
      count++;
    }
    assertThat(count).isEqualTo(ENTRY_COUNT);
  }

  /**
   * Test of entryWith method, of class ZipIn.
   */
  @Test
  public void testEntryWith() throws Exception {
    int count = ENTRY_COUNT;
    String filename = "test.jar";
    ZipFileBuilder builder = new ZipFileBuilder();
    for (int i = 0; i < count; i++) {
      builder.add("pkg/f" + i + ".class", "All day long");
    }
    builder.create(filename);
    final ZipIn zipIn = newZipIn(filename);
    zipIn.centralDirectory();
    count = 0;
    int offset = 0;
    LocalFileHeader header;
    do {
      header = zipIn.nextHeaderFrom(offset);
      String name = "pkg/f" + count + ".class";
      if (header != null) {
        ZipEntry zipEntry = zipIn.entryWith(header);
        assertThat(zipEntry.getDirEntry()).isNotNull();
        assertThat(zipEntry.getHeader()).isSameAs(header);
        assertThat(zipEntry.getHeader().getFilename()).isEqualTo(name);
        assertThat(zipEntry.getDirEntry().getFilename()).isEqualTo(name);
        assertThat(header.getFilename()).isEqualTo(name);
        count++;
        offset = (int) header.fileOffset() + 4;
      }
    } while(header != null);
    assertThat(count).isEqualTo(ENTRY_COUNT);
  }

  private ZipIn newZipIn(String filename) throws IOException {
    return new ZipIn(fileSystem.getInputChannel(filename), filename);
  }
}
