123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992 |
- // 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');
- goog.require('jspb.utils');
- goog.requireType('jspb.BinaryMessage');
- describe('binaryReaderTest', function() {
- /**
- * Tests the reader instance cache.
- */
- it('testInstanceCaches', /** @suppress {visibility} */ 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.
- */
- it('testReadErrors', /** @suppress {checkTypes|visibility} */ 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}
- */
- var doTestUnsignedField_ = function(
- 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}
- */
- var doTestSignedField_ = function(
- 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() {
- assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
- assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
- assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
- assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
- assertNotUndefined(jspb.BinaryReader.prototype.readBool);
- assertNotUndefined(jspb.BinaryWriter.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 reading a field from hexadecimal string (format: '08 BE EF').
- * @param {Function} readField
- * @param {number} expected
- * @param {string} hexString
- */
- function doTestHexStringVarint_(readField, expected, hexString) {
- var bytesCount = (hexString.length + 1) / 3;
- var bytes = new Uint8Array(bytesCount);
- for (var i = 0; i < bytesCount; i++) {
- bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
- }
- var reader = jspb.BinaryReader.alloc(bytes);
- reader.nextField();
- assertEquals(expected, readField.call(reader));
- }
- /**
- * Tests non-canonical redundant varint decoding.
- */
- it('testRedundantVarintFields', function() {
- assertNotNull(jspb.BinaryReader.prototype.readUint32);
- assertNotNull(jspb.BinaryReader.prototype.readUint64);
- assertNotNull(jspb.BinaryReader.prototype.readSint32);
- assertNotNull(jspb.BinaryReader.prototype.readSint64);
- // uint32 and sint32 take no more than 5 bytes
- // 08 - field prefix (type = 0 means varint)
- doTestHexStringVarint_(
- jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00');
- // 11 stands for -6 in zigzag encoding
- doTestHexStringVarint_(
- jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00');
- // uint64 and sint64 take no more than 10 bytes
- // 08 - field prefix (type = 0 means varint)
- doTestHexStringVarint_(
- jspb.BinaryReader.prototype.readUint64, 12,
- '08 8C 80 80 80 80 80 80 80 80 00');
- // 11 stands for -6 in zigzag encoding
- doTestHexStringVarint_(
- jspb.BinaryReader.prototype.readSint64, -6,
- '08 8B 80 80 80 80 80 80 80 80 00');
- });
- /**
- * Tests reading 64-bit integers as split values.
- */
- it('handles split 64 fields', function() {
- var writer = new jspb.BinaryWriter();
- writer.writeInt64String(1, '4294967296');
- writer.writeSfixed64String(2, '4294967298');
- writer.writeInt64String(3, '3'); // 3 is the zig-zag encoding of -2.
- var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
- function rejoin(lowBits, highBits) {
- return highBits * 2 ** 32 + (lowBits >>> 0);
- }
- reader.nextField();
- expect(reader.getFieldNumber()).toEqual(1);
- expect(reader.readSplitVarint64(rejoin)).toEqual(0x100000000);
- reader.nextField();
- expect(reader.getFieldNumber()).toEqual(2);
- expect(reader.readSplitFixed64(rejoin)).toEqual(0x100000002);
- reader.nextField();
- expect(reader.getFieldNumber()).toEqual(3);
- expect(reader.readSplitZigzagVarint64(rejoin)).toEqual(-2);
- });
- /**
- * 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);
- doTestSignedField_(
- jspb.BinaryReader.prototype.readSintHash64,
- jspb.BinaryWriter.prototype.writeSintHash64, 1, -Math.pow(2, 63),
- Math.pow(2, 63) - 513, jspb.utils.numberToHash64);
- });
- /**
- * 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() {
- // Previously the skipGroup implementation was wrong, which only consume
- // the decoder by nextField. This case is for making the previous
- // implementation failed in skipGroup by an early end group tag.
- // The reason is 44 = 5 * 8 + 4, this will be translated in to a field
- // with number 5 and with type 4 (end group)
- writer.writeInt64(44, 44);
- // This will make previous implementation failed by invalid tag (7).
- writer.writeInt64(42, 47);
- writer.writeInt64(42, 42);
- // This is for making the previous implementation failed by an invalid
- // varint. The bytes have at least 9 consecutive minus byte, which will
- // fail in this.nextField for previous implementation.
- writer.writeBytes(43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
- writer.writeGroup(6, dummyMessage, function() {
- writer.writeInt64(84, 42);
- writer.writeInt64(84, 44);
- writer.writeBytes(
- 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
- });
- });
- // 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());
- });
- });
|