// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/**
 * @fileoverview Test cases for jspb's binary protocol buffer decoder.
 *
 * There are two particular magic numbers that need to be pointed out -
 * 2^64-1025 is the largest number representable as both a double and an
 * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
 * both a double and a signed 64-bit integer.
 *
 * Test suite is written using Jasmine -- see http://jasmine.github.io/
 *
 * @author aappleby@google.com (Austin Appleby)
 */

goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryEncoder');


/**
 * Tests encoding and decoding of unsigned types.
 * @param {Function} readValue
 * @param {Function} writeValue
 * @param {number} epsilon
 * @param {number} upperLimit
 * @param {Function} filter
 * @suppress {missingProperties|visibility}
 */
function doTestUnsignedValue(readValue,
    writeValue, epsilon, upperLimit, filter) {
  var encoder = new jspb.BinaryEncoder();

  // Encode zero and limits.
  writeValue.call(encoder, filter(0));
  writeValue.call(encoder, filter(epsilon));
  writeValue.call(encoder, filter(upperLimit));

  // Encode positive values.
  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
    writeValue.call(encoder, filter(cursor));
  }

  var decoder = jspb.BinaryDecoder.alloc(encoder.end());

  // Check zero and limits.
  assertEquals(filter(0), readValue.call(decoder));
  assertEquals(filter(epsilon), readValue.call(decoder));
  assertEquals(filter(upperLimit), readValue.call(decoder));

  // Check positive values.
  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
    if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
  }

  // Encoding values outside the valid range should assert.
  assertThrows(function() {writeValue.call(encoder, -1);});
  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
}


/**
 * Tests encoding and decoding of signed types.
 * @param {Function} readValue
 * @param {Function} writeValue
 * @param {number} epsilon
 * @param {number} lowerLimit
 * @param {number} upperLimit
 * @param {Function} filter
 * @suppress {missingProperties}
 */
function doTestSignedValue(readValue,
    writeValue, epsilon, lowerLimit, upperLimit, filter) {
  var encoder = new jspb.BinaryEncoder();

  // Encode zero and limits.
  writeValue.call(encoder, filter(lowerLimit));
  writeValue.call(encoder, filter(-epsilon));
  writeValue.call(encoder, filter(0));
  writeValue.call(encoder, filter(epsilon));
  writeValue.call(encoder, filter(upperLimit));

  var inputValues = [];

  // Encode negative values.
  for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
    var val = filter(cursor);
    writeValue.call(encoder, val);
    inputValues.push(val);
  }

  // Encode positive values.
  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
    var val = filter(cursor);
    writeValue.call(encoder, val);
    inputValues.push(val);
  }

  var decoder = jspb.BinaryDecoder.alloc(encoder.end());

  // Check zero and limits.
  assertEquals(filter(lowerLimit), readValue.call(decoder));
  assertEquals(filter(-epsilon), readValue.call(decoder));
  assertEquals(filter(0), readValue.call(decoder));
  assertEquals(filter(epsilon), readValue.call(decoder));
  assertEquals(filter(upperLimit), readValue.call(decoder));

  // Verify decoded values.
  for (var i = 0; i < inputValues.length; i++) {
    assertEquals(inputValues[i], readValue.call(decoder));
  }

  // Encoding values outside the valid range should assert.
  assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);});
  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
}

