Index: third_party/protobuf/js/binary/reader_test.js |
diff --git a/third_party/protobuf/js/binary/reader_test.js b/third_party/protobuf/js/binary/reader_test.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a6482610ea5b296fb62a1863819d1ef1fcc46033 |
--- /dev/null |
+++ b/third_party/protobuf/js/binary/reader_test.js |
@@ -0,0 +1,889 @@ |
+// 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. We use the internal |
+ // .rawWriteVarint() to ensure the tested wire data is what we want, |
+ // independently of any serialization logic. |
+ writer.writeInt32(5, sentinel); |
+ // Start group, field 5. |
+ writer.rawWriteVarint( |
+ (5 << 3) + jspb.BinaryConstants.WireType.START_GROUP); |
+ // Varint, field 42. |
+ writer.rawWriteVarint( |
+ (42 << 3) + jspb.BinaryConstants.WireType.VARINT); |
+ // Varint data. |
+ writer.rawWriteVarint(42); |
+ // Start group, field 6. |
+ writer.rawWriteVarint( |
+ (6 << 3) + jspb.BinaryConstants.WireType.START_GROUP); |
+ // Varint, field 84. |
+ writer.rawWriteVarint( |
+ (84 << 3) + jspb.BinaryConstants.WireType.VARINT); |
+ writer.rawWriteVarint(42); |
+ // End group, field 6. |
+ writer.rawWriteVarint( |
+ (6 << 3) + jspb.BinaryConstants.WireType.END_GROUP); |
+ // End group, field 5. |
+ writer.rawWriteVarint( |
+ (5 << 3) + jspb.BinaryConstants.WireType.END_GROUP); |
+ |
+ // 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()); |
+ }); |
+}); |