1/** 2 * @fileoverview Tests for tag.js. 3 */ 4goog.module('protobuf.binary.TagTests'); 5 6const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); 7const WireType = goog.require('protobuf.binary.WireType'); 8const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); 9const {createTag, get32BitVarintLength, skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag'); 10 11 12goog.setTestOnly(); 13 14/** 15 * @param {...number} bytes 16 * @return {!ArrayBuffer} 17 */ 18function createArrayBuffer(...bytes) { 19 return new Uint8Array(bytes).buffer; 20} 21 22describe('skipField', () => { 23 it('skips varints', () => { 24 const bufferDecoder = 25 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); 26 skipField(bufferDecoder, WireType.VARINT, 1); 27 expect(bufferDecoder.cursor()).toBe(2); 28 }); 29 30 it('throws for out of bounds varints', () => { 31 const bufferDecoder = 32 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); 33 bufferDecoder.setCursor(2); 34 if (CHECK_CRITICAL_STATE) { 35 expect(() => skipField(bufferDecoder, WireType.VARINT, 1)).toThrowError(); 36 } 37 }); 38 39 it('skips fixed64', () => { 40 const bufferDecoder = BufferDecoder.fromArrayBuffer( 41 createArrayBuffer(0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); 42 skipField(bufferDecoder, WireType.FIXED64, 1); 43 expect(bufferDecoder.cursor()).toBe(8); 44 }); 45 46 it('throws for fixed64 if length is too short', () => { 47 const bufferDecoder = 48 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); 49 if (CHECK_CRITICAL_STATE) { 50 expect(() => skipField(bufferDecoder, WireType.FIXED64, 1)) 51 .toThrowError(); 52 } 53 }); 54 55 it('skips fixed32', () => { 56 const bufferDecoder = BufferDecoder.fromArrayBuffer( 57 createArrayBuffer(0x80, 0x00, 0x00, 0x00)); 58 skipField(bufferDecoder, WireType.FIXED32, 1); 59 expect(bufferDecoder.cursor()).toBe(4); 60 }); 61 62 it('throws for fixed32 if length is too short', () => { 63 const bufferDecoder = 64 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); 65 if (CHECK_CRITICAL_STATE) { 66 expect(() => skipField(bufferDecoder, WireType.FIXED32, 1)) 67 .toThrowError(); 68 } 69 }); 70 71 72 it('skips length delimited', () => { 73 const bufferDecoder = BufferDecoder.fromArrayBuffer( 74 createArrayBuffer(0x03, 0x00, 0x00, 0x00)); 75 skipField(bufferDecoder, WireType.DELIMITED, 1); 76 expect(bufferDecoder.cursor()).toBe(4); 77 }); 78 79 it('throws for length delimited if length is too short', () => { 80 const bufferDecoder = 81 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x03, 0x00, 0x00)); 82 if (CHECK_CRITICAL_STATE) { 83 expect(() => skipField(bufferDecoder, WireType.DELIMITED, 1)) 84 .toThrowError(); 85 } 86 }); 87 88 it('skips groups', () => { 89 const bufferDecoder = BufferDecoder.fromArrayBuffer( 90 createArrayBuffer(0x0B, 0x08, 0x01, 0x0C)); 91 bufferDecoder.setCursor(1); 92 skipField(bufferDecoder, WireType.START_GROUP, 1); 93 expect(bufferDecoder.cursor()).toBe(4); 94 }); 95 96 it('skips group in group', () => { 97 const buffer = createArrayBuffer( 98 0x0B, // start outter 99 0x10, 0x01, // field: 2, value: 1 100 0x0B, // start inner group 101 0x10, 0x01, // payload inner group 102 0x0C, // stop inner group 103 0x0C // end outter 104 ); 105 const bufferDecoder = BufferDecoder.fromArrayBuffer(buffer); 106 bufferDecoder.setCursor(1); 107 skipField(bufferDecoder, WireType.START_GROUP, 1); 108 expect(bufferDecoder.cursor()).toBe(8); 109 }); 110 111 it('throws for group if length is too short', () => { 112 // no closing group 113 const bufferDecoder = 114 BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0B, 0x00, 0x00)); 115 if (CHECK_CRITICAL_STATE) { 116 expect(() => skipField(bufferDecoder, WireType.START_GROUP, 1)) 117 .toThrowError(); 118 } 119 }); 120}); 121 122 123describe('tagToWireType', () => { 124 it('decodes numbers ', () => { 125 // simple numbers 126 expect(tagToWireType(0x00)).toBe(WireType.VARINT); 127 expect(tagToWireType(0x01)).toBe(WireType.FIXED64); 128 expect(tagToWireType(0x02)).toBe(WireType.DELIMITED); 129 expect(tagToWireType(0x03)).toBe(WireType.START_GROUP); 130 expect(tagToWireType(0x04)).toBe(WireType.END_GROUP); 131 expect(tagToWireType(0x05)).toBe(WireType.FIXED32); 132 133 // upper bits should not matter 134 expect(tagToWireType(0x08)).toBe(WireType.VARINT); 135 expect(tagToWireType(0x09)).toBe(WireType.FIXED64); 136 expect(tagToWireType(0x0A)).toBe(WireType.DELIMITED); 137 expect(tagToWireType(0x0B)).toBe(WireType.START_GROUP); 138 expect(tagToWireType(0x0C)).toBe(WireType.END_GROUP); 139 expect(tagToWireType(0x0D)).toBe(WireType.FIXED32); 140 141 // upper bits should not matter 142 expect(tagToWireType(0xF8)).toBe(WireType.VARINT); 143 expect(tagToWireType(0xF9)).toBe(WireType.FIXED64); 144 expect(tagToWireType(0xFA)).toBe(WireType.DELIMITED); 145 expect(tagToWireType(0xFB)).toBe(WireType.START_GROUP); 146 expect(tagToWireType(0xFC)).toBe(WireType.END_GROUP); 147 expect(tagToWireType(0xFD)).toBe(WireType.FIXED32); 148 149 // negative numbers work 150 expect(tagToWireType(-8)).toBe(WireType.VARINT); 151 expect(tagToWireType(-7)).toBe(WireType.FIXED64); 152 expect(tagToWireType(-6)).toBe(WireType.DELIMITED); 153 expect(tagToWireType(-5)).toBe(WireType.START_GROUP); 154 expect(tagToWireType(-4)).toBe(WireType.END_GROUP); 155 expect(tagToWireType(-3)).toBe(WireType.FIXED32); 156 }); 157}); 158 159describe('tagToFieldNumber', () => { 160 it('returns fieldNumber', () => { 161 expect(tagToFieldNumber(0x08)).toBe(1); 162 expect(tagToFieldNumber(0x09)).toBe(1); 163 expect(tagToFieldNumber(0x10)).toBe(2); 164 expect(tagToFieldNumber(0x12)).toBe(2); 165 }); 166}); 167 168describe('createTag', () => { 169 it('combines fieldNumber and wireType', () => { 170 expect(createTag(WireType.VARINT, 1)).toBe(0x08); 171 expect(createTag(WireType.FIXED64, 1)).toBe(0x09); 172 expect(createTag(WireType.DELIMITED, 1)).toBe(0x0A); 173 expect(createTag(WireType.START_GROUP, 1)).toBe(0x0B); 174 expect(createTag(WireType.END_GROUP, 1)).toBe(0x0C); 175 expect(createTag(WireType.FIXED32, 1)).toBe(0x0D); 176 177 expect(createTag(WireType.VARINT, 2)).toBe(0x10); 178 expect(createTag(WireType.FIXED64, 2)).toBe(0x11); 179 expect(createTag(WireType.DELIMITED, 2)).toBe(0x12); 180 expect(createTag(WireType.START_GROUP, 2)).toBe(0x13); 181 expect(createTag(WireType.END_GROUP, 2)).toBe(0x14); 182 expect(createTag(WireType.FIXED32, 2)).toBe(0x15); 183 184 expect(createTag(WireType.VARINT, 0x1FFFFFFF)).toBe(0xFFFFFFF8 >>> 0); 185 expect(createTag(WireType.FIXED64, 0x1FFFFFFF)).toBe(0xFFFFFFF9 >>> 0); 186 expect(createTag(WireType.DELIMITED, 0x1FFFFFFF)).toBe(0xFFFFFFFA >>> 0); 187 expect(createTag(WireType.START_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFB >>> 0); 188 expect(createTag(WireType.END_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFC >>> 0); 189 expect(createTag(WireType.FIXED32, 0x1FFFFFFF)).toBe(0xFFFFFFFD >>> 0); 190 }); 191}); 192 193describe('get32BitVarintLength', () => { 194 it('length of tag', () => { 195 expect(get32BitVarintLength(0)).toBe(1); 196 expect(get32BitVarintLength(1)).toBe(1); 197 expect(get32BitVarintLength(1)).toBe(1); 198 199 expect(get32BitVarintLength(Math.pow(2, 7) - 1)).toBe(1); 200 expect(get32BitVarintLength(Math.pow(2, 7))).toBe(2); 201 202 expect(get32BitVarintLength(Math.pow(2, 14) - 1)).toBe(2); 203 expect(get32BitVarintLength(Math.pow(2, 14))).toBe(3); 204 205 expect(get32BitVarintLength(Math.pow(2, 21) - 1)).toBe(3); 206 expect(get32BitVarintLength(Math.pow(2, 21))).toBe(4); 207 208 expect(get32BitVarintLength(Math.pow(2, 28) - 1)).toBe(4); 209 expect(get32BitVarintLength(Math.pow(2, 28))).toBe(5); 210 211 expect(get32BitVarintLength(Math.pow(2, 31) - 1)).toBe(5); 212 213 expect(get32BitVarintLength(-1)).toBe(5); 214 expect(get32BitVarintLength(-Math.pow(2, 31))).toBe(5); 215 216 expect(get32BitVarintLength(createTag(WireType.VARINT, 0x1fffffff))) 217 .toBe(5); 218 expect(get32BitVarintLength(createTag(WireType.FIXED32, 0x1fffffff))) 219 .toBe(5); 220 }); 221}); 222