// 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 reader.
 *
 * 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.BinaryReader');
goog.require('jspb.BinaryWriter');



describe('binaryReaderTest', function() {
  /**
   * Tests the reader instance cache.
   * @suppress {visibility}
   */
  it('testInstanceCaches', function() {
    var writer = new jspb.BinaryWriter();
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
    writer.writeMessage(1, dummyMessage, goog.nullFunction);
    writer.writeMessage(2, dummyMessage, goog.nullFunction);

    var buffer = writer.getResultBuffer();

    // Empty the instance caches.
    jspb.BinaryReader.instanceCache_ = [];

    // 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);
    assertEquals(0, jspb.BinaryReader.instanceCache_.length);

    // Allocating and then freeing a reader should remove one decoder from its
    // cache, but it should stay stuck to the reader afterwards since we can't
    // have a reader without a decoder.
    jspb.BinaryReader.alloc().free();

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

    // Allocating a reader should remove a reader from the cache.
    var reader = jspb.BinaryReader.alloc(buffer);

    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
    assertEquals(0, jspb.BinaryReader.instanceCache_.length);

    // Processing the message reuses the current reader.
    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    reader.readMessage(dummyMessage, function() {
      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
    });

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    reader.readMessage(dummyMessage, function() {
      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
    });

    assertEquals(false, reader.nextField());

    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
    assertEquals(0, jspb.BinaryReader.instanceCache_.length);

    // Freeing the reader should put it back into the cache.
    reader.free();

    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
  });


  /**
   * @param {number} x
   * @return {number}
   */
  function truncate(x) {
    var temp = new Float32Array(1);
    temp[0] = x;
    return temp[0];
  }


  /**
   * Verifies that misuse of the reader class triggers assertions.
   * @suppress {checkTypes|visibility}
   */
  it('testReadErrors', function() {
    // Calling readMessage on a non-delimited field should trigger an
    // assertion.
    var reader = jspb.BinaryReader.alloc([8, 1]);
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
    reader.nextField();
    assertThrows(function() {
      reader.readMessage(dummyMessage, goog.nullFunction);
    });

    // Reading past the end of the stream should trigger an assertion.
    reader = jspb.BinaryReader.alloc([9, 1]);
    reader.nextField();
    assertThrows(function() {reader.readFixed64()});

    // Reading past the end of a submessage should trigger an assertion.
    reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
    reader.nextField();
    reader.readMessage(dummyMessage, function() {
      reader.nextField();
      assertThrows(function() {reader.readFixed32()});
    });

    // Skipping an invalid field should trigger an assertion.
    reader = jspb.BinaryReader.alloc([12, 1]);
    reader.nextWireType_ = 1000;
    assertThrows(function() {reader.skipField()});

    // Reading fields with the wrong wire type should assert.
    reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
    reader.nextField();
    assertThrows(function() {reader.readInt32()});
    assertThrows(function() {reader.readInt32String()});
    assertThrows(function() {reader.readInt64()});
    assertThrows(function() {reader.readInt64String()});
    assertThrows(function() {reader.readUint32()});
    assertThrows(function() {reader.readUint32String()});
    assertThrows(function() {reader.readUint64()});
    assertThrows(function() {reader.readUint64String()});
    assertThrows(function() {reader.readSint32()});
    assertThrows(function() {reader.readBool()});
    assertThrows(function() {reader.readEnum()});

    reader = jspb.BinaryReader.alloc([8, 1]);
    reader.nextField();
    assertThrows(function() {reader.readFixed32()});
    assertThrows(function() {reader.readFixed64()});
    assertThrows(function() {reader.readSfixed32()});
    assertThrows(function() {reader.readSfixed64()});
    assertThrows(function() {reader.readFloat()});
    assertThrows(function() {reader.readDouble()});

    assertThrows(function() {reader.readString()});
    assertThrows(function() {reader.readBytes()});
  });


  /**
   * Tests encoding and decoding of unsigned field types.
   * @param {Function} readField
   * @param {Function} writeField
   * @param {number} epsilon
   * @param {number} upperLimit
   * @param {Function} filter
   * @private
   * @suppress {missingProperties}
   */
  function doTestUnsignedField_(readField,
      writeField, epsilon, upperLimit, filter) {
    assertNotNull(readField);
    assertNotNull(writeField);

    var writer = new jspb.BinaryWriter();

    // Encode zero and limits.
    writeField.call(writer, 1, filter(0));
    writeField.call(writer, 2, filter(epsilon));
    writeField.call(writer, 3, filter(upperLimit));

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

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    // Check zero and limits.
    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(filter(0), readField.call(reader));

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    assertEquals(filter(epsilon), readField.call(reader));

    reader.nextField();
    assertEquals(3, reader.getFieldNumber());
    assertEquals(filter(upperLimit), readField.call(reader));

    // Check positive values.
    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
      reader.nextField();
      if (4 != reader.getFieldNumber()) throw 'fail!';
      if (filter(cursor) != readField.call(reader)) throw 'fail!';
    }
  };


  /**
   * Tests encoding and decoding of signed field types.
   * @param {Function} readField
   * @param {Function} writeField
   * @param {number} epsilon
   * @param {number} lowerLimit
   * @param {number} upperLimit
   * @param {Function} filter
   * @private
   * @suppress {missingProperties}
   */
  function doTestSignedField_(readField,
      writeField, epsilon, lowerLimit, upperLimit, filter) {
    var writer = new jspb.BinaryWriter();

    // Encode zero and limits.
    writeField.call(writer, 1, filter(lowerLimit));
    writeField.call(writer, 2, filter(-epsilon));
    writeField.call(writer, 3, filter(0));
    writeField.call(writer, 4, filter(epsilon));
    writeField.call(writer, 5, filter(upperLimit));

    var inputValues = [];

    // Encode negative values.
    for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
      var val = filter(cursor);
      writeField.call(writer, 6, val);
      inputValues.push({
        fieldNumber: 6,
        value: val
      });
    }

    // Encode positive values.
    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
      var val = filter(cursor);
      writeField.call(writer, 7, val);
      inputValues.push({
        fieldNumber: 7,
        value: val
      });
    }

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    // Check zero and limits.
    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(filter(lowerLimit), readField.call(reader));

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    assertEquals(filter(-epsilon), readField.call(reader));

    reader.nextField();
    assertEquals(3, reader.getFieldNumber());
    assertEquals(filter(0), readField.call(reader));

    reader.nextField();
    assertEquals(4, reader.getFieldNumber());
    assertEquals(filter(epsilon), readField.call(reader));

    reader.nextField();
    assertEquals(5, reader.getFieldNumber());
    assertEquals(filter(upperLimit), readField.call(reader));

    for (var i = 0; i < inputValues.length; i++) {
      var expected = inputValues[i];
      reader.nextField();
      assertEquals(expected.fieldNumber, reader.getFieldNumber());
      assertEquals(expected.value, readField.call(reader));
    }
  };


  /**
   * Tests fields that use varint encoding.
   */
  it('testVarintFields', function() {
    assertNotNull(jspb.BinaryReader.prototype.readUint32);
    assertNotNull(jspb.BinaryReader.prototype.writeUint32);
    assertNotNull(jspb.BinaryReader.prototype.readUint64);
    assertNotNull(jspb.BinaryReader.prototype.writeUint64);
    assertNotNull(jspb.BinaryReader.prototype.readBool);
    assertNotNull(jspb.BinaryReader.prototype.writeBool);
    doTestUnsignedField_(
        jspb.BinaryReader.prototype.readUint32,
        jspb.BinaryWriter.prototype.writeUint32,
        1, Math.pow(2, 32) - 1, Math.round);

    doTestUnsignedField_(
        jspb.BinaryReader.prototype.readUint64,
        jspb.BinaryWriter.prototype.writeUint64,
        1, Math.pow(2, 64) - 1025, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readInt32,
        jspb.BinaryWriter.prototype.writeInt32,
        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readInt64,
        jspb.BinaryWriter.prototype.writeInt64,
        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readEnum,
        jspb.BinaryWriter.prototype.writeEnum,
        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);

    doTestUnsignedField_(
        jspb.BinaryReader.prototype.readBool,
        jspb.BinaryWriter.prototype.writeBool,
        1, 1, function(x) { return !!x; });
  });


  /**
   * Tests 64-bit fields that are handled as strings.
   */
  it('testStringInt64Fields', function() {
    var writer = new jspb.BinaryWriter();

    var testSignedData = [
      '2730538252207801776',
      '-2688470994844604560',
      '3398529779486536359',
      '3568577411627971000',
      '272477188847484900',
      '-6649058714086158188',
      '-7695254765712060806',
      '-4525541438037104029',
      '-4993706538836508568',
      '4990160321893729138'
    ];
    var testUnsignedData = [
      '7822732630241694882',
      '6753602971916687352',
      '2399935075244442116',
      '8724292567325338867',
      '16948784802625696584',
      '4136275908516066934',
      '3575388346793700364',
      '5167142028379259461',
      '1557573948689737699',
      '17100725280812548567'
    ];

    for (var i = 0; i < testSignedData.length; i++) {
      writer.writeInt64String(2 * i + 1, testSignedData[i]);
      writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
    }

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    for (var i = 0; i < testSignedData.length; i++) {
      reader.nextField();
      assertEquals(2 * i + 1, reader.getFieldNumber());
      assertEquals(testSignedData[i], reader.readInt64String());
      reader.nextField();
      assertEquals(2 * i + 2, reader.getFieldNumber());
      assertEquals(testUnsignedData[i], reader.readUint64String());
    }
  });


  /**
   * Tests fields that use zigzag encoding.
   */
  it('testZigzagFields', function() {
    doTestSignedField_(
        jspb.BinaryReader.prototype.readSint32,
        jspb.BinaryWriter.prototype.writeSint32,
        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readSint64,
        jspb.BinaryWriter.prototype.writeSint64,
        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
  });


  /**
   * Tests fields that use fixed-length encoding.
   */
  it('testFixedFields', function() {
    doTestUnsignedField_(
        jspb.BinaryReader.prototype.readFixed32,
        jspb.BinaryWriter.prototype.writeFixed32,
        1, Math.pow(2, 32) - 1, Math.round);

    doTestUnsignedField_(
        jspb.BinaryReader.prototype.readFixed64,
        jspb.BinaryWriter.prototype.writeFixed64,
        1, Math.pow(2, 64) - 1025, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readSfixed32,
        jspb.BinaryWriter.prototype.writeSfixed32,
        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readSfixed64,
        jspb.BinaryWriter.prototype.writeSfixed64,
        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
  });


  /**
   * Tests floating point fields.
   */
  it('testFloatFields', function() {
    doTestSignedField_(
        jspb.BinaryReader.prototype.readFloat,
        jspb.BinaryWriter.prototype.writeFloat,
        jspb.BinaryConstants.FLOAT32_MIN,
        -jspb.BinaryConstants.FLOAT32_MAX,
        jspb.BinaryConstants.FLOAT32_MAX,
        truncate);

    doTestSignedField_(
        jspb.BinaryReader.prototype.readDouble,
        jspb.BinaryWriter.prototype.writeDouble,
        jspb.BinaryConstants.FLOAT64_EPS * 10,
        -jspb.BinaryConstants.FLOAT64_MIN,
        jspb.BinaryConstants.FLOAT64_MIN,
        function(x) { return x; });
  });


  /**
   * Tests length-delimited string fields.
   */
  it('testStringFields', function() {
    var s1 = 'The quick brown fox jumps over the lazy dog.';
    var s2 = '人人生而自由，在尊嚴和權利上一律平等。';

    var writer = new jspb.BinaryWriter();

    writer.writeString(1, s1);
    writer.writeString(2, s2);

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(s1, reader.readString());

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    assertEquals(s2, reader.readString());
  });


  /**
   * Tests length-delimited byte fields.
   */
  it('testByteFields', function() {
    var message = [];
    var lowerLimit = 1;
    var upperLimit = 256;
    var scale = 1.1;

    var writer = new jspb.BinaryWriter();

    for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
      var len = Math.round(cursor);
      var bytes = [];
      for (var i = 0; i < len; i++) bytes.push(i % 256);

      writer.writeBytes(len, bytes);
    }

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
      var len = Math.round(cursor);
      if (len != reader.getFieldNumber()) throw 'fail!';

      var bytes = reader.readBytes();
      if (len != bytes.length) throw 'fail!';
      for (var i = 0; i < bytes.length; i++) {
        if (i % 256 != bytes[i]) throw 'fail!';
      }
    }
  });


  /**
   * Tests nested messages.
   */
  it('testNesting', function() {
    var writer = new jspb.BinaryWriter();
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});

    writer.writeInt32(1, 100);

    // Add one message with 3 int fields.
    writer.writeMessage(2, dummyMessage, function() {
      writer.writeInt32(3, 300);
      writer.writeInt32(4, 400);
      writer.writeInt32(5, 500);
    });

    // Add one empty message.
    writer.writeMessage(6, dummyMessage, goog.nullFunction);

    writer.writeInt32(7, 700);

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    // Validate outermost message.

    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(100, reader.readInt32());

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    reader.readMessage(dummyMessage, function() {
      // Validate embedded message 1.
      reader.nextField();
      assertEquals(3, reader.getFieldNumber());
      assertEquals(300, reader.readInt32());

      reader.nextField();
      assertEquals(4, reader.getFieldNumber());
      assertEquals(400, reader.readInt32());

      reader.nextField();
      assertEquals(5, reader.getFieldNumber());
      assertEquals(500, reader.readInt32());

      assertEquals(false, reader.nextField());
    });

    reader.nextField();
    assertEquals(6, reader.getFieldNumber());
    reader.readMessage(dummyMessage, function() {
      // Validate embedded message 2.

      assertEquals(false, reader.nextField());
    });

    reader.nextField();
    assertEquals(7, reader.getFieldNumber());
    assertEquals(700, reader.readInt32());

    assertEquals(false, reader.nextField());
  });

  /**
   * Tests skipping fields of each type by interleaving them with sentinel
   * values and skipping everything that's not a sentinel.
   */
  it('testSkipField', function() {
    var writer = new jspb.BinaryWriter();

    var sentinel = 123456789;

    // Write varint fields of different sizes.
    writer.writeInt32(1, sentinel);
    writer.writeInt32(1, 1);
    writer.writeInt32(1, 1000);
    writer.writeInt32(1, 1000000);
    writer.writeInt32(1, 1000000000);

    // Write fixed 64-bit encoded fields.
    writer.writeInt32(2, sentinel);
    writer.writeDouble(2, 1);
    writer.writeFixed64(2, 1);
    writer.writeSfixed64(2, 1);

    // Write fixed 32-bit encoded fields.
    writer.writeInt32(3, sentinel);
    writer.writeFloat(3, 1);
    writer.writeFixed32(3, 1);
    writer.writeSfixed32(3, 1);

    // Write delimited fields.
    writer.writeInt32(4, sentinel);
    writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    writer.writeString(4, 'The quick brown fox jumps over the lazy dog');

    // Write a group with a nested group inside.
    writer.writeInt32(5, sentinel);
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
    writer.writeGroup(5, dummyMessage, function() {
      writer.writeInt64(42, 42);
      writer.writeGroup(6, dummyMessage, function() {
        writer.writeInt64(84, 42);
      });
    });

    // Write final sentinel.
    writer.writeInt32(6, sentinel);

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    function skip(field, count) {
      for (var i = 0; i < count; i++) {
        reader.nextField();
        if (field != reader.getFieldNumber()) throw 'fail!';
        reader.skipField();
      }
    }

    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
    skip(1, 4);

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
    skip(2, 3);

    reader.nextField();
    assertEquals(3, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
    skip(3, 3);

    reader.nextField();
    assertEquals(4, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
    skip(4, 2);

    reader.nextField();
    assertEquals(5, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
    skip(5, 1);

    reader.nextField();
    assertEquals(6, reader.getFieldNumber());
    assertEquals(sentinel, reader.readInt32());
  });


  /**
   * Tests packed fields.
   */
  it('testPackedFields', function() {
    var writer = new jspb.BinaryWriter();

    var sentinel = 123456789;

    var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
    var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
    var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
    var boolData = [true, false, true, true, false, false, true, false];

    for (var i = 0; i < floatData.length; i++) {
      floatData[i] = truncate(floatData[i]);
    }

    writer.writeInt32(1, sentinel);

    writer.writePackedInt32(2, signedData);
    writer.writePackedInt64(2, signedData);
    writer.writePackedUint32(2, unsignedData);
    writer.writePackedUint64(2, unsignedData);
    writer.writePackedSint32(2, signedData);
    writer.writePackedSint64(2, signedData);
    writer.writePackedFixed32(2, unsignedData);
    writer.writePackedFixed64(2, unsignedData);
    writer.writePackedSfixed32(2, signedData);
    writer.writePackedSfixed64(2, signedData);
    writer.writePackedFloat(2, floatData);
    writer.writePackedDouble(2, doubleData);
    writer.writePackedBool(2, boolData);
    writer.writePackedEnum(2, unsignedData);

    writer.writeInt32(3, sentinel);

    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    reader.nextField();
    assertEquals(sentinel, reader.readInt32());

    reader.nextField();
    assertElementsEquals(reader.readPackedInt32(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedInt64(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedUint32(), unsignedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedUint64(), unsignedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedSint32(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedSint64(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedFixed32(), unsignedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedFixed64(), unsignedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedSfixed32(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedSfixed64(), signedData);

    reader.nextField();
    assertElementsEquals(reader.readPackedFloat(), floatData);

    reader.nextField();
    assertElementsEquals(reader.readPackedDouble(), doubleData);

    reader.nextField();
    assertElementsEquals(reader.readPackedBool(), boolData);

    reader.nextField();
    assertElementsEquals(reader.readPackedEnum(), unsignedData);

    reader.nextField();
    assertEquals(sentinel, reader.readInt32());
  });


  /**
   * Byte blobs inside nested messages should always have their byte offset set
   * relative to the start of the outermost blob, not the start of their parent
   * blob.
   */
  it('testNestedBlobs', function() {
    // Create a proto consisting of two nested messages, with the inner one
    // containing a blob of bytes.

    var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
    var blob = [1, 2, 3, 4, 5];
    var writer = new jspb.BinaryWriter();
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});

    writer.writeMessage(1, dummyMessage, function() {
      writer.writeMessage(1, dummyMessage, function() {
        writer.writeBytes(1, blob);
      });
    });

    // Peel off the outer two message layers. Each layer should have two bytes
    // of overhead, one for the field tag and one for the length of the inner
    // blob.

    var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
    assertEquals(fieldTag, decoder1.readUnsignedVarint32());
    assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());

    var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
    assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());

    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
    assertEquals(blob.length, decoder2.readUnsignedVarint32());
    var bytes = decoder2.readBytes(blob.length);

    assertElementsEquals(bytes, blob);
  });


  /**
   * Tests read callbacks.
   */
  it('testReadCallbacks', function() {
    var writer = new jspb.BinaryWriter();
    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});

    // Add an int, a submessage, and another int.
    writer.writeInt32(1, 100);

    writer.writeMessage(2, dummyMessage, function() {
      writer.writeInt32(3, 300);
      writer.writeInt32(4, 400);
      writer.writeInt32(5, 500);
    });

    writer.writeInt32(7, 700);

    // Create the reader and register a custom read callback.
    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());

    /**
     * @param {!jspb.BinaryReader} reader
     * @return {*}
     */
    function readCallback(reader) {
      reader.nextField();
      assertEquals(3, reader.getFieldNumber());
      assertEquals(300, reader.readInt32());

      reader.nextField();
      assertEquals(4, reader.getFieldNumber());
      assertEquals(400, reader.readInt32());

      reader.nextField();
      assertEquals(5, reader.getFieldNumber());
      assertEquals(500, reader.readInt32());

      assertEquals(false, reader.nextField());
    };

    reader.registerReadCallback('readCallback', readCallback);

    // Read the container message.
    reader.nextField();
    assertEquals(1, reader.getFieldNumber());
    assertEquals(100, reader.readInt32());

    reader.nextField();
    assertEquals(2, reader.getFieldNumber());
    reader.readMessage(dummyMessage, function() {
      // Decode the embedded message using the registered callback.
      reader.runReadCallback('readCallback');
    });

    reader.nextField();
    assertEquals(7, reader.getFieldNumber());
    assertEquals(700, reader.readInt32());

    assertEquals(false, reader.nextField());
  });
});
