/** * @fileoverview Tests for BufferDecoder. */ goog.module('protobuf.binary.varintsTest'); const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); const {CHECK_CRITICAL_STATE, CHECK_STATE} = goog.require('protobuf.internal.checks'); goog.setTestOnly(); /** * @param {...number} bytes * @return {!ArrayBuffer} */ function createArrayBuffer(...bytes) { return new Uint8Array(bytes).buffer; } describe('setCursor does', () => { it('set the cursor at the position specified', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1)); expect(bufferDecoder.cursor()).toBe(0); bufferDecoder.setCursor(1); expect(bufferDecoder.cursor()).toBe(1); }); }); describe('skip does', () => { it('advance the cursor', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1, 0x2)); bufferDecoder.setCursor(1); bufferDecoder.skip(1); expect(bufferDecoder.cursor()).toBe(2); }); }); describe('Skip varint does', () => { it('skip a varint', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); bufferDecoder.skipVarint(); expect(bufferDecoder.cursor()).toBe(1); }); it('fail when varint is larger than 10 bytes', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); if (CHECK_CRITICAL_STATE) { expect(() => bufferDecoder.skipVarint()).toThrow(); } else { // Note in unchecked mode we produce invalid output for invalid inputs. // This test just documents our behavior in those cases. // These values might change at any point and are not considered // what the implementation should be doing here. bufferDecoder.skipVarint(); expect(bufferDecoder.cursor()).toBe(11); } }); it('fail when varint is beyond end of underlying array', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x80)); expect(() => bufferDecoder.skipVarint()).toThrow(); }); }); describe('readVarint64 does', () => { it('read zero', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00)); const {lowBits, highBits} = bufferDecoder.getVarint(0); expect(lowBits).toBe(0); expect(highBits).toBe(0); expect(bufferDecoder.cursor()).toBe(1); }); it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); const {lowBits, highBits} = bufferDecoder.getVarint(0); expect(lowBits).toBe(1); expect(highBits).toBe(0); expect(bufferDecoder.cursor()).toBe(1); }); it('read max value', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); const {lowBits, highBits} = bufferDecoder.getVarint(0); expect(lowBits).toBe(-1); expect(highBits).toBe(-1); expect(bufferDecoder.cursor()).toBe(10); }); }); describe('readUnsignedVarint32 does', () => { it('read zero', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00)); const result = bufferDecoder.getUnsignedVarint32(); expect(result).toBe(0); expect(bufferDecoder.cursor()).toBe(1); }); it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); const result = bufferDecoder.getUnsignedVarint32(); expect(result).toBe(1); expect(bufferDecoder.cursor()).toBe(1); }); it('read max int32', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF, 0x0F)); const result = bufferDecoder.getUnsignedVarint32(); expect(result).toBe(4294967295); expect(bufferDecoder.cursor()).toBe(5); }); it('read max value', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); const result = bufferDecoder.getUnsignedVarint32(); expect(result).toBe(4294967295); expect(bufferDecoder.cursor()).toBe(10); }); it('fail if data is longer than 10 bytes', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); if (CHECK_CRITICAL_STATE) { expect(() => bufferDecoder.getUnsignedVarint32()).toThrow(); } else { // Note in unchecked mode we produce invalid output for invalid inputs. // This test just documents our behavior in those cases. // These values might change at any point and are not considered // what the implementation should be doing here. const result = bufferDecoder.getUnsignedVarint32(); expect(result).toBe(4294967295); expect(bufferDecoder.cursor()).toBe(10); } }); }); describe('readUnsignedVarint32At does', () => { it('reads from a specific index', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x1, 0x2)); const result = bufferDecoder.getUnsignedVarint32At(1); expect(result).toBe(2); expect(bufferDecoder.cursor()).toBe(2); }); }); describe('getFloat32 does', () => { it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0x00, 0x00, 0x80, 0x3F)); const result = bufferDecoder.getFloat32(0); expect(result).toBe(1); expect(bufferDecoder.cursor()).toBe(4); }); }); describe('getFloat64 does', () => { it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F)); const result = bufferDecoder.getFloat64(0); expect(result).toBe(1); expect(bufferDecoder.cursor()).toBe(8); }); }); describe('getInt32 does', () => { it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0x01, 0x00, 0x00, 0x00)); const result = bufferDecoder.getInt32(0); expect(result).toBe(1); expect(bufferDecoder.cursor()).toBe(4); }); it('read minus one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF)); const result = bufferDecoder.getInt32(0); expect(result).toBe(-1); expect(bufferDecoder.cursor()).toBe(4); }); }); describe('getUint32 does', () => { it('read one', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x00, 0x00, 0x0)); const result = bufferDecoder.getUint32(0); expect(result).toBe(1); expect(bufferDecoder.cursor()).toBe(4); }); it('read max uint32', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer( createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF)); const result = bufferDecoder.getUint32(0); expect(result).toBe(4294967295); expect(bufferDecoder.cursor()).toBe(4); }); }); describe('subBufferDecoder does', () => { it('can create valid sub buffers', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02)); expect(bufferDecoder.subBufferDecoder(0, 0)) .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer())); expect(bufferDecoder.subBufferDecoder(0, 1)) .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00))); expect(bufferDecoder.subBufferDecoder(1, 0)) .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer())); expect(bufferDecoder.subBufferDecoder(1, 1)) .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01))); expect(bufferDecoder.subBufferDecoder(1, 2)) .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x02))); }); it('can not create invalid', () => { const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02)); if (CHECK_STATE) { expect(() => bufferDecoder.subBufferDecoder(-1, 1)).toThrow(); expect(() => bufferDecoder.subBufferDecoder(0, -4)).toThrow(); expect(() => bufferDecoder.subBufferDecoder(0, 4)).toThrow(); } }); });