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 decoder.
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.BinaryEncoder');
48ffe3c632Sopenharmony_cigoog.require('jspb.utils');
49ffe3c632Sopenharmony_ci
50ffe3c632Sopenharmony_ci
51ffe3c632Sopenharmony_ci/**
52ffe3c632Sopenharmony_ci * Tests encoding and decoding of unsigned types.
53ffe3c632Sopenharmony_ci * @param {Function} readValue
54ffe3c632Sopenharmony_ci * @param {Function} writeValue
55ffe3c632Sopenharmony_ci * @param {number} epsilon
56ffe3c632Sopenharmony_ci * @param {number} upperLimit
57ffe3c632Sopenharmony_ci * @param {Function} filter
58ffe3c632Sopenharmony_ci * @suppress {missingProperties|visibility}
59ffe3c632Sopenharmony_ci */
60ffe3c632Sopenharmony_cifunction doTestUnsignedValue(readValue,
61ffe3c632Sopenharmony_ci    writeValue, epsilon, upperLimit, filter) {
62ffe3c632Sopenharmony_ci  var encoder = new jspb.BinaryEncoder();
63ffe3c632Sopenharmony_ci
64ffe3c632Sopenharmony_ci  // Encode zero and limits.
65ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(0));
66ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(epsilon));
67ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(upperLimit));
68ffe3c632Sopenharmony_ci
69ffe3c632Sopenharmony_ci  // Encode positive values.
70ffe3c632Sopenharmony_ci  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
71ffe3c632Sopenharmony_ci    writeValue.call(encoder, filter(cursor));
72ffe3c632Sopenharmony_ci  }
73ffe3c632Sopenharmony_ci
74ffe3c632Sopenharmony_ci  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
75ffe3c632Sopenharmony_ci
76ffe3c632Sopenharmony_ci  // Check zero and limits.
77ffe3c632Sopenharmony_ci  assertEquals(filter(0), readValue.call(decoder));
78ffe3c632Sopenharmony_ci  assertEquals(filter(epsilon), readValue.call(decoder));
79ffe3c632Sopenharmony_ci  assertEquals(filter(upperLimit), readValue.call(decoder));
80ffe3c632Sopenharmony_ci
81ffe3c632Sopenharmony_ci  // Check positive values.
82ffe3c632Sopenharmony_ci  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
83ffe3c632Sopenharmony_ci    if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
84ffe3c632Sopenharmony_ci  }
85ffe3c632Sopenharmony_ci
86ffe3c632Sopenharmony_ci  // Encoding values outside the valid range should assert.
87ffe3c632Sopenharmony_ci  assertThrows(function() {writeValue.call(encoder, -1);});
88ffe3c632Sopenharmony_ci  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
89ffe3c632Sopenharmony_ci}
90ffe3c632Sopenharmony_ci
91ffe3c632Sopenharmony_ci
92ffe3c632Sopenharmony_ci/**
93ffe3c632Sopenharmony_ci * Tests encoding and decoding of signed types.
94ffe3c632Sopenharmony_ci * @param {Function} readValue
95ffe3c632Sopenharmony_ci * @param {Function} writeValue
96ffe3c632Sopenharmony_ci * @param {number} epsilon
97ffe3c632Sopenharmony_ci * @param {number} lowerLimit
98ffe3c632Sopenharmony_ci * @param {number} upperLimit
99ffe3c632Sopenharmony_ci * @param {Function} filter
100ffe3c632Sopenharmony_ci * @suppress {missingProperties}
101ffe3c632Sopenharmony_ci */
102ffe3c632Sopenharmony_cifunction doTestSignedValue(readValue,
103ffe3c632Sopenharmony_ci    writeValue, epsilon, lowerLimit, upperLimit, filter) {
104ffe3c632Sopenharmony_ci  var encoder = new jspb.BinaryEncoder();
105ffe3c632Sopenharmony_ci
106ffe3c632Sopenharmony_ci  // Encode zero and limits.
107ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(lowerLimit));
108ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(-epsilon));
109ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(0));
110ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(epsilon));
111ffe3c632Sopenharmony_ci  writeValue.call(encoder, filter(upperLimit));
112ffe3c632Sopenharmony_ci
113ffe3c632Sopenharmony_ci  var inputValues = [];
114ffe3c632Sopenharmony_ci
115ffe3c632Sopenharmony_ci  // Encode negative values.
116ffe3c632Sopenharmony_ci  for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
117ffe3c632Sopenharmony_ci    var val = filter(cursor);
118ffe3c632Sopenharmony_ci    writeValue.call(encoder, val);
119ffe3c632Sopenharmony_ci    inputValues.push(val);
120ffe3c632Sopenharmony_ci  }
121ffe3c632Sopenharmony_ci
122ffe3c632Sopenharmony_ci  // Encode positive values.
123ffe3c632Sopenharmony_ci  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
124ffe3c632Sopenharmony_ci    var val = filter(cursor);
125ffe3c632Sopenharmony_ci    writeValue.call(encoder, val);
126ffe3c632Sopenharmony_ci    inputValues.push(val);
127ffe3c632Sopenharmony_ci  }
128ffe3c632Sopenharmony_ci
129ffe3c632Sopenharmony_ci  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
130ffe3c632Sopenharmony_ci
131ffe3c632Sopenharmony_ci  // Check zero and limits.
132ffe3c632Sopenharmony_ci  assertEquals(filter(lowerLimit), readValue.call(decoder));
133ffe3c632Sopenharmony_ci  assertEquals(filter(-epsilon), readValue.call(decoder));
134ffe3c632Sopenharmony_ci  assertEquals(filter(0), readValue.call(decoder));
135ffe3c632Sopenharmony_ci  assertEquals(filter(epsilon), readValue.call(decoder));
136ffe3c632Sopenharmony_ci  assertEquals(filter(upperLimit), readValue.call(decoder));
137ffe3c632Sopenharmony_ci
138ffe3c632Sopenharmony_ci  // Verify decoded values.
139ffe3c632Sopenharmony_ci  for (var i = 0; i < inputValues.length; i++) {
140ffe3c632Sopenharmony_ci    assertEquals(inputValues[i], readValue.call(decoder));
141ffe3c632Sopenharmony_ci  }
142ffe3c632Sopenharmony_ci
143ffe3c632Sopenharmony_ci  // Encoding values outside the valid range should assert.
144ffe3c632Sopenharmony_ci  var pastLowerLimit = lowerLimit * 1.1;
145ffe3c632Sopenharmony_ci  var pastUpperLimit = upperLimit * 1.1;
146ffe3c632Sopenharmony_ci  if (pastLowerLimit !== -Infinity) {
147ffe3c632Sopenharmony_ci    expect(() => void writeValue.call(encoder, pastLowerLimit)).toThrow();
148ffe3c632Sopenharmony_ci  }
149ffe3c632Sopenharmony_ci  if (pastUpperLimit !== Infinity) {
150ffe3c632Sopenharmony_ci    expect(() => void writeValue.call(encoder, pastUpperLimit)).toThrow();
151ffe3c632Sopenharmony_ci  }
152ffe3c632Sopenharmony_ci}
153ffe3c632Sopenharmony_ci
154ffe3c632Sopenharmony_cidescribe('binaryDecoderTest', function() {
155ffe3c632Sopenharmony_ci  /**
156ffe3c632Sopenharmony_ci   * Tests the decoder instance cache.
157ffe3c632Sopenharmony_ci   */
158ffe3c632Sopenharmony_ci  it('testInstanceCache', /** @suppress {visibility} */ function() {
159ffe3c632Sopenharmony_ci    // Empty the instance caches.
160ffe3c632Sopenharmony_ci    jspb.BinaryDecoder.instanceCache_ = [];
161ffe3c632Sopenharmony_ci
162ffe3c632Sopenharmony_ci    // Allocating and then freeing a decoder should put it in the instance
163ffe3c632Sopenharmony_ci    // cache.
164ffe3c632Sopenharmony_ci    jspb.BinaryDecoder.alloc().free();
165ffe3c632Sopenharmony_ci
166ffe3c632Sopenharmony_ci    assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);
167ffe3c632Sopenharmony_ci
168ffe3c632Sopenharmony_ci    // Allocating and then freeing three decoders should leave us with three in
169ffe3c632Sopenharmony_ci    // the cache.
170ffe3c632Sopenharmony_ci
171ffe3c632Sopenharmony_ci    var decoder1 = jspb.BinaryDecoder.alloc();
172ffe3c632Sopenharmony_ci    var decoder2 = jspb.BinaryDecoder.alloc();
173ffe3c632Sopenharmony_ci    var decoder3 = jspb.BinaryDecoder.alloc();
174ffe3c632Sopenharmony_ci    decoder1.free();
175ffe3c632Sopenharmony_ci    decoder2.free();
176ffe3c632Sopenharmony_ci    decoder3.free();
177ffe3c632Sopenharmony_ci
178ffe3c632Sopenharmony_ci    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
179ffe3c632Sopenharmony_ci  });
180ffe3c632Sopenharmony_ci
181ffe3c632Sopenharmony_ci
182ffe3c632Sopenharmony_ci  describe('varint64', function() {
183ffe3c632Sopenharmony_ci    var /** !jspb.BinaryEncoder */ encoder;
184ffe3c632Sopenharmony_ci    var /** !jspb.BinaryDecoder */ decoder;
185ffe3c632Sopenharmony_ci
186ffe3c632Sopenharmony_ci    var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
187ffe3c632Sopenharmony_ci                                    0x00, 0x00, 0x00, 0x00);
188ffe3c632Sopenharmony_ci    var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
189ffe3c632Sopenharmony_ci                                    0x00, 0x00, 0x00, 0x00);
190ffe3c632Sopenharmony_ci    var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
191ffe3c632Sopenharmony_ci                                    0x87, 0x65, 0x43, 0x21);
192ffe3c632Sopenharmony_ci    var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
193ffe3c632Sopenharmony_ci                                    0xFF, 0xFF, 0xFF, 0xFF);
194ffe3c632Sopenharmony_ci    beforeEach(function() {
195ffe3c632Sopenharmony_ci      encoder = new jspb.BinaryEncoder();
196ffe3c632Sopenharmony_ci
197ffe3c632Sopenharmony_ci      encoder.writeVarintHash64(hashA);
198ffe3c632Sopenharmony_ci      encoder.writeVarintHash64(hashB);
199ffe3c632Sopenharmony_ci      encoder.writeVarintHash64(hashC);
200ffe3c632Sopenharmony_ci      encoder.writeVarintHash64(hashD);
201ffe3c632Sopenharmony_ci
202ffe3c632Sopenharmony_ci      encoder.writeFixedHash64(hashA);
203ffe3c632Sopenharmony_ci      encoder.writeFixedHash64(hashB);
204ffe3c632Sopenharmony_ci      encoder.writeFixedHash64(hashC);
205ffe3c632Sopenharmony_ci      encoder.writeFixedHash64(hashD);
206ffe3c632Sopenharmony_ci
207ffe3c632Sopenharmony_ci      decoder = jspb.BinaryDecoder.alloc(encoder.end());
208ffe3c632Sopenharmony_ci    });
209ffe3c632Sopenharmony_ci
210ffe3c632Sopenharmony_ci    it('reads 64-bit integers as hash strings', function() {
211ffe3c632Sopenharmony_ci      assertEquals(hashA, decoder.readVarintHash64());
212ffe3c632Sopenharmony_ci      assertEquals(hashB, decoder.readVarintHash64());
213ffe3c632Sopenharmony_ci      assertEquals(hashC, decoder.readVarintHash64());
214ffe3c632Sopenharmony_ci      assertEquals(hashD, decoder.readVarintHash64());
215ffe3c632Sopenharmony_ci
216ffe3c632Sopenharmony_ci      assertEquals(hashA, decoder.readFixedHash64());
217ffe3c632Sopenharmony_ci      assertEquals(hashB, decoder.readFixedHash64());
218ffe3c632Sopenharmony_ci      assertEquals(hashC, decoder.readFixedHash64());
219ffe3c632Sopenharmony_ci      assertEquals(hashD, decoder.readFixedHash64());
220ffe3c632Sopenharmony_ci    });
221ffe3c632Sopenharmony_ci
222ffe3c632Sopenharmony_ci    it('reads split 64 bit integers', function() {
223ffe3c632Sopenharmony_ci      function hexJoin(bitsLow, bitsHigh) {
224ffe3c632Sopenharmony_ci        return `0x${(bitsHigh >>> 0).toString(16)}:0x${
225ffe3c632Sopenharmony_ci            (bitsLow >>> 0).toString(16)}`;
226ffe3c632Sopenharmony_ci      }
227ffe3c632Sopenharmony_ci      function hexJoinHash(hash64) {
228ffe3c632Sopenharmony_ci        jspb.utils.splitHash64(hash64);
229ffe3c632Sopenharmony_ci        return hexJoin(jspb.utils.split64Low, jspb.utils.split64High);
230ffe3c632Sopenharmony_ci      }
231ffe3c632Sopenharmony_ci
232ffe3c632Sopenharmony_ci      expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashA));
233ffe3c632Sopenharmony_ci      expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashB));
234ffe3c632Sopenharmony_ci      expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashC));
235ffe3c632Sopenharmony_ci      expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashD));
236ffe3c632Sopenharmony_ci
237ffe3c632Sopenharmony_ci      expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashA));
238ffe3c632Sopenharmony_ci      expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashB));
239ffe3c632Sopenharmony_ci      expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashC));
240ffe3c632Sopenharmony_ci      expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashD));
241ffe3c632Sopenharmony_ci    });
242ffe3c632Sopenharmony_ci  });
243ffe3c632Sopenharmony_ci
244ffe3c632Sopenharmony_ci  describe('sint64', function() {
245ffe3c632Sopenharmony_ci    var /** !jspb.BinaryDecoder */ decoder;
246ffe3c632Sopenharmony_ci
247ffe3c632Sopenharmony_ci    var hashA =
248ffe3c632Sopenharmony_ci        String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
249ffe3c632Sopenharmony_ci    var hashB =
250ffe3c632Sopenharmony_ci        String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
251ffe3c632Sopenharmony_ci    var hashC =
252ffe3c632Sopenharmony_ci        String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21);
253ffe3c632Sopenharmony_ci    var hashD =
254ffe3c632Sopenharmony_ci        String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
255ffe3c632Sopenharmony_ci    beforeEach(function() {
256ffe3c632Sopenharmony_ci      var encoder = new jspb.BinaryEncoder();
257ffe3c632Sopenharmony_ci
258ffe3c632Sopenharmony_ci      encoder.writeZigzagVarintHash64(hashA);
259ffe3c632Sopenharmony_ci      encoder.writeZigzagVarintHash64(hashB);
260ffe3c632Sopenharmony_ci      encoder.writeZigzagVarintHash64(hashC);
261ffe3c632Sopenharmony_ci      encoder.writeZigzagVarintHash64(hashD);
262ffe3c632Sopenharmony_ci
263ffe3c632Sopenharmony_ci      decoder = jspb.BinaryDecoder.alloc(encoder.end());
264ffe3c632Sopenharmony_ci    });
265ffe3c632Sopenharmony_ci
266ffe3c632Sopenharmony_ci    it('reads 64-bit integers as decimal strings', function() {
267ffe3c632Sopenharmony_ci      const signed = true;
268ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarint64String())
269ffe3c632Sopenharmony_ci          .toEqual(jspb.utils.hash64ToDecimalString(hashA, signed));
270ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarint64String())
271ffe3c632Sopenharmony_ci          .toEqual(jspb.utils.hash64ToDecimalString(hashB, signed));
272ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarint64String())
273ffe3c632Sopenharmony_ci          .toEqual(jspb.utils.hash64ToDecimalString(hashC, signed));
274ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarint64String())
275ffe3c632Sopenharmony_ci          .toEqual(jspb.utils.hash64ToDecimalString(hashD, signed));
276ffe3c632Sopenharmony_ci    });
277ffe3c632Sopenharmony_ci
278ffe3c632Sopenharmony_ci    it('reads 64-bit integers as hash strings', function() {
279ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarintHash64()).toEqual(hashA);
280ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarintHash64()).toEqual(hashB);
281ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarintHash64()).toEqual(hashC);
282ffe3c632Sopenharmony_ci      expect(decoder.readZigzagVarintHash64()).toEqual(hashD);
283ffe3c632Sopenharmony_ci    });
284ffe3c632Sopenharmony_ci
285ffe3c632Sopenharmony_ci    it('reads split 64 bit zigzag integers', function() {
286ffe3c632Sopenharmony_ci      function hexJoin(bitsLow, bitsHigh) {
287ffe3c632Sopenharmony_ci        return `0x${(bitsHigh >>> 0).toString(16)}:0x${
288ffe3c632Sopenharmony_ci            (bitsLow >>> 0).toString(16)}`;
289ffe3c632Sopenharmony_ci      }
290ffe3c632Sopenharmony_ci      function hexJoinHash(hash64) {
291ffe3c632Sopenharmony_ci        jspb.utils.splitHash64(hash64);
292ffe3c632Sopenharmony_ci        return hexJoin(jspb.utils.split64Low, jspb.utils.split64High);
293ffe3c632Sopenharmony_ci      }
294ffe3c632Sopenharmony_ci
295ffe3c632Sopenharmony_ci      expect(decoder.readSplitZigzagVarint64(hexJoin))
296ffe3c632Sopenharmony_ci          .toEqual(hexJoinHash(hashA));
297ffe3c632Sopenharmony_ci      expect(decoder.readSplitZigzagVarint64(hexJoin))
298ffe3c632Sopenharmony_ci          .toEqual(hexJoinHash(hashB));
299ffe3c632Sopenharmony_ci      expect(decoder.readSplitZigzagVarint64(hexJoin))
300ffe3c632Sopenharmony_ci          .toEqual(hexJoinHash(hashC));
301ffe3c632Sopenharmony_ci      expect(decoder.readSplitZigzagVarint64(hexJoin))
302ffe3c632Sopenharmony_ci          .toEqual(hexJoinHash(hashD));
303ffe3c632Sopenharmony_ci    });
304ffe3c632Sopenharmony_ci
305ffe3c632Sopenharmony_ci    it('does zigzag encoding properly', function() {
306ffe3c632Sopenharmony_ci      // Test cases directly from the protobuf dev guide.
307ffe3c632Sopenharmony_ci      // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
308ffe3c632Sopenharmony_ci      var testCases = [
309ffe3c632Sopenharmony_ci        {original: '0', zigzag: '0'},
310ffe3c632Sopenharmony_ci        {original: '-1', zigzag: '1'},
311ffe3c632Sopenharmony_ci        {original: '1', zigzag: '2'},
312ffe3c632Sopenharmony_ci        {original: '-2', zigzag: '3'},
313ffe3c632Sopenharmony_ci        {original: '2147483647', zigzag: '4294967294'},
314ffe3c632Sopenharmony_ci        {original: '-2147483648', zigzag: '4294967295'},
315ffe3c632Sopenharmony_ci        // 64-bit extremes, not in dev guide.
316ffe3c632Sopenharmony_ci        {original: '9223372036854775807', zigzag: '18446744073709551614'},
317ffe3c632Sopenharmony_ci        {original: '-9223372036854775808', zigzag: '18446744073709551615'},
318ffe3c632Sopenharmony_ci      ];
319ffe3c632Sopenharmony_ci      var encoder = new jspb.BinaryEncoder();
320ffe3c632Sopenharmony_ci      testCases.forEach(function(c) {
321ffe3c632Sopenharmony_ci        encoder.writeZigzagVarint64String(c.original);
322ffe3c632Sopenharmony_ci      });
323ffe3c632Sopenharmony_ci      var buffer = encoder.end();
324ffe3c632Sopenharmony_ci      var zigzagDecoder = jspb.BinaryDecoder.alloc(buffer);
325ffe3c632Sopenharmony_ci      var varintDecoder = jspb.BinaryDecoder.alloc(buffer);
326ffe3c632Sopenharmony_ci      testCases.forEach(function(c) {
327ffe3c632Sopenharmony_ci        expect(zigzagDecoder.readZigzagVarint64String()).toEqual(c.original);
328ffe3c632Sopenharmony_ci        expect(varintDecoder.readUnsignedVarint64String()).toEqual(c.zigzag);
329ffe3c632Sopenharmony_ci      });
330ffe3c632Sopenharmony_ci    });
331ffe3c632Sopenharmony_ci  });
332ffe3c632Sopenharmony_ci
333ffe3c632Sopenharmony_ci  /**
334ffe3c632Sopenharmony_ci   * Tests reading and writing large strings
335ffe3c632Sopenharmony_ci   */
336ffe3c632Sopenharmony_ci  it('testLargeStrings', function() {
337ffe3c632Sopenharmony_ci    var encoder = new jspb.BinaryEncoder();
338ffe3c632Sopenharmony_ci
339ffe3c632Sopenharmony_ci    var len = 150000;
340ffe3c632Sopenharmony_ci    var long_string = '';
341ffe3c632Sopenharmony_ci    for (var i = 0; i < len; i++) {
342ffe3c632Sopenharmony_ci      long_string += 'a';
343ffe3c632Sopenharmony_ci    }
344ffe3c632Sopenharmony_ci
345ffe3c632Sopenharmony_ci    encoder.writeString(long_string);
346ffe3c632Sopenharmony_ci
347ffe3c632Sopenharmony_ci    var decoder = jspb.BinaryDecoder.alloc(encoder.end());
348ffe3c632Sopenharmony_ci
349ffe3c632Sopenharmony_ci    assertEquals(long_string, decoder.readString(len));
350ffe3c632Sopenharmony_ci  });
351ffe3c632Sopenharmony_ci
352ffe3c632Sopenharmony_ci  /**
353ffe3c632Sopenharmony_ci   * Test encoding and decoding utf-8.
354ffe3c632Sopenharmony_ci   */
355ffe3c632Sopenharmony_ci   it('testUtf8', function() {
356ffe3c632Sopenharmony_ci    var encoder = new jspb.BinaryEncoder();
357ffe3c632Sopenharmony_ci
358ffe3c632Sopenharmony_ci    var ascii = "ASCII should work in 3, 2, 1...";
359ffe3c632Sopenharmony_ci    var utf8_two_bytes = "©";
360ffe3c632Sopenharmony_ci    var utf8_three_bytes = "❄";
361ffe3c632Sopenharmony_ci    var utf8_four_bytes = "�";
362ffe3c632Sopenharmony_ci
363ffe3c632Sopenharmony_ci    encoder.writeString(ascii);
364ffe3c632Sopenharmony_ci    encoder.writeString(utf8_two_bytes);
365ffe3c632Sopenharmony_ci    encoder.writeString(utf8_three_bytes);
366ffe3c632Sopenharmony_ci    encoder.writeString(utf8_four_bytes);
367ffe3c632Sopenharmony_ci
368ffe3c632Sopenharmony_ci    var decoder = jspb.BinaryDecoder.alloc(encoder.end());
369ffe3c632Sopenharmony_ci
370ffe3c632Sopenharmony_ci    assertEquals(ascii, decoder.readString(ascii.length));
371ffe3c632Sopenharmony_ci    assertEquals(utf8_two_bytes, decoder.readString(utf8_two_bytes.length));
372ffe3c632Sopenharmony_ci    assertEquals(utf8_three_bytes, decoder.readString(utf8_three_bytes.length));
373ffe3c632Sopenharmony_ci    assertEquals(utf8_four_bytes, decoder.readString(utf8_four_bytes.length));
374ffe3c632Sopenharmony_ci   });
375ffe3c632Sopenharmony_ci
376ffe3c632Sopenharmony_ci  /**
377ffe3c632Sopenharmony_ci   * Verifies that misuse of the decoder class triggers assertions.
378ffe3c632Sopenharmony_ci   */
379ffe3c632Sopenharmony_ci  it('testDecodeErrors', function() {
380ffe3c632Sopenharmony_ci    // Reading a value past the end of the stream should trigger an assertion.
381ffe3c632Sopenharmony_ci    var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
382ffe3c632Sopenharmony_ci    assertThrows(function() {decoder.readUint64()});
383ffe3c632Sopenharmony_ci
384ffe3c632Sopenharmony_ci    // Overlong varints should trigger assertions.
385ffe3c632Sopenharmony_ci    decoder.setBlock([255, 255, 255, 255, 255, 255,
386ffe3c632Sopenharmony_ci                      255, 255, 255, 255, 255, 0]);
387ffe3c632Sopenharmony_ci    assertThrows(function() {decoder.readUnsignedVarint64()});
388ffe3c632Sopenharmony_ci    decoder.reset();
389ffe3c632Sopenharmony_ci    assertThrows(function() {decoder.readSignedVarint64()});
390ffe3c632Sopenharmony_ci    decoder.reset();
391ffe3c632Sopenharmony_ci    assertThrows(function() {decoder.readZigzagVarint64()});
392ffe3c632Sopenharmony_ci    decoder.reset();
393ffe3c632Sopenharmony_ci    assertThrows(function() {decoder.readUnsignedVarint32()});
394ffe3c632Sopenharmony_ci  });
395ffe3c632Sopenharmony_ci
396ffe3c632Sopenharmony_ci
397ffe3c632Sopenharmony_ci  /**
398ffe3c632Sopenharmony_ci   * Tests encoding and decoding of unsigned integers.
399ffe3c632Sopenharmony_ci   */
400ffe3c632Sopenharmony_ci  it('testUnsignedIntegers', function() {
401ffe3c632Sopenharmony_ci    doTestUnsignedValue(
402ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readUint8,
403ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeUint8,
404ffe3c632Sopenharmony_ci        1, 0xFF, Math.round);
405ffe3c632Sopenharmony_ci
406ffe3c632Sopenharmony_ci    doTestUnsignedValue(
407ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readUint16,
408ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeUint16,
409ffe3c632Sopenharmony_ci        1, 0xFFFF, Math.round);
410ffe3c632Sopenharmony_ci
411ffe3c632Sopenharmony_ci    doTestUnsignedValue(
412ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readUint32,
413ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeUint32,
414ffe3c632Sopenharmony_ci        1, 0xFFFFFFFF, Math.round);
415ffe3c632Sopenharmony_ci
416ffe3c632Sopenharmony_ci    doTestUnsignedValue(
417ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readUint64,
418ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeUint64,
419ffe3c632Sopenharmony_ci        1, Math.pow(2, 64) - 1025, Math.round);
420ffe3c632Sopenharmony_ci  });
421ffe3c632Sopenharmony_ci
422ffe3c632Sopenharmony_ci
423ffe3c632Sopenharmony_ci  /**
424ffe3c632Sopenharmony_ci   * Tests encoding and decoding of signed integers.
425ffe3c632Sopenharmony_ci   */
426ffe3c632Sopenharmony_ci  it('testSignedIntegers', function() {
427ffe3c632Sopenharmony_ci    doTestSignedValue(
428ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readInt8,
429ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeInt8,
430ffe3c632Sopenharmony_ci        1, -0x80, 0x7F, Math.round);
431ffe3c632Sopenharmony_ci
432ffe3c632Sopenharmony_ci    doTestSignedValue(
433ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readInt16,
434ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeInt16,
435ffe3c632Sopenharmony_ci        1, -0x8000, 0x7FFF, Math.round);
436ffe3c632Sopenharmony_ci
437ffe3c632Sopenharmony_ci    doTestSignedValue(
438ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readInt32,
439ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeInt32,
440ffe3c632Sopenharmony_ci        1, -0x80000000, 0x7FFFFFFF, Math.round);
441ffe3c632Sopenharmony_ci
442ffe3c632Sopenharmony_ci    doTestSignedValue(
443ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readInt64,
444ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeInt64,
445ffe3c632Sopenharmony_ci        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
446ffe3c632Sopenharmony_ci  });
447ffe3c632Sopenharmony_ci
448ffe3c632Sopenharmony_ci
449ffe3c632Sopenharmony_ci  /**
450ffe3c632Sopenharmony_ci   * Tests encoding and decoding of floats.
451ffe3c632Sopenharmony_ci   */
452ffe3c632Sopenharmony_ci  it('testFloats', function() {
453ffe3c632Sopenharmony_ci    /**
454ffe3c632Sopenharmony_ci     * @param {number} x
455ffe3c632Sopenharmony_ci     * @return {number}
456ffe3c632Sopenharmony_ci     */
457ffe3c632Sopenharmony_ci    function truncate(x) {
458ffe3c632Sopenharmony_ci      var temp = new Float32Array(1);
459ffe3c632Sopenharmony_ci      temp[0] = x;
460ffe3c632Sopenharmony_ci      return temp[0];
461ffe3c632Sopenharmony_ci    }
462ffe3c632Sopenharmony_ci    doTestSignedValue(
463ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readFloat,
464ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeFloat,
465ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT32_EPS,
466ffe3c632Sopenharmony_ci        -jspb.BinaryConstants.FLOAT32_MAX,
467ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT32_MAX,
468ffe3c632Sopenharmony_ci        truncate);
469ffe3c632Sopenharmony_ci
470ffe3c632Sopenharmony_ci    doTestSignedValue(
471ffe3c632Sopenharmony_ci        jspb.BinaryDecoder.prototype.readDouble,
472ffe3c632Sopenharmony_ci        jspb.BinaryEncoder.prototype.writeDouble,
473ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT64_EPS * 10,
474ffe3c632Sopenharmony_ci        -jspb.BinaryConstants.FLOAT64_MAX,
475ffe3c632Sopenharmony_ci        jspb.BinaryConstants.FLOAT64_MAX,
476ffe3c632Sopenharmony_ci        function(x) { return x; });
477ffe3c632Sopenharmony_ci  });
478ffe3c632Sopenharmony_ci});
479