1/** 2 * @fileoverview Tests for writer.js. 3 */ 4goog.module('protobuf.binary.WriterTest'); 5 6goog.setTestOnly(); 7 8// Note to the reader: 9// Since the writer behavior changes with the checking level some of the tests 10// in this file have to know which checking level is enable to make correct 11// assertions. 12const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); 13const ByteString = goog.require('protobuf.ByteString'); 14const WireType = goog.require('protobuf.binary.WireType'); 15const Writer = goog.require('protobuf.binary.Writer'); 16const {CHECK_BOUNDS, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks'); 17const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays'); 18const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs'); 19const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs'); 20const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs'); 21const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs'); 22const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs'); 23const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs'); 24const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs'); 25const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs'); 26const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs'); 27const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs'); 28const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs'); 29const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs'); 30const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs'); 31const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs'); 32const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs'); 33const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs'); 34const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs'); 35const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs'); 36const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs'); 37const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs'); 38const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs'); 39 40 41/** 42 * @param {...number} bytes 43 * @return {!ArrayBuffer} 44 */ 45function createArrayBuffer(...bytes) { 46 return new Uint8Array(bytes).buffer; 47} 48 49/****************************************************************************** 50 * OPTIONAL FUNCTIONS 51 ******************************************************************************/ 52 53describe('Writer does', () => { 54 it('return an empty ArrayBuffer when nothing is encoded', () => { 55 const writer = new Writer(); 56 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 57 }); 58 59 it('encode tag', () => { 60 const writer = new Writer(); 61 writer.writeTag(1, WireType.VARINT); 62 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08)); 63 64 writer.writeTag(0x0FFFFFFF, WireType.VARINT); 65 expect(writer.getAndResetResultBuffer()) 66 .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7)); 67 68 writer.writeTag(0x10000000, WireType.VARINT); 69 expect(writer.getAndResetResultBuffer()) 70 .toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08)); 71 72 writer.writeTag(0x1FFFFFFF, WireType.VARINT); 73 expect(writer.getAndResetResultBuffer()) 74 .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F)); 75 }); 76 77 it('reset after calling getAndResetResultBuffer', () => { 78 const writer = new Writer(); 79 writer.writeTag(1, WireType.VARINT); 80 writer.getAndResetResultBuffer(); 81 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 82 }); 83 84 it('fail when field number is too large for writeTag', () => { 85 const writer = new Writer(); 86 if (CHECK_TYPE) { 87 expect(() => writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT)) 88 .toThrowError('Field number is out of range: 536870912'); 89 } else { 90 // Note in unchecked mode we produce invalid output for invalid inputs. 91 // This test just documents our behavior in those cases. 92 // These values might change at any point and are not considered 93 // what the implementation should be doing here. 94 writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT); 95 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0)); 96 } 97 }); 98 99 it('fail when field number is negative for writeTag', () => { 100 const writer = new Writer(); 101 if (CHECK_TYPE) { 102 expect(() => writer.writeTag(-1, WireType.VARINT)) 103 .toThrowError('Field number is out of range: -1'); 104 } else { 105 // Note in unchecked mode we produce invalid output for invalid inputs. 106 // This test just documents our behavior in those cases. 107 // These values might change at any point and are not considered 108 // what the implementation should be doing here. 109 writer.writeTag(-1, WireType.VARINT); 110 expect(writer.getAndResetResultBuffer()) 111 .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF)); 112 } 113 }); 114 115 it('fail when wire type is invalid for writeTag', () => { 116 const writer = new Writer(); 117 if (CHECK_TYPE) { 118 expect(() => writer.writeTag(1, /** @type {!WireType} */ (0x08))) 119 .toThrowError('Invalid wire type: 8'); 120 } else { 121 // Note in unchecked mode we produce invalid output for invalid inputs. 122 // This test just documents our behavior in those cases. 123 // These values might change at any point and are not considered 124 // what the implementation should be doing here. 125 writer.writeTag(1, /** @type {!WireType} */ (0x08)); 126 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08)); 127 } 128 }); 129 130 it('encode singular boolean value', () => { 131 const writer = new Writer(); 132 writer.writeBool(1, true); 133 expect(writer.getAndResetResultBuffer()) 134 .toEqual(createArrayBuffer(0x08, 0x01)); 135 }); 136 137 it('encode length delimited', () => { 138 const writer = new Writer(); 139 writer.writeDelimited(1, createArrayBuffer(0x01, 0x02)); 140 expect(writer.getAndResetResultBuffer()) 141 .toEqual(createArrayBuffer(0x0A, 0x02, 0x01, 0x02)); 142 }); 143}); 144 145describe('Writer.writeBufferDecoder does', () => { 146 it('encode BufferDecoder containing a varint value', () => { 147 const writer = new Writer(); 148 const expected = createArrayBuffer( 149 0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01); 150 writer.writeBufferDecoder( 151 BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT, 1); 152 const result = writer.getAndResetResultBuffer(); 153 expect(result).toEqual(arrayBufferSlice(expected, 1, 3)); 154 }); 155 156 it('encode BufferDecoder containing a fixed64 value', () => { 157 const writer = new Writer(); 158 const expected = createArrayBuffer( 159 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 160 /* fixed64 end= */ 0x08, 0x08, 0x01); 161 writer.writeBufferDecoder( 162 BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64, 1); 163 const result = writer.getAndResetResultBuffer(); 164 expect(result).toEqual(arrayBufferSlice(expected, 1, 9)); 165 }); 166 167 it('encode BufferDecoder containing a length delimited value', () => { 168 const writer = new Writer(); 169 const expected = createArrayBuffer( 170 0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02, 171 /* data end= */ 0x03, 0x08, 0x01); 172 writer.writeBufferDecoder( 173 BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED, 1); 174 const result = writer.getAndResetResultBuffer(); 175 expect(result).toEqual(arrayBufferSlice(expected, 1, 5)); 176 }); 177 178 it('encode BufferDecoder containing a group', () => { 179 const writer = new Writer(); 180 const expected = createArrayBuffer( 181 0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B, 182 /* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01); 183 writer.writeBufferDecoder( 184 BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP, 1); 185 const result = writer.getAndResetResultBuffer(); 186 expect(result).toEqual(arrayBufferSlice(expected, 1, 6)); 187 }); 188 189 it('encode BufferDecoder containing a fixed32 value', () => { 190 const writer = new Writer(); 191 const expected = createArrayBuffer( 192 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04, 193 0x08, 0x01); 194 writer.writeBufferDecoder( 195 BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32, 1); 196 const result = writer.getAndResetResultBuffer(); 197 expect(result).toEqual(arrayBufferSlice(expected, 1, 5)); 198 }); 199 200 it('fail when encoding out of bound data', () => { 201 const writer = new Writer(); 202 const buffer = createArrayBuffer(0x4, 0x0, 0x1, 0x2, 0x3); 203 const subBuffer = arrayBufferSlice(buffer, 0, 2); 204 expect( 205 () => writer.writeBufferDecoder( 206 BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED, 1)) 207 .toThrow(); 208 }); 209}); 210 211describe('Writer.writeBytes does', () => { 212 let writer; 213 beforeEach(() => { 214 writer = new Writer(); 215 }); 216 217 it('encodes empty ByteString', () => { 218 writer.writeBytes(1, ByteString.EMPTY); 219 const buffer = writer.getAndResetResultBuffer(); 220 expect(buffer.byteLength).toBe(2); 221 }); 222 223 it('encodes empty array', () => { 224 writer.writeBytes(1, ByteString.fromArrayBuffer(new ArrayBuffer(0))); 225 expect(writer.getAndResetResultBuffer()) 226 .toEqual(createArrayBuffer( 227 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) 228 0, // length of the bytes 229 )); 230 }); 231 232 it('encodes ByteString', () => { 233 const array = createArrayBuffer(1, 2, 3); 234 writer.writeBytes(1, ByteString.fromArrayBuffer(array)); 235 expect(writer.getAndResetResultBuffer()) 236 .toEqual(createArrayBuffer( 237 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) 238 3, // length of the bytes 239 1, 240 2, 241 3, 242 )); 243 }); 244}); 245 246describe('Writer.writeDouble does', () => { 247 let writer; 248 beforeEach(() => { 249 writer = new Writer(); 250 }); 251 252 for (const pair of getDoublePairs()) { 253 it(`encode ${pair.name}`, () => { 254 writer.writeDouble(1, pair.doubleValue); 255 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 256 expect(buffer.length).toBe(9); 257 // ensure we have a correct tag 258 expect(buffer[0]).toEqual(0x09); 259 // Encoded values are stored right after the tag 260 expect(buffer.subarray(1, 9)) 261 .toEqual(pair.bufferDecoder.asUint8Array()); 262 }); 263 } 264 265 /** 266 * NaN may have different value in different browsers. Thus, we need to make 267 * the test lenient. 268 */ 269 it('encode NaN', () => { 270 writer.writeDouble(1, NaN); 271 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 272 expect(buffer.length).toBe(9); 273 // ensure we have a correct tag 274 expect(buffer[0]).toEqual(0x09); 275 // Encoded values are stored right after the tag 276 const float64 = new DataView(buffer.buffer); 277 expect(float64.getFloat64(1, true)).toBeNaN(); 278 }); 279}); 280 281describe('Writer.writeFixed32 does', () => { 282 let writer; 283 beforeEach(() => { 284 writer = new Writer(); 285 }); 286 287 for (const pair of getFixed32Pairs()) { 288 it(`encode ${pair.name}`, () => { 289 writer.writeFixed32(1, pair.intValue); 290 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 291 expect(buffer.length).toBe(5); 292 // ensure we have a correct tag 293 expect(buffer[0]).toEqual(0x0D); 294 // Encoded values are stored right after the tag 295 expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); 296 }); 297 } 298}); 299 300describe('Writer.writeFloat does', () => { 301 let writer; 302 beforeEach(() => { 303 writer = new Writer(); 304 }); 305 306 for (const pair of getFloatPairs()) { 307 it(`encode ${pair.name}`, () => { 308 writer.writeFloat(1, pair.floatValue); 309 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 310 expect(buffer.length).toBe(5); 311 // ensure we have a correct tag 312 expect(buffer[0]).toEqual(0x0D); 313 // Encoded values are stored right after the tag 314 expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); 315 }); 316 } 317 318 /** 319 * NaN may have different value in different browsers. Thus, we need to make 320 * the test lenient. 321 */ 322 it('encode NaN', () => { 323 writer.writeFloat(1, NaN); 324 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 325 expect(buffer.length).toBe(5); 326 // ensure we have a correct tag 327 expect(buffer[0]).toEqual(0x0D); 328 // Encoded values are stored right after the tag 329 const float32 = new DataView(buffer.buffer); 330 expect(float32.getFloat32(1, true)).toBeNaN(); 331 }); 332}); 333 334describe('Writer.writeInt32 does', () => { 335 let writer; 336 beforeEach(() => { 337 writer = new Writer(); 338 }); 339 340 for (const pair of getInt32Pairs()) { 341 if (!pair.skip_writer) { 342 it(`encode ${pair.name}`, () => { 343 writer.writeInt32(1, pair.intValue); 344 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 345 // ensure we have a correct tag 346 expect(buffer[0]).toEqual(0x08); 347 // Encoded values are stored right after the tag 348 expect(buffer.subarray(1, buffer.length)) 349 .toEqual(pair.bufferDecoder.asUint8Array()); 350 }); 351 } 352 } 353}); 354 355describe('Writer.writeSfixed32 does', () => { 356 let writer; 357 beforeEach(() => { 358 writer = new Writer(); 359 }); 360 361 it('encode empty array', () => { 362 writer.writePackedSfixed32(1, []); 363 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 364 }); 365 366 for (const pair of getSfixed32Pairs()) { 367 it(`encode ${pair.name}`, () => { 368 writer.writeSfixed32(1, pair.intValue); 369 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 370 expect(buffer.length).toBe(5); 371 // ensure we have a correct tag 372 expect(buffer[0]).toEqual(0x0D); 373 // Encoded values are stored right after the tag 374 expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); 375 }); 376 } 377}); 378 379describe('Writer.writeSfixed64 does', () => { 380 let writer; 381 beforeEach(() => { 382 writer = new Writer(); 383 }); 384 385 for (const pair of getSfixed64Pairs()) { 386 it(`encode ${pair.name}`, () => { 387 writer.writeSfixed64(1, pair.longValue); 388 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 389 expect(buffer.length).toBe(9); 390 // ensure we have a correct tag 391 expect(buffer[0]).toEqual(0x09); 392 // Encoded values are stored right after the tag 393 expect(buffer.subarray(1, 9)).toEqual(pair.bufferDecoder.asUint8Array()); 394 }); 395 } 396}); 397 398describe('Writer.writeSint32 does', () => { 399 let writer; 400 beforeEach(() => { 401 writer = new Writer(); 402 }); 403 404 for (const pair of getSint32Pairs()) { 405 if (!pair.skip_writer) { 406 it(`encode ${pair.name}`, () => { 407 writer.writeSint32(1, pair.intValue); 408 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 409 // ensure we have a correct tag 410 expect(buffer[0]).toEqual(0x08); 411 // Encoded values are stored right after the tag 412 expect(buffer.subarray(1, buffer.length)) 413 .toEqual(pair.bufferDecoder.asUint8Array()); 414 }); 415 } 416 } 417}); 418 419describe('Writer.writeSint64 does', () => { 420 let writer; 421 beforeEach(() => { 422 writer = new Writer(); 423 }); 424 425 for (const pair of getSint64Pairs()) { 426 if (!pair.skip_writer) { 427 it(`encode ${pair.name}`, () => { 428 writer.writeSint64(1, pair.longValue); 429 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 430 // ensure we have a correct tag 431 expect(buffer[0]).toEqual(0x08); 432 // Encoded values are stored right after the tag 433 expect(buffer.subarray(1, buffer.length)) 434 .toEqual(pair.bufferDecoder.asUint8Array()); 435 }); 436 } 437 } 438}); 439 440describe('Writer.writeInt64 does', () => { 441 let writer; 442 beforeEach(() => { 443 writer = new Writer(); 444 }); 445 446 for (const pair of getInt64Pairs()) { 447 if (!pair.skip_writer) { 448 it(`encode ${pair.name}`, () => { 449 writer.writeInt64(1, pair.longValue); 450 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 451 // ensure we have a correct tag 452 expect(buffer[0]).toEqual(0x08); 453 // Encoded values are stored right after the tag 454 expect(buffer.subarray(1, buffer.length)) 455 .toEqual(pair.bufferDecoder.asUint8Array()); 456 }); 457 } 458 } 459}); 460 461describe('Writer.writeUint32 does', () => { 462 let writer; 463 beforeEach(() => { 464 writer = new Writer(); 465 }); 466 467 for (const pair of getUint32Pairs()) { 468 if (!pair.skip_writer) { 469 it(`encode ${pair.name}`, () => { 470 writer.writeUint32(1, pair.intValue); 471 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 472 // ensure we have a correct tag 473 expect(buffer[0]).toEqual(0x08); 474 // Encoded values are stored right after the tag 475 expect(buffer.subarray(1, buffer.length)) 476 .toEqual(pair.bufferDecoder.asUint8Array()); 477 }); 478 } 479 } 480}); 481 482describe('Writer.writeString does', () => { 483 let writer; 484 beforeEach(() => { 485 writer = new Writer(); 486 }); 487 488 it('encode empty string', () => { 489 writer.writeString(1, ''); 490 expect(writer.getAndResetResultBuffer()) 491 .toEqual(createArrayBuffer( 492 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) 493 0, // length of the string 494 )); 495 }); 496 497 it('encode simple string', () => { 498 writer.writeString(1, 'hello'); 499 expect(writer.getAndResetResultBuffer()) 500 .toEqual(createArrayBuffer( 501 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) 502 5, // length of the string 503 'h'.charCodeAt(0), 504 'e'.charCodeAt(0), 505 'l'.charCodeAt(0), 506 'l'.charCodeAt(0), 507 'o'.charCodeAt(0), 508 )); 509 }); 510 511 it('throw for invalid fieldnumber', () => { 512 if (CHECK_BOUNDS) { 513 expect(() => writer.writeString(-1, 'a')) 514 .toThrowError('Field number is out of range: -1'); 515 } else { 516 writer.writeString(-1, 'a'); 517 expect(new Uint8Array(writer.getAndResetResultBuffer())) 518 .toEqual(new Uint8Array(createArrayBuffer( 519 -6, // invalid tag 520 0xff, 521 0xff, 522 0xff, 523 0x0f, 524 1, // string length 525 'a'.charCodeAt(0), 526 ))); 527 } 528 }); 529 530 it('throw for null string value', () => { 531 expect( 532 () => writer.writeString( 533 1, /** @type {string} */ (/** @type {*} */ (null)))) 534 .toThrow(); 535 }); 536}); 537 538 539/****************************************************************************** 540 * REPEATED FUNCTIONS 541 ******************************************************************************/ 542 543describe('Writer.writePackedBool does', () => { 544 let writer; 545 beforeEach(() => { 546 writer = new Writer(); 547 }); 548 549 it('encode empty array', () => { 550 writer.writePackedBool(1, []); 551 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 552 }); 553 554 for (const pair of getPackedBoolPairs()) { 555 if (!pair.skip_writer) { 556 it(`encode ${pair.name}`, () => { 557 writer.writePackedBool(1, pair.boolValues); 558 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 559 // ensure we have a correct tag 560 expect(buffer[0]).toEqual(0x0A); 561 // Encoded values are stored right after the tag 562 expect(buffer.subarray(1, buffer.length)) 563 .toEqual(pair.bufferDecoder.asUint8Array()); 564 }); 565 } 566 } 567}); 568 569describe('Writer.writeRepeatedBool does', () => { 570 let writer; 571 beforeEach(() => { 572 writer = new Writer(); 573 }); 574 575 it('encode empty array', () => { 576 writer.writeRepeatedBool(1, []); 577 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 578 }); 579 580 it('encode repeated unpacked boolean values', () => { 581 const writer = new Writer(); 582 writer.writeRepeatedBool(1, [true, false]); 583 expect(writer.getAndResetResultBuffer()) 584 .toEqual(createArrayBuffer( 585 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint)) 586 0x01, // value[0] 587 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint)) 588 0x00, // value[1] 589 )); 590 }); 591}); 592 593describe('Writer.writePackedDouble does', () => { 594 let writer; 595 beforeEach(() => { 596 writer = new Writer(); 597 }); 598 599 it('encode empty array', () => { 600 writer.writePackedDouble(1, []); 601 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 602 }); 603 604 for (const pair of getPackedDoublePairs()) { 605 if (!pair.skip_writer) { 606 it(`encode ${pair.name}`, () => { 607 writer.writePackedDouble(1, pair.doubleValues); 608 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 609 // ensure we have a correct tag 610 expect(buffer[0]).toEqual(0x0A); 611 // Encoded values are stored right after the tag 612 expect(buffer.subarray(1, buffer.length)) 613 .toEqual(pair.bufferDecoder.asUint8Array()); 614 }); 615 } 616 } 617}); 618 619describe('Writer.writePackedFixed32 does', () => { 620 let writer; 621 beforeEach(() => { 622 writer = new Writer(); 623 }); 624 625 it('encode empty array', () => { 626 writer.writePackedFixed32(1, []); 627 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 628 }); 629 630 for (const pair of getPackedFixed32Pairs()) { 631 if (!pair.skip_writer) { 632 it(`encode ${pair.name}`, () => { 633 writer.writePackedFixed32(1, pair.fixed32Values); 634 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 635 // ensure we have a correct tag 636 expect(buffer[0]).toEqual(0x0A); 637 // Encoded values are stored right after the tag 638 expect(buffer.subarray(1, buffer.length)) 639 .toEqual(pair.bufferDecoder.asUint8Array()); 640 }); 641 } 642 } 643}); 644 645describe('Writer.writePackedFloat does', () => { 646 let writer; 647 beforeEach(() => { 648 writer = new Writer(); 649 }); 650 651 it('encode empty array', () => { 652 writer.writePackedFloat(1, []); 653 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 654 }); 655 656 for (const pair of getPackedFloatPairs()) { 657 if (!pair.skip_writer) { 658 it(`encode ${pair.name}`, () => { 659 writer.writePackedFloat(1, pair.floatValues); 660 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 661 // ensure we have a correct tag 662 expect(buffer[0]).toEqual(0x0A); 663 // Encoded values are stored right after the tag 664 expect(buffer.subarray(1, buffer.length)) 665 .toEqual(pair.bufferDecoder.asUint8Array()); 666 }); 667 } 668 } 669}); 670 671describe('Writer.writePackedInt32 does', () => { 672 let writer; 673 beforeEach(() => { 674 writer = new Writer(); 675 }); 676 677 it('encode empty array', () => { 678 writer.writePackedInt32(1, []); 679 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 680 }); 681 682 for (const pair of getPackedInt32Pairs()) { 683 if (!pair.skip_writer) { 684 it(`encode ${pair.name}`, () => { 685 writer.writePackedInt32(1, pair.int32Values); 686 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 687 // ensure we have a correct tag 688 expect(buffer[0]).toEqual(0x0A); 689 // Encoded values are stored right after the tag 690 expect(buffer.subarray(1, buffer.length)) 691 .toEqual(pair.bufferDecoder.asUint8Array()); 692 }); 693 } 694 } 695}); 696 697describe('Writer.writePackedInt64 does', () => { 698 let writer; 699 beforeEach(() => { 700 writer = new Writer(); 701 }); 702 703 it('encode empty array', () => { 704 writer.writePackedInt64(1, []); 705 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 706 }); 707 708 for (const pair of getPackedInt64Pairs()) { 709 if (!pair.skip_writer) { 710 it(`encode ${pair.name}`, () => { 711 writer.writePackedInt64(1, pair.int64Values); 712 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 713 // ensure we have a correct tag 714 expect(buffer[0]).toEqual(0x0A); 715 // Encoded values are stored right after the tag 716 expect(buffer.subarray(1, buffer.length)) 717 .toEqual(pair.bufferDecoder.asUint8Array()); 718 }); 719 } 720 } 721}); 722 723describe('Writer.writePackedSfixed32 does', () => { 724 let writer; 725 beforeEach(() => { 726 writer = new Writer(); 727 }); 728 729 it('encode empty array', () => { 730 writer.writePackedSfixed32(1, []); 731 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 732 }); 733 734 for (const pair of getPackedSfixed32Pairs()) { 735 if (!pair.skip_writer) { 736 it(`encode ${pair.name}`, () => { 737 writer.writePackedSfixed32(1, pair.sfixed32Values); 738 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 739 // ensure we have a correct tag 740 expect(buffer[0]).toEqual(0x0A); 741 // Encoded values are stored right after the tag 742 expect(buffer.subarray(1, buffer.length)) 743 .toEqual(pair.bufferDecoder.asUint8Array()); 744 }); 745 } 746 } 747}); 748 749describe('Writer.writePackedSfixed64 does', () => { 750 let writer; 751 beforeEach(() => { 752 writer = new Writer(); 753 }); 754 755 it('encode empty array', () => { 756 writer.writePackedSfixed64(1, []); 757 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 758 }); 759 760 for (const pair of getPackedSfixed64Pairs()) { 761 if (!pair.skip_writer) { 762 it(`encode ${pair.name}`, () => { 763 writer.writePackedSfixed64(1, pair.sfixed64Values); 764 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 765 // ensure we have a correct tag 766 expect(buffer[0]).toEqual(0x0A); 767 // Encoded values are stored right after the tag 768 expect(buffer.subarray(1, buffer.length)) 769 .toEqual(pair.bufferDecoder.asUint8Array()); 770 }); 771 } 772 } 773}); 774 775describe('Writer.writePackedSint32 does', () => { 776 let writer; 777 beforeEach(() => { 778 writer = new Writer(); 779 }); 780 781 it('encode empty array', () => { 782 writer.writePackedSint32(1, []); 783 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 784 }); 785 786 for (const pair of getPackedSint32Pairs()) { 787 if (!pair.skip_writer) { 788 it(`encode ${pair.name}`, () => { 789 writer.writePackedSint32(1, pair.sint32Values); 790 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 791 // ensure we have a correct tag 792 expect(buffer[0]).toEqual(0x0A); 793 // Encoded values are stored right after the tag 794 expect(buffer.subarray(1, buffer.length)) 795 .toEqual(pair.bufferDecoder.asUint8Array()); 796 }); 797 } 798 } 799}); 800 801describe('Writer.writePackedSint64 does', () => { 802 let writer; 803 beforeEach(() => { 804 writer = new Writer(); 805 }); 806 807 it('encode empty array', () => { 808 writer.writePackedSint64(1, []); 809 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 810 }); 811 812 for (const pair of getPackedSint64Pairs()) { 813 if (!pair.skip_writer) { 814 it(`encode ${pair.name}`, () => { 815 writer.writePackedSint64(1, pair.sint64Values); 816 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 817 // ensure we have a correct tag 818 expect(buffer[0]).toEqual(0x0A); 819 // Encoded values are stored right after the tag 820 expect(buffer.subarray(1, buffer.length)) 821 .toEqual(pair.bufferDecoder.asUint8Array()); 822 }); 823 } 824 } 825}); 826 827describe('Writer.writePackedUint32 does', () => { 828 let writer; 829 beforeEach(() => { 830 writer = new Writer(); 831 }); 832 833 it('encode empty array', () => { 834 writer.writePackedUint32(1, []); 835 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 836 }); 837 838 for (const pair of getPackedUint32Pairs()) { 839 if (!pair.skip_writer) { 840 it(`encode ${pair.name}`, () => { 841 writer.writePackedUint32(1, pair.uint32Values); 842 const buffer = new Uint8Array(writer.getAndResetResultBuffer()); 843 // ensure we have a correct tag 844 expect(buffer[0]).toEqual(0x0A); 845 // Encoded values are stored right after the tag 846 expect(buffer.subarray(1, buffer.length)) 847 .toEqual(pair.bufferDecoder.asUint8Array()); 848 }); 849 } 850 } 851}); 852 853describe('Writer.writeRepeatedBytes does', () => { 854 let writer; 855 beforeEach(() => { 856 writer = new Writer(); 857 }); 858 859 it('encode empty array', () => { 860 writer.writeRepeatedBytes(1, []); 861 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 862 }); 863 864 it('encode single value', () => { 865 const value = createArrayBuffer(0x61); 866 writer.writeRepeatedBytes(1, [ByteString.fromArrayBuffer(value)]); 867 expect(writer.getAndResetResultBuffer()) 868 .toEqual(createArrayBuffer( 869 0x0A, 870 0x01, 871 0x61, // a 872 )); 873 }); 874 875 it('encode multiple values', () => { 876 const value1 = createArrayBuffer(0x61); 877 const value2 = createArrayBuffer(0x62); 878 writer.writeRepeatedBytes(1, [ 879 ByteString.fromArrayBuffer(value1), 880 ByteString.fromArrayBuffer(value2), 881 ]); 882 expect(writer.getAndResetResultBuffer()) 883 .toEqual(createArrayBuffer( 884 0x0A, 885 0x01, 886 0x61, // a 887 0x0A, 888 0x01, 889 0x62, // b 890 )); 891 }); 892}); 893 894describe('Writer.writeRepeatedString does', () => { 895 let writer; 896 beforeEach(() => { 897 writer = new Writer(); 898 }); 899 900 it('encode empty array', () => { 901 writer.writeRepeatedString(1, []); 902 expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); 903 }); 904 905 it('encode single value', () => { 906 writer.writeRepeatedString(1, ['a']); 907 expect(writer.getAndResetResultBuffer()) 908 .toEqual(createArrayBuffer( 909 0x0A, 910 0x01, 911 0x61, // a 912 )); 913 }); 914 915 it('encode multiple values', () => { 916 writer.writeRepeatedString(1, ['a', 'b']); 917 expect(writer.getAndResetResultBuffer()) 918 .toEqual(createArrayBuffer( 919 0x0A, 920 0x01, 921 0x61, // a 922 0x0A, 923 0x01, 924 0x62, // b 925 )); 926 }); 927}); 928