/*
 * Copyright (C) 2014 Square, Inc.
 *
 * 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 okio;

import java.io.IOException;
import java.util.zip.CRC32;
import org.junit.Test;

import static kotlin.text.Charsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public final class GzipSourceTest {

  @Test public void gunzip() throws Exception {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeader);
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  @Test public void gunzip_withHCRC() throws Exception {
    CRC32 hcrc = new CRC32();
    ByteString gzipHeader = gzipHeaderWithFlags((byte) 0x02);
    hcrc.update(gzipHeader.toByteArray());

    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeader);
    gzipped.writeShort(TestUtil.reverseBytes((short) hcrc.getValue())); // little endian
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  @Test public void gunzip_withExtra() throws Exception {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeaderWithFlags((byte) 0x04));
    gzipped.writeShort(TestUtil.reverseBytes((short) 7)); // little endian extra length
    gzipped.write("blubber".getBytes(UTF_8), 0, 7);
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  @Test public void gunzip_withName() throws Exception {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeaderWithFlags((byte) 0x08));
    gzipped.write("foo.txt".getBytes(UTF_8), 0, 7);
    gzipped.writeByte(0); // zero-terminated
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  @Test public void gunzip_withComment() throws Exception {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeaderWithFlags((byte) 0x10));
    gzipped.write("rubbish".getBytes(UTF_8), 0, 7);
    gzipped.writeByte(0); // zero-terminated
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  /**
   * For portability, it is a good idea to export the gzipped bytes and try running gzip.  Ex.
   * {@code echo gzipped | base64 --decode | gzip -l -v}
   */
  @Test public void gunzip_withAll() throws Exception {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeaderWithFlags((byte) 0x1c));
    gzipped.writeShort(TestUtil.reverseBytes((short) 7)); // little endian extra length
    gzipped.write("blubber".getBytes(UTF_8), 0, 7);
    gzipped.write("foo.txt".getBytes(UTF_8), 0, 7);
    gzipped.writeByte(0); // zero-terminated
    gzipped.write("rubbish".getBytes(UTF_8), 0, 7);
    gzipped.writeByte(0); // zero-terminated
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);
    assertGzipped(gzipped);
  }

  private void assertGzipped(Buffer gzipped) throws IOException {
    Buffer gunzipped = gunzip(gzipped);
    assertEquals("It's a UNIX system! I know this!", gunzipped.readUtf8());
  }

  /**
   * Note that you cannot test this with old versions of gzip, as they interpret flag bit 1 as
   * CONTINUATION, not HCRC. For example, this is the case with the default gzip on osx.
   */
  @Test public void gunzipWhenHeaderCRCIncorrect() {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeaderWithFlags((byte) 0x02));
    gzipped.writeShort((short) 0); // wrong HCRC!
    gzipped.write(deflated);
    gzipped.write(gzipTrailer);

    try {
      gunzip(gzipped);
      fail();
    } catch (IOException e) {
      assertEquals("FHCRC: actual 0x0000261d != expected 0x00000000", e.getMessage());
    }
  }

  @Test public void gunzipWhenCRCIncorrect() {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeader);
    gzipped.write(deflated);
    gzipped.writeInt(TestUtil.reverseBytes(0x1234567)); // wrong CRC
    gzipped.write(gzipTrailer.toByteArray(), 3, 4);

    try {
      gunzip(gzipped);
      fail();
    } catch (IOException e) {
      assertEquals("CRC: actual 0x37ad8f8d != expected 0x01234567", e.getMessage());
    }
  }

  @Test public void gunzipWhenLengthIncorrect() {
    Buffer gzipped = new Buffer();
    gzipped.write(gzipHeader);
    gzipped.write(deflated);
    gzipped.write(gzipTrailer.toByteArray(), 0, 4);
    gzipped.writeInt(TestUtil.reverseBytes(0x123456)); // wrong length

    try {
      gunzip(gzipped);
      fail();
    } catch (IOException e) {
      assertEquals("ISIZE: actual 0x00000020 != expected 0x00123456", e.getMessage());
    }
  }

  @Test public void gunzipExhaustsSource() throws Exception {
    Buffer gzippedSource = new Buffer()
        .write(ByteString.decodeHex("1f8b08000000000000004b4c4a0600c241243503000000")); // 'abc'

    ExhaustableSource exhaustableSource = new ExhaustableSource(gzippedSource);
    BufferedSource gunzippedSource = Okio.buffer(new GzipSource(exhaustableSource));

    assertEquals('a', gunzippedSource.readByte());
    assertEquals('b', gunzippedSource.readByte());
    assertEquals('c', gunzippedSource.readByte());
    assertFalse(exhaustableSource.exhausted);
    assertEquals(-1, gunzippedSource.read(new Buffer(), 1));
    assertTrue(exhaustableSource.exhausted);
  }

  @Test public void gunzipThrowsIfSourceIsNotExhausted() throws Exception {
    Buffer gzippedSource = new Buffer()
        .write(ByteString.decodeHex("1f8b08000000000000004b4c4a0600c241243503000000")); // 'abc'
    gzippedSource.writeByte('d'); // This byte shouldn't be here!

    BufferedSource gunzippedSource = Okio.buffer(new GzipSource(gzippedSource));

    assertEquals('a', gunzippedSource.readByte());
    assertEquals('b', gunzippedSource.readByte());
    assertEquals('c', gunzippedSource.readByte());
    try {
      gunzippedSource.readByte();
      fail();
    } catch (IOException expected) {
    }
  }

  private ByteString gzipHeaderWithFlags(byte flags) {
    byte[] result = gzipHeader.toByteArray();
    result[3] = flags;
    return ByteString.of(result);
  }

  private final ByteString gzipHeader = ByteString.decodeHex("1f8b0800000000000000");

  // Deflated "It's a UNIX system! I know this!"
  private final ByteString deflated = ByteString.decodeHex(
      "f32c512f56485408f5f38c5028ae2c2e49cd5554f054c8cecb2f5728c9c82c560400");

  private final ByteString gzipTrailer = ByteString.decodeHex(""
      + "8d8fad37" // Checksum of deflated.
      + "20000000" // 32 in little endian.
  );

  private Buffer gunzip(Buffer gzipped) throws IOException {
    Buffer result = new Buffer();
    GzipSource source = new GzipSource(gzipped);
    while (source.read(result, Integer.MAX_VALUE) != -1) {
    }
    return result;
  }

  /** This source keeps track of whether its read has returned -1. */
  static class ExhaustableSource implements Source {
    private final Source source;
    private boolean exhausted;

    ExhaustableSource(Source source) {
      this.source = source;
    }

    @Override public long read(Buffer sink, long byteCount) throws IOException {
      long result = source.read(sink, byteCount);
      if (result == -1) exhausted = true;
      return result;
    }

    @Override public Timeout timeout() {
      return source.timeout();
    }

    @Override public void close() throws IOException {
      source.close();
    }
  }
}
