1ffe3c632Sopenharmony_ci/**
2ffe3c632Sopenharmony_ci * @fileoverview Tests for indexer.js.
3ffe3c632Sopenharmony_ci */
4ffe3c632Sopenharmony_cigoog.module('protobuf.binary.IndexerTest');
5ffe3c632Sopenharmony_ci
6ffe3c632Sopenharmony_cigoog.setTestOnly();
7ffe3c632Sopenharmony_ci
8ffe3c632Sopenharmony_ci// Note to the reader:
9ffe3c632Sopenharmony_ci// Since the index behavior changes with the checking level some of the tests
10ffe3c632Sopenharmony_ci// in this file have to know which checking level is enabled to make correct
11ffe3c632Sopenharmony_ci// assertions.
12ffe3c632Sopenharmony_ci// Test are run in all checking levels.
13ffe3c632Sopenharmony_ciconst BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
14ffe3c632Sopenharmony_ciconst BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
15ffe3c632Sopenharmony_ciconst WireType = goog.require('protobuf.binary.WireType');
16ffe3c632Sopenharmony_ciconst {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
17ffe3c632Sopenharmony_ciconst {Field, IndexEntry} = goog.require('protobuf.binary.field');
18ffe3c632Sopenharmony_ciconst {buildIndex} = goog.require('protobuf.binary.indexer');
19ffe3c632Sopenharmony_ciconst {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
20ffe3c632Sopenharmony_ci
21ffe3c632Sopenharmony_ci/**
22ffe3c632Sopenharmony_ci * Returns the number of fields stored.
23ffe3c632Sopenharmony_ci *
24ffe3c632Sopenharmony_ci * @param {!BinaryStorage} storage
25ffe3c632Sopenharmony_ci * @return {number}
26ffe3c632Sopenharmony_ci */
27ffe3c632Sopenharmony_cifunction getStorageSize(storage) {
28ffe3c632Sopenharmony_ci  let size = 0;
29ffe3c632Sopenharmony_ci  storage.forEach(() => void size++);
30ffe3c632Sopenharmony_ci  return size;
31ffe3c632Sopenharmony_ci}
32ffe3c632Sopenharmony_ci
33ffe3c632Sopenharmony_ci/**
34ffe3c632Sopenharmony_ci * @type {number}
35ffe3c632Sopenharmony_ci */
36ffe3c632Sopenharmony_ciconst PIVOT = 1;
37ffe3c632Sopenharmony_ci
38ffe3c632Sopenharmony_ci/**
39ffe3c632Sopenharmony_ci * Asserts a single IndexEntry at a given field number.
40ffe3c632Sopenharmony_ci * @param {!BinaryStorage} storage
41ffe3c632Sopenharmony_ci * @param {number} fieldNumber
42ffe3c632Sopenharmony_ci * @param {...!IndexEntry} expectedEntries
43ffe3c632Sopenharmony_ci */
44ffe3c632Sopenharmony_cifunction assertStorageEntries(storage, fieldNumber, ...expectedEntries) {
45ffe3c632Sopenharmony_ci  expect(getStorageSize(storage)).toBe(1);
46ffe3c632Sopenharmony_ci
47ffe3c632Sopenharmony_ci  const entryArray = storage.get(fieldNumber).getIndexArray();
48ffe3c632Sopenharmony_ci  expect(entryArray).not.toBeUndefined();
49ffe3c632Sopenharmony_ci  expect(entryArray.length).toBe(expectedEntries.length);
50ffe3c632Sopenharmony_ci
51ffe3c632Sopenharmony_ci  for (let i = 0; i < entryArray.length; i++) {
52ffe3c632Sopenharmony_ci    const storageEntry = entryArray[i];
53ffe3c632Sopenharmony_ci    const expectedEntry = expectedEntries[i];
54ffe3c632Sopenharmony_ci
55ffe3c632Sopenharmony_ci    expect(storageEntry).toBe(expectedEntry);
56ffe3c632Sopenharmony_ci  }
57ffe3c632Sopenharmony_ci}
58ffe3c632Sopenharmony_ci
59ffe3c632Sopenharmony_cidescribe('Indexer does', () => {
60ffe3c632Sopenharmony_ci  it('return empty storage for empty array', () => {
61ffe3c632Sopenharmony_ci    const storage = buildIndex(createBufferDecoder(), PIVOT);
62ffe3c632Sopenharmony_ci    expect(storage).not.toBeNull();
63ffe3c632Sopenharmony_ci    expect(getStorageSize(storage)).toBe(0);
64ffe3c632Sopenharmony_ci  });
65ffe3c632Sopenharmony_ci
66ffe3c632Sopenharmony_ci  it('throw for null array', () => {
67ffe3c632Sopenharmony_ci    expect(
68ffe3c632Sopenharmony_ci        () => buildIndex(
69ffe3c632Sopenharmony_ci            /** @type {!BufferDecoder} */ (/** @type {*} */ (null)), PIVOT))
70ffe3c632Sopenharmony_ci        .toThrow();
71ffe3c632Sopenharmony_ci  });
72ffe3c632Sopenharmony_ci
73ffe3c632Sopenharmony_ci  it('fail for invalid wire type (6)', () => {
74ffe3c632Sopenharmony_ci    expect(() => buildIndex(createBufferDecoder(0x0E, 0x01), PIVOT))
75ffe3c632Sopenharmony_ci        .toThrowError('Unexpected wire type: 6');
76ffe3c632Sopenharmony_ci  });
77ffe3c632Sopenharmony_ci
78ffe3c632Sopenharmony_ci  it('fail for invalid wire type (7)', () => {
79ffe3c632Sopenharmony_ci    expect(() => buildIndex(createBufferDecoder(0x0F, 0x01), PIVOT))
80ffe3c632Sopenharmony_ci        .toThrowError('Unexpected wire type: 7');
81ffe3c632Sopenharmony_ci  });
82ffe3c632Sopenharmony_ci
83ffe3c632Sopenharmony_ci  it('index varint', () => {
84ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x08, 0x01, 0x08, 0x01);
85ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
86ffe3c632Sopenharmony_ci    assertStorageEntries(
87ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
88ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1),
89ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 3));
90ffe3c632Sopenharmony_ci  });
91ffe3c632Sopenharmony_ci
92ffe3c632Sopenharmony_ci  it('index varint with two bytes field number', () => {
93ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0xF8, 0x01, 0x01);
94ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
95ffe3c632Sopenharmony_ci    assertStorageEntries(
96ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 31,
97ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 2));
98ffe3c632Sopenharmony_ci  });
99ffe3c632Sopenharmony_ci
100ffe3c632Sopenharmony_ci  it('fail for varints that are longer than 10 bytes', () => {
101ffe3c632Sopenharmony_ci    const data = createBufferDecoder(
102ffe3c632Sopenharmony_ci        0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00);
103ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
104ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
105ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 12 size: 11');
106ffe3c632Sopenharmony_ci    } else {
107ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
108ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
109ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
110ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
111ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
112ffe3c632Sopenharmony_ci      assertStorageEntries(
113ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
114ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1));
115ffe3c632Sopenharmony_ci    }
116ffe3c632Sopenharmony_ci  });
117ffe3c632Sopenharmony_ci
118ffe3c632Sopenharmony_ci  it('fail for varints with no data', () => {
119ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x08);
120ffe3c632Sopenharmony_ci    expect(() => buildIndex(data, PIVOT)).toThrow();
121ffe3c632Sopenharmony_ci  });
122ffe3c632Sopenharmony_ci
123ffe3c632Sopenharmony_ci  it('index fixed64', () => {
124ffe3c632Sopenharmony_ci    const data = createBufferDecoder(
125ffe3c632Sopenharmony_ci        /* first= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
126ffe3c632Sopenharmony_ci        /* second= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
127ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
128ffe3c632Sopenharmony_ci    assertStorageEntries(
129ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
130ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1),
131ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 10));
132ffe3c632Sopenharmony_ci  });
133ffe3c632Sopenharmony_ci
134ffe3c632Sopenharmony_ci  it('fail for fixed64 data missing in input', () => {
135ffe3c632Sopenharmony_ci    const data =
136ffe3c632Sopenharmony_ci        createBufferDecoder(0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07);
137ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
138ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
139ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 9 size: 8');
140ffe3c632Sopenharmony_ci    } else {
141ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
142ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
143ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
144ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
145ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
146ffe3c632Sopenharmony_ci      assertStorageEntries(
147ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
148ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1));
149ffe3c632Sopenharmony_ci    }
150ffe3c632Sopenharmony_ci  });
151ffe3c632Sopenharmony_ci
152ffe3c632Sopenharmony_ci  it('fail for fixed64 tag that has no data after it', () => {
153ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
154ffe3c632Sopenharmony_ci      const data = createBufferDecoder(0x09);
155ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
156ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 9 size: 1');
157ffe3c632Sopenharmony_ci    } else {
158ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
159ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
160ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
161ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
162ffe3c632Sopenharmony_ci      const data = createBufferDecoder(0x09);
163ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
164ffe3c632Sopenharmony_ci      assertStorageEntries(
165ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
166ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1));
167ffe3c632Sopenharmony_ci    }
168ffe3c632Sopenharmony_ci  });
169ffe3c632Sopenharmony_ci
170ffe3c632Sopenharmony_ci  it('index delimited', () => {
171ffe3c632Sopenharmony_ci    const data = createBufferDecoder(
172ffe3c632Sopenharmony_ci        /* first= */ 0x0A, 0x02, 0x00, 0x01, /* second= */ 0x0A, 0x02, 0x00,
173ffe3c632Sopenharmony_ci        0x01);
174ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
175ffe3c632Sopenharmony_ci    assertStorageEntries(
176ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
177ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1),
178ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 5));
179ffe3c632Sopenharmony_ci  });
180ffe3c632Sopenharmony_ci
181ffe3c632Sopenharmony_ci  it('fail for length deliimted field data missing in input', () => {
182ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0A, 0x04, 0x00, 0x01);
183ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
184ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
185ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 6 size: 4');
186ffe3c632Sopenharmony_ci    } else {
187ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
188ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
189ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
190ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
191ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
192ffe3c632Sopenharmony_ci      assertStorageEntries(
193ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
194ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1));
195ffe3c632Sopenharmony_ci    }
196ffe3c632Sopenharmony_ci  });
197ffe3c632Sopenharmony_ci
198ffe3c632Sopenharmony_ci  it('fail for delimited tag that has no data after it', () => {
199ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0A);
200ffe3c632Sopenharmony_ci    expect(() => buildIndex(data, PIVOT)).toThrow();
201ffe3c632Sopenharmony_ci  });
202ffe3c632Sopenharmony_ci
203ffe3c632Sopenharmony_ci  it('index fixed32', () => {
204ffe3c632Sopenharmony_ci    const data = createBufferDecoder(
205ffe3c632Sopenharmony_ci        /* first= */ 0x0D, 0x01, 0x02, 0x03, 0x04, /* second= */ 0x0D, 0x01,
206ffe3c632Sopenharmony_ci        0x02, 0x03, 0x04);
207ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
208ffe3c632Sopenharmony_ci    assertStorageEntries(
209ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
210ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1),
211ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 6));
212ffe3c632Sopenharmony_ci  });
213ffe3c632Sopenharmony_ci
214ffe3c632Sopenharmony_ci  it('fail for fixed32 data missing in input', () => {
215ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0D, 0x01, 0x02, 0x03);
216ffe3c632Sopenharmony_ci
217ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
218ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
219ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 5 size: 4');
220ffe3c632Sopenharmony_ci    } else {
221ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
222ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
223ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
224ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
225ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
226ffe3c632Sopenharmony_ci      assertStorageEntries(
227ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
228ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1));
229ffe3c632Sopenharmony_ci    }
230ffe3c632Sopenharmony_ci  });
231ffe3c632Sopenharmony_ci
232ffe3c632Sopenharmony_ci  it('fail for fixed32 tag that has no data after it', () => {
233ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
234ffe3c632Sopenharmony_ci      const data = createBufferDecoder(0x0D);
235ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
236ffe3c632Sopenharmony_ci          .toThrowError('Index out of bounds: index: 5 size: 1');
237ffe3c632Sopenharmony_ci    } else {
238ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
239ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
240ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
241ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
242ffe3c632Sopenharmony_ci      const data = createBufferDecoder(0x0D);
243ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
244ffe3c632Sopenharmony_ci      assertStorageEntries(
245ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
246ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1));
247ffe3c632Sopenharmony_ci    }
248ffe3c632Sopenharmony_ci  });
249ffe3c632Sopenharmony_ci
250ffe3c632Sopenharmony_ci  it('index group', () => {
251ffe3c632Sopenharmony_ci    const data = createBufferDecoder(
252ffe3c632Sopenharmony_ci        /* first= */ 0x0B, 0x08, 0x01, 0x0C, /* second= */ 0x0B, 0x08, 0x01,
253ffe3c632Sopenharmony_ci        0x0C);
254ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
255ffe3c632Sopenharmony_ci    assertStorageEntries(
256ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
257ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1),
258ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 5));
259ffe3c632Sopenharmony_ci  });
260ffe3c632Sopenharmony_ci
261ffe3c632Sopenharmony_ci  it('index group and skips inner group', () => {
262ffe3c632Sopenharmony_ci    const data =
263ffe3c632Sopenharmony_ci        createBufferDecoder(0x0B, 0x0B, 0x08, 0x01, 0x0C, 0x08, 0x01, 0x0C);
264ffe3c632Sopenharmony_ci    const storage = buildIndex(data, PIVOT);
265ffe3c632Sopenharmony_ci    assertStorageEntries(
266ffe3c632Sopenharmony_ci        storage, /* fieldNumber= */ 1,
267ffe3c632Sopenharmony_ci        Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
268ffe3c632Sopenharmony_ci  });
269ffe3c632Sopenharmony_ci
270ffe3c632Sopenharmony_ci  it('fail on unmatched stop group', () => {
271ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0C, 0x01);
272ffe3c632Sopenharmony_ci    expect(() => buildIndex(data, PIVOT))
273ffe3c632Sopenharmony_ci        .toThrowError('Unexpected wire type: 4');
274ffe3c632Sopenharmony_ci  });
275ffe3c632Sopenharmony_ci
276ffe3c632Sopenharmony_ci  it('fail for groups without matching stop group', () => {
277ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0B, 0x08, 0x01, 0x1C);
278ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
279ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT))
280ffe3c632Sopenharmony_ci          .toThrowError('Expected stop group for fieldnumber 1 not found.');
281ffe3c632Sopenharmony_ci    } else {
282ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
283ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
284ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
285ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
286ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
287ffe3c632Sopenharmony_ci      assertStorageEntries(
288ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
289ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
290ffe3c632Sopenharmony_ci    }
291ffe3c632Sopenharmony_ci  });
292ffe3c632Sopenharmony_ci
293ffe3c632Sopenharmony_ci  it('fail for groups without stop group', () => {
294ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0B, 0x08, 0x01);
295ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
296ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.');
297ffe3c632Sopenharmony_ci    } else {
298ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
299ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
300ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
301ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
302ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
303ffe3c632Sopenharmony_ci      assertStorageEntries(
304ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
305ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
306ffe3c632Sopenharmony_ci    }
307ffe3c632Sopenharmony_ci  });
308ffe3c632Sopenharmony_ci
309ffe3c632Sopenharmony_ci  it('fail for group tag that has no data after it', () => {
310ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x0B);
311ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
312ffe3c632Sopenharmony_ci      expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.');
313ffe3c632Sopenharmony_ci    } else {
314ffe3c632Sopenharmony_ci      // Note in unchecked mode we produce invalid output for invalid inputs.
315ffe3c632Sopenharmony_ci      // This test just documents our behavior in those cases.
316ffe3c632Sopenharmony_ci      // These values might change at any point and are not considered
317ffe3c632Sopenharmony_ci      // what the implementation should be doing here.
318ffe3c632Sopenharmony_ci      const storage = buildIndex(data, PIVOT);
319ffe3c632Sopenharmony_ci      assertStorageEntries(
320ffe3c632Sopenharmony_ci          storage, /* fieldNumber= */ 1,
321ffe3c632Sopenharmony_ci          Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
322ffe3c632Sopenharmony_ci    }
323ffe3c632Sopenharmony_ci  });
324ffe3c632Sopenharmony_ci
325ffe3c632Sopenharmony_ci  it('index too large tag', () => {
326ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0xF8, 0xFF, 0xFF, 0xFF, 0xFF);
327ffe3c632Sopenharmony_ci    expect(() => buildIndex(data, PIVOT)).toThrow();
328ffe3c632Sopenharmony_ci  });
329ffe3c632Sopenharmony_ci
330ffe3c632Sopenharmony_ci  it('fail for varint tag that has no data after it', () => {
331ffe3c632Sopenharmony_ci    const data = createBufferDecoder(0x08);
332ffe3c632Sopenharmony_ci    expect(() => buildIndex(data, PIVOT)).toThrow();
333ffe3c632Sopenharmony_ci  });
334ffe3c632Sopenharmony_ci});
335