blob: 6c5f36e9218ed0d3f58399120ba15bf86fcc4737 [file] [log] [blame]
Feng Xiaoe841bac2015-12-11 17:09:20 -08001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31/**
32 * @fileoverview Test cases for jspb's binary protocol buffer writer. In
33 * practice BinaryWriter is used to drive the Decoder and Reader test cases,
34 * so only writer-specific tests are here.
35 *
36 * Test suite is written using Jasmine -- see http://jasmine.github.io/
37 *
38 * @author aappleby@google.com (Austin Appleby)
39 */
40
41goog.require('goog.crypt');
42goog.require('goog.testing.asserts');
Paul Yang763c3582019-09-12 11:03:27 -070043goog.require('jspb.BinaryConstants');
Paul Yang7bff8392019-07-19 14:49:01 -070044goog.require('jspb.BinaryReader');
Feng Xiaoe841bac2015-12-11 17:09:20 -080045goog.require('jspb.BinaryWriter');
Rafi Kamal4f02f052019-08-22 16:14:22 -070046goog.require('jspb.utils');
Joshua Haberman51daaba2021-02-04 14:09:49 -080047goog.require('goog.crypt.base64');
48goog.requireType('jspb.BinaryMessage');
Feng Xiaoe841bac2015-12-11 17:09:20 -080049
50/**
51 * @param {function()} func This function should throw an error when run.
52 */
53function assertFails(func) {
Feng Xiaod36c0c52017-03-29 14:32:48 -070054 assertThrows(func);
Feng Xiaoe841bac2015-12-11 17:09:20 -080055}
56
57
58describe('binaryWriterTest', function() {
59 /**
60 * Verifies that misuse of the writer class triggers assertions.
61 */
62 it('testWriteErrors', function() {
63 // Submessages with invalid field indices should assert.
64 var writer = new jspb.BinaryWriter();
Joshua Haberman51daaba2021-02-04 14:09:49 -080065 var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({});
Feng Xiaoe841bac2015-12-11 17:09:20 -080066
67 assertFails(function() {
68 writer.writeMessage(-1, dummyMessage, goog.nullFunction);
69 });
70
71 // Writing invalid field indices should assert.
72 writer = new jspb.BinaryWriter();
Joshua Haberman51daaba2021-02-04 14:09:49 -080073 assertFails(function() {
74 writer.writeUint64(-1, 1);
75 });
Feng Xiaoe841bac2015-12-11 17:09:20 -080076
77 // Writing out-of-range field values should assert.
78 writer = new jspb.BinaryWriter();
79
Joshua Haberman51daaba2021-02-04 14:09:49 -080080 assertFails(function() {
81 writer.writeInt32(1, -Infinity);
82 });
83 assertFails(function() {
84 writer.writeInt32(1, Infinity);
85 });
Feng Xiaoe841bac2015-12-11 17:09:20 -080086
Joshua Haberman51daaba2021-02-04 14:09:49 -080087 assertFails(function() {
88 writer.writeInt64(1, -Infinity);
89 });
90 assertFails(function() {
91 writer.writeInt64(1, Infinity);
92 });
Feng Xiaoe841bac2015-12-11 17:09:20 -080093
Joshua Haberman51daaba2021-02-04 14:09:49 -080094 assertFails(function() {
95 writer.writeUint32(1, -1);
96 });
97 assertFails(function() {
98 writer.writeUint32(1, Infinity);
99 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800100
Joshua Haberman51daaba2021-02-04 14:09:49 -0800101 assertFails(function() {
102 writer.writeUint64(1, -1);
103 });
104 assertFails(function() {
105 writer.writeUint64(1, Infinity);
106 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800107
Joshua Haberman51daaba2021-02-04 14:09:49 -0800108 assertFails(function() {
109 writer.writeSint32(1, -Infinity);
110 });
111 assertFails(function() {
112 writer.writeSint32(1, Infinity);
113 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800114
Joshua Haberman51daaba2021-02-04 14:09:49 -0800115 assertFails(function() {
116 writer.writeSint64(1, -Infinity);
117 });
118 assertFails(function() {
119 writer.writeSint64(1, Infinity);
120 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800121
Joshua Haberman51daaba2021-02-04 14:09:49 -0800122 assertFails(function() {
123 writer.writeFixed32(1, -1);
124 });
125 assertFails(function() {
126 writer.writeFixed32(1, Infinity);
127 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800128
Joshua Haberman51daaba2021-02-04 14:09:49 -0800129 assertFails(function() {
130 writer.writeFixed64(1, -1);
131 });
132 assertFails(function() {
133 writer.writeFixed64(1, Infinity);
134 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800135
Joshua Haberman51daaba2021-02-04 14:09:49 -0800136 assertFails(function() {
137 writer.writeSfixed32(1, -Infinity);
138 });
139 assertFails(function() {
140 writer.writeSfixed32(1, Infinity);
141 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800142
Joshua Haberman51daaba2021-02-04 14:09:49 -0800143 assertFails(function() {
144 writer.writeSfixed64(1, -Infinity);
145 });
146 assertFails(function() {
147 writer.writeSfixed64(1, Infinity);
148 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800149 });
150
151
152 /**
153 * Basic test of retrieving the result as a Uint8Array buffer
154 */
155 it('testGetResultBuffer', function() {
156 var expected = '0864120b48656c6c6f20776f726c641a0301020320c801';
157
158 var writer = new jspb.BinaryWriter();
159 writer.writeUint32(1, 100);
160 writer.writeString(2, 'Hello world');
161 writer.writeBytes(3, new Uint8Array([1, 2, 3]));
162 writer.writeUint32(4, 200);
163
164 var buffer = writer.getResultBuffer();
165 assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
166 });
Adam Cozzette0400cca2018-03-13 16:37:29 -0700167
168
169 /**
170 * Tests websafe encodings for base64 strings.
171 */
172 it('testWebSafeOption', function() {
173 var writer = new jspb.BinaryWriter();
174 writer.writeBytes(1, new Uint8Array([127]));
175 assertEquals('CgF/', writer.getResultBase64String());
Rafi Kamal4f02f052019-08-22 16:14:22 -0700176 assertEquals(
177 'CgF/',
178 writer.getResultBase64String(goog.crypt.base64.Alphabet.DEFAULT));
179 assertEquals(
180 'CgF_',
181 writer.getResultBase64String(
182 goog.crypt.base64.Alphabet.WEBSAFE_NO_PADDING));
Adam Cozzette0400cca2018-03-13 16:37:29 -0700183 });
Paul Yang7bff8392019-07-19 14:49:01 -0700184
185 it('writes split 64 fields', function() {
186 var writer = new jspb.BinaryWriter();
187 writer.writeSplitVarint64(1, 0x1, 0x2);
188 writer.writeSplitVarint64(1, 0xFFFFFFFF, 0xFFFFFFFF);
189 writer.writeSplitFixed64(2, 0x1, 0x2);
190 writer.writeSplitFixed64(2, 0xFFFFFFF0, 0xFFFFFFFF);
191 function lo(i) {
192 return i + 1;
193 }
194 function hi(i) {
195 return i + 2;
196 }
197 writer.writeRepeatedSplitVarint64(3, [0, 1, 2], lo, hi);
198 writer.writeRepeatedSplitFixed64(4, [0, 1, 2], lo, hi);
199 writer.writePackedSplitVarint64(5, [0, 1, 2], lo, hi);
200 writer.writePackedSplitFixed64(6, [0, 1, 2], lo, hi);
201
202 function bitsAsArray(lowBits, highBits) {
203 return [lowBits >>> 0, highBits >>> 0];
204 }
205 var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
206 reader.nextField();
207 expect(reader.getFieldNumber()).toEqual(1);
208 expect(reader.readSplitVarint64(bitsAsArray)).toEqual([0x1, 0x2]);
209
210 reader.nextField();
211 expect(reader.getFieldNumber()).toEqual(1);
212 expect(reader.readSplitVarint64(bitsAsArray)).toEqual([
213 0xFFFFFFFF, 0xFFFFFFFF
214 ]);
215
216 reader.nextField();
217 expect(reader.getFieldNumber()).toEqual(2);
218 expect(reader.readSplitFixed64(bitsAsArray)).toEqual([0x1, 0x2]);
219
220 reader.nextField();
221 expect(reader.getFieldNumber()).toEqual(2);
222 expect(reader.readSplitFixed64(bitsAsArray)).toEqual([
223 0xFFFFFFF0, 0xFFFFFFFF
224 ]);
225
226 for (let i = 0; i < 3; i++) {
227 reader.nextField();
228 expect(reader.getFieldNumber()).toEqual(3);
229 expect(reader.readSplitVarint64(bitsAsArray)).toEqual([i + 1, i + 2]);
230 }
231
232 for (let i = 0; i < 3; i++) {
233 reader.nextField();
234 expect(reader.getFieldNumber()).toEqual(4);
235 expect(reader.readSplitFixed64(bitsAsArray)).toEqual([i + 1, i + 2]);
236 }
237
238 reader.nextField();
239 expect(reader.getFieldNumber()).toEqual(5);
240 expect(reader.readPackedInt64String()).toEqual([
241 String(2 * 2 ** 32 + 1),
242 String(3 * 2 ** 32 + 2),
243 String(4 * 2 ** 32 + 3),
244 ]);
245
246 reader.nextField();
247 expect(reader.getFieldNumber()).toEqual(6);
248 expect(reader.readPackedFixed64String()).toEqual([
249 String(2 * 2 ** 32 + 1),
250 String(3 * 2 ** 32 + 2),
251 String(4 * 2 ** 32 + 3),
252 ]);
253 });
Rafi Kamal4f02f052019-08-22 16:14:22 -0700254
255 it('writes zigzag 64 fields', function() {
Brian Wignalla104dff2020-01-08 13:18:20 -0500256 // Test cases directly from the protobuf dev guide.
Rafi Kamal4f02f052019-08-22 16:14:22 -0700257 // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types
258 var testCases = [
259 {original: '0', zigzag: '0'},
260 {original: '-1', zigzag: '1'},
261 {original: '1', zigzag: '2'},
262 {original: '-2', zigzag: '3'},
263 {original: '2147483647', zigzag: '4294967294'},
264 {original: '-2147483648', zigzag: '4294967295'},
265 // 64-bit extremes, not in dev guide.
266 {original: '9223372036854775807', zigzag: '18446744073709551614'},
267 {original: '-9223372036854775808', zigzag: '18446744073709551615'},
268 ];
269 function decimalToLowBits(v) {
270 jspb.utils.splitDecimalString(v);
271 return jspb.utils.split64Low >>> 0;
272 }
273 function decimalToHighBits(v) {
274 jspb.utils.splitDecimalString(v);
275 return jspb.utils.split64High >>> 0;
276 }
277
278 var writer = new jspb.BinaryWriter();
279 testCases.forEach(function(c) {
280 writer.writeSint64String(1, c.original);
281 writer.writeSintHash64(1, jspb.utils.decimalStringToHash64(c.original));
282 jspb.utils.splitDecimalString(c.original);
283 writer.writeSplitZigzagVarint64(
284 1, jspb.utils.split64Low, jspb.utils.split64High);
285 });
286
287 writer.writeRepeatedSint64String(2, testCases.map(function(c) {
288 return c.original;
289 }));
290
291 writer.writeRepeatedSintHash64(3, testCases.map(function(c) {
292 return jspb.utils.decimalStringToHash64(c.original);
293 }));
294
295 writer.writeRepeatedSplitZigzagVarint64(
296 4, testCases.map(function(c) {
297 return c.original;
298 }),
299 decimalToLowBits, decimalToHighBits);
300
301 writer.writePackedSint64String(5, testCases.map(function(c) {
302 return c.original;
303 }));
304
305 writer.writePackedSintHash64(6, testCases.map(function(c) {
306 return jspb.utils.decimalStringToHash64(c.original);
307 }));
308
309 writer.writePackedSplitZigzagVarint64(
310 7, testCases.map(function(c) {
311 return c.original;
312 }),
313 decimalToLowBits, decimalToHighBits);
314
315 // Verify by reading the stream as normal int64 fields and checking with
316 // the canonical zigzag encoding of each value.
317 var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
318 testCases.forEach(function(c) {
319 reader.nextField();
320 expect(reader.getFieldNumber()).toEqual(1);
321 expect(reader.readUint64String()).toEqual(c.zigzag);
322 reader.nextField();
323 expect(reader.getFieldNumber()).toEqual(1);
324 expect(reader.readUint64String()).toEqual(c.zigzag);
325 reader.nextField();
326 expect(reader.getFieldNumber()).toEqual(1);
327 expect(reader.readUint64String()).toEqual(c.zigzag);
328 });
329
330 testCases.forEach(function(c) {
331 reader.nextField();
332 expect(reader.getFieldNumber()).toEqual(2);
333 expect(reader.readUint64String()).toEqual(c.zigzag);
334 });
335
336 testCases.forEach(function(c) {
337 reader.nextField();
338 expect(reader.getFieldNumber()).toEqual(3);
339 expect(reader.readUint64String()).toEqual(c.zigzag);
340 });
341
342 testCases.forEach(function(c) {
343 reader.nextField();
344 expect(reader.getFieldNumber()).toEqual(4);
345 expect(reader.readUint64String()).toEqual(c.zigzag);
346 });
347
348 reader.nextField();
349 expect(reader.getFieldNumber()).toEqual(5);
350 expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
351 return c.zigzag;
352 }));
353
354 reader.nextField();
355 expect(reader.getFieldNumber()).toEqual(6);
356 expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
357 return c.zigzag;
358 }));
359
360 reader.nextField();
361 expect(reader.getFieldNumber()).toEqual(7);
362 expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) {
363 return c.zigzag;
364 }));
365 });
Paul Yang763c3582019-09-12 11:03:27 -0700366
367 it('writes float32 fields', function() {
368 var testCases = [
369 0, 1, -1, jspb.BinaryConstants.FLOAT32_MIN,
370 -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX,
371 -jspb.BinaryConstants.FLOAT32_MAX, 3.1415927410125732, Infinity,
372 -Infinity, NaN
373 ];
374 var writer = new jspb.BinaryWriter();
375 testCases.forEach(function(f) {
376 writer.writeFloat(1, f);
377 });
378 var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
379 testCases.forEach(function(f) {
380 reader.nextField();
381 expect(reader.getFieldNumber()).toEqual(1);
382 if (isNaN(f)) {
383 expect(isNaN(reader.readFloat())).toEqual(true);
384 } else {
385 expect(reader.readFloat()).toEqual(f);
386 }
387 });
388 });
389
390 it('writes double fields', function() {
391 var testCases = [
392 0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER,
393 Number.MAX_VALUE, Number.MIN_VALUE, jspb.BinaryConstants.FLOAT32_MIN,
394 -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX,
395 -jspb.BinaryConstants.FLOAT32_MAX, Math.PI, Infinity, -Infinity, NaN
396 ];
397 var writer = new jspb.BinaryWriter();
398 testCases.forEach(function(f) {
399 writer.writeDouble(1, f);
400 });
401 var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
402 testCases.forEach(function(f) {
403 reader.nextField();
404 expect(reader.getFieldNumber()).toEqual(1);
405 if (isNaN(f)) {
406 expect(isNaN(reader.readDouble())).toEqual(true);
407 } else {
408 expect(reader.readDouble()).toEqual(f);
409 }
410 });
411 });
Feng Xiaoe841bac2015-12-11 17:09:20 -0800412});