describe('binaryDecoderTest', function() {
  /**
   * Tests the decoder instance cache.
   */
  it('testInstanceCache', /** @suppress {visibility} */ function() {
    // Empty the instance caches.
    jspb.BinaryDecoder.instanceCache_ = [];

    // Allocating and then freeing a decoder should put it in the instance
    // cache.
    jspb.BinaryDecoder.alloc().free();

    assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);

    // Allocating and then freeing three decoders should leave us with three in
    // the cache.

    var decoder1 = jspb.BinaryDecoder.alloc();
    var decoder2 = jspb.BinaryDecoder.alloc();
    var decoder3 = jspb.BinaryDecoder.alloc();
    decoder1.free();
    decoder2.free();
    decoder3.free();

    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
  });


  /**
   * Tests reading 64-bit integers as hash strings.
   */
  it('testHashStrings', function() {
    var encoder = new jspb.BinaryEncoder();

    var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00);
    var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00);
    var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
                                    0x87, 0x65, 0x43, 0x21);
    var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
                                    0xFF, 0xFF, 0xFF, 0xFF);

    encoder.writeVarintHash64(hashA);
    encoder.writeVarintHash64(hashB);
    encoder.writeVarintHash64(hashC);
    encoder.writeVarintHash64(hashD);

    encoder.writeFixedHash64(hashA);
    encoder.writeFixedHash64(hashB);
    encoder.writeFixedHash64(hashC);
    encoder.writeFixedHash64(hashD);

    var decoder = jspb.BinaryDecoder.alloc(encoder.end());

    assertEquals(hashA, decoder.readVarintHash64());
    assertEquals(hashB, decoder.readVarintHash64());
    assertEquals(hashC, decoder.readVarintHash64());
    assertEquals(hashD, decoder.readVarintHash64());

    assertEquals(hashA, decoder.readFixedHash64());
    assertEquals(hashB, decoder.readFixedHash64());
    assertEquals(hashC, decoder.readFixedHash64());
    assertEquals(hashD, decoder.readFixedHash64());
  });

  /**
   * Test encoding and decoding utf-8.
   */
   it('testUtf8', function() {
    var encoder = new jspb.BinaryEncoder();

    var ascii = "ASCII should work in 3, 2, 1...";
    var utf8_two_bytes = "©";
    var utf8_three_bytes = "❄";
    var utf8_four_bytes = "😁";

    encoder.writeString(ascii);
    encoder.writeString(utf8_two_bytes);
    encoder.writeString(utf8_three_bytes);
    encoder.writeString(utf8_four_bytes);

    var decoder = jspb.BinaryDecoder.alloc(encoder.end());

    assertEquals(ascii, decoder.readString(ascii.length));
    assertEquals(utf8_two_bytes, decoder.readString(utf8_two_bytes.length));
    assertEquals(utf8_three_bytes, decoder.readString(utf8_three_bytes.length));
    assertEquals(utf8_four_bytes, decoder.readString(utf8_four_bytes.length));
   });

  /**
   * Verifies that misuse of the decoder class triggers assertions.
   * @suppress {checkTypes|visibility}
   */
  it('testDecodeErrors', function() {
    // Reading a value past the end of the stream should trigger an assertion.
    var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
    assertThrows(function() {decoder.readUint64()});

    // Overlong varints should trigger assertions.
    decoder.setBlock([255, 255, 255, 255, 255, 255,
                      255, 255, 255, 255, 255, 0]);
    assertThrows(function() {decoder.readUnsignedVarint64()});
    decoder.reset();
    assertThrows(function() {decoder.readSignedVarint64()});
    decoder.reset();
    assertThrows(function() {decoder.readZigzagVarint64()});

    // Positive 32-bit varints encoded with 1 bits in positions 33 through 35
    // should trigger assertions.
    decoder.setBlock([255, 255, 255, 255, 0x1F]);
    assertThrows(function() {decoder.readUnsignedVarint32()});

    decoder.setBlock([255, 255, 255, 255, 0x2F]);
    assertThrows(function() {decoder.readUnsignedVarint32()});

    decoder.setBlock([255, 255, 255, 255, 0x4F]);
    assertThrows(function() {decoder.readUnsignedVarint32()});

    // Negative 32-bit varints encoded with non-1 bits in the high dword should
    // trigger assertions.
    decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]);
    assertThrows(function() {decoder.readUnsignedVarint32()});

    decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]);
    assertThrows(function() {decoder.readUnsignedVarint32()});
  });


  /**
   * Tests encoding and decoding of unsigned integers.
   */
  it('testUnsignedIntegers', function() {
    doTestUnsignedValue(
        jspb.BinaryDecoder.prototype.readUint8,
        jspb.BinaryEncoder.prototype.writeUint8,
        1, 0xFF, Math.round);

    doTestUnsignedValue(
        jspb.BinaryDecoder.prototype.readUint16,
        jspb.BinaryEncoder.prototype.writeUint16,
        1, 0xFFFF, Math.round);

    doTestUnsignedValue(
        jspb.BinaryDecoder.prototype.readUint32,
        jspb.BinaryEncoder.prototype.writeUint32,
        1, 0xFFFFFFFF, Math.round);

    doTestUnsignedValue(
        jspb.BinaryDecoder.prototype.readUint64,
        jspb.BinaryEncoder.prototype.writeUint64,
        1, Math.pow(2, 64) - 1025, Math.round);
  });


  /**
   * Tests encoding and decoding of signed integers.
   */
  it('testSignedIntegers', function() {
    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readInt8,
        jspb.BinaryEncoder.prototype.writeInt8,
        1, -0x80, 0x7F, Math.round);

    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readInt16,
        jspb.BinaryEncoder.prototype.writeInt16,
        1, -0x8000, 0x7FFF, Math.round);

    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readInt32,
        jspb.BinaryEncoder.prototype.writeInt32,
        1, -0x80000000, 0x7FFFFFFF, Math.round);

    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readInt64,
        jspb.BinaryEncoder.prototype.writeInt64,
        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
  });


  /**
   * Tests encoding and decoding of floats.
   */
  it('testFloats', function() {
    /**
     * @param {number} x
     * @return {number}
     */
    function truncate(x) {
      var temp = new Float32Array(1);
      temp[0] = x;
      return temp[0];
    }
    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readFloat,
        jspb.BinaryEncoder.prototype.writeFloat,
        jspb.BinaryConstants.FLOAT32_EPS,
        -jspb.BinaryConstants.FLOAT32_MAX,
        jspb.BinaryConstants.FLOAT32_MAX,
        truncate);

    doTestSignedValue(
        jspb.BinaryDecoder.prototype.readDouble,
        jspb.BinaryEncoder.prototype.writeDouble,
        jspb.BinaryConstants.FLOAT64_EPS * 10,
        -jspb.BinaryConstants.FLOAT64_MAX,
        jspb.BinaryConstants.FLOAT64_MAX,
        function(x) { return x; });
  });
});
