• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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