1ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format
2ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc.  All rights reserved.
3ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/
4ffe3c632Sopenharmony_ci//
5ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
6ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are
7ffe3c632Sopenharmony_ci// met:
8ffe3c632Sopenharmony_ci//
9ffe3c632Sopenharmony_ci//     * Redistributions of source code must retain the above copyright
10ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer.
11ffe3c632Sopenharmony_ci//     * Redistributions in binary form must reproduce the above
12ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer
13ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the
14ffe3c632Sopenharmony_ci// distribution.
15ffe3c632Sopenharmony_ci//     * Neither the name of Google Inc. nor the names of its
16ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from
17ffe3c632Sopenharmony_ci// this software without specific prior written permission.
18ffe3c632Sopenharmony_ci//
19ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30ffe3c632Sopenharmony_ci
31ffe3c632Sopenharmony_ci/**
32ffe3c632Sopenharmony_ci * @fileoverview Test cases for jspb's binary protocol buffer reader.
33ffe3c632Sopenharmony_ci *
34ffe3c632Sopenharmony_ci * There are two particular magic numbers that need to be pointed out -
35ffe3c632Sopenharmony_ci * 2^64-1025 is the largest number representable as both a double and an
36ffe3c632Sopenharmony_ci * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
37ffe3c632Sopenharmony_ci * both a double and a signed 64-bit integer.
38ffe3c632Sopenharmony_ci *
39ffe3c632Sopenharmony_ci * Test suite is written using Jasmine -- see http://jasmine.github.io/
40ffe3c632Sopenharmony_ci *
41ffe3c632Sopenharmony_ci * @author aappleby@google.com (Austin Appleby)
42ffe3c632Sopenharmony_ci */
43ffe3c632Sopenharmony_ci
44ffe3c632Sopenharmony_cigoog.require('goog.testing.asserts');
45ffe3c632Sopenharmony_cigoog.require('jspb.BinaryConstants');
46ffe3c632Sopenharmony_cigoog.require('jspb.BinaryDecoder');
47ffe3c632Sopenharmony_cigoog.require('jspb.BinaryReader');
48ffe3c632Sopenharmony_cigoog.require('jspb.BinaryWriter');
49ffe3c632Sopenharmony_ci
50ffe3c632Sopenharmony_ci
51ffe3c632Sopenharmony_ci
52ffe3c632Sopenharmony_cidescribe('binaryReaderTest', function() {
53ffe3c632Sopenharmony_ci  /**
54ffe3c632Sopenharmony_ci   * Tests the reader instance cache.
55ffe3c632Sopenharmony_ci   */
56ffe3c632Sopenharmony_ci  it('testInstanceCaches', /** @suppress {visibility} */ function() {
57ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
58ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
59ffe3c632Sopenharmony_ci    writer.writeMessage(1, dummyMessage, goog.nullFunction);
60ffe3c632Sopenharmony_ci    writer.writeMessage(2, dummyMessage, goog.nullFunction);
61ffe3c632Sopenharmony_ci
62ffe3c632Sopenharmony_ci    var buffer = writer.getResultBuffer();
63ffe3c632Sopenharmony_ci
64ffe3c632Sopenharmony_ci    // Empty the instance caches.
65ffe3c632Sopenharmony_ci    jspb.BinaryReader.instanceCache_ = [];
66ffe3c632Sopenharmony_ci
67ffe3c632Sopenharmony_ci    // Allocating and then freeing three decoders should leave us with three in
68ffe3c632Sopenharmony_ci    // the cache.
69ffe3c632Sopenharmony_ci
70ffe3c632Sopenharmony_ci    var decoder1 = jspb.BinaryDecoder.alloc();
71ffe3c632Sopenharmony_ci    var decoder2 = jspb.BinaryDecoder.alloc();
72ffe3c632Sopenharmony_ci    var decoder3 = jspb.BinaryDecoder.alloc();
73ffe3c632Sopenharmony_ci    decoder1.free();
74ffe3c632Sopenharmony_ci    decoder2.free();
75ffe3c632Sopenharmony_ci    decoder3.free();
76ffe3c632Sopenharmony_ci
77ffe3c632Sopenharmony_ci    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
78ffe3c632Sopenharmony_ci    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
79ffe3c632Sopenharmony_ci
80ffe3c632Sopenharmony_ci    // Allocating and then freeing a reader should remove one decoder from its
81ffe3c632Sopenharmony_ci    // cache, but it should stay stuck to the reader afterwards since we can't
82ffe3c632Sopenharmony_ci    // have a reader without a decoder.
83ffe3c632Sopenharmony_ci    jspb.BinaryReader.alloc().free();
84ffe3c632Sopenharmony_ci
85ffe3c632Sopenharmony_ci    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
86ffe3c632Sopenharmony_ci    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
87ffe3c632Sopenharmony_ci
88ffe3c632Sopenharmony_ci    // Allocating a reader should remove a reader from the cache.
89ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(buffer);
90ffe3c632Sopenharmony_ci
91ffe3c632Sopenharmony_ci    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
92ffe3c632Sopenharmony_ci    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
93ffe3c632Sopenharmony_ci
94ffe3c632Sopenharmony_ci    // Processing the message reuses the current reader.
95ffe3c632Sopenharmony_ci    reader.nextField();
96ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
97ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
98ffe3c632Sopenharmony_ci      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
99ffe3c632Sopenharmony_ci    });
100ffe3c632Sopenharmony_ci
101ffe3c632Sopenharmony_ci    reader.nextField();
102ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
103ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
104ffe3c632Sopenharmony_ci      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
105ffe3c632Sopenharmony_ci    });
106ffe3c632Sopenharmony_ci
107ffe3c632Sopenharmony_ci    assertEquals(false, reader.nextField());
108ffe3c632Sopenharmony_ci
109ffe3c632Sopenharmony_ci    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
110ffe3c632Sopenharmony_ci    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
111ffe3c632Sopenharmony_ci
112ffe3c632Sopenharmony_ci    // Freeing the reader should put it back into the cache.
113ffe3c632Sopenharmony_ci    reader.free();
114ffe3c632Sopenharmony_ci
115ffe3c632Sopenharmony_ci    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
116ffe3c632Sopenharmony_ci    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
117ffe3c632Sopenharmony_ci  });
118ffe3c632Sopenharmony_ci
119ffe3c632Sopenharmony_ci
120ffe3c632Sopenharmony_ci  /**
121ffe3c632Sopenharmony_ci   * @param {number} x
122ffe3c632Sopenharmony_ci   * @return {number}
123ffe3c632Sopenharmony_ci   */
124ffe3c632Sopenharmony_ci  function truncate(x) {
125ffe3c632Sopenharmony_ci    var temp = new Float32Array(1);
126ffe3c632Sopenharmony_ci    temp[0] = x;
127ffe3c632Sopenharmony_ci    return temp[0];
128ffe3c632Sopenharmony_ci  }
129ffe3c632Sopenharmony_ci
130ffe3c632Sopenharmony_ci
131ffe3c632Sopenharmony_ci  /**
132ffe3c632Sopenharmony_ci   * Verifies that misuse of the reader class triggers assertions.
133ffe3c632Sopenharmony_ci   */
134ffe3c632Sopenharmony_ci  it('testReadErrors', /** @suppress {checkTypes|visibility} */ function() {
135ffe3c632Sopenharmony_ci    // Calling readMessage on a non-delimited field should trigger an
136ffe3c632Sopenharmony_ci    // assertion.
137ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc([8, 1]);
138ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
139ffe3c632Sopenharmony_ci    reader.nextField();
140ffe3c632Sopenharmony_ci    assertThrows(function() {
141ffe3c632Sopenharmony_ci      reader.readMessage(dummyMessage, goog.nullFunction);
142ffe3c632Sopenharmony_ci    });
143ffe3c632Sopenharmony_ci
144ffe3c632Sopenharmony_ci    // Reading past the end of the stream should trigger an assertion.
145ffe3c632Sopenharmony_ci    reader = jspb.BinaryReader.alloc([9, 1]);
146ffe3c632Sopenharmony_ci    reader.nextField();
147ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readFixed64()});
148ffe3c632Sopenharmony_ci
149ffe3c632Sopenharmony_ci    // Reading past the end of a submessage should trigger an assertion.
150ffe3c632Sopenharmony_ci    reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
151ffe3c632Sopenharmony_ci    reader.nextField();
152ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
153ffe3c632Sopenharmony_ci      reader.nextField();
154ffe3c632Sopenharmony_ci      assertThrows(function() {reader.readFixed32()});
155ffe3c632Sopenharmony_ci    });
156ffe3c632Sopenharmony_ci
157ffe3c632Sopenharmony_ci    // Skipping an invalid field should trigger an assertion.
158ffe3c632Sopenharmony_ci    reader = jspb.BinaryReader.alloc([12, 1]);
159ffe3c632Sopenharmony_ci    reader.nextWireType_ = 1000;
160ffe3c632Sopenharmony_ci    assertThrows(function() {reader.skipField()});
161ffe3c632Sopenharmony_ci
162ffe3c632Sopenharmony_ci    // Reading fields with the wrong wire type should assert.
163ffe3c632Sopenharmony_ci    reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
164ffe3c632Sopenharmony_ci    reader.nextField();
165ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readInt32()});
166ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readInt32String()});
167ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readInt64()});
168ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readInt64String()});
169ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readUint32()});
170ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readUint32String()});
171ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readUint64()});
172ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readUint64String()});
173ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readSint32()});
174ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readBool()});
175ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readEnum()});
176ffe3c632Sopenharmony_ci
177ffe3c632Sopenharmony_ci    reader = jspb.BinaryReader.alloc([8, 1]);
178ffe3c632Sopenharmony_ci    reader.nextField();
179ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readFixed32()});
180ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readFixed64()});
181ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readSfixed32()});
182ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readSfixed64()});
183ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readFloat()});
184ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readDouble()});
185ffe3c632Sopenharmony_ci
186ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readString()});
187ffe3c632Sopenharmony_ci    assertThrows(function() {reader.readBytes()});
188ffe3c632Sopenharmony_ci  });
189ffe3c632Sopenharmony_ci
190ffe3c632Sopenharmony_ci
191ffe3c632Sopenharmony_ci  /**
192ffe3c632Sopenharmony_ci   * Tests encoding and decoding of unsigned field types.
193ffe3c632Sopenharmony_ci   * @param {Function} readField
194ffe3c632Sopenharmony_ci   * @param {Function} writeField
195ffe3c632Sopenharmony_ci   * @param {number} epsilon
196ffe3c632Sopenharmony_ci   * @param {number} upperLimit
197ffe3c632Sopenharmony_ci   * @param {Function} filter
198ffe3c632Sopenharmony_ci   * @private
199ffe3c632Sopenharmony_ci   * @suppress {missingProperties}
200ffe3c632Sopenharmony_ci   */
201ffe3c632Sopenharmony_ci  var doTestUnsignedField_ = function(readField,
202ffe3c632Sopenharmony_ci      writeField, epsilon, upperLimit, filter) {
203ffe3c632Sopenharmony_ci    assertNotNull(readField);
204ffe3c632Sopenharmony_ci    assertNotNull(writeField);
205ffe3c632Sopenharmony_ci
206ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
207ffe3c632Sopenharmony_ci
208ffe3c632Sopenharmony_ci    // Encode zero and limits.
209ffe3c632Sopenharmony_ci    writeField.call(writer, 1, filter(0));
210ffe3c632Sopenharmony_ci    writeField.call(writer, 2, filter(epsilon));
211ffe3c632Sopenharmony_ci    writeField.call(writer, 3, filter(upperLimit));
212ffe3c632Sopenharmony_ci
213ffe3c632Sopenharmony_ci    // Encode positive values.
214ffe3c632Sopenharmony_ci    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
215ffe3c632Sopenharmony_ci      writeField.call(writer, 4, filter(cursor));
216ffe3c632Sopenharmony_ci    }
217ffe3c632Sopenharmony_ci
218ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
219ffe3c632Sopenharmony_ci
220ffe3c632Sopenharmony_ci    // Check zero and limits.
221ffe3c632Sopenharmony_ci    reader.nextField();
222ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
223ffe3c632Sopenharmony_ci    assertEquals(filter(0), readField.call(reader));
224ffe3c632Sopenharmony_ci
225ffe3c632Sopenharmony_ci    reader.nextField();
226ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
227ffe3c632Sopenharmony_ci    assertEquals(filter(epsilon), readField.call(reader));
228ffe3c632Sopenharmony_ci
229ffe3c632Sopenharmony_ci    reader.nextField();
230ffe3c632Sopenharmony_ci    assertEquals(3, reader.getFieldNumber());
231ffe3c632Sopenharmony_ci    assertEquals(filter(upperLimit), readField.call(reader));
232ffe3c632Sopenharmony_ci
233ffe3c632Sopenharmony_ci    // Check positive values.
234ffe3c632Sopenharmony_ci    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
235ffe3c632Sopenharmony_ci      reader.nextField();
236ffe3c632Sopenharmony_ci      if (4 != reader.getFieldNumber()) throw 'fail!';
237ffe3c632Sopenharmony_ci      if (filter(cursor) != readField.call(reader)) throw 'fail!';
238ffe3c632Sopenharmony_ci    }
239ffe3c632Sopenharmony_ci  };
240ffe3c632Sopenharmony_ci
241ffe3c632Sopenharmony_ci
242ffe3c632Sopenharmony_ci  /**
243ffe3c632Sopenharmony_ci   * Tests encoding and decoding of signed field types.
244ffe3c632Sopenharmony_ci   * @param {Function} readField
245ffe3c632Sopenharmony_ci   * @param {Function} writeField
246ffe3c632Sopenharmony_ci   * @param {number} epsilon
247ffe3c632Sopenharmony_ci   * @param {number} lowerLimit
248ffe3c632Sopenharmony_ci   * @param {number} upperLimit
249ffe3c632Sopenharmony_ci   * @param {Function} filter
250ffe3c632Sopenharmony_ci   * @private
251ffe3c632Sopenharmony_ci   * @suppress {missingProperties}
252ffe3c632Sopenharmony_ci   */
253ffe3c632Sopenharmony_ci  var doTestSignedField_ = function(readField,
254ffe3c632Sopenharmony_ci      writeField, epsilon, lowerLimit, upperLimit, filter) {
255ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
256ffe3c632Sopenharmony_ci
257ffe3c632Sopenharmony_ci    // Encode zero and limits.
258ffe3c632Sopenharmony_ci    writeField.call(writer, 1, filter(lowerLimit));
259ffe3c632Sopenharmony_ci    writeField.call(writer, 2, filter(-epsilon));
260ffe3c632Sopenharmony_ci    writeField.call(writer, 3, filter(0));
261ffe3c632Sopenharmony_ci    writeField.call(writer, 4, filter(epsilon));
262ffe3c632Sopenharmony_ci    writeField.call(writer, 5, filter(upperLimit));
263ffe3c632Sopenharmony_ci
264ffe3c632Sopenharmony_ci    var inputValues = [];
265ffe3c632Sopenharmony_ci
266ffe3c632Sopenharmony_ci    // Encode negative values.
267ffe3c632Sopenharmony_ci    for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
268ffe3c632Sopenharmony_ci      var val = filter(cursor);
269ffe3c632Sopenharmony_ci      writeField.call(writer, 6, val);
270ffe3c632Sopenharmony_ci      inputValues.push({
271ffe3c632Sopenharmony_ci        fieldNumber: 6,
272ffe3c632Sopenharmony_ci        value: val
273ffe3c632Sopenharmony_ci      });
274ffe3c632Sopenharmony_ci    }
275ffe3c632Sopenharmony_ci
276ffe3c632Sopenharmony_ci    // Encode positive values.
277ffe3c632Sopenharmony_ci    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
278ffe3c632Sopenharmony_ci      var val = filter(cursor);
279ffe3c632Sopenharmony_ci      writeField.call(writer, 7, val);
280ffe3c632Sopenharmony_ci      inputValues.push({
281ffe3c632Sopenharmony_ci        fieldNumber: 7,
282ffe3c632Sopenharmony_ci        value: val
283ffe3c632Sopenharmony_ci      });
284ffe3c632Sopenharmony_ci    }
285ffe3c632Sopenharmony_ci
286ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
287ffe3c632Sopenharmony_ci
288ffe3c632Sopenharmony_ci    // Check zero and limits.
289ffe3c632Sopenharmony_ci    reader.nextField();
290ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
291ffe3c632Sopenharmony_ci    assertEquals(filter(lowerLimit), readField.call(reader));
292ffe3c632Sopenharmony_ci
293ffe3c632Sopenharmony_ci    reader.nextField();
294ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
295ffe3c632Sopenharmony_ci    assertEquals(filter(-epsilon), readField.call(reader));
296ffe3c632Sopenharmony_ci
297ffe3c632Sopenharmony_ci    reader.nextField();
298ffe3c632Sopenharmony_ci    assertEquals(3, reader.getFieldNumber());
299ffe3c632Sopenharmony_ci    assertEquals(filter(0), readField.call(reader));
300ffe3c632Sopenharmony_ci
301ffe3c632Sopenharmony_ci    reader.nextField();
302ffe3c632Sopenharmony_ci    assertEquals(4, reader.getFieldNumber());
303ffe3c632Sopenharmony_ci    assertEquals(filter(epsilon), readField.call(reader));
304ffe3c632Sopenharmony_ci
305ffe3c632Sopenharmony_ci    reader.nextField();
306ffe3c632Sopenharmony_ci    assertEquals(5, reader.getFieldNumber());
307ffe3c632Sopenharmony_ci    assertEquals(filter(upperLimit), readField.call(reader));
308ffe3c632Sopenharmony_ci
309ffe3c632Sopenharmony_ci    for (var i = 0; i < inputValues.length; i++) {
310ffe3c632Sopenharmony_ci      var expected = inputValues[i];
311ffe3c632Sopenharmony_ci      reader.nextField();
312ffe3c632Sopenharmony_ci      assertEquals(expected.fieldNumber, reader.getFieldNumber());
313ffe3c632Sopenharmony_ci      assertEquals(expected.value, readField.call(reader));
314ffe3c632Sopenharmony_ci    }
315ffe3c632Sopenharmony_ci  };
316ffe3c632Sopenharmony_ci
317ffe3c632Sopenharmony_ci
318ffe3c632Sopenharmony_ci  /**
319ffe3c632Sopenharmony_ci   * Tests fields that use varint encoding.
320ffe3c632Sopenharmony_ci   */
321ffe3c632Sopenharmony_ci  it('testVarintFields', function() {
322ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
323ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
324ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
325ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
326ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryReader.prototype.readBool);
327ffe3c632Sopenharmony_ci    assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
328ffe3c632Sopenharmony_ci    doTestUnsignedField_(
329ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readUint32,
330ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeUint32,
331ffe3c632Sopenharmony_ci        1, Math.pow(2, 32) - 1, Math.round);
332ffe3c632Sopenharmony_ci
333ffe3c632Sopenharmony_ci    doTestUnsignedField_(
334ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readUint64,
335ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeUint64,
336ffe3c632Sopenharmony_ci        1, Math.pow(2, 64) - 1025, Math.round);
337ffe3c632Sopenharmony_ci
338ffe3c632Sopenharmony_ci    doTestSignedField_(
339ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readInt32,
340ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeInt32,
341ffe3c632Sopenharmony_ci        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
342ffe3c632Sopenharmony_ci
343ffe3c632Sopenharmony_ci    doTestSignedField_(
344ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readInt64,
345ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeInt64,
346ffe3c632Sopenharmony_ci        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
347ffe3c632Sopenharmony_ci
348ffe3c632Sopenharmony_ci    doTestSignedField_(
349ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readEnum,
350ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeEnum,
351ffe3c632Sopenharmony_ci        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
352ffe3c632Sopenharmony_ci
353ffe3c632Sopenharmony_ci    doTestUnsignedField_(
354ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readBool,
355ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeBool,
356ffe3c632Sopenharmony_ci        1, 1, function(x) { return !!x; });
357ffe3c632Sopenharmony_ci  });
358ffe3c632Sopenharmony_ci
359ffe3c632Sopenharmony_ci
360ffe3c632Sopenharmony_ci  /**
361ffe3c632Sopenharmony_ci   * Tests reading a field from hexadecimal string (format: '08 BE EF').
362ffe3c632Sopenharmony_ci   * @param {Function} readField
363ffe3c632Sopenharmony_ci   * @param {number} expected
364ffe3c632Sopenharmony_ci   * @param {string} hexString
365ffe3c632Sopenharmony_ci   */
366ffe3c632Sopenharmony_ci  function doTestHexStringVarint_(readField, expected, hexString) {
367ffe3c632Sopenharmony_ci    var bytesCount = (hexString.length + 1) / 3;
368ffe3c632Sopenharmony_ci    var bytes = new Uint8Array(bytesCount);
369ffe3c632Sopenharmony_ci    for (var i = 0; i < bytesCount; i++) {
370ffe3c632Sopenharmony_ci      bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
371ffe3c632Sopenharmony_ci    }
372ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(bytes);
373ffe3c632Sopenharmony_ci    reader.nextField();
374ffe3c632Sopenharmony_ci    assertEquals(expected, readField.call(reader));
375ffe3c632Sopenharmony_ci  }
376ffe3c632Sopenharmony_ci
377ffe3c632Sopenharmony_ci
378ffe3c632Sopenharmony_ci  /**
379ffe3c632Sopenharmony_ci   * Tests non-canonical redundant varint decoding.
380ffe3c632Sopenharmony_ci   */
381ffe3c632Sopenharmony_ci  it('testRedundantVarintFields', function() {
382ffe3c632Sopenharmony_ci    assertNotNull(jspb.BinaryReader.prototype.readUint32);
383ffe3c632Sopenharmony_ci    assertNotNull(jspb.BinaryReader.prototype.readUint64);
384ffe3c632Sopenharmony_ci    assertNotNull(jspb.BinaryReader.prototype.readSint32);
385ffe3c632Sopenharmony_ci    assertNotNull(jspb.BinaryReader.prototype.readSint64);
386ffe3c632Sopenharmony_ci
387ffe3c632Sopenharmony_ci    // uint32 and sint32 take no more than 5 bytes
388ffe3c632Sopenharmony_ci    // 08 - field prefix (type = 0 means varint)
389ffe3c632Sopenharmony_ci    doTestHexStringVarint_(
390ffe3c632Sopenharmony_ci      jspb.BinaryReader.prototype.readUint32,
391ffe3c632Sopenharmony_ci      12, '08 8C 80 80 80 00');
392ffe3c632Sopenharmony_ci
393ffe3c632Sopenharmony_ci    // 11 stands for -6 in zigzag encoding
394ffe3c632Sopenharmony_ci    doTestHexStringVarint_(
395ffe3c632Sopenharmony_ci      jspb.BinaryReader.prototype.readSint32,
396ffe3c632Sopenharmony_ci      -6, '08 8B 80 80 80 00');
397ffe3c632Sopenharmony_ci
398ffe3c632Sopenharmony_ci    // uint64 and sint64 take no more than 10 bytes
399ffe3c632Sopenharmony_ci    // 08 - field prefix (type = 0 means varint)
400ffe3c632Sopenharmony_ci    doTestHexStringVarint_(
401ffe3c632Sopenharmony_ci      jspb.BinaryReader.prototype.readUint64,
402ffe3c632Sopenharmony_ci      12, '08 8C 80 80 80 80 80 80 80 80 00');
403ffe3c632Sopenharmony_ci
404ffe3c632Sopenharmony_ci    // 11 stands for -6 in zigzag encoding
405ffe3c632Sopenharmony_ci    doTestHexStringVarint_(
406ffe3c632Sopenharmony_ci      jspb.BinaryReader.prototype.readSint64,
407ffe3c632Sopenharmony_ci      -6, '08 8B 80 80 80 80 80 80 80 80 00');
408ffe3c632Sopenharmony_ci  });
409ffe3c632Sopenharmony_ci
410ffe3c632Sopenharmony_ci  /**
411ffe3c632Sopenharmony_ci   * Tests reading 64-bit integers as split values.
412ffe3c632Sopenharmony_ci   */
413ffe3c632Sopenharmony_ci  it('handles split 64 fields', function() {
414ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
415ffe3c632Sopenharmony_ci    writer.writeInt64String(1, '4294967296');
416ffe3c632Sopenharmony_ci    writer.writeSfixed64String(2, '4294967298');
417ffe3c632Sopenharmony_ci    writer.writeInt64String(3, '3');  // 3 is the zig-zag encoding of -2.
418ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
419ffe3c632Sopenharmony_ci
420ffe3c632Sopenharmony_ci    function rejoin(lowBits, highBits) {
421ffe3c632Sopenharmony_ci      return highBits * 2 ** 32 + (lowBits >>> 0);
422ffe3c632Sopenharmony_ci    }
423ffe3c632Sopenharmony_ci    reader.nextField();
424ffe3c632Sopenharmony_ci    expect(reader.getFieldNumber()).toEqual(1);
425ffe3c632Sopenharmony_ci    expect(reader.readSplitVarint64(rejoin)).toEqual(0x100000000);
426ffe3c632Sopenharmony_ci
427ffe3c632Sopenharmony_ci    reader.nextField();
428ffe3c632Sopenharmony_ci    expect(reader.getFieldNumber()).toEqual(2);
429ffe3c632Sopenharmony_ci    expect(reader.readSplitFixed64(rejoin)).toEqual(0x100000002);
430ffe3c632Sopenharmony_ci
431ffe3c632Sopenharmony_ci    reader.nextField();
432ffe3c632Sopenharmony_ci    expect(reader.getFieldNumber()).toEqual(3);
433ffe3c632Sopenharmony_ci    expect(reader.readSplitZigzagVarint64(rejoin)).toEqual(-2);
434ffe3c632Sopenharmony_ci  });
435ffe3c632Sopenharmony_ci
436ffe3c632Sopenharmony_ci  /**
437ffe3c632Sopenharmony_ci   * Tests 64-bit fields that are handled as strings.
438ffe3c632Sopenharmony_ci   */
439ffe3c632Sopenharmony_ci  it('testStringInt64Fields', function() {
440ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
441ffe3c632Sopenharmony_ci
442ffe3c632Sopenharmony_ci    var testSignedData = [
443ffe3c632Sopenharmony_ci      '2730538252207801776',
444ffe3c632Sopenharmony_ci      '-2688470994844604560',
445ffe3c632Sopenharmony_ci      '3398529779486536359',
446ffe3c632Sopenharmony_ci      '3568577411627971000',
447ffe3c632Sopenharmony_ci      '272477188847484900',
448ffe3c632Sopenharmony_ci      '-6649058714086158188',
449ffe3c632Sopenharmony_ci      '-7695254765712060806',
450ffe3c632Sopenharmony_ci      '-4525541438037104029',
451ffe3c632Sopenharmony_ci      '-4993706538836508568',
452ffe3c632Sopenharmony_ci      '4990160321893729138'
453ffe3c632Sopenharmony_ci    ];
454ffe3c632Sopenharmony_ci    var testUnsignedData = [
455ffe3c632Sopenharmony_ci      '7822732630241694882',
456ffe3c632Sopenharmony_ci      '6753602971916687352',
457ffe3c632Sopenharmony_ci      '2399935075244442116',
458ffe3c632Sopenharmony_ci      '8724292567325338867',
459ffe3c632Sopenharmony_ci      '16948784802625696584',
460ffe3c632Sopenharmony_ci      '4136275908516066934',
461ffe3c632Sopenharmony_ci      '3575388346793700364',
462ffe3c632Sopenharmony_ci      '5167142028379259461',
463ffe3c632Sopenharmony_ci      '1557573948689737699',
464ffe3c632Sopenharmony_ci      '17100725280812548567'
465ffe3c632Sopenharmony_ci    ];
466ffe3c632Sopenharmony_ci
467ffe3c632Sopenharmony_ci    for (var i = 0; i < testSignedData.length; i++) {
468ffe3c632Sopenharmony_ci      writer.writeInt64String(2 * i + 1, testSignedData[i]);
469ffe3c632Sopenharmony_ci      writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
470ffe3c632Sopenharmony_ci    }
471ffe3c632Sopenharmony_ci
472ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
473ffe3c632Sopenharmony_ci
474ffe3c632Sopenharmony_ci    for (var i = 0; i < testSignedData.length; i++) {
475ffe3c632Sopenharmony_ci      reader.nextField();
476ffe3c632Sopenharmony_ci      assertEquals(2 * i + 1, reader.getFieldNumber());
477ffe3c632Sopenharmony_ci      assertEquals(testSignedData[i], reader.readInt64String());
478ffe3c632Sopenharmony_ci      reader.nextField();
479ffe3c632Sopenharmony_ci      assertEquals(2 * i + 2, reader.getFieldNumber());
480ffe3c632Sopenharmony_ci      assertEquals(testUnsignedData[i], reader.readUint64String());
481ffe3c632Sopenharmony_ci    }
482ffe3c632Sopenharmony_ci  });
483ffe3c632Sopenharmony_ci
484ffe3c632Sopenharmony_ci
485ffe3c632Sopenharmony_ci  /**
486ffe3c632Sopenharmony_ci   * Tests fields that use zigzag encoding.
487ffe3c632Sopenharmony_ci   */
488ffe3c632Sopenharmony_ci  it('testZigzagFields', function() {
489ffe3c632Sopenharmony_ci    doTestSignedField_(
490ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readSint32,
491ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeSint32,
492ffe3c632Sopenharmony_ci        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
493ffe3c632Sopenharmony_ci
494ffe3c632Sopenharmony_ci    doTestSignedField_(
495ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readSint64,
496ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeSint64,
497ffe3c632Sopenharmony_ci        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
498ffe3c632Sopenharmony_ci
499ffe3c632Sopenharmony_ci    doTestSignedField_(
500ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readSintHash64,
501ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeSintHash64, 1, -Math.pow(2, 63),
502ffe3c632Sopenharmony_ci        Math.pow(2, 63) - 513, jspb.utils.numberToHash64);
503ffe3c632Sopenharmony_ci  });
504ffe3c632Sopenharmony_ci
505ffe3c632Sopenharmony_ci
506ffe3c632Sopenharmony_ci  /**
507ffe3c632Sopenharmony_ci   * Tests fields that use fixed-length encoding.
508ffe3c632Sopenharmony_ci   */
509ffe3c632Sopenharmony_ci  it('testFixedFields', function() {
510ffe3c632Sopenharmony_ci    doTestUnsignedField_(
511ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readFixed32,
512ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeFixed32,
513ffe3c632Sopenharmony_ci        1, Math.pow(2, 32) - 1, Math.round);
514ffe3c632Sopenharmony_ci
515ffe3c632Sopenharmony_ci    doTestUnsignedField_(
516ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readFixed64,
517ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeFixed64,
518ffe3c632Sopenharmony_ci        1, Math.pow(2, 64) - 1025, Math.round);
519ffe3c632Sopenharmony_ci
520ffe3c632Sopenharmony_ci    doTestSignedField_(
521ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readSfixed32,
522ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeSfixed32,
523ffe3c632Sopenharmony_ci        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
524ffe3c632Sopenharmony_ci
525ffe3c632Sopenharmony_ci    doTestSignedField_(
526ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readSfixed64,
527ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeSfixed64,
528ffe3c632Sopenharmony_ci        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
529ffe3c632Sopenharmony_ci  });
530ffe3c632Sopenharmony_ci
531ffe3c632Sopenharmony_ci
532ffe3c632Sopenharmony_ci  /**
533ffe3c632Sopenharmony_ci   * Tests floating point fields.
534ffe3c632Sopenharmony_ci   */
535ffe3c632Sopenharmony_ci  it('testFloatFields', function() {
536ffe3c632Sopenharmony_ci    doTestSignedField_(
537ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readFloat,
538ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeFloat,
539ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT32_MIN,
540ffe3c632Sopenharmony_ci        -jspb.BinaryConstants.FLOAT32_MAX,
541ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT32_MAX,
542ffe3c632Sopenharmony_ci        truncate);
543ffe3c632Sopenharmony_ci
544ffe3c632Sopenharmony_ci    doTestSignedField_(
545ffe3c632Sopenharmony_ci        jspb.BinaryReader.prototype.readDouble,
546ffe3c632Sopenharmony_ci        jspb.BinaryWriter.prototype.writeDouble,
547ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT64_EPS * 10,
548ffe3c632Sopenharmony_ci        -jspb.BinaryConstants.FLOAT64_MIN,
549ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT64_MIN,
550ffe3c632Sopenharmony_ci        function(x) { return x; });
551ffe3c632Sopenharmony_ci  });
552ffe3c632Sopenharmony_ci
553ffe3c632Sopenharmony_ci
554ffe3c632Sopenharmony_ci  /**
555ffe3c632Sopenharmony_ci   * Tests length-delimited string fields.
556ffe3c632Sopenharmony_ci   */
557ffe3c632Sopenharmony_ci  it('testStringFields', function() {
558ffe3c632Sopenharmony_ci    var s1 = 'The quick brown fox jumps over the lazy dog.';
559ffe3c632Sopenharmony_ci    var s2 = '人人生而自由,在尊嚴和權利上一律平等。';
560ffe3c632Sopenharmony_ci
561ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
562ffe3c632Sopenharmony_ci
563ffe3c632Sopenharmony_ci    writer.writeString(1, s1);
564ffe3c632Sopenharmony_ci    writer.writeString(2, s2);
565ffe3c632Sopenharmony_ci
566ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
567ffe3c632Sopenharmony_ci
568ffe3c632Sopenharmony_ci    reader.nextField();
569ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
570ffe3c632Sopenharmony_ci    assertEquals(s1, reader.readString());
571ffe3c632Sopenharmony_ci
572ffe3c632Sopenharmony_ci    reader.nextField();
573ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
574ffe3c632Sopenharmony_ci    assertEquals(s2, reader.readString());
575ffe3c632Sopenharmony_ci  });
576ffe3c632Sopenharmony_ci
577ffe3c632Sopenharmony_ci
578ffe3c632Sopenharmony_ci  /**
579ffe3c632Sopenharmony_ci   * Tests length-delimited byte fields.
580ffe3c632Sopenharmony_ci   */
581ffe3c632Sopenharmony_ci  it('testByteFields', function() {
582ffe3c632Sopenharmony_ci    var message = [];
583ffe3c632Sopenharmony_ci    var lowerLimit = 1;
584ffe3c632Sopenharmony_ci    var upperLimit = 256;
585ffe3c632Sopenharmony_ci    var scale = 1.1;
586ffe3c632Sopenharmony_ci
587ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
588ffe3c632Sopenharmony_ci
589ffe3c632Sopenharmony_ci    for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
590ffe3c632Sopenharmony_ci      var len = Math.round(cursor);
591ffe3c632Sopenharmony_ci      var bytes = [];
592ffe3c632Sopenharmony_ci      for (var i = 0; i < len; i++) bytes.push(i % 256);
593ffe3c632Sopenharmony_ci
594ffe3c632Sopenharmony_ci      writer.writeBytes(len, bytes);
595ffe3c632Sopenharmony_ci    }
596ffe3c632Sopenharmony_ci
597ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
598ffe3c632Sopenharmony_ci
599ffe3c632Sopenharmony_ci    for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
600ffe3c632Sopenharmony_ci      var len = Math.round(cursor);
601ffe3c632Sopenharmony_ci      if (len != reader.getFieldNumber()) throw 'fail!';
602ffe3c632Sopenharmony_ci
603ffe3c632Sopenharmony_ci      var bytes = reader.readBytes();
604ffe3c632Sopenharmony_ci      if (len != bytes.length) throw 'fail!';
605ffe3c632Sopenharmony_ci      for (var i = 0; i < bytes.length; i++) {
606ffe3c632Sopenharmony_ci        if (i % 256 != bytes[i]) throw 'fail!';
607ffe3c632Sopenharmony_ci      }
608ffe3c632Sopenharmony_ci    }
609ffe3c632Sopenharmony_ci  });
610ffe3c632Sopenharmony_ci
611ffe3c632Sopenharmony_ci
612ffe3c632Sopenharmony_ci  /**
613ffe3c632Sopenharmony_ci   * Tests nested messages.
614ffe3c632Sopenharmony_ci   */
615ffe3c632Sopenharmony_ci  it('testNesting', function() {
616ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
617ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
618ffe3c632Sopenharmony_ci
619ffe3c632Sopenharmony_ci    writer.writeInt32(1, 100);
620ffe3c632Sopenharmony_ci
621ffe3c632Sopenharmony_ci    // Add one message with 3 int fields.
622ffe3c632Sopenharmony_ci    writer.writeMessage(2, dummyMessage, function() {
623ffe3c632Sopenharmony_ci      writer.writeInt32(3, 300);
624ffe3c632Sopenharmony_ci      writer.writeInt32(4, 400);
625ffe3c632Sopenharmony_ci      writer.writeInt32(5, 500);
626ffe3c632Sopenharmony_ci    });
627ffe3c632Sopenharmony_ci
628ffe3c632Sopenharmony_ci    // Add one empty message.
629ffe3c632Sopenharmony_ci    writer.writeMessage(6, dummyMessage, goog.nullFunction);
630ffe3c632Sopenharmony_ci
631ffe3c632Sopenharmony_ci    writer.writeInt32(7, 700);
632ffe3c632Sopenharmony_ci
633ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
634ffe3c632Sopenharmony_ci
635ffe3c632Sopenharmony_ci    // Validate outermost message.
636ffe3c632Sopenharmony_ci
637ffe3c632Sopenharmony_ci    reader.nextField();
638ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
639ffe3c632Sopenharmony_ci    assertEquals(100, reader.readInt32());
640ffe3c632Sopenharmony_ci
641ffe3c632Sopenharmony_ci    reader.nextField();
642ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
643ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
644ffe3c632Sopenharmony_ci      // Validate embedded message 1.
645ffe3c632Sopenharmony_ci      reader.nextField();
646ffe3c632Sopenharmony_ci      assertEquals(3, reader.getFieldNumber());
647ffe3c632Sopenharmony_ci      assertEquals(300, reader.readInt32());
648ffe3c632Sopenharmony_ci
649ffe3c632Sopenharmony_ci      reader.nextField();
650ffe3c632Sopenharmony_ci      assertEquals(4, reader.getFieldNumber());
651ffe3c632Sopenharmony_ci      assertEquals(400, reader.readInt32());
652ffe3c632Sopenharmony_ci
653ffe3c632Sopenharmony_ci      reader.nextField();
654ffe3c632Sopenharmony_ci      assertEquals(5, reader.getFieldNumber());
655ffe3c632Sopenharmony_ci      assertEquals(500, reader.readInt32());
656ffe3c632Sopenharmony_ci
657ffe3c632Sopenharmony_ci      assertEquals(false, reader.nextField());
658ffe3c632Sopenharmony_ci    });
659ffe3c632Sopenharmony_ci
660ffe3c632Sopenharmony_ci    reader.nextField();
661ffe3c632Sopenharmony_ci    assertEquals(6, reader.getFieldNumber());
662ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
663ffe3c632Sopenharmony_ci      // Validate embedded message 2.
664ffe3c632Sopenharmony_ci
665ffe3c632Sopenharmony_ci      assertEquals(false, reader.nextField());
666ffe3c632Sopenharmony_ci    });
667ffe3c632Sopenharmony_ci
668ffe3c632Sopenharmony_ci    reader.nextField();
669ffe3c632Sopenharmony_ci    assertEquals(7, reader.getFieldNumber());
670ffe3c632Sopenharmony_ci    assertEquals(700, reader.readInt32());
671ffe3c632Sopenharmony_ci
672ffe3c632Sopenharmony_ci    assertEquals(false, reader.nextField());
673ffe3c632Sopenharmony_ci  });
674ffe3c632Sopenharmony_ci
675ffe3c632Sopenharmony_ci  /**
676ffe3c632Sopenharmony_ci   * Tests skipping fields of each type by interleaving them with sentinel
677ffe3c632Sopenharmony_ci   * values and skipping everything that's not a sentinel.
678ffe3c632Sopenharmony_ci   */
679ffe3c632Sopenharmony_ci  it('testSkipField', function() {
680ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
681ffe3c632Sopenharmony_ci
682ffe3c632Sopenharmony_ci    var sentinel = 123456789;
683ffe3c632Sopenharmony_ci
684ffe3c632Sopenharmony_ci    // Write varint fields of different sizes.
685ffe3c632Sopenharmony_ci    writer.writeInt32(1, sentinel);
686ffe3c632Sopenharmony_ci    writer.writeInt32(1, 1);
687ffe3c632Sopenharmony_ci    writer.writeInt32(1, 1000);
688ffe3c632Sopenharmony_ci    writer.writeInt32(1, 1000000);
689ffe3c632Sopenharmony_ci    writer.writeInt32(1, 1000000000);
690ffe3c632Sopenharmony_ci
691ffe3c632Sopenharmony_ci    // Write fixed 64-bit encoded fields.
692ffe3c632Sopenharmony_ci    writer.writeInt32(2, sentinel);
693ffe3c632Sopenharmony_ci    writer.writeDouble(2, 1);
694ffe3c632Sopenharmony_ci    writer.writeFixed64(2, 1);
695ffe3c632Sopenharmony_ci    writer.writeSfixed64(2, 1);
696ffe3c632Sopenharmony_ci
697ffe3c632Sopenharmony_ci    // Write fixed 32-bit encoded fields.
698ffe3c632Sopenharmony_ci    writer.writeInt32(3, sentinel);
699ffe3c632Sopenharmony_ci    writer.writeFloat(3, 1);
700ffe3c632Sopenharmony_ci    writer.writeFixed32(3, 1);
701ffe3c632Sopenharmony_ci    writer.writeSfixed32(3, 1);
702ffe3c632Sopenharmony_ci
703ffe3c632Sopenharmony_ci    // Write delimited fields.
704ffe3c632Sopenharmony_ci    writer.writeInt32(4, sentinel);
705ffe3c632Sopenharmony_ci    writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
706ffe3c632Sopenharmony_ci    writer.writeString(4, 'The quick brown fox jumps over the lazy dog');
707ffe3c632Sopenharmony_ci
708ffe3c632Sopenharmony_ci    // Write a group with a nested group inside.
709ffe3c632Sopenharmony_ci    writer.writeInt32(5, sentinel);
710ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
711ffe3c632Sopenharmony_ci    writer.writeGroup(5, dummyMessage, function() {
712ffe3c632Sopenharmony_ci      // Previously the skipGroup implementation was wrong, which only consume
713ffe3c632Sopenharmony_ci      // the decoder by nextField. This case is for making the previous
714ffe3c632Sopenharmony_ci      // implementation failed in skipGroup by an early end group tag.
715ffe3c632Sopenharmony_ci      // The reason is 44 = 5 * 8 + 4, this will be translated in to a field
716ffe3c632Sopenharmony_ci      // with number 5 and with type 4 (end group)
717ffe3c632Sopenharmony_ci      writer.writeInt64(44, 44);
718ffe3c632Sopenharmony_ci      // This will make previous implementation failed by invalid tag (7).
719ffe3c632Sopenharmony_ci      writer.writeInt64(42, 47);
720ffe3c632Sopenharmony_ci      writer.writeInt64(42, 42);
721ffe3c632Sopenharmony_ci      // This is for making the previous implementation failed by an invalid
722ffe3c632Sopenharmony_ci      // varint. The bytes have at least 9 consecutive minus byte, which will
723ffe3c632Sopenharmony_ci      // fail in this.nextField for previous implementation.
724ffe3c632Sopenharmony_ci      writer.writeBytes(43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
725ffe3c632Sopenharmony_ci      writer.writeGroup(6, dummyMessage, function() {
726ffe3c632Sopenharmony_ci        writer.writeInt64(84, 42);
727ffe3c632Sopenharmony_ci        writer.writeInt64(84, 44);
728ffe3c632Sopenharmony_ci        writer.writeBytes(
729ffe3c632Sopenharmony_ci          43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]);
730ffe3c632Sopenharmony_ci      });
731ffe3c632Sopenharmony_ci    });
732ffe3c632Sopenharmony_ci
733ffe3c632Sopenharmony_ci    // Write final sentinel.
734ffe3c632Sopenharmony_ci    writer.writeInt32(6, sentinel);
735ffe3c632Sopenharmony_ci
736ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
737ffe3c632Sopenharmony_ci
738ffe3c632Sopenharmony_ci    function skip(field, count) {
739ffe3c632Sopenharmony_ci      for (var i = 0; i < count; i++) {
740ffe3c632Sopenharmony_ci        reader.nextField();
741ffe3c632Sopenharmony_ci        if (field != reader.getFieldNumber()) throw 'fail!';
742ffe3c632Sopenharmony_ci        reader.skipField();
743ffe3c632Sopenharmony_ci      }
744ffe3c632Sopenharmony_ci    }
745ffe3c632Sopenharmony_ci
746ffe3c632Sopenharmony_ci    reader.nextField();
747ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
748ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
749ffe3c632Sopenharmony_ci    skip(1, 4);
750ffe3c632Sopenharmony_ci
751ffe3c632Sopenharmony_ci    reader.nextField();
752ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
753ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
754ffe3c632Sopenharmony_ci    skip(2, 3);
755ffe3c632Sopenharmony_ci
756ffe3c632Sopenharmony_ci    reader.nextField();
757ffe3c632Sopenharmony_ci    assertEquals(3, reader.getFieldNumber());
758ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
759ffe3c632Sopenharmony_ci    skip(3, 3);
760ffe3c632Sopenharmony_ci
761ffe3c632Sopenharmony_ci    reader.nextField();
762ffe3c632Sopenharmony_ci    assertEquals(4, reader.getFieldNumber());
763ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
764ffe3c632Sopenharmony_ci    skip(4, 2);
765ffe3c632Sopenharmony_ci
766ffe3c632Sopenharmony_ci    reader.nextField();
767ffe3c632Sopenharmony_ci    assertEquals(5, reader.getFieldNumber());
768ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
769ffe3c632Sopenharmony_ci    skip(5, 1);
770ffe3c632Sopenharmony_ci
771ffe3c632Sopenharmony_ci    reader.nextField();
772ffe3c632Sopenharmony_ci    assertEquals(6, reader.getFieldNumber());
773ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
774ffe3c632Sopenharmony_ci  });
775ffe3c632Sopenharmony_ci
776ffe3c632Sopenharmony_ci
777ffe3c632Sopenharmony_ci  /**
778ffe3c632Sopenharmony_ci   * Tests packed fields.
779ffe3c632Sopenharmony_ci   */
780ffe3c632Sopenharmony_ci  it('testPackedFields', function() {
781ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
782ffe3c632Sopenharmony_ci
783ffe3c632Sopenharmony_ci    var sentinel = 123456789;
784ffe3c632Sopenharmony_ci
785ffe3c632Sopenharmony_ci    var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
786ffe3c632Sopenharmony_ci    var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
787ffe3c632Sopenharmony_ci    var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
788ffe3c632Sopenharmony_ci    var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
789ffe3c632Sopenharmony_ci    var boolData = [true, false, true, true, false, false, true, false];
790ffe3c632Sopenharmony_ci
791ffe3c632Sopenharmony_ci    for (var i = 0; i < floatData.length; i++) {
792ffe3c632Sopenharmony_ci      floatData[i] = truncate(floatData[i]);
793ffe3c632Sopenharmony_ci    }
794ffe3c632Sopenharmony_ci
795ffe3c632Sopenharmony_ci    writer.writeInt32(1, sentinel);
796ffe3c632Sopenharmony_ci
797ffe3c632Sopenharmony_ci    writer.writePackedInt32(2, signedData);
798ffe3c632Sopenharmony_ci    writer.writePackedInt64(2, signedData);
799ffe3c632Sopenharmony_ci    writer.writePackedUint32(2, unsignedData);
800ffe3c632Sopenharmony_ci    writer.writePackedUint64(2, unsignedData);
801ffe3c632Sopenharmony_ci    writer.writePackedSint32(2, signedData);
802ffe3c632Sopenharmony_ci    writer.writePackedSint64(2, signedData);
803ffe3c632Sopenharmony_ci    writer.writePackedFixed32(2, unsignedData);
804ffe3c632Sopenharmony_ci    writer.writePackedFixed64(2, unsignedData);
805ffe3c632Sopenharmony_ci    writer.writePackedSfixed32(2, signedData);
806ffe3c632Sopenharmony_ci    writer.writePackedSfixed64(2, signedData);
807ffe3c632Sopenharmony_ci    writer.writePackedFloat(2, floatData);
808ffe3c632Sopenharmony_ci    writer.writePackedDouble(2, doubleData);
809ffe3c632Sopenharmony_ci    writer.writePackedBool(2, boolData);
810ffe3c632Sopenharmony_ci    writer.writePackedEnum(2, unsignedData);
811ffe3c632Sopenharmony_ci
812ffe3c632Sopenharmony_ci    writer.writeInt32(3, sentinel);
813ffe3c632Sopenharmony_ci
814ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
815ffe3c632Sopenharmony_ci
816ffe3c632Sopenharmony_ci    reader.nextField();
817ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
818ffe3c632Sopenharmony_ci
819ffe3c632Sopenharmony_ci    reader.nextField();
820ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedInt32(), signedData);
821ffe3c632Sopenharmony_ci
822ffe3c632Sopenharmony_ci    reader.nextField();
823ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedInt64(), signedData);
824ffe3c632Sopenharmony_ci
825ffe3c632Sopenharmony_ci    reader.nextField();
826ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedUint32(), unsignedData);
827ffe3c632Sopenharmony_ci
828ffe3c632Sopenharmony_ci    reader.nextField();
829ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedUint64(), unsignedData);
830ffe3c632Sopenharmony_ci
831ffe3c632Sopenharmony_ci    reader.nextField();
832ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedSint32(), signedData);
833ffe3c632Sopenharmony_ci
834ffe3c632Sopenharmony_ci    reader.nextField();
835ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedSint64(), signedData);
836ffe3c632Sopenharmony_ci
837ffe3c632Sopenharmony_ci    reader.nextField();
838ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedFixed32(), unsignedData);
839ffe3c632Sopenharmony_ci
840ffe3c632Sopenharmony_ci    reader.nextField();
841ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedFixed64(), unsignedData);
842ffe3c632Sopenharmony_ci
843ffe3c632Sopenharmony_ci    reader.nextField();
844ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedSfixed32(), signedData);
845ffe3c632Sopenharmony_ci
846ffe3c632Sopenharmony_ci    reader.nextField();
847ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedSfixed64(), signedData);
848ffe3c632Sopenharmony_ci
849ffe3c632Sopenharmony_ci    reader.nextField();
850ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedFloat(), floatData);
851ffe3c632Sopenharmony_ci
852ffe3c632Sopenharmony_ci    reader.nextField();
853ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedDouble(), doubleData);
854ffe3c632Sopenharmony_ci
855ffe3c632Sopenharmony_ci    reader.nextField();
856ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedBool(), boolData);
857ffe3c632Sopenharmony_ci
858ffe3c632Sopenharmony_ci    reader.nextField();
859ffe3c632Sopenharmony_ci    assertElementsEquals(reader.readPackedEnum(), unsignedData);
860ffe3c632Sopenharmony_ci
861ffe3c632Sopenharmony_ci    reader.nextField();
862ffe3c632Sopenharmony_ci    assertEquals(sentinel, reader.readInt32());
863ffe3c632Sopenharmony_ci  });
864ffe3c632Sopenharmony_ci
865ffe3c632Sopenharmony_ci
866ffe3c632Sopenharmony_ci  /**
867ffe3c632Sopenharmony_ci   * Byte blobs inside nested messages should always have their byte offset set
868ffe3c632Sopenharmony_ci   * relative to the start of the outermost blob, not the start of their parent
869ffe3c632Sopenharmony_ci   * blob.
870ffe3c632Sopenharmony_ci   */
871ffe3c632Sopenharmony_ci  it('testNestedBlobs', function() {
872ffe3c632Sopenharmony_ci    // Create a proto consisting of two nested messages, with the inner one
873ffe3c632Sopenharmony_ci    // containing a blob of bytes.
874ffe3c632Sopenharmony_ci
875ffe3c632Sopenharmony_ci    var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
876ffe3c632Sopenharmony_ci    var blob = [1, 2, 3, 4, 5];
877ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
878ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
879ffe3c632Sopenharmony_ci
880ffe3c632Sopenharmony_ci    writer.writeMessage(1, dummyMessage, function() {
881ffe3c632Sopenharmony_ci      writer.writeMessage(1, dummyMessage, function() {
882ffe3c632Sopenharmony_ci        writer.writeBytes(1, blob);
883ffe3c632Sopenharmony_ci      });
884ffe3c632Sopenharmony_ci    });
885ffe3c632Sopenharmony_ci
886ffe3c632Sopenharmony_ci    // Peel off the outer two message layers. Each layer should have two bytes
887ffe3c632Sopenharmony_ci    // of overhead, one for the field tag and one for the length of the inner
888ffe3c632Sopenharmony_ci    // blob.
889ffe3c632Sopenharmony_ci
890ffe3c632Sopenharmony_ci    var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
891ffe3c632Sopenharmony_ci    assertEquals(fieldTag, decoder1.readUnsignedVarint32());
892ffe3c632Sopenharmony_ci    assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());
893ffe3c632Sopenharmony_ci
894ffe3c632Sopenharmony_ci    var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
895ffe3c632Sopenharmony_ci    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
896ffe3c632Sopenharmony_ci    assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());
897ffe3c632Sopenharmony_ci
898ffe3c632Sopenharmony_ci    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
899ffe3c632Sopenharmony_ci    assertEquals(blob.length, decoder2.readUnsignedVarint32());
900ffe3c632Sopenharmony_ci    var bytes = decoder2.readBytes(blob.length);
901ffe3c632Sopenharmony_ci
902ffe3c632Sopenharmony_ci    assertElementsEquals(bytes, blob);
903ffe3c632Sopenharmony_ci  });
904ffe3c632Sopenharmony_ci
905ffe3c632Sopenharmony_ci
906ffe3c632Sopenharmony_ci  /**
907ffe3c632Sopenharmony_ci   * Tests read callbacks.
908ffe3c632Sopenharmony_ci   */
909ffe3c632Sopenharmony_ci  it('testReadCallbacks', function() {
910ffe3c632Sopenharmony_ci    var writer = new jspb.BinaryWriter();
911ffe3c632Sopenharmony_ci    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
912ffe3c632Sopenharmony_ci
913ffe3c632Sopenharmony_ci    // Add an int, a submessage, and another int.
914ffe3c632Sopenharmony_ci    writer.writeInt32(1, 100);
915ffe3c632Sopenharmony_ci
916ffe3c632Sopenharmony_ci    writer.writeMessage(2, dummyMessage, function() {
917ffe3c632Sopenharmony_ci      writer.writeInt32(3, 300);
918ffe3c632Sopenharmony_ci      writer.writeInt32(4, 400);
919ffe3c632Sopenharmony_ci      writer.writeInt32(5, 500);
920ffe3c632Sopenharmony_ci    });
921ffe3c632Sopenharmony_ci
922ffe3c632Sopenharmony_ci    writer.writeInt32(7, 700);
923ffe3c632Sopenharmony_ci
924ffe3c632Sopenharmony_ci    // Create the reader and register a custom read callback.
925ffe3c632Sopenharmony_ci    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
926ffe3c632Sopenharmony_ci
927ffe3c632Sopenharmony_ci    /**
928ffe3c632Sopenharmony_ci     * @param {!jspb.BinaryReader} reader
929ffe3c632Sopenharmony_ci     * @return {*}
930ffe3c632Sopenharmony_ci     */
931ffe3c632Sopenharmony_ci    function readCallback(reader) {
932ffe3c632Sopenharmony_ci      reader.nextField();
933ffe3c632Sopenharmony_ci      assertEquals(3, reader.getFieldNumber());
934ffe3c632Sopenharmony_ci      assertEquals(300, reader.readInt32());
935ffe3c632Sopenharmony_ci
936ffe3c632Sopenharmony_ci      reader.nextField();
937ffe3c632Sopenharmony_ci      assertEquals(4, reader.getFieldNumber());
938ffe3c632Sopenharmony_ci      assertEquals(400, reader.readInt32());
939ffe3c632Sopenharmony_ci
940ffe3c632Sopenharmony_ci      reader.nextField();
941ffe3c632Sopenharmony_ci      assertEquals(5, reader.getFieldNumber());
942ffe3c632Sopenharmony_ci      assertEquals(500, reader.readInt32());
943ffe3c632Sopenharmony_ci
944ffe3c632Sopenharmony_ci      assertEquals(false, reader.nextField());
945ffe3c632Sopenharmony_ci    };
946ffe3c632Sopenharmony_ci
947ffe3c632Sopenharmony_ci    reader.registerReadCallback('readCallback', readCallback);
948ffe3c632Sopenharmony_ci
949ffe3c632Sopenharmony_ci    // Read the container message.
950ffe3c632Sopenharmony_ci    reader.nextField();
951ffe3c632Sopenharmony_ci    assertEquals(1, reader.getFieldNumber());
952ffe3c632Sopenharmony_ci    assertEquals(100, reader.readInt32());
953ffe3c632Sopenharmony_ci
954ffe3c632Sopenharmony_ci    reader.nextField();
955ffe3c632Sopenharmony_ci    assertEquals(2, reader.getFieldNumber());
956ffe3c632Sopenharmony_ci    reader.readMessage(dummyMessage, function() {
957ffe3c632Sopenharmony_ci      // Decode the embedded message using the registered callback.
958ffe3c632Sopenharmony_ci      reader.runReadCallback('readCallback');
959ffe3c632Sopenharmony_ci    });
960ffe3c632Sopenharmony_ci
961ffe3c632Sopenharmony_ci    reader.nextField();
962ffe3c632Sopenharmony_ci    assertEquals(7, reader.getFieldNumber());
963ffe3c632Sopenharmony_ci    assertEquals(700, reader.readInt32());
964ffe3c632Sopenharmony_ci
965ffe3c632Sopenharmony_ci    assertEquals(false, reader.nextField());
966ffe3c632Sopenharmony_ci  });
967ffe3c632Sopenharmony_ci});
968